Merge branch 'DRTVWR-559' into DRTVWR-583
commit
bd9c0a2e65
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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>()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#ifndef LL_TEXTUREMANAGERBRIDGE_H
|
||||
#define LL_TEXTUREMANAGERBRIDGE_H
|
||||
|
||||
#include "llavatarappearancedefines.h"
|
||||
#include "llpointer.h"
|
||||
#include "llgltexture.h"
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
|||
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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] );
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -320,6 +320,7 @@ private:
|
|||
LLUIColor mTabsFlashingColor;
|
||||
S32 mTabIconCtrlPad;
|
||||
bool mUseTabEllipses;
|
||||
LLFrameTimer mMouseDownTimer;
|
||||
};
|
||||
|
||||
#endif // LL_TABCONTAINER_H
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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*/)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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()))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -986,6 +986,8 @@ void LLFloaterIMSessionTab::onOpen(const LLSD& key)
|
|||
}
|
||||
|
||||
mInputButtonPanel->setVisible(isTornOff());
|
||||
|
||||
setFocus(TRUE);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
///----------------------------------------------------------------------------
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue