Merge branch 'DRTVWR-559' into DRTVWR-583

master
Jonathan "Geenz" Goodman 2023-10-16 08:48:50 -07:00
commit bd9c0a2e65
257 changed files with 19221 additions and 8316 deletions

View File

@ -238,6 +238,7 @@ Ansariel Hiller
SL-15227
SL-15398
SL-18432
SL-19140
SL-4126
Aralara Rajal
Arare Chantilly
@ -895,6 +896,7 @@ Kitty Barnett
STORM-2149
MAINT-7581
MAINT-7081
SL-18988
Kolor Fall
Komiko Okamoto
Korvel Noh

View File

@ -21,7 +21,6 @@ set(llappearance_SOURCE_FILES
lltexglobalcolor.cpp
lltexlayer.cpp
lltexlayerparams.cpp
lltexturemanagerbridge.cpp
llwearable.cpp
llwearabledata.cpp
llwearabletype.cpp
@ -44,7 +43,6 @@ set(llappearance_HEADER_FILES
lltexglobalcolor.h
lltexlayer.h
lltexlayerparams.h
lltexturemanagerbridge.h
llwearable.h
llwearabledata.h
llwearabletype.h

View File

@ -55,7 +55,7 @@ void LLCallbackList::addFunction( callback_t func, void *data)
// only add one callback per func/data pair
//
if (containsFunction(func))
if (containsFunction(func, data))
{
return;
}

View File

@ -40,9 +40,12 @@
///----------------------------------------------------------------------------
/// Exported functions
///----------------------------------------------------------------------------
// FIXME D567 - what's the point of these, especially if we don't even use them consistently?
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_THUMBNAIL_ID_LABEL("thumbnail_id");
static const std::string INV_ASSET_TYPE_LABEL("type");
static const std::string INV_PREFERRED_TYPE_LABEL("preferred_type");
static const std::string INV_INVENTORY_TYPE_LABEL("inv_type");
@ -99,6 +102,7 @@ void LLInventoryObject::copyObject(const LLInventoryObject* other)
mParentUUID = other->mParentUUID;
mType = other->mType;
mName = other->mName;
mThumbnailUUID = other->mThumbnailUUID;
}
const LLUUID& LLInventoryObject::getUUID() const
@ -111,6 +115,11 @@ const LLUUID& LLInventoryObject::getParentUUID() const
return mParentUUID;
}
const LLUUID& LLInventoryObject::getThumbnailUUID() const
{
return mThumbnailUUID;
}
const std::string& LLInventoryObject::getName() const
{
return mName;
@ -160,6 +169,11 @@ void LLInventoryObject::setParent(const LLUUID& new_parent)
mParentUUID = new_parent;
}
void LLInventoryObject::setThumbnailUUID(const LLUUID& thumbnail_uuid)
{
mThumbnailUUID = thumbnail_uuid;
}
void LLInventoryObject::setType(LLAssetType::EType type)
{
mType = type;
@ -201,6 +215,26 @@ BOOL LLInventoryObject::importLegacyStream(std::istream& input_stream)
{
mType = LLAssetType::lookup(valuestr);
}
else if (0 == strcmp("metadata", keyword))
{
LLSD metadata(valuestr);
if (metadata.has("thumbnail"))
{
const LLSD& thumbnail = metadata["thumbnail"];
if (thumbnail.has("asset_id"))
{
setThumbnailUUID(thumbnail["asset_id"].asUUID());
}
else
{
setThumbnailUUID(LLUUID::null);
}
}
else
{
setThumbnailUUID(LLUUID::null);
}
}
else if(0 == strcmp("name", keyword))
{
//strcpy(valuestr, buffer + strlen(keyword) + 3);
@ -336,6 +370,7 @@ void LLInventoryItem::copyItem(const LLInventoryItem* other)
copyObject(other);
mPermissions = other->mPermissions;
mAssetUUID = other->mAssetUUID;
mThumbnailUUID = other->mThumbnailUUID;
mDescription = other->mDescription;
mSaleInfo = other->mSaleInfo;
mInventoryType = other->mInventoryType;
@ -400,6 +435,7 @@ U32 LLInventoryItem::getCRC32() const
//LL_DEBUGS() << "8 crc: " << std::hex << crc << std::dec << LL_ENDL;
crc += (U32)mCreationDate;
//LL_DEBUGS() << "9 crc: " << std::hex << crc << std::dec << LL_ENDL;
crc += mThumbnailUUID.getCRC32();
return crc;
}
@ -655,6 +691,26 @@ BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream)
{
mType = LLAssetType::lookup(valuestr);
}
else if (0 == strcmp("metadata", keyword))
{
LLSD metadata(valuestr);
if (metadata.has("thumbnail"))
{
const LLSD& thumbnail = metadata["thumbnail"];
if (thumbnail.has("asset_id"))
{
setThumbnailUUID(thumbnail["asset_id"].asUUID());
}
else
{
setThumbnailUUID(LLUUID::null);
}
}
else
{
setThumbnailUUID(LLUUID::null);
}
}
else if(0 == strcmp("inv_type", keyword))
{
mInventoryType = LLInventoryType::lookup(std::string(valuestr));
@ -744,6 +800,13 @@ BOOL LLInventoryItem::exportLegacyStream(std::ostream& output_stream, BOOL inclu
output_stream << "\t\tparent_id\t" << uuid_str << "\n";
mPermissions.exportLegacyStream(output_stream);
if (mThumbnailUUID.notNull())
{
LLSD metadata;
metadata["thumbnail"] = LLSD().with("asset_id", mThumbnailUUID);
output_stream << "\t\tmetadata\t" << metadata << "|\n";
}
// Check for permissions to see the asset id, and if so write it
// out as an asset id. Otherwise, apply our cheesy encryption.
if(include_asset_key)
@ -797,6 +860,11 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
sd[INV_PARENT_ID_LABEL] = mParentUUID;
sd[INV_PERMISSIONS_LABEL] = ll_create_sd_from_permissions(mPermissions);
if (mThumbnailUUID.notNull())
{
sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
}
U32 mask = mPermissions.getMaskBase();
if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
|| (mAssetUUID.isNull()))
@ -848,6 +916,35 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
{
mParentUUID = sd[w];
}
mThumbnailUUID.setNull();
w = INV_THUMBNAIL_LABEL;
if (sd.has(w))
{
const LLSD &thumbnail_map = sd[w];
w = INV_ASSET_ID_LABEL;
if (thumbnail_map.has(w))
{
mThumbnailUUID = thumbnail_map[w];
}
/* Example:
<key> asset_id </key>
<uuid> acc0ec86 - 17f2 - 4b92 - ab41 - 6718b1f755f7 </uuid>
<key> perms </key>
<integer> 8 </integer>
<key>service</key>
<integer> 3 </integer>
<key>version</key>
<integer> 1 </key>
*/
}
else
{
w = INV_THUMBNAIL_ID_LABEL;
if (sd.has(w))
{
mThumbnailUUID = sd[w].asUUID();
}
}
w = INV_PERMISSIONS_LABEL;
if (sd.has(w))
{
@ -972,135 +1069,6 @@ fail:
}
// Deleted LLInventoryItem::exportFileXML() and LLInventoryItem::importXML()
// because I can't find any non-test code references to it. 2009-05-04 JC
S32 LLInventoryItem::packBinaryBucket(U8* bin_bucket, LLPermissions* perm_override) const
{
// Figure out which permissions to use.
LLPermissions perm;
if (perm_override)
{
// Use the permissions override.
perm = *perm_override;
}
else
{
// Use the current permissions.
perm = getPermissions();
}
// describe the inventory item
char* buffer = (char*) bin_bucket;
std::string creator_id_str;
perm.getCreator().toString(creator_id_str);
std::string owner_id_str;
perm.getOwner().toString(owner_id_str);
std::string last_owner_id_str;
perm.getLastOwner().toString(last_owner_id_str);
std::string group_id_str;
perm.getGroup().toString(group_id_str);
std::string asset_id_str;
getAssetUUID().toString(asset_id_str);
S32 size = sprintf(buffer, /* Flawfinder: ignore */
"%d|%d|%s|%s|%s|%s|%s|%x|%x|%x|%x|%x|%s|%s|%d|%d|%x",
getType(),
getInventoryType(),
getName().c_str(),
creator_id_str.c_str(),
owner_id_str.c_str(),
last_owner_id_str.c_str(),
group_id_str.c_str(),
perm.getMaskBase(),
perm.getMaskOwner(),
perm.getMaskGroup(),
perm.getMaskEveryone(),
perm.getMaskNextOwner(),
asset_id_str.c_str(),
getDescription().c_str(),
getSaleInfo().getSaleType(),
getSaleInfo().getSalePrice(),
getFlags()) + 1;
return size;
}
void LLInventoryItem::unpackBinaryBucket(U8* bin_bucket, S32 bin_bucket_size)
{
// Early exit on an empty binary bucket.
if (bin_bucket_size <= 1) return;
if (NULL == bin_bucket)
{
LL_ERRS() << "unpackBinaryBucket failed. bin_bucket is NULL." << LL_ENDL;
return;
}
// Convert the bin_bucket into a string.
std::vector<char> item_buffer(bin_bucket_size+1);
memcpy(&item_buffer[0], bin_bucket, bin_bucket_size); /* Flawfinder: ignore */
item_buffer[bin_bucket_size] = '\0';
std::string str(&item_buffer[0]);
LL_DEBUGS() << "item buffer: " << str << LL_ENDL;
// Tokenize the string.
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
tokenizer tokens(str, sep);
tokenizer::iterator iter = tokens.begin();
// Extract all values.
LLUUID item_id;
item_id.generate();
setUUID(item_id);
LLAssetType::EType type;
type = (LLAssetType::EType)(atoi((*(iter++)).c_str()));
setType( type );
LLInventoryType::EType inv_type;
inv_type = (LLInventoryType::EType)(atoi((*(iter++)).c_str()));
setInventoryType( inv_type );
std::string name((*(iter++)).c_str());
rename( name );
LLUUID creator_id((*(iter++)).c_str());
LLUUID owner_id((*(iter++)).c_str());
LLUUID last_owner_id((*(iter++)).c_str());
LLUUID group_id((*(iter++)).c_str());
PermissionMask mask_base = strtoul((*(iter++)).c_str(), NULL, 16);
PermissionMask mask_owner = strtoul((*(iter++)).c_str(), NULL, 16);
PermissionMask mask_group = strtoul((*(iter++)).c_str(), NULL, 16);
PermissionMask mask_every = strtoul((*(iter++)).c_str(), NULL, 16);
PermissionMask mask_next = strtoul((*(iter++)).c_str(), NULL, 16);
LLPermissions perm;
perm.init(creator_id, owner_id, last_owner_id, group_id);
perm.initMasks(mask_base, mask_owner, mask_group, mask_every, mask_next);
setPermissions(perm);
//LL_DEBUGS() << "perm: " << perm << LL_ENDL;
LLUUID asset_id((*(iter++)).c_str());
setAssetUUID(asset_id);
std::string desc((*(iter++)).c_str());
setDescription(desc);
LLSaleInfo::EForSale sale_type;
sale_type = (LLSaleInfo::EForSale)(atoi((*(iter++)).c_str()));
S32 price = atoi((*(iter++)).c_str());
LLSaleInfo sale_info(sale_type, price);
setSaleInfo(sale_info);
U32 flags = strtoul((*(iter++)).c_str(), NULL, 16);
setFlags(flags);
time_t now = time(NULL);
setCreationDate(now);
}
///----------------------------------------------------------------------------
/// Class LLInventoryCategory
///----------------------------------------------------------------------------
@ -1150,11 +1118,32 @@ void LLInventoryCategory::setPreferredType(LLFolderType::EType type)
LLSD LLInventoryCategory::asLLSD() const
{
LLSD sd = LLSD();
sd["item_id"] = mUUID;
sd["parent_id"] = mParentUUID;
sd[INV_ITEM_ID_LABEL] = mUUID;
sd[INV_PARENT_ID_LABEL] = mParentUUID;
S8 type = static_cast<S8>(mPreferredType);
sd["type"] = type;
sd["name"] = mName;
sd[INV_ASSET_TYPE_LABEL] = type;
sd[INV_NAME_LABEL] = mName;
if (mThumbnailUUID.notNull())
{
sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
}
return sd;
}
LLSD LLInventoryCategory::asAISCreateCatLLSD() const
{
LLSD sd = LLSD();
sd[INV_FOLDER_ID_LABEL_WS] = mUUID;
sd[INV_PARENT_ID_LABEL] = mParentUUID;
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);
}
return sd;
}
@ -1184,6 +1173,25 @@ bool LLInventoryCategory::fromLLSD(const LLSD& sd)
{
mParentUUID = sd[w];
}
mThumbnailUUID.setNull();
w = INV_THUMBNAIL_LABEL;
if (sd.has(w))
{
const LLSD &thumbnail_map = sd[w];
w = INV_ASSET_ID_LABEL;
if (thumbnail_map.has(w))
{
mThumbnailUUID = thumbnail_map[w];
}
}
else
{
w = INV_THUMBNAIL_ID_LABEL;
if (sd.has(w))
{
mThumbnailUUID = sd[w];
}
}
w = INV_ASSET_TYPE_LABEL;
if (sd.has(w))
{
@ -1275,6 +1283,26 @@ BOOL LLInventoryCategory::importLegacyStream(std::istream& input_stream)
LLStringUtil::replaceNonstandardASCII(mName, ' ');
LLStringUtil::replaceChar(mName, '|', ' ');
}
else if (0 == strcmp("metadata", keyword))
{
LLSD metadata(valuestr);
if (metadata.has("thumbnail"))
{
const LLSD& thumbnail = metadata["thumbnail"];
if (thumbnail.has("asset_id"))
{
setThumbnailUUID(thumbnail["asset_id"].asUUID());
}
else
{
setThumbnailUUID(LLUUID::null);
}
}
else
{
setThumbnailUUID(LLUUID::null);
}
}
else
{
LL_WARNS() << "unknown keyword '" << keyword
@ -1295,6 +1323,12 @@ BOOL LLInventoryCategory::exportLegacyStream(std::ostream& output_stream, BOOL)
output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n";
output_stream << "\t\tpref_type\t" << LLFolderType::lookup(mPreferredType) << "\n";
output_stream << "\t\tname\t" << mName.c_str() << "|\n";
if (mThumbnailUUID.notNull())
{
LLSD metadata;
metadata["thumbnail"] = LLSD().with("asset_id", mThumbnailUUID);
output_stream << "\t\tmetadata\t" << metadata << "|\n";
}
output_stream << "\t}\n";
return TRUE;
}
@ -1308,6 +1342,11 @@ LLSD LLInventoryCategory::exportLLSD() const
cat_data[INV_PREFERRED_TYPE_LABEL] = LLFolderType::lookup(mPreferredType);
cat_data[INV_NAME_LABEL] = mName;
if (mThumbnailUUID.notNull())
{
cat_data[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
}
return cat_data;
}
@ -1329,6 +1368,16 @@ bool LLInventoryCategory::importLLSD(const LLSD& cat_data)
{
setPreferredType(LLFolderType::lookup(cat_data[INV_PREFERRED_TYPE_LABEL].asString()));
}
if (cat_data.has(INV_THUMBNAIL_LABEL))
{
LLUUID thumbnail_uuid;
const LLSD &thumbnail_data = cat_data[INV_THUMBNAIL_LABEL];
if (thumbnail_data.has(INV_ASSET_ID_LABEL))
{
thumbnail_uuid = thumbnail_data[INV_ASSET_ID_LABEL].asUUID();
}
setThumbnailUUID(thumbnail_uuid);
}
if (cat_data.has(INV_NAME_LABEL))
{
mName = cat_data[INV_NAME_LABEL].asString();

View File

@ -70,6 +70,7 @@ public:
virtual const LLUUID& getUUID() const; // inventoryID that this item points to
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 const std::string& getName() const;
virtual LLAssetType::EType getType() const;
LLAssetType::EType getActualType() const; // bypasses indirection for linked items
@ -84,6 +85,7 @@ public:
void setUUID(const LLUUID& new_uuid);
virtual void rename(const std::string& new_name);
void setParent(const LLUUID& new_parent);
virtual void setThumbnailUUID(const LLUUID& thumbnail_uuid);
void setType(LLAssetType::EType type);
virtual void setCreationDate(time_t creation_date_utc); // only stored for items
@ -108,6 +110,7 @@ public:
protected:
LLUUID mUUID;
LLUUID mParentUUID; // Parent category. Root categories have LLUUID::NULL.
LLUUID mThumbnailUUID;
LLAssetType::EType mType;
std::string mName;
time_t mCreationDate; // seconds from 1/1/1970, UTC
@ -203,9 +206,6 @@ public:
// Helper Functions
//--------------------------------------------------------------------
public:
// Pack all information needed to reconstruct this item into the given binary bucket.
S32 packBinaryBucket(U8* bin_bucket, LLPermissions* perm_override = NULL) const;
void unpackBinaryBucket(U8* bin_bucket, S32 bin_bucket_size);
LLSD asLLSD() const;
void asLLSD( LLSD& sd ) const;
bool fromLLSD(const LLSD& sd, bool is_new = true);
@ -253,6 +253,7 @@ public:
LLFolderType::EType getPreferredType() const;
void setPreferredType(LLFolderType::EType type);
LLSD asLLSD() const;
LLSD asAISCreateCatLLSD() const;
bool fromLLSD(const LLSD& sd);
//--------------------------------------------------------------------

View File

@ -400,27 +400,7 @@ namespace tut
// Deleted LLInventoryItem::exportFileXML() and LLInventoryItem::importXML()
// because I can't find any non-test code references to it. 2009-05-04 JC
}
template<> template<>
void inventory_object::test<10>()
{
LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
U8* bin_bucket = new U8[300];
S32 bin_bucket_size = src1->packBinaryBucket(bin_bucket, NULL);
LLPointer<LLInventoryItem> src2 = new LLInventoryItem();
src2->unpackBinaryBucket(bin_bucket, bin_bucket_size);
ensure_equals("1.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice());
ensure_equals("2.sale type::getSaleType() failed type", src1->getSaleInfo().getSaleType(), src2->getSaleInfo().getSaleType());
ensure_equals("3.type::getType() failed", src1->getType(), src2->getType());
ensure_equals("4.inventory type::getInventoryType() failed type", src1->getInventoryType(), src2->getInventoryType());
ensure_equals("5.name::getName() failed", src1->getName(), src2->getName());
ensure_equals("6.description::getDescription() failed", src1->getDescription(), src2->getDescription());
ensure_equals("7.flags::getFlags() failed", src1->getFlags(), src2->getFlags());
}
template<> template<>
void inventory_object::test<11>()
{

View File

@ -39,7 +39,7 @@ const F32 DEFAULT_NEAR_PLANE = 0.25f;
const F32 DEFAULT_FAR_PLANE = 64.f; // far reaches across two horizontal, not diagonal, regions
const F32 MAX_ASPECT_RATIO = 50.0f;
const F32 MAX_NEAR_PLANE = 10.f;
const F32 MAX_NEAR_PLANE = 1023.9f; // Clamp the near plane just before the skybox ends
const F32 MAX_FAR_PLANE = 100000.0f; //1000000.0f; // Max allowed. Not good Z precision though.
const F32 MAX_FAR_CLIP = 512.0f;

View File

@ -364,7 +364,26 @@ LLUUID LLCoprocedurePool::enqueueCoprocedure(const std::string &name, LLCoproced
{
LLUUID id(LLUUID::generateNewID());
LL_INFOS("CoProcMgr") << "Coprocedure(" << name << ") enqueuing with id=" << id.asString() << " in pool \"" << mPoolName << "\" at " << mPending << LL_ENDL;
if (mPoolName == "AIS")
{
// Fetch is going to be spammy.
LL_DEBUGS("CoProcMgr", "Inventory") << "Coprocedure(" << name << ") enqueuing with id=" << id.asString() << " in pool \"" << mPoolName
<< "\" at "
<< mPending << LL_ENDL;
if (mPending >= (LLCoprocedureManager::DEFAULT_QUEUE_SIZE - 1))
{
// If it's all used up (not supposed to happen,
// fetched should cap it), we are going to crash
LL_WARNS("CoProcMgr", "Inventory") << "About to run out of queue space for Coprocedure(" << name
<< ") enqueuing with id=" << id.asString() << " Already pending:" << mPending << LL_ENDL;
}
}
else
{
LL_INFOS("CoProcMgr") << "Coprocedure(" << name << ") enqueuing with id=" << id.asString() << " in pool \"" << mPoolName << "\" at "
<< mPending << LL_ENDL;
}
auto pushed = mPendingCoprocs->try_push(boost::make_shared<QueuedCoproc>(name, id, proc));
if (pushed == boost::fibers::channel_op_status::success)
{

View File

@ -3402,6 +3402,7 @@ typedef std::map<const char*, LLMessageBuilder*> BuilderMap;
void LLMessageSystem::newMessageFast(const char *name)
{
//LL_DEBUGS("Messaging") << "creating new message: " << name << LL_ENDL;
LLMessageConfig::Flavor message_flavor =
LLMessageConfig::getMessageFlavor(name);
LLMessageConfig::Flavor server_flavor =

View File

@ -34,6 +34,7 @@ set(llprimitive_HEADER_FILES
lldaeloader.h
llgltfloader.h
llgltfmaterial.h
llgltfmaterial_templates.h
legacy_object_types.h
llmaterial.h
llmaterialid.h

View File

@ -24,25 +24,28 @@
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llgltfmaterial.h"
#include "llsdserialize.h"
// NOTE -- this should be the one and only place tiny_gltf.h is included
#include "tinygltf/tiny_gltf.h"
#include "llgltfmaterial_templates.h"
const char* const LLGLTFMaterial::ASSET_VERSION = "1.1";
const char* const LLGLTFMaterial::ASSET_TYPE = "GLTF 2.0";
const std::array<std::string, 2> LLGLTFMaterial::ACCEPTED_ASSET_VERSIONS = { "1.0", "1.1" };
const char* const GLTF_FILE_EXTENSION_TRANSFORM = "KHR_texture_transform";
const char* const GLTF_FILE_EXTENSION_TRANSFORM_SCALE = "scale";
const char* const GLTF_FILE_EXTENSION_TRANSFORM_OFFSET = "offset";
const char* const GLTF_FILE_EXTENSION_TRANSFORM_ROTATION = "rotation";
const char* const LLGLTFMaterial::GLTF_FILE_EXTENSION_TRANSFORM = "KHR_texture_transform";
const char* const LLGLTFMaterial::GLTF_FILE_EXTENSION_TRANSFORM_SCALE = "scale";
const char* const LLGLTFMaterial::GLTF_FILE_EXTENSION_TRANSFORM_OFFSET = "offset";
const char* const LLGLTFMaterial::GLTF_FILE_EXTENSION_TRANSFORM_ROTATION = "rotation";
// special UUID that indicates a null UUID in override data
static const LLUUID GLTF_OVERRIDE_NULL_UUID = LLUUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
const LLUUID LLGLTFMaterial::GLTF_OVERRIDE_NULL_UUID = LLUUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
void LLGLTFMaterial::TextureTransform::getPacked(F32 (&packed)[8]) const
{
@ -68,14 +71,14 @@ LLGLTFMaterial::LLGLTFMaterial(const LLGLTFMaterial& rhs)
LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs)
{
//have to do a manual operator= because of LLRefCount
//have to do a manual operator= because of LLRefCount
mTextureId = rhs.mTextureId;
mTextureTransform = rhs.mTextureTransform;
mBaseColor = rhs.mBaseColor;
mEmissiveColor = rhs.mEmissiveColor;
mMetallicFactor = rhs.mMetallicFactor;
mRoughnessFactor = rhs.mRoughnessFactor;
mAlphaCutoff = rhs.mAlphaCutoff;
@ -97,7 +100,7 @@ bool LLGLTFMaterial::operator==(const LLGLTFMaterial& rhs) const
mBaseColor == rhs.mBaseColor &&
mEmissiveColor == rhs.mEmissiveColor &&
mMetallicFactor == rhs.mMetallicFactor &&
mRoughnessFactor == rhs.mRoughnessFactor &&
mAlphaCutoff == rhs.mAlphaCutoff &&
@ -122,6 +125,7 @@ bool LLGLTFMaterial::fromJSON(const std::string& json, std::string& warn_msg, st
return true;
}
return false;
}
@ -190,7 +194,8 @@ void LLGLTFMaterial::setFromModel(const tinygltf::Model& model, S32 mat_index)
}
}
LLVector2 vec2_from_json(const tinygltf::Value::Object& object, const char* key, const LLVector2& default_value)
// static
LLVector2 LLGLTFMaterial::vec2FromJson(const tinygltf::Value::Object& object, const char* key, const LLVector2& default_value)
{
const auto it = object.find(key);
if (it == object.end())
@ -215,7 +220,8 @@ LLVector2 vec2_from_json(const tinygltf::Value::Object& object, const char* key,
return value;
}
F32 float_from_json(const tinygltf::Value::Object& object, const char* key, const F32 default_value)
// static
F32 LLGLTFMaterial::floatFromJson(const tinygltf::Value::Object& object, const char* key, const F32 default_value)
{
const auto it = object.find(key);
if (it == object.end())
@ -230,52 +236,6 @@ F32 float_from_json(const tinygltf::Value::Object& object, const char* key, cons
return (F32)real_json.GetNumberAsDouble();
}
template<typename T>
std::string gltf_get_texture_image(const tinygltf::Model& model, const T& texture_info)
{
const S32 texture_idx = texture_info.index;
if (texture_idx < 0 || texture_idx >= model.textures.size())
{
return "";
}
const tinygltf::Texture& texture = model.textures[texture_idx];
// Ignore texture.sampler for now
const S32 image_idx = texture.source;
if (image_idx < 0 || image_idx >= model.images.size())
{
return "";
}
const tinygltf::Image& image = model.images[image_idx];
return image.uri;
}
// *NOTE: Use template here as workaround for the different similar texture info classes
template<typename T>
void LLGLTFMaterial::setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id)
{
LL_PROFILE_ZONE_SCOPED;
const std::string uri = gltf_get_texture_image(model, texture_info);
mTextureId[texture_info_id].set(uri);
const tinygltf::Value::Object& extensions_object = texture_info.extensions;
const auto transform_it = extensions_object.find(GLTF_FILE_EXTENSION_TRANSFORM);
if (transform_it != extensions_object.end())
{
const tinygltf::Value& transform_json = std::get<1>(*transform_it);
if (transform_json.IsObject())
{
const tinygltf::Value::Object& transform_object = transform_json.Get<tinygltf::Value::Object>();
TextureTransform& transform = mTextureTransform[texture_info_id];
transform.mOffset = vec2_from_json(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_OFFSET, getDefaultTextureOffset());
transform.mScale = vec2_from_json(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_SCALE, getDefaultTextureScale());
transform.mRotation = float_from_json(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_ROTATION, getDefaultTextureRotation());
}
}
}
void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const
{
LL_PROFILE_ZONE_SCOPED;
@ -302,7 +262,7 @@ void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const
material_out.alphaMode = getAlphaMode();
material_out.alphaCutoff = mAlphaCutoff;
mBaseColor.write(material_out.pbrMetallicRoughness.baseColorFactor);
if (mEmissiveColor != LLGLTFMaterial::getDefaultEmissiveColor())
@ -320,7 +280,7 @@ void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const
tinygltf::Value::Object extras;
bool write_extras = false;
if (mOverrideAlphaMode && mAlphaMode == getDefaultAlphaMode())
{
{
extras["override_alpha_mode"] = tinygltf::Value(mOverrideAlphaMode);
write_extras = true;
}
@ -339,57 +299,6 @@ void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const
model.asset.version = "2.0";
}
template<typename T>
void gltf_allocate_texture_image(tinygltf::Model& model, T& texture_info, const std::string& uri)
{
const S32 image_idx = model.images.size();
model.images.emplace_back();
model.images[image_idx].uri = uri;
// The texture, not to be confused with the texture info
const S32 texture_idx = model.textures.size();
model.textures.emplace_back();
tinygltf::Texture& texture = model.textures[texture_idx];
texture.source = image_idx;
texture_info.index = texture_idx;
}
template<typename T>
void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, bool force_write) const
{
LL_PROFILE_ZONE_SCOPED;
const LLUUID& texture_id = mTextureId[texture_info_id];
const TextureTransform& transform = mTextureTransform[texture_info_id];
const bool is_blank_transform = transform == sDefault.mTextureTransform[0];
// Check if this material matches all the fallback values, and if so, then
// skip including it to reduce material size
if (!force_write && texture_id.isNull() && is_blank_transform)
{
return;
}
// tinygltf will discard this texture info if there is no valid texture,
// causing potential loss of information for overrides, so ensure one is
// defined. -Cosmic,2023-01-30
gltf_allocate_texture_image(model, texture_info, texture_id.asString());
if (!is_blank_transform)
{
tinygltf::Value::Object transform_map;
transform_map[GLTF_FILE_EXTENSION_TRANSFORM_OFFSET] = tinygltf::Value(tinygltf::Value::Array({
tinygltf::Value(transform.mOffset.mV[VX]),
tinygltf::Value(transform.mOffset.mV[VY])
}));
transform_map[GLTF_FILE_EXTENSION_TRANSFORM_SCALE] = tinygltf::Value(tinygltf::Value::Array({
tinygltf::Value(transform.mScale.mV[VX]),
tinygltf::Value(transform.mScale.mV[VY])
}));
transform_map[GLTF_FILE_EXTENSION_TRANSFORM_ROTATION] = tinygltf::Value(transform.mRotation);
texture_info.extensions[GLTF_FILE_EXTENSION_TRANSFORM] = tinygltf::Value(transform_map);
}
}
void LLGLTFMaterial::sanitizeAssetMaterial()
{
mTextureTransform = sDefault.mTextureTransform;
@ -403,19 +312,19 @@ bool LLGLTFMaterial::setBaseMaterial()
return *this != old_override;
}
bool LLGLTFMaterial::isClearedForBaseMaterial()
{
LLGLTFMaterial cleared_override = sDefault;
cleared_override.setBaseMaterial(*this);
return *this == cleared_override;
}
// For material overrides only. Copies transforms from the old override.
void LLGLTFMaterial::setBaseMaterial(const LLGLTFMaterial& old_override_mat)
{
mTextureTransform = old_override_mat.mTextureTransform;
}
bool LLGLTFMaterial::isClearedForBaseMaterial() const
{
LLGLTFMaterial cleared_override = sDefault;
cleared_override.setBaseMaterial(*this);
return *this == cleared_override;
}
// static
void LLGLTFMaterial::hackOverrideUUID(LLUUID& id)
@ -516,7 +425,7 @@ void LLGLTFMaterial::setAlphaMode(const std::string& mode, bool for_override)
{
m = ALPHA_MODE_BLEND;
}
setAlphaMode(m, for_override);
}
@ -709,7 +618,6 @@ void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& d
{
data["tex"][i] = LLSD::UUID(override_texture_id);
}
}
if (override_mat.mBaseColor != getDefaultBaseColor())
@ -764,23 +672,6 @@ void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& d
data["ti"][i]["r"] = override_mat.mTextureTransform[i].mRotation;
}
}
#if 0
{
std::ostringstream ostr;
LLSDSerialize::serialize(data, ostr, LLSDSerialize::LLSD_NOTATION);
std::string param_str(ostr.str());
LL_INFOS() << param_str << LL_ENDL;
LL_INFOS() << "Notation size: " << param_str.size() << LL_ENDL;
}
{
std::ostringstream ostr;
LLSDSerialize::serialize(data, ostr, LLSDSerialize::LLSD_BINARY);
std::string param_str(ostr.str());
LL_INFOS() << "Binary size: " << param_str.size() << LL_ENDL;
}
#endif
}

View File

@ -35,10 +35,13 @@
#include "hbxxh.h"
#include <string>
#include <map>
namespace tinygltf
{
class Model;
struct TextureInfo;
class Value;
}
class LLTextureEntry;
@ -52,6 +55,9 @@ public:
static const char* const ASSET_VERSION;
static const char* const ASSET_TYPE;
// Max allowed size of a GLTF material asset or override, when serialized
// as a minified JSON string
static constexpr size_t MAX_ASSET_LENGTH = 2048;
static const std::array<std::string, 2> ACCEPTED_ASSET_VERSIONS;
static bool isAcceptedVersion(const std::string& version) { return std::find(ACCEPTED_ASSET_VERSIONS.cbegin(), ACCEPTED_ASSET_VERSIONS.cend(), version) != ACCEPTED_ASSET_VERSIONS.cend(); }
@ -64,6 +70,7 @@ public:
void getPacked(F32 (&packed)[8]) const;
bool operator==(const TextureTransform& other) const;
bool operator!=(const TextureTransform& other) const { return !(*this == other); }
};
enum AlphaMode
@ -96,8 +103,13 @@ public:
GLTF_TEXTURE_INFO_COUNT
};
std::array<LLUUID, GLTF_TEXTURE_INFO_COUNT> mTextureId;
static const char* const GLTF_FILE_EXTENSION_TRANSFORM;
static const char* const GLTF_FILE_EXTENSION_TRANSFORM_SCALE;
static const char* const GLTF_FILE_EXTENSION_TRANSFORM_OFFSET;
static const char* const GLTF_FILE_EXTENSION_TRANSFORM_ROTATION;
static const LLUUID GLTF_OVERRIDE_NULL_UUID;
std::array<LLUUID, GLTF_TEXTURE_INFO_COUNT> mTextureId;
std::array<TextureTransform, GLTF_TEXTURE_INFO_COUNT> mTextureTransform;
// NOTE: initialize values to defaults according to the GLTF spec
@ -137,7 +149,7 @@ public:
void setAlphaMode(S32 mode, bool for_override = false);
void setDoubleSided(bool double_sided, bool for_override = false);
//NOTE: texture offsets only exist in overrides, so "for_override" is not needed
// *NOTE: texture offsets only exist in overrides, so "for_override" is not needed
void setTextureOffset(TextureInfo texture_info, const LLVector2& offset);
void setTextureScale(TextureInfo texture_info, const LLVector2& scale);
@ -155,7 +167,6 @@ public:
static LLVector2 getDefaultTextureScale();
static F32 getDefaultTextureRotation();
static void hackOverrideUUID(LLUUID& id);
static void applyOverrideUUID(LLUUID& dst_id, const LLUUID& override_id);
@ -164,7 +175,7 @@ public:
void setAlphaMode(const std::string& mode, bool for_override = false);
const char* getAlphaMode() const;
// set the contents of this LLGLTFMaterial from the given json
// returns true if successful
// if unsuccessful, the contents of this LLGLTFMaterial should be left unchanged and false is returned
@ -176,7 +187,6 @@ public:
// get the contents of this LLGLTFMaterial as a json string
std::string asJSON(bool prettyprint = false) const;
// initialize from given tinygltf::Model
// model - the model to reference
// mat_index - index of material in model's material array
@ -202,21 +212,29 @@ public:
// For material overrides only. Clears most properties to
// default/fallthrough, but preserves the transforms.
bool setBaseMaterial();
void setBaseMaterial(const LLGLTFMaterial& old_override_mat);
// True if setBaseMaterial() was just called
bool isClearedForBaseMaterial();
bool isClearedForBaseMaterial() const;
// For local materials, they have to keep track of where
// they are assigned to for full updates
virtual void addTextureEntry(LLTextureEntry* te) {};
virtual void removeTextureEntry(LLTextureEntry* te) {};
private:
protected:
static LLVector2 vec2FromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const LLVector2& default_value);
static F32 floatFromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const F32 default_value);
template<typename T>
static void allocateTextureImage(tinygltf::Model& model, T& texture_info, const std::string& uri);
template<typename T>
void setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id);
template<typename T>
static void setFromTexture(const tinygltf::Model& model, const T& texture_info, LLUUID& texture_id, TextureTransform& transform);
template<typename T>
void writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, bool force_write = false) const;
void setBaseMaterial(const LLGLTFMaterial& old_override_mat);
template<typename T>
static void writeToTexture(tinygltf::Model& model, T& texture_info, const LLUUID& texture_id, const TextureTransform& transform, bool force_write = false);
};

View File

@ -0,0 +1,142 @@
/**
* @file llgltfmaterial_templates.h
* @brief Material template definition
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, 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$
*/
#pragma once
#include "llgltfmaterial.h"
// Use templates here as workaround for the different similar texture info classes in tinygltf
// Includer must first include tiny_gltf.h with the desired flags
template<typename T>
std::string gltf_get_texture_image(const tinygltf::Model& model, const T& texture_info)
{
const S32 texture_idx = texture_info.index;
if (texture_idx < 0 || texture_idx >= model.textures.size())
{
return "";
}
const tinygltf::Texture& texture = model.textures[texture_idx];
// Ignore texture.sampler for now
const S32 image_idx = texture.source;
if (image_idx < 0 || image_idx >= model.images.size())
{
return "";
}
const tinygltf::Image& image = model.images[image_idx];
return image.uri;
}
template<typename T>
void LLGLTFMaterial::setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id)
{
setFromTexture(model, texture_info, mTextureId[texture_info_id], mTextureTransform[texture_info_id]);
const std::string uri = gltf_get_texture_image(model, texture_info);
}
// static
template<typename T>
void LLGLTFMaterial::setFromTexture(const tinygltf::Model& model, const T& texture_info, LLUUID& texture_id, TextureTransform& transform)
{
LL_PROFILE_ZONE_SCOPED;
const std::string uri = gltf_get_texture_image(model, texture_info);
texture_id.set(uri);
const tinygltf::Value::Object& extensions_object = texture_info.extensions;
const auto transform_it = extensions_object.find(GLTF_FILE_EXTENSION_TRANSFORM);
if (transform_it != extensions_object.end())
{
const tinygltf::Value& transform_json = std::get<1>(*transform_it);
if (transform_json.IsObject())
{
const tinygltf::Value::Object& transform_object = transform_json.Get<tinygltf::Value::Object>();
transform.mOffset = vec2FromJson(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_OFFSET, getDefaultTextureOffset());
transform.mScale = vec2FromJson(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_SCALE, getDefaultTextureScale());
transform.mRotation = floatFromJson(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_ROTATION, getDefaultTextureRotation());
}
}
}
// static
template<typename T>
void LLGLTFMaterial::allocateTextureImage(tinygltf::Model& model, T& texture_info, const std::string& uri)
{
const S32 image_idx = model.images.size();
model.images.emplace_back();
model.images[image_idx].uri = uri;
// The texture, not to be confused with the texture info
const S32 texture_idx = model.textures.size();
model.textures.emplace_back();
tinygltf::Texture& texture = model.textures[texture_idx];
texture.source = image_idx;
texture_info.index = texture_idx;
}
// static
template<typename T>
void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, bool force_write) const
{
writeToTexture(model, texture_info, mTextureId[texture_info_id], mTextureTransform[texture_info_id], force_write);
}
// static
template<typename T>
void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, const LLUUID& texture_id, const TextureTransform& transform, bool force_write)
{
LL_PROFILE_ZONE_SCOPED;
const bool is_blank_transform = transform == sDefault.mTextureTransform[0];
// Check if this material matches all the fallback values, and if so, then
// skip including it to reduce material size
if (!force_write && texture_id.isNull() && is_blank_transform)
{
return;
}
// tinygltf will discard this texture info if there is no valid texture,
// causing potential loss of information for overrides, so ensure one is
// defined. -Cosmic,2023-01-30
allocateTextureImage(model, texture_info, texture_id.asString());
if (!is_blank_transform)
{
tinygltf::Value::Object transform_map;
transform_map[GLTF_FILE_EXTENSION_TRANSFORM_OFFSET] = tinygltf::Value(tinygltf::Value::Array({
tinygltf::Value(transform.mOffset.mV[VX]),
tinygltf::Value(transform.mOffset.mV[VY])
}));
transform_map[GLTF_FILE_EXTENSION_TRANSFORM_SCALE] = tinygltf::Value(tinygltf::Value::Array({
tinygltf::Value(transform.mScale.mV[VX]),
tinygltf::Value(transform.mScale.mV[VY])
}));
transform_map[GLTF_FILE_EXTENSION_TRANSFORM_ROTATION] = tinygltf::Value(transform.mRotation);
texture_info.extensions[GLTF_FILE_EXTENSION_TRANSFORM] = tinygltf::Value(transform_map);
}
}

