diff options
Diffstat (limited to 'indra/newview')
| -rw-r--r-- | indra/newview/llinventorymodel.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/llmaterialeditor.cpp | 200 | ||||
| -rw-r--r-- | indra/newview/llmaterialeditor.h | 1 | ||||
| -rw-r--r-- | indra/newview/llpanelface.cpp | 65 | ||||
| -rw-r--r-- | indra/newview/llpanelface.h | 6 | ||||
| -rw-r--r-- | indra/newview/llviewerinventory.cpp | 61 | ||||
| -rw-r--r-- | indra/newview/llviewerinventory.h | 5 | 
7 files changed, 188 insertions, 154 deletions
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 74a5442586..ca13b9eb03 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1465,6 +1465,10 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask)  		{  			mask |= LLInventoryObserver::LABEL;  		} +        if (old_item->getPermissions() != item->getPermissions()) +        { +            mask |= LLInventoryObserver::INTERNAL; +        }  		old_item->copyViewerItem(item);  		if (update_parent_on_server)  		{ diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 5be1aa08ab..8f016b9125 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" @@ -1312,16 +1313,22 @@ public:              return;          } +        // Name may or may not have already been applied +        const bool changed_name = item->getName() != mNewName;          // 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) +        const bool changed_permissions = item->getPermissions() != mPermissions; +        const bool changed = changed_name || changed_permissions; +        LLSD updates; +        if (changed)          { -            LLSD updates; -            updates["name"] = mNewName; +            if (changed_name) +            { +                updates["name"] = mNewName; +            } +            if (changed_permissions) +            { +                updates["permissions"] = ll_create_sd_from_permissions(mPermissions); +            }              update_inventory_item(inv_item_id, updates, NULL);          } @@ -1331,10 +1338,16 @@ public:                  inv_item_id,                  LLAssetType::AT_MATERIAL,                  mAssetData, -                [](LLUUID item_id, LLUUID new_asset_id, LLUUID new_item_id, LLSD response) +                [changed, updates](LLUUID item_id, LLUUID new_asset_id, LLUUID new_item_id, LLSD response)                  {                      // done callback                      LL_INFOS("Material") << "inventory item uploaded.  item: " << item_id << " new_item_id: " << new_item_id << " response: " << response << LL_ENDL; + +                    // *HACK: Sometimes permissions do not stick in the UI. They are correct on the server-side, though. +                    if (changed) +                    { +                        update_inventory_item(new_item_id, updates, NULL); +                    }                  },                  nullptr // failure callback, floater already closed              ); @@ -1796,8 +1809,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())      { @@ -1810,6 +1864,10 @@ bool can_use_objects_material(LLSelectedTEGetMatData& func, const std::vector<Pe      llassert(func.mIsOverride);      LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func, true /*first applicable*/); +    if (item_source == ItemSource::AGENT) +    { +        func.mObjectId = LLUUID::null; +    }      LLViewerObject* selected_object = func.mObject;      if (!selected_object)      { @@ -1830,19 +1888,47 @@ 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; +    const bool blank_material = func.mMaterialId == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID; +    if (!blank_material)      { -        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)) +            LLViewerInventoryItem* item = selected_object->getInventoryItemByAsset(func.mMaterialId); +            if (item && !item_has_perms(nullptr, item))              {                  return false;              } +            item_out = item;          } +        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))          { @@ -1895,13 +1981,24 @@ bool can_use_objects_material(LLSelectedTEGetMatData& func, const std::vector<Pe      // creation history when there's no material item present. In that case,      // the agent who saved the material will be considered the creator.      // -Cosmic,2023-08-07 -    if (item_out) +    if (item_source == ItemSource::AGENT)      { +        llassert(blank_material || item_out); // See comment at ItemSource::AGENT definition +          permissions_out.set(item_permissions);      }      else      { -        permissions_out.set(object_permissions); +        llassert(item_source == ItemSource::OBJECT); + +        if (item_out) +        { +            permissions_out.set(item_permissions); +        } +        else +        { +            permissions_out.set(object_permissions); +        }      }      permissions_out.accumulate(floater_perm); @@ -1913,7 +2010,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 +2018,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 +2044,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 +2052,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; @@ -2050,62 +2147,9 @@ void LLMaterialEditor::saveObjectsMaterialAs(const LLGLTFMaterial* render_materi      }      else      { -        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_id)); -        } -        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) -    { -        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); - -    LLViewerObject* object = gObjectList.findObject(object_id); -    if (!object) -    { -        return; +        llassert(object_id.isNull()); // Case for copying item from object inventory is no longer implemented +        LLNotificationsUtil::add("SaveMaterialAs", args, payload, boost::bind(&LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback, _1, _2, permissions));      } -    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); - -    LLPointer<LLInventoryCallback> 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 diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h index 1c40fcc348..2e25a9ca3d 100644 --- a/indra/newview/llmaterialeditor.h +++ b/indra/newview/llmaterialeditor.h @@ -116,7 +116,6 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener      static bool canSaveObjectsMaterial();      static bool canClipboardObjectsMaterial();      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); 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) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 5ee613d49d..1b70e5f84f 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1658,67 +1658,6 @@ 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<LLInventoryCallback> cb) -{ -    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<LLInventoryCallback> 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<LLInventoryCallback> 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 bce8da0a69..e043285ffb 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -463,11 +463,6 @@ 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<LLInventoryCallback> cb); -  void menu_create_inventory_item(LLInventoryPanel* root,  								LLFolderBridge* bridge,  								const LLSD& userdata,  | 
