summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCosmic Linden <cosmic@lindenlab.com>2023-07-25 14:52:56 -0700
committerCosmic Linden <cosmic@lindenlab.com>2023-08-11 16:31:00 -0700
commit7bf6103ad95c281c2ed680c9eb9b07cc584ddc91 (patch)
tree58511786208b21d572478b5ae8280927cc8ec01b
parentca6f465088be904fa5b85297396227f905792a3b (diff)
SL-20024: (WIP) (not tested) Improved behavior for saving material to inventory. Check perms, keep perms.
-rw-r--r--indra/llinventory/llpermissions.h4
-rw-r--r--indra/newview/llmaterialeditor.cpp164
-rw-r--r--indra/newview/llmaterialeditor.h8
-rw-r--r--indra/newview/llpanelface.cpp2
4 files changed, 129 insertions, 49 deletions
diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h
index 27252f7b97..32fae844fb 100644
--- a/indra/llinventory/llpermissions.h
+++ b/indra/llinventory/llpermissions.h
@@ -251,7 +251,9 @@ public:
BOOL setNextOwnerBits(const LLUUID& agent, const LLUUID& group, BOOL set, PermissionMask bits);
// This is currently only used in the Viewer to handle calling cards
- // where the creator is actually used to store the target. Use with care.
+ // where the creator is actually used to store the target.
+ // It is also used for saving a GLTF material on a prim.
+ // Use with care.
void setCreator(const LLUUID& creator) { mCreator = creator; }
//
diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
index b30f94e145..6e043ecee5 100644
--- a/indra/newview/llmaterialeditor.cpp
+++ b/indra/newview/llmaterialeditor.cpp
@@ -237,6 +237,7 @@ struct LLSelectedTEGetMatData : public LLSelectedTEFunctor
LLUUID mTexEmissiveId;
LLUUID mTexNormalId;
LLUUID mObjectId;
+ LLViewerObject* mObject = nullptr;
S32 mObjectTE;
LLUUID mMaterialId;
LLPointer<LLGLTFMaterial> mMaterial;
@@ -293,6 +294,7 @@ bool LLSelectedTEGetMatData::apply(LLViewerObject* objectp, S32 te_index)
mTexNormalId = tex_normal_id;
mObjectTE = te_index;
mObjectId = objectp->getID();
+ mObject = objectp;
mFirst = false;
}
else
@@ -1194,7 +1196,9 @@ bool LLMaterialEditor::saveIfNeeded()
{
//make a new inventory item
std::string res_desc = buildMaterialDescription();
- createInventoryItem(buffer, mMaterialName, res_desc);
+ LLPermissions local_permissions;
+ local_permissions.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null);
+ createInventoryItem(buffer, mMaterialName, res_desc, local_permissions);
// We do not update floater with uploaded asset yet, so just close it.
closeFloater();
@@ -1288,7 +1292,7 @@ bool LLMaterialEditor::updateInventoryItem(const std::string &buffer, const LLUU
return true;
}
-void LLMaterialEditor::createInventoryItem(const std::string &buffer, const std::string &name, const std::string &desc)
+void LLMaterialEditor::createInventoryItem(const std::string &buffer, const std::string &name, const std::string &desc, const LLPermissions& owner_permissions)
{
// gen a new uuid for this asset
LLTransactionID tid;
@@ -1299,7 +1303,7 @@ void LLMaterialEditor::createInventoryItem(const std::string &buffer, const std:
create_inventory_item(gAgent.getID(), gAgent.getSessionID(), parent, tid, name, desc,
LLAssetType::AT_MATERIAL, LLInventoryType::IT_MATERIAL, subtype, next_owner_perm,
- new LLBoostFuncInventoryCallback([output = buffer](LLUUID const& inv_item_id)
+ new LLBoostFuncInventoryCallback([output = buffer, owner_permissions](LLUUID const& inv_item_id)
{
LLViewerInventoryItem* item = gInventory.getItem(inv_item_id);
if (item)
@@ -1309,8 +1313,15 @@ void LLMaterialEditor::createInventoryItem(const std::string &buffer, const std:
if (perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms("Materials")
|| perm.getMaskGroup() != LLFloaterPerms::getGroupPerms("Materials"))
{
- perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Materials"));
- perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Materials"));
+ LLPermissions floater_perm;
+ floater_perm.set(perm);
+ floater_perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Materials"));
+ floater_perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Materials"));
+ perm.accumulate(floater_perm);
+ perm.accumulate(owner_permissions);
+ // TODO: Decide if these are needed
+ perm.setCreator(owner_permissions.getCreator());
+ perm.setLastOwner(owner_permissions.getLastOwner());
item->setPermissions(perm);
@@ -1794,55 +1805,112 @@ void LLMaterialEditor::loadLive()
}
}
-void LLMaterialEditor::saveObjectsMaterialAs()
+// *NOTE: permissions_out ignores user preferences for new item creation
+// (LLFloaterPerms). Those are applied later on in
+// LLMaterialEditor::createInventoryItem.
+bool can_save_objects_material(LLSelectedTEGetMatData& func, LLPermissions& permissions_out)
{
- LLSelectedTEGetMatData func(false);
LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func, true /*first applicable*/);
- saveMaterialAs(func.mMaterial, func.mLocalMaterial);
-}
-void LLMaterialEditor::savePickedMaterialAs()
-{
- LLPickInfo pick = LLToolPie::getInstance()->getPick();
- if (pick.mPickType != LLPickInfo::PICK_OBJECT || !pick.getObject())
+ LLViewerObject* selected_object = func.mObject;
+ llassert(selected_object); // Note the function name
+ const LLViewerInventoryItem* item = selected_object->getInventoryItemByAsset(func.mMaterialId);
+
+ LLPermissions item_permissions;
+ const bool previous_item_owned = item && item->getPermissions().getLastOwner().notNull();
+ if (item)
{
- return;
+ item_permissions.set(item->getPermissions());
+ if (!gAgent.allowOperation(PERM_MODIFY, item_permissions, GP_OBJECT_MANIPULATE))
+ {
+ return false;
+ }
+ if (!gAgent.allowOperation(PERM_COPY, item_permissions, GP_OBJECT_MANIPULATE))
+ {
+ return false;
+ }
+ if (!item_permissions.setOwnerAndGroup(LLUUID::null, gAgent.getID(), LLUUID::null, true))
+ {
+ llassert(false);
+ return false;
+ }
}
-
- LLPointer<LLGLTFMaterial> render_material;
- LLPointer<LLLocalGLTFMaterial> local_material;
-
- LLViewerObject *objectp = pick.getObject();
- LLUUID mat_id = objectp->getRenderMaterialID(pick.mObjectFace);
- if (mat_id.notNull() && objectp->permCopy())
+ else
{
- // Try a face user picked first
- // (likely the only method we need, but in such case
- // enable_object_save_gltf_material will need to check this)
- LLTextureEntry *tep = objectp->getTE(pick.mObjectFace);
- LLGLTFMaterial *mat = tep->getGLTFMaterial();
- LLLocalGLTFMaterial *local_mat = dynamic_cast<LLLocalGLTFMaterial*>(mat);
+ item_permissions.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null);
+ }
- if (local_mat)
+ LLPermissions* object_permissions_p = LLSelectMgr::getInstance()->findObjectPermissions(selected_object);
+ LLPermissions object_permissions;
+ const bool previous_object_owned = object_permissions_p && object_permissions_p->getLastOwner().notNull();
+ if (object_permissions_p)
+ {
+ object_permissions.set(*object_permissions_p);
+ if (!gAgent.allowOperation(PERM_MODIFY, object_permissions, GP_OBJECT_MANIPULATE))
{
- local_material = local_mat;
+ return false;
+ }
+ if (!gAgent.allowOperation(PERM_COPY, object_permissions, GP_OBJECT_MANIPULATE))
+ {
+ return false;
+ }
+ if (!object_permissions.setOwnerAndGroup(LLUUID::null, gAgent.getID(), LLUUID::null, true))
+ {
+ llassert(false);
+ return false;
}
- render_material = tep->getGLTFRenderMaterial();
}
else
{
- // Find an applicable material.
- // Do this before showing message, because
- // message is going to drop selection.
- LLSelectedTEGetMatData func(false);
- LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func, true /*first applicable*/);
- local_material = func.mLocalMaterial;
- render_material = func.mMaterial;
+ object_permissions.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null);
}
- saveMaterialAs(render_material, local_material);
+ permissions_out.set(item_permissions);
+ permissions_out.accumulate(object_permissions);
+
+ if (previous_item_owned != previous_object_owned)
+ {
+ // Likely ownership history conflict. Prefer the item history. Fall
+ // back to object history if no associated item.
+ if (previous_item_owned)
+ {
+ permissions_out.setCreator(item_permissions.getCreator());
+ permissions_out.setLastOwner(item_permissions.getLastOwner());
+ }
+ else if (previous_object_owned)
+ {
+ permissions_out.setCreator(object_permissions.getCreator());
+ permissions_out.setLastOwner(object_permissions.getLastOwner());
+ }
+ }
+
+ llassert(permissions_out.getOwner() == gAgent.getID());
+ llassert(permissions_out.getCreator().notNull());
+ llassert(permissions_out.getGroup().isNull());
+
+ return true;
+}
+
+bool LLMaterialEditor::canSaveObjectsMaterial()
+{
+ LLSelectedTEGetMatData func(false);
+ LLPermissions permissions;
+ return can_save_objects_material(func, permissions);
}
-void LLMaterialEditor::saveMaterialAs(const LLGLTFMaterial* render_material, const LLLocalGLTFMaterial *local_material)
+void LLMaterialEditor::saveObjectsMaterialAs()
+{
+ LLSelectedTEGetMatData func(false);
+ LLPermissions permissions;
+ bool allowed = can_save_objects_material(func, permissions);
+ if (!allowed)
+ {
+ LL_WARNS("MaterialEditor") << "Failed to save GLTF material from object" << LL_ENDL;
+ return;
+ }
+ saveMaterialAs(func.mMaterial, func.mLocalMaterial, permissions);
+}
+
+void LLMaterialEditor::saveMaterialAs(const LLGLTFMaterial* render_material, const LLLocalGLTFMaterial *local_material, const LLPermissions& permissions)
{
if (local_material)
{
@@ -1918,10 +1986,20 @@ void LLMaterialEditor::saveMaterialAs(const LLGLTFMaterial* render_material, con
LLSD args;
args["DESC"] = LLTrans::getString("New Material");
- LLNotificationsUtil::add("SaveMaterialAs", args, payload, boost::bind(&LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback, _1, _2));
+ // At this point, last owner, etc should be set. LLFloaterPerms will be honored later on
+ if (local_material)
+ {
+ LLPermissions local_permissions;
+ local_permissions.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null);
+ LLNotificationsUtil::add("SaveMaterialAs", args, payload, boost::bind(&LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback, _1, _2, local_permissions));
+ }
+ else
+ {
+ LLNotificationsUtil::add("SaveMaterialAs", args, payload, boost::bind(&LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback, _1, _2, permissions));
+ }
}
-void LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback(const LLSD& notification, const LLSD& response)
+void LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback(const LLSD& notification, const LLSD& response, const LLPermissions& permissions)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
@@ -1936,7 +2014,7 @@ void LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback(const LLSD& notificati
LLSDSerialize::serialize(asset, str, LLSDSerialize::LLSD_BINARY);
std::string new_name = response["message"].asString();
- createInventoryItem(str.str(), new_name, std::string());
+ createInventoryItem(str.str(), new_name, std::string(), permissions);
}
}
@@ -2710,7 +2788,7 @@ bool LLMaterialEditor::setFromSelection()
if (func.mMaterial.notNull())
{
setFromGLTFMaterial(func.mMaterial);
- LLViewerObject* selected_object = selected_objects->getFirstSelectedObject(NULL);
+ LLViewerObject* selected_object = func.mObject;
const LLViewerInventoryItem* item = selected_object->getInventoryItemByAsset(func.mMaterialId);
const bool allow_modify = !item || canModify(selected_object, item);
setEnableEditing(allow_modify);
diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h
index 6f674a4170..5ee42f65f4 100644
--- a/indra/newview/llmaterialeditor.h
+++ b/indra/newview/llmaterialeditor.h
@@ -112,9 +112,9 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
static void updateLive(const LLUUID &object_id, S32 te);
static void loadLive();
+ static bool canSaveObjectsMaterial();
static void saveObjectsMaterialAs();
- static void savePickedMaterialAs();
- static void onSaveObjectsMaterialAsMsgCallback(const LLSD& notification, const LLSD& response);
+ static void onSaveObjectsMaterialAsMsgCallback(const LLSD& notification, const LLSD& response, const LLPermissions& permissions);
static void onLoadComplete(const LLUUID& asset_uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status);
@@ -229,10 +229,10 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
static bool capabilitiesAvailable();
private:
- static void saveMaterialAs(const LLGLTFMaterial *render_material, const LLLocalGLTFMaterial *local_material);
+ static void saveMaterialAs(const LLGLTFMaterial *render_material, const LLLocalGLTFMaterial *local_material, const LLPermissions& permissions);
static bool updateInventoryItem(const std::string &buffer, const LLUUID &item_id, const LLUUID &task_id);
- static void createInventoryItem(const std::string &buffer, const std::string &name, const std::string &desc);
+ static void createInventoryItem(const std::string &buffer, const std::string &name, const std::string &desc, const LLPermissions& owner_permissions);
void setFromGLTFMaterial(LLGLTFMaterial* mat);
bool setFromSelection();
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index e91b14a453..b9daf19284 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -1856,7 +1856,7 @@ void LLPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material,
getChildView("pbr_from_inventory")->setEnabled(editable && has_pbr_capabilities);
getChildView("edit_selected_pbr")->setEnabled(editable && has_pbr_material && !has_faces_without_pbr && has_pbr_capabilities);
- getChildView("save_selected_pbr")->setEnabled(objectp->permCopy() && has_pbr_material && identical_pbr && has_pbr_capabilities);
+ getChildView("save_selected_pbr")->setEnabled(LLMaterialEditor::canSaveObjectsMaterial() && identical_pbr);
const bool show_pbr = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR && mComboMatMedia->getEnabled();
if (show_pbr)