View File

@ -85,6 +85,8 @@ const F32 LIGHT_MAX_CUTOFF = 180.f;
const F32 REFLECTION_PROBE_MIN_AMBIANCE = 0.f;
const F32 REFLECTION_PROBE_MAX_AMBIANCE = 100.f;
const F32 REFLECTION_PROBE_DEFAULT_AMBIANCE = 0.f;
// *NOTE: Clip distances are clamped in LLCamera::setNear. The max clip
// distance is currently limited by the skybox
const F32 REFLECTION_PROBE_MIN_CLIP_DISTANCE = 0.f;
const F32 REFLECTION_PROBE_MAX_CLIP_DISTANCE = 1024.f;
const F32 REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE = 0.f;

View File

@ -29,6 +29,7 @@ set(llrender_SOURCE_FILES
llrendertarget.cpp
llshadermgr.cpp
lltexture.cpp
lltexturemanagerbridge.cpp
lluiimage.cpp
llvertexbuffer.cpp
llglcommonfunc.cpp
@ -58,6 +59,7 @@ set(llrender_HEADER_FILES
llrendersphere.h
llshadermgr.h
lltexture.h
lltexturemanagerbridge.h
lluiimage.h
lluiimage.inl
llvertexbuffer.h

View File

@ -1023,6 +1023,20 @@ LLFontGL* LLFontGL::getFontSansSerifSmall()
return fontp;
}
//static
LLFontGL* LLFontGL::getFontSansSerifSmallBold()
{
static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Small",BOLD));
return fontp;
}
//static
LLFontGL* LLFontGL::getFontSansSerifSmallItalic()
{
static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Small",ITALIC));
return fontp;
}
//static
LLFontGL* LLFontGL::getFontSansSerif()
{

View File

@ -189,6 +189,8 @@ public:
static LLFontGL* getFontMonospace();
static LLFontGL* getFontSansSerifSmall();
static LLFontGL* getFontSansSerifSmallBold();
static LLFontGL* getFontSansSerifSmallItalic();
static LLFontGL* getFontSansSerif();
static LLFontGL* getFontSansSerifBig();
static LLFontGL* getFontSansSerifHuge();

View File

@ -27,7 +27,6 @@
#ifndef LL_TEXTUREMANAGERBRIDGE_H
#define LL_TEXTUREMANAGERBRIDGE_H
#include "llavatarappearancedefines.h"
#include "llpointer.h"
#include "llgltexture.h"

View File

@ -60,7 +60,7 @@ LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params)
initNoTabsWidget(params.no_matched_tabs_text);
mSingleExpansion = params.single_expansion;
if(mFitParent && !mSingleExpansion)
if (mFitParent && !mSingleExpansion)
{
LL_INFOS() << "fit_parent works best when combined with single_expansion" << LL_ENDL;
}
@ -102,14 +102,13 @@ void LLAccordionCtrl::draw()
LLPanel::draw();
}
//---------------------------------------------------------------------------------
BOOL LLAccordionCtrl::postBuild()
{
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
static LLUICachedControl<S32> scrollbar_size("UIScrollbarSize", 0);
LLRect scroll_rect;
scroll_rect.setOriginAndSize(
scroll_rect.setOriginAndSize(
getRect().getWidth() - scrollbar_size,
1,
scrollbar_size,
@ -126,39 +125,42 @@ BOOL LLAccordionCtrl::postBuild()
sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
sbparams.change_callback(boost::bind(&LLAccordionCtrl::onScrollPosChangeCallback, this, _1, _2));
mScrollbar = LLUICtrlFactory::create<LLScrollbar> (sbparams);
LLView::addChild( mScrollbar );
mScrollbar->setVisible( false );
mScrollbar = LLUICtrlFactory::create<LLScrollbar>(sbparams);
LLView::addChild(mScrollbar);
mScrollbar->setVisible(FALSE);
mScrollbar->setFollowsRight();
mScrollbar->setFollowsTop();
mScrollbar->setFollowsBottom();
//if it was created from xml...
std::vector<LLUICtrl*> accordion_tabs;
for(child_list_const_iter_t it = getChildList()->begin();
for (child_list_const_iter_t it = getChildList()->begin();
getChildList()->end() != it; ++it)
{
LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(*it);
if(accordion_tab == NULL)
if (accordion_tab == NULL)
continue;
if(std::find(mAccordionTabs.begin(),mAccordionTabs.end(),accordion_tab) == mAccordionTabs.end())
if (std::find(mAccordionTabs.begin(), mAccordionTabs.end(), accordion_tab) == mAccordionTabs.end())
{
accordion_tabs.push_back(accordion_tab);
}
}
for(std::vector<LLUICtrl*>::reverse_iterator it = accordion_tabs.rbegin();it!=accordion_tabs.rend();++it)
addCollapsibleCtrl(*it);
arrange ();
if(mSingleExpansion)
for (std::vector<LLUICtrl*>::reverse_iterator it = accordion_tabs.rbegin();
it < accordion_tabs.rend(); ++it)
{
if(!mAccordionTabs[0]->getDisplayChildren())
addCollapsibleCtrl(*it);
}
arrange();
if (mSingleExpansion)
{
if (!mAccordionTabs[0]->getDisplayChildren())
mAccordionTabs[0]->setDisplayChildren(true);
for(size_t i=1;i<mAccordionTabs.size();++i)
for (size_t i = 1; i < mAccordionTabs.size(); ++i)
{
if(mAccordionTabs[i]->getDisplayChildren())
if (mAccordionTabs[i]->getDisplayChildren())
mAccordionTabs[i]->setDisplayChildren(false);
}
}
@ -205,23 +207,22 @@ BOOL LLAccordionCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
//---------------------------------------------------------------------------------
void LLAccordionCtrl::shiftAccordionTabs(S16 panel_num, S32 delta)
{
for(size_t i = panel_num; i < mAccordionTabs.size(); i++ )
for (size_t i = panel_num; i < mAccordionTabs.size(); ++i)
{
ctrlShiftVertical(mAccordionTabs[i],delta);
}
}
//---------------------------------------------------------------------------------
void LLAccordionCtrl::onCollapseCtrlCloseOpen(S16 panel_num)
{
if(mSingleExpansion)
if (mSingleExpansion)
{
for(size_t i=0;i<mAccordionTabs.size();++i)
for (size_t i = 0; i < mAccordionTabs.size(); ++i)
{
if(i==panel_num)
if (i == panel_num)
continue;
if(mAccordionTabs[i]->getDisplayChildren())
if (mAccordionTabs[i]->getDisplayChildren())
mAccordionTabs[i]->setDisplayChildren(false);
}
@ -232,64 +233,63 @@ void LLAccordionCtrl::onCollapseCtrlCloseOpen(S16 panel_num)
void LLAccordionCtrl::show_hide_scrollbar(S32 width, S32 height)
{
calcRecuiredHeight();
if(getRecuiredHeight() > height )
showScrollbar(width,height);
if (getRecuiredHeight() > height)
showScrollbar(width, height);
else
hideScrollbar(width,height);
hideScrollbar(width, height);
}
void LLAccordionCtrl::showScrollbar(S32 width, S32 height)
void LLAccordionCtrl::showScrollbar(S32 width, S32 height)
{
bool was_visible = mScrollbar->getVisible();
mScrollbar->setVisible(true);
mScrollbar->setVisible(TRUE);
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
ctrlSetLeftTopAndSize(mScrollbar
,width-scrollbar_size - PARENT_BORDER_MARGIN/2
,height-PARENT_BORDER_MARGIN
,scrollbar_size
,height-2*PARENT_BORDER_MARGIN);
, width - scrollbar_size - PARENT_BORDER_MARGIN / 2
, height - PARENT_BORDER_MARGIN
, scrollbar_size
, height - PARENT_BORDER_MARGIN * 2);
mScrollbar->setPageSize(height);
mScrollbar->setDocParams(mInnerRect.getHeight(),mScrollbar->getDocPos());
mScrollbar->setDocParams(mInnerRect.getHeight(), mScrollbar->getDocPos());
if(was_visible)
if (was_visible)
{
S32 scroll_pos = llmin(mScrollbar->getDocPos(), getRecuiredHeight() - height - 1);
mScrollbar->setDocPos(scroll_pos);
}
}
void LLAccordionCtrl::hideScrollbar( S32 width, S32 height )
void LLAccordionCtrl::hideScrollbar(S32 width, S32 height)
{
if(mScrollbar->getVisible() == false)
if (mScrollbar->getVisible() == FALSE)
return;
mScrollbar->setVisible(false);
mScrollbar->setVisible(FALSE);
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
S32 panel_width = width - 2*BORDER_MARGIN;
//reshape all accordeons and shift all draggers
for(size_t i=0;i<mAccordionTabs.size();++i)
// Reshape all accordions and shift all draggers
for (size_t i = 0; i < mAccordionTabs.size(); ++i)
{
LLRect panel_rect = mAccordionTabs[i]->getRect();
ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_rect.mTop,panel_width,panel_rect.getHeight());
ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_rect.mLeft, panel_rect.mTop, panel_width, panel_rect.getHeight());
}
mScrollbar->setDocPos(0);
if(mAccordionTabs.size()>0)
if (!mAccordionTabs.empty())
{
S32 panel_top = height - BORDER_MARGIN; // Top coordinate of the first panel
S32 panel_top = height - BORDER_MARGIN; // Top coordinate of the first panel
S32 diff = panel_top - mAccordionTabs[0]->getRect().mTop;
shiftAccordionTabs(0,diff);
shiftAccordionTabs(0, diff);
}
}
//---------------------------------------------------------------------------------
S32 LLAccordionCtrl::calcRecuiredHeight()
{
@ -305,7 +305,7 @@ S32 LLAccordionCtrl::calcRecuiredHeight()
}
}
mInnerRect.setLeftTopAndSize(0,rec_height + BORDER_MARGIN*2,getRect().getWidth(),rec_height + BORDER_MARGIN);
mInnerRect.setLeftTopAndSize(0, rec_height + BORDER_MARGIN * 2, getRect().getWidth(), rec_height + BORDER_MARGIN);
return mInnerRect.getHeight();
}
@ -313,7 +313,7 @@ S32 LLAccordionCtrl::calcRecuiredHeight()
//---------------------------------------------------------------------------------
void LLAccordionCtrl::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height)
{
if(!panel)
if (!panel)
return;
LLRect panel_rect = panel->getRect();
panel_rect.setLeftTopAndSize( left, top, width, height);
@ -321,9 +321,9 @@ void LLAccordionCtrl::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S3
panel->setRect(panel_rect);
}
void LLAccordionCtrl::ctrlShiftVertical(LLView* panel,S32 delta)
void LLAccordionCtrl::ctrlShiftVertical(LLView* panel, S32 delta)
{
if(!panel)
if (!panel)
return;
panel->translate(0,delta);
}
@ -333,9 +333,9 @@ void LLAccordionCtrl::ctrlShiftVertical(LLView* panel,S32 delta)
void LLAccordionCtrl::addCollapsibleCtrl(LLView* view)
{
LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(view);
if(!accordion_tab)
if (!accordion_tab)
return;
if(std::find(beginChild(), endChild(), accordion_tab) == endChild())
if (std::find(beginChild(), endChild(), accordion_tab) == endChild())
addChild(accordion_tab);
mAccordionTabs.push_back(accordion_tab);
@ -369,7 +369,7 @@ void LLAccordionCtrl::removeCollapsibleCtrl(LLView* view)
}
}
void LLAccordionCtrl::initNoTabsWidget(const LLTextBox::Params& tb_params)
void LLAccordionCtrl::initNoTabsWidget(const LLTextBox::Params& tb_params)
{
LLTextBox::Params tp = tb_params;
tp.rect(getLocalRect());
@ -377,39 +377,39 @@ void LLAccordionCtrl::initNoTabsWidget(const LLTextBox::Params& tb_params)
mNoVisibleTabsHelpText = LLUICtrlFactory::create<LLTextBox>(tp, this);
}
void LLAccordionCtrl::updateNoTabsHelpTextVisibility()
void LLAccordionCtrl::updateNoTabsHelpTextVisibility()
{
bool visible_exists = false;
std::vector<LLAccordionCtrlTab*>::const_iterator it = mAccordionTabs.begin();
const std::vector<LLAccordionCtrlTab*>::const_iterator it_end = mAccordionTabs.end();
for (; it != it_end; ++it)
while (it < it_end)
{
if ((*it)->getVisible())
if ((*(it++))->getVisible())
{
visible_exists = true;
break;
}
}
mNoVisibleTabsHelpText->setVisible(!visible_exists);
mNoVisibleTabsHelpText->setVisible(visible_exists ? FALSE : TRUE);
}
void LLAccordionCtrl::arrangeSinge()
void LLAccordionCtrl::arrangeSingle()
{
S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter
S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel
S32 panel_width = getRect().getWidth() - 4; // Top coordinate of the first panel
S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter
S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel
S32 panel_width = getRect().getWidth() - 4;
S32 panel_height;
S32 collapsed_height = 0;
for(size_t i=0;i<mAccordionTabs.size();++i)
for (size_t i = 0; i < mAccordionTabs.size(); ++i)
{
LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
if(accordion_tab->getVisible() == false) //skip hidden accordion tabs
if (accordion_tab->getVisible() == FALSE) // Skip hidden accordion tabs
continue;
if(!accordion_tab->isExpanded() )
if (!accordion_tab->isExpanded() )
{
collapsed_height+=mAccordionTabs[i]->getRect().getHeight();
}
@ -417,28 +417,28 @@ void LLAccordionCtrl::arrangeSinge()
S32 expanded_height = getRect().getHeight() - BORDER_MARGIN - collapsed_height;
for(size_t i=0;i<mAccordionTabs.size();++i)
for (size_t i = 0; i < mAccordionTabs.size(); ++i)
{
LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
if(accordion_tab->getVisible() == false) //skip hidden accordion tabs
if (accordion_tab->getVisible() == FALSE) // Skip hidden accordion tabs
continue;
if(!accordion_tab->isExpanded() )
if (!accordion_tab->isExpanded() )
{
panel_height = accordion_tab->getRect().getHeight();
}
else
{
if(mFitParent)
if (mFitParent)
{
panel_height = expanded_height;
}
else
{
if(accordion_tab->getAccordionView())
if (accordion_tab->getAccordionView())
{
panel_height = accordion_tab->getAccordionView()->getRect().getHeight() +
accordion_tab->getHeaderHeight() + 2*BORDER_MARGIN;
accordion_tab->getHeaderHeight() + BORDER_MARGIN * 2;
}
else
{
@ -451,67 +451,67 @@ void LLAccordionCtrl::arrangeSinge()
panel_height = llmax(panel_height, accordion_tab->getHeaderHeight());
ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height);
panel_top-=mAccordionTabs[i]->getRect().getHeight();
panel_top -= mAccordionTabs[i]->getRect().getHeight();
}
show_hide_scrollbar(getRect().getWidth(), getRect().getHeight());
updateLayout(getRect().getWidth(), getRect().getHeight());
}
void LLAccordionCtrl::arrangeMultiple()
void LLAccordionCtrl::arrangeMultiple()
{
S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter
S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel
S32 panel_width = getRect().getWidth() - 4; // Top coordinate of the first panel
S32 panel_left = BORDER_MARGIN; // Margin from left side of Splitter
S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel
S32 panel_width = getRect().getWidth() - 4;
//Calculate params
for(size_t i = 0; i < mAccordionTabs.size(); i++ )
for (size_t i = 0; i < mAccordionTabs.size(); i++ )
{
LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
if(accordion_tab->getVisible() == false) //skip hidden accordion tabs
if (accordion_tab->getVisible() == FALSE) // Skip hidden accordion tabs
continue;
if(!accordion_tab->isExpanded() )
if (!accordion_tab->isExpanded() )
{
ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, accordion_tab->getRect().getHeight());
panel_top-=mAccordionTabs[i]->getRect().getHeight();
panel_top -= mAccordionTabs[i]->getRect().getHeight();
}
else
{
S32 panel_height = accordion_tab->getRect().getHeight();
if(mFitParent)
if (mFitParent)
{
// all expanded tabs will have equal height
// All expanded tabs will have equal height
panel_height = calcExpandedTabHeight(i, panel_top);
ctrlSetLeftTopAndSize(accordion_tab, panel_left, panel_top, panel_width, panel_height);
// try to make accordion tab fit accordion view height.
// Try to make accordion tab fit accordion view height.
// Accordion View should implement getRequiredRect() and provide valid height
S32 optimal_height = accordion_tab->getAccordionView()->getRequiredRect().getHeight();
optimal_height += accordion_tab->getHeaderHeight() + 2 * BORDER_MARGIN;
if(optimal_height < panel_height)
if (optimal_height < panel_height)
{
panel_height = optimal_height;
}
// minimum tab height is equal to header height
if(mAccordionTabs[i]->getHeaderHeight() > panel_height)
if (mAccordionTabs[i]->getHeaderHeight() > panel_height)
{
panel_height = mAccordionTabs[i]->getHeaderHeight();
}
}
ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height);
panel_top-=panel_height;
panel_top -= panel_height;
}
}
show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
show_hide_scrollbar(getRect().getWidth(), getRect().getHeight());
updateLayout(getRect().getWidth(),getRect().getHeight());
updateLayout(getRect().getWidth(), getRect().getHeight());
}
@ -519,70 +519,67 @@ void LLAccordionCtrl::arrange()
{
updateNoTabsHelpTextVisibility();
if( mAccordionTabs.size() == 0)
if (mAccordionTabs.empty())
{
//We do not arrange if we do not have what should be arranged
// Nothing to arrange
return;
}
if(mAccordionTabs.size() == 1)
if (mAccordionTabs.size() == 1)
{
S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel
S32 panel_width = getRect().getWidth() - 4; // Top coordinate of the first panel
S32 panel_top = getRect().getHeight() - BORDER_MARGIN; // Top coordinate of the first panel
S32 panel_width = getRect().getWidth() - 4;
LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[0]);
LLRect panel_rect = accordion_tab->getRect();
S32 panel_height = getRect().getHeight() - 2*BORDER_MARGIN;
S32 panel_height = getRect().getHeight() - BORDER_MARGIN * 2;
if (accordion_tab->getFitParent())
panel_height = accordion_tab->getRect().getHeight();
ctrlSetLeftTopAndSize(accordion_tab,panel_rect.mLeft,panel_top,panel_width,panel_height);
show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
return;
ctrlSetLeftTopAndSize(accordion_tab, panel_rect.mLeft, panel_top, panel_width, panel_height);
show_hide_scrollbar(getRect().getWidth(), getRect().getHeight());
return;
}
if(mSingleExpansion)
arrangeSinge ();
if (mSingleExpansion)
arrangeSingle();
else
arrangeMultiple ();
arrangeMultiple();
}
//---------------------------------------------------------------------------------
BOOL LLAccordionCtrl::handleScrollWheel ( S32 x, S32 y, S32 clicks )
BOOL LLAccordionCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
if(LLPanel::handleScrollWheel(x,y,clicks))
if (LLPanel::handleScrollWheel(x, y, clicks))
return TRUE;
if( mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) )
if (mScrollbar->getVisible() && mScrollbar->handleScrollWheel(0, 0, clicks))
return TRUE;
return false;
return FALSE;
}
BOOL LLAccordionCtrl::handleKeyHere (KEY key, MASK mask)
BOOL LLAccordionCtrl::handleKeyHere(KEY key, MASK mask)
{
if( mScrollbar->getVisible() && mScrollbar->handleKeyHere( key,mask ) )
if (mScrollbar->getVisible() && mScrollbar->handleKeyHere(key, mask))
return TRUE;
return LLPanel::handleKeyHere(key,mask);
return LLPanel::handleKeyHere(key, mask);
}
BOOL LLAccordionCtrl::handleDragAndDrop (S32 x, S32 y, MASK mask,
BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg)
BOOL LLAccordionCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg)
{
// Scroll folder view if needed. Never accepts a drag or drop.
*accept = ACCEPT_NO;
BOOL handled = autoScroll(x, y);
if( !handled )
if (!handled)
{
handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type,
cargo_data, accept, tooltip_msg) != NULL;
@ -590,14 +587,14 @@ BOOL LLAccordionCtrl::handleDragAndDrop (S32 x, S32 y, MASK mask,
return TRUE;
}
BOOL LLAccordionCtrl::autoScroll (S32 x, S32 y)
BOOL LLAccordionCtrl::autoScroll(S32 x, S32 y)
{
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
bool scrolling = false;
if( mScrollbar->getVisible() )
if (mScrollbar->getVisible())
{
LLRect rect_local( 0, getRect().getHeight(), getRect().getWidth() - scrollbar_size, 0 );
LLRect rect_local(0, getRect().getHeight(), getRect().getWidth() - scrollbar_size, 0);
LLRect screen_local_extents;
// clip rect against root view
@ -610,51 +607,52 @@ BOOL LLAccordionCtrl::autoScroll (S32 x, S32 y)
LLRect bottom_scroll_rect = screen_local_extents;
bottom_scroll_rect.mTop = rect_local.mBottom + auto_scroll_region_height;
if( bottom_scroll_rect.pointInRect( x, y ) && (mScrollbar->getDocPos() < mScrollbar->getDocPosMax()) )
if (bottom_scroll_rect.pointInRect( x, y ) && (mScrollbar->getDocPos() < mScrollbar->getDocPosMax()))
{
mScrollbar->setDocPos( mScrollbar->getDocPos() + auto_scroll_speed );
mScrollbar->setDocPos(mScrollbar->getDocPos() + auto_scroll_speed);
mAutoScrolling = true;
scrolling = true;
}
LLRect top_scroll_rect = screen_local_extents;
top_scroll_rect.mBottom = rect_local.mTop - auto_scroll_region_height;
if( top_scroll_rect.pointInRect( x, y ) && (mScrollbar->getDocPos() > 0) )
if (top_scroll_rect.pointInRect(x, y) && (mScrollbar->getDocPos() > 0))
{
mScrollbar->setDocPos( mScrollbar->getDocPos() - auto_scroll_speed );
mScrollbar->setDocPos(mScrollbar->getDocPos() - auto_scroll_speed);
mAutoScrolling = true;
scrolling = true;
}
}
return scrolling;
return scrolling ? TRUE : FALSE;
}
void LLAccordionCtrl::updateLayout (S32 width, S32 height)
void LLAccordionCtrl::updateLayout(S32 width, S32 height)
{
S32 panel_top = height - BORDER_MARGIN ;
if(mScrollbar->getVisible())
panel_top+=mScrollbar->getDocPos();
if (mScrollbar->getVisible())
panel_top += mScrollbar->getDocPos();
S32 panel_width = width - 2*BORDER_MARGIN;
S32 panel_width = width - BORDER_MARGIN * 2;
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
if(mScrollbar->getVisible())
panel_width-=scrollbar_size;
if (mScrollbar->getVisible())
panel_width -= scrollbar_size;
//set sizes for first panels and dragbars
for(size_t i=0;i<mAccordionTabs.size();++i)
// set sizes for first panels and dragbars
for (size_t i = 0; i < mAccordionTabs.size(); ++i)
{
if(!mAccordionTabs[i]->getVisible())
if (!mAccordionTabs[i]->getVisible())
continue;
LLRect panel_rect = mAccordionTabs[i]->getRect();
ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_top,panel_width,panel_rect.getHeight());
panel_top-=panel_rect.getHeight();
ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_rect.mLeft, panel_top, panel_width, panel_rect.getHeight());
panel_top -= panel_rect.getHeight();
}
}
void LLAccordionCtrl::onScrollPosChangeCallback(S32, LLScrollbar*)
void LLAccordionCtrl::onScrollPosChangeCallback(S32, LLScrollbar*)
{
updateLayout(getRect().getWidth(),getRect().getHeight());
updateLayout(getRect().getWidth(), getRect().getHeight());
}
// virtual
@ -687,42 +685,43 @@ void LLAccordionCtrl::onUpdateScrollToChild(const LLUICtrl *cntrl)
LLUICtrl::onUpdateScrollToChild(cntrl);
}
void LLAccordionCtrl::onOpen (const LLSD& key)
void LLAccordionCtrl::onOpen(const LLSD& key)
{
for(size_t i=0;i<mAccordionTabs.size();++i)
for (size_t i = 0; i < mAccordionTabs.size(); ++i)
{
LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
LLPanel* panel = dynamic_cast<LLPanel*>(accordion_tab->getAccordionView());
if(panel!=NULL)
if (panel != NULL)
{
panel->onOpen(key);
}
}
}
S32 LLAccordionCtrl::notifyParent(const LLSD& info)
{
if(info.has("action"))
if (info.has("action"))
{
std::string str_action = info["action"];
if(str_action == "size_changes")
if (str_action == "size_changes")
{
//
arrange();
return 1;
}
else if(str_action == "select_next")
if (str_action == "select_next")
{
for(size_t i=0;i<mAccordionTabs.size();++i)
for (size_t i = 0; i < mAccordionTabs.size(); ++i)
{
LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
if(accordion_tab->hasFocus())
if (accordion_tab->hasFocus())
{
while(++i<mAccordionTabs.size())
while (++i < mAccordionTabs.size())
{
if(mAccordionTabs[i]->getVisible())
if (mAccordionTabs[i]->getVisible())
break;
}
if(i<mAccordionTabs.size())
if (i < mAccordionTabs.size())
{
accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
accordion_tab->notify(LLSD().with("action","select_first"));
@ -733,17 +732,17 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info)
}
return 0;
}
else if(str_action == "select_prev")
if (str_action == "select_prev")
{
for(size_t i=0;i<mAccordionTabs.size();++i)
for (size_t i = 0; i < mAccordionTabs.size(); ++i)
{
LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
if(accordion_tab->hasFocus() && i>0)
if (accordion_tab->hasFocus() && i > 0)
{
bool prev_visible_tab_found = false;
while(i>0)
while (i > 0)
{
if(mAccordionTabs[--i]->getVisible())
if (mAccordionTabs[--i]->getVisible())
{
prev_visible_tab_found = true;
break;
@ -761,12 +760,12 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info)
}
return 0;
}
else if(str_action == "select_current")
if (str_action == "select_current")
{
for(size_t i=0;i<mAccordionTabs.size();++i)
for (size_t i = 0; i < mAccordionTabs.size(); ++i)
{
// Set selection to the currently focused tab.
if(mAccordionTabs[i]->hasFocus())
if (mAccordionTabs[i]->hasFocus())
{
if (mAccordionTabs[i] != mSelectedTab)
{
@ -783,7 +782,7 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info)
}
return 0;
}
else if(str_action == "deselect_current")
if (str_action == "deselect_current")
{
// Reset selection to the currently selected tab.
if (mSelectedTab)
@ -802,9 +801,9 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info)
screenRectToLocal(screen_rc, &local_rc);
// Translate to parent coordinatess to check if we are in visible rectangle
local_rc.translate( getRect().mLeft, getRect().mBottom );
local_rc.translate(getRect().mLeft, getRect().mBottom);
if ( !getRect().contains (local_rc) )
if (!getRect().contains (local_rc))
{
// Back to local coords and calculate position for scroller
S32 bottom = mScrollbar->getDocPos() - local_rc.mBottom + getRect().mBottom;
@ -814,7 +813,7 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info)
bottom, // min vertical scroll
top); // max vertical scroll
mScrollbar->setDocPos( scroll_pos );
mScrollbar->setDocPos(scroll_pos);
}
return 1;
}
@ -834,15 +833,16 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info)
}
return LLPanel::notifyParent(info);
}
void LLAccordionCtrl::reset ()
void LLAccordionCtrl::reset()
{
if(mScrollbar)
if (mScrollbar)
mScrollbar->setDocPos(0);
}
void LLAccordionCtrl::expandDefaultTab()
{
if (mAccordionTabs.size() > 0)
if (!mAccordionTabs.empty())
{
LLAccordionCtrlTab* tab = mAccordionTabs.front();
@ -877,7 +877,7 @@ void LLAccordionCtrl::sort()
arrange();
}
void LLAccordionCtrl::setFilterSubString(const std::string& filter_string)
void LLAccordionCtrl::setFilterSubString(const std::string& filter_string)
{
LLStringUtil::format_map_t args;
args["[SEARCH_TERM]"] = LLURI::escape(filter_string);
@ -907,7 +907,7 @@ const LLAccordionCtrlTab* LLAccordionCtrl::getExpandedTab() const
S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 available_height /* = 0 */)
{
if(tab_index < 0)
if (tab_index < 0)
{
return available_height;
}
@ -915,9 +915,9 @@ S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 availabl
S32 collapsed_tabs_height = 0;
S32 num_expanded = 0;
for(size_t n = tab_index; n < mAccordionTabs.size(); ++n)
for (size_t n = tab_index; n < mAccordionTabs.size(); ++n)
{
if(!mAccordionTabs[n]->isExpanded())
if (!mAccordionTabs[n]->isExpanded())
{
collapsed_tabs_height += mAccordionTabs[n]->getHeaderHeight();
}
@ -927,7 +927,7 @@ S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 availabl
}
}
if(0 == num_expanded)
if (0 == num_expanded)
{
return available_height;
}

View File

@ -144,7 +144,7 @@ private:
void initNoTabsWidget(const LLTextBox::Params& tb_params);
void updateNoTabsHelpTextVisibility();
void arrangeSinge();
void arrangeSingle();
void arrangeMultiple();
// Calc Splitter's height that is necessary to display all child content

View File

@ -69,13 +69,13 @@ public:
virtual BOOL postBuild();
std::string getTitle();
void setTitle(const std::string& title, const std::string& hl);
void setTitle(const std::string& title, const std::string& hl);
void setTitleFontStyle(std::string style);
void setTitleFontStyle(std::string style);
void setTitleColor(LLUIColor);
void setTitleColor(LLUIColor);
void setSelected(bool is_selected) { mIsSelected = is_selected; }
void setSelected(bool is_selected) { mIsSelected = is_selected; }
virtual void onMouseEnter(S32 x, S32 y, MASK mask);
virtual void onMouseLeave(S32 x, S32 y, MASK mask);
@ -85,8 +85,8 @@ public:
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg);
private:
private:
LLTextBox* mHeaderTextbox;
// Overlay images (arrows)
@ -102,7 +102,7 @@ private:
LLPointer<LLUIImage> mImageHeaderFocused;
// style saved when applying it in setTitleFontStyle
LLStyle::Params mStyleParams;
LLStyle::Params mStyleParams;
LLUIColor mHeaderBGColor;
@ -157,19 +157,17 @@ BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::postBuild()
std::string LLAccordionCtrlTab::LLAccordionCtrlTabHeader::getTitle()
{
if(mHeaderTextbox)
if (mHeaderTextbox)
{
return mHeaderTextbox->getText();
}
else
{
return LLStringUtil::null;
}
return LLStringUtil::null;
}
void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitle(const std::string& title, const std::string& hl)
{
if(mHeaderTextbox)
if (mHeaderTextbox)
{
LLTextUtil::textboxSetHighlightedVal(
mHeaderTextbox,
@ -192,7 +190,7 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitleFontStyle(std::string
void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitleColor(LLUIColor color)
{
if(mHeaderTextbox)
if (mHeaderTextbox)
{
mHeaderTextbox->setColor(color);
}
@ -204,11 +202,11 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw()
S32 height = getRect().getHeight();
F32 alpha = getCurrentTransparency();
gl_rect_2d(0,0,width - 1 ,height - 1,mHeaderBGColor.get() % alpha,true);
gl_rect_2d(0, 0, width - 1, height - 1, mHeaderBGColor.get() % alpha, TRUE);
LLAccordionCtrlTab* parent = dynamic_cast<LLAccordionCtrlTab*>(getParent());
bool collapsible = (parent && parent->getCollapsible());
bool expanded = (parent && parent->getDisplayChildren());
bool collapsible = parent && parent->getCollapsible();
bool expanded = parent && parent->getDisplayChildren();
// Handle overlay images, if needed
// Only show green "focus" background image if the accordion is open,
@ -218,23 +216,22 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw()
/*&& !(collapsible && !expanded)*/ // WHY??
)
{
mImageHeaderFocused->draw(0,0,width,height);
mImageHeaderFocused->draw(0, 0, width, height);
}
else
{
mImageHeader->draw(0,0,width,height);
mImageHeader->draw(0, 0, width, height);
}
if(mNeedsHighlight)
if (mNeedsHighlight)
{
mImageHeaderOver->draw(0,0,width,height);
mImageHeaderOver->draw(0, 0, width, height);
}
if(collapsible)
if (collapsible)
{
LLPointer<LLUIImage> overlay_image;
if(expanded)
if (expanded)
{
overlay_image = mImageExpanded;
}
@ -242,8 +239,7 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw()
{
overlay_image = mImageCollapsed;
}
overlay_image->draw(HEADER_IMAGE_LEFT_OFFSET,
(height - overlay_image->getHeight()) / 2);
overlay_image->draw(HEADER_IMAGE_LEFT_OFFSET, (height - overlay_image->getHeight()) / 2);
}
LLUICtrl::draw();
@ -253,7 +249,7 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::reshape(S32 width, S32 height
{
S32 header_height = mHeaderTextbox->getTextPixelHeight();
LLRect textboxRect(HEADER_TEXT_LEFT_OFFSET,(height+header_height)/2 ,width,(height-header_height)/2);
LLRect textboxRect(HEADER_TEXT_LEFT_OFFSET, (height + header_height) / 2, width, (height - header_height) / 2);
mHeaderTextbox->reshape(textboxRect.getWidth(), textboxRect.getHeight());
mHeaderTextbox->setRect(textboxRect);
@ -272,20 +268,24 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseEnter(S32 x, S32 y, MA
LLUICtrl::onMouseEnter(x, y, mask);
mNeedsHighlight = true;
}
void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseLeave(S32 x, S32 y, MASK mask)
{
LLUICtrl::onMouseLeave(x, y, mask);
mNeedsHighlight = false;
mAutoOpenTimer.stop();
}
BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleKey(KEY key, MASK mask, BOOL called_from_parent)
{
if ( ( key == KEY_LEFT || key == KEY_RIGHT) && mask == MASK_NONE)
if ((key == KEY_LEFT || key == KEY_RIGHT) && mask == MASK_NONE)
{
return getParent()->handleKey(key, mask, called_from_parent);
}
return LLUICtrl::handleKey(key, mask, called_from_parent);
}
BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop,
EDragAndDropType cargo_type,
@ -295,7 +295,7 @@ BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleDragAndDrop(S32 x, S32
{
LLAccordionCtrlTab* parent = dynamic_cast<LLAccordionCtrlTab*>(getParent());
if ( parent && !parent->getDisplayChildren() && parent->getCollapsible() && parent->canOpenClose() )
if (parent && !parent->getDisplayChildren() && parent->getCollapsible() && parent->canOpenClose())
{
if (mAutoOpenTimer.getStarted())
{
@ -307,12 +307,15 @@ BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleDragAndDrop(S32 x, S32
}
}
else
{
mAutoOpenTimer.start();
}
}
return LLUICtrl::handleDragAndDrop(x, y, mask, drop, cargo_type,
cargo_data, accept, tooltip_msg);
}
LLAccordionCtrlTab::Params::Params()
: title("title")
,display_children("expanded", true)
@ -384,41 +387,39 @@ LLAccordionCtrlTab::~LLAccordionCtrlTab()
{
}
void LLAccordionCtrlTab::setDisplayChildren(bool display)
{
mDisplayChildren = display;
LLRect rect = getRect();
rect.mBottom = rect.mTop - (getDisplayChildren() ?
mExpandedHeight : HEADER_HEIGHT);
rect.mBottom = rect.mTop - (getDisplayChildren() ? mExpandedHeight : HEADER_HEIGHT);
setRect(rect);
if(mContainerPanel)
if (mContainerPanel)
{
mContainerPanel->setVisible(getDisplayChildren());
}
if(mDisplayChildren)
if (mDisplayChildren)
{
adjustContainerPanel();
}
else
{
if(mScrollbar)
mScrollbar->setVisible(false);
if (mScrollbar)
mScrollbar->setVisible(FALSE);
}
}
void LLAccordionCtrlTab::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)
{
LLRect headerRect;
headerRect.setLeftTopAndSize(
0,height,width,HEADER_HEIGHT);
headerRect.setLeftTopAndSize(0, height, width, HEADER_HEIGHT);
mHeader->setRect(headerRect);
mHeader->reshape(headerRect.getWidth(), headerRect.getHeight());
if(!mDisplayChildren)
if (!mDisplayChildren)
return;
LLRect childRect;
@ -426,7 +427,7 @@ void LLAccordionCtrlTab::reshape(S32 width, S32 height, BOOL called_from_parent
childRect.setLeftTopAndSize(
getPaddingLeft(),
height - getHeaderHeight() - getPaddingTop(),
width - getPaddingLeft() - getPaddingRight(),
width - getPaddingLeft() - getPaddingRight(),
height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() );
adjustContainerPanel(childRect);
@ -434,7 +435,7 @@ void LLAccordionCtrlTab::reshape(S32 width, S32 height, BOOL called_from_parent
void LLAccordionCtrlTab::changeOpenClose(bool is_open)
{
if(is_open)
if (is_open)
mExpandedHeight = getRect().getHeight();
setDisplayChildren(!is_open);
@ -483,14 +484,14 @@ void LLAccordionCtrlTab::onUpdateScrollToChild(const LLUICtrl *cntrl)
BOOL LLAccordionCtrlTab::handleMouseDown(S32 x, S32 y, MASK mask)
{
if(mCollapsible && mHeaderVisible && mCanOpenClose)
if (mCollapsible && mHeaderVisible && mCanOpenClose)
{
if(y >= (getRect().getHeight() - HEADER_HEIGHT) )
if (y >= (getRect().getHeight() - HEADER_HEIGHT))
{
mHeader->setFocus(true);
changeOpenClose(getDisplayChildren());
//reset stored state
// Reset stored state
mWasStateStored = false;
return TRUE;
}
@ -510,7 +511,7 @@ boost::signals2::connection LLAccordionCtrlTab::setDropDownStateChangedCallback(
bool LLAccordionCtrlTab::addChild(LLView* child, S32 tab_group)
{
if(DD_HEADER_NAME != child->getName())
if (DD_HEADER_NAME != child->getName())
{
reshape(child->getRect().getWidth() , child->getRect().getHeight() + HEADER_HEIGHT );
mExpandedHeight = getRect().getHeight();
@ -518,12 +519,12 @@ bool LLAccordionCtrlTab::addChild(LLView* child, S32 tab_group)
bool res = LLUICtrl::addChild(child, tab_group);
if(DD_HEADER_NAME != child->getName())
if (DD_HEADER_NAME != child->getName())
{
if(!mCollapsible)
if (!mCollapsible)
setDisplayChildren(true);
else
setDisplayChildren(getDisplayChildren());
setDisplayChildren(getDisplayChildren());
}
if (!mContainerPanel)
@ -534,7 +535,7 @@ bool LLAccordionCtrlTab::addChild(LLView* child, S32 tab_group)
void LLAccordionCtrlTab::setAccordionView(LLView* panel)
{
addChild(panel,0);
addChild(panel, 0);
}
std::string LLAccordionCtrlTab::getTitle() const
@ -543,10 +544,8 @@ std::string LLAccordionCtrlTab::getTitle() const
{
return mHeader->getTitle();
}
else
{
return LLStringUtil::null;
}
return LLStringUtil::null;
}
void LLAccordionCtrlTab::setTitle(const std::string& title, const std::string& hl)
@ -579,6 +578,7 @@ boost::signals2::connection LLAccordionCtrlTab::setFocusReceivedCallback(const f
{
return mHeader->setFocusReceivedCallback(cb);
}
return boost::signals2::connection();
}
@ -588,6 +588,7 @@ boost::signals2::connection LLAccordionCtrlTab::setFocusLostCallback(const focus
{
return mHeader->setFocusLostCallback(cb);
}
return boost::signals2::connection();
}
@ -601,59 +602,65 @@ void LLAccordionCtrlTab::setSelected(bool is_selected)
LLView* LLAccordionCtrlTab::findContainerView()
{
for(child_list_const_iter_t it = getChildList()->begin();
getChildList()->end() != it; ++it)
child_list_const_iter_t it = getChildList()->begin(), it_end = getChildList()->end();
while (it != it_end)
{
LLView* child = *it;
if(DD_HEADER_NAME == child->getName())
continue;
if(!child->getVisible())
continue;
return child;
LLView* child = *(it++);
if (DD_HEADER_NAME != child->getName() && child->getVisible())
return child;
}
return NULL;
}
void LLAccordionCtrlTab::selectOnFocusReceived()
{
if (getParent()) // A parent may not be set if tabs are added dynamically.
{
getParent()->notifyParent(LLSD().with("action", "select_current"));
}
}
void LLAccordionCtrlTab::deselectOnFocusLost()
{
if(getParent()) // A parent may not be set if tabs are added dynamically.
if (getParent()) // A parent may not be set if tabs are added dynamically.
{
getParent()->notifyParent(LLSD().with("action", "deselect_current"));
}
}
S32 LLAccordionCtrlTab::getHeaderHeight()
{
return mHeaderVisible?HEADER_HEIGHT:0;
return mHeaderVisible ? HEADER_HEIGHT : 0;
}
void LLAccordionCtrlTab::setHeaderVisible(bool value)
void LLAccordionCtrlTab::setHeaderVisible(bool value)
{
if(mHeaderVisible == value)
if (mHeaderVisible == value)
return;
mHeaderVisible = value;
if(mHeader)
mHeader->setVisible(value);
if (mHeader)
{
mHeader->setVisible(value ? TRUE : FALSE);
}
reshape(getRect().getWidth(), getRect().getHeight(), FALSE);
};
//virtual
BOOL LLAccordionCtrlTab::postBuild()
{
if(mHeader)
if (mHeader)
{
mHeader->setVisible(mHeaderVisible);
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
}
static LLUICachedControl<S32> scrollbar_size("UIScrollbarSize", 0);
LLRect scroll_rect;
scroll_rect.setOriginAndSize(
scroll_rect.setOriginAndSize(
getRect().getWidth() - scrollbar_size,
1,
scrollbar_size,
@ -661,7 +668,7 @@ BOOL LLAccordionCtrlTab::postBuild()
mContainerPanel = findContainerView();
if(!mFitPanel)
if (!mFitPanel)
{
LLScrollbar::Params sbparams;
sbparams.name("scrollable vertical");
@ -674,9 +681,8 @@ BOOL LLAccordionCtrlTab::postBuild()
sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
sbparams.change_callback(boost::bind(&LLAccordionCtrlTab::onScrollPosChangeCallback, this, _1, _2));
mScrollbar = LLUICtrlFactory::create<LLScrollbar> (sbparams);
LLView::addChild( mScrollbar );
mScrollbar = LLUICtrlFactory::create<LLScrollbar>(sbparams);
LLView::addChild(mScrollbar);
mScrollbar->setFollowsRight();
mScrollbar->setFollowsTop();
mScrollbar->setFollowsBottom();
@ -684,44 +690,48 @@ BOOL LLAccordionCtrlTab::postBuild()
mScrollbar->setVisible(false);
}
if(mContainerPanel)
if (mContainerPanel)
{
mContainerPanel->setVisible(mDisplayChildren);
}
return LLUICtrl::postBuild();
}
bool LLAccordionCtrlTab::notifyChildren (const LLSD& info)
bool LLAccordionCtrlTab::notifyChildren (const LLSD& info)
{
if(info.has("action"))
if (info.has("action"))
{
std::string str_action = info["action"];
if(str_action == "store_state")
if (str_action == "store_state")
{
storeOpenCloseState();
return true;
}
if(str_action == "restore_state")
if (str_action == "restore_state")
{
restoreOpenCloseState();
return true;
}
}
return LLUICtrl::notifyChildren(info);
}
S32 LLAccordionCtrlTab::notifyParent(const LLSD& info)
{
if(info.has("action"))
if (info.has("action"))
{
std::string str_action = info["action"];
if(str_action == "size_changes")
if (str_action == "size_changes")
{
//
S32 height = info["height"];
height = llmax(height,10) + HEADER_HEIGHT + getPaddingTop() + getPaddingBottom();
height = llmax(height, 10) + HEADER_HEIGHT + getPaddingTop() + getPaddingBottom();
mExpandedHeight = height;
if(isExpanded() && !mSkipChangesOnNotifyParent)
if (isExpanded() && !mSkipChangesOnNotifyParent)
{
LLRect panel_rect = getRect();
panel_rect.setLeftTopAndSize( panel_rect.mLeft, panel_rect.mTop, panel_rect.getWidth(), height);
@ -729,12 +739,13 @@ S32 LLAccordionCtrlTab::notifyParent(const LLSD& info)
setRect(panel_rect);
}
//LLAccordionCtrl should rearrange accordion tab if one of accordion change its size
// LLAccordionCtrl should rearrange accordion tab if one of accordions changed its size
if (getParent()) // A parent may not be set if tabs are added dynamically.
getParent()->notifyParent(info);
return 1;
}
else if(str_action == "select_prev")
if (str_action == "select_prev")
{
showAndFocusHeader();
return 1;
@ -772,78 +783,85 @@ S32 LLAccordionCtrlTab::notifyParent(const LLSD& info)
S32 LLAccordionCtrlTab::notify(const LLSD& info)
{
if(info.has("action"))
if (info.has("action"))
{
std::string str_action = info["action"];
if(str_action == "select_first")
if (str_action == "select_first")
{
showAndFocusHeader();
return 1;
}
else if( str_action == "select_last" )
if (str_action == "select_last")
{
if(getDisplayChildren() == false)
if (!getDisplayChildren())
{
showAndFocusHeader();
}
else
{
LLView* view = getAccordionView();
if(view)
view->notify(LLSD().with("action","select_last"));
if (view)
{
view->notify(LLSD().with("action", "select_last"));
}
}
}
}
return 0;
}
BOOL LLAccordionCtrlTab::handleKey(KEY key, MASK mask, BOOL called_from_parent)
{
if( !mHeader->hasFocus() )
if (!mHeader->hasFocus())
return LLUICtrl::handleKey(key, mask, called_from_parent);
if ( (key == KEY_RETURN )&& mask == MASK_NONE)
if ((key == KEY_RETURN) && mask == MASK_NONE)
{
changeOpenClose(getDisplayChildren());
return TRUE;
}
if ( (key == KEY_ADD || key == KEY_RIGHT)&& mask == MASK_NONE)
if ((key == KEY_ADD || key == KEY_RIGHT) && mask == MASK_NONE)
{
if(getDisplayChildren() == false)
{
changeOpenClose(getDisplayChildren());
return TRUE;
}
}
if ( (key == KEY_SUBTRACT || key == KEY_LEFT)&& mask == MASK_NONE)
{
if(getDisplayChildren() == true)
if (!getDisplayChildren())
{
changeOpenClose(getDisplayChildren());
return TRUE;
}
}
if ( key == KEY_DOWN && mask == MASK_NONE)
if ((key == KEY_SUBTRACT || key == KEY_LEFT) && mask == MASK_NONE)
{
//if collapsed go to the next accordion
if(getDisplayChildren() == false)
//we processing notifyParent so let call parent directly
getParent()->notifyParent(LLSD().with("action","select_next"));
if (getDisplayChildren())
{
changeOpenClose(getDisplayChildren());
return TRUE;
}
}
if (key == KEY_DOWN && mask == MASK_NONE)
{
// if collapsed go to the next accordion
if (!getDisplayChildren())
{
// we're processing notifyParent so let call parent directly
getParent()->notifyParent(LLSD().with("action", "select_next"));
}
else
{
getAccordionView()->notify(LLSD().with("action","select_first"));
getAccordionView()->notify(LLSD().with("action", "select_first"));
}
return TRUE;
}
if ( key == KEY_UP && mask == MASK_NONE)
if (key == KEY_UP && mask == MASK_NONE)
{
//go to the previous accordion
// go to the previous accordion
//we processing notifyParent so let call parent directly
getParent()->notifyParent(LLSD().with("action","select_prev"));
// we're processing notifyParent so let call parent directly
getParent()->notifyParent(LLSD().with("action", "select_prev"));
return TRUE;
}
@ -869,28 +887,29 @@ void LLAccordionCtrlTab::showAndFocusHeader()
// accordion tab (assuming that the parent is an LLAccordionCtrl) the calls chain
// is shortened and messages from inside the collapsed tabs are avoided.
// See STORM-536.
getParent()->notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));
getParent()->notifyParent(LLSD().with("scrollToShowRect", screen_rc.getValue()));
}
void LLAccordionCtrlTab::storeOpenCloseState()
void LLAccordionCtrlTab::storeOpenCloseState()
{
if(mWasStateStored)
if (mWasStateStored)
return;
mStoredOpenCloseState = getDisplayChildren();
mWasStateStored = true;
}
void LLAccordionCtrlTab::restoreOpenCloseState()
void LLAccordionCtrlTab::restoreOpenCloseState()
{
if(!mWasStateStored)
if (!mWasStateStored)
return;
if(getDisplayChildren() != mStoredOpenCloseState)
if (getDisplayChildren() != mStoredOpenCloseState)
{
changeOpenClose(getDisplayChildren());
}
mWasStateStored = false;
}
void LLAccordionCtrlTab::adjustContainerPanel ()
void LLAccordionCtrlTab::adjustContainerPanel()
{
S32 width = getRect().getWidth();
S32 height = getRect().getHeight();
@ -907,83 +926,83 @@ void LLAccordionCtrlTab::adjustContainerPanel ()
void LLAccordionCtrlTab::adjustContainerPanel(const LLRect& child_rect)
{
if(!mContainerPanel)
if (!mContainerPanel)
return;
if(!mFitPanel)
if (!mFitPanel)
{
show_hide_scrollbar(child_rect);
updateLayout(child_rect);
}
else
{
mContainerPanel->reshape(child_rect.getWidth(),child_rect.getHeight());
mContainerPanel->reshape(child_rect.getWidth(), child_rect.getHeight());
mContainerPanel->setRect(child_rect);
}
}
S32 LLAccordionCtrlTab::getChildViewHeight()
{
if(!mContainerPanel)
if (!mContainerPanel)
return 0;
return mContainerPanel->getRect().getHeight();
}
void LLAccordionCtrlTab::show_hide_scrollbar(const LLRect& child_rect)
{
if(getChildViewHeight() > child_rect.getHeight() )
if (getChildViewHeight() > child_rect.getHeight())
showScrollbar(child_rect);
else
hideScrollbar(child_rect);
}
void LLAccordionCtrlTab::showScrollbar(const LLRect& child_rect)
{
if(!mContainerPanel || !mScrollbar)
if (!mContainerPanel || !mScrollbar)
return;
bool was_visible = mScrollbar->getVisible();
mScrollbar->setVisible(true);
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
{
ctrlSetLeftTopAndSize(mScrollbar,child_rect.getWidth()-scrollbar_size,
child_rect.getHeight()-PARENT_BORDER_MARGIN,
scrollbar_size,
child_rect.getHeight()-2*PARENT_BORDER_MARGIN);
}
ctrlSetLeftTopAndSize(mScrollbar,
child_rect.getWidth() - scrollbar_size,
child_rect.getHeight() - PARENT_BORDER_MARGIN,
scrollbar_size,
child_rect.getHeight() - PARENT_BORDER_MARGIN * 2);
LLRect orig_rect = mContainerPanel->getRect();
mScrollbar->setPageSize(child_rect.getHeight());
mScrollbar->setDocParams(orig_rect.getHeight(),mScrollbar->getDocPos());
mScrollbar->setDocParams(orig_rect.getHeight(), mScrollbar->getDocPos());
if(was_visible)
if (was_visible)
{
S32 scroll_pos = llmin(mScrollbar->getDocPos(), orig_rect.getHeight() - child_rect.getHeight() - 1);
mScrollbar->setDocPos(scroll_pos);
}
else//shrink child panel
else // Shrink child panel
{
updateLayout(child_rect);
}
}
void LLAccordionCtrlTab::hideScrollbar( const LLRect& child_rect )
void LLAccordionCtrlTab::hideScrollbar(const LLRect& child_rect)
{
if(!mContainerPanel || !mScrollbar)
if (!mContainerPanel || !mScrollbar)
return;
if(mScrollbar->getVisible() == false)
if (mScrollbar->getVisible() == FALSE)
return;
mScrollbar->setVisible(false);
mScrollbar->setVisible(FALSE);
mScrollbar->setDocPos(0);
//shrink child panel
updateLayout(child_rect);
}
void LLAccordionCtrlTab::onScrollPosChangeCallback(S32, LLScrollbar*)
void LLAccordionCtrlTab::onScrollPosChangeCallback(S32, LLScrollbar*)
{
LLRect child_rect;
@ -999,21 +1018,20 @@ void LLAccordionCtrlTab::onScrollPosChangeCallback(S32, LLScrollbar*)
updateLayout(child_rect);
}
void LLAccordionCtrlTab::drawChild(const LLRect& root_rect,LLView* child)
void LLAccordionCtrlTab::drawChild(const LLRect& root_rect, LLView* child)
{
if (child && child->getVisible() && child->getRect().isValid())
{
LLRect screen_rect;
localRectToScreen(child->getRect(),&screen_rect);
if ( root_rect.overlaps(screen_rect) && sDirtyRect.overlaps(screen_rect))
localRectToScreen(child->getRect(), &screen_rect);
if (root_rect.overlaps(screen_rect) && sDirtyRect.overlaps(screen_rect))
{
gGL.matrixMode(LLRender::MM_MODELVIEW);
LLUI::pushMatrix();
{
LLUI::translate((F32)child->getRect().mLeft, (F32)child->getRect().mBottom);
child->draw();
}
LLUI::popMatrix();
}
@ -1022,64 +1040,67 @@ void LLAccordionCtrlTab::drawChild(const LLRect& root_rect,LLView* child)
void LLAccordionCtrlTab::draw()
{
if(mFitPanel)
if (mFitPanel)
{
LLUICtrl::draw();
}
else
{
LLRect root_rect = getRootView()->getRect();
drawChild(root_rect,mHeader);
drawChild(root_rect,mScrollbar );
{
LLRect child_rect;
LLRect root_rect(getRootView()->getRect());
drawChild(root_rect, mHeader);
drawChild(root_rect, mScrollbar);
S32 width = getRect().getWidth();
S32 height = getRect().getHeight();
LLRect child_rect;
child_rect.setLeftTopAndSize(
getPaddingLeft(),
height - getHeaderHeight() - getPaddingTop(),
width - getPaddingLeft() - getPaddingRight(),
height - getHeaderHeight() - getPaddingTop() - getPaddingBottom() );
S32 width = getRect().getWidth();
S32 height = getRect().getHeight();
LLLocalClipRect clip(child_rect);
drawChild(root_rect,mContainerPanel);
}
child_rect.setLeftTopAndSize(
getPaddingLeft(),
height - getHeaderHeight() - getPaddingTop(),
width - getPaddingLeft() - getPaddingRight(),
height - getHeaderHeight() - getPaddingTop() - getPaddingBottom());
LLLocalClipRect clip(child_rect);
drawChild(root_rect,mContainerPanel);
}
}
void LLAccordionCtrlTab::updateLayout ( const LLRect& child_rect )
void LLAccordionCtrlTab::updateLayout(const LLRect& child_rect)
{
LLView* child = getAccordionView();
if(!mContainerPanel)
if (!mContainerPanel)
return;
S32 panel_top = child_rect.getHeight();
S32 panel_width = child_rect.getWidth();
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
if(mScrollbar && mScrollbar->getVisible() != false)
static LLUICachedControl<S32> scrollbar_size("UIScrollbarSize", 0);
if (mScrollbar && mScrollbar->getVisible())
{
panel_top+=mScrollbar->getDocPos();
panel_width-=scrollbar_size;
panel_top += mScrollbar->getDocPos();
panel_width -= scrollbar_size;
}
//set sizes for first panels and dragbars
// Set sizes for first panels and dragbars
LLRect panel_rect = child->getRect();
ctrlSetLeftTopAndSize(mContainerPanel,child_rect.mLeft,panel_top,panel_width,panel_rect.getHeight());
ctrlSetLeftTopAndSize(mContainerPanel, child_rect.mLeft, panel_top, panel_width, panel_rect.getHeight());
}
void LLAccordionCtrlTab::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height)
{
if(!panel)
if (!panel)
return;
LLRect panel_rect = panel->getRect();
panel_rect.setLeftTopAndSize( left, top, width, height);
panel_rect.setLeftTopAndSize(left, top, width, height);
panel->reshape( width, height, 1);
panel->setRect(panel_rect);
}
BOOL LLAccordionCtrlTab::handleToolTip(S32 x, S32 y, MASK mask)
{
//header may be not the first child but we need to process it first
if(y >= (getRect().getHeight() - HEADER_HEIGHT - HEADER_HEIGHT/2) )
if (y >= (getRect().getHeight() - HEADER_HEIGHT - HEADER_HEIGHT / 2))
{
//inside tab header
//fix for EXT-6619
@ -1088,16 +1109,18 @@ BOOL LLAccordionCtrlTab::handleToolTip(S32 x, S32 y, MASK mask)
}
return LLUICtrl::handleToolTip(x, y, mask);
}
BOOL LLAccordionCtrlTab::handleScrollWheel ( S32 x, S32 y, S32 clicks )
BOOL LLAccordionCtrlTab::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
if( LLUICtrl::handleScrollWheel(x,y,clicks))
if (LLUICtrl::handleScrollWheel(x, y, clicks))
{
return TRUE;
}
if( mScrollbar && mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) )
if (mScrollbar && mScrollbar->getVisible() && mScrollbar->handleScrollWheel(0, 0, clicks))
{
return TRUE;
}
return FALSE;
}

View File

@ -104,7 +104,7 @@ public:
virtual void setDisplayChildren(bool display);
// Returns expand/collapse state
virtual bool getDisplayChildren() const {return mDisplayChildren;};
virtual bool getDisplayChildren() const { return mDisplayChildren; };
//set LLAccordionCtrlTab panel
void setAccordionView(LLView* panel);

View File

@ -203,7 +203,8 @@ LLButton::LLButton(const LLButton::Params& p)
}
// Hack to make sure there is space for at least one character
if (getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(std::string(" ")))
if (getRect().mRight >= 0 && getRect().getWidth() > 0 &&
getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(std::string(" ")))
{
// Use old defaults
mLeftHPad = llbutton_orig_h_pad;

View File

@ -1198,7 +1198,7 @@ void LLFlatListView::onFocusReceived()
{
if (size())
{
mSelectedItemsBorder->setVisible(TRUE);
mSelectedItemsBorder->setVisible(TRUE);
}
gEditMenuHandler = this;
}
@ -1207,7 +1207,7 @@ void LLFlatListView::onFocusLost()
{
mSelectedItemsBorder->setVisible(FALSE);
// Route menu back to the default
if( gEditMenuHandler == this )
if (gEditMenuHandler == this)
{
gEditMenuHandler = NULL;
}
@ -1216,16 +1216,16 @@ void LLFlatListView::onFocusLost()
//virtual
S32 LLFlatListView::notify(const LLSD& info)
{
if(info.has("action"))
if (info.has("action"))
{
std::string str_action = info["action"];
if(str_action == "select_first")
if (str_action == "select_first")
{
setFocus(true);
selectFirstItem();
return 1;
}
else if(str_action == "select_last")
else if (str_action == "select_last")
{
setFocus(true);
selectLastItem();
@ -1238,6 +1238,7 @@ S32 LLFlatListView::notify(const LLSD& info)
notifyParentItemsRectChanged();
return 1;
}
return 0;
}
@ -1249,10 +1250,8 @@ void LLFlatListView::detachItems(std::vector<LLPanel*>& detached_items)
detached_items.clear();
// Go through items and detach valid items, remove them from items panel
// and add to detached_items.
for (pairs_iterator_t
iter = mItemPairs.begin(),
iter_end = mItemPairs.end();
iter != iter_end; ++iter)
pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end();
while (iter != iter_end)
{
LLPanel* pItem = (*iter)->first;
if (1 == pItem->notify(action))
@ -1261,6 +1260,7 @@ void LLFlatListView::detachItems(std::vector<LLPanel*>& detached_items)
mItemsPanel->removeChild(pItem);
detached_items.push_back(pItem);
}
iter++;
}
if (!detached_items.empty())
{
@ -1268,13 +1268,12 @@ void LLFlatListView::detachItems(std::vector<LLPanel*>& detached_items)
if (detached_items.size() == mItemPairs.size())
{
// This way will be faster if all items were disconnected
for (pairs_iterator_t
iter = mItemPairs.begin(),
iter_end = mItemPairs.end();
iter != iter_end; ++iter)
pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end();
while (iter != iter_end)
{
(*iter)->first = NULL;
delete *iter;
iter++;
}
mItemPairs.clear();
// Also set items panel height to zero.
@ -1287,16 +1286,14 @@ void LLFlatListView::detachItems(std::vector<LLPanel*>& detached_items)
}
else
{
for (std::vector<LLPanel*>::const_iterator
detached_iter = detached_items.begin(),
detached_iter_end = detached_items.end();
detached_iter != detached_iter_end; ++detached_iter)
std::vector<LLPanel*>::const_iterator
detached_iter = detached_items.begin(),
detached_iter_end = detached_items.end();
while (detached_iter < detached_iter_end)
{
LLPanel* pDetachedItem = *detached_iter;
for (pairs_iterator_t
iter = mItemPairs.begin(),
iter_end = mItemPairs.end();
iter != iter_end; ++iter)
pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end();
while (iter != iter_end)
{
item_pair_t* item_pair = *iter;
if (item_pair->first == pDetachedItem)
@ -1306,7 +1303,9 @@ void LLFlatListView::detachItems(std::vector<LLPanel*>& detached_items)
delete item_pair;
break;
}
iter++;
}
detached_iter++;
}
rearrangeItems();
}
@ -1322,7 +1321,6 @@ LLFlatListViewEx::Params::Params()
: no_items_msg("no_items_msg")
, no_filtered_items_msg("no_filtered_items_msg")
{
}
LLFlatListViewEx::LLFlatListViewEx(const Params& p)
@ -1332,7 +1330,6 @@ LLFlatListViewEx::LLFlatListViewEx(const Params& p)
, mForceShowingUnmatchedItems(false)
, mHasMatchedItems(false)
{
}
void LLFlatListViewEx::updateNoItemsMessage(const std::string& filter_string)
@ -1352,7 +1349,6 @@ void LLFlatListViewEx::updateNoItemsMessage(const std::string& filter_string)
// list does not contain any items at all
setNoItemsCommentText(mNoItemsMsg);
}
}
bool LLFlatListViewEx::getForceShowingUnmatchedItems()
@ -1411,12 +1407,10 @@ void LLFlatListViewEx::filterItems()
getItems(items);
mHasMatchedItems = false;
for (item_panel_list_t::iterator
iter = items.begin(),
iter_end = items.end();
iter != iter_end; ++iter)
item_panel_list_t::iterator iter = items.begin(), iter_end = items.end();
while (iter < iter_end)
{
LLPanel* pItem = (*iter);
LLPanel* pItem = *(iter++);
updateItemVisibility(pItem, action);
}

View File

@ -189,7 +189,9 @@ LLFolderView::LLFolderView(const Params& p)
mStatusTextBox(NULL),
mShowItemLinkOverlays(p.show_item_link_overlays),
mViewModel(p.view_model),
mGroupedItemModel(p.grouped_item_model)
mGroupedItemModel(p.grouped_item_model),
mForceArrange(false),
mSingleFolderMode(false)
{
LLPanel* panel = p.parent_panel;
mParentPanel = panel->getHandle();
@ -609,6 +611,7 @@ void LLFolderView::clearSelection()
}
mSelectedItems.clear();
mNeedsScroll = false;
}
std::set<LLFolderViewItem*> LLFolderView::getSelectionList() const
@ -665,7 +668,7 @@ void LLFolderView::draw()
}
else if (mShowEmptyMessage)
{
mStatusTextBox->setValue(getFolderViewModel()->getStatusText());
mStatusTextBox->setValue(getFolderViewModel()->getStatusText(mItems.empty() && mFolders.empty()));
mStatusTextBox->setVisible( TRUE );
// firstly reshape message textbox with current size. This is necessary to
@ -693,12 +696,16 @@ void LLFolderView::draw()
}
}
if (mRenameItem && mRenamer && mRenamer->getVisible() && !getVisibleRect().overlaps(mRenamer->getRect()))
{
// renamer is not connected to the item we are renaming in any form so manage it manually
// TODO: consider stopping on any scroll action instead of when out of visible area
finishRenamingItem();
}
if (mRenameItem
&& mRenamer
&& mRenamer->getVisible()
&& !getVisibleRect().overlaps(mRenamer->getRect()))
{
// renamer is not connected to the item we are renaming in any form so manage it manually
// TODO: consider stopping on any scroll action instead of when out of visible area
LL_DEBUGS("Inventory") << "Renamer out of bounds, hiding" << LL_ENDL;
finishRenamingItem();
}
// skip over LLFolderViewFolder::draw since we don't want the folder icon, label,
// and arrow for the root folder
@ -832,9 +839,12 @@ void LLFolderView::autoOpenItem( LLFolderViewFolder* item )
mAutoOpenItems.push(item);
item->setOpen(TRUE);
if(!item->isSingleFolderMode())
{
LLRect content_rect = (mScrollContainer ? mScrollContainer->getContentWindowRect() : LLRect());
LLRect constraint_rect(0,content_rect.getHeight(), content_rect.getWidth(), 0);
scrollToShowItem(item, constraint_rect);
}
}
void LLFolderView::closeAutoOpenedFolders()
@ -1038,6 +1048,8 @@ void LLFolderView::paste()
// public rename functionality - can only start the process
void LLFolderView::startRenamingSelectedItem( void )
{
LL_DEBUGS("Inventory") << "Starting inventory renamer" << LL_ENDL;
// make sure selection is visible
scrollToShowSelection();
@ -1273,6 +1285,11 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
if(mSelectedItems.size())
{
LLFolderViewItem* last_selected = getCurSelectedItem();
if(last_selected && last_selected->isSingleFolderMode())
{
handled = FALSE;
break;
}
LLFolderViewItem* parent_folder = last_selected->getParentFolder();
if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder())
{
@ -1458,9 +1475,19 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )
mCallbackRegistrar->popScope();
}
}
BOOL item_clicked = FALSE;
for (selected_items_t::iterator item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
{
item_clicked |= (*item_it)->getRect().pointInRect(x, y);
}
if(!item_clicked && mSingleFolderMode)
{
clearSelection();
}
bool hide_folder_menu = mSuppressFolderMenu && isFolderSelected();
if (menu && (handled
&& ( count > 0 && (hasVisibleChildren()) )) && // show menu only if selected items are visible
if (menu && (mSingleFolderMode || (handled
&& ( count > 0 && (hasVisibleChildren()) ))) && // show menu only if selected items are visible
!hide_folder_menu)
{
if (mCallbackRegistrar)
@ -1532,6 +1559,22 @@ BOOL LLFolderView::handleHover( S32 x, S32 y, MASK mask )
return LLView::handleHover( x, y, mask );
}
LLFolderViewItem* LLFolderView::getHoveredItem() const
{
return dynamic_cast<LLFolderViewItem*>(mHoveredItem.get());
}
void LLFolderView::setHoveredItem(LLFolderViewItem* itemp)
{
if (mHoveredItem.get() != itemp)
{
if (itemp)
mHoveredItem = itemp->getHandle();
else
mHoveredItem.markDead();
}
}
BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
@ -1716,7 +1759,7 @@ void LLFolderView::update()
mNeedsAutoSelect = FALSE;
}
BOOL is_visible = isInVisibleChain();
BOOL is_visible = isInVisibleChain() || mForceArrange;
//Puts folders/items in proper positions
// arrange() takes the model filter flag into account and call sort() if necessary (CHUI-849)
@ -1817,13 +1860,28 @@ void LLFolderView::update()
}
}
if (mSignalSelectCallback)
{
//RN: we use keyboard focus as a proxy for user-explicit actions
BOOL take_keyboard_focus = (mSignalSelectCallback == SIGNAL_KEYBOARD_FOCUS);
mSelectSignal(mSelectedItems, take_keyboard_focus);
}
mSignalSelectCallback = FALSE;
if (mSelectedItems.size())
{
LLFolderViewItem* item = mSelectedItems.back();
// If the goal is to show renamer, don't callback untill
// item is visible or is no longer being scrolled to.
// Otherwise renamer will be instantly closed
// Todo: consider moving renamer out of selection callback
if (!mNeedsAutoRename || !mNeedsScroll || item->getVisible())
{
if (mSignalSelectCallback)
{
//RN: we use keyboard focus as a proxy for user-explicit actions
BOOL take_keyboard_focus = (mSignalSelectCallback == SIGNAL_KEYBOARD_FOCUS);
mSelectSignal(mSelectedItems, take_keyboard_focus);
}
mSignalSelectCallback = FALSE;
}
}
else
{
mSignalSelectCallback = FALSE;
}
}
void LLFolderView::dumpSelectionInformation()
@ -1886,6 +1944,11 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu)
flags = multi_select_flag;
}
if(mSingleFolderMode && (mSelectedItems.size() == 0))
{
buildContextMenu(*menu, flags);
}
// This adds a check for restrictions based on the entire
// selection set - for example, any one wearable may not push you
// over the limit, but all wearables together still might.
@ -2042,7 +2105,7 @@ LLFolderViewItem* LLFolderView::getNextUnselectedItem()
return new_selection;
}
S32 LLFolderView::getItemHeight()
S32 LLFolderView::getItemHeight() const
{
if(!hasVisibleChildren())
{

View File

@ -127,6 +127,9 @@ public:
bool getAllowMultiSelect() { return mAllowMultiSelect; }
bool getAllowDrag() { return mAllowDrag; }
void setSingleFolderMode(bool is_single_mode) { mSingleFolderMode = is_single_mode; }
bool isSingleFolderMode() { return mSingleFolderMode; }
// Close all folders in the view
void closeAllFolders();
void openTopLevelFolders();
@ -136,7 +139,7 @@ public:
// Find width and height of this object and its children. Also
// makes sure that this view and its children are the right size.
virtual S32 arrange( S32* width, S32* height );
virtual S32 getItemHeight();
virtual S32 getItemHeight() const;
void arrangeAll() { mArrangeGeneration++; }
S32 getArrangeGeneration() { return mArrangeGeneration; }
@ -144,6 +147,10 @@ public:
// applies filters to control visibility of items
virtual void filter( LLFolderViewFilter& filter);
void clearHoveredItem() { setHoveredItem(nullptr); }
LLFolderViewItem* getHoveredItem() const;
void setHoveredItem(LLFolderViewItem* itemp);
// Get the last selected item
virtual LLFolderViewItem* getCurSelectedItem( void );
selected_items_t& getSelectedItems( void );
@ -210,6 +217,7 @@ public:
virtual void draw();
virtual void deleteAllChildren();
void stopAutoScollining() {mNeedsScroll = false;}
void scrollToShowSelection();
void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect);
void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; }
@ -237,11 +245,15 @@ public:
void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; }
void setEnableRegistrar(LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* registrar) { mEnableRegistrar = registrar; }
void setForceArrange(bool force) { mForceArrange = force; }
LLPanel* getParentPanel() { return mParentPanel.get(); }
// DEBUG only
void dumpSelectionInformation();
virtual S32 notify(const LLSD& info) ;
void setShowEmptyMessage(bool show_msg) { mShowEmptyMessage = show_msg; }
bool useLabelSuffix() { return mUseLabelSuffix; }
virtual void updateMenu();
@ -275,6 +287,7 @@ protected:
LLHandle<LLView> mPopupMenuHandle;
std::string mMenuFileName;
LLHandle<LLView> mHoveredItem;
selected_items_t mSelectedItems;
bool mKeyboardSelection,
mAllowMultiSelect,
@ -291,7 +304,8 @@ protected:
mShowItemLinkOverlays,
mShowSelectionContext,
mShowSingleSelection,
mSuppressFolderMenu;
mSuppressFolderMenu,
mSingleFolderMode;
// Renaming variables and methods
LLFolderViewItem* mRenameItem; // The item currently being renamed
@ -330,6 +344,8 @@ protected:
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar;
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* mEnableRegistrar;
bool mForceArrange;
public:
static F32 sAutoOpenTime;

View File

@ -32,6 +32,7 @@
#include "llfolderview.h"
#include "llfolderviewmodel.h"
#include "llpanel.h"
#include "llcallbacklist.h"
#include "llcriticaldamp.h"
#include "llclipboard.h"
#include "llfocusmgr.h" // gFocusMgr
@ -113,6 +114,8 @@ LLFolderViewItem::Params::Params()
icon_width("icon_width", 0),
text_pad("text_pad", 0),
text_pad_right("text_pad_right", 0),
single_folder_mode("single_folder_mode", false),
double_click_override("double_click_override", false),
arrow_size("arrow_size", 0),
max_folder_item_overlap("max_folder_item_overlap", 0)
{ }
@ -151,7 +154,9 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mTextPad(p.text_pad),
mTextPadRight(p.text_pad_right),
mArrowSize(p.arrow_size),
mMaxFolderItemOverlap(p.max_folder_item_overlap)
mSingleFolderMode(p.single_folder_mode),
mMaxFolderItemOverlap(p.max_folder_item_overlap),
mDoubleClickOverride(p.double_click_override)
{
if (!sColorSetInitialized)
{
@ -162,7 +167,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
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("InventoryItemColor", DEFAULT_WHITE);
sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE);
sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE);
sColorSetInitialized = true;
}
@ -396,7 +401,7 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height )
// it is purely visual, so it is fine to do at our laisure
refreshSuffix();
}
mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + mLabelPaddingRight;
mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(LLFontGL::NORMAL)->getWidth(mLabelSuffix) + mLabelPaddingRight;
mLabelWidthDirty = false;
}
@ -413,7 +418,7 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height )
return *height;
}
S32 LLFolderViewItem::getItemHeight()
S32 LLFolderViewItem::getItemHeight() const
{
return mItemHeight;
}
@ -625,11 +630,14 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask )
getWindow()->setCursor(UI_CURSOR_NOLOCKED);
}
root->clearHoveredItem();
return TRUE;
}
else
{
getRoot()->setShowSelectionContext(FALSE);
LLFolderView* pRoot = getRoot();
pRoot->setHoveredItem(this);
pRoot->setShowSelectionContext(FALSE);
getWindow()->setCursor(UI_CURSOR_ARROW);
// let parent handle this then...
return FALSE;
@ -684,6 +692,13 @@ BOOL LLFolderViewItem::handleMouseUp( S32 x, S32 y, MASK mask )
void LLFolderViewItem::onMouseLeave(S32 x, S32 y, MASK mask)
{
mIsMouseOverTitle = false;
// NOTE: LLViewerWindow::updateUI() calls "enter" before "leave"; if the mouse moved to another item, we can't just outright clear it
LLFolderView* pRoot = getRoot();
if (this == pRoot->getHoveredItem())
{
pRoot->clearHoveredItem();
}
}
BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
@ -890,7 +905,10 @@ void LLFolderViewItem::draw()
getViewModelItem()->update();
drawOpenFolderArrow(default_params, sFgColor);
if(!mSingleFolderMode)
{
drawOpenFolderArrow(default_params, sFgColor);
}
drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor);
@ -926,16 +944,43 @@ void LLFolderViewItem::draw()
F32 text_left = (F32)getLabelXPos();
std::string combined_string = mLabel + mLabelSuffix;
const LLFontGL* suffix_font = getLabelFontForStyle(LLFontGL::NORMAL);
S32 filter_offset = mViewModelItem->getFilterStringOffset();
if (filter_string_length > 0)
{
S32 left = ll_round(text_left) + font->getWidth(combined_string, 0, mViewModelItem->getFilterStringOffset()) - 2;
S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD);
S32 top = getRect().getHeight() - TOP_PAD;
if(mLabelSuffix.empty() || (font == suffix_font))
{
S32 left = ll_round(text_left) + font->getWidth(combined_string, 0, mViewModelItem->getFilterStringOffset()) - 2;
S32 right = left + font->getWidth(combined_string, mViewModelItem->getFilterStringOffset(), filter_string_length) + 2;
S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD);
S32 top = getRect().getHeight() - TOP_PAD;
LLUIImage* box_image = default_params.selection_image;
LLRect box_rect(left, top, right, bottom);
box_image->draw(box_rect, sFilterBGColor);
}
else
{
S32 label_filter_length = llmin((S32)mLabel.size() - filter_offset, (S32)filter_string_length);
if(label_filter_length > 0)
{
S32 left = ll_round(text_left) + font->getWidthF32(mLabel, 0, llmin(filter_offset, (S32)mLabel.size())) - 2;
S32 right = left + font->getWidthF32(mLabel, filter_offset, label_filter_length) + 2;
LLUIImage* box_image = default_params.selection_image;
LLRect box_rect(left, top, right, bottom);
box_image->draw(box_rect, sFilterBGColor);
}
S32 suffix_filter_length = label_filter_length > 0 ? filter_string_length - label_filter_length : filter_string_length;
if(suffix_filter_length > 0)
{
S32 suffix_offset = llmax(0, filter_offset - (S32)mLabel.size());
S32 left = ll_round(text_left) + font->getWidthF32(mLabel, 0, mLabel.size()) + suffix_font->getWidthF32(mLabelSuffix, 0, suffix_offset) - 2;
S32 right = left + suffix_font->getWidthF32(mLabelSuffix, suffix_offset, suffix_filter_length) + 2;
LLUIImage* box_image = default_params.selection_image;
LLRect box_rect(left, top, right, bottom);
box_image->draw(box_rect, sFilterBGColor);
}
}
}
LLColor4 color = (mIsSelected && filled) ? mFontHighlightColor : mFontColor;
@ -952,7 +997,7 @@ void LLFolderViewItem::draw()
//
if (!mLabelSuffix.empty())
{
font->renderUTF8( mLabelSuffix, 0, right_x, y, isFadeItem() ? color : (LLColor4)sSuffixColor,
suffix_font->renderUTF8( mLabelSuffix, 0, right_x, y, isFadeItem() ? color : (LLColor4)sSuffixColor,
LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
S32_MAX, S32_MAX, &right_x, FALSE );
}
@ -962,12 +1007,35 @@ void LLFolderViewItem::draw()
//
if (filter_string_length > 0)
{
S32 filter_offset = mViewModelItem->getFilterStringOffset();
F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, filter_offset + filter_string_length) - font->getWidthF32(combined_string, filter_offset, filter_string_length);
F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD;
font->renderUTF8( combined_string, filter_offset, match_string_left, yy,
if(mLabelSuffix.empty() || (font == suffix_font))
{
F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, filter_offset + filter_string_length) - font->getWidthF32(combined_string, filter_offset, filter_string_length);
F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD;
font->renderUTF8( combined_string, filter_offset, match_string_left, yy,
sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
filter_string_length, S32_MAX, &right_x, FALSE );
}
else
{
S32 label_filter_length = llmin((S32)mLabel.size() - filter_offset, (S32)filter_string_length);
if(label_filter_length > 0)
{
F32 match_string_left = text_left + font->getWidthF32(mLabel, 0, filter_offset + label_filter_length) - font->getWidthF32(mLabel, filter_offset, label_filter_length);
F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD;
font->renderUTF8( mLabel, filter_offset, match_string_left, yy,
sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, label_filter_length, S32_MAX, &right_x, FALSE );
}
S32 suffix_filter_length = label_filter_length > 0 ? filter_string_length - label_filter_length : filter_string_length;
if(suffix_filter_length > 0)
{
S32 suffix_offset = llmax(0, filter_offset - (S32)mLabel.size());
F32 match_string_left = text_left + font->getWidthF32(mLabel, 0, mLabel.size()) + suffix_font->getWidthF32(mLabelSuffix, 0, suffix_offset + suffix_filter_length) - suffix_font->getWidthF32(mLabelSuffix, suffix_offset, suffix_filter_length);
F32 yy = (F32)getRect().getHeight() - suffix_font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD;
suffix_font->renderUTF8( mLabelSuffix, suffix_offset, match_string_left, yy, sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, suffix_filter_length, S32_MAX, &right_x, FALSE );
}
}
}
//Gilbert Linden 9-20-2012: Although this should be legal, removing it because it causes the mLabelSuffix rendering to
@ -1278,7 +1346,7 @@ BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem
child_selected = TRUE;
}
}
if(openitem && child_selected)
if(openitem && child_selected && !mSingleFolderMode)
{
setOpenArrangeRecursively(TRUE);
}
@ -1703,6 +1771,11 @@ BOOL LLFolderViewFolder::isRemovable()
return TRUE;
}
void LLFolderViewFolder::destroyRoot()
{
delete this;
}
// this is an internal method used for adding items to folders.
void LLFolderViewFolder::addItem(LLFolderViewItem* item)
{
@ -1771,7 +1844,19 @@ void LLFolderViewFolder::toggleOpen()
// Force a folder open or closed
void LLFolderViewFolder::setOpen(BOOL openitem)
{
setOpenArrangeRecursively(openitem);
if(mSingleFolderMode)
{
// navigateToFolder can destroy this view
// delay it in case setOpen was called from click or key processing
doOnIdleOneTime([this]()
{
getViewModelItem()->navigateToFolder();
});
}
else
{
setOpenArrangeRecursively(openitem);
}
}
void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse)
@ -1974,7 +2059,8 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask )
}
if( !handled )
{
if(mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad)
if((mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad)
&& !mSingleFolderMode)
{
toggleOpen();
handled = TRUE;
@ -1992,12 +2078,45 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask )
BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask )
{
BOOL handled = FALSE;
if(mSingleFolderMode)
{
static LLUICachedControl<bool> double_click_new_window("SingleModeDoubleClickOpenWindow", false);
if (double_click_new_window)
{
getViewModelItem()->navigateToFolder(true);
}
else
{
// navigating is going to destroy views and change children
// delay it untill handleDoubleClick processing is complete
doOnIdleOneTime([this]()
{
getViewModelItem()->navigateToFolder(false);
});
}
return TRUE;
}
if( isOpen() )
{
handled = childrenHandleDoubleClick( x, y, mask ) != NULL;
}
if( !handled )
{
if(mDoubleClickOverride)
{
static LLUICachedControl<U32> double_click_action("MultiModeDoubleClickFolder", false);
if (double_click_action == 1)
{
getViewModelItem()->navigateToFolder(true);
return TRUE;
}
if (double_click_action == 2)
{
getViewModelItem()->navigateToFolder(false, true);
return TRUE;
}
}
if(mIndentation < x && x < mIndentation + (isCollapsed() ? 0 : mArrowSize) + mTextPad)
{
// don't select when user double-clicks plus sign

View File

@ -72,6 +72,8 @@ public:
text_pad_right,
arrow_size,
max_folder_item_overlap;
Optional<bool> single_folder_mode,
double_click_override;
Params();
};
@ -121,6 +123,8 @@ protected:
mIsMouseOverTitle,
mAllowWear,
mAllowDrop,
mSingleFolderMode,
mDoubleClickOverride,
mSelectPending,
mIsItemCut;
@ -174,7 +178,7 @@ public:
// Finds width and height of this object and it's children. Also
// makes sure that this view and it's children are the right size.
virtual S32 arrange( S32* width, S32* height );
virtual S32 getItemHeight();
virtual S32 getItemHeight() const;
virtual S32 getLabelXPos();
S32 getIconPad();
S32 getTextPad();
@ -213,9 +217,9 @@ public:
void setIsCurSelection(BOOL select) { mIsCurSelection = select; }
BOOL getIsCurSelection() { return mIsCurSelection; }
BOOL getIsCurSelection() const { return mIsCurSelection; }
BOOL hasVisibleChildren() { return mHasVisibleChildren; }
BOOL hasVisibleChildren() const { return mHasVisibleChildren; }
// true if object can't have children
virtual bool isFolderComplete() { return true; }
@ -264,7 +268,7 @@ public:
virtual LLFolderView* getRoot();
virtual const LLFolderView* getRoot() const;
BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor );
S32 getIndentation() { return mIndentation; }
S32 getIndentation() const { return mIndentation; }
virtual BOOL passedFilter(S32 filter_generation = -1);
virtual BOOL isPotentiallyVisible(S32 filter_generation = -1);
@ -277,6 +281,8 @@ public:
// Does not need filter update
virtual void refreshSuffix();
bool isSingleFolderMode() { return mSingleFolderMode; }
// LLView functionality
virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
@ -387,6 +393,7 @@ public:
// destroys this folder, and all children
virtual void destroyView();
void destroyRoot();
// whether known children are fully loaded (arrange sets to true)
virtual bool isFolderComplete() { return mIsFolderComplete; }

View File

@ -34,7 +34,7 @@ bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item)
return item->getSortVersion() < mTargetSortVersion;
}
std::string LLFolderViewModelCommon::getStatusText()
std::string LLFolderViewModelCommon::getStatusText(bool is_empty_folder)
{
if (!contentsReady() || mFolderView->getViewModelItem()->getLastFilterGeneration() < getFilter().getCurrentGeneration())
{
@ -42,7 +42,7 @@ std::string LLFolderViewModelCommon::getStatusText()
}
else
{
return getFilter().getEmptyLookupMessage();
return getFilter().getEmptyLookupMessage(is_empty_folder);
}
}

