diff options
| author | Cosmic Linden <cosmic@lindenlab.com> | 2023-07-28 17:29:09 -0700 | 
|---|---|---|
| committer | Cosmic Linden <cosmic@lindenlab.com> | 2023-08-11 16:31:00 -0700 | 
| commit | a5d318567cc5c3e8f2f86fce1132f5883014e14e (patch) | |
| tree | 093b6d2dbc04c96914a7a462e35102fc2818fed1 | |
| parent | 7bf6103ad95c281c2ed680c9eb9b07cc584ddc91 (diff) | |
SL-20024: (WIP) (untested) Fix GLTF material permissions in some more edge cases
| -rw-r--r-- | indra/newview/llmaterialeditor.cpp | 139 | ||||
| -rw-r--r-- | indra/newview/llmaterialeditor.h | 1 | ||||
| -rw-r--r-- | indra/newview/llpanelface.cpp | 57 | ||||
| -rw-r--r-- | indra/newview/llpanelface.h | 6 | 
4 files changed, 134 insertions, 69 deletions
| 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<LLLocalGLTFMaterial*>(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<PermissionBit>& 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<LLTextureCtrl>("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<PBRPickerItemListener>(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 <memory> +  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<PBRPickerItemListener> mInventoryListener; +  public:  	#if defined(DEF_GET_MAT_STATE)  		#undef DEF_GET_MAT_STATE | 
