summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2025-04-25 18:57:58 +0300
committerAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2025-04-28 23:36:55 +0300
commit7bd18e256d70804f72d747ccc1e62c92679dd645 (patch)
tree014ef7b4884a293cdd3729243c2eafbe058ca0b6
parent1f3ba13a632a751cc3217cbe02d8aa2190df6b41 (diff)
viewerp#300 Fix inconsistency with copying textures vs pbr
-rw-r--r--indra/newview/llinventorymodel.cpp1
-rw-r--r--indra/newview/llpanelface.cpp462
-rw-r--r--indra/newview/llpanelface.h3
-rw-r--r--indra/newview/lltexturectrl.cpp3
4 files changed, 312 insertions, 157 deletions
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 0a2d938bd0..cf1efd283a 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -2768,6 +2768,7 @@ bool LLInventoryModel::loadSkeleton(
bool is_cache_obsolete = false;
if (loadFromFile(inventory_filename, categories, items, categories_to_update, is_cache_obsolete))
{
+ LL_PROFILE_ZONE_NAMED("loadFromFile");
// We were able to find a cache of files. So, use what we
// found to generate a set of categories we should add. We
// will go through each category loaded and if the version
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 6e0b0d252e..2e57e2a5bd 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -4009,6 +4009,85 @@ void LLPanelFace::onPasteColor(LLViewerObject* objectp, S32 te)
}
}
+void set_item_availability(
+ const LLUUID& id,
+ LLSD& dest,
+ const std::string& modifier,
+ bool is_creator,
+ std::map<LLUUID, LLUUID> &asset_item_map,
+ LLViewerObject* objectp)
+{
+ if (id.isNull())
+ {
+ return;
+ }
+
+ LLUUID item_id;
+ bool from_library = get_is_predefined_texture(id);
+ bool full_perm = from_library;
+ full_perm |= is_creator;
+
+ if (!full_perm)
+ {
+ std::map<LLUUID, LLUUID>::iterator iter = asset_item_map.find(id);
+ if (iter != asset_item_map.end())
+ {
+ item_id = iter->second;
+ }
+ else
+ {
+ // What this does is simply searches inventory for item with same asset id,
+ // as result it is Hightly unreliable, leaves little control to user, borderline hack
+ // but there are little options to preserve permissions - multiple inventory
+ // items might reference same asset and inventory search is expensive.
+ bool no_transfer = false;
+ if (objectp->getInventoryItemByAsset(id))
+ {
+ no_transfer = !objectp->getInventoryItemByAsset(id)->getIsFullPerm();
+ }
+ item_id = get_copy_free_item_by_asset_id(id, no_transfer);
+ // record value to avoid repeating inventory search when possible
+ asset_item_map[id] = item_id;
+ }
+ }
+
+ if (item_id.notNull() && gInventory.isObjectDescendentOf(item_id, gInventory.getLibraryRootFolderID()))
+ {
+ full_perm = true;
+ from_library = true;
+ }
+
+ dest[modifier + "itemfullperm"] = full_perm;
+ dest[modifier + "fromlibrary"] = from_library;
+
+ // If full permission object, texture is free to copy,
+ // but otherwise we need to check inventory and extract permissions
+ //
+ // Normally we care only about restrictions for current user and objects
+ // don't inherit any 'next owner' permissions from texture, so there is
+ // no need to record item id if full_perm==true
+ if (!full_perm && item_id.notNull())
+ {
+ LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
+ if (itemp)
+ {
+ LLPermissions item_permissions = itemp->getPermissions();
+ if (item_permissions.allowOperationBy(PERM_COPY,
+ gAgent.getID(),
+ gAgent.getGroupID()))
+ {
+ dest[modifier + "itemid"] = item_id;
+ dest[modifier + "itemfullperm"] = itemp->getIsFullPerm();
+ if (!itemp->isFinished())
+ {
+ // needed for dropTextureAllFaces
+ LLInventoryModelBackgroundFetch::instance().start(item_id, false);
+ }
+ }
+ }
+ }
+}
+
void LLPanelFace::onCopyTexture()
{
LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
@@ -4046,6 +4125,7 @@ void LLPanelFace::onCopyTexture()
if (tep)
{
LLSD te_data;
+ LLUUID pbr_id = objectp->getRenderMaterialID(te);
// asLLSD() includes media
te_data["te"] = tep->asLLSD();
@@ -4054,21 +4134,20 @@ void LLPanelFace::onCopyTexture()
te_data["te"]["bumpshiny"] = tep->getBumpShiny();
te_data["te"]["bumpfullbright"] = tep->getBumpShinyFullbright();
te_data["te"]["texgen"] = tep->getTexGen();
- te_data["te"]["pbr"] = objectp->getRenderMaterialID(te);
+ te_data["te"]["pbr"] = pbr_id;
if (tep->getGLTFMaterialOverride() != nullptr)
{
te_data["te"]["pbr_override"] = tep->getGLTFMaterialOverride()->asJSON();
}
- if (te_data["te"].has("imageid"))
+ if (te_data["te"].has("imageid") || pbr_id.notNull())
{
- LLUUID item_id;
- LLUUID id = te_data["te"]["imageid"].asUUID();
- bool from_library = get_is_predefined_texture(id);
- bool full_perm = from_library;
+ LLUUID img_id = te_data["te"]["imageid"].asUUID();
+ bool pbr_from_library = false;
+ bool pbr_full_perm = false;
+ bool is_creator = false;
- if (!full_perm
- && objectp->permCopy()
+ if (objectp->permCopy()
&& objectp->permTransfer()
&& objectp->permModify())
{
@@ -4078,66 +4157,31 @@ void LLPanelFace::onCopyTexture()
std::string creator_app_link;
LLUUID creator_id;
LLSelectMgr::getInstance()->selectGetCreator(creator_id, creator_app_link);
- full_perm = objectp->mOwnerID == creator_id;
+ is_creator = objectp->mOwnerID == creator_id;
}
- if (id.notNull() && !full_perm)
+ // check permissions for blin-phong/diffuse image and for pbr asset
+ if (img_id.notNull())
{
- std::map<LLUUID, LLUUID>::iterator iter = asset_item_map.find(id);
- if (iter != asset_item_map.end())
- {
- item_id = iter->second;
- }
- else
- {
- // What this does is simply searches inventory for item with same asset id,
- // as result it is Hightly unreliable, leaves little control to user, borderline hack
- // but there are little options to preserve permissions - multiple inventory
- // items might reference same asset and inventory search is expensive.
- bool no_transfer = false;
- if (objectp->getInventoryItemByAsset(id))
- {
- no_transfer = !objectp->getInventoryItemByAsset(id)->getIsFullPerm();
- }
- item_id = get_copy_free_item_by_asset_id(id, no_transfer);
- // record value to avoid repeating inventory search when possible
- asset_item_map[id] = item_id;
- }
+ set_item_availability(img_id, te_data["te"], "img", is_creator, asset_item_map, objectp);
}
-
- if (item_id.notNull() && gInventory.isObjectDescendentOf(item_id, gInventory.getLibraryRootFolderID()))
+ if (pbr_id.notNull())
{
- full_perm = true;
- from_library = true;
- }
+ set_item_availability(pbr_id, te_data["te"], "pbr", is_creator, asset_item_map, objectp);
- {
- te_data["te"]["itemfullperm"] = full_perm;
- te_data["te"]["fromlibrary"] = from_library;
-
- // If full permission object, texture is free to copy,
- // but otherwise we need to check inventory and extract permissions
- //
- // Normally we care only about restrictions for current user and objects
- // don't inherit any 'next owner' permissions from texture, so there is
- // no need to record item id if full_perm==true
- if (!full_perm && !from_library && item_id.notNull())
+ // permissions for overrides
+ // Overrides do not permit no-copy textures
+ LLGLTFMaterial* override = tep->getGLTFMaterialOverride();
+ if (override != nullptr)
{
- LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
- if (itemp)
+ for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
{
- LLPermissions item_permissions = itemp->getPermissions();
- if (item_permissions.allowOperationBy(PERM_COPY,
- gAgent.getID(),
- gAgent.getGroupID()))
+ LLUUID& texture_id = override->mTextureId[i];
+ if (texture_id.notNull())
{
- te_data["te"]["imageitemid"] = item_id;
- te_data["te"]["itemfullperm"] = itemp->getIsFullPerm();
- if (!itemp->isFinished())
- {
- // needed for dropTextureAllFaces
- LLInventoryModelBackgroundFetch::instance().start(item_id, false);
- }
+ const std::string prefix = "pbr" + std::to_string(i);
+ te_data["te"][prefix + "imageid"] = texture_id;
+ set_item_availability(texture_id, te_data["te"], prefix, is_creator, asset_item_map, objectp);
}
}
}
@@ -4201,6 +4245,44 @@ void LLPanelFace::onCopyTexture()
}
}
+bool get_full_permission(const LLSD& te, const std::string &prefix)
+{
+ return te.has(prefix + "itemfullperm") && te[prefix+"itemfullperm"].asBoolean();
+}
+
+bool LLPanelFace::validateInventoryItem(const LLSD& te, const std::string& prefix)
+{
+ if (te.has(prefix + "itemid"))
+ {
+ LLUUID item_id = te[prefix + "itemid"].asUUID();
+ if (item_id.notNull())
+ {
+ LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
+ if (!itemp)
+ {
+ // image might be in object's inventory, but it can be not up to date
+ LLSD notif_args;
+ static std::string reason = getString("paste_error_inventory_not_found");
+ notif_args["REASON"] = reason;
+ LLNotificationsUtil::add("FacePasteFailed", notif_args);
+ return false;
+ }
+ }
+ }
+ else
+ {
+ // Item was not found on 'copy' stage
+ // Since this happened at copy, might be better to either show this
+ // at copy stage or to drop clipboard here
+ LLSD notif_args;
+ static std::string reason = getString("paste_error_inventory_not_found");
+ notif_args["REASON"] = reason;
+ LLNotificationsUtil::add("FacePasteFailed", notif_args);
+ return false;
+ }
+ return true;
+}
+
void LLPanelFace::onPasteTexture()
{
if (!mClipboardParams.has("texture"))
@@ -4265,39 +4347,49 @@ void LLPanelFace::onPasteTexture()
for (; iter != end; ++iter)
{
const LLSD& te_data = *iter;
- if (te_data.has("te") && te_data["te"].has("imageid"))
+ if (te_data.has("te"))
{
- bool full_perm = te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean();
- full_perm_object &= full_perm;
- if (!full_perm)
+ if (te_data["te"].has("imageid"))
{
- if (te_data["te"].has("imageitemid"))
+ bool full_perm = get_full_permission(te_data["te"], "img");
+ full_perm_object &= full_perm;
+ if (!full_perm)
{
- LLUUID item_id = te_data["te"]["imageitemid"].asUUID();
- if (item_id.notNull())
+ if (!validateInventoryItem(te_data["te"], "img"))
{
- LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
- if (!itemp)
- {
- // image might be in object's inventory, but it can be not up to date
- LLSD notif_args;
- static std::string reason = getString("paste_error_inventory_not_found");
- notif_args["REASON"] = reason;
- LLNotificationsUtil::add("FacePasteFailed", notif_args);
- return;
- }
+ return;
}
}
- else
+ }
+ if (te_data["te"].has("pbr"))
+ {
+ bool full_perm = get_full_permission(te_data["te"], "pbr");
+ full_perm_object &= full_perm;
+ if (!full_perm)
{
- // Item was not found on 'copy' stage
- // Since this happened at copy, might be better to either show this
- // at copy stage or to drop clipboard here
- LLSD notif_args;
- static std::string reason = getString("paste_error_inventory_not_found");
- notif_args["REASON"] = reason;
- LLNotificationsUtil::add("FacePasteFailed", notif_args);
- return;
+ if (!validateInventoryItem(te_data["te"], "pbr"))
+ {
+ return;
+ }
+ }
+ if (te_data["te"].has("pbr_override"))
+ {
+ for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
+ {
+ const std::string prefix = "pbr" + std::to_string(i);
+ if (te_data["te"].has(prefix + "imageid"))
+ {
+ bool full_perm = get_full_permission(te_data["te"], prefix);
+ full_perm_object &= full_perm;
+ if (!full_perm)
+ {
+ if (!validateInventoryItem(te_data["te"], prefix))
+ {
+ return;
+ }
+ }
+ }
+ }
}
}
}
@@ -4322,6 +4414,71 @@ void LLPanelFace::onPasteTexture()
selected_objects->applyToTEs(&navigate_home_func);
}
+void get_item_and_permissions(const LLUUID &id, LLViewerInventoryItem*& itemp, bool& full_perm, bool& from_library, const LLSD &data, const std::string &prefix)
+{
+ full_perm = get_full_permission(data, prefix);
+ from_library = data.has(prefix + "fromlibrary") && data.get(prefix + "fromlibrary").asBoolean();
+ LLViewerInventoryItem* itemp_res = NULL;
+
+ if (data.has(prefix + "itemid"))
+ {
+ LLUUID item_id = data.get(prefix + "itemid").asUUID();
+ if (item_id.notNull())
+ {
+ LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
+ if (itemp && itemp->isFinished())
+ {
+ // dropTextureAllFaces will fail if incomplete
+ itemp_res = itemp;
+ }
+ else
+ {
+ // Theoretically shouldn't happend, but if it does happen, we
+ // might need to add a notification to user that paste will fail
+ // since inventory isn't fully loaded
+ LL_WARNS() << "Item " << item_id << " is incomplete, paste might fail silently." << LL_ENDL;
+ }
+ }
+ }
+
+ // for case when item got removed from inventory after we pressed 'copy'
+ // or texture got pasted into previous object
+ if (!itemp_res && !full_perm)
+ {
+ // Due to checks for imageitemid in LLPanelFace::onPasteTexture() this should no longer be reachable.
+ LL_INFOS() << "Item " << data.get(prefix + "itemid").asUUID() << " no longer in inventory." << LL_ENDL;
+ // Todo: fix this, we are often searching same texture multiple times (equal to number of faces)
+ // Perhaps just mPanelFace->onPasteTexture(objectp, te, &asset_to_item_id_map); ? Not pretty, but will work
+ LLViewerInventoryCategory::cat_array_t cats;
+ LLViewerInventoryItem::item_array_t items;
+ LLAssetIDMatches asset_id_matches(id);
+ gInventory.collectDescendentsIf(LLUUID::null,
+ cats,
+ items,
+ LLInventoryModel::INCLUDE_TRASH,
+ asset_id_matches);
+
+ // Extremely unreliable and perfomance unfriendly.
+ // But we need this to check permissions and it is how texture control finds items
+ for (S32 i = 0; i < items.size(); i++)
+ {
+ LLViewerInventoryItem* itemp = items[i];
+ if (itemp && itemp->isFinished())
+ {
+ // dropTextureAllFaces will fail if incomplete
+ LLPermissions item_permissions = itemp->getPermissions();
+ if (item_permissions.allowOperationBy(PERM_COPY,
+ gAgent.getID(),
+ gAgent.getGroupID()))
+ {
+ itemp_res = itemp;
+ break; // first match
+ }
+ }
+ }
+ }
+}
+
void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te)
{
LLSD te_data;
@@ -4345,77 +4502,22 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te)
if (te_data.has("te"))
{
// Texture
- bool full_perm = te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean();
- bool from_library = te_data["te"].has("fromlibrary") && te_data["te"]["fromlibrary"].asBoolean();
if (te_data["te"].has("imageid"))
{
+ bool img_full_perm = false;
+ bool img_from_library = false;
const LLUUID& imageid = te_data["te"]["imageid"].asUUID(); //texture or asset id
- LLViewerInventoryItem* itemp_res = NULL;
+ LLViewerInventoryItem* img_itemp_res = NULL;
- if (te_data["te"].has("imageitemid"))
- {
- LLUUID item_id = te_data["te"]["imageitemid"].asUUID();
- if (item_id.notNull())
- {
- LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
- if (itemp && itemp->isFinished())
- {
- // dropTextureAllFaces will fail if incomplete
- itemp_res = itemp;
- }
- else
- {
- // Theoretically shouldn't happend, but if it does happen, we
- // might need to add a notification to user that paste will fail
- // since inventory isn't fully loaded
- LL_WARNS() << "Item " << item_id << " is incomplete, paste might fail silently." << LL_ENDL;
- }
- }
- }
- // for case when item got removed from inventory after we pressed 'copy'
- // or texture got pasted into previous object
- if (!itemp_res && !full_perm)
- {
- // Due to checks for imageitemid in LLPanelFace::onPasteTexture() this should no longer be reachable.
- LL_INFOS() << "Item " << te_data["te"]["imageitemid"].asUUID() << " no longer in inventory." << LL_ENDL;
- // Todo: fix this, we are often searching same texture multiple times (equal to number of faces)
- // Perhaps just mPanelFace->onPasteTexture(objectp, te, &asset_to_item_id_map); ? Not pretty, but will work
- LLViewerInventoryCategory::cat_array_t cats;
- LLViewerInventoryItem::item_array_t items;
- LLAssetIDMatches asset_id_matches(imageid);
- gInventory.collectDescendentsIf(LLUUID::null,
- cats,
- items,
- LLInventoryModel::INCLUDE_TRASH,
- asset_id_matches);
-
- // Extremely unreliable and perfomance unfriendly.
- // But we need this to check permissions and it is how texture control finds items
- for (S32 i = 0; i < items.size(); i++)
- {
- LLViewerInventoryItem* itemp = items[i];
- if (itemp && itemp->isFinished())
- {
- // dropTextureAllFaces will fail if incomplete
- LLPermissions item_permissions = itemp->getPermissions();
- if (item_permissions.allowOperationBy(PERM_COPY,
- gAgent.getID(),
- gAgent.getGroupID()))
- {
- itemp_res = itemp;
- break; // first match
- }
- }
- }
- }
+ get_item_and_permissions(imageid, img_itemp_res, img_full_perm, img_from_library, te_data["te"], "img");
- if (itemp_res)
+ if (img_itemp_res)
{
if (te == -1) // all faces
{
LLToolDragAndDrop::dropTextureAllFaces(objectp,
- itemp_res,
- from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT,
+ img_itemp_res,
+ img_from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT,
LLUUID::null,
false);
}
@@ -4423,15 +4525,15 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te)
{
LLToolDragAndDrop::dropTextureOneFace(objectp,
te,
- itemp_res,
- from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT,
+ img_itemp_res,
+ img_from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT,
LLUUID::null,
false,
0);
}
}
// not an inventory item or no complete items
- else if (full_perm)
+ else if (img_full_perm)
{
// Either library, local or existed as fullperm when user made a copy
LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(imageid, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
@@ -4459,17 +4561,65 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te)
// PBR/GLTF
if (te_data["te"].has("pbr"))
{
- objectp->setRenderMaterialID(te, te_data["te"]["pbr"].asUUID(), false /*managing our own update*/);
- tep->setGLTFRenderMaterial(nullptr);
- tep->setGLTFMaterialOverride(nullptr);
+ const LLUUID pbr_id = te_data["te"]["pbr"].asUUID();
+ bool pbr_full_perm = false;
+ bool pbr_from_library = false;
+ LLViewerInventoryItem* pbr_itemp_res = NULL;
+
+ get_item_and_permissions(pbr_id, pbr_itemp_res, pbr_full_perm, pbr_from_library, te_data["te"], "pbr");
+ bool allow = true;
+
+ // check overrides first since they don't need t be moved to inventory
if (te_data["te"].has("pbr_override"))
{
- LLGLTFMaterialList::queueApply(objectp, te, te_data["te"]["pbr"].asUUID(), te_data["te"]["pbr_override"]);
+ for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
+ {
+ const std::string prefix = "pbr" + std::to_string(i);
+ if (te_data["te"].has(prefix + "imageid"))
+ {
+ LLUUID tex_id = te_data["te"][prefix + "imageid"];
+
+ bool full_perm = false;
+ bool from_library = false;
+ LLViewerInventoryItem* itemp_res = NULL;
+ get_item_and_permissions(tex_id, itemp_res, full_perm, from_library, te_data["te"], prefix);
+ allow = full_perm;
+ if (!allow) break;
+ }
+ }
+ }
+
+ if (allow && pbr_itemp_res)
+ {
+ if (pbr_itemp_res)
+ {
+ allow = LLToolDragAndDrop::handleDropMaterialProtections(
+ objectp,
+ pbr_itemp_res,
+ pbr_from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT,
+ pbr_id);
+ }
+ else
+ {
+ allow = pbr_full_perm;
+ }
}
- else
+
+ if (allow)
{
- LLGLTFMaterialList::queueApply(objectp, te, te_data["te"]["pbr"].asUUID());
+ objectp->setRenderMaterialID(te, te_data["te"]["pbr"].asUUID(), false /*managing our own update*/);
+ tep->setGLTFRenderMaterial(nullptr);
+ tep->setGLTFMaterialOverride(nullptr);
+
+ if (te_data["te"].has("pbr_override"))
+ {
+ LLGLTFMaterialList::queueApply(objectp, te, te_data["te"]["pbr"].asUUID(), te_data["te"]["pbr_override"]);
+ }
+ else
+ {
+ LLGLTFMaterialList::queueApply(objectp, te, te_data["te"]["pbr"].asUUID());
+ }
}
}
else
diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h
index 6e0d34cbd6..b59f7434af 100644
--- a/indra/newview/llpanelface.h
+++ b/indra/newview/llpanelface.h
@@ -264,6 +264,9 @@ public: // needs to be accessible to selection manager
void onCopyTexture();
void onPasteTexture();
void onPasteTexture(LLViewerObject* objectp, S32 te);
+private:
+ // for copy/paste operations
+ bool validateInventoryItem(const LLSD& te, const std::string& prefix);
protected:
void menuDoToSelected(const LLSD& userdata);
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 35057a910a..20127f5f27 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -88,7 +88,8 @@ bool get_is_predefined_texture(LLUUID asset_id)
|| asset_id == DEFAULT_OBJECT_NORMAL
|| asset_id == BLANK_OBJECT_NORMAL
|| asset_id == IMG_WHITE
- || asset_id == LLUUID(SCULPT_DEFAULT_TEXTURE))
+ || asset_id == LLUUID(SCULPT_DEFAULT_TEXTURE)
+ || asset_id == BLANK_MATERIAL_ASSET_ID)
{
return true;
}