View File

@ -69,7 +69,7 @@ public:
virtual bool checkFolder(const LLFolderViewModelItem* folder) const = 0;
virtual void setEmptyLookupMessage(const std::string& message) = 0;
virtual std::string getEmptyLookupMessage() const = 0;
virtual std::string getEmptyLookupMessage(bool is_empty_folder = false) const = 0;
virtual bool showAllResults() const = 0;
@ -125,7 +125,7 @@ public:
virtual void setFolderView(LLFolderView* folder_view) = 0;
virtual LLFolderViewFilter& getFilter() = 0;
virtual const LLFolderViewFilter& getFilter() const = 0;
virtual std::string getStatusText() = 0;
virtual std::string getStatusText(bool is_empty_folder = false) = 0;
virtual bool startDrag(std::vector<LLFolderViewModelItem*>& items) = 0;
};
@ -159,6 +159,8 @@ public:
virtual void openItem( void ) = 0;
virtual void closeItem( void ) = 0;
virtual void selectItem(void) = 0;
virtual void navigateToFolder(bool new_window = false, bool change_mode = false) = 0;
virtual BOOL isItemWearable() const { return FALSE; }
@ -392,7 +394,7 @@ public:
// sort everything
mTargetSortVersion++;
}
virtual std::string getStatusText();
virtual std::string getStatusText(bool is_empty_folder = false);
virtual void filter();
void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;}

