From ca6f465088be904fa5b85297396227f905792a3b Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Mon, 24 Jul 2023 16:16:52 -0700 Subject: SL-20024: Disable material editor on prim when contained material is no mod --- indra/newview/llmaterialeditor.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indra/newview/llmaterialeditor.cpp') diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 3a0e64985c..b30f94e145 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -238,6 +238,7 @@ struct LLSelectedTEGetMatData : public LLSelectedTEFunctor LLUUID mTexNormalId; LLUUID mObjectId; S32 mObjectTE; + LLUUID mMaterialId; LLPointer mMaterial; LLPointer mLocalMaterial; }; @@ -259,6 +260,7 @@ bool LLSelectedTEGetMatData::apply(LLViewerObject* objectp, S32 te_index) return false; } LLUUID mat_id = objectp->getRenderMaterialID(te_index); + mMaterialId = mat_id; bool can_use = mIsOverride ? objectp->permModify() : objectp->permCopy(); LLTextureEntry *tep = objectp->getTE(te_index); // We might want to disable this entirely if at least @@ -2708,7 +2710,10 @@ bool LLMaterialEditor::setFromSelection() if (func.mMaterial.notNull()) { setFromGLTFMaterial(func.mMaterial); - setEnableEditing(true); + LLViewerObject* selected_object = selected_objects->getFirstSelectedObject(NULL); + const LLViewerInventoryItem* item = selected_object->getInventoryItemByAsset(func.mMaterialId); + const bool allow_modify = !item || canModify(selected_object, item); + setEnableEditing(allow_modify); } else { -- cgit v1.3 From 7bf6103ad95c281c2ed680c9eb9b07cc584ddc91 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Tue, 25 Jul 2023 14:52:56 -0700 Subject: SL-20024: (WIP) (not tested) Improved behavior for saving material to inventory. Check perms, keep perms. --- indra/llinventory/llpermissions.h | 4 +- indra/newview/llmaterialeditor.cpp | 164 +++++++++++++++++++++++++++---------- indra/newview/llmaterialeditor.h | 8 +- indra/newview/llpanelface.cpp | 2 +- 4 files changed, 129 insertions(+), 49 deletions(-) (limited to 'indra/newview/llmaterialeditor.cpp') 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 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 render_material; - LLPointer 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(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) -- cgit v1.3 From a5d318567cc5c3e8f2f86fce1132f5883014e14e Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 28 Jul 2023 17:29:09 -0700 Subject: SL-20024: (WIP) (untested) Fix GLTF material permissions in some more edge cases --- indra/newview/llmaterialeditor.cpp | 139 ++++++++++++++++++++----------------- indra/newview/llmaterialeditor.h | 1 + indra/newview/llpanelface.cpp | 57 +++++++++++++-- indra/newview/llpanelface.h | 6 ++ 4 files changed, 134 insertions(+), 69 deletions(-) (limited to 'indra/newview/llmaterialeditor.cpp') diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 6e043ecee5..af40c9e931 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -293,8 +293,8 @@ bool LLSelectedTEGetMatData::apply(LLViewerObject* objectp, S32 te_index) mTexEmissiveId = tex_emissive_id; mTexNormalId = tex_normal_id; mObjectTE = te_index; - mObjectId = objectp->getID(); mObject = objectp; + mObjectId = objectp->getID(); mFirst = false; } else @@ -322,6 +322,7 @@ bool LLSelectedTEGetMatData::apply(LLViewerObject* objectp, S32 te_index) LLGLTFMaterial *mat = tep->getGLTFMaterial(); LLLocalGLTFMaterial *local_mat = dynamic_cast(mat); + mObject = objectp; if (local_mat) { mLocalMaterial = local_mat; @@ -1297,38 +1298,39 @@ void LLMaterialEditor::createInventoryItem(const std::string &buffer, const std: // gen a new uuid for this asset LLTransactionID tid; tid.generate(); // timestamp-based randomization + uniquification - U32 next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Materials"); + LLPermissions final_perm; + { + final_perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); + + LLPermissions floater_perm; + floater_perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); + floater_perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Materials")); + floater_perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Materials")); + floater_perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("Materials")); + + final_perm.accumulate(floater_perm); + final_perm.accumulate(owner_permissions); + } + // NOTE: create_inventory_item doesn't allow presetting some permissions. + // The rest will be fixed after the callback. LLUUID parent = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_MATERIAL); const U8 subtype = NO_INV_SUBTYPE; // TODO maybe use AT_SETTINGS and LLSettingsType::ST_MATERIAL ? 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, owner_permissions](LLUUID const& inv_item_id) + LLAssetType::AT_MATERIAL, LLInventoryType::IT_MATERIAL, subtype, final_perm.getMaskNextOwner(), + new LLBoostFuncInventoryCallback([output = buffer, final_perm](LLUUID const& inv_item_id) { LLViewerInventoryItem* item = gInventory.getItem(inv_item_id); if (item) { // create_inventory_item doesn't allow presetting some permissions, fix it now LLPermissions perm = item->getPermissions(); - if (perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms("Materials") - || perm.getMaskGroup() != 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()); + perm.accumulate(final_perm); + item->setPermissions(perm); - item->setPermissions(perm); - - item->updateServer(FALSE); - gInventory.updateItem(item); - gInventory.notifyObservers(); - } + item->updateServer(FALSE); + gInventory.updateItem(item); + gInventory.notifyObservers(); } // from reference in LLSettingsVOBase::createInventoryItem()/updateInventoryItem() @@ -1805,29 +1807,47 @@ void LLMaterialEditor::loadLive() } } -// *NOTE: permissions_out ignores user preferences for new item creation -// (LLFloaterPerms). Those are applied later on in +// *NOTE: permissions_out ignores user preferences for new item creation. See +// LLFloaterPerms. Preferences are applied later on in // LLMaterialEditor::createInventoryItem. -bool can_save_objects_material(LLSelectedTEGetMatData& func, LLPermissions& permissions_out) +bool can_use_objects_material(LLSelectedTEGetMatData& func, const std::vector& ops, LLPermissions& permissions_out) { + if (!LLMaterialEditor::capabilitiesAvailable()) + { + return false; + } + LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func, true /*first applicable*/); LLViewerObject* selected_object = func.mObject; - llassert(selected_object); // Note the function name + if (!selected_object) + { + // LLSelectedTEGetMatData can fail if there are no selected faces + // with materials, but we expect at least some object is selected. + llassert(LLSelectMgr::getInstance()->getSelection()->getFirstObject()); + return false; + } + for (PermissionBit op : ops) + { + if (op == PERM_MODIFY && selected_object->isPermanentEnforced()) + { + return false; + } + } + const LLViewerInventoryItem* item = selected_object->getInventoryItemByAsset(func.mMaterialId); LLPermissions item_permissions; - const bool previous_item_owned = item && item->getPermissions().getLastOwner().notNull(); if (item) { 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)) + for (PermissionBit op : ops) { - return false; + if (!gAgent.allowOperation(op, item_permissions, GP_OBJECT_MANIPULATE)) + { + return false; + } } + // Update flags for new owner if (!item_permissions.setOwnerAndGroup(LLUUID::null, gAgent.getID(), LLUUID::null, true)) { llassert(false); @@ -1839,20 +1859,21 @@ bool can_save_objects_material(LLSelectedTEGetMatData& func, LLPermissions& perm item_permissions.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); } - LLPermissions* object_permissions_p = LLSelectMgr::getInstance()->findObjectPermissions(selected_object); + // Use root object for permissions checking + LLViewerObject* root_object = selected_object->getRootEdit(); + LLPermissions* object_permissions_p = LLSelectMgr::getInstance()->findObjectPermissions(root_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)) + for (PermissionBit op : ops) { - return false; - } - if (!gAgent.allowOperation(PERM_COPY, object_permissions, GP_OBJECT_MANIPULATE)) - { - return false; + if (!gAgent.allowOperation(op, object_permissions, GP_OBJECT_MANIPULATE)) + { + return false; + } } + // Update flags for new owner if (!object_permissions.setOwnerAndGroup(LLUUID::null, gAgent.getID(), LLUUID::null, true)) { llassert(false); @@ -1865,43 +1886,34 @@ bool can_save_objects_material(LLSelectedTEGetMatData& func, LLPermissions& perm } permissions_out.set(item_permissions); + // *NOTE: A close inspection of LLPermissions::accumulate shows that + // conflicting UUIDs will be unset. This is acceptable behavior for now. + // The server doesn't allow us to create an item while claiming someone + // else was the creator/previous owner. 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::canModifyObjectsMaterial() +{ + LLSelectedTEGetMatData func(false); + LLPermissions permissions; + return can_use_objects_material(func, std::vector({PERM_MODIFY}), permissions); +} + bool LLMaterialEditor::canSaveObjectsMaterial() { LLSelectedTEGetMatData func(false); LLPermissions permissions; - return can_save_objects_material(func, permissions); + return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), permissions); } void LLMaterialEditor::saveObjectsMaterialAs() { LLSelectedTEGetMatData func(false); LLPermissions permissions; - bool allowed = can_save_objects_material(func, permissions); + bool allowed = can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), permissions); if (!allowed) { LL_WARNS("MaterialEditor") << "Failed to save GLTF material from object" << LL_ENDL; @@ -1986,7 +1998,6 @@ void LLMaterialEditor::saveMaterialAs(const LLGLTFMaterial* render_material, con LLSD args; args["DESC"] = LLTrans::getString("New Material"); - // At this point, last owner, etc should be set. LLFloaterPerms will be honored later on if (local_material) { LLPermissions local_permissions; diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h index 5ee42f65f4..54e59fcdf8 100644 --- a/indra/newview/llmaterialeditor.h +++ b/indra/newview/llmaterialeditor.h @@ -112,6 +112,7 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener static void updateLive(const LLUUID &object_id, S32 te); static void loadLive(); + static bool canModifyObjectsMaterial(); static bool canSaveObjectsMaterial(); static void saveObjectsMaterialAs(); static void onSaveObjectsMaterialAsMsgCallback(const LLSD& notification, const LLSD& response, const LLPermissions& permissions); diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index b9daf19284..90271b75b2 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -51,6 +51,7 @@ #include "llinventorymodelbackgroundfetch.h" #include "llfloatermediasettings.h" #include "llfloaterreg.h" +#include "llfloatertools.h" #include "lllineeditor.h" #include "llmaterialmgr.h" #include "llmaterialeditor.h" @@ -77,6 +78,7 @@ #include "llviewerregion.h" #include "llviewerstats.h" #include "llvovolume.h" +#include "llvoinventorylistener.h" #include "lluictrlfactory.h" #include "llpluginclassmedia.h" #include "llviewertexturelist.h"// Update sel manager as to which channel we're editing so it can reflect the correct overlay UI @@ -1834,13 +1836,48 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) } } +// One-off listener that updates the build floater UI when the prim inventory updates +class PBRPickerItemListener : public LLVOInventoryListener +{ +protected: + LLViewerObject* mObjectp; +public: + + PBRPickerItemListener(LLViewerObject* object) + : mObjectp(object) + { + registerVOInventoryListener(mObjectp, nullptr); + } + + const LLViewerObject* const getObject() { return mObjectp; } + + void inventoryChanged(LLViewerObject* object, + LLInventoryObject::object_list_t* inventory, + S32 serial_num, + void* user_data) override + { + if (gFloaterTools) + { + gFloaterTools->dirty(); + } + removeVOInventoryListener(); + } + + ~PBRPickerItemListener() + { + removeVOInventoryListener(); + } +}; + void LLPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material, bool& has_faces_without_pbr, bool force_set_values) { has_pbr_material = false; - const bool editable = objectp->permModify() && !objectp->isPermanentEnforced(); bool has_pbr_capabilities = LLMaterialEditor::capabilitiesAvailable(); bool identical_pbr = true; + const bool settable = has_pbr_capabilities && objectp->permModify() && !objectp->isPermanentEnforced(); + const bool editable = LLMaterialEditor::canModifyObjectsMaterial(); + const bool saveable = LLMaterialEditor::canSaveObjectsMaterial(); // pbr material LLTextureCtrl* pbr_ctrl = findChild("pbr_control"); @@ -1850,13 +1887,23 @@ void LLPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material, LLSelectedTE::getPbrMaterialId(pbr_id, identical_pbr, has_pbr_material, has_faces_without_pbr); pbr_ctrl->setTentative(identical_pbr ? FALSE : TRUE); - pbr_ctrl->setEnabled(editable && has_pbr_capabilities); + pbr_ctrl->setEnabled(settable); pbr_ctrl->setImageAssetID(pbr_id); } - 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(LLMaterialEditor::canSaveObjectsMaterial() && identical_pbr); + const bool inventory_pending = objectp->isInventoryPending(); + getChildView("pbr_from_inventory")->setEnabled(settable); + getChildView("edit_selected_pbr")->setEnabled(editable && !inventory_pending && !has_faces_without_pbr); + getChildView("save_selected_pbr")->setEnabled(saveable && !inventory_pending && identical_pbr); + // TODO: Vet inventory updates and memory management + if (inventory_pending && (!mInventoryListener || mInventoryListener->getObject() != objectp)) + { + mInventoryListener = std::make_unique(objectp); + } + else + { + mInventoryListener = nullptr; + } const bool show_pbr = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR && mComboMatMedia->getEnabled(); if (show_pbr) diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index e2d9f65e58..d737665ad0 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -35,6 +35,8 @@ #include "lltextureentry.h" #include "llselectmgr.h" +#include + class LLButton; class LLCheckBoxCtrl; class LLColorSwatchCtrl; @@ -51,6 +53,8 @@ class LLMaterialID; class LLMediaCtrl; class LLMenuButton; +class PBRPickerItemListener; + // Represents an edit for use in replicating the op across one or more materials in the selection set. // // The apply function optionally performs the edit which it implements @@ -503,6 +507,8 @@ private: static Selection sMaterialOverrideSelection; + std::unique_ptr mInventoryListener; + public: #if defined(DEF_GET_MAT_STATE) #undef DEF_GET_MAT_STATE -- cgit v1.3 From 76c8cca9363c0ef55bf66a2bbff4a86a02f37acf Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Mon, 7 Aug 2023 14:26:33 -0700 Subject: SL-20024: Fix author attributions not transferring for saved object materials, fix item not renamed --- indra/newview/llmaterialeditor.cpp | 178 ++++++++++++++++++++++++++---------- indra/newview/llmaterialeditor.h | 6 +- indra/newview/llviewerinventory.cpp | 63 +++++++++++++ indra/newview/llviewerinventory.h | 4 + indra/newview/llviewerobject.cpp | 11 +++ indra/newview/llviewerobject.h | 2 + 6 files changed, 214 insertions(+), 50 deletions(-) (limited to 'indra/newview/llmaterialeditor.cpp') diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index af40c9e931..bc3d5b88ab 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -37,6 +37,7 @@ #include "llfilesystem.h" #include "llgltfmateriallist.h" #include "llinventorymodel.h" +#include "llinventoryobserver.h" #include "lllocalgltfmaterials.h" #include "llnotificationsutil.h" #include "lltexturectrl.h" @@ -323,6 +324,7 @@ bool LLSelectedTEGetMatData::apply(LLViewerObject* objectp, S32 te_index) LLLocalGLTFMaterial *local_mat = dynamic_cast(mat); mObject = objectp; + mObjectId = objectp->getID(); if (local_mat) { mLocalMaterial = local_mat; @@ -1293,44 +1295,38 @@ 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, const LLPermissions& owner_permissions) +// Callback intended for when an item is copied from an object's inventory and +// needs to be modified to reflect the new asset/name. For example: When saving +// a modified material to the inventory from the build floater. +class LLObjectsMaterialItemCallback : public LLInventoryCallback { - // gen a new uuid for this asset - LLTransactionID tid; - tid.generate(); // timestamp-based randomization + uniquification - LLPermissions final_perm; +public: + LLObjectsMaterialItemCallback(const LLPermissions& permissions, const std::string& asset_data, const std::string& new_name) + : mPermissions(permissions), + mAssetData(asset_data), + mNewName(new_name) { - final_perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); - - LLPermissions floater_perm; - floater_perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); - floater_perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Materials")); - floater_perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Materials")); - floater_perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("Materials")); - - final_perm.accumulate(floater_perm); - final_perm.accumulate(owner_permissions); } - // NOTE: create_inventory_item doesn't allow presetting some permissions. - // The rest will be fixed after the callback. - LLUUID parent = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_MATERIAL); - const U8 subtype = NO_INV_SUBTYPE; // TODO maybe use AT_SETTINGS and LLSettingsType::ST_MATERIAL ? - create_inventory_item(gAgent.getID(), gAgent.getSessionID(), parent, tid, name, desc, - LLAssetType::AT_MATERIAL, LLInventoryType::IT_MATERIAL, subtype, final_perm.getMaskNextOwner(), - new LLBoostFuncInventoryCallback([output = buffer, final_perm](LLUUID const& inv_item_id) + void fire(const LLUUID& inv_item_id) override { LLViewerInventoryItem* item = gInventory.getItem(inv_item_id); - if (item) + if (!item) { - // create_inventory_item doesn't allow presetting some permissions, fix it now - LLPermissions perm = item->getPermissions(); - perm.accumulate(final_perm); - item->setPermissions(perm); + return; + } - item->updateServer(FALSE); - gInventory.updateItem(item); - gInventory.notifyObservers(); + // create_inventory_item/copy_inventory_item don't allow presetting some permissions, fix it now + item->setPermissions(mPermissions); + item->updateServer(FALSE); + gInventory.updateItem(item); + gInventory.notifyObservers(); + + if (item->getName() != mNewName) + { + LLSD updates; + updates["name"] = mNewName; + update_inventory_item(inv_item_id, updates, NULL); } // from reference in LLSettingsVOBase::createInventoryItem()/updateInventoryItem() @@ -1338,7 +1334,7 @@ void LLMaterialEditor::createInventoryItem(const std::string &buffer, const std: std::make_shared( inv_item_id, LLAssetType::AT_MATERIAL, - output, + mAssetData, [](LLUUID item_id, LLUUID new_asset_id, LLUUID new_item_id, LLSD response) { // done callback @@ -1357,8 +1353,25 @@ void LLMaterialEditor::createInventoryItem(const std::string &buffer, const std: } LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo); } - }) - ); + } +private: + LLPermissions mPermissions; + std::string mAssetData; + std::string mNewName; +}; + +void LLMaterialEditor::createInventoryItem(const std::string &buffer, const std::string &name, const std::string &desc, const LLPermissions& permissions) +{ + // gen a new uuid for this asset + LLTransactionID tid; + tid.generate(); // timestamp-based randomization + uniquification + LLUUID parent = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_MATERIAL); + const U8 subtype = NO_INV_SUBTYPE; // TODO maybe use AT_SETTINGS and LLSettingsType::ST_MATERIAL ? + + LLPointer cb = new LLObjectsMaterialItemCallback(permissions, buffer, name); + create_inventory_item(gAgent.getID(), gAgent.getSessionID(), parent, tid, name, desc, + LLAssetType::AT_MATERIAL, LLInventoryType::IT_MATERIAL, subtype, permissions.getMaskNextOwner(), + cb); } void LLMaterialEditor::finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId) @@ -1807,10 +1820,8 @@ void LLMaterialEditor::loadLive() } } -// *NOTE: permissions_out ignores user preferences for new item creation. See -// LLFloaterPerms. Preferences are applied later on in -// LLMaterialEditor::createInventoryItem. -bool can_use_objects_material(LLSelectedTEGetMatData& func, const std::vector& ops, LLPermissions& permissions_out) +// *NOTE: permissions_out includes user preferences for new item creation (LLFloaterPerms) +bool can_use_objects_material(LLSelectedTEGetMatData& func, const std::vector& ops, LLPermissions& permissions_out, LLViewerInventoryItem*& item_out) { if (!LLMaterialEditor::capabilitiesAvailable()) { @@ -1834,12 +1845,12 @@ bool can_use_objects_material(LLSelectedTEGetMatData& func, const std::vectorgetInventoryItemByAsset(func.mMaterialId); + item_out = selected_object->getInventoryItemByAsset(func.mMaterialId); LLPermissions item_permissions; - if (item) + if (item_out) { - item_permissions.set(item->getPermissions()); + item_permissions.set(item_out->getPermissions()); for (PermissionBit op : ops) { if (!gAgent.allowOperation(op, item_permissions, GP_OBJECT_MANIPULATE)) @@ -1885,12 +1896,19 @@ bool can_use_objects_material(LLSelectedTEGetMatData& func, const std::vectorgetUUID())); + } + else + { + LLNotificationsUtil::add("SaveMaterialAs", args, payload, boost::bind(&LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback, _1, _2, permissions)); + } } } +// static +void LLMaterialEditor::onCopyObjectsMaterialAsMsgCallback(const LLSD& notification, const LLSD& response, const LLPermissions& permissions, const LLUUID& object_id, const LLUUID& item_id) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == option) + { + LLSD asset; + asset["version"] = LLGLTFMaterial::ASSET_VERSION; + asset["type"] = LLGLTFMaterial::ASSET_TYPE; + // This is the string serialized from LLGLTFMaterial::asJSON + asset["data"] = notification["payload"]["data"]; + + std::ostringstream str; + LLSDSerialize::serialize(asset, str, LLSDSerialize::LLSD_BINARY); + + LLViewerObject* object = gObjectList.findObject(object_id); + if (!object) + { + return; + } + const LLInventoryItem* item = object->getInventoryItem(item_id); + if (!item) + { + return; + } + + std::string new_name = response["message"].asString(); + LLInventoryObject::correctInventoryName(new_name); + if (new_name.empty()) + { + return; + } + + const LLUUID destination_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL); + + // TODO: Test + // TODO: Rename the item + LLPointer cb = new LLObjectsMaterialItemCallback(permissions, str.str(), new_name); + // NOTE: This should be an item copy. Saving a material to an inventory should be disabled when the associated material is no-copy. + move_or_copy_inventory_from_object(destination_id, + object_id, + item_id, + cb); + } +} + +// static void LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback(const LLSD& notification, const LLSD& response, const LLPermissions& permissions) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); @@ -2025,6 +2102,11 @@ void LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback(const LLSD& notificati LLSDSerialize::serialize(asset, str, LLSDSerialize::LLSD_BINARY); std::string new_name = response["message"].asString(); + LLInventoryObject::correctInventoryName(new_name); + if (new_name.empty()) + { + return; + } createInventoryItem(str.str(), new_name, std::string(), permissions); } } diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h index 54e59fcdf8..2176f493a9 100644 --- a/indra/newview/llmaterialeditor.h +++ b/indra/newview/llmaterialeditor.h @@ -38,6 +38,7 @@ class LLGLTFMaterial; class LLLocalGLTFMaterial; class LLTextureCtrl; class LLTextBox; +class LLViewerInventoryItem; namespace tinygltf { @@ -115,6 +116,7 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener static bool canModifyObjectsMaterial(); static bool canSaveObjectsMaterial(); static void saveObjectsMaterialAs(); + static void onCopyObjectsMaterialAsMsgCallback(const LLSD& notification, const LLSD& response, const LLPermissions& permissions, const LLUUID& object_id, const LLUUID& item_id); 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); @@ -230,10 +232,10 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener static bool capabilitiesAvailable(); private: - static void saveMaterialAs(const LLGLTFMaterial *render_material, const LLLocalGLTFMaterial *local_material, const LLPermissions& permissions); + static void saveObjectsMaterialAs(const LLGLTFMaterial *render_material, const LLLocalGLTFMaterial *local_material, const LLPermissions& permissions, const LLUUID& object_id /* = LLUUID::null */, LLViewerInventoryItem* item /* = nullptr */); 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, const LLPermissions& owner_permissions); + static void createInventoryItem(const std::string &buffer, const std::string &name, const std::string &desc, const LLPermissions& permissions); void setFromGLTFMaterial(LLGLTFMaterial* mat); bool setFromSelection(); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 518967709d..b722e715b6 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1604,6 +1604,69 @@ void copy_inventory_from_notecard(const LLUUID& destination_id, } } +void move_or_copy_inventory_from_object(const LLUUID& destination_id, + const LLUUID& object_id, + const LLUUID& item_id, + LLPointer cb) +{ + // TODO: Implement + + LLViewerObject* object = gObjectList.findObject(object_id); + if (!object) + { + return; + } + const LLInventoryItem* item = object->getInventoryItem(item_id); + if (!item) + { + return; + } + + class LLItemAddedObserver : public LLInventoryObserver + { + public: + LLItemAddedObserver(const LLUUID& copied_asset_id, LLPointer cb) + : LLInventoryObserver(), + mAssetId(copied_asset_id), + mCallback(cb) + { + } + + void changed(U32 mask) override + { + if((mask & (LLInventoryObserver::ADD)) == 0) + { + return; + } + for (const LLUUID& changed_id : gInventory.getChangedIDs()) + { + LLViewerInventoryItem* changed_item = gInventory.getItem(changed_id); + if (changed_item->getAssetUUID() == mAssetId) + { + changeComplete(changed_item->getUUID()); + return; + } + } + } + + private: + void changeComplete(const LLUUID& item_id) + { + mCallback->fire(item_id); + gInventory.removeObserver(this); + delete this; + } + + LLUUID mAssetId; + LLPointer mCallback; + }; + + const LLUUID& asset_id = item->getAssetUUID(); + LLItemAddedObserver* observer = new LLItemAddedObserver(asset_id, cb); + gInventory.addObserver(observer); + object->moveInventory(destination_id, item_id); +} + void create_new_item(const std::string& name, const LLUUID& parent_id, LLAssetType::EType asset_type, diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 24b632632b..6c0f1b8d07 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -439,6 +439,10 @@ void copy_inventory_from_notecard(const LLUUID& destination_id, const LLInventoryItem *src, U32 callback_id = 0); +void move_or_copy_inventory_from_object(const LLUUID& destination_id, + const LLUUID& object_id, + const LLUUID& item_id, + LLPointer cb); void menu_create_inventory_item(LLInventoryPanel* root, LLFolderBridge* bridge, diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index d21d6f7027..69e62ace97 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -3610,6 +3610,17 @@ LLInventoryObject* LLViewerObject::getInventoryObject(const LLUUID& item_id) return rv; } +LLInventoryItem* LLViewerObject::getInventoryItem(const LLUUID& item_id) +{ + LLInventoryObject* iobj = getInventoryObject(item_id); + if (!iobj || iobj->getType() == LLAssetType::AT_CATEGORY) + { + return NULL; + } + LLInventoryItem* item = dynamic_cast(iobj); + return item; +} + void LLViewerObject::getInventoryContents(LLInventoryObject::object_list_t& objects) { if(mInventory) diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 3665c64965..ff28937f81 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -494,6 +494,8 @@ public: void updateInventoryLocal(LLInventoryItem* item, U8 key); // Update without messaging. void updateMaterialInventory(LLViewerInventoryItem* item, U8 key, bool is_new); LLInventoryObject* getInventoryObject(const LLUUID& item_id); + // TODO: Decide if this is worth keeping - Returns NULL if item does not exist or is a category + LLInventoryItem* getInventoryItem(const LLUUID& item_id); // Get content except for root category void getInventoryContents(LLInventoryObject::object_list_t& objects); -- cgit v1.3 From 57cc252fd6e3956d53da3c4eb4cad512ddf75e8c Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Mon, 7 Aug 2023 16:31:03 -0700 Subject: SL-20024: Miscellaneous cleanup --- indra/newview/llmaterialeditor.cpp | 110 +++++++++++++++++++----------------- indra/newview/llmaterialeditor.h | 2 +- indra/newview/llviewerinventory.cpp | 2 - indra/newview/llviewerobject.h | 1 - 4 files changed, 58 insertions(+), 57 deletions(-) (limited to 'indra/newview/llmaterialeditor.cpp') diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index bc3d5b88ab..989f18f1f4 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -1940,11 +1940,12 @@ void LLMaterialEditor::saveObjectsMaterialAs() LL_WARNS("MaterialEditor") << "Failed to save GLTF material from object" << LL_ENDL; return; } - saveObjectsMaterialAs(func.mMaterial, func.mLocalMaterial, permissions, func.mObjectId, item); + const LLUUID item_id = item ? item->getUUID() : LLUUID::null; + saveObjectsMaterialAs(func.mMaterial, func.mLocalMaterial, permissions, func.mObjectId, item_id); } -void LLMaterialEditor::saveObjectsMaterialAs(const LLGLTFMaterial* render_material, const LLLocalGLTFMaterial *local_material, const LLPermissions& permissions, const LLUUID& object_id, LLViewerInventoryItem* item) // TODO: item should probably just be an ID at this point +void LLMaterialEditor::saveObjectsMaterialAs(const LLGLTFMaterial* render_material, const LLLocalGLTFMaterial *local_material, const LLPermissions& permissions, const LLUUID& object_id, const LLUUID& item_id) { if (local_material) { @@ -2028,10 +2029,10 @@ void LLMaterialEditor::saveObjectsMaterialAs(const LLGLTFMaterial* render_materi } else { - if (item) + if (item_id.notNull()) { // Copy existing item from object inventory, and create new composite asset on top of it - LLNotificationsUtil::add("SaveMaterialAs", args, payload, boost::bind(&LLMaterialEditor::onCopyObjectsMaterialAsMsgCallback, _1, _2, permissions, object_id, item->getUUID())); + LLNotificationsUtil::add("SaveMaterialAs", args, payload, boost::bind(&LLMaterialEditor::onCopyObjectsMaterialAsMsgCallback, _1, _2, permissions, object_id, item_id)); } else { @@ -2044,71 +2045,74 @@ void LLMaterialEditor::saveObjectsMaterialAs(const LLGLTFMaterial* render_materi void LLMaterialEditor::onCopyObjectsMaterialAsMsgCallback(const LLSD& notification, const LLSD& response, const LLPermissions& permissions, const LLUUID& object_id, const LLUUID& item_id) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (0 == option) + if (0 != option) { - LLSD asset; - asset["version"] = LLGLTFMaterial::ASSET_VERSION; - asset["type"] = LLGLTFMaterial::ASSET_TYPE; - // This is the string serialized from LLGLTFMaterial::asJSON - asset["data"] = notification["payload"]["data"]; - - std::ostringstream str; - LLSDSerialize::serialize(asset, str, LLSDSerialize::LLSD_BINARY); + return; + } - LLViewerObject* object = gObjectList.findObject(object_id); - if (!object) - { - return; - } - const LLInventoryItem* item = object->getInventoryItem(item_id); - if (!item) - { - return; - } + LLSD asset; + asset["version"] = LLGLTFMaterial::ASSET_VERSION; + asset["type"] = LLGLTFMaterial::ASSET_TYPE; + // This is the string serialized from LLGLTFMaterial::asJSON + asset["data"] = notification["payload"]["data"]; - std::string new_name = response["message"].asString(); - LLInventoryObject::correctInventoryName(new_name); - if (new_name.empty()) - { - return; - } + std::ostringstream str; + LLSDSerialize::serialize(asset, str, LLSDSerialize::LLSD_BINARY); - const LLUUID destination_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL); + LLViewerObject* object = gObjectList.findObject(object_id); + if (!object) + { + return; + } + const LLInventoryItem* item = object->getInventoryItem(item_id); + if (!item) + { + return; + } - // TODO: Test - // TODO: Rename the item - LLPointer cb = new LLObjectsMaterialItemCallback(permissions, str.str(), new_name); - // NOTE: This should be an item copy. Saving a material to an inventory should be disabled when the associated material is no-copy. - move_or_copy_inventory_from_object(destination_id, - object_id, - item_id, - cb); + std::string new_name = response["message"].asString(); + LLInventoryObject::correctInventoryName(new_name); + if (new_name.empty()) + { + return; } + + const LLUUID destination_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL); + + LLPointer cb = new LLObjectsMaterialItemCallback(permissions, str.str(), new_name); + // NOTE: This should be an item copy. Saving a material to an inventory should be disabled when the associated material is no-copy. + move_or_copy_inventory_from_object(destination_id, + object_id, + item_id, + cb); } // static void LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback(const LLSD& notification, const LLSD& response, const LLPermissions& permissions) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (0 == option) + if (0 != option) { - LLSD asset; - asset["version"] = LLGLTFMaterial::ASSET_VERSION; - asset["type"] = LLGLTFMaterial::ASSET_TYPE; - // This is the string serialized from LLGLTFMaterial::asJSON - asset["data"] = notification["payload"]["data"]; + return; + } + + LLSD asset; + asset["version"] = LLGLTFMaterial::ASSET_VERSION; + asset["type"] = LLGLTFMaterial::ASSET_TYPE; + // This is the string serialized from LLGLTFMaterial::asJSON + asset["data"] = notification["payload"]["data"]; - std::ostringstream str; - LLSDSerialize::serialize(asset, str, LLSDSerialize::LLSD_BINARY); + std::ostringstream str; + LLSDSerialize::serialize(asset, str, LLSDSerialize::LLSD_BINARY); - std::string new_name = response["message"].asString(); - LLInventoryObject::correctInventoryName(new_name); - if (new_name.empty()) - { - return; - } - createInventoryItem(str.str(), new_name, std::string(), permissions); + std::string new_name = response["message"].asString(); + LLInventoryObject::correctInventoryName(new_name); + if (new_name.empty()) + { + return; } + + createInventoryItem(str.str(), new_name, std::string(), permissions); } const void upload_bulk(const std::vector& filenames, LLFilePicker::ELoadFilter type); diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h index 2176f493a9..6b2f49e2fc 100644 --- a/indra/newview/llmaterialeditor.h +++ b/indra/newview/llmaterialeditor.h @@ -232,7 +232,7 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener static bool capabilitiesAvailable(); private: - static void saveObjectsMaterialAs(const LLGLTFMaterial *render_material, const LLLocalGLTFMaterial *local_material, const LLPermissions& permissions, const LLUUID& object_id /* = LLUUID::null */, LLViewerInventoryItem* item /* = nullptr */); + static void saveObjectsMaterialAs(const LLGLTFMaterial *render_material, const LLLocalGLTFMaterial *local_material, const LLPermissions& permissions, const LLUUID& object_id /* = LLUUID::null */, const LLUUID& item /* = LLUUID::null */); 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, const LLPermissions& permissions); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index b722e715b6..aa1827a8e2 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1609,8 +1609,6 @@ void move_or_copy_inventory_from_object(const LLUUID& destination_id, const LLUUID& item_id, LLPointer cb) { - // TODO: Implement - LLViewerObject* object = gObjectList.findObject(object_id); if (!object) { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index ff28937f81..898b21e1ae 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -494,7 +494,6 @@ public: void updateInventoryLocal(LLInventoryItem* item, U8 key); // Update without messaging. void updateMaterialInventory(LLViewerInventoryItem* item, U8 key, bool is_new); LLInventoryObject* getInventoryObject(const LLUUID& item_id); - // TODO: Decide if this is worth keeping - Returns NULL if item does not exist or is a category LLInventoryItem* getInventoryItem(const LLUUID& item_id); // Get content except for root category -- cgit v1.3 From 076a02e2d8ddb10856602c3f5f3115ace41327b5 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Mon, 7 Aug 2023 17:27:30 -0700 Subject: SL-20024: Strike a better balance with saved material permissions handling, w/r/t author intent and being easier to understand --- indra/newview/llmaterialeditor.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'indra/newview/llmaterialeditor.cpp') diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 989f18f1f4..41df58914b 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -1295,9 +1295,8 @@ bool LLMaterialEditor::updateInventoryItem(const std::string &buffer, const LLUU return true; } -// Callback intended for when an item is copied from an object's inventory and -// needs to be modified to reflect the new asset/name. For example: When saving -// a modified material to the inventory from the build floater. +// Callback intended for when a material is saved from an object and needs to +// be modified to reflect the new asset/name. class LLObjectsMaterialItemCallback : public LLInventoryCallback { public: @@ -1902,12 +1901,22 @@ bool can_use_objects_material(LLSelectedTEGetMatData& func, const std::vector Date: Fri, 11 Aug 2023 17:18:06 -0700 Subject: SL-20024: Double-check object inventory is not pending when save button pressed --- indra/newview/llmaterialeditor.cpp | 4 ++++ indra/newview/llpanelface.cpp | 7 +++---- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'indra/newview/llmaterialeditor.cpp') diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 41df58914b..92042ad49f 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -1836,6 +1836,10 @@ bool can_use_objects_material(LLSelectedTEGetMatData& func, const std::vectorgetSelection()->getFirstObject()); return false; } + if (selected_object->isInventoryPending()) + { + return false; + } for (PermissionBit op : ops) { if (op == PERM_MODIFY && selected_object->isPermanentEnforced()) diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 21651899db..8f09136ccf 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -1897,11 +1897,10 @@ void LLPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material, pbr_ctrl->setImageAssetID(pbr_id); } - const bool inventory_pending = objectp->isInventoryPending(); getChildView("pbr_from_inventory")->setEnabled(settable); - getChildView("edit_selected_pbr")->setEnabled(editable && !inventory_pending && !has_faces_without_pbr); - getChildView("save_selected_pbr")->setEnabled(saveable && !inventory_pending && identical_pbr); - if (inventory_pending) + getChildView("edit_selected_pbr")->setEnabled(editable && !has_faces_without_pbr); + getChildView("save_selected_pbr")->setEnabled(saveable && identical_pbr); + if (objectp->isInventoryPending()) { // Reuse the same listener when possible if (!mInventoryListener || !mInventoryListener->isListeningFor(objectp)) -- cgit v1.3 From a388c5494e2e5b6669820995a2f4d62a308b870f Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 18 Aug 2023 16:08:03 -0700 Subject: SL-20024: Fix unable to modify a no-copy material from the build floater --- indra/newview/llmaterialeditor.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'indra/newview/llmaterialeditor.cpp') diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 92042ad49f..54d85c87ac 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -1827,7 +1827,12 @@ bool can_use_objects_material(LLSelectedTEGetMatData& func, const std::vectorgetSelection()->applyToTEs(&func, true /*first applicable*/); + LLViewerObject* selected_object = func.mObject; if (!selected_object) { @@ -1928,7 +1933,7 @@ bool can_use_objects_material(LLSelectedTEGetMatData& func, const std::vector