diff options
| author | Dave Parks <davep@lindenlab.com> | 2022-06-28 15:15:57 -0500 | 
|---|---|---|
| committer | Dave Parks <davep@lindenlab.com> | 2022-06-28 15:15:57 -0500 | 
| commit | 57805cac68bbc67ecb8a8e76c0ced2ce9b622dd1 (patch) | |
| tree | cdc7d029f5375d6c33d6ffc73db6400cebe1baa5 | |
| parent | cc535ecccc3c415655a52cc597b33102e5ea21db (diff) | |
SL-17379 More complete integration of material asset type
| -rw-r--r-- | indra/llfilesystem/lldiskcache.cpp | 1 | ||||
| -rw-r--r-- | indra/llprimitive/llgltfmaterial.h | 10 | ||||
| -rw-r--r-- | indra/newview/app_settings/settings.xml | 11 | ||||
| -rw-r--r-- | indra/newview/llfloaterbulkpermission.cpp | 1 | ||||
| -rw-r--r-- | indra/newview/llinventorybridge.cpp | 3 | ||||
| -rw-r--r-- | indra/newview/llmaterialeditor.cpp | 630 | ||||
| -rw-r--r-- | indra/newview/llmaterialeditor.h | 50 | ||||
| -rw-r--r-- | indra/newview/llviewerinventory.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/llviewermessage.cpp | 6 | ||||
| -rw-r--r-- | indra/newview/llviewerregion.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/notifications.xml | 25 | 
11 files changed, 663 insertions, 80 deletions
diff --git a/indra/llfilesystem/lldiskcache.cpp b/indra/llfilesystem/lldiskcache.cpp index ee43a599f7..538446d732 100644 --- a/indra/llfilesystem/lldiskcache.cpp +++ b/indra/llfilesystem/lldiskcache.cpp @@ -209,6 +209,7 @@ const std::string LLDiskCache::assetTypeToString(LLAssetType::EType at)          { LLAssetType::AT_PERSON, "PERSON" },          { LLAssetType::AT_MESH, "MESH" },          { LLAssetType::AT_SETTINGS, "SETTINGS" }, +        { LLAssetType::AT_MATERIAL, "MATERIAL" },          { LLAssetType::AT_UNKNOWN, "UNKNOWN" }      }; diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h index 2df4883a3c..d6f59cd1a3 100644 --- a/indra/llprimitive/llgltfmaterial.h +++ b/indra/llprimitive/llgltfmaterial.h @@ -83,6 +83,16 @@ public:              mAlphaMode = ALPHA_MODE_OPAQUE;          }      } + +    const char* getAlphaMode() +    { +        switch (mAlphaMode) +        { +        case ALPHA_MODE_MASK: return "MASK"; +        case ALPHA_MODE_BLEND: return "BLEND"; +        default: return "OPAQUE"; +        } +    }  }; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 35a79f12de..1be6124a2a 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1252,6 +1252,17 @@        <key>Value</key>        <integer>1</integer>      </map> +  <key>BulkChangeIncludeMaterials</key> +  <map> +    <key>Comment</key> +    <string>Bulk permission changes affect materials</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>1</integer> +  </map>      <key>BulkChangeEveryoneCopy</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp index a1a06706bc..a3cc939f85 100644 --- a/indra/newview/llfloaterbulkpermission.cpp +++ b/indra/newview/llfloaterbulkpermission.cpp @@ -306,6 +306,7 @@ void LLFloaterBulkPermission::handleInventory(LLViewerObject* viewer_obj, LLInve  			( asstype == LLAssetType::AT_LSL_TEXT  && gSavedSettings.getBOOL("BulkChangeIncludeScripts"   )) ||  			( asstype == LLAssetType::AT_SOUND     && gSavedSettings.getBOOL("BulkChangeIncludeSounds"    )) ||  			( asstype == LLAssetType::AT_SETTINGS  && gSavedSettings.getBOOL("BulkChangeIncludeSettings"  )) || +            ( asstype == LLAssetType::AT_MATERIAL  && gSavedSettings.getBOOL("BulkChangeIncludeMaterials")) ||  			( asstype == LLAssetType::AT_TEXTURE   && gSavedSettings.getBOOL("BulkChangeIncludeTextures"  )))  		{  			LLViewerObject* object = gObjectList.findObject(viewer_obj->getID()); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index cd6f631ee1..2bb2c9676b 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -7651,8 +7651,7 @@ public:          LLViewerInventoryItem* item = getItem();          if (item)          { -            // TODO - show UI for material preview? -            LL_INFOS() << "inventory action performed on material: " << item->getName() << " " << item->getUUID() << LL_ENDL; +            LLFloaterReg::showInstance("material_editor", LLSD(item->getUUID()), TAKE_FOCUS_YES);          }          LLInvFVBridgeAction::doIt();      } diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index f1166fbc0d..ada5bb3882 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -42,8 +42,14 @@  #include "llviewerinventory.h"  #include "llviewerregion.h"  #include "llvovolume.h" - +#include "roles_constants.h"  #include "tinygltf/tiny_gltf.h" +#include "llviewerobjectlist.h" +#include "llfloaterreg.h" +#include "llfilesystem.h" +#include "llsdserialize.h" + +#include <strstream>  ///----------------------------------------------------------------------------  /// Class LLPreviewNotecard @@ -51,9 +57,14 @@  // Default constructor  LLMaterialEditor::LLMaterialEditor(const LLSD& key) -    : LLFloater(key) +    : LLPreview(key)      , mHasUnsavedChanges(false)  { +    const LLInventoryItem* item = getItem(); +    if (item) +    { +        mAssetID = item->getAssetUUID(); +    }  }  BOOL LLMaterialEditor::postBuild() @@ -104,7 +115,7 @@ BOOL LLMaterialEditor::postBuild()      // Disable/enable setCanApplyImmediately() based on      // working from inventory, upload or editing inworld -	return LLFloater::postBuild(); +	return LLPreview::postBuild();  }  void LLMaterialEditor::onClickCloseBtn(bool app_quitting) @@ -149,7 +160,7 @@ LLColor4 LLMaterialEditor::getAlbedoColor()  void LLMaterialEditor::setAlbedoColor(const LLColor4& color)  {      childSetValue("albedo color", color.getValue()); -    childSetValue("transparency", color.mV[3]); +    setTransparency(color.mV[3]);  }  F32 LLMaterialEditor::getTransparency() @@ -157,6 +168,11 @@ F32 LLMaterialEditor::getTransparency()      return childGetValue("transparency").asReal();  } +void LLMaterialEditor::setTransparency(F32 transparency) +{ +    childSetValue("transparency", transparency); +} +  std::string LLMaterialEditor::getAlphaMode()  {      return childGetValue("alpha mode").asString(); @@ -375,11 +391,51 @@ static U32 write_texture(const LLUUID& id, tinygltf::Model& model)      return texture_idx;  } +  void LLMaterialEditor::onClickSave()  {      applyToSelection(); +     +    saveIfNeeded(); +} + +std::string LLMaterialEditor::getGLTFJson(bool prettyprint) +{      tinygltf::Model model; +    getGLTFModel(model); + +    std::ostringstream str; + +    tinygltf::TinyGLTF gltf; +     +    gltf.WriteGltfSceneToStream(&model, str, prettyprint, false); + +    std::string dump = str.str(); + +    return dump; +} + +void LLMaterialEditor::getGLBData(std::vector<U8>& data) +{ +    tinygltf::Model model; +    getGLTFModel(model); + +    std::ostringstream str; + +    tinygltf::TinyGLTF gltf; + +    gltf.WriteGltfSceneToStream(&model, str, false, true); + +    std::string dump = str.str(); + +    data.resize(dump.length()); + +    memcpy(&data[0], dump.c_str(), dump.length()); +} + +void LLMaterialEditor::getGLTFModel(tinygltf::Model& model) +{      model.materials.resize(1);      tinygltf::PbrMetallicRoughness& pbrMaterial = model.materials[0].pbrMetallicRoughness; @@ -392,11 +448,11 @@ void LLMaterialEditor::onClickSave()      model.materials[0].alphaMode = getAlphaMode();      LLUUID albedo_id = getAlbedoId(); -     +      if (albedo_id.notNull())      {          U32 texture_idx = write_texture(albedo_id, model); -         +          pbrMaterial.baseColorTexture.index = texture_idx;      } @@ -406,14 +462,14 @@ void LLMaterialEditor::onClickSave()      pbrMaterial.metallicFactor = metalness;      pbrMaterial.roughnessFactor = roughness; -     +      LLUUID mr_id = getMetallicRoughnessId();      if (mr_id.notNull())      {          U32 texture_idx = write_texture(mr_id, model);          pbrMaterial.metallicRoughnessTexture.index = texture_idx;      } -     +      //write emissive      LLColor4 emissive_color = getEmissiveColor();      model.materials[0].emissiveFactor.resize(3); @@ -437,54 +493,213 @@ void LLMaterialEditor::onClickSave()      //write doublesided      model.materials[0].doubleSided = getDoubleSided(); +    model.asset.version = "2.0"; +} + +std::string LLMaterialEditor::getEncodedAsset() +{ +    LLSD asset; +    asset["version"] = "1.0"; +    asset["type"] = "GLTF 2.0"; +    asset["data"] = getGLTFJson(false); +      std::ostringstream str; +    LLSDSerialize::serialize(asset, str, LLSDSerialize::LLSD_BINARY); -    tinygltf::TinyGLTF gltf; -    model.asset.version = "2.0"; -    gltf.WriteGltfSceneToStream(&model, str, true, false); +    return str.str(); +} + +bool LLMaterialEditor::decodeAsset(const std::vector<char>& buffer) +{ +    LLSD asset; -    std::string dump = str.str(); +    std::istrstream str(&buffer[0], buffer.size()); +    if (LLSDSerialize::deserialize(asset, str, buffer.size())) +    { +        if (asset.has("version") && asset["version"] == "1.0") +        { +            if (asset.has("type") && asset["type"] == "GLTF 2.0") +            { +                if (asset.has("data") && asset["data"].isString()) +                { +                    std::string data = asset["data"]; + +                    tinygltf::TinyGLTF gltf; +                    tinygltf::TinyGLTF loader; +                    std::string        error_msg; +                    std::string        warn_msg; + +                    tinygltf::Model model_in; + +                    if (loader.LoadASCIIFromString(&model_in, &error_msg, &warn_msg, data.c_str(), data.length(), "")) +                    { +                        return setFromGltfModel(model_in, true); +                    } +                    else +                    { +                        LL_WARNS() << "Failed to decode material asset: " << LL_ENDL; +                        LL_WARNS() << warn_msg << LL_ENDL; +                        LL_WARNS() << error_msg << LL_ENDL; +                    } +                } +            } +        } +    } +    else +    { +        LL_WARNS() << "Failed to deserialize material LLSD" << LL_ENDL; +    } + +    return false; +} -    LL_INFOS() << mMaterialName << ": " << dump << LL_ENDL; - -    // gen a new uuid for this asset -    LLTransactionID tid; -    tid.generate();     // timestamp-based randomization + uniquification -    LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); -    std::string res_desc = "Saved Material"; -    U32 next_owner_perm = LLPermissions::DEFAULT.getMaskNextOwner(); -    LLUUID parent = gInventory.findCategoryUUIDForType(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, mMaterialName, res_desc, -        LLAssetType::AT_MATERIAL, LLInventoryType::IT_MATERIAL, subtype, next_owner_perm, -        new LLBoostFuncInventoryCallback([output=dump](LLUUID const & inv_item_id){ -            // from reference in LLSettingsVOBase::createInventoryItem()/updateInventoryItem() -            LLResourceUploadInfo::ptr_t uploadInfo = -                std::make_shared<LLBufferedAssetUploadInfo>( -                    inv_item_id, -                    LLAssetType::AT_SETTINGS, // TODO switch to AT_MATERIAL -                    output, -                    [](LLUUID item_id, LLUUID new_asset_id, LLUUID new_item_id, LLSD response) { -                        LL_INFOS("Material") << "inventory item uploaded.  item: " << item_id << " asset: " << new_asset_id << " new_item_id: " << new_item_id << " response: " << response << LL_ENDL; -                        LLSD params = llsd::map("ASSET_ID", new_asset_id); -                        LLNotificationsUtil::add("MaterialCreated", params); +bool LLMaterialEditor::saveIfNeeded(LLInventoryItem* copyitem, bool sync) +{ +    std::string buffer = getEncodedAsset(); +     +    const LLInventoryItem* item = getItem(); +    // save it out to database +    if (item) +    { +        const LLViewerRegion* region = gAgent.getRegion(); +        if (!region) +        { +            LL_WARNS() << "Not connected to a region, cannot save material." << LL_ENDL; +            return false; +        } +        std::string agent_url = region->getCapability("UpdateMaterialAgentInventory"); +        std::string task_url = region->getCapability("UpdateMaterialTaskInventory"); + +        if (!agent_url.empty() && !task_url.empty()) +        { +            std::string url; +            LLResourceUploadInfo::ptr_t uploadInfo; + +            if (mObjectUUID.isNull() && !agent_url.empty()) +            { +                uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(mItemUUID, LLAssetType::AT_MATERIAL, buffer, +                    [](LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD) { +                        LLMaterialEditor::finishInventoryUpload(itemId, newAssetId, newItemId);                      }); +                url = agent_url; +            } +            else if (!mObjectUUID.isNull() && !task_url.empty()) +            { +                LLUUID object_uuid(mObjectUUID); +                uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(mObjectUUID, mItemUUID, LLAssetType::AT_MATERIAL, buffer, +                    [object_uuid](LLUUID itemId, LLUUID, LLUUID newAssetId, LLSD) { +                        LLMaterialEditor::finishTaskUpload(itemId, newAssetId, object_uuid); +                    }); +                url = task_url; +            } -            const LLViewerRegion* region = gAgent.getRegion(); -            if (region) +            if (!url.empty() && uploadInfo)              { -                 std::string agent_url(region->getCapability("UpdateSettingsAgentInventory")); -                 if (agent_url.empty()) -                 { -                     LL_ERRS() << "missing required agent inventory cap url" << LL_ENDL; -                 } -                 LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo); +                mAssetStatus = PREVIEW_ASSET_LOADING; +                setEnabled(false); + +                LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);              } -        }) -    ); + +        } +        else // !gAssetStorage +        { +            LL_WARNS() << "Not connected to an materials capable region." << LL_ENDL; +            return false; +        } + +        if (mCloseAfterSave) +        { +            closeFloater(); +        } +    } +    else +    { //make a new inventory item +        // gen a new uuid for this asset +        LLTransactionID tid; +        tid.generate();     // timestamp-based randomization + uniquification +        LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); +        std::string res_desc = "Saved Material"; +        U32 next_owner_perm = LLPermissions::DEFAULT.getMaskNextOwner(); +        LLUUID parent = gInventory.findCategoryUUIDForType(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, mMaterialName, res_desc, +            LLAssetType::AT_MATERIAL, LLInventoryType::IT_MATERIAL, subtype, next_owner_perm, +            new LLBoostFuncInventoryCallback([output = buffer](LLUUID const& inv_item_id) { +                // from reference in LLSettingsVOBase::createInventoryItem()/updateInventoryItem() +                LLResourceUploadInfo::ptr_t uploadInfo = +                    std::make_shared<LLBufferedAssetUploadInfo>( +                        inv_item_id, +                        LLAssetType::AT_MATERIAL, +                        output, +                        [](LLUUID item_id, LLUUID new_asset_id, LLUUID new_item_id, LLSD response) { +                            LL_INFOS("Material") << "inventory item uploaded.  item: " << item_id << " asset: " << new_asset_id << " new_item_id: " << new_item_id << " response: " << response << LL_ENDL; +                            LLSD params = llsd::map("ASSET_ID", new_asset_id); +                            LLNotificationsUtil::add("MaterialCreated", params); +                        }); + +                const LLViewerRegion* region = gAgent.getRegion(); +                if (region) +                { +                    std::string agent_url(region->getCapability("UpdateMaterialAgentInventory")); +                    if (agent_url.empty()) +                    { +                        LL_ERRS() << "missing required agent inventory cap url" << LL_ENDL; +                    } +                    LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo); +                } +                }) +        ); +    } +     +    return true; +} + +void LLMaterialEditor::finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId) +{ +    // Update the UI with the new asset. +    LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", LLSD(itemId)); +    if (me) +    { +        if (newItemId.isNull()) +        { +            me->setAssetId(newAssetId); +            me->refreshFromInventory(); +        } +        else +        { +            me->refreshFromInventory(newItemId); +        } +    }  } +void LLMaterialEditor::finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUID taskId) +{ + +    LLSD floater_key; +    floater_key["taskid"] = taskId; +    floater_key["itemid"] = itemId; +    LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", LLSD(itemId)); +    if (me) +    { +        me->setAssetId(newAssetId); +        me->refreshFromInventory(); +    } +} + +void LLMaterialEditor::refreshFromInventory(const LLUUID& new_item_id) +{ +    if (new_item_id.notNull()) +    { +        mItemUUID = new_item_id; +        setKey(LLSD(new_item_id)); +    } +    LL_DEBUGS() << "LLPreviewNotecard::refreshFromInventory()" << LL_ENDL; +    loadAsset(); +} + +  void LLMaterialEditor::onClickSaveAs()  {      LLSD args; @@ -806,16 +1021,7 @@ void LLMaterialFilePicker::loadMaterial(const std::string& filename)      mME->setEmissiveId(emissive_id);      mME->setNormalId(normal_id); -    mME->setAlphaMode(material_in.alphaMode); -    mME->setAlphaCutoff(material_in.alphaCutoff); -     -    mME->setAlbedoColor(get_color(material_in.pbrMetallicRoughness.baseColorFactor)); -    mME->setEmissiveColor(get_color(material_in.emissiveFactor)); -     -    mME->setMetalnessFactor(material_in.pbrMetallicRoughness.metallicFactor); -    mME->setRoughnessFactor(material_in.pbrMetallicRoughness.roughnessFactor); - -    mME->setDoubleSided(material_in.doubleSided); +    mME->setFromGltfModel(model_in);      std::string new_material = LLTrans::getString("New Material");      mME->setMaterialName(new_material); @@ -826,6 +1032,81 @@ void LLMaterialFilePicker::loadMaterial(const std::string& filename)      mME->applyToSelection();  } +bool LLMaterialEditor::setFromGltfModel(tinygltf::Model& model, bool set_textures) +{ +    if (model.materials.size() > 0) +    { +        tinygltf::Material& material_in = model.materials[0]; + +        if (set_textures) +        { +            S32 index; +            LLUUID id; + +            // get albedo texture +            index = material_in.pbrMetallicRoughness.baseColorTexture.index; +            if (index >= 0) +            { +                id.set(model.images[index].uri); +                setAlbedoId(id); +            } +            else +            { +                setAlbedoId(LLUUID::null); +            } + +            // get normal map +            index = material_in.normalTexture.index; +            if (index >= 0) +            { +                id.set(model.images[index].uri); +                setNormalId(id); +            } +            else +            { +                setNormalId(LLUUID::null); +            } + +            // get metallic-roughness texture +            index = material_in.pbrMetallicRoughness.metallicRoughnessTexture.index; +            if (index >= 0) +            { +                id.set(model.images[index].uri); +                setMetallicRoughnessId(id); +            } +            else +            { +                setMetallicRoughnessId(LLUUID::null); +            } + +            // get emissive texture +            index = material_in.emissiveTexture.index; +            if (index >= 0) +            { +                id.set(model.images[index].uri); +                setEmissiveId(id); +            } +            else +            { +                setEmissiveId(LLUUID::null); +            } +        } + +        setAlphaMode(material_in.alphaMode); +        setAlphaCutoff(material_in.alphaCutoff); + +        setAlbedoColor(get_color(material_in.pbrMetallicRoughness.baseColorFactor)); +        setEmissiveColor(get_color(material_in.emissiveFactor)); + +        setMetalnessFactor(material_in.pbrMetallicRoughness.metallicFactor); +        setRoughnessFactor(material_in.pbrMetallicRoughness.roughnessFactor); + +        setDoubleSided(material_in.doubleSided); +    } + +    return true; +} +  void LLMaterialEditor::importMaterial()  {      (new LLMaterialFilePicker(this))->getFile(); @@ -841,22 +1122,7 @@ void LLMaterialEditor::applyToSelection()      if (objectp && objectp->getVolume())      {          LLGLTFMaterial* mat = new LLGLTFMaterial(); -        mat->mAlbedoColor = getAlbedoColor(); -        mat->mAlbedoColor.mV[3] = getTransparency(); -        mat->mAlbedoId = getAlbedoId(); -         -        mat->mNormalId = getNormalId(); - -        mat->mMetallicRoughnessId = getMetallicRoughnessId(); -        mat->mMetallicFactor = getMetalnessFactor(); -        mat->mRoughnessFactor = getRoughnessFactor(); -         -        mat->mEmissiveColor = getEmissiveColor(); -        mat->mEmissiveId = getEmissiveId(); -         -        mat->mDoubleSided = getDoubleSided(); -        mat->setAlphaMode(getAlphaMode()); - +        getGLTFMaterial(mat);          LLVOVolume* vobjp = (LLVOVolume*)objectp;          for (int i = 0; i < vobjp->getNumTEs(); ++i)          { @@ -867,3 +1133,223 @@ void LLMaterialEditor::applyToSelection()          vobjp->markForUpdate(TRUE);      }  } + +void LLMaterialEditor::getGLTFMaterial(LLGLTFMaterial* mat) +{ +    mat->mAlbedoColor = getAlbedoColor(); +    mat->mAlbedoColor.mV[3] = getTransparency(); +    mat->mAlbedoId = getAlbedoId(); + +    mat->mNormalId = getNormalId(); + +    mat->mMetallicRoughnessId = getMetallicRoughnessId(); +    mat->mMetallicFactor = getMetalnessFactor(); +    mat->mRoughnessFactor = getRoughnessFactor(); + +    mat->mEmissiveColor = getEmissiveColor(); +    mat->mEmissiveId = getEmissiveId(); + +    mat->mDoubleSided = getDoubleSided(); +    mat->setAlphaMode(getAlphaMode()); +} + +void LLMaterialEditor::setFromGLTFMaterial(LLGLTFMaterial* mat) +{ +    setAlbedoColor(mat->mAlbedoColor); +    setAlbedoId(mat->mAlbedoId); +    setNormalId(mat->mNormalId); + +    setMetallicRoughnessId(mat->mMetallicRoughnessId); +    setMetalnessFactor(mat->mMetallicFactor); +    setRoughnessFactor(mat->mRoughnessFactor); + +    setEmissiveColor(mat->mEmissiveColor); +    setEmissiveId(mat->mEmissiveId); + +    setDoubleSided(mat->mDoubleSided); +    setAlphaMode(mat->getAlphaMode()); +} + +void LLMaterialEditor::loadAsset() +{ +    // derived from LLPreviewNotecard::loadAsset +     +    // TODO: see commented out "editor" references and make them do something appropriate to the UI +    +    // request the asset. +    const LLInventoryItem* item = getItem(); +     +    bool fail = false; + +    if (item) +    { +        LLPermissions perm(item->getPermissions()); +        BOOL is_owner = gAgent.allowOperation(PERM_OWNER, perm, GP_OBJECT_MANIPULATE); +        BOOL allow_copy = gAgent.allowOperation(PERM_COPY, perm, GP_OBJECT_MANIPULATE); +        BOOL allow_modify = canModify(mObjectUUID, item); +        BOOL source_library = mObjectUUID.isNull() && gInventory.isObjectDescendentOf(mItemUUID, gInventory.getLibraryRootFolderID()); + +        if (allow_copy || gAgent.isGodlike()) +        { +            mAssetID = item->getAssetUUID(); +            if (mAssetID.isNull()) +            { +                mAssetStatus = PREVIEW_ASSET_LOADED; +            } +            else +            { +                LLHost source_sim = LLHost(); +                LLSD* user_data = new LLSD(); + +                if (mObjectUUID.notNull()) +                { +                    LLViewerObject* objectp = gObjectList.findObject(mObjectUUID); +                    if (objectp && objectp->getRegion()) +                    { +                        source_sim = objectp->getRegion()->getHost(); +                    } +                    else +                    { +                        // The object that we're trying to look at disappeared, bail. +                        LL_WARNS() << "Can't find object " << mObjectUUID << " associated with notecard." << LL_ENDL; +                        mAssetID.setNull(); +                        /*editor->setText(getString("no_object")); +                        editor->makePristine(); +                        editor->setEnabled(FALSE);*/ +                        mAssetStatus = PREVIEW_ASSET_LOADED; +                        return; +                    } +                    user_data->with("taskid", mObjectUUID).with("itemid", mItemUUID); +                } +                else +                { +                    user_data = new LLSD(mItemUUID); +                } + +                gAssetStorage->getInvItemAsset(source_sim, +                    gAgent.getID(), +                    gAgent.getSessionID(), +                    item->getPermissions().getOwner(), +                    mObjectUUID, +                    item->getUUID(), +                    item->getAssetUUID(), +                    item->getType(), +                    &onLoadComplete, +                    (void*)user_data, +                    TRUE); +                mAssetStatus = PREVIEW_ASSET_LOADING; +            } +        } +        else +        { +            mAssetID.setNull(); +            /*editor->setText(getString("not_allowed")); +            editor->makePristine(); +            editor->setEnabled(FALSE);*/ +            mAssetStatus = PREVIEW_ASSET_LOADED; +        } + +        if (!allow_modify) +        { +            //editor->setEnabled(FALSE); +            //getChildView("lock")->setVisible(TRUE); +            //getChildView("Edit")->setEnabled(FALSE); +        } + +        if ((allow_modify || is_owner) && !source_library) +        { +            //getChildView("Delete")->setEnabled(TRUE); +        } +    } +    else if (mObjectUUID.notNull() && mItemUUID.notNull()) +    { +        LLViewerObject* objectp = gObjectList.findObject(mObjectUUID); +        if (objectp && (objectp->isInventoryPending() || objectp->isInventoryDirty())) +        { +            // It's a material in object's inventory and we failed to get it because inventory is not up to date. +            // Subscribe for callback and retry at inventoryChanged() +            registerVOInventoryListener(objectp, NULL); //removes previous listener + +            if (objectp->isInventoryDirty()) +            { +                objectp->requestInventory(); +            } +        } +        else +        { +            fail = true; +        } +    } +    else +    { +        fail = true; +    } + +    if (fail) +    { +        /*editor->setText(LLStringUtil::null); +        editor->makePristine(); +        editor->setEnabled(TRUE);*/ +        // Don't set asset status here; we may not have set the item id yet +        // (e.g. when this gets called initially) +        //mAssetStatus = PREVIEW_ASSET_LOADED; +    } +} + +// static +void LLMaterialEditor::onLoadComplete(const LLUUID& asset_uuid, +    LLAssetType::EType type, +    void* user_data, S32 status, LLExtStat ext_status) +{ +    LL_INFOS() << "LLMaterialEditor::onLoadComplete()" << LL_ENDL; +    LLSD* floater_key = (LLSD*)user_data; +    LLMaterialEditor* editor = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", *floater_key); +    if (editor) +    { +        if (0 == status) +        { +            LLFileSystem file(asset_uuid, type, LLFileSystem::READ); + +            S32 file_length = file.getSize(); + +            std::vector<char> buffer(file_length + 1); +            file.read((U8*)&buffer[0], file_length); + +            editor->decodeAsset(buffer); + +            BOOL modifiable = editor->canModify(editor->mObjectID, editor->getItem()); +            editor->setEnabled(modifiable); +            editor->mAssetStatus = PREVIEW_ASSET_LOADED; +        } +        else +        { +            if (LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || +                LL_ERR_FILE_EMPTY == status) +            { +                LLNotificationsUtil::add("MaterialMissing"); +            } +            else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) +            { +                LLNotificationsUtil::add("MaterialNoPermissions"); +            } +            else +            { +                LLNotificationsUtil::add("UnableToLoadMaterial"); +            } + +            LL_WARNS() << "Problem loading material: " << status << LL_ENDL; +            editor->mAssetStatus = PREVIEW_ASSET_ERROR; +        } +    } +    delete floater_key; +} + +void LLMaterialEditor::inventoryChanged(LLViewerObject* object, +    LLInventoryObject::object_list_t* inventory, +    S32 serial_num, +    void* user_data) +{ +    removeVOInventoryListener(); +    loadAsset(); +} + diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h index 7f9c6c0b63..4090ed120b 100644 --- a/indra/newview/llmaterialeditor.h +++ b/indra/newview/llmaterialeditor.h @@ -26,22 +26,62 @@  #pragma once -#include "llfloater.h" +#include "llpreview.h" +#include "llvoinventorylistener.h"  class LLTextureCtrl; -class LLMaterialEditor : public LLFloater +namespace tinygltf +{ +    class Model; +} + +class LLGLTFMaterial; + +class LLMaterialEditor : public LLPreview, public LLVOInventoryListener  {  public:  	LLMaterialEditor(const LLSD& key); +    bool setFromGltfModel(tinygltf::Model& model, bool set_textures = false); +      // open a file dialog and select a gltf/glb file for import      void importMaterial();      // for live preview, apply current material to currently selected object      void applyToSelection(); +    void getGLTFMaterial(LLGLTFMaterial* mat); + +    void setFromGLTFMaterial(LLGLTFMaterial* mat); + +    void loadAsset(); + +    static void onLoadComplete(const LLUUID& asset_uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status); + +    void inventoryChanged(LLViewerObject* object, LLInventoryObject::object_list_t* inventory, S32 serial_num, void* user_data) override; +      void onClickSave(); + +    // get a dump of the json representation of the current state of the editor UI in GLTF format +    std::string getGLTFJson(bool prettyprint = true); + +    void getGLBData(std::vector<U8>& data); + +    void getGLTFModel(tinygltf::Model& model); + +    std::string getEncodedAsset(); + +    bool decodeAsset(const std::vector<char>& buffer); + +    bool saveIfNeeded(LLInventoryItem* copyitem = nullptr, bool sync = true); + +    static void finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId); + +    static void finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUID taskId); + +    void refreshFromInventory(const LLUUID& new_item_id = LLUUID::null); +      void onClickSaveAs();      void onSaveAsMsgCallback(const LLSD& notification, const LLSD& response);      void onClickCancel(); @@ -60,7 +100,8 @@ public:      void    setAlbedoColor(const LLColor4& color);      F32     getTransparency(); -     +    void     setTransparency(F32 transparency); +      std::string getAlphaMode();      void setAlphaMode(const std::string& alpha_mode); @@ -98,6 +139,9 @@ public:      void onCommitNormalTexture(LLUICtrl* ctrl, const LLSD& data);  private: +    LLUUID mAssetID; +    LLUUID mObjectID; +      LLTextureCtrl* mAlbedoTextureCtrl;      LLTextureCtrl* mMetallicTextureCtrl;      LLTextureCtrl* mEmissiveTextureCtrl; diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d777cde554..2265379ce4 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1731,8 +1731,8 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge,  	}      else if ("material" == type_name)      { -        const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE); -        create_new_item(NEW_GESTURE_NAME, +        const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL); +        create_new_item(NEW_MATERIAL_NAME,              parent_id,              LLAssetType::AT_MATERIAL,              LLInventoryType::IT_MATERIAL, diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index a886303563..375f176b60 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1414,7 +1414,8 @@ bool check_asset_previewable(const LLAssetType::EType asset_type)  			(asset_type == LLAssetType::AT_TEXTURE)   ||  			(asset_type == LLAssetType::AT_ANIMATION) ||  			(asset_type == LLAssetType::AT_SCRIPT)    || -			(asset_type == LLAssetType::AT_SOUND); +			(asset_type == LLAssetType::AT_SOUND) || +            (asset_type == LLAssetType::AT_MATERIAL);  }  void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_name) @@ -1519,6 +1520,9 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam  					case LLAssetType::AT_SOUND:  						LLFloaterReg::showInstance("preview_sound", LLSD(obj_id), take_focus);  						break; +                    case LLAssetType::AT_MATERIAL: +                        LLFloaterReg::showInstance("material editor", LLSD(obj_id), take_focus); +                        break;  					default:  						LL_DEBUGS("Messaging") << "No preview method for previewable asset type : " << LLAssetType::lookupHumanReadable(asset_type)  << LL_ENDL;  						break; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 67ad72e997..6345323ff9 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -3095,6 +3095,8 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)  	capabilityNames.append("UpdateScriptTask");      capabilityNames.append("UpdateSettingsAgentInventory");      capabilityNames.append("UpdateSettingsTaskInventory"); +    capabilityNames.append("UpdateMaterialAgentInventory"); +    capabilityNames.append("UpdateMaterialTaskInventory");  	capabilityNames.append("UploadBakedTexture");      capabilityNames.append("UserInfo");  	capabilityNames.append("ViewerAsset");  diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 0ca3e043e7..ae4b0538d8 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6764,6 +6764,22 @@ You don't have permission to view this notecard.    <notification     icon="notifytip.tga" +   name="MaterialMissing" +   type="notifytip"> +    Material is missing from database. +    <tag>fail</tag> +  </notification> + +  <notification +   icon="notifytip.tga" +   name="MaterialNoPermissions" +   type="notifytip"> +    You don't have permission to view this material. +    <tag>fail</tag> +  </notification> + +  <notification +   icon="notifytip.tga"     name="RezItemNoPermissions"     type="notifytip">  Insufficient permissions to rez object. @@ -6795,6 +6811,15 @@ Please try again.    <notification     icon="notifytip.tga" +   name="UnableToLoadMaterial" +   type="notifytip"> +    Unable to load material. +    Please try again. +    <tag>fail</tag> +  </notification> + +  <notification +   icon="notifytip.tga"     name="ScriptMissing"     type="notifytip">  Script is missing from database.  | 