View File

@ -39,7 +39,9 @@ class LLUICtrlFactory;
// Classes
//
//
// Class for diplaying named UI textures
// Do not use for displaying textures from network,
// UI textures are stored permanently!
class LLIconCtrl
: public LLUICtrl
{

View File

@ -216,7 +216,8 @@ LLLayoutStack::Params::Params()
drag_handle_first_indent("drag_handle_first_indent", 0),
drag_handle_second_indent("drag_handle_second_indent", 0),
drag_handle_thickness("drag_handle_thickness", 5),
drag_handle_shift("drag_handle_shift", 2)
drag_handle_shift("drag_handle_shift", 2),
drag_handle_color("drag_handle_color", LLUIColorTable::instance().getColor("ResizebarBody"))
{
addSynonym(border_size, "drag_handle_gap");
}
@ -236,7 +237,8 @@ LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)
mDragHandleFirstIndent(p.drag_handle_first_indent),
mDragHandleSecondIndent(p.drag_handle_second_indent),
mDragHandleThickness(p.drag_handle_thickness),
mDragHandleShift(p.drag_handle_shift)
mDragHandleShift(p.drag_handle_shift),
mDragHandleColor(p.drag_handle_color())
{
}
@ -523,6 +525,15 @@ void LLLayoutStack::updateLayout()
mNeedsLayout = continue_animating;
} // end LLLayoutStack::updateLayout
void LLLayoutStack::setPanelSpacing(S32 val)
{
if (mPanelSpacing != val)
{
mPanelSpacing = val;
mNeedsLayout = true;
}
}
LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const
{
if (!panelp) return NULL;
@ -576,7 +587,7 @@ void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp)
resize_bar_bg_panel_p.follows.flags = FOLLOWS_ALL;
resize_bar_bg_panel_p.tab_stop = false;
resize_bar_bg_panel_p.background_visible = true;
resize_bar_bg_panel_p.bg_alpha_color = LLUIColorTable::instance().getColor("ResizebarBody");
resize_bar_bg_panel_p.bg_alpha_color = mDragHandleColor;
resize_bar_bg_panel_p.has_border = true;
resize_bar_bg_panel_p.border.border_thickness = 1;
resize_bar_bg_panel_p.border.highlight_light_color = LLUIColorTable::instance().getColor("ResizebarBorderLight");

View File

@ -59,6 +59,8 @@ public:
Optional<S32> drag_handle_thickness;
Optional<S32> drag_handle_shift;
Optional<LLUIColor> drag_handle_color;
Params();
};
@ -89,6 +91,7 @@ public:
void updateLayout();
S32 getPanelSpacing() const { return mPanelSpacing; }
void setPanelSpacing(S32 val);
static void updateClass();
@ -128,6 +131,7 @@ private:
S32 mDragHandleSecondIndent;
S32 mDragHandleThickness;
S32 mDragHandleShift;
LLUIColor mDragHandleColor;
}; // end class LLLayoutStack

View File

@ -573,13 +573,13 @@ void LLMenuItemGL::onVisibilityChange(BOOL new_visibility)
//
// This class represents a separator.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LLMenuItemSeparatorGL::Params::Params()
{
}
LLMenuItemSeparatorGL::LLMenuItemSeparatorGL(const LLMenuItemSeparatorGL::Params& p) :
LLMenuItemGL( p )
{
if (p.on_visible.isProvided())
{
mVisibleSignal.connect(initEnableCallback(p.on_visible));
}
}
//virtual
@ -596,6 +596,15 @@ void LLMenuItemSeparatorGL::draw( void )
gl_line_2d( PAD, y, getRect().getWidth() - PAD, y );
}
void LLMenuItemSeparatorGL::buildDrawLabel( void )
{
if (mVisibleSignal.num_slots() > 0)
{
bool visible = mVisibleSignal(this, LLSD());
setVisible(visible);
}
}
BOOL LLMenuItemSeparatorGL::handleMouseDown(S32 x, S32 y, MASK mask)
{
LLMenuGL* parent_menu = getMenu();

View File

@ -234,7 +234,9 @@ class LLMenuItemSeparatorGL : public LLMenuItemGL
public:
struct Params : public LLInitParam::Block<Params, LLMenuItemGL::Params>
{
Params();
Optional<EnableCallbackParam > on_visible;
Params() : on_visible("on_visible")
{}
};
LLMenuItemSeparatorGL(const LLMenuItemSeparatorGL::Params& p = LLMenuItemSeparatorGL::Params());
@ -243,7 +245,12 @@ public:
/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
virtual void buildDrawLabel();
/*virtual*/ U32 getNominalHeight( void ) const;
private:
enable_signal_t mVisibleSignal;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -188,12 +188,12 @@ void LLScrollbar::setPageSize( S32 page_size )
}
}
BOOL LLScrollbar::isAtBeginning()
bool LLScrollbar::isAtBeginning() const
{
return mDocPos == 0;
}
BOOL LLScrollbar::isAtEnd()
bool LLScrollbar::isAtEnd() const
{
return mDocPos == getDocPosMax();
}
@ -591,7 +591,12 @@ void LLScrollbar::setValue(const LLSD& value)
BOOL LLScrollbar::handleKeyHere(KEY key, MASK mask)
{
BOOL handled = FALSE;
if (getDocPosMax() == 0 && !getVisible())
{
return FALSE;
}
BOOL handled = FALSE;
switch( key )
{

View File

@ -105,8 +105,8 @@ public:
bool setDocPos( S32 pos, BOOL update_thumb = TRUE );
S32 getDocPos() const { return mDocPos; }
BOOL isAtBeginning();
BOOL isAtEnd();
bool isAtBeginning() const;
bool isAtEnd() const;
// Setting both at once.
void setDocParams( S32 size, S32 pos );

View File

@ -105,8 +105,8 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p)
mBorder = LLUICtrlFactory::create<LLViewBorder> (params);
LLView::addChild( mBorder );
mInnerRect.set( 0, getRect().getHeight(), getRect().getWidth(), 0 );
mInnerRect.stretch( -getBorderWidth() );
mInnerRect = getLocalRect();
mInnerRect.stretch( -getBorderWidth() );
LLRect vertical_scroll_rect = mInnerRect;
vertical_scroll_rect.mLeft = vertical_scroll_rect.mRight - scrollbar_size;
@ -124,8 +124,9 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p)
mScrollbar[VERTICAL] = LLUICtrlFactory::create<LLScrollbar> (sbparams);
LLView::addChild( mScrollbar[VERTICAL] );
LLRect horizontal_scroll_rect = mInnerRect;
horizontal_scroll_rect.mTop = horizontal_scroll_rect.mBottom + scrollbar_size;
LLRect horizontal_scroll_rect;
horizontal_scroll_rect.mTop = scrollbar_size;
horizontal_scroll_rect.mRight = mInnerRect.getWidth();
sbparams.name("scrollable horizontal");
sbparams.rect(horizontal_scroll_rect);
sbparams.orientation(LLScrollbar::HORIZONTAL);
@ -134,7 +135,7 @@ LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p)
sbparams.page_size(mInnerRect.getWidth());
sbparams.step_size(VERTICAL_MULTIPLE);
sbparams.visible(false);
sbparams.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT);
sbparams.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
sbparams.change_callback(p.scroll_callback);
mScrollbar[HORIZONTAL] = LLUICtrlFactory::create<LLScrollbar> (sbparams);
LLView::addChild( mScrollbar[HORIZONTAL] );

View File

@ -98,8 +98,10 @@ public:
void pageDown(S32 overlap = 0);
void goToTop();
void goToBottom();
bool isAtTop() { return mScrollbar[VERTICAL]->isAtBeginning(); }
bool isAtBottom() { return mScrollbar[VERTICAL]->isAtEnd(); }
bool isAtTop() const { return mScrollbar[VERTICAL]->isAtBeginning(); }
bool isAtBottom() const { return mScrollbar[VERTICAL]->isAtEnd(); }
S32 getDocPosVertical() const { return mScrollbar[VERTICAL]->getDocPos(); }
S32 getDocPosHorizontal() const { return mScrollbar[HORIZONTAL]->getDocPos(); }
S32 getBorderWidth() const;
// LLView functionality

View File

@ -605,6 +605,7 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
LLButton* tab_button = getTab(index)->mButton;
gFocusMgr.setMouseCapture(this);
tab_button->setFocus(TRUE);
mMouseDownTimer.start();
}
}
if (handled) {
@ -653,7 +654,11 @@ BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask )
handled = LLPanel::handleHover(x, y, mask);
}
commitHoveredButton(x, y);
F32 drag_delay = 0.25f; // filter out clicks from dragging
if (mMouseDownTimer.getElapsedTimeF32() > drag_delay)
{
commitHoveredButton(x, y);
}
return handled;
}
@ -699,6 +704,7 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
}
commitHoveredButton(x, y);
mMouseDownTimer.stop();
LLPanel* cur_panel = getCurrentPanel();
if (hasMouseCapture())
{
@ -1002,7 +1008,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
}
else
{
//Scip tab button space if they are invisible(EXT - 576)
// Skip tab button space if tabs are invisible (EXT-576)
tab_panel_top = getRect().getHeight();
tab_panel_bottom = LLPANEL_BORDER_WIDTH;
}
@ -1017,9 +1023,9 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
}
else
{
tab_panel_rect = LLRect(LLPANEL_BORDER_WIDTH,
tab_panel_rect = LLRect(LLPANEL_BORDER_WIDTH * 3,
tab_panel_top,
getRect().getWidth()-LLPANEL_BORDER_WIDTH,
getRect().getWidth() - LLPANEL_BORDER_WIDTH * 2,
tab_panel_bottom );
}
child->setFollowsAll();
@ -1106,7 +1112,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
p.follows.flags = p.follows.flags() | FOLLOWS_TOP;
}
else
{
{
p.name("htab_"+std::string(child->getName()));
p.visible(false);
p.image_unselected(tab_img);

View File

@ -320,6 +320,7 @@ private:
LLUIColor mTabsFlashingColor;
S32 mTabIconCtrlPad;
bool mUseTabEllipses;
LLFrameTimer mMouseDownTimer;
};
#endif // LL_TABCONTAINER_H

View File

@ -163,6 +163,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p)
: LLPanel(p),
mHasClickCallback(p.click_callback.isProvided()),
mPadding(p.padding),
mMaxWidth(p.max_width),
mTextBox(NULL),
mInfoButton(NULL),
mPlayMediaButton(NULL),
@ -272,7 +273,7 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p)
// do this *after* we've had our size set in LLPanel::initFromParams();
const S32 REALLY_LARGE_HEIGHT = 10000;
mTextBox->reshape(p.max_width, REALLY_LARGE_HEIGHT);
mTextBox->reshape(mMaxWidth, REALLY_LARGE_HEIGHT);
if (p.styled_message.isProvided())
{
@ -288,16 +289,19 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p)
mTextBox->setText(p.message());
}
S32 text_width = llmin(p.max_width(), mTextBox->getTextPixelWidth() + 1);
updateTextBox();
snapToChildren();
}
void LLToolTip::updateTextBox()
{
S32 text_width = llmin(mMaxWidth, mTextBox->getTextPixelWidth() + 1);
S32 text_height = mTextBox->getTextPixelHeight();
mTextBox->reshape(text_width, text_height);
if (mInfoButton)
{
LLRect text_rect = mTextBox->getRect();
LLRect icon_rect = mInfoButton->getRect();
mTextBox->translate(0, icon_rect.getCenterY() - text_rect.getCenterY());
}
}
void LLToolTip::snapToChildren()
{
// reshape tooltip panel to fit text box
LLRect tooltip_rect = calcBoundingRect();
tooltip_rect.mTop += mPadding;
@ -305,7 +309,14 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p)
tooltip_rect.mBottom = 0;
tooltip_rect.mLeft = 0;
mTextBox->reshape(mTextBox->getRect().getWidth(), llmax(mTextBox->getRect().getHeight(), tooltip_rect.getHeight() - 2 * mPadding));
if (mInfoButton)
{
mTextBox->reshape(mTextBox->getRect().getWidth(), llmax(mTextBox->getRect().getHeight(), tooltip_rect.getHeight() - 2 * mPadding));
LLRect text_rect = mTextBox->getRect();
LLRect icon_rect = mInfoButton->getRect();
mInfoButton->translate(0, text_rect.getCenterY() - icon_rect.getCenterY());
}
setShape(tooltip_rect);
}
@ -428,7 +439,10 @@ void LLToolTipMgr::createToolTip(const LLToolTip::Params& params)
}
tooltip_params.rect = LLRect (0, 1, 1, 0);
mToolTip = LLUICtrlFactory::create<LLToolTip> (tooltip_params);
if (tooltip_params.create_callback.isProvided())
mToolTip = tooltip_params.create_callback()(tooltip_params);
else
mToolTip = LLUICtrlFactory::create<LLToolTip> (tooltip_params);
gToolTipView->addChild(mToolTip);

View File

@ -68,6 +68,7 @@ public:
struct Params : public LLInitParam::Block<Params, LLPanel::Params>
{
typedef boost::function<void(void)> click_callback_t;
typedef boost::function<LLToolTip*(LLToolTip::Params)> create_callback_t;
Optional<std::string> message;
Multiple<StyledText> styled_message;
@ -84,6 +85,8 @@ public:
Optional<bool> time_based_media,
web_based_media,
media_playing;
Optional<create_callback_t> create_callback;
Optional<LLSD> create_params;
Optional<click_callback_t> click_callback,
click_playmedia_callback,
click_homepage_callback;
@ -103,11 +106,15 @@ public:
bool hasClickCallback();
LLToolTip(const Params& p);
void initFromParams(const LLToolTip::Params& params);
virtual void initFromParams(const LLToolTip::Params& params);
void getToolTipMessage(std::string & message);
private:
protected:
void updateTextBox();
void snapToChildren();
protected:
class LLTextBox* mTextBox;
class LLButton* mInfoButton;
class LLButton* mPlayMediaButton;
@ -117,6 +124,7 @@ private:
LLFrameTimer mVisibleTimer;
bool mHasClickCallback;
S32 mPadding; // pixels
S32 mMaxWidth;
};
// used for the inspector tooltips which need different background images etc.

View File

@ -531,6 +531,15 @@ void LLUICtrl::setControlVariable(LLControlVariable* control)
}
}
void LLUICtrl::removeControlVariable()
{
if (mControlVariable)
{
mControlConnection.disconnect();
mControlVariable = NULL;
}
}
//virtual
void LLUICtrl::setControlName(const std::string& control_name, LLView *context)
{

View File

@ -175,6 +175,7 @@ public:
bool setControlValue(const LLSD& value);
void setControlVariable(LLControlVariable* control);
virtual void setControlName(const std::string& control, LLView *context = NULL);
void removeControlVariable();
LLControlVariable* getControlVariable() { return mControlVariable; }

View File

@ -311,7 +311,13 @@ bool LLView::addChild(LLView* child, S32 tab_group)
}
child->mParentView = this;
updateBoundingRect();
if (getVisible() && child->getVisible())
{
// if child isn't visible it won't affect bounding rect
// if current view is not visible it will be recalculated
// on visibility change
updateBoundingRect();
}
mLastTabGroup = tab_group;
return true;
}
@ -581,6 +587,7 @@ void LLView::deleteAllChildren()
delete viewp;
mChildList.pop_front();
}
updateBoundingRect();
}
void LLView::setAllChildrenEnabled(BOOL b)
@ -879,6 +886,17 @@ LLView* LLView::childFromPoint(S32 x, S32 y, bool recur)
return 0;
}
F32 LLView::getTooltipTimeout()
{
static LLCachedControl<F32> tooltip_fast_delay(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipFastDelay", 0.1f);
static LLCachedControl<F32> tooltip_delay(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipDelay", 0.7f);
// allow "scrubbing" over ui by showing next tooltip immediately
// if previous one was still visible
return (F32)(LLToolTipMgr::instance().toolTipVisible()
? tooltip_fast_delay
: tooltip_delay);
}
BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
@ -888,14 +906,7 @@ BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
std::string tooltip = getToolTip();
if (!tooltip.empty())
{
static LLCachedControl<F32> tooltip_fast_delay(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipFastDelay", 0.1f);
static LLCachedControl<F32> tooltip_delay(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipDelay", 0.7f);
static LLCachedControl<bool> allow_ui_tooltips(*LLUI::getInstance()->mSettingGroups["config"], "BasicUITooltips", true);
// allow "scrubbing" over ui by showing next tooltip immediately
// if previous one was still visible
F32 timeout = LLToolTipMgr::instance().toolTipVisible()
? tooltip_fast_delay
: tooltip_delay;
// Even if we don't show tooltips, consume the event, nothing below should show tooltip
if (allow_ui_tooltips)
@ -903,7 +914,7 @@ BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
LLToolTipMgr::instance().show(LLToolTip::Params()
.message(tooltip)
.sticky_rect(calcScreenRect())
.delay_time(timeout));
.delay_time(getTooltipTimeout()));
}
handled = TRUE;
}

View File

@ -243,6 +243,7 @@ public:
ECursorType getHoverCursor() { return mHoverCursor; }
static F32 getTooltipTimeout();
virtual const std::string getToolTip() const { return mToolTipMsg.getString(); }
void sendChildToFront(LLView* child);

View File

@ -195,6 +195,7 @@ set(viewer_SOURCE_FILES
llfloaterbuyland.cpp
llfloatercamera.cpp
llfloatercamerapresets.cpp
llfloaterchangeitemthumbnail.cpp
llfloaterchatvoicevolume.cpp
llfloaterclassified.cpp
llfloatercolorpicker.cpp
@ -231,6 +232,7 @@ set(viewer_SOURCE_FILES
llfloaterimsession.cpp
llfloaterimcontainer.cpp
llfloaterinspect.cpp
llfloaterinventorysettings.cpp
llfloaterjoystick.cpp
llfloaterlagmeter.cpp
llfloaterland.cpp
@ -249,10 +251,9 @@ set(viewer_SOURCE_FILES
llfloaternewfeaturenotification.cpp
llfloaternotificationsconsole.cpp
llfloaternotificationstabbed.cpp
llfloateroutfitphotopreview.cpp
llfloaterobjectweights.cpp
llfloateropenobject.cpp
llfloatersimpleoutfitsnapshot.cpp
llfloatersimplesnapshot.cpp
llfloaterpathfindingcharacters.cpp
llfloaterpathfindingconsole.cpp
llfloaterpathfindinglinksets.cpp
@ -267,7 +268,6 @@ set(viewer_SOURCE_FILES
llfloaterpreferenceviewadvanced.cpp
llfloaterpreviewtrash.cpp
llfloaterprofiletexture.cpp
llfloaterproperties.cpp
llfloaterregiondebugconsole.cpp
llfloaterregioninfo.cpp
llfloaterreporter.cpp
@ -339,10 +339,13 @@ set(viewer_SOURCE_FILES
llinspectgroup.cpp
llinspectobject.cpp
llinspectremoteobject.cpp
llinspecttexture.cpp
llinspecttoast.cpp
llinventorybridge.cpp
llinventoryfilter.cpp
llinventoryfunctions.cpp
llinventorygallery.cpp
llinventorygallerymenu.cpp
llinventoryicon.cpp
llinventoryitemslist.cpp
llinventorylistitem.cpp
@ -573,6 +576,7 @@ set(viewer_SOURCE_FILES
lltextureinfodetails.cpp
lltexturestats.cpp
lltextureview.cpp
llthumbnailctrl.cpp
lltinygltfhelper.cpp
lltoast.cpp
lltoastalertpanel.cpp
@ -842,6 +846,7 @@ set(viewer_HEADER_FILES
llfloaterbuycurrencyhtml.h
llfloaterbuyland.h
llfloatercamerapresets.h
llfloaterchangeitemthumbnail.h
llfloatercamera.h
llfloaterchatvoicevolume.h
llfloaterclassified.h
@ -882,6 +887,7 @@ set(viewer_HEADER_FILES
llfloaterimsession.h
llfloaterimcontainer.h
llfloaterinspect.h
llfloaterinventorysettings.h
llfloaterjoystick.h
llfloaterlagmeter.h
llfloaterland.h
@ -900,10 +906,9 @@ set(viewer_HEADER_FILES
llfloaternewfeaturenotification.h
llfloaternotificationsconsole.h
llfloaternotificationstabbed.h
llfloateroutfitphotopreview.h
llfloaterobjectweights.h
llfloateropenobject.h
llfloatersimpleoutfitsnapshot.h
llfloatersimplesnapshot.h
llfloaterpathfindingcharacters.h
llfloaterpathfindingconsole.h
llfloaterpathfindinglinksets.h
@ -918,7 +923,6 @@ set(viewer_HEADER_FILES
llfloaterpreferenceviewadvanced.h
llfloaterpreviewtrash.h
llfloaterprofiletexture.h
llfloaterproperties.h
llfloaterregiondebugconsole.h
llfloaterregioninfo.h
llfloaterreporter.h
@ -988,10 +992,13 @@ set(viewer_HEADER_FILES
llinspectgroup.h
llinspectobject.h
llinspectremoteobject.h
llinspecttexture.h
llinspecttoast.h
llinventorybridge.h
llinventoryfilter.h
llinventoryfunctions.h
llinventorygallery.h
llinventorygallerymenu.h
llinventoryicon.h
llinventoryitemslist.h
llinventorylistitem.h
@ -1213,6 +1220,7 @@ set(viewer_HEADER_FILES
lltextureinfodetails.h
lltexturestats.h
lltextureview.h
llthumbnailctrl.h
lltinygltfhelper.h
lltoast.h
lltoastalertpanel.h

View File

@ -274,6 +274,7 @@ INVENTORY_NOTECARD Passed to task inventory library functions to reference notec
INVENTORY_BODYPART Passed to task inventory library functions to reference body parts
INVENTORY_ANIMATION Passed to task inventory library functions to reference animations
INVENTORY_GESTURE Passed to task inventory library functions to reference gestures
INVENTORY_MATERIAL Passed to task inventory library functions to reference materials
INVENTORY_ALL Passed to task inventory library functions to reference all inventory items
INVENTORY_NONE Returned by llGetInventoryType when no item is found

View File

@ -1963,6 +1963,15 @@
<key>tooltip</key>
<string/>
</map>
<key>INVENTORY_MATERIAL</key>
<map>
<key>type</key>
<string>integer</string>
<key>value</key>
<integer>57</integer>
<key>tooltip</key>
<string/>
</map>
<key>JSON_APPEND</key>
<map>
<key>type</key>

View File

@ -5012,17 +5012,6 @@
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>InventoryInboxToggleState</key>
<map>
<key>Comment</key>
<string>Stores the open/closed state of inventory Received items panel</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>InventoryLinking</key>
<map>
@ -9057,16 +9046,16 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderLocalLights</key>
<key>RenderLocalLightCount</key>
<map>
<key>Comment</key>
<string>Whether or not to render local lights.</string>
<string>Number of local lights to render.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<string>S32</string>
<key>Value</key>
<integer>1</integer>
<integer>256</integer>
</map>
<key>RenderShadowSplitExponent</key>
<map>
@ -12999,39 +12988,6 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>AmbientDisable</key>
<map>
<key>Comment</key>
<string>If TRUE, ambient light has no effect</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>SunlightDisable</key>
<map>
<key>Comment</key>
<string>If TRUE, sunlight has no effect</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LocalLightDisable</key>
<map>
<key>Comment</key>
<string>If TRUE, local lights have no effect</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>TextureDiscardLevel</key>
<map>
<key>Comment</key>
@ -15691,6 +15647,17 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>BatchSizeAIS3</key>
<map>
<key>Comment</key>
<string>Amount of folder ais packs into category subset request</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>20</integer>
</map>
<key>PoolSizeAIS</key>
<map>
<key>Comment</key>
@ -15698,7 +15665,7 @@
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>1</integer>
<integer>20</integer>
</map>
<key>PoolSizeUpload</key>
<map>
@ -17482,6 +17449,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>FindOriginalOpenWindow</key>
<map>
<key>Comment</key>
<string>Sets the action for 'Find original' and 'Show in Inventory' (0 - shows item in main Inventory, 1 - opens a new single-folder window)</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>
@ -17515,5 +17493,27 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>MultiModeDoubleClickFolder</key>
<map>
<key>Comment</key>
<string>Sets the action for Double-click on folder in multi-folder view (0 - expands and collapses folder, 1 - opens a new window, 2 stays in current floater but switches to SFV)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>SingleModeDoubleClickOpenWindow</key>
<map>
<key>Comment</key>
<string>Sets the action for Double-click on folder in single-folder view (0 - stays in current window, 1 - opens a new window)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
</llsd>

View File

@ -382,8 +382,7 @@ vec3 pbrIbl(vec3 diffuseColor,
vec3 irradiance, // irradiance map sample
float ao, // ambient occlusion factor
float nv, // normal dot view vector
float perceptualRough,
out vec3 specContrib)
float perceptualRough)
{
// retrieve a scale and bias to F0. See [1], Figure 3
vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0-perceptualRough);
@ -393,23 +392,9 @@ vec3 pbrIbl(vec3 diffuseColor,
vec3 diffuse = diffuseLight * diffuseColor;
vec3 specular = specularLight * (specularColor * brdf.x + brdf.y);
specContrib = specular * ao;
return (diffuse + specular) * ao;
}
vec3 pbrIbl(vec3 diffuseColor,
vec3 specularColor,
vec3 radiance, // radiance map sample
vec3 irradiance, // irradiance map sample
float ao, // ambient occlusion factor
float nv, // normal dot view vector
float perceptualRough)
{
vec3 specContrib;
return pbrIbl(diffuseColor, specularColor, radiance, irradiance, ao, nv, perceptualRough, specContrib);
}
// Encapsulate the various inputs used by the various functions in the shading equation
// We store values in this struct to simplify the integration of alternative implementations
@ -475,8 +460,7 @@ vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
vec3 l, //surface point to light
out vec3 specContrib) //specular contribution (exposed to alpha shaders to calculate "glare")
vec3 l) //surface point to light
{
// make sure specular highlights from punctual lights don't fall off of polished surfaces
perceptualRoughness = max(perceptualRoughness, 8.0/255.0);
@ -524,28 +508,13 @@ vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
// Calculation of analytical lighting contribution
vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs);
specContrib = F * G * D / (4.0 * NdotL * NdotV);
vec3 specContrib = F * G * D / (4.0 * NdotL * NdotV);
// Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)
vec3 color = NdotL * (diffuseContrib + specContrib);
specContrib *= NdotL;
specContrib = max(specContrib, vec3(0));
return clamp(color, vec3(0), vec3(10));
}
vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
vec3 l) //surface point to light
{
vec3 specContrib;
return pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n, v, l, specContrib);
}
void calcDiffuseSpecular(vec3 baseColor, float metallic, inout vec3 diffuseColor, inout vec3 specularColor)
{
vec3 f0 = vec3(0.04);
@ -554,30 +523,21 @@ void calcDiffuseSpecular(vec3 baseColor, float metallic, inout vec3 diffuseColor
specularColor = mix(f0, baseColor, metallic);
}
vec3 pbrBaseLight(vec3 diffuseColor, vec3 specularColor, float metallic, vec3 v, vec3 norm, float perceptualRoughness, vec3 light_dir, vec3 sunlit, float scol, vec3 radiance, vec3 irradiance, vec3 colorEmissive, float ao, vec3 additive, vec3 atten, out vec3 specContrib)
vec3 pbrBaseLight(vec3 diffuseColor, vec3 specularColor, float metallic, vec3 v, vec3 norm, float perceptualRoughness, vec3 light_dir, vec3 sunlit, float scol, vec3 radiance, vec3 irradiance, vec3 colorEmissive, float ao, vec3 additive, vec3 atten)
{
vec3 color = vec3(0);
float NdotV = clamp(abs(dot(norm, v)), 0.001, 1.0);
vec3 ibl_spec;
color += pbrIbl(diffuseColor, specularColor, radiance, irradiance, ao, NdotV, perceptualRoughness, ibl_spec);
color += pbrIbl(diffuseColor, specularColor, radiance, irradiance, ao, NdotV, perceptualRoughness);
color += pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, norm, v, normalize(light_dir), specContrib) * sunlit * 3.0 * scol; //magic number to balance with legacy materials
specContrib *= sunlit * 2.75 * scol;
specContrib += ibl_spec;
color += pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, norm, v, normalize(light_dir)) * sunlit * 3.0 * scol; //magic number to balance with legacy materials
color += colorEmissive;
return color;
}
vec3 pbrBaseLight(vec3 diffuseColor, vec3 specularColor, float metallic, vec3 v, vec3 norm, float perceptualRoughness, vec3 light_dir, vec3 sunlit, float scol, vec3 radiance, vec3 irradiance, vec3 colorEmissive, float ao, vec3 additive, vec3 atten)
{
vec3 specContrib;
return pbrBaseLight(diffuseColor, specularColor, metallic, v, norm, perceptualRoughness, light_dir, sunlit, scol, radiance, irradiance, colorEmissive, ao, additive, atten, specContrib);
}
uniform vec4 waterPlane;
uniform float waterSign;

View File

@ -40,8 +40,6 @@ vec4 applyWaterFogView(vec3 pos, vec4 color);
#endif
vec3 srgb_to_linear(vec3 cs);
vec3 legacy_adjust_fullbright(vec3 c);
vec3 legacy_adjust(vec3 c);
vec3 linear_to_srgb(vec3 cl);
vec3 atmosFragLighting(vec3 light, vec3 additive, vec3 atten);
void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten);
@ -98,9 +96,7 @@ void main()
#endif
#ifndef IS_HUD
color.rgb = legacy_adjust(color.rgb);
color.rgb = srgb_to_linear(color.rgb);
color.rgb = legacy_adjust_fullbright(color.rgb);
color.rgb = atmosFragLighting(color.rgb, additive, atten);
#endif

View File

@ -113,31 +113,3 @@ vec3 inv_toneMapACES_Hill(vec3 color)
return color;
}
// adjust legacy colors to back out tonemapping and exposure
// NOTE: obsolete now that setting probe ambiance to zero removes tonemapping and exposure, but keeping for a minute
// while that change goes through testing - davep 6/1/2023
#define LEGACY_ADJUST 0
vec3 legacy_adjust(vec3 c)
{
#if LEGACY_ADJUST
vec3 desat = rgb2hsv(c.rgb);
desat.g *= 1.0-(1.0-desat.b)*0.5;
desat.b += (1.0-desat.b)*0.1f;
desat.rgb = hsv2rgb(desat);
return desat;
#else
return c;
#endif
}
vec3 legacy_adjust_fullbright(vec3 c)
{
#if LEGACY_ADJUST
float exp_scale = clamp(texture(exposureMap, vec2(0.5, 0.5)).r, 0.01, 10.0);
return c / exp_scale * 1.34; //magic 1.34 arrived at by binary search for a value that reproduces midpoint grey consistenty
#else
return c;
#endif
}

View File

@ -45,7 +45,6 @@ uniform float sky_ambient_scale;
float getAmbientClamp() { return 1.0f; }
vec3 srgb_to_linear(vec3 col);
vec3 legacy_adjust(vec3 col);
// return colors in sRGB space
void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive,

View File

@ -71,7 +71,6 @@ vec4 applyWaterFogViewLinear(vec3 pos, vec4 color, vec3 sunlit);
vec3 srgb_to_linear(vec3 c);
vec3 linear_to_srgb(vec3 c);
vec3 legacy_adjust(vec3 c);
vec2 encode_normal (vec3 n);
vec3 atmosFragLightingLinear(vec3 light, vec3 additive, vec3 atten);
@ -234,7 +233,6 @@ void main()
}
diffuse_srgb.rgb *= vertex_color.rgb;
diffuse_srgb.rgb = legacy_adjust(diffuse_srgb.rgb);
diffuse_linear.rgb = srgb_to_linear(diffuse_srgb.rgb);
#endif // USE_VERTEX_COLOR
@ -291,9 +289,7 @@ void main()
LIGHT_LOOP(7)
// sum local light contrib in linear colorspace
#if !defined(LOCAL_LIGHT_KILL)
color.rgb += light.rgb;
#endif // !defined(LOCAL_LIGHT_KILL)
#endif // #else // FOR_IMPOSTOR

View File

@ -112,16 +112,14 @@ vec3 pbrBaseLight(vec3 diffuseColor,
vec3 colorEmissive,
float ao,
vec3 additive,
vec3 atten,
out vec3 specContrib);
vec3 atten);
vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
vec3 l, //surface point to light
out vec3 specContrib);
vec3 l); //surface point to light
vec3 calcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
float perceptualRoughness,
@ -132,7 +130,7 @@ vec3 calcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
vec3 lp, // light position
vec3 ld, // light direction (for spotlights)
vec3 lightColor,
float lightSize, float falloff, float is_pointlight, inout float glare, float ambiance)
float lightSize, float falloff, float is_pointlight, float ambiance)
{
vec3 color = vec3(0,0,0);
@ -154,10 +152,7 @@ vec3 calcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
vec3 intensity = spot_atten * dist_atten * lightColor * 3.0; //magic number to balance with legacy materials
vec3 speccol;
color = intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, lv, speccol);
speccol *= intensity;
glare += max(max(speccol.r, speccol.g), speccol.b);
color = intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, lv);
}
return color;
@ -166,7 +161,6 @@ vec3 calcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
void main()
{
vec3 color = vec3(0,0,0);
float glare = 0.0;
vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
vec3 pos = vary_position;
@ -232,9 +226,7 @@ void main()
vec3 v = -normalize(pos.xyz);
vec3 spec;
color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten, spec);
glare += max(max(spec.r, spec.g), spec.b);
color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten);
color.rgb = atmosFragLightingLinear(color.rgb, additive, atten);
@ -246,7 +238,7 @@ void main()
vec3 light = vec3(0);
// Punctual lights
#define LIGHT_LOOP(i) light += calcPointLightOrSpotLight(diffuseColor, specularColor, perceptualRoughness, metallic, norm.xyz, pos.xyz, v, light_position[i].xyz, light_direction[i].xyz, light_diffuse[i].rgb, light_deferred_attenuation[i].x, light_deferred_attenuation[i].y, light_attenuation[i].z, glare, light_attenuation[i].w);
#define LIGHT_LOOP(i) light += calcPointLightOrSpotLight(diffuseColor, specularColor, perceptualRoughness, metallic, norm.xyz, pos.xyz, v, light_position[i].xyz, light_direction[i].xyz, light_diffuse[i].rgb, light_deferred_attenuation[i].x, light_deferred_attenuation[i].y, light_attenuation[i].z, light_attenuation[i].w);
LIGHT_LOOP(1)
LIGHT_LOOP(2)
@ -261,9 +253,6 @@ void main()
float a = basecolor.a*vertex_color.a;
glare = min(glare, 1.0);
a = max(a, glare);
frag_color = max(vec4(color.rgb,a), vec4(0));
}

