diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/newview/llmaterialeditor.cpp | 178 | ||||
| -rw-r--r-- | indra/newview/llmaterialeditor.h | 6 | ||||
| -rw-r--r-- | indra/newview/llviewerinventory.cpp | 63 | ||||
| -rw-r--r-- | indra/newview/llviewerinventory.h | 4 | ||||
| -rw-r--r-- | indra/newview/llviewerobject.cpp | 11 | ||||
| -rw-r--r-- | indra/newview/llviewerobject.h | 2 | 
6 files changed, 214 insertions, 50 deletions
| 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<LLLocalGLTFMaterial*>(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<LLBufferedAssetUploadInfo>(                  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<LLObjectsMaterialItemCallback> 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<PermissionBit>& 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<PermissionBit>& ops, LLPermissions& permissions_out, LLViewerInventoryItem*& item_out)  {      if (!LLMaterialEditor::capabilitiesAvailable())      { @@ -1834,12 +1845,12 @@ bool can_use_objects_material(LLSelectedTEGetMatData& func, const std::vector<Pe          }      } -    const LLViewerInventoryItem* item = selected_object->getInventoryItemByAsset(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::vector<Pe          object_permissions.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")); +      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. +    // The server will populate creator info based on the item creation method +    // used.      permissions_out.accumulate(object_permissions); +    permissions_out.accumulate(floater_perm);      return true;  } @@ -1899,30 +1917,34 @@ bool LLMaterialEditor::canModifyObjectsMaterial()  {      LLSelectedTEGetMatData func(false);      LLPermissions permissions; -    return can_use_objects_material(func, std::vector({PERM_MODIFY}), permissions); +    LLViewerInventoryItem* item_out; +    return can_use_objects_material(func, std::vector({PERM_MODIFY}), permissions, item_out);  }  bool LLMaterialEditor::canSaveObjectsMaterial()  {      LLSelectedTEGetMatData func(false);      LLPermissions permissions; -    return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), permissions); +    LLViewerInventoryItem* item_out; +    return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), permissions, item_out);  }  void LLMaterialEditor::saveObjectsMaterialAs()  {      LLSelectedTEGetMatData func(false);      LLPermissions permissions; -    bool allowed = can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), permissions); +    LLViewerInventoryItem* item = nullptr; +    bool allowed = can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), permissions, item);      if (!allowed)      {          LL_WARNS("MaterialEditor") << "Failed to save GLTF material from object" << LL_ENDL;          return;      } -    saveMaterialAs(func.mMaterial, func.mLocalMaterial, permissions); +    saveObjectsMaterialAs(func.mMaterial, func.mLocalMaterial, permissions, func.mObjectId, item);  } -void LLMaterialEditor::saveMaterialAs(const LLGLTFMaterial* render_material, const LLLocalGLTFMaterial *local_material, const LLPermissions& permissions) + +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  {      if (local_material)      { @@ -2006,10 +2028,65 @@ void LLMaterialEditor::saveMaterialAs(const LLGLTFMaterial* render_material, con      }      else      { -        LLNotificationsUtil::add("SaveMaterialAs", args, payload, boost::bind(&LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback, _1, _2, permissions)); +        if (item) +        { +            // 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())); +        } +        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<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  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<LLInventoryCallback> 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<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 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<LLInventoryCallback> 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<LLInventoryItem*>(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); | 
