diff options
author | Cosmic Linden <cosmic@lindenlab.com> | 2023-11-02 09:55:44 -0700 |
---|---|---|
committer | Cosmic Linden <cosmic@lindenlab.com> | 2023-11-09 13:54:41 -0800 |
commit | 711354c2f526421b7cd2918f584731624a9995e5 (patch) | |
tree | 831a6bc08e80a87a593d03bc48036d5e045adfe9 | |
parent | b3384a057d9556b2429a9c5847e8e1240103585a (diff) |
SL-20553: Save material button in build floater now depends on agent inventory rather than object inventory
-rw-r--r-- | indra/newview/llmaterialeditor.cpp | 92 | ||||
-rw-r--r-- | indra/newview/llpanelface.cpp | 65 | ||||
-rw-r--r-- | indra/newview/llpanelface.h | 6 |
3 files changed, 142 insertions, 21 deletions
diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 5be1aa08ab..bae4afb7e6 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -38,6 +38,7 @@ #include "llgltfmateriallist.h" #include "llinventorymodel.h" #include "llinventoryobserver.h" +#include "llinventoryfunctions.h" #include "lllocalgltfmaterials.h" #include "llnotificationsutil.h" #include "lltexturectrl.h" @@ -1796,8 +1797,49 @@ void LLMaterialEditor::loadLive() } } +namespace +{ + // Which inventory to consult for item permissions + enum class ItemSource + { + // Consult the permissions of the item in the object's inventory. If + // the item is not present, then usage of the asset is allowed. + OBJECT, + // Consult the permissions of the item in the agent's inventory. If + // the item is not present, then usage of the asset is not allowed. + AGENT + }; + + class LLAssetIDMatchesWithPerms : public LLInventoryCollectFunctor + { + public: + LLAssetIDMatchesWithPerms(const LLUUID& asset_id, const std::vector<PermissionBit>& ops) : mAssetID(asset_id), mOps(ops) {} + virtual ~LLAssetIDMatchesWithPerms() {} + bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) + { + if (!item || item->getAssetUUID() != mAssetID) + { + return false; + } + LLPermissions item_permissions = item->getPermissions(); + for (PermissionBit op : mOps) + { + if (!gAgent.allowOperation(op, item_permissions, GP_OBJECT_MANIPULATE)) + { + return false; + } + } + return true; + } + + protected: + LLUUID mAssetID; + std::vector<PermissionBit> mOps; + }; +}; + // *NOTE: permissions_out includes user preferences for new item creation (LLFloaterPerms) -bool can_use_objects_material(LLSelectedTEGetMatData& func, const std::vector<PermissionBit>& ops, LLPermissions& permissions_out, LLViewerInventoryItem*& item_out) +bool can_use_objects_material(LLSelectedTEGetMatData& func, const std::vector<PermissionBit>& ops, const ItemSource item_source, LLPermissions& permissions_out, LLViewerInventoryItem*& item_out) { if (!LLMaterialEditor::capabilitiesAvailable()) { @@ -1830,19 +1872,45 @@ bool can_use_objects_material(LLSelectedTEGetMatData& func, const std::vector<Pe } } - item_out = selected_object->getInventoryItemByAsset(func.mMaterialId); - - LLPermissions item_permissions; - if (item_out) + // Look for the item to base permissions off of + item_out = nullptr; + if (func.mMaterialId != LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID) { - item_permissions.set(item_out->getPermissions()); - for (PermissionBit op : ops) + LLAssetIDMatchesWithPerms item_has_perms(func.mMaterialId, ops); + if (item_source == ItemSource::OBJECT) { - if (!gAgent.allowOperation(op, item_permissions, GP_OBJECT_MANIPULATE)) + item_out = selected_object->getInventoryItemByAsset(func.mMaterialId); + if (item_out && !item_has_perms(nullptr, item_out)) { return false; } } + else + { + llassert(item_source == ItemSource::AGENT); + + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + gInventory.collectDescendentsIf(LLUUID::null, + cats, + items, + // *NOTE: PBRPickerAgentListener will need + // to be changed if checking the trash is + // disabled + LLInventoryModel::INCLUDE_TRASH, + item_has_perms); + if (items.empty()) + { + return false; + } + item_out = items[0]; + } + } + + LLPermissions item_permissions; + if (item_out) + { + item_permissions = item_out->getPermissions(); // Update flags for new owner if (!item_permissions.setOwnerAndGroup(LLUUID::null, gAgent.getID(), LLUUID::null, true)) { @@ -1913,7 +1981,7 @@ bool LLMaterialEditor::canModifyObjectsMaterial() LLSelectedTEGetMatData func(true); LLPermissions permissions; LLViewerInventoryItem* item_out; - return can_use_objects_material(func, std::vector({PERM_MODIFY}), permissions, item_out); + return can_use_objects_material(func, std::vector({PERM_MODIFY}), ItemSource::OBJECT, permissions, item_out); } bool LLMaterialEditor::canSaveObjectsMaterial() @@ -1921,7 +1989,7 @@ bool LLMaterialEditor::canSaveObjectsMaterial() LLSelectedTEGetMatData func(true); LLPermissions permissions; LLViewerInventoryItem* item_out; - return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), permissions, item_out); + return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), ItemSource::AGENT, permissions, item_out); } bool LLMaterialEditor::canClipboardObjectsMaterial() @@ -1947,7 +2015,7 @@ bool LLMaterialEditor::canClipboardObjectsMaterial() LLSelectedTEGetMatData func(true); LLPermissions permissions; LLViewerInventoryItem* item_out; - return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY, PERM_TRANSFER}), permissions, item_out); + return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY, PERM_TRANSFER}), ItemSource::OBJECT, permissions, item_out); } void LLMaterialEditor::saveObjectsMaterialAs() @@ -1955,7 +2023,7 @@ void LLMaterialEditor::saveObjectsMaterialAs() LLSelectedTEGetMatData func(true); LLPermissions permissions; LLViewerInventoryItem* item = nullptr; - bool allowed = can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), permissions, item); + bool allowed = can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), ItemSource::AGENT, permissions, item); if (!allowed) { LL_WARNS("MaterialEditor") << "Failed to save GLTF material from object" << LL_ENDL; diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 9150b89de3..02c00e7f87 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -1880,15 +1880,55 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) } } +// One-off listener that updates the build floater UI when the agent inventory adds or removes an item +class PBRPickerAgentListener : public LLInventoryObserver +{ +protected: + bool mChangePending = true; +public: + PBRPickerAgentListener() : LLInventoryObserver() + { + gInventory.addObserver(this); + } + + const bool isListening() + { + return mChangePending; + } + + void changed(U32 mask) override + { + if (!(mask & (ADD | REMOVE))) + { + return; + } + + if (gFloaterTools) + { + gFloaterTools->dirty(); + } + gInventory.removeObserver(this); + mChangePending = false; + } + + ~PBRPickerAgentListener() override + { + gInventory.removeObserver(this); + mChangePending = false; + + LLInventoryObserver::~LLInventoryObserver(); + } +}; + // One-off listener that updates the build floater UI when the prim inventory updates -class PBRPickerItemListener : public LLVOInventoryListener +class PBRPickerObjectListener : public LLVOInventoryListener { protected: LLViewerObject* mObjectp; bool mChangePending = true; public: - PBRPickerItemListener(LLViewerObject* object) + PBRPickerObjectListener(LLViewerObject* object) : mObjectp(object) { registerVOInventoryListener(mObjectp, nullptr); @@ -1912,7 +1952,7 @@ public: mChangePending = false; } - ~PBRPickerItemListener() + ~PBRPickerObjectListener() { removeVOInventoryListener(); mChangePending = false; @@ -1931,9 +1971,9 @@ void LLPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material, // pbr material LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control"); + LLUUID pbr_id; if (pbr_ctrl) { - LLUUID pbr_id; LLSelectedTE::getPbrMaterialId(pbr_id, identical_pbr, has_pbr_material, has_faces_without_pbr); pbr_ctrl->setTentative(identical_pbr ? FALSE : TRUE); @@ -1956,14 +1996,25 @@ void LLPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material, if (objectp->isInventoryPending()) { // Reuse the same listener when possible - if (!mInventoryListener || !mInventoryListener->isListeningFor(objectp)) + if (!mVOInventoryListener || !mVOInventoryListener->isListeningFor(objectp)) { - mInventoryListener = std::make_unique<PBRPickerItemListener>(objectp); + mVOInventoryListener = std::make_unique<PBRPickerObjectListener>(objectp); } } else { - mInventoryListener = nullptr; + mVOInventoryListener = nullptr; + } + if (!identical_pbr || pbr_id.isNull() || pbr_id == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID) + { + mAgentInventoryListener = nullptr; + } + else + { + if (!mAgentInventoryListener || !mAgentInventoryListener->isListening()) + { + mAgentInventoryListener = std::make_unique<PBRPickerAgentListener>(); + } } const bool show_pbr = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR && mComboMatMedia->getEnabled(); diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index d36662c11b..5ca6a95699 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -53,7 +53,8 @@ class LLMaterialID; class LLMediaCtrl; class LLMenuButton; -class PBRPickerItemListener; +class PBRPickerAgentListener; +class PBRPickerObjectListener; // Represents an edit for use in replicating the op across one or more materials in the selection set. // @@ -508,7 +509,8 @@ private: static Selection sMaterialOverrideSelection; - std::unique_ptr<PBRPickerItemListener> mInventoryListener; + std::unique_ptr<PBRPickerAgentListener> mAgentInventoryListener; + std::unique_ptr<PBRPickerObjectListener> mVOInventoryListener; public: #if defined(DEF_GET_MAT_STATE) |