View File

@ -40,8 +40,6 @@ in vec3 vary_position;
uniform samplerCube environmentMap;
vec3 atmosFragLighting(vec3 light, vec3 additive, vec3 atten);
vec3 legacy_adjust_fullbright(vec3 c);
vec3 legacy_adjust(vec3 c);
void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten);
vec3 linear_to_srgb(vec3 c);
@ -82,10 +80,8 @@ void main()
vec4 spec = vec4(0,0,0,0);
sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, vec2(0), pos.xyz, norm.xyz, spec.a, env_intensity, false, amblit);
color.rgb = legacy_adjust(color.rgb);
color.rgb = srgb_to_linear(color.rgb);
color.rgb = legacy_adjust_fullbright(color.rgb);
applyLegacyEnv(color.rgb, legacyenv, spec, pos, norm, env_intensity);
color.rgb = atmosFragLighting(color.rgb, additive, atten);
#endif

View File

@ -48,8 +48,6 @@ void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float
vec3 srgb_to_linear(vec3 cs);
vec3 linear_to_srgb(vec3 cs);
vec3 legacy_adjust(vec3 c);
vec3 legacy_adjust_fullbright(vec3 c);
uniform vec4 clipPlane;
uniform float clipSign;
@ -329,7 +327,6 @@ void main()
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
//forward rendering, output lit linear color
diffcol.rgb = legacy_adjust(diffcol.rgb);
diffcol.rgb = srgb_to_linear(diffcol.rgb);
spec.rgb = srgb_to_linear(spec.rgb);
spec.a = glossiness; // pack glossiness into spec alpha for lighting functions
@ -395,7 +392,7 @@ void main()
applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz);
}
color = mix(color.rgb, legacy_adjust_fullbright(diffcol.rgb), emissive);
color = mix(color.rgb, diffcol.rgb, emissive);
if (env > 0.0)
{ // add environmentmap

View File

@ -52,7 +52,6 @@ vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensi
vec2 getScreenXY(vec4 clip);
vec2 getScreenCoord(vec4 clip);
vec3 srgb_to_linear(vec3 c);
vec3 legacy_adjust(vec3 c);
// Util
vec3 hue_to_rgb(float hue);
@ -67,9 +66,6 @@ vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
void main()
{
#if defined(LOCAL_LIGHT_KILL)
discard; // Bail immediately
#else
vec3 final_color = vec3(0, 0, 0);
vec2 tc = getScreenCoord(vary_fragcoord);
vec3 pos = getPosition(tc).xyz;
@ -118,7 +114,7 @@ void main()
float dist_atten = calcLegacyDistanceAttenuation(dist, falloff);
vec3 intensity = dist_atten * lightColor * 3.9;
vec3 intensity = dist_atten * lightColor * 3.25;
final_color += intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, lv);
}
@ -126,7 +122,6 @@ void main()
}
else
{
diffuse.rgb = legacy_adjust(diffuse.rgb);
diffuse = srgb_to_linear(diffuse);
spec.rgb = srgb_to_linear(spec.rgb);
@ -174,7 +169,6 @@ void main()
frag_color.rgb = max(final_color, vec3(0));
frag_color.a = 0.0;
#endif // LOCAL_LIGHT_KILL
#ifdef IS_AMD_CARD
// If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage

View File

@ -1,263 +0,0 @@
/**
* @file class3\deferred\multiSpotLightF.glsl
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, 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$
*/
/*[EXTRA_CODE_HERE]*/
out vec4 frag_color;
uniform sampler2D diffuseRect;
uniform sampler2D specularRect;
uniform sampler2D depthMap;
uniform sampler2D normalMap;
uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
uniform samplerCube environmentMap;
uniform sampler2D lightMap;
uniform sampler2D projectionMap; // rgba
uniform sampler2D lightFunc;
uniform mat4 proj_mat; //screen space to light space
uniform float proj_near; //near clip for projection
uniform vec3 proj_p; //plane projection is emitting from (in screen space)
uniform vec3 proj_n;
uniform float proj_focus; //distance from plane to begin blurring
uniform float proj_lod; //(number of mips in proj map)
uniform float proj_range; //range between near clip and far clip plane of projection
uniform float proj_ambient_lod;
uniform float proj_ambiance;
uniform float near_clip;
uniform float far_clip;
uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
uniform float sun_wash;
uniform int proj_shadow_idx;
uniform float shadow_fade;
// Light params
uniform vec3 center;
uniform float size;
uniform vec3 color;
uniform float falloff;
in vec4 vary_fragcoord;
uniform vec2 screen_res;
uniform mat4 inv_proj;
void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
float calcLegacyDistanceAttenuation(float distance, float falloff);
vec3 colorized_dot(float x);
bool clipProjectedLightVars(vec3 center, vec3 pos, out float dist, out float l_dist, out vec3 lv, out vec4 proj_tc );
vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
vec3 getProjectedLightAmbiance(float amb_da, float attenuation, float lit, float nl, float noise, vec2 projected_uv);
vec3 getProjectedLightDiffuseColor(float light_distance, vec2 projected_uv );
vec3 getProjectedLightSpecularColor(vec3 pos, vec3 n);
vec2 getScreenXY(vec4 clip);
vec2 getScreenCoord(vec4 clip);
vec3 srgb_to_linear(vec3 cs);
vec3 legacy_adjust(vec3 c);
vec4 texture2DLodSpecular(vec2 tc, float lod);
vec4 getPosition(vec2 pos_screen);
const float M_PI = 3.14159265;
vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
float perceptualRoughness,
float metallic,
vec3 n, // normal
vec3 v, // surface point to camera
vec3 l); //surface point to light
void main()
{
#if defined(LOCAL_LIGHT_KILL)
discard;
#else
vec3 final_color = vec3(0,0,0);
vec2 tc = getScreenCoord(vary_fragcoord);
vec3 pos = getPosition(tc).xyz;
vec3 lv;
vec4 proj_tc;
float dist, l_dist;
if (clipProjectedLightVars(center, pos, dist, l_dist, lv, proj_tc))
{
discard;
}
float shadow = 1.0;
if (proj_shadow_idx >= 0)
{
vec4 shd = texture(lightMap, tc);
shadow = (proj_shadow_idx==0)?shd.b:shd.a;
shadow += shadow_fade;
shadow = clamp(shadow, 0.0, 1.0);
}
float envIntensity;
vec3 n;
vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity);
float dist_atten = calcLegacyDistanceAttenuation(dist, falloff);
if (dist_atten <= 0.0)
{
discard;
}
lv = proj_origin-pos.xyz;
vec3 h, l, v = -normalize(pos);
float nh, nl, nv, vh, lightDist;
calcHalfVectors(lv, n, v, h, l, nh, nl, nv, vh, lightDist);
vec3 diffuse = texture(diffuseRect, tc).rgb;
vec4 spec = texture(specularRect, tc);
vec3 dlit = vec3(0, 0, 0);
vec3 slit = vec3(0, 0, 0);
vec3 amb_rgb = vec3(0);
if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
{
vec3 colorEmissive = texture(emissiveRect, tc).rgb;
vec3 orm = spec.rgb;
float perceptualRoughness = orm.g;
float metallic = orm.b;
vec3 f0 = vec3(0.04);
vec3 baseColor = diffuse.rgb;
vec3 diffuseColor = baseColor.rgb*(vec3(1.0)-f0);
diffuseColor *= 1.0 - metallic;
vec3 specularColor = mix(f0, baseColor.rgb, metallic);
// We need this additional test inside a light's frustum since a spotlight's ambiance can be applied
if (proj_tc.x > 0.0 && proj_tc.x < 1.0
&& proj_tc.y > 0.0 && proj_tc.y < 1.0)
{
float lit = 0.0;
float amb_da = 0.0;
if (nl > 0.0)
{
amb_da += (nl*0.5 + 0.5) * proj_ambiance;
dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy );
vec3 intensity = dist_atten * dlit * 3.9 * shadow; // Legacy attenuation, magic number to balance with legacy materials
final_color += intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, normalize(lv));
}
amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, 1.0, proj_tc.xy );
final_color += diffuse.rgb * amb_rgb;
}
}
else
{
diffuse = legacy_adjust(diffuse);
diffuse = srgb_to_linear(diffuse);
spec.rgb = srgb_to_linear(spec.rgb);
if (proj_tc.z > 0.0 &&
proj_tc.x < 1.0 &&
proj_tc.y < 1.0 &&
proj_tc.x > 0.0 &&
proj_tc.y > 0.0)
{
float amb_da = 0;
float lit = 0.0;
if (nl > 0.0)
{
lit = nl * dist_atten;
dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy );
final_color = dlit*lit*diffuse*shadow;
// unshadowed for consistency between forward and deferred?
amb_da += (nl*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance;
}
amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, 1.0, proj_tc.xy );
final_color += diffuse.rgb * amb_rgb;
}
if (spec.a > 0.0)
{
dlit *= min(nl*6.0, 1.0) * dist_atten;
float fres = pow(1 - vh, 5)*0.4+0.5;
float gtdenom = 2 * nh;
float gt = max(0, min(gtdenom * nv / vh, gtdenom * nl / vh));
if (nh > 0.0)
{
float scol = fres*texture(lightFunc, vec2(nh, spec.a)).r*gt/(nh*nl);
vec3 speccol = dlit*scol*spec.rgb*shadow;
speccol = clamp(speccol, vec3(0), vec3(1));
final_color += speccol;
}
}
if (envIntensity > 0.0)
{
vec3 ref = reflect(normalize(pos), n);
//project from point pos in direction ref to plane proj_p, proj_n
vec3 pdelta = proj_p-pos;
float ds = dot(ref, proj_n);
if (ds < 0.0)
{
vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
if (stc.z > 0.0)
{
stc /= stc.w;
if (stc.x < 1.0 &&
stc.y < 1.0 &&
stc.x > 0.0 &&
stc.y > 0.0)
{
final_color += color.rgb * texture2DLodSpecular(stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity;
}
}
}
}
}
//not sure why, but this line prevents MATBUG-194
final_color = max(final_color, vec3(0.0));
//output linear
frag_color.rgb = final_color;
frag_color.a = 0.0;
#endif // LOCAL_LIGHT_KILL
}

View File

@ -57,7 +57,6 @@ vec4 getPosition(vec2 pos_screen);
vec2 getScreenXY(vec4 clip);
vec2 getScreenCoord(vec4 clip);
vec3 srgb_to_linear(vec3 c);
vec3 legacy_adjust(vec3 c);
float getDepth(vec2 tc);
vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
@ -107,7 +106,7 @@ void main()
vec3 specularColor = mix(f0, baseColor.rgb, metallic);
vec3 intensity = dist_atten * color * 3.9; // Legacy attenuation, magic number to balance with legacy materials
vec3 intensity = dist_atten * color * 3.25; // Legacy attenuation, magic number to balance with legacy materials
final_color += intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, normalize(lv));
}
else
@ -116,7 +115,6 @@ void main()
{
discard;
}
diffuse = legacy_adjust(diffuse);
diffuse = srgb_to_linear(diffuse);
spec.rgb = srgb_to_linear(spec.rgb);

View File

@ -86,7 +86,6 @@ float getDepth(vec2 pos_screen);
vec3 linear_to_srgb(vec3 c);
vec3 srgb_to_linear(vec3 c);
vec3 legacy_adjust(vec3 c);
uniform vec4 waterPlane;
@ -234,8 +233,6 @@ void main()
else
{
// legacy shaders are still writng sRGB to gbuffer
baseColor.rgb = legacy_adjust(baseColor.rgb);
baseColor.rgb = srgb_to_linear(baseColor.rgb);
spec.rgb = srgb_to_linear(spec.rgb);

View File

@ -25,16 +25,6 @@
/*[EXTRA_CODE_HERE]*/
#define DEBUG_ANY_LIGHT_TYPE 0 // Output green light cone
#define DEBUG_LEG_LIGHT_TYPE 0 // Show Legacy objects in green
#define DEBUG_PBR_LIGHT_TYPE 0 // Show PBR objects in green
#define DEBUG_PBR_SPOT 0
#define DEBUG_PBR_SPOT_DIFFUSE 0
#define DEBUG_PBR_SPOT_SPECULAR 0
#define DEBUG_SPOT_NL 0 // monochome area effected by light
#define DEBUG_SPOT_ZERO 0 // Output zero for spotlight
out vec4 frag_color;
uniform sampler2D diffuseRect;
@ -64,11 +54,16 @@ uniform float sun_wash;
uniform int proj_shadow_idx;
uniform float shadow_fade;
// Light params
#if defined(MULTI_SPOTLIGHT)
uniform vec3 center;
#else
in vec3 trans_center;
#endif
uniform float size;
uniform vec3 color;
uniform float falloff;
in vec3 trans_center;
in vec4 vary_fragcoord;
uniform vec2 screen_res;
@ -80,11 +75,8 @@ bool clipProjectedLightVars(vec3 center, vec3 pos, out float dist, out float l_d
vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
vec3 getProjectedLightAmbiance(float amb_da, float attenuation, float lit, float nl, float noise, vec2 projected_uv);
vec3 getProjectedLightDiffuseColor(float light_distance, vec2 projected_uv );
vec3 getProjectedLightSpecularColor(vec3 pos, vec3 n);
vec2 getScreenXY(vec4 clip_point);
vec2 getScreenCoord(vec4 clip_point);
vec3 srgb_to_linear(vec3 c);
vec3 legacy_adjust(vec3 c);
vec2 getScreenCoord(vec4 clip);
vec3 srgb_to_linear(vec3 cs);
vec4 texture2DLodSpecular(vec2 tc, float lod);
vec4 getPosition(vec2 pos_screen);
@ -100,9 +92,6 @@ vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
void main()
{
#if defined(LOCAL_LIGHT_KILL)
discard;
#else
vec3 final_color = vec3(0,0,0);
vec2 tc = getScreenCoord(vary_fragcoord);
vec3 pos = getPosition(tc).xyz;
@ -110,24 +99,31 @@ void main()
vec3 lv;
vec4 proj_tc;
float dist, l_dist;
if (clipProjectedLightVars(trans_center, pos, dist, l_dist, lv, proj_tc))
vec3 c;
#if defined(MULTI_SPOTLIGHT)
c = center;
#else
c = trans_center;
#endif
if (clipProjectedLightVars(c, pos, dist, l_dist, lv, proj_tc))
{
discard;
}
float shadow = 1.0;
if (proj_shadow_idx >= 0)
{
vec4 shd = texture(lightMap, tc);
shadow = (proj_shadow_idx == 0) ? shd.b : shd.a;
shadow = (proj_shadow_idx==0)?shd.b:shd.a;
shadow += shadow_fade;
shadow = clamp(shadow, 0.0, 1.0);
shadow = clamp(shadow, 0.0, 1.0);
}
float envIntensity;
vec3 n;
vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG()
vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity);
float dist_atten = calcLegacyDistanceAttenuation(dist, falloff);
if (dist_atten <= 0.0)
@ -135,7 +131,7 @@ void main()
discard;
}
lv = proj_origin-pos.xyz; // NOTE: Re-using lv
lv = proj_origin-pos.xyz;
vec3 h, l, v = -normalize(pos);
float nh, nl, nv, vh, lightDist;
calcHalfVectors(lv, n, v, h, l, nh, nl, nv, vh, lightDist);
@ -146,10 +142,11 @@ void main()
vec3 slit = vec3(0, 0, 0);
vec3 amb_rgb = vec3(0);
if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
{
vec3 colorEmissive = texture(emissiveRect, tc).rgb;
vec3 orm = spec.rgb;
vec3 colorEmissive = texture(emissiveRect, tc).rgb;
vec3 orm = spec.rgb;
float perceptualRoughness = orm.g;
float metallic = orm.b;
vec3 f0 = vec3(0.04);
@ -167,33 +164,34 @@ void main()
float lit = 0.0;
float amb_da = 0.0;
lv = normalize(lv);
if (nl > 0.0)
{
amb_da += (nl*0.5 + 0.5) * proj_ambiance;
dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy );
vec3 intensity = dist_atten * dlit * 3.9 * shadow; // Legacy attenuation
final_color += intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, normalize(lv));
vec3 intensity = dist_atten * dlit * 3.25 * shadow; // Legacy attenuation, magic number to balance with legacy materials
final_color += intensity*pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, lv);
}
amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, 1.0, proj_tc.xy );
final_color += diffuse.rgb * amb_rgb;
amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, 1.0, proj_tc.xy ) * 3.25; //magic number to balance with legacy ambiance
final_color += amb_rgb * pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, n.xyz, v, -lv);
}
}
else
{
diffuse = legacy_adjust(diffuse);
diffuse = srgb_to_linear(diffuse);
spec.rgb = srgb_to_linear(spec.rgb);
if (proj_tc.z > 0.0 &&
proj_tc.x < 1.0 &&
proj_tc.y < 1.0 &&
proj_tc.x > 0.0 &&
proj_tc.y > 0.0)
{
float amb_da = proj_ambiance;
float amb_da = 0;
float lit = 0.0;
if (nl > 0.0)
@ -204,24 +202,23 @@ void main()
final_color = dlit*lit*diffuse*shadow;
// unshadowed for consistency between forward and deferred?
amb_da += (nl*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance;
}
vec3 amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, 1.0, proj_tc.xy );
final_color += diffuse.rgb*amb_rgb;
#if DEBUG_LEG_LIGHT_TYPE
final_color = vec3(0,0.5,0);
#endif
amb_rgb = getProjectedLightAmbiance( amb_da, dist_atten, lit, nl, 1.0, proj_tc.xy );
final_color += diffuse.rgb * amb_rgb * max(dot(-normalize(lv), n), 0.0);
}
if (spec.a > 0.0)
{
dlit *= min(nl*6.0, 1.0) * dist_atten;
float fres = pow(1 - dot(h, v), 5)*0.4+0.5;
float fres = pow(1 - vh, 5)*0.4+0.5;
float gtdenom = 2 * nh;
float gt = max(0, min(gtdenom * nv / vh, gtdenom * nl / vh));
if (nh > 0.0)
{
float scol = fres*texture(lightFunc, vec2(nh, spec.a)).r*gt/(nh*nl);
@ -229,26 +226,26 @@ void main()
speccol = clamp(speccol, vec3(0), vec3(1));
final_color += speccol;
}
}
}
if (envIntensity > 0.0)
{
vec3 ref = reflect(normalize(pos), n);
//project from point pos in direction ref to plane proj_p, proj_n
vec3 pdelta = proj_p-pos;
float ds = dot(ref, proj_n);
if (ds < 0.0)
{
vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
if (stc.z > 0.0)
{
stc /= stc.w;
if (stc.x < 1.0 &&
stc.y < 1.0 &&
stc.x > 0.0 &&
@ -261,24 +258,10 @@ void main()
}
}
#if DEBUG_PBR_SPOT_DIFFUSE
final_color = vec3(nl * dist_atten);
#endif
#if DEBUG_SPOT_NL
final_color = vec3(nl);
#endif
#if DEBUG_SPOT_ZERO
final_color = vec3(0,0,0);
#endif
#if DEBUG_ANY_LIGHT_TYPE
final_color = vec3(0,0.3333,0);
#endif
//not sure why, but this line prevents MATBUG-194
final_color = max(final_color, vec3(0.0));
//output linear colors as gamma correction happens down stream
//output linear
frag_color.rgb = final_color;
frag_color.a = 0.0;
#endif // LOCAL_LIGHT_KILL
}

View File

@ -1,4 +1,4 @@
version 58
version 59
// The version number above should be incremented IF AND ONLY IF some
// change has been made that is sufficiently important to justify
// resetting the graphics preferences of all users to the recommended
@ -42,7 +42,7 @@ RenderGamma 1 0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 8192
RenderObjectBump 1 1
RenderLocalLights 1 1
RenderLocalLightCount 1 4096
RenderTransparentWater 1 1
RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 2
@ -87,10 +87,10 @@ RenderAvatarMaxComplexity 1 35000
RenderFarClip 1 64
RenderFlexTimeFactor 1 0
RenderGlowResolutionPow 1 8
RenderLocalLights 1 0
RenderLocalLightCount 1 8
RenderMaxPartCount 1 0
RenderTransparentWater 1 0
RenderReflectionsEnabled 1 0
RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 0
RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
@ -117,7 +117,7 @@ RenderFarClip 1 96
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 8
RenderMaxPartCount 1 2048
RenderLocalLights 1 1
RenderLocalLightCount 1 256
RenderTransparentWater 1 0
RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 0
@ -146,7 +146,7 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
RenderLocalLights 1 1
RenderLocalLightCount 1 512
RenderTransparentWater 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
@ -175,7 +175,7 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
RenderLocalLights 1 1
RenderLocalLightCount 1 1024
RenderTransparentWater 1 1
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
@ -204,7 +204,7 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
RenderLocalLights 1 1
RenderLocalLightCount 1 2048
RenderTransparentWater 1 1
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
@ -233,7 +233,7 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
RenderLocalLights 1 1
RenderLocalLightCount 1 4096
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
@ -260,7 +260,7 @@ RenderAvatarPhysicsLODFactor 1 1.0
RenderFarClip 1 256
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderLocalLights 1 1
RenderLocalLightCount 1 8192
RenderMaxPartCount 1 8192
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
@ -299,7 +299,7 @@ list safe
RenderAnisotropic 1 0
RenderAvatarMaxNonImpostors 1 16
RenderAvatarMaxComplexity 1 80000
RenderLocalLights 1 0
RenderLocalLightCount 1 0
RenderMaxPartCount 1 1024
RenderTerrainDetail 1 0
RenderTransparentWater 1 0

View File

@ -1,4 +1,4 @@
version 53
version 54
// The version number above should be incremented IF AND ONLY IF some
// change has been made that is sufficiently important to justify
// resetting the graphics preferences of all users to the recommended
@ -42,7 +42,7 @@ RenderGamma 1 0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 8192
RenderObjectBump 1 1
RenderLocalLights 1 1
RenderLocalLightCount 1 4096
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
@ -85,7 +85,7 @@ RenderAvatarMaxComplexity 1 35000
RenderFarClip 1 64
RenderFlexTimeFactor 1 0
RenderGlowResolutionPow 1 8
RenderLocalLights 1 0
RenderLocalLightCount 1 8
RenderMaxPartCount 1 0
RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
@ -97,7 +97,7 @@ RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
WLSkyDetail 1 96
RenderFSAASamples 1 0
RenderReflectionsEnabled 1 0
RenderReflectionsEnabled 1 1
RenderReflectionProbeDetail 1 0
RenderScreenSpaceReflections 1 0
RenderReflectionProbeLevel 1 0
@ -115,7 +115,7 @@ RenderFarClip 1 96
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 8
RenderMaxPartCount 1 2048
RenderLocalLights 1 1
RenderLocalLightCount 1 256
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 1.0
RenderTransparentWater 1 1
@ -144,7 +144,7 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
RenderLocalLights 1 1
RenderLocalLightCount 1 512
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
@ -173,7 +173,7 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
RenderLocalLights 1 1
RenderLocalLightCount 1 1024
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
@ -202,7 +202,7 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
RenderLocalLights 1 1
RenderLocalLightCount 1 2048
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
@ -231,7 +231,7 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
RenderLocalLights 1 1
RenderLocalLightCount 1 4096
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
@ -258,7 +258,7 @@ RenderAvatarMaxNonImpostors 1 16
RenderFarClip 1 256
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderLocalLights 1 1
RenderLocalLightCount 1 8192
RenderMaxPartCount 1 8192
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
@ -298,7 +298,7 @@ list safe
RenderAnisotropic 1 0
RenderAvatarMaxNonImpostors 1 16
RenderAvatarMaxComplexity 1 80000
RenderLocalLights 1 0
RenderLocalLightCount 1 0
RenderMaxPartCount 1 1024
RenderTerrainDetail 1 0
RenderDeferredSSAO 0 0
@ -313,7 +313,6 @@ RenderDeferredSSAO 1 0
list Intel
RenderAnisotropic 1 0
RenderLocalLights 1 0
RenderFSAASamples 1 0
list GL3

View File

@ -122,8 +122,7 @@ const F32 MAX_FIDGET_TIME = 20.f; // seconds
const S32 UI_FEATURE_VERSION = 1;
// For version 1: 1 - inventory, 2 - gltf
// Will need to change to 3 once either inventory or gltf releases and cause a conflict
const S32 UI_FEATURE_FLAGS = 2;
const S32 UI_FEATURE_FLAGS = 3;
// The agent instance.
LLAgent gAgent;

View File

@ -1306,8 +1306,9 @@ void LLAgentWearables::findAttachmentsAddRemoveInfo(LLInventoryModel::item_array
}
// Build up list of objects to be removed and items currently attached.
for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
iter != gAgentAvatarp->mAttachmentPoints.end();)
LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
LLVOAvatar::attachment_map_t::iterator end = gAgentAvatarp->mAttachmentPoints.end();
while (iter != end)
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
@ -1526,7 +1527,7 @@ bool LLAgentWearables::moveWearable(const LLViewerInventoryItem* item, bool clos
}
// static
void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, const LLUUID& parent_id)
void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, const LLUUID& parent_id, std::function<void(const LLUUID&)> created_cb)
{
if (type == LLWearableType::WT_INVALID || type == LLWearableType::WT_NONE) return;
@ -1538,7 +1539,7 @@ void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, con
LLViewerWearable* wearable = LLWearableList::instance().createNewWearable(type, gAgentAvatarp);
LLAssetType::EType asset_type = wearable->getAssetType();
LLPointer<LLInventoryCallback> cb;
LLPointer<LLBoostFuncInventoryCallback> cb;
if(wear)
{
cb = new LLBoostFuncInventoryCallback(wear_and_edit_cb);
@ -1547,6 +1548,10 @@ void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, con
{
cb = new LLBoostFuncInventoryCallback(wear_cb);
}
if (created_cb != NULL)
{
cb->addOnFireFunc(created_cb);
}
LLUUID folder_id;

View File

@ -129,7 +129,7 @@ protected:
//--------------------------------------------------------------------
public:
static void createWearable(LLWearableType::EType type, bool wear = false, const LLUUID& parent_id = LLUUID::null);
static void createWearable(LLWearableType::EType type, bool wear = false, const LLUUID& parent_id = LLUUID::null, std::function<void(const LLUUID&)> created_cb = NULL);
static void editWearable(const LLUUID& item_id);
bool moveWearable(const LLViewerInventoryItem* item, bool closer_to_body);

File diff suppressed because it is too large Load Diff

View File

@ -38,6 +38,12 @@
class AISAPI
{
public:
static const S32 HTTP_TIMEOUT;
typedef enum {
INVENTORY,
LIBRARY
} ITEM_TYPE;
typedef boost::function<void(const LLUUID &invItem)> completion_t;
static bool isAvailable();
@ -50,9 +56,16 @@ public:
static void PurgeDescendents(const LLUUID &categoryId, completion_t callback = completion_t());
static void UpdateCategory(const LLUUID &categoryId, const LLSD &updates, completion_t callback = completion_t());
static void UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t callback = completion_t());
static void FetchItem(const LLUUID &itemId, ITEM_TYPE type, completion_t callback = completion_t());
static void FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0);
static void FetchCategoryChildren(const std::string &identifier, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0);
static void FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0);
static void FetchCategorySubset(const LLUUID& catId, const uuid_vec_t specificChildren, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0);
static void FetchCOF(completion_t callback = completion_t());
static void FetchCategoryLinks(const LLUUID &catId, completion_t callback = completion_t());
static void FetchOrphans(completion_t callback = completion_t() );
static void CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback = completion_t());
private:
typedef enum {
COPYINVENTORY,
SLAMFOLDER,
@ -61,9 +74,18 @@ private:
PURGEDESCENDENTS,
UPDATECATEGORY,
UPDATEITEM,
COPYLIBRARYCATEGORY
COPYLIBRARYCATEGORY,
CREATEINVENTORY,
FETCHITEM,
FETCHCATEGORYCHILDREN,
FETCHCATEGORYCATEGORIES,
FETCHCATEGORYSUBSET,
FETCHCOF,
FETCHORPHANS,
FETCHCATEGORYLINKS
} COMMAND_TYPE;
private:
static const std::string INVENTORY_CAP_NAME;
static const std::string LIBRARY_CAP_NAME;
@ -72,6 +94,7 @@ private:
static void EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc);
static void onIdle(void *userdata); // launches postponed AIS commands
static void onUpdateReceived(const LLSD& update, COMMAND_TYPE type, const LLSD& request_body);
static std::string getInvCap();
static std::string getLibCap();
@ -87,24 +110,29 @@ private:
class AISUpdate
{
public:
AISUpdate(const LLSD& update);
AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD& request_body);
void parseUpdate(const LLSD& update);
void parseMeta(const LLSD& update);
void parseContent(const LLSD& update);
void parseUUIDArray(const LLSD& content, const std::string& name, uuid_list_t& ids);
void parseLink(const LLSD& link_map);
void parseLink(const LLSD& link_map, S32 depth);
void parseItem(const LLSD& link_map);
void parseCategory(const LLSD& link_map);
void parseDescendentCount(const LLUUID& category_id, const LLSD& embedded);
void parseEmbedded(const LLSD& embedded);
void parseEmbeddedLinks(const LLSD& links);
void parseCategory(const LLSD& link_map, S32 depth);
void parseDescendentCount(const LLUUID& category_id, LLFolderType::EType type, const LLSD& embedded);
void parseEmbedded(const LLSD& embedded, S32 depth);
void parseEmbeddedLinks(const LLSD& links, S32 depth);
void parseEmbeddedItems(const LLSD& items);
void parseEmbeddedCategories(const LLSD& categories);
void parseEmbeddedCategories(const LLSD& categories, S32 depth);
void parseEmbeddedItem(const LLSD& item);
void parseEmbeddedCategory(const LLSD& category);
void parseEmbeddedCategory(const LLSD& category, S32 depth);
void doUpdate();
private:
void clearParseResults();
void checkTimeout();
// Fetch can return large packets of data, throttle it to not cause lags
// Todo: make throttle work over all fetch requests isntead of per-request
const F32 AIS_EXPIRY_SECONDS = 0.008f;
typedef std::map<LLUUID,S32> uuid_int_map_t;
uuid_int_map_t mCatDescendentDeltas;
@ -113,6 +141,7 @@ private:
typedef std::map<LLUUID,LLPointer<LLViewerInventoryItem> > deferred_item_map_t;
deferred_item_map_t mItemsCreated;
deferred_item_map_t mItemsLost;
deferred_item_map_t mItemsUpdated;
typedef std::map<LLUUID,LLPointer<LLViewerInventoryCategory> > deferred_category_map_t;
deferred_category_map_t mCategoriesCreated;
@ -123,6 +152,10 @@ private:
uuid_list_t mObjectsDeletedIds;
uuid_list_t mItemIds;
uuid_list_t mCategoryIds;
bool mFetch;
S32 mFetchDepth;
LLTimer mTimer;
AISAPI::COMMAND_TYPE mType;
};
#endif

View File

@ -40,6 +40,7 @@
#include "llgesturemgr.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llinventoryobserver.h"
#include "llmd5.h"
#include "llnotificationsutil.h"
@ -590,6 +591,71 @@ LLUpdateAppearanceAndEditWearableOnDestroy::~LLUpdateAppearanceAndEditWearableOn
}
}
class LLBrokenLinkObserver : public LLInventoryObserver
{
public:
LLUUID mUUID;
bool mEnforceItemRestrictions;
bool mEnforceOrdering;
nullary_func_t mPostUpdateFunc;
LLBrokenLinkObserver(const LLUUID& uuid,
bool enforce_item_restrictions ,
bool enforce_ordering ,
nullary_func_t post_update_func) :
mUUID(uuid),
mEnforceItemRestrictions(enforce_item_restrictions),
mEnforceOrdering(enforce_ordering),
mPostUpdateFunc(post_update_func)
{
}
/* virtual */ void changed(U32 mask);
void postProcess();
};
void LLBrokenLinkObserver::changed(U32 mask)
{
if (mask & LLInventoryObserver::REBUILD)
{
// This observer should be executed after LLInventoryPanel::itemChanged(),
// but if it isn't, consider calling updateAppearanceFromCOF with a delay
const uuid_set_t& changed_item_ids = gInventory.getChangedIDs();
for (uuid_set_t::const_iterator it = changed_item_ids.begin(); it != changed_item_ids.end(); ++it)
{
const LLUUID& id = *it;
if (id == mUUID)
{
// Might not be processed yet and it is not a
// good idea to update appearane here, postpone.
doOnIdleOneTime([this]()
{
postProcess();
});
gInventory.removeObserver(this);
return;
}
}
}
}
void LLBrokenLinkObserver::postProcess()
{
LLViewerInventoryItem* item = gInventory.getItem(mUUID);
llassert(item && !item->getIsBrokenLink()); // the whole point was to get a correct link
if (item && item->getIsBrokenLink())
{
LL_INFOS_ONCE("Avatar") << "Outfit link broken despite being regenerated" << LL_ENDL;
LL_DEBUGS("Avatar", "Inventory") << "Outfit link " << mUUID << " \"" << item->getName() << "\" is broken despite being regenerated" << LL_ENDL;
}
LLAppearanceMgr::instance().updateAppearanceFromCOF(
mEnforceItemRestrictions ,
mEnforceOrdering ,
mPostUpdateFunc);
delete this;
}
struct LLFoundData
{
@ -1706,12 +1772,18 @@ void LLAppearanceMgr::shallowCopyCategory(const LLUUID& src_id, const LLUUID& ds
{
parent_id = gInventory.getRootFolderID();
}
LLUUID subfolder_id = gInventory.createNewCategory( parent_id,
LLFolderType::FT_NONE,
src_cat->getName());
shallowCopyCategoryContents(src_id, subfolder_id, cb);
gInventory.createNewCategory(
parent_id,
LLFolderType::FT_NONE,
src_cat->getName(),
[src_id, cb](const LLUUID &new_id)
{
LLAppearanceMgr::getInstance()->shallowCopyCategoryContents(src_id, new_id, cb);
gInventory.notifyObservers();
gInventory.notifyObservers();
},
src_cat->getThumbnailUUID()
);
}
void LLAppearanceMgr::slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,
@ -2414,6 +2486,39 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
LL_DEBUGS("Avatar") << self_av_string() << "starting" << LL_ENDL;
if (gInventory.hasPosiblyBrockenLinks())
{
// Inventory has either broken links or links that
// haven't loaded yet.
// Check if LLAppearanceMgr needs to wait.
LLUUID current_outfit_id = getCOF();
LLInventoryModel::item_array_t cof_items;
LLInventoryModel::cat_array_t cof_cats;
LLFindBrokenLinks is_brocken_link;
gInventory.collectDescendentsIf(current_outfit_id,
cof_cats,
cof_items,
LLInventoryModel::EXCLUDE_TRASH,
is_brocken_link);
if (cof_items.size() > 0)
{
// Some links haven't loaded yet, but fetch isn't complete so
// links are likely fine and we will have to wait for them to
// load
if (LLInventoryModelBackgroundFetch::getInstance()->folderFetchActive())
{
LLBrokenLinkObserver* observer = new LLBrokenLinkObserver(cof_items.front()->getUUID(),
enforce_item_restrictions,
enforce_ordering,
post_update_func);
gInventory.addObserver(observer);
return;
}
}
}
if (enforce_item_restrictions)
{
// The point here is just to call
@ -2730,22 +2835,29 @@ void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool ap
{
pid = gInventory.getRootFolderID();
}
LLUUID new_cat_id = gInventory.createNewCategory(
gInventory.createNewCategory(
pid,
LLFolderType::FT_NONE,
name);
name,
[cat_id, append](const LLUUID& new_cat_id)
{
LLInventoryModel::cat_array_t* cats;
LLInventoryModel::item_array_t* items;
gInventory.getDirectDescendentsOf(cat_id, cats, items);
// Create a CopyMgr that will copy items, manage its own destruction
new LLCallAfterInventoryCopyMgr(
*items, new_cat_id, std::string("wear_inventory_category_callback"),
boost::bind(&LLAppearanceMgr::wearInventoryCategoryOnAvatar,
LLAppearanceMgr::getInstance(),
gInventory.getCategory(new_cat_id),
append));
// Create a CopyMgr that will copy items, manage its own destruction
new LLCallAfterInventoryCopyMgr(
*items, new_cat_id, std::string("wear_inventory_category_callback"),
boost::bind(&LLAppearanceMgr::wearInventoryCategoryOnAvatar,
LLAppearanceMgr::getInstance(),
gInventory.getCategory(new_cat_id),
append));
// BAP fixes a lag in display of created dir.
gInventory.notifyObservers();
// BAP fixes a lag in display of created dir.
gInventory.notifyObservers();
},
cat->getThumbnailUUID()
);
}
else
{
@ -3203,7 +3315,7 @@ void LLAppearanceMgr::copyLibraryGestures()
// Copy gestures
LLUUID lib_gesture_cat_id =
gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_GESTURE,false);
gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_GESTURE);
if (lib_gesture_cat_id.isNull())
{
LL_WARNS() << "Unable to copy gestures, source category not found" << LL_ENDL;
@ -3714,7 +3826,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd
if (cofVersion == LLViewerInventoryCategory::VERSION_UNKNOWN)
{
LL_WARNS("AVatar") << "COF version is unknown... not requesting until COF version is known." << LL_ENDL;
LL_INFOS("AVatar") << "COF version is unknown... not requesting until COF version is known." << LL_ENDL;
return;
}
else
@ -3986,26 +4098,15 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo
// First, make a folder in the My Outfits directory.
const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
if (AISAPI::isAvailable())
{
// cap-based category creation was buggy until recently. use
// existence of AIS as an indicator the fix is present. Does
// not actually use AIS to create the category.
inventory_func_type func = boost::bind(&LLAppearanceMgr::onOutfitFolderCreated,this,_1,show_panel);
gInventory.createNewCategory(
parent_id,
LLFolderType::FT_OUTFIT,
new_folder_name,
func);
}
else
{
LLUUID folder_id = gInventory.createNewCategory(
parent_id,
LLFolderType::FT_OUTFIT,
new_folder_name);
onOutfitFolderCreated(folder_id, show_panel);
}
gInventory.createNewCategory(
parent_id,
LLFolderType::FT_OUTFIT,
new_folder_name,
[show_panel](const LLUUID &new_cat_id)
{
LLAppearanceMgr::getInstance()->onOutfitFolderCreated(new_cat_id, show_panel);
});
}
void LLAppearanceMgr::wearBaseOutfit()
@ -4338,6 +4439,73 @@ public:
~CallAfterCategoryFetchStage1()
{
}
/*virtual*/ void startFetch()
{
bool ais3 = AISAPI::isAvailable();
for (uuid_vec_t::const_iterator it = mIDs.begin(); it != mIDs.end(); ++it)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
if (!cat) continue;
if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)
{
// CHECK IT: isCategoryComplete() checks both version and descendant count but
// fetch() only works for Unknown version and doesn't care about descentants,
// as result fetch won't start and folder will potentially get stuck as
// incomplete in observer.
// Likely either both should use only version or both should check descendants.
cat->fetch(); //blindly fetch it without seeing if anything else is fetching it.
mIncomplete.push_back(*it); //Add to list of things being downloaded for this observer.
}
else if (!isCategoryComplete(cat))
{
LL_DEBUGS("Inventory") << "Categoty " << *it << " incomplete despite having version" << LL_ENDL;
LLInventoryModelBackgroundFetch::instance().scheduleFolderFetch(*it, true);
mIncomplete.push_back(*it);
}
else if (ais3)
{
LLInventoryModel::cat_array_t* cats;
LLInventoryModel::item_array_t* items;
gInventory.getDirectDescendentsOf(cat->getUUID(), cats, items);
if (items)
{
S32 complete_count = 0;
S32 incomplete_count = 0;
for (LLInventoryModel::item_array_t::const_iterator it = items->begin(); it < items->end(); ++it)
{
if (!(*it)->isFinished())
{
incomplete_count++;
}
else
{
complete_count++;
}
}
// AIS can fetch couple items, but if there
// is more than a dozen it will be very slow
// it's faster to get whole folder in such case
if (incomplete_count > LLInventoryFetchItemsObserver::MAX_INDIVIDUAL_ITEM_REQUESTS
|| (incomplete_count > 1 && complete_count == 0))
{
LLInventoryModelBackgroundFetch::instance().scheduleFolderFetch(*it, true);
mIncomplete.push_back(*it);
}
else
{
// let stage2 handle incomplete ones
mComplete.push_back(*it);
}
}
// else should have been handled by isCategoryComplete
}
else
{
mComplete.push_back(*it);
}
}
}
virtual void done()
{
if (mComplete.size() <= 0)
@ -4354,13 +4522,11 @@ public:
// What we do here is get the complete information on the
// items in the requested category, and set up an observer
// that will wait for that to happen.
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
gInventory.collectDescendents(mComplete.front(),
cat_array,
item_array,
LLInventoryModel::EXCLUDE_TRASH);
S32 count = item_array.size();
LLInventoryModel::cat_array_t* cats;
LLInventoryModel::item_array_t* items;
gInventory.getDirectDescendentsOf(mComplete.front(), cats, items);
S32 count = items->size();
if(!count)
{
LL_WARNS() << "Nothing fetched in category " << mComplete.front()
@ -4372,11 +4538,13 @@ public:
return;
}
LL_INFOS() << "stage1 got " << item_array.size() << " items, passing to stage2 " << LL_ENDL;
LLViewerInventoryCategory* cat = gInventory.getCategory(mComplete.front());
S32 version = cat ? cat->getVersion() : -2;
LL_INFOS() << "stage1, category " << mComplete.front() << " got " << count << " items, version " << version << " passing to stage2 " << LL_ENDL;
uuid_vec_t ids;
for(S32 i = 0; i < count; ++i)
{
ids.push_back(item_array.at(i)->getUUID());
ids.push_back(items->at(i)->getUUID());
}
gInventory.removeObserver(this);
@ -4401,18 +4569,78 @@ protected:
nullary_func_t mCallable;
};
void callAfterCOFFetch(nullary_func_t cb)
{
LLUUID cat_id = LLAppearanceMgr::instance().getCOF();
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
if (AISAPI::isAvailable())
{
// Mark cof (update timer) so that background fetch won't request it
cat->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE);
// For reliability assume that we have no relevant cache, so
// fetch cof along with items cof's links point to.
AISAPI::FetchCOF([cb](const LLUUID& id)
{
cb();
LLUUID cat_id = LLAppearanceMgr::instance().getCOF();
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
if (cat)
{
cat->setFetching(LLViewerInventoryCategory::FETCH_NONE);
}
});
}
else
{
LL_INFOS() << "AIS API v3 not available, using callAfterCategoryFetch" << LL_ENDL;
// startup should have marked folder as fetching, remove that
cat->setFetching(LLViewerInventoryCategory::FETCH_NONE);
callAfterCategoryFetch(cat_id, cb);
}
}
void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb)
{
CallAfterCategoryFetchStage1 *stage1 = new CallAfterCategoryFetchStage1(cat_id, cb);
stage1->startFetch();
if (stage1->isFinished())
{
stage1->done();
}
else
{
gInventory.addObserver(stage1);
}
CallAfterCategoryFetchStage1* stage1 = new CallAfterCategoryFetchStage1(cat_id, cb);
stage1->startFetch();
if (stage1->isFinished())
{
stage1->done();
}
else
{
gInventory.addObserver(stage1);
}
}
void callAfterCategoryLinksFetch(const LLUUID &cat_id, nullary_func_t cb)
{
LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
if (AISAPI::isAvailable())
{
// Mark folder (update timer) so that background fetch won't request it
cat->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE);
// Assume that we have no relevant cache. Fetch folder, and items folder's links point to.
AISAPI::FetchCategoryLinks(cat_id,
[cb, cat_id](const LLUUID &id)
{
cb();
LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
if (cat)
{
cat->setFetching(LLViewerInventoryCategory::FETCH_NONE);
}
});
}
else
{
LL_WARNS() << "AIS API v3 not available, can't use AISAPI::FetchCOF" << LL_ENDL;
// startup should have marked folder as fetching, remove that
cat->setFetching(LLViewerInventoryCategory::FETCH_NONE);
callAfterCategoryFetch(cat_id, cb);
}
}
void add_wearable_type_counts(const uuid_vec_t& ids,

View File

@ -338,7 +338,9 @@ public:
LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& name);
// Invoke a given callable after category contents are fully fetched.
void callAfterCOFFetch(nullary_func_t cb);
void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb);
void callAfterCategoryLinksFetch(const LLUUID &cat_id, nullary_func_t cb);
// Wear all items in a uuid vector.
void wear_multiple(const uuid_vec_t& ids, bool replace);

View File

@ -215,7 +215,7 @@
#include "llcommandlineparser.h"
#include "llfloatermemleak.h"
#include "llfloaterreg.h"
#include "llfloatersimpleoutfitsnapshot.h"
#include "llfloatersimplesnapshot.h"
#include "llfloatersnapshot.h"
#include "llsidepanelinventory.h"
#include "llatmosphere.h"
@ -1520,7 +1520,7 @@ bool LLAppViewer::doFrame()
gPipeline.mReflectionMapManager.update();
gPipeline.mHeroProbeManager.update();
LLFloaterSnapshot::update(); // take snapshots
LLFloaterSimpleOutfitSnapshot::update();
LLFloaterSimpleSnapshot::update();
gGLActive = FALSE;
}

View File

@ -240,6 +240,13 @@ void LLAttachmentsMgr::linkRecentlyArrivedAttachments()
return;
}
if (LLAppearanceMgr::instance().getCOFVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)
{
// Wait for cof to load
LL_DEBUGS_ONCE("Avatar") << "Received atachments, but cof isn't loaded yet, postponing processing" << LL_ENDL;
return;
}
LL_DEBUGS("Avatar") << "ATT checking COF linkability for " << mRecentlyArrivedAttachments.size()
<< " recently arrived items" << LL_ENDL;

View File

@ -730,39 +730,55 @@ namespace action_give_inventory
/**
* Checks My Inventory visibility.
*/
static bool is_give_inventory_acceptable_ids(const std::set<LLUUID> inventory_selected_uuids)
{
if (inventory_selected_uuids.empty()) return false; // nothing selected
bool acceptable = false;
std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
for (; it != it_end; ++it)
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
// any category can be offered.
if (inv_cat)
{
acceptable = true;
continue;
}
LLViewerInventoryItem* inv_item = gInventory.getItem(*it);
// check if inventory item can be given
if (LLGiveInventory::isInventoryGiveAcceptable(inv_item))
{
acceptable = true;
continue;
}
// there are neither item nor category in inventory
acceptable = false;
break;
}
return acceptable;
}
static bool is_give_inventory_acceptable(LLInventoryPanel* panel = NULL)
{
// check selection in the panel
const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(panel);
if (inventory_selected_uuids.empty()) return false; // nothing selected
std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(panel);
if (inventory_selected_uuids.empty())
{
if(panel && panel->getRootFolder() && panel->getRootFolder()->isSingleFolderMode())
{
inventory_selected_uuids.insert(panel->getRootFolderID());
}
else
{
return false; // nothing selected
}
}
bool acceptable = false;
std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
for (; it != it_end; ++it)
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
// any category can be offered.
if (inv_cat)
{
acceptable = true;
continue;
}
LLViewerInventoryItem* inv_item = gInventory.getItem(*it);
// check if inventory item can be given
if (LLGiveInventory::isInventoryGiveAcceptable(inv_item))
{
acceptable = true;
continue;
}
// there are neither item nor category in inventory
acceptable = false;
break;
}
return acceptable;
return is_give_inventory_acceptable_ids(inventory_selected_uuids);
}
static void build_items_string(const std::set<LLUUID>& inventory_selected_uuids , std::string& items_string)
@ -890,46 +906,65 @@ namespace action_give_inventory
* @param avatar_names - avatar names request to be sent.
* @param avatar_uuids - avatar names request to be sent.
*/
static void give_inventory(const uuid_vec_t& avatar_uuids, const std::vector<LLAvatarName> avatar_names, LLInventoryPanel* panel = NULL)
{
llassert(avatar_names.size() == avatar_uuids.size());
const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(panel);
if (inventory_selected_uuids.empty())
{
return;
}
static void give_inventory_ids(const uuid_vec_t& avatar_uuids, const std::vector<LLAvatarName> avatar_names, const uuid_set_t inventory_selected_uuids)
{
llassert(avatar_names.size() == avatar_uuids.size());
std::string residents;
LLAvatarActions::buildResidentsString(avatar_names, residents, true);
if (inventory_selected_uuids.empty())
{
return;
}
std::string items;
build_items_string(inventory_selected_uuids, items);
std::string residents;
LLAvatarActions::buildResidentsString(avatar_names, residents, true);
int folders_count = 0;
std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
std::string items;
build_items_string(inventory_selected_uuids, items);
//traverse through selected inventory items and count folders among them
for ( ; it != inventory_selected_uuids.end() && folders_count <=1 ; ++it)
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
if (NULL != inv_cat)
{
folders_count++;
}
}
int folders_count = 0;
std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
// EXP-1599
// In case of sharing multiple folders, make the confirmation
// dialog contain a warning that only one folder can be shared at a time.
std::string notification = (folders_count > 1) ? "ShareFolderConfirmation" : "ShareItemsConfirmation";
LLSD substitutions;
substitutions["RESIDENTS"] = residents;
substitutions["ITEMS"] = items;
LLShareInfo::instance().mAvatarNames = avatar_names;
LLShareInfo::instance().mAvatarUuids = avatar_uuids;
LLNotificationsUtil::add(notification, substitutions, LLSD(), boost::bind(&give_inventory_cb, _1, _2, inventory_selected_uuids));
}
//traverse through selected inventory items and count folders among them
for ( ; it != inventory_selected_uuids.end() && folders_count <=1 ; ++it)
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
if (NULL != inv_cat)
{
folders_count++;
}
}
// EXP-1599
// In case of sharing multiple folders, make the confirmation
// dialog contain a warning that only one folder can be shared at a time.
std::string notification = (folders_count > 1) ? "ShareFolderConfirmation" : "ShareItemsConfirmation";
LLSD substitutions;
substitutions["RESIDENTS"] = residents;
substitutions["ITEMS"] = items;
LLShareInfo::instance().mAvatarNames = avatar_names;
LLShareInfo::instance().mAvatarUuids = avatar_uuids;
LLNotificationsUtil::add(notification, substitutions, LLSD(), boost::bind(&give_inventory_cb, _1, _2, inventory_selected_uuids));
}
static void give_inventory(const uuid_vec_t& avatar_uuids, const std::vector<LLAvatarName> avatar_names, LLInventoryPanel* panel = NULL)
{
llassert(avatar_names.size() == avatar_uuids.size());
std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(panel);;
if (inventory_selected_uuids.empty())
{
if(panel && panel->getRootFolder() && panel->getRootFolder()->isSingleFolderMode())
{
inventory_selected_uuids.insert(panel->getRootFolderID());
}
else
{
return;
}
}
give_inventory_ids(avatar_uuids, avatar_names, inventory_selected_uuids);
}
}
// static
@ -1037,6 +1072,28 @@ void LLAvatarActions::shareWithAvatars(LLView * panel)
LLNotificationsUtil::add("ShareNotification");
}
//static
void LLAvatarActions::shareWithAvatars(const uuid_set_t inventory_selected_uuids, LLFloater* root_floater)
{
using namespace action_give_inventory;
LLFloaterAvatarPicker* picker =
LLFloaterAvatarPicker::show(boost::bind(give_inventory_ids, _1, _2, inventory_selected_uuids), TRUE, FALSE, FALSE, root_floater->getName());
if (!picker)
{
return;
}
picker->setOkBtnEnableCb(boost::bind(is_give_inventory_acceptable_ids, inventory_selected_uuids));
picker->openFriendsTab();
if (root_floater)
{
root_floater->addDependentFloater(picker);
}
LLNotificationsUtil::add("ShareNotification");
}
// static
bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NULL*/)
{

View File

@ -133,6 +133,7 @@ public:
* Share items with the picked avatars.
*/
static void shareWithAvatars(LLView * panel);
static void shareWithAvatars(const uuid_set_t inventory_selected_uuids, LLFloater* root_floater);
/**
* Block/unblock the avatar by id.

View File

@ -111,6 +111,7 @@ public:
virtual void previewItem( void );
virtual void selectItem(void) { }
virtual void showProperties(void);
virtual void navigateToFolder(bool new_window = false, bool change_mode = false) {}
// Methods used in sorting (see LLConversationSort::operator())
EConversationType const getType() const { return mConvType; }
@ -249,7 +250,7 @@ public:
bool check(const LLFolderViewModelItem* item) { return true; }
bool checkFolder(const LLFolderViewModelItem* folder) const { return true; }
void setEmptyLookupMessage(const std::string& message) { }
std::string getEmptyLookupMessage() const { return mEmpty; }
std::string getEmptyLookupMessage(bool is_empty_folder = false) const { return mEmpty; }
bool showAllResults() const { return true; }
std::string::size_type getStringMatchOffset(LLFolderViewModelItem* item) const { return std::string::npos; }
std::string::size_type getFilterStringSize() const { return 0; }

View File

@ -2954,12 +2954,20 @@ void LLEnvironment::DayTransition::animate()
setWater(mNextInstance->getWater());
});
// pause probe updates and reset reflection maps on sky change
gPipeline.mReflectionMapManager.pause();
gPipeline.mReflectionMapManager.reset();
mSky = mStartSky->buildClone();
mBlenderSky = std::make_shared<LLSettingsBlenderTimeDelta>(mSky, mStartSky, mNextInstance->getSky(), mTransitionTime);
mBlenderSky->setOnFinished(
[this](LLSettingsBlender::ptr_t blender) {
mBlenderSky.reset();
// resume reflection probe updates
gPipeline.mReflectionMapManager.resume();
if (!mBlenderSky && !mBlenderWater)
LLEnvironment::instance().mCurrentEnvironment = mNextInstance;
else
@ -3550,12 +3558,19 @@ namespace
LLSettingsSky::ptr_t target_sky(start_sky->buildClone());
mInjectedSky->setSource(target_sky);
// clear reflection probes and pause updates during sky change
gPipeline.mReflectionMapManager.pause();
gPipeline.mReflectionMapManager.reset();
mBlenderSky = std::make_shared<LLSettingsBlenderTimeDelta>(target_sky, start_sky, psky, transition);
mBlenderSky->setOnFinished(
[this, psky](LLSettingsBlender::ptr_t blender)
{
mBlenderSky.reset();
mInjectedSky->setSource(psky);
// resume updating reflection probes when done animating sky
gPipeline.mReflectionMapManager.resume();
setSky(mInjectedSky);
if (!mBlenderWater && (countExperiencesActive() == 0))
{

View File

@ -0,0 +1,955 @@
/**
* @file llfloaterchangeitemthumbnail.cpp
* @brief LLFloaterChangeItemThumbnail class implementation
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, 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 "llfloaterchangeitemthumbnail.h"
#include "llbutton.h"
#include "llclipboard.h"
#include "lliconctrl.h"
#include "llinventoryfunctions.h"
#include "llinventoryicon.h"
#include "llinventorymodel.h"
#include "llinventoryobserver.h"
#include "llfloaterreg.h"
#include "llfloatersimplesnapshot.h"
#include "lllineeditor.h"
#include "llnotificationsutil.h"
#include "lltextbox.h"
#include "lltexturectrl.h"
#include "llthumbnailctrl.h"
#include "llviewerfoldertype.h"
#include "llviewermenufile.h"
#include "llviewerobjectlist.h"
#include "llviewertexturelist.h"
#include "llwindow.h"
class LLThumbnailImagePicker : public LLFilePickerThread
{
public:
LLThumbnailImagePicker(const LLUUID &item_id);
LLThumbnailImagePicker(const LLUUID &item_id, const LLUUID &task_id);
~LLThumbnailImagePicker();
void notify(const std::vector<std::string>& filenames) override;
private:
LLUUID mInventoryId;
LLUUID mTaskId;
};
LLThumbnailImagePicker::LLThumbnailImagePicker(const LLUUID &item_id)
: LLFilePickerThread(LLFilePicker::FFLOAD_IMAGE)
, mInventoryId(item_id)
{
}
LLThumbnailImagePicker::LLThumbnailImagePicker(const LLUUID &item_id, const LLUUID &task_id)
: LLFilePickerThread(LLFilePicker::FFLOAD_IMAGE)
, mInventoryId(item_id)
, mTaskId(task_id)
{
}
LLThumbnailImagePicker::~LLThumbnailImagePicker()
{
}
void LLThumbnailImagePicker::notify(const std::vector<std::string>& filenames)
{
if (filenames.empty())
{
return;
}
std::string file_path = filenames[0];
if (file_path.empty())
{
return;
}
LLFloaterSimpleSnapshot::uploadThumbnail(file_path, mInventoryId, mTaskId);
}
LLFloaterChangeItemThumbnail::LLFloaterChangeItemThumbnail(const LLSD& key)
: LLFloater(key)
, mObserverInitialized(false)
, mTooltipState(TOOLTIP_NONE)
{
}
LLFloaterChangeItemThumbnail::~LLFloaterChangeItemThumbnail()
{
gInventory.removeObserver(this);
removeVOInventoryListener();
}
BOOL LLFloaterChangeItemThumbnail::postBuild()
{
mItemNameText = getChild<LLUICtrl>("item_name");
mItemTypeIcon = getChild<LLIconCtrl>("item_type_icon");
mThumbnailCtrl = getChild<LLThumbnailCtrl>("item_thumbnail");
mToolTipTextBox = getChild<LLTextBox>("tooltip_text");
LLSD tooltip_text;
mToolTipTextBox->setValue(tooltip_text);
LLButton *upload_local = getChild<LLButton>("upload_local");
upload_local->setClickedCallback(onUploadLocal, (void*)this);
upload_local->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_UPLOAD_LOCAL));
upload_local->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_UPLOAD_LOCAL));
LLButton *upload_snapshot = getChild<LLButton>("upload_snapshot");
upload_snapshot->setClickedCallback(onUploadSnapshot, (void*)this);
upload_snapshot->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_UPLOAD_SNAPSHOT));
upload_snapshot->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_UPLOAD_SNAPSHOT));
LLButton *use_texture = getChild<LLButton>("use_texture");
use_texture->setClickedCallback(onUseTexture, (void*)this);
use_texture->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_USE_TEXTURE));
use_texture->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_USE_TEXTURE));
mCopyToClipboardBtn = getChild<LLButton>("copy_to_clipboard");
mCopyToClipboardBtn->setClickedCallback(onCopyToClipboard, (void*)this);
mCopyToClipboardBtn->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_COPY_TO_CLIPBOARD));
mCopyToClipboardBtn->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_COPY_TO_CLIPBOARD));
mPasteFromClipboardBtn = getChild<LLButton>("paste_from_clipboard");
mPasteFromClipboardBtn->setClickedCallback(onPasteFromClipboard, (void*)this);
mPasteFromClipboardBtn->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_COPY_FROM_CLIPBOARD));
mPasteFromClipboardBtn->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_COPY_FROM_CLIPBOARD));
mRemoveImageBtn = getChild<LLButton>("remove_image");
mRemoveImageBtn->setClickedCallback(onRemove, (void*)this);
mRemoveImageBtn->setMouseEnterCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseEnter, this, _1, _2, TOOLTIP_REMOVE));
mRemoveImageBtn->setMouseLeaveCallback(boost::bind(&LLFloaterChangeItemThumbnail::onButtonMouseLeave, this, _1, _2, TOOLTIP_REMOVE));
return LLFloater::postBuild();
}
void LLFloaterChangeItemThumbnail::onOpen(const LLSD& key)
{
if (!key.has("item_id") && !key.isUUID())
{
closeFloater();
}
if (key.isUUID())
{
mItemId = key.asUUID();
}
else
{
mItemId = key["item_id"].asUUID();
mTaskId = key["task_id"].asUUID();
}
refreshFromInventory();
}
void LLFloaterChangeItemThumbnail::onFocusReceived()
{
mPasteFromClipboardBtn->setEnabled(LLClipboard::instance().hasContents());
}
void LLFloaterChangeItemThumbnail::onMouseEnter(S32 x, S32 y, MASK mask)
{
mPasteFromClipboardBtn->setEnabled(LLClipboard::instance().hasContents());
}
BOOL LLFloaterChangeItemThumbnail::handleDragAndDrop(
S32 x,
S32 y,
MASK mask,
BOOL drop,
EDragAndDropType cargo_type,
void *cargo_data,
EAcceptance *accept,
std::string& tooltip_msg)
{
if (cargo_type == DAD_TEXTURE)
{
LLInventoryItem *item = (LLInventoryItem *)cargo_data;
if (item->getAssetUUID().notNull())
{
if (drop)
{
assignAndValidateAsset(item->getAssetUUID());
}
*accept = ACCEPT_YES_SINGLE;
}
else
{
*accept = ACCEPT_NO;
}
}
else
{
*accept = ACCEPT_NO;
}
LL_DEBUGS("UserInput") << "dragAndDrop handled by LLFloaterChangeItemThumbnail " << getKey() << LL_ENDL;
return TRUE;
}
void LLFloaterChangeItemThumbnail::changed(U32 mask)
{
//LLInventoryObserver
if (mTaskId.notNull() || mItemId.isNull())
{
// Task inventory or not set up yet
return;
}
const std::set<LLUUID>& mChangedItemIDs = gInventory.getChangedIDs();
std::set<LLUUID>::const_iterator it;
for (it = mChangedItemIDs.begin(); it != mChangedItemIDs.end(); it++)
{
// set dirty for 'item profile panel' only if changed item is the item for which 'item profile panel' is shown (STORM-288)
if (*it == mItemId)
{
// if there's a change we're interested in.
if ((mask & (LLInventoryObserver::LABEL | LLInventoryObserver::INTERNAL | LLInventoryObserver::REMOVE)) != 0)
{
refreshFromInventory();
}
}
}
}
void LLFloaterChangeItemThumbnail::inventoryChanged(LLViewerObject* object,
LLInventoryObject::object_list_t* inventory,
S32 serial_num,
void* user_data)
{
//LLVOInventoryListener
refreshFromInventory();
}
LLInventoryObject* LLFloaterChangeItemThumbnail::getInventoryObject()
{
LLInventoryObject* obj = NULL;
if (mTaskId.isNull())
{
// it is in agent inventory
if (!mObserverInitialized)
{
gInventory.addObserver(this);
mObserverInitialized = true;
}
obj = gInventory.getObject(mItemId);
}
else
{
LLViewerObject* object = gObjectList.findObject(mTaskId);
if (object)
{
if (!mObserverInitialized)
{
registerVOInventoryListener(object, NULL);
mObserverInitialized = false;
}
obj = object->getInventoryObject(mItemId);
}
}
return obj;
}
void LLFloaterChangeItemThumbnail::refreshFromInventory()
{
LLInventoryObject* obj = getInventoryObject();
if (!obj)
{
closeFloater();
}
if (obj)
{
const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
bool in_trash = gInventory.isObjectDescendentOf(obj->getUUID(), trash_id);
if (in_trash && obj->getUUID() != trash_id)
{
// Close properties when moving to trash
// Aren't supposed to view properties from trash
closeFloater();
}
else
{
refreshFromObject(obj);
}
}
else
{
closeFloater();
}
}
class LLIsOutfitTextureType : public LLInventoryCollectFunctor
{
public:
LLIsOutfitTextureType() {}
virtual ~LLIsOutfitTextureType() {}
virtual bool operator()(LLInventoryCategory* cat,
LLInventoryItem* item);
};
bool LLIsOutfitTextureType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
return item && (item->getType() == LLAssetType::AT_TEXTURE);
}
void LLFloaterChangeItemThumbnail::refreshFromObject(LLInventoryObject* obj)
{
LLUIImagePtr icon_img;
LLUUID thumbnail_id = obj->getThumbnailUUID();
LLViewerInventoryItem* item = dynamic_cast<LLViewerInventoryItem*>(obj);
if (item)
{
setTitle(getString("title_item_thumbnail"));
icon_img = LLInventoryIcon::getIcon(item->getType(), item->getInventoryType(), item->getFlags(), FALSE);
mRemoveImageBtn->setEnabled(thumbnail_id.notNull() && ((item->getActualType() != LLAssetType::AT_TEXTURE) || (item->getAssetUUID() != thumbnail_id)));
}
else
{
LLViewerInventoryCategory* cat = dynamic_cast<LLViewerInventoryCategory*>(obj);
if (cat)
{
setTitle(getString("title_folder_thumbnail"));
icon_img = LLUI::getUIImage(LLViewerFolderType::lookupIconName(cat->getPreferredType(), true));
if (thumbnail_id.isNull() && (cat->getPreferredType() == LLFolderType::FT_OUTFIT))
{
// Legacy support, check if there is an image inside
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
// Not LLIsOfAssetType, because we allow links
LLIsOutfitTextureType f;
gInventory.getDirectDescendentsOf(mItemId, cats, items, f);
if (1 == items.size())
{
LLViewerInventoryItem* item = items.front();
if (item && item->getIsLinkType())
{
item = item->getLinkedItem();
}
if (item)
{
thumbnail_id = item->getAssetUUID();
if (thumbnail_id.notNull())
{
// per SL-19188, set this image as a thumbnail
LL_INFOS() << "Setting image " << thumbnail_id
<< " from outfit as a thumbnail for inventory object " << obj->getUUID()
<< LL_ENDL;
assignAndValidateAsset(thumbnail_id, true);
}
}
}
}
mRemoveImageBtn->setEnabled(thumbnail_id.notNull());
}
}
mItemTypeIcon->setImage(icon_img);
mItemNameText->setValue(obj->getName());
mThumbnailCtrl->setValue(thumbnail_id);
mCopyToClipboardBtn->setEnabled(thumbnail_id.notNull());
mPasteFromClipboardBtn->setEnabled(LLClipboard::instance().hasContents());
// todo: some elements might not support setting thumbnails
// since they already have them
// It is unclear how system folders should function
}
void LLFloaterChangeItemThumbnail::onUploadLocal(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
(new LLThumbnailImagePicker(self->mItemId, self->mTaskId))->getFile();
LLFloater* floaterp = self->mPickerHandle.get();
if (floaterp)
{
floaterp->closeFloater();
}
floaterp = self->mSnapshotHandle.get();
if (floaterp)
{
floaterp->closeFloater();
}
}
void LLFloaterChangeItemThumbnail::onUploadSnapshot(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
LLFloater* floaterp = self->mSnapshotHandle.get();
// Show the dialog
if (floaterp)
{
floaterp->openFloater();
}
else
{
LLSD key;
key["item_id"] = self->mItemId;
key["task_id"] = self->mTaskId;
LLFloaterSimpleSnapshot* snapshot_floater = (LLFloaterSimpleSnapshot*)LLFloaterReg::showInstance("simple_snapshot", key, true);
if (snapshot_floater)
{
self->addDependentFloater(snapshot_floater);
self->mSnapshotHandle = snapshot_floater->getHandle();
snapshot_floater->setOwner(self);
}
}
floaterp = self->mPickerHandle.get();
if (floaterp)
{
floaterp->closeFloater();
}
}
void LLFloaterChangeItemThumbnail::onUseTexture(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
LLInventoryObject* obj = self->getInventoryObject();
if (obj)
{
self->showTexturePicker(obj->getThumbnailUUID());
}
LLFloater* floaterp = self->mSnapshotHandle.get();
if (floaterp)
{
floaterp->closeFloater();
}
}
void LLFloaterChangeItemThumbnail::onCopyToClipboard(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
LLInventoryObject* obj = self->getInventoryObject();
if (obj)
{
LLClipboard::instance().reset();
LLClipboard::instance().addToClipboard(obj->getThumbnailUUID(), LLAssetType::AT_NONE);
self->mPasteFromClipboardBtn->setEnabled(true);
}
}
void LLFloaterChangeItemThumbnail::onPasteFromClipboard(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
std::vector<LLUUID> objects;
LLClipboard::instance().pasteFromClipboard(objects);
if (objects.size() > 0)
{
LLUUID potential_uuid = objects[0];
LLUUID asset_id;
if (potential_uuid.notNull())
{
LLViewerInventoryItem* item = gInventory.getItem(potential_uuid);
if (item)
{
// no point checking snapshot?
if (item->getType() == LLAssetType::AT_TEXTURE)
{
bool copy = item->getPermissions().allowCopyBy(gAgent.getID());
bool xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID());
if (copy && xfer)
{
asset_id = item->getAssetUUID();
}
else
{
LLNotificationsUtil::add("ThumbnailInsufficientPermissions");
return;
}
}
}
else
{
// assume that this is a texture
asset_id = potential_uuid;
}
}
LLInventoryObject* obj = self->getInventoryObject();
if (obj && obj->getThumbnailUUID() == asset_id)
{
// nothing to do
return;
}
if (asset_id.notNull())
{
self->assignAndValidateAsset(asset_id);
}
// else show 'buffer has no texture' warning?
}
}
void LLFloaterChangeItemThumbnail::onRemove(void *userdata)
{
LLFloaterChangeItemThumbnail *self = (LLFloaterChangeItemThumbnail*)userdata;
LLSD payload;
payload["item_id"] = self->mItemId;
payload["object_id"] = self->mTaskId;
LLNotificationsUtil::add("DeleteThumbnail", LLSD(), payload, boost::bind(&LLFloaterChangeItemThumbnail::onRemovalConfirmation, _1, _2, self->getHandle()));
}
// static
void LLFloaterChangeItemThumbnail::onRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFloater> handle)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0 && !handle.isDead() && !handle.get()->isDead())
{
LLFloaterChangeItemThumbnail* self = (LLFloaterChangeItemThumbnail*)handle.get();
self->setThumbnailId(LLUUID::null);
}
}
struct ImageLoadedData
{
LLUUID mThumbnailId;
LLUUID mObjectId;
LLHandle<LLFloater> mFloaterHandle;
bool mSilent;
// Keep image reference to prevent deletion on timeout
LLPointer<LLViewerFetchedTexture> mTexturep;
};
void LLFloaterChangeItemThumbnail::assignAndValidateAsset(const LLUUID &asset_id, bool silent)
{
LLPointer<LLViewerFetchedTexture> texturep = LLViewerTextureManager::getFetchedTexture(asset_id);
if (texturep->isMissingAsset())
{
LL_WARNS() << "Attempted to assign missing asset " << asset_id << LL_ENDL;
if (!silent)
{
LLNotificationsUtil::add("ThumbnailDimentionsLimit");
}
}
else if (texturep->getFullWidth() == 0)
{
if (silent)
{
mExpectingAssetId = LLUUID::null;
}
else
{
// don't warn user multiple times if some textures took their time
mExpectingAssetId = asset_id;
}
ImageLoadedData *data = new ImageLoadedData();
data->mObjectId = mItemId;
data->mThumbnailId = asset_id;
data->mFloaterHandle = getHandle();
data->mSilent = silent;
data->mTexturep = texturep;
texturep->setLoadedCallback(onImageDataLoaded,
MAX_DISCARD_LEVEL, // Don't need full image, just size data
FALSE,
FALSE,
(void*)data,
NULL,
FALSE);
}
else
{
if (validateAsset(asset_id))
{
setThumbnailId(asset_id);
}
else if (!silent)
{
LLNotificationsUtil::add("ThumbnailDimentionsLimit");
}
}
}
bool LLFloaterChangeItemThumbnail::validateAsset(const LLUUID &asset_id)
{
if (asset_id.isNull())
{
return false;
}
LLPointer<LLViewerFetchedTexture> texturep = LLViewerTextureManager::findFetchedTexture(asset_id, TEX_LIST_STANDARD);
if (!texturep)
{
return false;
}
if (texturep->isMissingAsset())
{
return false;
}
if (texturep->getFullWidth() != texturep->getFullHeight())
{
return false;
}
if (texturep->getFullWidth() > LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MAX
|| texturep->getFullHeight() > LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MAX)
{
return false;
}
if (texturep->getFullWidth() < LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MIN
|| texturep->getFullHeight() < LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MIN)
{
return false;
}
return true;
}
//static
void LLFloaterChangeItemThumbnail::onImageDataLoaded(
BOOL success,
LLViewerFetchedTexture *src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
BOOL final,
void* userdata)
{
if (!userdata) return;
if (!final && success) return; //not done yet
ImageLoadedData* data = (ImageLoadedData*)userdata;
if (success)
{
// Update the item, set it even if floater is dead
if (validateAsset(data->mThumbnailId))
{
setThumbnailId(data->mThumbnailId, data->mObjectId);
}
else if (!data->mSilent)
{
// Should this only appear if floater is alive?
LLNotificationsUtil::add("ThumbnailDimentionsLimit");
}
}
// Update floater
if (!data->mSilent && !data->mFloaterHandle.isDead())
{
LLFloaterChangeItemThumbnail* self = static_cast<LLFloaterChangeItemThumbnail*>(data->mFloaterHandle.get());
if (self && self->mExpectingAssetId == data->mThumbnailId)
{
self->mExpectingAssetId = LLUUID::null;
}
}
delete data;
}
//static
void LLFloaterChangeItemThumbnail::onFullImageLoaded(
BOOL success,
LLViewerFetchedTexture* src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
BOOL final,
void* userdata)
{
if (!userdata) return;
if (!final && success) return; //not done yet
ImageLoadedData* data = (ImageLoadedData*)userdata;
if (success)
{
if (src_vi->getFullWidth() != src_vi->getFullHeight()
|| src_vi->getFullWidth() < LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MIN)
{
if (!data->mSilent)
{
LLNotificationsUtil::add("ThumbnailDimentionsLimit");
}
}
else if (src_vi->getFullWidth() > LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MAX)
{
LLFloaterSimpleSnapshot::uploadThumbnail(src, data->mObjectId, LLUUID::null);
}
else
{
setThumbnailId(data->mThumbnailId, data->mObjectId);
}
}
delete data;
}
void LLFloaterChangeItemThumbnail::showTexturePicker(const LLUUID &thumbnail_id)
{
// show hourglass cursor when loading inventory window
getWindow()->setCursor(UI_CURSOR_WAIT);
LLFloater* floaterp = mPickerHandle.get();
// Show the dialog
if (floaterp)
{
floaterp->openFloater();
}
else
{
floaterp = new LLFloaterTexturePicker(
this,
thumbnail_id,
thumbnail_id,
thumbnail_id,
FALSE,
TRUE,
"SELECT PHOTO",
PERM_NONE,
PERM_NONE,
FALSE,
NULL);
mPickerHandle = floaterp->getHandle();
LLFloaterTexturePicker* texture_floaterp = dynamic_cast<LLFloaterTexturePicker*>(floaterp);
if (texture_floaterp)
{
//texture_floaterp->setTextureSelectedCallback();
//texture_floaterp->setOnUpdateImageStatsCallback();
texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource, const LLUUID&, const LLUUID&)
{
if (op == LLTextureCtrl::TEXTURE_SELECT)
{
onTexturePickerCommit();
}
}
);
texture_floaterp->setLocalTextureEnabled(FALSE);
texture_floaterp->setBakeTextureEnabled(FALSE);
texture_floaterp->setCanApplyImmediately(false);
texture_floaterp->setCanApply(false, true, false /*Hide 'preview disabled'*/);
texture_floaterp->setMinDimentionsLimits(LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MIN);
addDependentFloater(texture_floaterp);
}
floaterp->openFloater();
}
floaterp->setFocus(TRUE);
}
void LLFloaterChangeItemThumbnail::onTexturePickerCommit()
{
LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mPickerHandle.get();
if (floaterp)
{
LLUUID asset_id = floaterp->getAssetID();
if (asset_id.isNull())
{
setThumbnailId(asset_id);
return;
}
LLInventoryObject* obj = getInventoryObject();
if (obj && obj->getThumbnailUUID() == asset_id)
{
// nothing to do
return;
}
LLPointer<LLViewerFetchedTexture> texturep = LLViewerTextureManager::findFetchedTexture(asset_id, TEX_LIST_STANDARD);
if (!texturep)
{
LL_WARNS() << "Image " << asset_id << " doesn't exist" << LL_ENDL;
return;
}
if (texturep->isMissingAsset())
{
LL_WARNS() << "Image " << asset_id << " is missing" << LL_ENDL;
return;
}
if (texturep->getFullWidth() != texturep->getFullHeight())
{
LLNotificationsUtil::add("ThumbnailDimentionsLimit");
return;
}
if (texturep->getFullWidth() < LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MIN
&& texturep->getFullWidth() > 0)
{
LLNotificationsUtil::add("ThumbnailDimentionsLimit");
return;
}
if (texturep->getFullWidth() > LLFloaterSimpleSnapshot::THUMBNAIL_SNAPSHOT_DIM_MAX
|| texturep->getFullWidth() == 0)
{
if (texturep->isFullyLoaded()
&& (texturep->getCachedRawImageLevel() == 0 || texturep->getRawImageLevel() == 0)
&& (texturep->isCachedRawImageReady() || texturep->isRawImageValid()))
{
if (texturep->isRawImageValid())
{
LLFloaterSimpleSnapshot::uploadThumbnail(texturep->getRawImage(), mItemId, mTaskId);
}
else
{
LLFloaterSimpleSnapshot::uploadThumbnail(texturep->getCachedRawImage(), mItemId, mTaskId);
}
}
else
{
ImageLoadedData* data = new ImageLoadedData();
data->mObjectId = mItemId;
data->mThumbnailId = asset_id;
data->mFloaterHandle = getHandle();
data->mSilent = false;
data->mTexturep = texturep;
texturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
texturep->setMinDiscardLevel(0);
texturep->setLoadedCallback(onFullImageLoaded,
0, // Need best quality
TRUE,
FALSE,
(void*)data,
NULL,
FALSE);
texturep->forceToSaveRawImage(0);
}
return;
}
setThumbnailId(asset_id);
}
}
void LLFloaterChangeItemThumbnail::setThumbnailId(const LLUUID &new_thumbnail_id)
{
LLInventoryObject* obj = getInventoryObject();
if (!obj)
{
return;
}
if (mTaskId.notNull())
{
LL_ERRS() << "Not implemented yet" << LL_ENDL;
return;
}
setThumbnailId(new_thumbnail_id, mItemId, obj);
}
void LLFloaterChangeItemThumbnail::setThumbnailId(const LLUUID& new_thumbnail_id, const LLUUID& object_id)
{
LLInventoryObject* obj = gInventory.getObject(object_id);
if (!obj)
{
return;
}
setThumbnailId(new_thumbnail_id, object_id, obj);
}
void LLFloaterChangeItemThumbnail::setThumbnailId(const LLUUID& new_thumbnail_id, const LLUUID& object_id, LLInventoryObject* obj)
{
if (obj->getThumbnailUUID() != new_thumbnail_id)
{
LLSD updates;
if (new_thumbnail_id.notNull())
{
// At the moment server expects id as a string
updates["thumbnail"] = LLSD().with("asset_id", new_thumbnail_id.asString());
}
else
{
// No thumbnail isntead of 'null id thumbnail'
updates["thumbnail"] = LLSD();
}
LLViewerInventoryCategory* view_folder = dynamic_cast<LLViewerInventoryCategory*>(obj);
if (view_folder)
{
update_inventory_category(object_id, updates, NULL);
}
LLViewerInventoryItem* view_item = dynamic_cast<LLViewerInventoryItem*>(obj);
if (view_item)
{
update_inventory_item(object_id, updates, NULL);
}
}
}
void LLFloaterChangeItemThumbnail::onButtonMouseEnter(LLUICtrl* button, const LLSD& param, EToolTipState state)
{
mTooltipState = state;
std::string tooltip_text;
std::string tooltip_name = "tooltip_" + button->getName();
if (hasString(tooltip_name))
{
tooltip_text = getString(tooltip_name);
}
mToolTipTextBox->setValue(tooltip_text);
}
void LLFloaterChangeItemThumbnail::onButtonMouseLeave(LLUICtrl* button, const LLSD& param, EToolTipState state)
{
if (mTooltipState == state)
{
mTooltipState = TOOLTIP_NONE;
LLSD tooltip_text;
mToolTipTextBox->setValue(tooltip_text);
}
}

View File

@ -0,0 +1,139 @@
/**
* @file llfloaterchangeitemthumbnail.h
* @brief LLFloaterChangeItemThumbnail class definition
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, 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_LLFLOATERCHANGEITEMTHUMBNAIL_H
#define LL_LLFLOATERCHANGEITEMTHUMBNAIL_H
#include "llfloater.h"
#include "llinventoryobserver.h"
#include "llvoinventorylistener.h"
class LLButton;
class LLIconCtrl;
class LLTextBox;
class LLThumbnailCtrl;
class LLUICtrl;
class LLViewerInventoryItem;
class LLViewerFetchedTexture;
class LLFloaterChangeItemThumbnail : public LLFloater, public LLInventoryObserver, public LLVOInventoryListener
{
public:
LLFloaterChangeItemThumbnail(const LLSD& key);
~LLFloaterChangeItemThumbnail();
BOOL postBuild() override;
void onOpen(const LLSD& key) override;
void onFocusReceived() override;
void onMouseEnter(S32 x, S32 y, MASK mask) override;
BOOL handleDragAndDrop(
S32 x,
S32 y,
MASK mask,
BOOL drop,
EDragAndDropType cargo_type,
void *cargo_data,
EAcceptance *accept,
std::string& tooltip_msg) override;
void changed(U32 mask) override;
void inventoryChanged(LLViewerObject* object,
LLInventoryObject::object_list_t* inventory,
S32 serial_num,
void* user_data) override;
static bool validateAsset(const LLUUID &asset_id);
private:
LLInventoryObject* getInventoryObject();
void refreshFromInventory();
void refreshFromObject(LLInventoryObject* obj);
static void onUploadLocal(void*);
static void onUploadSnapshot(void*);
static void onUseTexture(void*);
static void onCopyToClipboard(void*);
static void onPasteFromClipboard(void*);
static void onRemove(void*);
static void onRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFloater> handle);
void assignAndValidateAsset(const LLUUID &asset_id, bool silent = false);
static void onImageDataLoaded(BOOL success,
LLViewerFetchedTexture *src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
BOOL final,
void* userdata);
static void onFullImageLoaded(BOOL success,
LLViewerFetchedTexture* src_vi,
LLImageRaw* src,
LLImageRaw* aux_src,
S32 discard_level,
BOOL final,
void* userdata);
void showTexturePicker(const LLUUID &thumbnail_id);
void onTexturePickerCommit();
void setThumbnailId(const LLUUID &new_thumbnail_id);
static void setThumbnailId(const LLUUID& new_thumbnail_id, const LLUUID& object_id);
static void setThumbnailId(const LLUUID& new_thumbnail_id, const LLUUID& object_id, LLInventoryObject* obj);
enum EToolTipState
{
TOOLTIP_NONE,
TOOLTIP_UPLOAD_LOCAL,
TOOLTIP_UPLOAD_SNAPSHOT,
TOOLTIP_USE_TEXTURE,
TOOLTIP_COPY_TO_CLIPBOARD,
TOOLTIP_COPY_FROM_CLIPBOARD,
TOOLTIP_REMOVE,
};
void onButtonMouseEnter(LLUICtrl* button, const LLSD& param, EToolTipState state);
void onButtonMouseLeave(LLUICtrl* button, const LLSD& param, EToolTipState state);
bool mObserverInitialized;
EToolTipState mTooltipState;
LLUUID mItemId;
LLUUID mTaskId;
LLUUID mExpectingAssetId;
LLIconCtrl *mItemTypeIcon;
LLUICtrl *mItemNameText;
LLThumbnailCtrl *mThumbnailCtrl;
LLTextBox *mToolTipTextBox;
LLButton *mCopyToClipboardBtn;
LLButton *mPasteFromClipboardBtn;
LLButton *mRemoveImageBtn;
LLHandle<LLFloater> mPickerHandle;
LLHandle<LLFloater> mSnapshotHandle;
};
#endif // LL_LLFLOATERCHANGEITEMTHUMBNAIL_H

View File

@ -260,7 +260,7 @@ void LLFloaterEditEnvironmentBase::onSaveAsCommit(const LLSD& notification, cons
}
else if (mInventoryItem)
{
const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
LLUUID parent_id = mInventoryItem->getParentUUID();
if (marketplacelistings_id == parent_id || gInventory.isObjectDescendentOf(mInventoryItem->getUUID(), gInventory.getLibraryRootFolderID()))
{

View File

@ -164,6 +164,12 @@ bool LLFloaterForgetUser::onConfirmLogout(const LLSD& notification, const LLSD&
if (option == 0)
{
// Remove creds
std::string grid_id = LLGridManager::getInstance()->getGridId(grid);
if (grid_id.empty())
{
grid_id = grid;
}
gSecAPIHandler->removeFromProtectedMap("mfa_hash", grid_id, LLStartUp::getUserId()); // doesn't write
gSecAPIHandler->removeFromCredentialMap("login_list", grid, LLStartUp::getUserId());
LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(grid);
@ -228,7 +234,13 @@ void LLFloaterForgetUser::processForgetUser()
void LLFloaterForgetUser::forgetUser(const std::string &userid, const std::string &fav_id, const std::string &grid, bool delete_data)
{
// Remove creds
gSecAPIHandler->removeFromCredentialMap("login_list", grid, userid);
std::string grid_id = LLGridManager::getInstance()->getGridId(grid);
if (grid_id.empty())
{
grid_id = grid;
}
gSecAPIHandler->removeFromProtectedMap("mfa_hash", grid_id, userid); // doesn't write
gSecAPIHandler->removeFromCredentialMap("login_list", grid, userid); // write operation
LLPointer<LLCredential> cred = gSecAPIHandler->loadCredential(grid);
if (cred.notNull() && cred->userID() == userid)

View File

@ -211,7 +211,7 @@ BOOL LLFloaterGesture::postBuild()
getChildView("play_btn")->setVisible( true);
getChildView("stop_btn")->setVisible( false);
setDefaultBtn("play_btn");
mGestureFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE, false);
mGestureFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE);
uuid_vec_t folders;
folders.push_back(mGestureFolderID);

View File

@ -289,6 +289,9 @@ void LLFloaterIMContainer::onOpen(const LLSD& key)
LLMultiFloater::onOpen(key);
reSelectConversation();
assignResizeLimits();
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(mSelectedSession);
session_floater->onOpen(key);
}
// virtual

View File

@ -986,6 +986,8 @@ void LLFloaterIMSessionTab::onOpen(const LLSD& key)
}
mInputButtonPanel->setVisible(isTornOff());
setFocus(TRUE);
}

View File

@ -0,0 +1,44 @@
/**
* @file llfloaterinventorysettings.cpp
* @brief LLFloaterInventorySettings class implementation
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, 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 "llfloaterinventorysettings.h"
LLFloaterInventorySettings::LLFloaterInventorySettings(const LLSD& key)
: LLFloater(key)
{
}
LLFloaterInventorySettings::~LLFloaterInventorySettings()
{}
BOOL LLFloaterInventorySettings::postBuild()
{
getChild<LLButton>("ok_btn")->setCommitCallback(boost::bind(&LLFloater::closeFloater, this, false));
return TRUE;
}

View File

@ -0,0 +1,45 @@
/**
* @file llfloaterinventorysettings.h
* @brief LLFloaterInventorySettings class definition
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, 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_LLFLOATERINVENTORYSETTINGS_H
#define LL_LLFLOATERINVENTORYSETTINGS_H
#include "llfloater.h"
class LLFloaterInventorySettings
: public LLFloater
{
friend class LLFloaterReg;
public:
virtual BOOL postBuild();
private:
LLFloaterInventorySettings(const LLSD& key);
~LLFloaterInventorySettings();
};
#endif

View File

@ -335,8 +335,8 @@ BOOL LLFloaterLinkReplace::tick()
void LLFloaterLinkReplace::processBatch(LLInventoryModel::item_array_t items)
{
const LLViewerInventoryItem* target_item = gInventory.getItem(mTargetUUID);
const LLUUID cof_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
const LLUUID outfit_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
const LLUUID cof_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
const LLUUID outfit_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); ++it)
{

View File

@ -41,8 +41,11 @@
#include "llnotificationmanager.h"
#include "llnotificationsutil.h"
#include "llsidepaneliteminfo.h"
#include "llsidepaneltaskinfo.h"
#include "lltabcontainer.h"
#include "lltextbox.h"
#include "lltrans.h"
#include "llviewerwindow.h"
///----------------------------------------------------------------------------
/// LLPanelMarketplaceListings
@ -227,18 +230,31 @@ void LLPanelMarketplaceListings::onTabChange()
void LLPanelMarketplaceListings::onAddButtonClicked()
{
// Find active panel
LLInventoryPanel* panel = (LLInventoryPanel*)getChild<LLTabContainer>("marketplace_filter_tabs")->getCurrentPanel();
if (panel)
{
LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
llassert(marketplacelistings_id.notNull());
LLFolderType::EType preferred_type = LLFolderType::lookup("category");
LLUUID category = gInventory.createNewCategory(marketplacelistings_id, preferred_type, LLStringUtil::null);
gInventory.notifyObservers();
panel->setSelectionByID(category, TRUE);
panel->getRootFolder()->setNeedsAutoRename(TRUE);
LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
llassert(marketplacelistings_id.notNull());
LLFolderType::EType preferred_type = LLFolderType::lookup("category");
LLHandle<LLPanel> handle = getHandle();
gInventory.createNewCategory(
marketplacelistings_id,
preferred_type,
LLStringUtil::null,
[handle](const LLUUID &new_cat_id)
{
// Find active panel
LLPanel *marketplace_panel = handle.get();
if (!marketplace_panel)
{
return;
}
LLInventoryPanel* panel = (LLInventoryPanel*)marketplace_panel->getChild<LLTabContainer>("marketplace_filter_tabs")->getCurrentPanel();
if (panel)
{
gInventory.notifyObservers();
panel->setSelectionByID(new_cat_id, TRUE);
panel->getRootFolder()->setNeedsAutoRename(TRUE);
}
}
);
}
void LLPanelMarketplaceListings::onAuditButtonClicked()
@ -359,6 +375,7 @@ LLFloaterMarketplaceListings::LLFloaterMarketplaceListings(const LLSD& key)
, mInventoryTitle(NULL)
, mPanelListings(NULL)
, mPanelListingsSet(false)
, mRootFolderCreating(false)
{
}
@ -431,7 +448,7 @@ void LLFloaterMarketplaceListings::fetchContents()
{
LLMarketplaceData::instance().setDataFetchedSignal(boost::bind(&LLFloaterMarketplaceListings::updateView, this));
LLMarketplaceData::instance().setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_LOADING);
LLInventoryModelBackgroundFetch::instance().start(mRootFolderId);
LLInventoryModelBackgroundFetch::instance().start(mRootFolderId, true);
LLMarketplaceData::instance().getSLMListings();
}
}
@ -444,15 +461,50 @@ void LLFloaterMarketplaceListings::setRootFolder()
// If we are *not* a merchant or we have no market place connection established yet, do nothing
return;
}
if (!gInventory.isInventoryUsable())
{
return;
}
LLFolderType::EType preferred_type = LLFolderType::FT_MARKETPLACE_LISTINGS;
// We are a merchant. Get the Marketplace listings folder, create it if needs be.
LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, true);
if (marketplacelistings_id.isNull())
{
// We should never get there unless the inventory fails badly
LL_ERRS("SLM") << "Inventory problem: failure to create the marketplace listings folder for a merchant!" << LL_ENDL;
return;
}
LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(preferred_type);
if (marketplacelistings_id.isNull())
{
if (!mRootFolderCreating)
{
mRootFolderCreating = true;
gInventory.createNewCategory(
gInventory.getRootFolderID(),
preferred_type,
LLStringUtil::null,
[](const LLUUID &new_cat_id)
{
LLFloaterMarketplaceListings* marketplace = LLFloaterReg::findTypedInstance<LLFloaterMarketplaceListings>("marketplace_listings");
if (marketplace)
{
if (new_cat_id.notNull())
{
// will call setRootFolder again
marketplace->updateView();
}
// don't update in case of failure, createNewCategory can return
// immediately if cap is missing and will cause a loop
else
{
// unblock
marketplace->mRootFolderCreating = false;
LL_WARNS("SLM") << "Inventory warning: Failed to create marketplace listings folder for a merchant" << LL_ENDL;
}
}
}
);
}
return;
}
mRootFolderCreating = false;
// No longer need to observe new category creation
if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver))
@ -540,6 +592,11 @@ void LLFloaterMarketplaceListings::updateView()
{
setRootFolder();
}
if (mRootFolderCreating)
{
// waiting for callback
return;
}
// Update the bottom initializing status and progress dial if we are initializing or if we're a merchant and still loading
if ((mkt_status <= MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING) || (is_merchant && (data_fetched <= MarketplaceFetchCodes::MARKET_FETCH_LOADING)) )
@ -843,14 +900,17 @@ void LLFloaterMarketplaceValidation::onOpen(const LLSD& key)
LLUUID cat_id(key.asUUID());
if (cat_id.isNull())
{
cat_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
cat_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
}
// Validates the folder
if (cat_id.notNull())
{
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
validate_marketplacelistings(cat, boost::bind(&LLFloaterMarketplaceValidation::appendMessage, this, _1, _2, _3), false);
LLMarketplaceValidator::getInstance()->validateMarketplaceListings(
cat_id,
NULL,
boost::bind(&LLFloaterMarketplaceValidation::appendMessage, this, _1, _2, _3),
false);
}
// Handle the listing folder being processed
@ -954,18 +1014,44 @@ LLFloaterItemProperties::~LLFloaterItemProperties()
BOOL LLFloaterItemProperties::postBuild()
{
// On the standalone properties floater, we have no need for a back button...
LLSidepanelItemInfo* panel = getChild<LLSidepanelItemInfo>("item_panel");
LLButton* back_btn = panel->getChild<LLButton>("back_btn");
back_btn->setVisible(FALSE);
return LLFloater::postBuild();
}
void LLFloaterItemProperties::onOpen(const LLSD& key)
{
// Tell the panel which item it needs to visualize
LLSidepanelItemInfo* panel = getChild<LLSidepanelItemInfo>("item_panel");
panel->setItemID(key["id"].asUUID());
LLPanel* panel = findChild<LLPanel>("sidepanel");
LLSidepanelItemInfo* item_panel = dynamic_cast<LLSidepanelItemInfo*>(panel);
if (item_panel)
{
item_panel->setItemID(key["id"].asUUID());
if (key.has("object"))
{
item_panel->setObjectID(key["object"].asUUID());
}
item_panel->setParentFloater(this);
}
LLSidepanelTaskInfo* task_panel = dynamic_cast<LLSidepanelTaskInfo*>(panel);
if (task_panel)
{
task_panel->setObjectSelection(LLSelectMgr::getInstance()->getSelection());
}
}
LLMultiItemProperties::LLMultiItemProperties(const LLSD& key)
: LLMultiFloater(LLSD())
{
// start with a small rect in the top-left corner ; will get resized
LLRect rect;
rect.setLeftTopAndSize(0, gViewerWindow->getWindowHeightScaled(), 350, 350);
setRect(rect);
LLFloater* last_floater = LLFloaterReg::getLastFloaterInGroup(key.asString());
if (last_floater)
{
stackWith(*last_floater);
}
setTitle(LLTrans::getString("MultiPropertiesTitle"));
buildTabContainer();
}

View File

@ -33,6 +33,7 @@
#include "llinventorypanel.h"
#include "llnotificationptr.h"
#include "llmodaldialog.h"
#include "llmultifloater.h"
#include "lltexteditor.h"
class LLInventoryCategoriesObserver;
@ -139,6 +140,7 @@ private:
LLTextBox * mInventoryTitle;
LLUUID mRootFolderId;
bool mRootFolderCreating;
LLPanelMarketplaceListings * mPanelListings;
bool mPanelListingsSet;
};
@ -223,4 +225,10 @@ public:
private:
};
class LLMultiItemProperties : public LLMultiFloater
{
public:
LLMultiItemProperties(const LLSD& key);
};
#endif // LL_LLFLOATERMARKETPLACELISTINGS_H

View File

@ -164,34 +164,12 @@ void LLFloaterOpenObject::moveToInventory(bool wear, bool replace)
}
inventory_func_type func = boost::bind(LLFloaterOpenObject::callbackCreateInventoryCategory,_1,object_id,wear,replace);
LLUUID category_id = gInventory.createNewCategory(parent_category_id,
LLFolderType::FT_NONE,
name,
func);
//If we get a null category ID, we are using a capability in createNewCategory and we will
//handle the following in the callbackCreateInventoryCategory routine.
if ( category_id.notNull() )
{
LLCatAndWear* data = new LLCatAndWear;
data->mCatID = category_id;
data->mWear = wear;
data->mFolderResponded = false;
data->mReplace = replace;
// Copy and/or move the items into the newly created folder.
// Ignore any "you're going to break this item" messages.
BOOL success = move_inv_category_world_to_agent(object_id, category_id, TRUE,
callbackMoveInventory,
(void*)data);
if (!success)
{
delete data;
data = NULL;
LLNotificationsUtil::add("OpenObjectCannotCopy");
}
}
// D567 copy thumbnail info
gInventory.createNewCategory(
parent_category_id,
LLFolderType::FT_NONE,
name,
func);
}
// static
@ -206,9 +184,14 @@ void LLFloaterOpenObject::callbackCreateInventoryCategory(const LLUUID& category
// Copy and/or move the items into the newly created folder.
// Ignore any "you're going to break this item" messages.
BOOL success = move_inv_category_world_to_agent(object_id, category_id, TRUE,
callbackMoveInventory,
(void*)wear_data);
BOOL success = move_inv_category_world_to_agent(object_id,
category_id,
TRUE,
[](S32 result, void* data, const LLMoveInv*)
{
callbackMoveInventory(result, data);
},
(void*)wear_data);
if (!success)
{
delete wear_data;

View File

@ -1,288 +0,0 @@
/**
* @file llfloateroutfitphotopreview.cpp
* @brief LLFloaterOutfitPhotoPreview class implementation
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llwindow.h"
#include "llfloateroutfitphotopreview.h"
#include "llagent.h"
#include "llappearancemgr.h"
#include "llbutton.h"
#include "llcombobox.h"
#include "llfilepicker.h"
#include "llfloaterreg.h"
#include "llimagetga.h"
#include "llimagepng.h"
#include "llinventory.h"
#include "llinventorymodel.h"
#include "llnotificationsutil.h"
#include "llresmgr.h"
#include "lltrans.h"
#include "lltextbox.h"
#include "lltextureview.h"
#include "llui.h"
#include "llviewerinventory.h"
#include "llviewertexture.h"
#include "llviewertexturelist.h"
#include "lluictrlfactory.h"
#include "llviewerwindow.h"
#include "lllineeditor.h"
const S32 MAX_OUTFIT_PHOTO_WIDTH = 256;
const S32 MAX_OUTFIT_PHOTO_HEIGHT = 256;
const S32 CLIENT_RECT_VPAD = 4;
LLFloaterOutfitPhotoPreview::LLFloaterOutfitPhotoPreview(const LLSD& key)
: LLPreview(key),
mUpdateDimensions(TRUE),
mImage(NULL),
mOutfitID(LLUUID()),
mImageOldBoostLevel(LLGLTexture::BOOST_NONE),
mExceedLimits(FALSE)
{
updateImageID();
}
LLFloaterOutfitPhotoPreview::~LLFloaterOutfitPhotoPreview()
{
LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ;
if (mImage.notNull())
{
mImage->setBoostLevel(mImageOldBoostLevel);
mImage = NULL;
}
}
// virtual
BOOL LLFloaterOutfitPhotoPreview::postBuild()
{
getChild<LLButton>("ok_btn")->setClickedCallback(boost::bind(&LLFloaterOutfitPhotoPreview::onOkBtn, this));
getChild<LLButton>("cancel_btn")->setClickedCallback(boost::bind(&LLFloaterOutfitPhotoPreview::onCancelBtn, this));
return LLPreview::postBuild();
}
void LLFloaterOutfitPhotoPreview::draw()
{
updateDimensions();
LLPreview::draw();
if (!isMinimized())
{
LLGLSUIDefault gls_ui;
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
const LLRect& border = mClientRect;
LLRect interior = mClientRect;
interior.stretch( -PREVIEW_BORDER_WIDTH );
// ...border
gl_rect_2d( border, LLColor4(0.f, 0.f, 0.f, 1.f));
gl_rect_2d_checkerboard( interior );
if ( mImage.notNull() )
{
// Draw the texture
gGL.diffuseColor3f( 1.f, 1.f, 1.f );
gl_draw_scaled_image(interior.mLeft,
interior.mBottom,
interior.getWidth(),
interior.getHeight(),
mImage);
// Pump the texture priority
F32 pixel_area = (F32)(interior.getWidth() * interior.getHeight() );
mImage->addTextureStats( pixel_area );
S32 int_width = interior.getWidth();
S32 int_height = interior.getHeight();
mImage->setKnownDrawSize(int_width, int_height);
}
}
}
// virtual
void LLFloaterOutfitPhotoPreview::reshape(S32 width, S32 height, BOOL called_from_parent)
{
LLPreview::reshape(width, height, called_from_parent);
LLRect dim_rect(getChildView("dimensions")->getRect());
S32 horiz_pad = 2 * (LLPANEL_BORDER_WIDTH + PREVIEW_PAD) + PREVIEW_RESIZE_HANDLE_SIZE;
S32 info_height = dim_rect.mTop + CLIENT_RECT_VPAD;
LLRect client_rect(horiz_pad, getRect().getHeight(), getRect().getWidth() - horiz_pad, 0);
client_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD);
client_rect.mBottom += PREVIEW_BORDER + CLIENT_RECT_VPAD + info_height ;
S32 client_width = client_rect.getWidth();
S32 client_height = client_width;
if(client_height > client_rect.getHeight())
{
client_height = client_rect.getHeight();
client_width = client_height;
}
mClientRect.setLeftTopAndSize(client_rect.getCenterX() - (client_width / 2), client_rect.getCenterY() + (client_height / 2), client_width, client_height);
}
void LLFloaterOutfitPhotoPreview::updateDimensions()
{
if (!mImage)
{
return;
}
if ((mImage->getFullWidth() * mImage->getFullHeight()) == 0)
{
return;
}
if (mAssetStatus != PREVIEW_ASSET_LOADED)
{
mAssetStatus = PREVIEW_ASSET_LOADED;
mUpdateDimensions = TRUE;
}
getChild<LLUICtrl>("dimensions")->setTextArg("[WIDTH]", llformat("%d", mImage->getFullWidth()));
getChild<LLUICtrl>("dimensions")->setTextArg("[HEIGHT]", llformat("%d", mImage->getFullHeight()));
if ((mImage->getFullWidth() <= MAX_OUTFIT_PHOTO_WIDTH) && (mImage->getFullHeight() <= MAX_OUTFIT_PHOTO_HEIGHT))
{
getChild<LLButton>("ok_btn")->setEnabled(TRUE);
mExceedLimits = FALSE;
}
else
{
mExceedLimits = TRUE;
LLStringUtil::format_map_t args;
args["MAX_WIDTH"] = llformat("%d", MAX_OUTFIT_PHOTO_WIDTH);
args["MAX_HEIGHT"] = llformat("%d", MAX_OUTFIT_PHOTO_HEIGHT);
std::string label = getString("exceed_limits", args);
getChild<LLUICtrl>("notification")->setValue(label);
getChild<LLUICtrl>("notification")->setColor(LLColor4::yellow);
getChild<LLButton>("ok_btn")->setEnabled(FALSE);
}
if (mUpdateDimensions)
{
mUpdateDimensions = FALSE;
reshape(getRect().getWidth(), getRect().getHeight());
gFloaterView->adjustToFitScreen(this, FALSE);
}
}
void LLFloaterOutfitPhotoPreview::loadAsset()
{
if (mImage.notNull())
{
mImage->setBoostLevel(mImageOldBoostLevel);
}
mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
mImageOldBoostLevel = mImage->getBoostLevel();
mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
mImage->forceToSaveRawImage(0) ;
mAssetStatus = PREVIEW_ASSET_LOADING;
mUpdateDimensions = TRUE;
updateDimensions();
}
LLPreview::EAssetStatus LLFloaterOutfitPhotoPreview::getAssetStatus()
{
if (mImage.notNull() && (mImage->getFullWidth() * mImage->getFullHeight() > 0))
{
mAssetStatus = PREVIEW_ASSET_LOADED;
}
return mAssetStatus;
}
void LLFloaterOutfitPhotoPreview::updateImageID()
{
const LLViewerInventoryItem *item = static_cast<const LLViewerInventoryItem*>(getItem());
if(item)
{
mImageID = item->getAssetUUID();
}
else
{
mImageID = mItemUUID;
}
}
/* virtual */
void LLFloaterOutfitPhotoPreview::setObjectID(const LLUUID& object_id)
{
mObjectUUID = object_id;
const LLUUID old_image_id = mImageID;
updateImageID();
if (mImageID != old_image_id)
{
mAssetStatus = PREVIEW_ASSET_UNLOADED;
loadAsset();
}
refreshFromItem();
}
void LLFloaterOutfitPhotoPreview::setOutfitID(const LLUUID& outfit_id)
{
mOutfitID = outfit_id;
LLViewerInventoryCategory* outfit_folder = gInventory.getCategory(mOutfitID);
if(outfit_folder && !mExceedLimits)
{
getChild<LLUICtrl>("notification")->setValue( getString("photo_confirmation"));
getChild<LLUICtrl>("notification")->setTextArg("[OUTFIT]", outfit_folder->getName());
getChild<LLUICtrl>("notification")->setColor(LLColor4::white);
}
}
void LLFloaterOutfitPhotoPreview::onOkBtn()
{
if(mOutfitID.notNull() && getItem())
{
LLAppearanceMgr::instance().removeOutfitPhoto(mOutfitID);
LLPointer<LLInventoryCallback> cb = NULL;
link_inventory_object(mOutfitID, LLConstPointer<LLInventoryObject>(getItem()), cb);
}
closeFloater();
}
void LLFloaterOutfitPhotoPreview::onCancelBtn()
{
closeFloater();
}

View File

@ -1,77 +0,0 @@
/**
* @file llfloateroutfitphotopreview.h
* @brief LLFloaterOutfitPhotoPreview class definition
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLFLOATEROUTFITPHOTOPREVIEW_H
#define LL_LLFLOATEROUTFITPHOTOPREVIEW_H
#include "llpreview.h"
#include "llbutton.h"
#include "llframetimer.h"
#include "llviewertexture.h"
class LLComboBox;
class LLImageRaw;
class LLFloaterOutfitPhotoPreview : public LLPreview
{
public:
LLFloaterOutfitPhotoPreview(const LLSD& key);
~LLFloaterOutfitPhotoPreview();
virtual void draw();
virtual void loadAsset();
virtual EAssetStatus getAssetStatus();
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
/*virtual*/ void setObjectID(const LLUUID& object_id);
void setOutfitID(const LLUUID& outfit_id);
void onOkBtn();
void onCancelBtn();
protected:
void init();
/* virtual */ BOOL postBuild();
private:
void updateImageID(); // set what image is being uploaded.
void updateDimensions();
LLUUID mImageID;
LLUUID mOutfitID;
LLPointer<LLViewerFetchedTexture> mImage;
S32 mImageOldBoostLevel;
// This is stored off in a member variable, because the save-as
// button and drag and drop functionality need to know.
BOOL mUpdateDimensions;
BOOL mExceedLimits;
LLLoadedCallbackEntry::source_callback_list_t mCallbackTextureList ;
};
#endif // LL_LLFLOATEROUTFITPHOTOPREVIEW_H

View File

@ -1,891 +0,0 @@
/**
* @file llfloaterproperties.cpp
* @brief A floater which shows an inventory item's properties.
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloaterproperties.h"
#include <algorithm>
#include <functional>
#include "llcachename.h"
#include "llavatarnamecache.h"
#include "lldbstrings.h"
#include "llfloaterreg.h"
#include "llagent.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "llavataractions.h"
#include "llinventorydefines.h"
#include "llinventoryobserver.h"
#include "llinventorymodel.h"
#include "lllineeditor.h"
//#include "llspinctrl.h"
#include "llradiogroup.h"
#include "llresmgr.h"
#include "roles_constants.h"
#include "llselectmgr.h"
#include "lltextbox.h"
#include "lltrans.h"
#include "lluiconstants.h"
#include "llviewerinventory.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llviewercontrol.h"
#include "llviewerwindow.h"
#include "llgroupactions.h"
#include "lluictrlfactory.h"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLPropertiesObserver
//
// helper class to watch the inventory.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Ugh. This can't be a singleton because it needs to remove itself
// from the inventory observer list when destroyed, which could
// happen after gInventory has already been destroyed if a singleton.
// Instead, do our own ref counting and create / destroy it as needed
class LLPropertiesObserver : public LLInventoryObserver
{
public:
LLPropertiesObserver(LLFloaterProperties* floater)
: mFloater(floater)
{
gInventory.addObserver(this);
}
virtual ~LLPropertiesObserver()
{
gInventory.removeObserver(this);
}
virtual void changed(U32 mask);
private:
LLFloaterProperties* mFloater; // Not a handle because LLFloaterProperties is managing LLPropertiesObserver
};
void LLPropertiesObserver::changed(U32 mask)
{
// if there's a change we're interested in.
if((mask & (LLInventoryObserver::LABEL | LLInventoryObserver::INTERNAL | LLInventoryObserver::REMOVE)) != 0)
{
mFloater->dirty();
}
}
///----------------------------------------------------------------------------
/// Class LLFloaterProperties
///----------------------------------------------------------------------------
// Default constructor
LLFloaterProperties::LLFloaterProperties(const LLUUID& item_id)
: LLFloater(mItemID),
mItemID(item_id),
mDirty(TRUE)
{
mPropertiesObserver = new LLPropertiesObserver(this);
}
// Destroys the object
LLFloaterProperties::~LLFloaterProperties()
{
delete mPropertiesObserver;
mPropertiesObserver = NULL;
}
// virtual
BOOL LLFloaterProperties::postBuild()
{
// build the UI
// item name & description
getChild<LLLineEditor>("LabelItemName")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe);
getChild<LLUICtrl>("LabelItemName")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitName,this));
getChild<LLLineEditor>("LabelItemDesc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe);
getChild<LLUICtrl>("LabelItemDesc")->setCommitCallback(boost::bind(&LLFloaterProperties:: onCommitDescription, this));
// Creator information
getChild<LLUICtrl>("BtnCreator")->setCommitCallback(boost::bind(&LLFloaterProperties::onClickCreator,this));
// owner information
getChild<LLUICtrl>("BtnOwner")->setCommitCallback(boost::bind(&LLFloaterProperties::onClickOwner,this));
// acquired date
// owner permissions
// Permissions debug text
// group permissions
getChild<LLUICtrl>("CheckShareWithGroup")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitPermissions, this));
// everyone permissions
getChild<LLUICtrl>("CheckEveryoneCopy")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitPermissions, this));
// next owner permissions
getChild<LLUICtrl>("CheckNextOwnerModify")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitPermissions, this));
getChild<LLUICtrl>("CheckNextOwnerCopy")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitPermissions, this));
getChild<LLUICtrl>("CheckNextOwnerTransfer")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitPermissions, this));
// Mark for sale or not, and sale info
getChild<LLUICtrl>("CheckPurchase")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitSaleInfo, this));
getChild<LLUICtrl>("ComboBoxSaleType")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitSaleType, this));
// "Price" label for edit
getChild<LLUICtrl>("Edit Cost")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitSaleInfo, this));
// The UI has been built, now fill in all the values
refresh();
return TRUE;
}
// virtual
void LLFloaterProperties::onOpen(const LLSD& key)
{
refresh();
}
void LLFloaterProperties::refresh()
{
LLInventoryItem* item = findItem();
if(item)
{
refreshFromItem(item);
}
else
{
//RN: it is possible that the container object is in the middle of an inventory refresh
// causing findItem() to fail, so just temporarily disable everything
mDirty = TRUE;
const char* enableNames[]={
"LabelItemName",
"LabelItemDesc",
"LabelCreatorName",
"BtnCreator",
"LabelOwnerName",
"BtnOwner",
"CheckOwnerModify",
"CheckOwnerCopy",
"CheckOwnerTransfer",
"CheckShareWithGroup",
"CheckEveryoneCopy",
"CheckNextOwnerModify",
"CheckNextOwnerCopy",
"CheckNextOwnerTransfer",
"CheckPurchase",
"ComboBoxSaleType",
"Edit Cost"
};
for(size_t t=0; t<LL_ARRAY_SIZE(enableNames); ++t)
{
getChildView(enableNames[t])->setEnabled(false);
}
const char* hideNames[]={
"BaseMaskDebug",
"OwnerMaskDebug",
"GroupMaskDebug",
"EveryoneMaskDebug",
"NextMaskDebug"
};
for(size_t t=0; t<LL_ARRAY_SIZE(hideNames); ++t)
{
getChildView(hideNames[t])->setVisible(false);
}
}
}
void LLFloaterProperties::draw()
{
if (mDirty)
{
// RN: clear dirty first because refresh can set dirty to TRUE
mDirty = FALSE;
refresh();
}
LLFloater::draw();
}
void LLFloaterProperties::refreshFromItem(LLInventoryItem* item)
{
////////////////////////
// PERMISSIONS LOOKUP //
////////////////////////
// do not enable the UI for incomplete items.
LLViewerInventoryItem* i = (LLViewerInventoryItem*)item;
BOOL is_complete = i->isFinished();
const BOOL cannot_restrict_permissions = LLInventoryType::cannotRestrictPermissions(i->getInventoryType());
const BOOL is_calling_card = (i->getInventoryType() == LLInventoryType::IT_CALLINGCARD);
const LLPermissions& perm = item->getPermissions();
const BOOL can_agent_manipulate = gAgent.allowOperation(PERM_OWNER, perm,
GP_OBJECT_MANIPULATE);
const BOOL can_agent_sell = gAgent.allowOperation(PERM_OWNER, perm,
GP_OBJECT_SET_SALE) &&
!cannot_restrict_permissions;
const BOOL is_link = i->getIsLinkType();
// You need permission to modify the object to modify an inventory
// item in it.
LLViewerObject* object = NULL;
if(!mObjectID.isNull()) object = gObjectList.findObject(mObjectID);
BOOL is_obj_modify = TRUE;
if(object)
{
is_obj_modify = object->permOwnerModify();
}
//////////////////////
// ITEM NAME & DESC //
//////////////////////
BOOL is_modifiable = gAgent.allowOperation(PERM_MODIFY, perm,
GP_OBJECT_MANIPULATE)
&& is_obj_modify && is_complete;
getChildView("LabelItemNameTitle")->setEnabled(TRUE);
getChildView("LabelItemName")->setEnabled(is_modifiable && !is_calling_card); // for now, don't allow rename of calling cards
getChild<LLUICtrl>("LabelItemName")->setValue(item->getName());
getChildView("LabelItemDescTitle")->setEnabled(TRUE);
getChildView("LabelItemDesc")->setEnabled(is_modifiable);
getChildView("IconLocked")->setVisible(!is_modifiable);
getChild<LLUICtrl>("LabelItemDesc")->setValue(item->getDescription());
//////////////////
// CREATOR NAME //
//////////////////
if(!gCacheName) return;
if(!gAgent.getRegion()) return;
if (item->getCreatorUUID().notNull())
{
LLAvatarName av_name;
LLAvatarNameCache::get(item->getCreatorUUID(), &av_name);
getChildView("BtnCreator")->setEnabled(TRUE);
getChildView("LabelCreatorTitle")->setEnabled(TRUE);
getChildView("LabelCreatorName")->setEnabled(TRUE);
getChild<LLUICtrl>("LabelCreatorName")->setValue(av_name.getUserName());
}
else
{
getChildView("BtnCreator")->setEnabled(FALSE);
getChildView("LabelCreatorTitle")->setEnabled(FALSE);
getChildView("LabelCreatorName")->setEnabled(FALSE);
getChild<LLUICtrl>("LabelCreatorName")->setValue(getString("unknown"));
}
////////////////
// OWNER NAME //
////////////////
if(perm.isOwned())
{
std::string name;
if (perm.isGroupOwned())
{
gCacheName->getGroupName(perm.getGroup(), name);
}
else
{
LLAvatarName av_name;
LLAvatarNameCache::get(perm.getOwner(), &av_name);
name = av_name.getUserName();
}
getChildView("BtnOwner")->setEnabled(TRUE);
getChildView("LabelOwnerTitle")->setEnabled(TRUE);
getChildView("LabelOwnerName")->setEnabled(TRUE);
getChild<LLUICtrl>("LabelOwnerName")->setValue(name);
}
else
{
getChildView("BtnOwner")->setEnabled(FALSE);
getChildView("LabelOwnerTitle")->setEnabled(FALSE);
getChildView("LabelOwnerName")->setEnabled(FALSE);
getChild<LLUICtrl>("LabelOwnerName")->setValue(getString("public"));
}
//////////////////
// ACQUIRE DATE //
//////////////////
time_t time_utc = item->getCreationDate();
if (0 == time_utc)
{
getChild<LLUICtrl>("LabelAcquiredDate")->setValue(getString("unknown"));
}
else
{
std::string timeStr = getString("acquiredDate");
LLSD substitution;
substitution["datetime"] = (S32) time_utc;
LLStringUtil::format (timeStr, substitution);
getChild<LLUICtrl>("LabelAcquiredDate")->setValue(timeStr);
}
///////////////////////
// OWNER PERMISSIONS //
///////////////////////
if(can_agent_manipulate)
{
getChild<LLUICtrl>("OwnerLabel")->setValue(getString("you_can"));
}
else
{
getChild<LLUICtrl>("OwnerLabel")->setValue(getString("owner_can"));
}
U32 base_mask = perm.getMaskBase();
U32 owner_mask = perm.getMaskOwner();
U32 group_mask = perm.getMaskGroup();
U32 everyone_mask = perm.getMaskEveryone();
U32 next_owner_mask = perm.getMaskNextOwner();
getChildView("OwnerLabel")->setEnabled(TRUE);
getChildView("CheckOwnerModify")->setEnabled(FALSE);
getChild<LLUICtrl>("CheckOwnerModify")->setValue(LLSD((BOOL)(owner_mask & PERM_MODIFY)));
getChildView("CheckOwnerCopy")->setEnabled(FALSE);
getChild<LLUICtrl>("CheckOwnerCopy")->setValue(LLSD((BOOL)(owner_mask & PERM_COPY)));
getChildView("CheckOwnerTransfer")->setEnabled(FALSE);
getChild<LLUICtrl>("CheckOwnerTransfer")->setValue(LLSD((BOOL)(owner_mask & PERM_TRANSFER)));
///////////////////////
// DEBUG PERMISSIONS //
///////////////////////
if( gSavedSettings.getBOOL("DebugPermissions") )
{
BOOL slam_perm = FALSE;
BOOL overwrite_group = FALSE;
BOOL overwrite_everyone = FALSE;
if (item->getType() == LLAssetType::AT_OBJECT)
{
U32 flags = item->getFlags();
slam_perm = flags & LLInventoryItemFlags::II_FLAGS_OBJECT_SLAM_PERM;
overwrite_everyone = flags & LLInventoryItemFlags::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
overwrite_group = flags & LLInventoryItemFlags::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
}
std::string perm_string;
perm_string = "B: ";
perm_string += mask_to_string(base_mask);
getChild<LLUICtrl>("BaseMaskDebug")->setValue(perm_string);
getChildView("BaseMaskDebug")->setVisible(TRUE);
perm_string = "O: ";
perm_string += mask_to_string(owner_mask);
getChild<LLUICtrl>("OwnerMaskDebug")->setValue(perm_string);
getChildView("OwnerMaskDebug")->setVisible(TRUE);
perm_string = "G";
perm_string += overwrite_group ? "*: " : ": ";
perm_string += mask_to_string(group_mask);
getChild<LLUICtrl>("GroupMaskDebug")->setValue(perm_string);
getChildView("GroupMaskDebug")->setVisible(TRUE);
perm_string = "E";
perm_string += overwrite_everyone ? "*: " : ": ";
perm_string += mask_to_string(everyone_mask);
getChild<LLUICtrl>("EveryoneMaskDebug")->setValue(perm_string);
getChildView("EveryoneMaskDebug")->setVisible(TRUE);
perm_string = "N";
perm_string += slam_perm ? "*: " : ": ";
perm_string += mask_to_string(next_owner_mask);
getChild<LLUICtrl>("NextMaskDebug")->setValue(perm_string);
getChildView("NextMaskDebug")->setVisible(TRUE);
}
else
{
getChildView("BaseMaskDebug")->setVisible(FALSE);
getChildView("OwnerMaskDebug")->setVisible(FALSE);
getChildView("GroupMaskDebug")->setVisible(FALSE);
getChildView("EveryoneMaskDebug")->setVisible(FALSE);
getChildView("NextMaskDebug")->setVisible(FALSE);
}
/////////////
// SHARING //
/////////////
// Check for ability to change values.
if (is_link || cannot_restrict_permissions)
{
getChildView("CheckShareWithGroup")->setEnabled(FALSE);
getChildView("CheckEveryoneCopy")->setEnabled(FALSE);
}
else if (is_obj_modify && can_agent_manipulate)
{
getChildView("CheckShareWithGroup")->setEnabled(TRUE);
getChildView("CheckEveryoneCopy")->setEnabled((owner_mask & PERM_COPY) && (owner_mask & PERM_TRANSFER));
}
else
{
getChildView("CheckShareWithGroup")->setEnabled(FALSE);
getChildView("CheckEveryoneCopy")->setEnabled(FALSE);
}
// Set values.
BOOL is_group_copy = (group_mask & PERM_COPY) ? TRUE : FALSE;
BOOL is_group_modify = (group_mask & PERM_MODIFY) ? TRUE : FALSE;
BOOL is_group_move = (group_mask & PERM_MOVE) ? TRUE : FALSE;
if (is_group_copy && is_group_modify && is_group_move)
{
getChild<LLUICtrl>("CheckShareWithGroup")->setValue(LLSD((BOOL)TRUE));
LLCheckBoxCtrl* ctl = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
if(ctl)
{
ctl->setTentative(FALSE);
}
}
else if (!is_group_copy && !is_group_modify && !is_group_move)
{
getChild<LLUICtrl>("CheckShareWithGroup")->setValue(LLSD((BOOL)FALSE));
LLCheckBoxCtrl* ctl = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
if(ctl)
{
ctl->setTentative(FALSE);
}
}
else
{
LLCheckBoxCtrl* ctl = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
if(ctl)
{
ctl->setTentative(TRUE);
ctl->set(TRUE);
}
}
getChild<LLUICtrl>("CheckEveryoneCopy")->setValue(LLSD((BOOL)(everyone_mask & PERM_COPY)));
///////////////
// SALE INFO //
///////////////
const LLSaleInfo& sale_info = item->getSaleInfo();
BOOL is_for_sale = sale_info.isForSale();
LLComboBox* combo_sale_type = getChild<LLComboBox>("ComboBoxSaleType");
LLUICtrl* edit_cost = getChild<LLUICtrl>("Edit Cost");
// Check for ability to change values.
if (is_obj_modify && can_agent_sell
&& gAgent.allowOperation(PERM_TRANSFER, perm, GP_OBJECT_MANIPULATE))
{
getChildView("CheckPurchase")->setEnabled(is_complete);
getChildView("NextOwnerLabel")->setEnabled(TRUE);
getChildView("CheckNextOwnerModify")->setEnabled((base_mask & PERM_MODIFY) && !cannot_restrict_permissions);
getChildView("CheckNextOwnerCopy")->setEnabled((base_mask & PERM_COPY) && !cannot_restrict_permissions);
getChildView("CheckNextOwnerTransfer")->setEnabled((next_owner_mask & PERM_COPY) && !cannot_restrict_permissions);
combo_sale_type->setEnabled(is_complete && is_for_sale);
edit_cost->setEnabled(is_complete && is_for_sale);
}
else
{
getChildView("CheckPurchase")->setEnabled(FALSE);
getChildView("NextOwnerLabel")->setEnabled(FALSE);
getChildView("CheckNextOwnerModify")->setEnabled(FALSE);
getChildView("CheckNextOwnerCopy")->setEnabled(FALSE);
getChildView("CheckNextOwnerTransfer")->setEnabled(FALSE);
combo_sale_type->setEnabled(FALSE);
edit_cost->setEnabled(FALSE);
}
// Set values.
getChild<LLUICtrl>("CheckPurchase")->setValue(is_for_sale);
getChild<LLUICtrl>("CheckNextOwnerModify")->setValue(LLSD(BOOL(next_owner_mask & PERM_MODIFY)));
getChild<LLUICtrl>("CheckNextOwnerCopy")->setValue(LLSD(BOOL(next_owner_mask & PERM_COPY)));
getChild<LLUICtrl>("CheckNextOwnerTransfer")->setValue(LLSD(BOOL(next_owner_mask & PERM_TRANSFER)));
if (is_for_sale)
{
S32 numerical_price;
numerical_price = sale_info.getSalePrice();
edit_cost->setValue(llformat("%d",numerical_price));
combo_sale_type->setValue(sale_info.getSaleType());
}
else
{
edit_cost->setValue(llformat("%d",0));
combo_sale_type->setValue(LLSaleInfo::FS_COPY);
}
}
void LLFloaterProperties::onClickCreator()
{
LLInventoryItem* item = findItem();
if(!item) return;
if(!item->getCreatorUUID().isNull())
{
LLAvatarActions::showProfile(item->getCreatorUUID());
}
}
// static
void LLFloaterProperties::onClickOwner()
{
LLInventoryItem* item = findItem();
if(!item) return;
if(item->getPermissions().isGroupOwned())
{
LLGroupActions::show(item->getPermissions().getGroup());
}
else
{
LLAvatarActions::showProfile(item->getPermissions().getOwner());
}
}
// static
void LLFloaterProperties::onCommitName()
{
//LL_INFOS() << "LLFloaterProperties::onCommitName()" << LL_ENDL;
LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
if(!item)
{
return;
}
LLLineEditor* labelItemName = getChild<LLLineEditor>("LabelItemName");
if(labelItemName&&
(item->getName() != labelItemName->getText()) &&
(gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)) )
{
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
new_item->rename(labelItemName->getText());
if(mObjectID.isNull())
{
new_item->updateServer(FALSE);
gInventory.updateItem(new_item);
gInventory.notifyObservers();
}
else
{
LLViewerObject* object = gObjectList.findObject(mObjectID);
if(object)
{
object->updateInventory(
new_item,
TASK_INVENTORY_ITEM_KEY,
false);
}
}
}
}
void LLFloaterProperties::onCommitDescription()
{
//LL_INFOS() << "LLFloaterProperties::onCommitDescription()" << LL_ENDL;
LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
if(!item) return;
LLLineEditor* labelItemDesc = getChild<LLLineEditor>("LabelItemDesc");
if(!labelItemDesc)
{
return;
}
if((item->getDescription() != labelItemDesc->getText()) &&
(gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)))
{
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
new_item->setDescription(labelItemDesc->getText());
if(mObjectID.isNull())
{
new_item->updateServer(FALSE);
gInventory.updateItem(new_item);
gInventory.notifyObservers();
}
else
{
LLViewerObject* object = gObjectList.findObject(mObjectID);
if(object)
{
object->updateInventory(
new_item,
TASK_INVENTORY_ITEM_KEY,
false);
}
}
}
}
// static
void LLFloaterProperties::onCommitPermissions()
{
//LL_INFOS() << "LLFloaterProperties::onCommitPermissions()" << LL_ENDL;
LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
if(!item) return;
LLPermissions perm(item->getPermissions());
LLCheckBoxCtrl* CheckShareWithGroup = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
if(CheckShareWithGroup)
{
perm.setGroupBits(gAgent.getID(), gAgent.getGroupID(),
CheckShareWithGroup->get(),
PERM_MODIFY | PERM_MOVE | PERM_COPY);
}
LLCheckBoxCtrl* CheckEveryoneCopy = getChild<LLCheckBoxCtrl>("CheckEveryoneCopy");
if(CheckEveryoneCopy)
{
perm.setEveryoneBits(gAgent.getID(), gAgent.getGroupID(),
CheckEveryoneCopy->get(), PERM_COPY);
}
LLCheckBoxCtrl* CheckNextOwnerModify = getChild<LLCheckBoxCtrl>("CheckNextOwnerModify");
if(CheckNextOwnerModify)
{
perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
CheckNextOwnerModify->get(), PERM_MODIFY);
}
LLCheckBoxCtrl* CheckNextOwnerCopy = getChild<LLCheckBoxCtrl>("CheckNextOwnerCopy");
if(CheckNextOwnerCopy)
{
perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
CheckNextOwnerCopy->get(), PERM_COPY);
}
LLCheckBoxCtrl* CheckNextOwnerTransfer = getChild<LLCheckBoxCtrl>("CheckNextOwnerTransfer");
if(CheckNextOwnerTransfer)
{
perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
CheckNextOwnerTransfer->get(), PERM_TRANSFER);
}
if(perm != item->getPermissions()
&& item->isFinished())
{
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
new_item->setPermissions(perm);
U32 flags = new_item->getFlags();
// If next owner permissions have changed (and this is an object)
// then set the slam permissions flag so that they are applied on rez.
if((perm.getMaskNextOwner()!=item->getPermissions().getMaskNextOwner())
&& (item->getType() == LLAssetType::AT_OBJECT))
{
flags |= LLInventoryItemFlags::II_FLAGS_OBJECT_SLAM_PERM;
}
// If everyone permissions have changed (and this is an object)
// then set the overwrite everyone permissions flag so they
// are applied on rez.
if ((perm.getMaskEveryone()!=item->getPermissions().getMaskEveryone())
&& (item->getType() == LLAssetType::AT_OBJECT))
{
flags |= LLInventoryItemFlags::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
}
// If group permissions have changed (and this is an object)
// then set the overwrite group permissions flag so they
// are applied on rez.
if ((perm.getMaskGroup()!=item->getPermissions().getMaskGroup())
&& (item->getType() == LLAssetType::AT_OBJECT))
{
flags |= LLInventoryItemFlags::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
}
new_item->setFlags(flags);
if(mObjectID.isNull())
{
new_item->updateServer(FALSE);
gInventory.updateItem(new_item);
gInventory.notifyObservers();
}
else
{
LLViewerObject* object = gObjectList.findObject(mObjectID);
if(object)
{
object->updateInventory(
new_item,
TASK_INVENTORY_ITEM_KEY,
false);
}
}
}
else
{
// need to make sure we don't just follow the click
refresh();
}
}
// static
void LLFloaterProperties::onCommitSaleInfo()
{
//LL_INFOS() << "LLFloaterProperties::onCommitSaleInfo()" << LL_ENDL;
updateSaleInfo();
}
// static
void LLFloaterProperties::onCommitSaleType()
{
//LL_INFOS() << "LLFloaterProperties::onCommitSaleType()" << LL_ENDL;
updateSaleInfo();
}
void LLFloaterProperties::updateSaleInfo()
{
LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
if(!item) return;
LLSaleInfo sale_info(item->getSaleInfo());
if(!gAgent.allowOperation(PERM_TRANSFER, item->getPermissions(), GP_OBJECT_SET_SALE))
{
getChild<LLUICtrl>("CheckPurchase")->setValue(LLSD((BOOL)FALSE));
}
if((BOOL)getChild<LLUICtrl>("CheckPurchase")->getValue())
{
// turn on sale info
LLSaleInfo::EForSale sale_type = LLSaleInfo::FS_COPY;
LLComboBox* combo_sale_type = getChild<LLComboBox>("ComboBoxSaleType");
if (combo_sale_type)
{
sale_type = static_cast<LLSaleInfo::EForSale>(combo_sale_type->getValue().asInteger());
}
if (sale_type == LLSaleInfo::FS_COPY
&& !gAgent.allowOperation(PERM_COPY, item->getPermissions(),
GP_OBJECT_SET_SALE))
{
sale_type = LLSaleInfo::FS_ORIGINAL;
}
S32 price = -1;
price = getChild<LLUICtrl>("Edit Cost")->getValue().asInteger();;
// Invalid data - turn off the sale
if (price < 0)
{
sale_type = LLSaleInfo::FS_NOT;
price = 0;
}
sale_info.setSaleType(sale_type);
sale_info.setSalePrice(price);
}
else
{
sale_info.setSaleType(LLSaleInfo::FS_NOT);
}
if(sale_info != item->getSaleInfo()
&& item->isFinished())
{
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
// Force an update on the sale price at rez
if (item->getType() == LLAssetType::AT_OBJECT)
{
U32 flags = new_item->getFlags();
flags |= LLInventoryItemFlags::II_FLAGS_OBJECT_SLAM_SALE;
new_item->setFlags(flags);
}
new_item->setSaleInfo(sale_info);
if(mObjectID.isNull())
{
// This is in the agent's inventory.
new_item->updateServer(FALSE);
gInventory.updateItem(new_item);
gInventory.notifyObservers();
}
else
{
// This is in an object's contents.
LLViewerObject* object = gObjectList.findObject(mObjectID);
if(object)
{
object->updateInventory(
new_item,
TASK_INVENTORY_ITEM_KEY,
false);
}
}
}
else
{
// need to make sure we don't just follow the click
refresh();
}
}
LLInventoryItem* LLFloaterProperties::findItem() const
{
LLInventoryItem* item = NULL;
if(mObjectID.isNull())
{
// it is in agent inventory
item = gInventory.getItem(mItemID);
}
else
{
LLViewerObject* object = gObjectList.findObject(mObjectID);
if(object)
{
item = (LLInventoryItem*)object->getInventoryObject(mItemID);
}
}
return item;
}
//static
void LLFloaterProperties::dirtyAll()
{
LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("properties");
for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin();
iter != inst_list.end(); ++iter)
{
LLFloaterProperties* floater = dynamic_cast<LLFloaterProperties*>(*iter);
llassert(floater); // else cast failed - wrong type D:
if (floater)
{
floater->dirty();
}
}
}
///----------------------------------------------------------------------------
/// LLMultiProperties
///----------------------------------------------------------------------------
LLMultiProperties::LLMultiProperties()
: LLMultiFloater(LLSD())
{
// start with a small rect in the top-left corner ; will get resized
LLRect rect;
rect.setLeftTopAndSize(0, gViewerWindow->getWindowHeightScaled(), 20, 20);
setRect(rect);
LLFloater* last_floater = LLFloaterReg::getLastFloaterInGroup("properties");
if (last_floater)
{
stackWith(*last_floater);
}
setTitle(LLTrans::getString("MultiPropertiesTitle"));
buildTabContainer();
}
///----------------------------------------------------------------------------
/// Local function definitions
///----------------------------------------------------------------------------

View File

@ -1,98 +0,0 @@
/**
* @file llfloaterproperties.h
* @brief A floater which shows an inventory item's properties.
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLFLOATERPROPERTIES_H
#define LL_LLFLOATERPROPERTIES_H
#include <map>
#include "llmultifloater.h"
#include "lliconctrl.h"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFloaterProperties
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLButton;
class LLCheckBoxCtrl;
class LLInventoryItem;
class LLLineEditor;
class LLRadioGroup;
class LLTextBox;
class LLPropertiesObserver;
class LLFloaterProperties : public LLFloater
{
public:
LLFloaterProperties(const LLUUID& item_id);
/*virtual*/ ~LLFloaterProperties();
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
void setObjectID(const LLUUID& object_id) { mObjectID = object_id; }
void dirty() { mDirty = TRUE; }
void refresh();
static void dirtyAll();
protected:
// ui callbacks
void onClickCreator();
void onClickOwner();
void onCommitName();
void onCommitDescription();
void onCommitPermissions();
void onCommitSaleInfo();
void onCommitSaleType();
void updateSaleInfo();
LLInventoryItem* findItem() const;
void refreshFromItem(LLInventoryItem* item);
virtual void draw();
protected:
// The item id of the inventory item in question.
LLUUID mItemID;
// mObjectID will have a value if it is associated with a task in
// the world, and will be == LLUUID::null if it's in the agent
// inventory.
LLUUID mObjectID;
BOOL mDirty;
LLPropertiesObserver* mPropertiesObserver;
};
class LLMultiProperties : public LLMultiFloater
{
public:
LLMultiProperties();
};
#endif // LL_LLFLOATERPROPERTIES_H

View File

@ -90,6 +90,29 @@ void LLFloaterSidePanelContainer::closeFloater(bool app_quitting)
}
}
LLFloater* LLFloaterSidePanelContainer::getTopmostInventoryFloater()
{
LLFloater* topmost_floater = NULL;
S32 z_min = S32_MAX;
LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory");
for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
{
LLFloater* inventory_floater = (*iter);
if (inventory_floater && inventory_floater->getVisible())
{
S32 z_order = gFloaterView->getZOrder(inventory_floater);
if (z_order < z_min)
{
z_min = z_order;
topmost_floater = inventory_floater;
}
}
}
return topmost_floater;
}
LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_name, const LLSD& params)
{
LLView* view = findChildView(panel_name, true);

View File

@ -57,6 +57,8 @@ public:
LLPanel* openChildPanel(const std::string& panel_name, const LLSD& params);
static LLFloater* getTopmostInventoryFloater();
static void showPanel(const std::string& floater_name, const LLSD& key);
static void showPanel(const std::string& floater_name, const std::string& panel_name, const LLSD& key);

View File

@ -1,333 +0,0 @@
/**
* @file llfloatersimpleoutfitsnapshot.cpp
* @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, 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 "llfloatersimpleoutfitsnapshot.h"
#include "llfloaterreg.h"
#include "llimagefiltersmanager.h"
#include "llstatusbar.h" // can_afford_transaction()
#include "llnotificationsutil.h"
#include "llagentbenefits.h"
#include "llviewercontrol.h"
LLSimpleOutfitSnapshotFloaterView* gSimpleOutfitSnapshotFloaterView = NULL;
const S32 OUTFIT_SNAPSHOT_WIDTH = 256;
const S32 OUTFIT_SNAPSHOT_HEIGHT = 256;
static LLDefaultChildRegistry::Register<LLSimpleOutfitSnapshotFloaterView> r("simple_snapshot_outfit_floater_view");
///----------------------------------------------------------------------------
/// Class LLFloaterSimpleOutfitSnapshot::Impl
///----------------------------------------------------------------------------
LLSnapshotModel::ESnapshotFormat LLFloaterSimpleOutfitSnapshot::Impl::getImageFormat(LLFloaterSnapshotBase* floater)
{
return LLSnapshotModel::SNAPSHOT_FORMAT_PNG;
}
LLSnapshotModel::ESnapshotLayerType LLFloaterSimpleOutfitSnapshot::Impl::getLayerType(LLFloaterSnapshotBase* floater)
{
return LLSnapshotModel::SNAPSHOT_TYPE_COLOR;
}
void LLFloaterSimpleOutfitSnapshot::Impl::updateControls(LLFloaterSnapshotBase* floater)
{
LLSnapshotLivePreview* previewp = getPreviewView();
updateResolution(floater);
if (previewp)
{
previewp->setSnapshotType(LLSnapshotModel::ESnapshotType::SNAPSHOT_TEXTURE);
previewp->setSnapshotFormat(LLSnapshotModel::ESnapshotFormat::SNAPSHOT_FORMAT_PNG);
previewp->setSnapshotBufferType(LLSnapshotModel::ESnapshotLayerType::SNAPSHOT_TYPE_COLOR);
}
}
std::string LLFloaterSimpleOutfitSnapshot::Impl::getSnapshotPanelPrefix()
{
return "panel_outfit_snapshot_";
}
void LLFloaterSimpleOutfitSnapshot::Impl::updateResolution(void* data)
{
LLFloaterSimpleOutfitSnapshot *view = (LLFloaterSimpleOutfitSnapshot *)data;
if (!view)
{
llassert(view);
return;
}
S32 width = OUTFIT_SNAPSHOT_WIDTH;
S32 height = OUTFIT_SNAPSHOT_HEIGHT;
LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp)
{
S32 original_width = 0, original_height = 0;
previewp->getSize(original_width, original_height);
if (gSavedSettings.getBOOL("RenderHUDInSnapshot"))
{ //clamp snapshot resolution to window size when showing UI HUD in snapshot
width = llmin(width, gViewerWindow->getWindowWidthRaw());
height = llmin(height, gViewerWindow->getWindowHeightRaw());
}
llassert(width > 0 && height > 0);
previewp->setSize(width, height);
if (original_width != width || original_height != height)
{
// hide old preview as the aspect ratio could be wrong
checkAutoSnapshot(previewp, FALSE);
previewp->updateSnapshot(TRUE);
}
}
}
void LLFloaterSimpleOutfitSnapshot::Impl::setStatus(EStatus status, bool ok, const std::string& msg)
{
switch (status)
{
case STATUS_READY:
mFloater->setCtrlsEnabled(true);
break;
case STATUS_WORKING:
mFloater->setCtrlsEnabled(false);
break;
case STATUS_FINISHED:
mFloater->setCtrlsEnabled(true);
break;
}
mStatus = status;
}
///----------------------------------------------------------------re------------
/// Class LLFloaterSimpleOutfitSnapshot
///----------------------------------------------------------------------------
LLFloaterSimpleOutfitSnapshot::LLFloaterSimpleOutfitSnapshot(const LLSD& key)
: LLFloaterSnapshotBase(key),
mOutfitGallery(NULL)
{
impl = new Impl(this);
}
LLFloaterSimpleOutfitSnapshot::~LLFloaterSimpleOutfitSnapshot()
{
}
BOOL LLFloaterSimpleOutfitSnapshot::postBuild()
{
getChild<LLUICtrl>("save_btn")->setLabelArg("[UPLOAD_COST]", std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost()));
childSetAction("new_snapshot_btn", ImplBase::onClickNewSnapshot, this);
childSetAction("save_btn", boost::bind(&LLFloaterSimpleOutfitSnapshot::onSend, this));
childSetAction("cancel_btn", boost::bind(&LLFloaterSimpleOutfitSnapshot::onCancel, this));
mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
// create preview window
LLRect full_screen_rect = getRootView()->getRect();
LLSnapshotLivePreview::Params p;
p.rect(full_screen_rect);
LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
LLView* parent_view = gSnapshotFloaterView->getParent();
parent_view->removeChild(gSnapshotFloaterView);
// make sure preview is below snapshot floater
parent_view->addChild(previewp);
parent_view->addChild(gSnapshotFloaterView);
//move snapshot floater to special purpose snapshotfloaterview
gFloaterView->removeChild(this);
gSnapshotFloaterView->addChild(this);
impl->mPreviewHandle = previewp->getHandle();
previewp->setContainer(this);
impl->updateControls(this);
impl->setAdvanced(true);
impl->setSkipReshaping(true);
previewp->mKeepAspectRatio = FALSE;
previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect());
previewp->setAllowRenderUI(false);
return TRUE;
}
const S32 PREVIEW_OFFSET_X = 12;
const S32 PREVIEW_OFFSET_Y = 70;
void LLFloaterSimpleOutfitSnapshot::draw()
{
LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp && (previewp->isSnapshotActive() || previewp->getThumbnailLock()))
{
// don't render snapshot window in snapshot, even if "show ui" is turned on
return;
}
LLFloater::draw();
if (previewp && !isMinimized() && mThumbnailPlaceholder->getVisible())
{
if(previewp->getThumbnailImage())
{
bool working = impl->getStatus() == ImplBase::STATUS_WORKING;
const LLRect& thumbnail_rect = getThumbnailPlaceholderRect();
const S32 thumbnail_w = previewp->getThumbnailWidth();
const S32 thumbnail_h = previewp->getThumbnailHeight();
S32 offset_x = PREVIEW_OFFSET_X;
S32 offset_y = PREVIEW_OFFSET_Y;
gGL.matrixMode(LLRender::MM_MODELVIEW);
// Apply floater transparency to the texture unless the floater is focused.
F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
LLColor4 color = working ? LLColor4::grey4 : LLColor4::white;
gl_draw_scaled_image(offset_x, offset_y,
thumbnail_w, thumbnail_h,
previewp->getThumbnailImage(), color % alpha);
#if LL_DARWIN
std::string alpha_color = getTransparencyType() == TT_ACTIVE ? "OutfitSnapshotMacMask" : "OutfitSnapshotMacMask2";
#else
std::string alpha_color = getTransparencyType() == TT_ACTIVE ? "FloaterFocusBackgroundColor" : "DkGray";
#endif
previewp->drawPreviewRect(offset_x, offset_y, LLUIColorTable::instance().getColor(alpha_color));
gGL.pushUIMatrix();
LLUI::translate((F32) thumbnail_rect.mLeft, (F32) thumbnail_rect.mBottom);
mThumbnailPlaceholder->draw();
gGL.popUIMatrix();
}
}
impl->updateLayout(this);
}
void LLFloaterSimpleOutfitSnapshot::onOpen(const LLSD& key)
{
LLSnapshotLivePreview* preview = getPreviewView();
if (preview)
{
preview->updateSnapshot(TRUE);
}
focusFirstItem(FALSE);
gSnapshotFloaterView->setEnabled(TRUE);
gSnapshotFloaterView->setVisible(TRUE);
gSnapshotFloaterView->adjustToFitScreen(this, FALSE);
impl->updateControls(this);
impl->setStatus(ImplBase::STATUS_READY);
}
void LLFloaterSimpleOutfitSnapshot::onCancel()
{
closeFloater();
}
void LLFloaterSimpleOutfitSnapshot::onSend()
{
S32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
if (can_afford_transaction(expected_upload_cost))
{
saveTexture();
postSave();
}
else
{
LLSD args;
args["COST"] = llformat("%d", expected_upload_cost);
LLNotificationsUtil::add("ErrorPhotoCannotAfford", args);
inventorySaveFailed();
}
}
void LLFloaterSimpleOutfitSnapshot::postSave()
{
impl->setStatus(ImplBase::STATUS_WORKING);
}
// static
void LLFloaterSimpleOutfitSnapshot::update()
{
LLFloaterSimpleOutfitSnapshot* inst = findInstance();
if (inst != NULL)
{
inst->impl->updateLivePreview();
}
}
// static
LLFloaterSimpleOutfitSnapshot* LLFloaterSimpleOutfitSnapshot::findInstance()
{
return LLFloaterReg::findTypedInstance<LLFloaterSimpleOutfitSnapshot>("simple_outfit_snapshot");
}
// static
LLFloaterSimpleOutfitSnapshot* LLFloaterSimpleOutfitSnapshot::getInstance()
{
return LLFloaterReg::getTypedInstance<LLFloaterSimpleOutfitSnapshot>("simple_outfit_snapshot");
}
void LLFloaterSimpleOutfitSnapshot::saveTexture()
{
LLSnapshotLivePreview* previewp = getPreviewView();
if (!previewp)
{
llassert(previewp != NULL);
return;
}
if (mOutfitGallery)
{
mOutfitGallery->onBeforeOutfitSnapshotSave();
}
previewp->saveTexture(TRUE, getOutfitID().asString());
if (mOutfitGallery)
{
mOutfitGallery->onAfterOutfitSnapshotSave();
}
closeFloater();
}
///----------------------------------------------------------------------------
/// Class LLSimpleOutfitSnapshotFloaterView
///----------------------------------------------------------------------------
LLSimpleOutfitSnapshotFloaterView::LLSimpleOutfitSnapshotFloaterView(const Params& p) : LLFloaterView(p)
{
}
LLSimpleOutfitSnapshotFloaterView::~LLSimpleOutfitSnapshotFloaterView()
{
}

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