diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp index f771337c92..4b1f89f99f 100644 --- a/indra/llprimitive/llgltfmaterial.cpp +++ b/indra/llprimitive/llgltfmaterial.cpp @@ -28,6 +28,7 @@ #include "llgltfmaterial.h" +// NOTE -- this should be the one and only place tiny_gltf.h is included #include "tinygltf/tiny_gltf.h" const char* GLTF_FILE_EXTENSION_TRANSFORM = "KHR_texture_transform"; @@ -35,6 +36,9 @@ const char* GLTF_FILE_EXTENSION_TRANSFORM_SCALE = "scale"; const char* GLTF_FILE_EXTENSION_TRANSFORM_OFFSET = "offset"; const char* GLTF_FILE_EXTENSION_TRANSFORM_ROTATION = "rotation"; +// special UUID that indicates a null UUID in override data +static const LLUUID GLTF_OVERRIDE_NULL_UUID = LLUUID("ffffffff-ffff-ffff-ffff-ffffffffffff"); + LLGLTFMaterial::LLGLTFMaterial(const LLGLTFMaterial& rhs) { *this = rhs; @@ -42,6 +46,7 @@ LLGLTFMaterial::LLGLTFMaterial(const LLGLTFMaterial& rhs) LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs) { + LL_PROFILE_ZONE_SCOPED; //have to do a manual operator= because of LLRefCount mBaseColorId = rhs.mBaseColorId; mNormalId = rhs.mNormalId; @@ -65,7 +70,7 @@ LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs) bool LLGLTFMaterial::fromJSON(const std::string& json, std::string& warn_msg, std::string& error_msg) { -#if 1 + LL_PROFILE_ZONE_SCOPED; tinygltf::TinyGLTF gltf; tinygltf::Model model_in; @@ -74,18 +79,14 @@ bool LLGLTFMaterial::fromJSON(const std::string& json, std::string& warn_msg, st { setFromModel(model_in, 0); - //DEBUG generate json and print - LL_INFOS() << asJSON(true) << LL_ENDL; - return true; } -#endif return false; } std::string LLGLTFMaterial::asJSON(bool prettyprint) const { -#if 1 + LL_PROFILE_ZONE_SCOPED; tinygltf::TinyGLTF gltf; tinygltf::Model model_out; @@ -97,13 +98,11 @@ std::string LLGLTFMaterial::asJSON(bool prettyprint) const gltf.WriteGltfSceneToStream(&model_out, str, prettyprint, false); return str.str(); -#else - return ""; -#endif } void LLGLTFMaterial::setFromModel(const tinygltf::Model& model, S32 mat_index) { + LL_PROFILE_ZONE_SCOPED; if (model.materials.size() <= mat_index) { return; @@ -198,6 +197,7 @@ std::string gltf_get_texture_image(const tinygltf::Model& model, const T& textur template void LLGLTFMaterial::setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id, LLUUID& texture_id_out) { + LL_PROFILE_ZONE_SCOPED; const std::string uri = gltf_get_texture_image(model, texture_info); texture_id_out.set(uri); @@ -219,6 +219,7 @@ void LLGLTFMaterial::setFromTexture(const tinygltf::Model& model, const T& textu void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const { + LL_PROFILE_ZONE_SCOPED; if (model.materials.size() < mat_index+1) { model.materials.resize(mat_index + 1); @@ -277,6 +278,7 @@ void gltf_allocate_texture_image(tinygltf::Model& model, T& texture_info, const template void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, const LLUUID& texture_id, bool is_override, const LLUUID& base_texture_id) const { + LL_PROFILE_ZONE_SCOPED; if (texture_id.isNull() || (is_override && texture_id == base_texture_id)) { return; @@ -298,64 +300,144 @@ void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, Tex texture_info.extensions[GLTF_FILE_EXTENSION_TRANSFORM] = tinygltf::Value(transform_map); } +// static +void LLGLTFMaterial::hackOverrideUUID(LLUUID& id) +{ + if (id == LLUUID::null) + { + id = GLTF_OVERRIDE_NULL_UUID; + } +} -void LLGLTFMaterial::setBaseColorId(const LLUUID& id) +void LLGLTFMaterial::setBaseColorId(const LLUUID& id, bool for_override) { mBaseColorId = id; + if (for_override) + { + hackOverrideUUID(mBaseColorId); + } } -void LLGLTFMaterial::setNormalId(const LLUUID& id) +void LLGLTFMaterial::setNormalId(const LLUUID& id, bool for_override) { mNormalId = id; + if (for_override) + { + hackOverrideUUID(mNormalId); + } } -void LLGLTFMaterial::setMetallicRoughnessId(const LLUUID& id) +void LLGLTFMaterial::setMetallicRoughnessId(const LLUUID& id, bool for_override) { mMetallicRoughnessId = id; + if (for_override) + { + hackOverrideUUID(mMetallicRoughnessId); + } } -void LLGLTFMaterial::setEmissiveId(const LLUUID& id) +void LLGLTFMaterial::setEmissiveId(const LLUUID& id, bool for_override) { mEmissiveId = id; + if (for_override) + { + hackOverrideUUID(mEmissiveId); + } } -void LLGLTFMaterial::setBaseColorFactor(const LLColor3& baseColor, F32 transparency) +void LLGLTFMaterial::setBaseColorFactor(const LLColor4& baseColor, bool for_override) { - mBaseColor.set(baseColor, transparency); + mBaseColor.set(baseColor); mBaseColor.clamp(); + + if (for_override) + { // hack -- nudge off of default value + if (mBaseColor == getDefaultBaseColor()) + { + mBaseColor.mV[3] -= FLT_EPSILON; + } + } } -void LLGLTFMaterial::setAlphaCutoff(F32 cutoff) +void LLGLTFMaterial::setAlphaCutoff(F32 cutoff, bool for_override) { mAlphaCutoff = llclamp(cutoff, 0.f, 1.f); + if (for_override) + { // hack -- nudge off of default value + if (mAlphaCutoff == getDefaultAlphaCutoff()) + { + mAlphaCutoff -= FLT_EPSILON; + } + } } -void LLGLTFMaterial::setEmissiveColorFactor(const LLColor3& emissiveColor) +void LLGLTFMaterial::setEmissiveColorFactor(const LLColor3& emissiveColor, bool for_override) { mEmissiveColor = emissiveColor; mEmissiveColor.clamp(); + + if (for_override) + { // hack -- nudge off of default value + if (mEmissiveColor == getDefaultEmissiveColor()) + { + mEmissiveColor.mV[0] += FLT_EPSILON; + } + } } -void LLGLTFMaterial::setMetallicFactor(F32 metallic) +void LLGLTFMaterial::setMetallicFactor(F32 metallic, bool for_override) { - mMetallicFactor = llclamp(metallic, 0.f, 1.f); + mMetallicFactor = llclamp(metallic, 0.f, for_override ? 1.f - FLT_EPSILON : 1.f); } -void LLGLTFMaterial::setRoughnessFactor(F32 roughness) +void LLGLTFMaterial::setRoughnessFactor(F32 roughness, bool for_override) { - mRoughnessFactor = llclamp(roughness, 0.f, 1.f); + mRoughnessFactor = llclamp(roughness, 0.f, for_override ? 1.f - FLT_EPSILON : 1.f); } -void LLGLTFMaterial::setAlphaMode(S32 mode) +void LLGLTFMaterial::setAlphaMode(const std::string& mode, bool for_override) +{ + S32 m = getDefaultAlphaMode(); + if (mode == "MASK") + { + m = ALPHA_MODE_MASK; + } + else if (mode == "BLEND") + { + m = ALPHA_MODE_BLEND; + } + + setAlphaMode(m, for_override); +} + +const char* LLGLTFMaterial::getAlphaMode() const +{ + switch (mAlphaMode) + { + case ALPHA_MODE_MASK: return "MASK"; + case ALPHA_MODE_BLEND: return "BLEND"; + default: return "OPAQUE"; + } +} + +void LLGLTFMaterial::setAlphaMode(S32 mode, bool for_override) { mAlphaMode = (AlphaMode) llclamp(mode, (S32) ALPHA_MODE_OPAQUE, (S32) ALPHA_MODE_MASK); + if (for_override) + { + // TODO: what do? + } } -void LLGLTFMaterial::setDoubleSided(bool double_sided) +void LLGLTFMaterial::setDoubleSided(bool double_sided, bool for_override) { // sure, no clamping will ever be needed for a bool, but include the // setter for consistency with the clamping API mDoubleSided = double_sided; + if (for_override) + { + // TODO: what do? + } } void LLGLTFMaterial::setTextureOffset(TextureInfo texture_info, const LLVector2& offset) @@ -373,101 +455,102 @@ void LLGLTFMaterial::setTextureRotation(TextureInfo texture_info, float rotation mTextureTransform[texture_info].mRotation = rotation; } -// Default value accessors +// Default value accessors (NOTE: these MUST match the GLTF specification) + +// Make a static default material for accessors +const LLGLTFMaterial LLGLTFMaterial::sDefault; LLUUID LLGLTFMaterial::getDefaultBaseColorId() { - return LLUUID::null; + return sDefault.mBaseColorId; } LLUUID LLGLTFMaterial::getDefaultNormalId() { - return LLUUID::null; + return sDefault.mNormalId; } LLUUID LLGLTFMaterial::getDefaultEmissiveId() { - return LLUUID::null; + return sDefault.mEmissiveId; } LLUUID LLGLTFMaterial::getDefaultMetallicRoughnessId() { - return LLUUID::null; + return sDefault.mMetallicRoughnessId; } F32 LLGLTFMaterial::getDefaultAlphaCutoff() { - return 0.f; + return sDefault.mAlphaCutoff; } S32 LLGLTFMaterial::getDefaultAlphaMode() { - return (S32) ALPHA_MODE_OPAQUE; + return (S32) sDefault.mAlphaMode; } F32 LLGLTFMaterial::getDefaultMetallicFactor() { - return 0.f; + return sDefault.mMetallicFactor; } F32 LLGLTFMaterial::getDefaultRoughnessFactor() { - return 0.f; + return sDefault.mRoughnessFactor; } LLColor4 LLGLTFMaterial::getDefaultBaseColor() { - return LLColor4::white; + return sDefault.mBaseColor; } LLColor3 LLGLTFMaterial::getDefaultEmissiveColor() { - return LLColor3::black; + return sDefault.mEmissiveColor; } bool LLGLTFMaterial::getDefaultDoubleSided() { - return false; + return sDefault.mDoubleSided; } LLVector2 LLGLTFMaterial::getDefaultTextureOffset() { - return LLVector2(0.f, 0.f); + return sDefault.mTextureTransform[0].mOffset; } LLVector2 LLGLTFMaterial::getDefaultTextureScale() { - return LLVector2(1.f, 1.f); + return sDefault.mTextureTransform[0].mScale; } F32 LLGLTFMaterial::getDefaultTextureRotation() { - return 0.f; + return sDefault.mTextureTransform[0].mRotation; +} + +// static +void LLGLTFMaterial::applyOverrideUUID(LLUUID& dst_id, const LLUUID& override_id) +{ + if (override_id != GLTF_OVERRIDE_NULL_UUID) + { + dst_id = override_id; + } + else + { + dst_id = LLUUID::null; + } } void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat) { - // TODO: potentially reimplement this with a more general purpose JSON merge + LL_PROFILE_ZONE_SCOPED; - if (override_mat.mBaseColorId != getDefaultBaseColorId()) - { - mBaseColorId = override_mat.mBaseColorId; - } - - if (override_mat.mNormalId != getDefaultNormalId()) - { - mNormalId = override_mat.mNormalId; - } - - if (override_mat.mMetallicRoughnessId != getDefaultMetallicRoughnessId()) - { - mMetallicRoughnessId = override_mat.mMetallicRoughnessId; - } - - if (override_mat.mEmissiveId != getDefaultEmissiveId()) - { - mEmissiveId = override_mat.mEmissiveId; - } + applyOverrideUUID(mBaseColorId, override_mat.mBaseColorId); + applyOverrideUUID(mNormalId, override_mat.mNormalId); + applyOverrideUUID(mMetallicRoughnessId, override_mat.mMetallicRoughnessId); + applyOverrideUUID(mEmissiveId, override_mat.mEmissiveId); if (override_mat.mBaseColor != getDefaultBaseColor()) { diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h index d94ce6e281..a385539cc5 100644 --- a/indra/llprimitive/llgltfmaterial.h +++ b/indra/llprimitive/llgltfmaterial.h @@ -45,6 +45,9 @@ class LLGLTFMaterial : public LLRefCount { public: + // default material for reference + static const LLGLTFMaterial sDefault; + struct TextureTransform { LLVector2 mOffset = { 0.f, 0.f }; @@ -69,12 +72,13 @@ public: LLUUID mMetallicRoughnessId; LLUUID mEmissiveId; + // NOTE : initialize values to defaults according to the GLTF spec LLColor4 mBaseColor = LLColor4(1, 1, 1, 1); LLColor3 mEmissiveColor = LLColor3(0, 0, 0); - F32 mMetallicFactor = 0.f; - F32 mRoughnessFactor = 0.f; - F32 mAlphaCutoff = 0.f; + F32 mMetallicFactor = 1.f; + F32 mRoughnessFactor = 1.f; + F32 mAlphaCutoff = 0.5f; bool mDoubleSided = false; AlphaMode mAlphaMode = ALPHA_MODE_OPAQUE; @@ -105,19 +109,22 @@ public: std::array mTextureTransform; //setters for various members (will clamp to acceptable ranges) + // for_override - set to true if this value is being set as part of an override (important for handling override to default value) - void setBaseColorId(const LLUUID& id); - void setNormalId(const LLUUID& id); - void setMetallicRoughnessId(const LLUUID& id); - void setEmissiveId(const LLUUID& id); + void setBaseColorId(const LLUUID& id, bool for_override = false); + void setNormalId(const LLUUID& id, bool for_override = false); + void setMetallicRoughnessId(const LLUUID& id, bool for_override = false); + void setEmissiveId(const LLUUID& id, bool for_override = false); - void setBaseColorFactor(const LLColor3& baseColor, F32 transparency); - void setAlphaCutoff(F32 cutoff); - void setEmissiveColorFactor(const LLColor3& emissiveColor); - void setMetallicFactor(F32 metallic); - void setRoughnessFactor(F32 roughness); - void setAlphaMode(S32 mode); - void setDoubleSided(bool double_sided); + void setBaseColorFactor(const LLColor4& baseColor, bool for_override = false); + void setAlphaCutoff(F32 cutoff, bool for_override = false); + void setEmissiveColorFactor(const LLColor3& emissiveColor, bool for_override = false); + void setMetallicFactor(F32 metallic, bool for_override = false); + void setRoughnessFactor(F32 roughness, bool for_override = false); + void setAlphaMode(S32 mode, bool for_override = false); + void setDoubleSided(bool double_sided, bool for_override = false); + + //NOTE: texture offsets only exist in overrides, so "for_override" is not needed void setTextureOffset(TextureInfo texture_info, const LLVector2& offset); void setTextureScale(TextureInfo texture_info, const LLVector2& scale); @@ -139,34 +146,16 @@ public: static LLVector2 getDefaultTextureScale(); static F32 getDefaultTextureRotation(); + + static void hackOverrideUUID(LLUUID& id); + static void applyOverrideUUID(LLUUID& dst_id, const LLUUID& override_id); + // set mAlphaMode from string. // Anything otherthan "MASK" or "BLEND" sets mAlphaMode to ALPHA_MODE_OPAQUE - void setAlphaMode(const std::string& mode) - { - if (mode == "MASK") - { - mAlphaMode = ALPHA_MODE_MASK; - } - else if (mode == "BLEND") - { - mAlphaMode = ALPHA_MODE_BLEND; - } - else - { - mAlphaMode = ALPHA_MODE_OPAQUE; - } - } - - const char* getAlphaMode() const - { - switch (mAlphaMode) - { - case ALPHA_MODE_MASK: return "MASK"; - case ALPHA_MODE_BLEND: return "BLEND"; - default: return "OPAQUE"; - } - } - + void setAlphaMode(const std::string& mode, bool for_override = false); + + const char* getAlphaMode() const; + // set the contents of this LLGLTFMaterial from the given json // returns true if successful // json - the json text to load from diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp index 611f146a84..a0d5793dcc 100644 --- a/indra/llprimitive/lltextureentry.cpp +++ b/indra/llprimitive/lltextureentry.cpp @@ -198,6 +198,7 @@ LLSD LLTextureEntry::asLLSD() const void LLTextureEntry::asLLSD(LLSD& sd) const { + LL_PROFILE_ZONE_SCOPED; sd["imageid"] = mID; sd["colors"] = ll_sd_from_color4(mColor); sd["scales"] = mScaleS; @@ -225,6 +226,7 @@ void LLTextureEntry::asLLSD(LLSD& sd) const bool LLTextureEntry::fromLLSD(const LLSD& sd) { + LL_PROFILE_ZONE_SCOPED; const char *w, *x; w = "imageid"; if (sd.has(w)) diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index ea8ca8ea95..2e5463f53d 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -235,6 +235,7 @@ public: /*virtual*/ void setIsChrome(BOOL is_chrome); /*virtual*/ void setRect(const LLRect &rect); void setIsSingleInstance(BOOL is_single_instance); + BOOL getIsSingleInstance() { return mSingleInstance; } void initFloater(const Params& p); diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index d91a448bc8..dabacccf66 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -61,6 +61,7 @@ namespace bool operator()(const LLDispatcher* dispatcher, const std::string& key, const LLUUID& invoice, const sparam_t& strings) override { + LL_PROFILE_ZONE_SCOPED; // receive override data from simulator via LargeGenericMessage // message should have: // object_id - UUID of LLViewerObject @@ -196,6 +197,7 @@ void LLGLTFMaterialList::queueOverrideUpdate(const LLUUID& id, S32 side, LLGLTFM void LLGLTFMaterialList::applyQueuedOverrides(LLViewerObject* obj) { + LL_PROFILE_ZONE_SCOPED; const LLUUID& id = obj->getID(); auto iter = mQueuedOverrides.find(id); @@ -225,9 +227,11 @@ void LLGLTFMaterialList::applyQueuedOverrides(LLViewerObject* obj) LLGLTFMaterial* LLGLTFMaterialList::getMaterial(const LLUUID& id) { + LL_PROFILE_ZONE_SCOPED; uuid_mat_map_t::iterator iter = mList.find(id); if (iter == mList.end()) { + LL_PROFILE_ZONE_NAMED("gltf fetch") LLFetchedGLTFMaterial* mat = new LLFetchedGLTFMaterial(); mList[id] = mat; @@ -242,55 +246,66 @@ LLGLTFMaterial* LLGLTFMaterialList::getMaterial(const LLUUID& id) gAssetStorage->getAssetData(id, LLAssetType::AT_MATERIAL, [=](const LLUUID& id, LLAssetType::EType asset_type, void* user_data, S32 status, LLExtStat ext_status) { + LL_PROFILE_ZONE_NAMED("gltf asset callback"); if (status) { LL_WARNS() << "Error getting material asset data: " << LLAssetStorage::getErrorString(status) << " (" << status << ")" << LL_ENDL; } - LLFileSystem file(id, asset_type, LLFileSystem::READ); - auto size = file.getSize(); - if (!size) + std::vector buffer; + { - LL_DEBUGS() << "Zero size material." << LL_ENDL; - mat->mFetching = false; - mat->unref(); - return; + LL_PROFILE_ZONE_NAMED("gltf read asset"); + LLFileSystem file(id, asset_type, LLFileSystem::READ); + auto size = file.getSize(); + if (!size) + { + LL_DEBUGS() << "Zero size material." << LL_ENDL; + mat->mFetching = false; + mat->unref(); + return; + } + + + + buffer.resize(size); + file.read((U8*)&buffer[0], buffer.size()); } - std::vector buffer; - buffer.resize(size); - file.read((U8*)&buffer[0], buffer.size()); - - LLSD asset; - - // read file into buffer - std::istrstream str(&buffer[0], buffer.size()); - - if (LLSDSerialize::deserialize(asset, str, buffer.size())) { - if (asset.has("version") && asset["version"] == "1.0") + LL_PROFILE_ZONE_NAMED("gltf deserialize asset"); + + LLSD asset; + + // read file into buffer + std::istrstream str(&buffer[0], buffer.size()); + + if (LLSDSerialize::deserialize(asset, str, buffer.size())) { - if (asset.has("type") && asset["type"].asString() == "GLTF 2.0") + if (asset.has("version") && asset["version"] == "1.0") { - if (asset.has("data") && asset["data"].isString()) + if (asset.has("type") && asset["type"].asString() == "GLTF 2.0") { - std::string data = asset["data"]; - - std::string warn_msg, error_msg; - - if (!mat->fromJSON(data, warn_msg, error_msg)) + if (asset.has("data") && asset["data"].isString()) { - LL_WARNS() << "Failed to decode material asset: " << LL_ENDL; - LL_WARNS() << warn_msg << LL_ENDL; - LL_WARNS() << error_msg << LL_ENDL; + std::string data = asset["data"]; + + std::string warn_msg, error_msg; + + if (!mat->fromJSON(data, warn_msg, error_msg)) + { + 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; + else + { + LL_WARNS() << "Failed to deserialize material LLSD" << LL_ENDL; + } } mat->mFetching = false; diff --git a/indra/newview/lllocalgltfmaterials.cpp b/indra/newview/lllocalgltfmaterials.cpp index f194226fa5..3912ed5e30 100644 --- a/indra/newview/lllocalgltfmaterials.cpp +++ b/indra/newview/lllocalgltfmaterials.cpp @@ -47,7 +47,6 @@ #include "llscrolllistctrl.h" #include "lltinygltfhelper.h" #include "llviewertexture.h" -#include "tinygltf/tiny_gltf.h" /*=======================================*/ /* Formal declarations, constants, etc. */ @@ -83,7 +82,7 @@ LLLocalGLTFMaterial::LLLocalGLTFMaterial(std::string filename, S32 index) } else { - LL_WARNS() << "File of no valid extension given, local material creation aborted." << "\n" + LL_WARNS("GLTF") << "File of no valid extension given, local material creation aborted." << "\n" << "Filename: " << mFilename << LL_ENDL; return; // no valid extension. } @@ -180,7 +179,7 @@ bool LLLocalGLTFMaterial::updateSelf() } else { - LL_WARNS() << "During the update process the following file was found" << "\n" + LL_WARNS("GLTF") << "During the update process the following file was found" << "\n" << "but could not be opened or decoded for " << LL_LOCAL_UPDATE_RETRIES << " attempts." << "\n" << "Filename: " << mFilename << "\n" << "Disabling further update attempts for this file." << LL_ENDL; @@ -199,7 +198,7 @@ bool LLLocalGLTFMaterial::updateSelf() else { - LL_WARNS() << "During the update process, the following file was not found." << "\n" + LL_WARNS("GLTF") << "During the update process, the following file was not found." << "\n" << "Filename: " << mFilename << "\n" << "Disabling further update attempts for this file." << LL_ENDL; @@ -234,120 +233,24 @@ bool LLLocalGLTFMaterial::loadMaterial() case ET_MATERIAL_GLTF: case ET_MATERIAL_GLB: { - tinygltf::TinyGLTF loader; - std::string error_msg; - std::string warn_msg; - - tinygltf::Model model_in; - std::string filename_lc = mFilename; LLStringUtil::toLower(filename_lc); + std::string material_name; - // Load a tinygltf model fom a file. Assumes that the input filename has already been - // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish. - if (std::string::npos == filename_lc.rfind(".gltf")) - { // file is binary - decode_successful = loader.LoadBinaryFromFile(&model_in, &error_msg, &warn_msg, filename_lc); - } - else - { // file is ascii - decode_successful = loader.LoadASCIIFromFile(&model_in, &error_msg, &warn_msg, filename_lc); - } + // Might be a good idea to make these textures into local textures + LLTinyGLTFHelper::getMaterialFromFile( + mFilename, + mMaterialIndex, + mGLTFMaterial, + material_name, + mBaseColorFetched, + mNormalFetched, + mMRFetched, + mEmissiveFetched); - if (!decode_successful) + if (!material_name.empty()) { - LL_WARNS() << "Cannot load Material, error: " << error_msg - << ", warning:" << warn_msg - << " file: " << mFilename - << LL_ENDL; - break; - } - - if (model_in.materials.size() <= mMaterialIndex) - { - // materials are missing - LL_WARNS() << "Cannot load Material, Material " << mMaterialIndex << " is missing, " << mFilename << LL_ENDL; - decode_successful = false; - break; - } - - // sets everything, but textures will have inaccurate ids - mGLTFMaterial->setFromModel(model_in, mMaterialIndex); - - std::string folder = gDirUtilp->getDirName(filename_lc); - tinygltf::Material material_in = model_in.materials[mMaterialIndex]; - - if (!material_in.name.empty()) - { - mShortName = gDirUtilp->getBaseFileName(filename_lc, true) + " (" + material_in.name + ")"; - } - - // get base color texture - LLPointer base_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index); - // get normal map - LLPointer normal_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.normalTexture.index); - // get metallic-roughness texture - LLPointer mr_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index); - // get emissive texture - LLPointer emissive_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.emissiveTexture.index); - // get occlusion map if needed - LLPointer occlusion_img; - if (material_in.occlusionTexture.index != material_in.pbrMetallicRoughness.metallicRoughnessTexture.index) - { - occlusion_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.occlusionTexture.index); - } - - // todo: pass it into local bitmaps? - LLTinyGLTFHelper::initFetchedTextures(material_in, - base_img, normal_img, mr_img, emissive_img, occlusion_img, - mBaseColorFetched, mNormalFetched, mMRFetched, mEmissiveFetched); - - if (mBaseColorFetched) - { - mBaseColorFetched->addTextureStats(64.f * 64.f, TRUE); - mGLTFMaterial->mBaseColorId = mBaseColorFetched->getID(); - mGLTFMaterial->mBaseColorTexture = mBaseColorFetched; - } - else - { - mGLTFMaterial->mBaseColorId = LLUUID::null; - mGLTFMaterial->mBaseColorTexture = nullptr; - } - - if (mNormalFetched) - { - mNormalFetched->addTextureStats(64.f * 64.f, TRUE); - mGLTFMaterial->mNormalId = mNormalFetched->getID(); - mGLTFMaterial->mNormalTexture = mBaseColorFetched; - } - else - { - mGLTFMaterial->mNormalId = LLUUID::null; - mGLTFMaterial->mNormalTexture = nullptr; - } - - if (mMRFetched) - { - mMRFetched->addTextureStats(64.f * 64.f, TRUE); - mGLTFMaterial->mMetallicRoughnessId = mMRFetched->getID(); - mGLTFMaterial->mMetallicRoughnessTexture = mBaseColorFetched; - } - else - { - mGLTFMaterial->mMetallicRoughnessId = LLUUID::null; - mGLTFMaterial->mMetallicRoughnessTexture = nullptr; - } - - if (mEmissiveFetched) - { - mEmissiveFetched->addTextureStats(64.f * 64.f, TRUE); - mGLTFMaterial->mEmissiveId = mEmissiveFetched->getID(); - mGLTFMaterial->mEmissiveTexture = mBaseColorFetched; - } - else - { - mGLTFMaterial->mEmissiveId = LLUUID::null; - mGLTFMaterial->mEmissiveTexture = nullptr; + mShortName = gDirUtilp->getBaseFileName(filename_lc, true) + " (" + material_name + ")"; } break; @@ -359,9 +262,9 @@ bool LLLocalGLTFMaterial::loadMaterial() // accessing mFilename and any other object properties might very well crash the viewer. // getting here should be impossible, or there's been a pretty serious bug. - LL_WARNS() << "During a decode attempt, the following local material had no properly assigned extension." << LL_ENDL; - LL_WARNS() << "Filename: " << mFilename << LL_ENDL; - LL_WARNS() << "Disabling further update attempts for this file." << LL_ENDL; + LL_WARNS("GLTF") << "During a decode attempt, the following local material had no properly assigned extension." << LL_ENDL; + LL_WARNS("GLTF") << "Filename: " << mFilename << LL_ENDL; + LL_WARNS("GLTF") << "Disabling further update attempts for this file." << LL_ENDL; mLinkStatus = LS_BROKEN; } } @@ -461,7 +364,7 @@ S32 LLLocalGLTFMaterialMgr::addUnit(const std::string& filename) if (!decode_successful) { - LL_WARNS() << "Cannot load, error: Failed to decode" << error_msg + LL_WARNS("GLTF") << "Cannot load, error: Failed to decode" << error_msg << ", warning:" << warn_msg << " file: " << filename << LL_ENDL; @@ -471,7 +374,7 @@ S32 LLLocalGLTFMaterialMgr::addUnit(const std::string& filename) if (model_in.materials.empty()) { // materials are missing - LL_WARNS() << "Cannot load. File has no materials " << filename << LL_ENDL; + LL_WARNS("GLTF") << "Cannot load. File has no materials " << filename << LL_ENDL; return 0; } materials_in_file = model_in.materials.size(); @@ -492,7 +395,7 @@ S32 LLLocalGLTFMaterialMgr::addUnit(const std::string& filename) } else { - LL_WARNS() << "Attempted to add invalid or unreadable image file, attempt cancelled.\n" + LL_WARNS("GLTF") << "Attempted to add invalid or unreadable image file, attempt cancelled.\n" << "Filename: " << filename << LL_ENDL; LLSD notif_args; diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index c99e7307ed..cb28607903 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -65,26 +65,22 @@ const std::string MATERIAL_NORMAL_DEFAULT_NAME = "Normal"; const std::string MATERIAL_METALLIC_DEFAULT_NAME = "Metallic Roughness"; const std::string MATERIAL_EMISSIVE_DEFAULT_NAME = "Emissive"; -// Don't use ids here, LLPreview will attempt to use it as an inventory item -static const std::string LIVE_MATERIAL_EDITOR_KEY = "Live Editor"; - // Dirty flags static const U32 MATERIAL_BASE_COLOR_DIRTY = 0x1 << 0; -static const U32 MATERIAL_BASE_TRANSPARENCY_DIRTY = 0x1 << 1; -static const U32 MATERIAL_BASE_COLOR_TEX_DIRTY = 0x1 << 2; +static const U32 MATERIAL_BASE_COLOR_TEX_DIRTY = 0x1 << 1; -static const U32 MATERIAL_NORMAL_TEX_DIRTY = 0x1 << 3; +static const U32 MATERIAL_NORMAL_TEX_DIRTY = 0x1 << 2; -static const U32 MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY = 0x1 << 4; -static const U32 MATERIAL_METALLIC_ROUGHTNESS_METALNESS_DIRTY = 0x1 << 5; -static const U32 MATERIAL_METALLIC_ROUGHTNESS_ROUGHNESS_DIRTY = 0x1 << 6; +static const U32 MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY = 0x1 << 3; +static const U32 MATERIAL_METALLIC_ROUGHTNESS_METALNESS_DIRTY = 0x1 << 4; +static const U32 MATERIAL_METALLIC_ROUGHTNESS_ROUGHNESS_DIRTY = 0x1 << 5; -static const U32 MATERIAL_EMISIVE_COLOR_DIRTY = 0x1 << 7; -static const U32 MATERIAL_EMISIVE_TEX_DIRTY = 0x1 << 8; +static const U32 MATERIAL_EMISIVE_COLOR_DIRTY = 0x1 << 6; +static const U32 MATERIAL_EMISIVE_TEX_DIRTY = 0x1 << 7; -static const U32 MATERIAL_DOUBLE_SIDED_DIRTY = 0x1 << 9; -static const U32 MATERIAL_ALPHA_MODE_DIRTY = 0x1 << 10; -static const U32 MATERIAL_ALPHA_CUTOFF_DIRTY = 0x1 << 11; +static const U32 MATERIAL_DOUBLE_SIDED_DIRTY = 0x1 << 8; +static const U32 MATERIAL_ALPHA_MODE_DIRTY = 0x1 << 9; +static const U32 MATERIAL_ALPHA_CUTOFF_DIRTY = 0x1 << 10; LLUUID LLMaterialEditor::mOverrideObjectId; S32 LLMaterialEditor::mOverrideObjectTE = -1; @@ -327,8 +323,6 @@ LLMaterialEditor::LLMaterialEditor(const LLSD& key) { mAssetID = item->getAssetUUID(); } - // if this is a 'live editor' instance, it uses live overrides - mIsOverride = key.asString() == LIVE_MATERIAL_EDITOR_KEY; } void LLMaterialEditor::setObjectID(const LLUUID& object_id) @@ -352,6 +346,10 @@ void LLMaterialEditor::setAuxItem(const LLInventoryItem* item) BOOL LLMaterialEditor::postBuild() { + // if this is a 'live editor' instance, it is also + // single instacne and uses live overrides + mIsOverride = getIsSingleInstance(); + mBaseColorTextureCtrl = getChild("base_color_texture"); mMetallicTextureCtrl = getChild("metallic_roughness_texture"); mEmissiveTextureCtrl = getChild("emissive_texture"); @@ -362,15 +360,28 @@ BOOL LLMaterialEditor::postBuild() mEmissiveTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitEmissiveTexture, this, _1, _2)); mNormalTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitNormalTexture, this, _1, _2)); - childSetAction("save", boost::bind(&LLMaterialEditor::onClickSave, this)); - childSetAction("save_as", boost::bind(&LLMaterialEditor::onClickSaveAs, this)); - childSetAction("cancel", boost::bind(&LLMaterialEditor::onClickCancel, this)); + if (!mIsOverride) + { + childSetAction("save", boost::bind(&LLMaterialEditor::onClickSave, this)); + childSetAction("save_as", boost::bind(&LLMaterialEditor::onClickSaveAs, this)); + childSetAction("cancel", boost::bind(&LLMaterialEditor::onClickCancel, this)); + } - S32 upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); - getChild("base_color_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost)); - getChild("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost)); - getChild("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost)); - getChild("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost)); + if (mIsOverride) + { + childSetVisible("base_color_upload_fee", FALSE); + childSetVisible("metallic_upload_fee", FALSE); + childSetVisible("emissive_upload_fee", FALSE); + childSetVisible("normal_upload_fee", FALSE); + } + else + { + S32 upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); + getChild("base_color_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost)); + getChild("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost)); + getChild("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost)); + getChild("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost)); + } boost::function changes_callback = [this](LLUICtrl * ctrl, void* userData) { @@ -384,7 +395,7 @@ BOOL LLMaterialEditor::postBuild() // BaseColor childSetCommitCallback("base color", changes_callback, (void*)&MATERIAL_BASE_COLOR_DIRTY); - childSetCommitCallback("transparency", changes_callback, (void*)&MATERIAL_BASE_TRANSPARENCY_DIRTY); + childSetCommitCallback("transparency", changes_callback, (void*)&MATERIAL_BASE_COLOR_DIRTY); childSetCommitCallback("alpha mode", changes_callback, (void*)&MATERIAL_ALPHA_MODE_DIRTY); childSetCommitCallback("alpha cutoff", changes_callback, (void*)&MATERIAL_ALPHA_CUTOFF_DIRTY); @@ -395,9 +406,14 @@ BOOL LLMaterialEditor::postBuild() // Emissive childSetCommitCallback("emissive color", changes_callback, (void*)&MATERIAL_EMISIVE_COLOR_DIRTY); - childSetVisible("unsaved_changes", mUnsavedChanges && !mIsOverride); + if (!mIsOverride) + { + // "unsaved_changes" doesn't exist in live editor + childSetVisible("unsaved_changes", mUnsavedChanges); - getChild("total_upload_fee")->setTextArg("[FEE]", llformat("%d", 0)); + // Doesn't exist in live editor + getChild("total_upload_fee")->setTextArg("[FEE]", llformat("%d", 0)); + } // Todo: // Disable/enable setCanApplyImmediately() based on @@ -408,7 +424,7 @@ BOOL LLMaterialEditor::postBuild() void LLMaterialEditor::onClickCloseBtn(bool app_quitting) { - if (app_quitting) + if (app_quitting || mIsOverride) { closeFloater(app_quitting); } @@ -619,18 +635,27 @@ void LLMaterialEditor::setDoubleSided(bool double_sided) void LLMaterialEditor::resetUnsavedChanges() { mUnsavedChanges = 0; - childSetVisible("unsaved_changes", false); - setCanSave(false); + if (!mIsOverride) + { + childSetVisible("unsaved_changes", false); + setCanSave(false); - mExpectedUploadCost = 0; - getChild("total_upload_fee")->setTextArg("[FEE]", llformat("%d", mExpectedUploadCost)); + mExpectedUploadCost = 0; + getChild("total_upload_fee")->setTextArg("[FEE]", llformat("%d", mExpectedUploadCost)); + } } void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag) { mUnsavedChanges |= dirty_flag; - // at the moment live editing (mIsOverride) applies everything 'live' - childSetVisible("unsaved_changes", mUnsavedChanges && !mIsOverride); + if (!mIsOverride) + { + // at the moment live editing (mIsOverride) applies everything 'live' + // and "unsaved_changes", save/cancel buttons don't exist there + return; + } + + childSetVisible("unsaved_changes", mUnsavedChanges); if (mUnsavedChanges) { @@ -674,12 +699,18 @@ void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag) void LLMaterialEditor::setCanSaveAs(bool value) { - childSetEnabled("save_as", value); + if (!mIsOverride) + { + childSetEnabled("save_as", value); + } } void LLMaterialEditor::setCanSave(bool value) { - childSetEnabled("save", value); + if (!mIsOverride) + { + childSetEnabled("save", value); + } } void LLMaterialEditor::setEnableEditing(bool can_modify) @@ -711,21 +742,24 @@ void LLMaterialEditor::setEnableEditing(bool can_modify) void LLMaterialEditor::onCommitBaseColorTexture(LLUICtrl * ctrl, const LLSD & data) { - // might be better to use arrays, to have a single callback - // and not to repeat the same thing for each tecture control - LLUUID new_val = mBaseColorTextureCtrl->getValue().asUUID(); - if (new_val == mBaseColorTextureUploadId && mBaseColorTextureUploadId.notNull()) + if (!mIsOverride) { - childSetValue("base_color_upload_fee", getString("upload_fee_string")); - } - else - { - // Texture picker has 'apply now' with 'cancel' support. - // Keep mBaseColorJ2C and mBaseColorFetched, it's our storage in - // case user decides to cancel changes. - // Without mBaseColorFetched, viewer will eventually cleanup - // the texture that is not in use - childSetValue("base_color_upload_fee", getString("no_upload_fee_string")); + // might be better to use arrays, to have a single callback + // and not to repeat the same thing for each tecture control + LLUUID new_val = mBaseColorTextureCtrl->getValue().asUUID(); + if (new_val == mBaseColorTextureUploadId && mBaseColorTextureUploadId.notNull()) + { + childSetValue("base_color_upload_fee", getString("upload_fee_string")); + } + else + { + // Texture picker has 'apply now' with 'cancel' support. + // Keep mBaseColorJ2C and mBaseColorFetched, it's our storage in + // case user decides to cancel changes. + // Without mBaseColorFetched, viewer will eventually cleanup + // the texture that is not in use + childSetValue("base_color_upload_fee", getString("no_upload_fee_string")); + } } markChangesUnsaved(MATERIAL_BASE_COLOR_TEX_DIRTY); applyToSelection(); @@ -733,14 +767,17 @@ void LLMaterialEditor::onCommitBaseColorTexture(LLUICtrl * ctrl, const LLSD & da void LLMaterialEditor::onCommitMetallicTexture(LLUICtrl * ctrl, const LLSD & data) { - LLUUID new_val = mMetallicTextureCtrl->getValue().asUUID(); - if (new_val == mMetallicTextureUploadId && mMetallicTextureUploadId.notNull()) + if (!mIsOverride) { - childSetValue("metallic_upload_fee", getString("upload_fee_string")); - } - else - { - childSetValue("metallic_upload_fee", getString("no_upload_fee_string")); + LLUUID new_val = mMetallicTextureCtrl->getValue().asUUID(); + if (new_val == mMetallicTextureUploadId && mMetallicTextureUploadId.notNull()) + { + childSetValue("metallic_upload_fee", getString("upload_fee_string")); + } + else + { + childSetValue("metallic_upload_fee", getString("no_upload_fee_string")); + } } markChangesUnsaved(MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY); applyToSelection(); @@ -748,14 +785,17 @@ void LLMaterialEditor::onCommitMetallicTexture(LLUICtrl * ctrl, const LLSD & dat void LLMaterialEditor::onCommitEmissiveTexture(LLUICtrl * ctrl, const LLSD & data) { - LLUUID new_val = mEmissiveTextureCtrl->getValue().asUUID(); - if (new_val == mEmissiveTextureUploadId && mEmissiveTextureUploadId.notNull()) + if (!mIsOverride) { - childSetValue("emissive_upload_fee", getString("upload_fee_string")); - } - else - { - childSetValue("emissive_upload_fee", getString("no_upload_fee_string")); + LLUUID new_val = mEmissiveTextureCtrl->getValue().asUUID(); + if (new_val == mEmissiveTextureUploadId && mEmissiveTextureUploadId.notNull()) + { + childSetValue("emissive_upload_fee", getString("upload_fee_string")); + } + else + { + childSetValue("emissive_upload_fee", getString("no_upload_fee_string")); + } } markChangesUnsaved(MATERIAL_EMISIVE_TEX_DIRTY); applyToSelection(); @@ -763,14 +803,17 @@ void LLMaterialEditor::onCommitEmissiveTexture(LLUICtrl * ctrl, const LLSD & dat void LLMaterialEditor::onCommitNormalTexture(LLUICtrl * ctrl, const LLSD & data) { - LLUUID new_val = mNormalTextureCtrl->getValue().asUUID(); - if (new_val == mNormalTextureUploadId && mNormalTextureUploadId.notNull()) + if (!mIsOverride) { - childSetValue("normal_upload_fee", getString("upload_fee_string")); - } - else - { - childSetValue("normal_upload_fee", getString("no_upload_fee_string")); + LLUUID new_val = mNormalTextureCtrl->getValue().asUUID(); + if (new_val == mNormalTextureUploadId && mNormalTextureUploadId.notNull()) + { + childSetValue("normal_upload_fee", getString("upload_fee_string")); + } + else + { + childSetValue("normal_upload_fee", getString("no_upload_fee_string")); + } } markChangesUnsaved(MATERIAL_NORMAL_TEX_DIRTY); applyToSelection(); @@ -1415,73 +1458,6 @@ void LLMaterialEditor::onCancelMsgCallback(const LLSD& notification, const LLSD& S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (0 == option) { - if (mIsOverride && !mObjectOverridesSavedValues.empty()) - { - // Reapply ids back onto selection. - // TODO: monitor selection changes and resave on selection changes - struct g : public LLSelectedObjectFunctor - { - g(LLMaterialEditor* me) : mEditor(me) {} - virtual bool apply(LLViewerObject* objectp) - { - if (!objectp || !objectp->permModify()) - { - return false; - } - - U32 local_id = objectp->getLocalID(); - if (mEditor->mObjectOverridesSavedValues.find(local_id) == mEditor->mObjectOverridesSavedValues.end()) - { - return false; - } - - S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); - for (U8 te = 0; te < num_tes; te++) - { - if (mEditor->mObjectOverridesSavedValues[local_id].size() > te - && objectp->getTE(te)->isSelected()) - { - objectp->setRenderMaterialID( - te, - mEditor->mObjectOverridesSavedValues[local_id][te], - false /*wait for bulk update*/); - } - } - return true; - } - LLMaterialEditor* mEditor; - } restorefunc(this); - LLSelectMgr::getInstance()->getSelection()->applyToObjects(&restorefunc); - - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - if (object && !object->permModify()) - { - return false; - } - - LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)object->getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL); - if (param_block) - { - if (param_block->isEmpty()) - { - object->setHasRenderMaterialParams(false); - } - else - { - object->parameterChanged(LLNetworkData::PARAMS_RENDER_MATERIAL, true); - } - } - - object->sendTEUpdate(); - return true; - } - } sendfunc; - LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc); - } - closeFloater(); } } @@ -1631,46 +1607,11 @@ void LLMaterialEditor::onSelectionChanged() clearTextures(); setFromSelection(); } - - // At the moment all cahges are 'live' so don't reset dirty flags - // saveLiveValues(); todo -} - -void LLMaterialEditor::saveLiveValues() -{ - // Collect ids to be able to revert overrides. - // TODO: monitor selection changes and resave on selection changes - mObjectOverridesSavedValues.clear(); - struct g : public LLSelectedObjectFunctor - { - g(LLMaterialEditor* me) : mEditor(me) {} - virtual bool apply(LLViewerObject* objectp) - { - if (!objectp) - { - return false; - } - - U32 local_id = objectp->getLocalID(); - S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); - for (U8 te = 0; te < num_tes; te++) - { - // Todo: fix this, overrides don't care about ids, - // we will have to save actual values or materials - LLUUID mat_id = objectp->getRenderMaterialID(te); - mEditor->mObjectOverridesSavedValues[local_id].push_back(mat_id); - } - return true; - } - LLMaterialEditor* mEditor; - } savefunc(this); - LLSelectMgr::getInstance()->getSelection()->applyToObjects(&savefunc); } void LLMaterialEditor::updateLive() { - const LLSD floater_key(LIVE_MATERIAL_EDITOR_KEY); - LLFloater* instance = LLFloaterReg::findInstance("material_editor", floater_key); + LLFloater* instance = LLFloaterReg::findInstance("live_material_editor"); if (instance && LLFloater::isVisible(instance)) { LLMaterialEditor* me = (LLMaterialEditor*)instance; @@ -1691,8 +1632,7 @@ void LLMaterialEditor::updateLive(const LLUUID &object_id, S32 te) // Not an update we are waiting for return; } - const LLSD floater_key(LIVE_MATERIAL_EDITOR_KEY); - LLFloater* instance = LLFloaterReg::findInstance("material_editor", floater_key); + LLFloater* instance = LLFloaterReg::findInstance("live_material_editor"); if (instance && LLFloater::isVisible(instance)) { LLMaterialEditor* me = (LLMaterialEditor*)instance; @@ -1707,26 +1647,19 @@ void LLMaterialEditor::updateLive(const LLUUID &object_id, S32 te) void LLMaterialEditor::loadLive() { - // Allow only one 'live' instance - const LLSD floater_key(LIVE_MATERIAL_EDITOR_KEY); - LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor", floater_key); + LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("live_material_editor"); if (me) { me->mOverrideInProgress = false; me->setFromSelection(); - me->setTitle(me->getString("material_override_title")); - me->childSetVisible("save", false); - me->childSetVisible("save_as", false); // Set up for selection changes updates if (!me->mSelectionUpdateSlot.connected()) { me->mSelectionUpdateSlot = LLSelectMgr::instance().mUpdateSignal.connect(boost::bind(&LLMaterialEditor::onSelectionChanged, me)); } - // Collect ids to be able to revert overrides on cancel. - me->saveLiveValues(); - me->openFloater(floater_key); + me->openFloater(); me->setFocus(TRUE); } } @@ -2227,10 +2160,17 @@ private: class LLRenderMaterialOverrideFunctor : public LLSelectedTEFunctor { public: - LLRenderMaterialOverrideFunctor(LLMaterialEditor * me, std::string const & url) - : mEditor(me), mCapUrl(url) + LLRenderMaterialOverrideFunctor( + LLMaterialEditor * me, + std::string const & url, + const LLUUID &report_on_object_id, + S32 report_on_te) + : mEditor(me) + , mCapUrl(url) + , mSuccess(false) + , mObjectId(report_on_object_id) + , mObjectTE(report_on_te) { - } bool apply(LLViewerObject* objectp, S32 te) override @@ -2263,66 +2203,71 @@ public: // Override object's values with values from editor where appropriate if (mEditor->getUnsavedChangesFlags() & MATERIAL_BASE_COLOR_DIRTY) { - material->mBaseColor = mEditor->getBaseColor(); - } - if (mEditor->getUnsavedChangesFlags() & MATERIAL_BASE_TRANSPARENCY_DIRTY) - { - material->mBaseColor.mV[3] = mEditor->getTransparency(); + material->setBaseColorFactor(mEditor->getBaseColor(), true); } if (mEditor->getUnsavedChangesFlags() & MATERIAL_BASE_COLOR_TEX_DIRTY) { - material->mBaseColorId = mEditor->getBaseColorId(); + material->setBaseColorId(mEditor->getBaseColorId(), true); } if (mEditor->getUnsavedChangesFlags() & MATERIAL_NORMAL_TEX_DIRTY) { - material->mNormalId = mEditor->getNormalId(); + material->setNormalId(mEditor->getNormalId(), true); } if (mEditor->getUnsavedChangesFlags() & MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY) { - material->mMetallicRoughnessId = mEditor->getMetallicRoughnessId(); + material->setMetallicRoughnessId(mEditor->getMetallicRoughnessId(), true); } if (mEditor->getUnsavedChangesFlags() & MATERIAL_METALLIC_ROUGHTNESS_METALNESS_DIRTY) { - material->mMetallicFactor = mEditor->getMetalnessFactor(); + material->setMetallicFactor(mEditor->getMetalnessFactor(), true); } if (mEditor->getUnsavedChangesFlags() & MATERIAL_METALLIC_ROUGHTNESS_ROUGHNESS_DIRTY) { - material->mRoughnessFactor = mEditor->getRoughnessFactor(); + material->setRoughnessFactor(mEditor->getRoughnessFactor(), true); } if (mEditor->getUnsavedChangesFlags() & MATERIAL_EMISIVE_COLOR_DIRTY) { - material->mEmissiveColor = mEditor->getEmissiveColor(); + material->setEmissiveColorFactor(LLColor3(mEditor->getEmissiveColor()), true); } if (mEditor->getUnsavedChangesFlags() & MATERIAL_EMISIVE_TEX_DIRTY) { - material->mEmissiveId = mEditor->getEmissiveId(); + material->setEmissiveId(mEditor->getEmissiveId(), true); } if (mEditor->getUnsavedChangesFlags() & MATERIAL_DOUBLE_SIDED_DIRTY) { - material->mDoubleSided = mEditor->getDoubleSided(); + material->setDoubleSided(mEditor->getDoubleSided(), true); } if (mEditor->getUnsavedChangesFlags() & MATERIAL_ALPHA_MODE_DIRTY) { - material->setAlphaMode(mEditor->getAlphaMode()); + material->setAlphaMode(mEditor->getAlphaMode(), true); } if (mEditor->getUnsavedChangesFlags() & MATERIAL_ALPHA_CUTOFF_DIRTY) { - material->mAlphaCutoff = mEditor->getAlphaCutoff(); + material->setAlphaCutoff(mEditor->getAlphaCutoff(), true); } std::string overrides_json = material->asJSON(); - LLSD overrides = llsd::map( "object_id", objectp->getID(), "side", te, "gltf_json", overrides_json ); - LLCoros::instance().launch("modifyMaterialCoro", std::bind(&LLGLTFMaterialList::modifyMaterialCoro, mCapUrl, overrides, modifyCallback)); + + void(*done_callback)(bool) = nullptr; + if (mObjectTE == te + && mObjectId == objectp->getID()) + { + mSuccess = true; + // We only want callback for face we are displayig material from + // even if we are setting all of them + done_callback = modifyCallback; + } + LLCoros::instance().launch("modifyMaterialCoro", std::bind(&LLGLTFMaterialList::modifyMaterialCoro, mCapUrl, overrides, done_callback)); } return true; } @@ -2334,12 +2279,17 @@ public: // something went wrong update selection LLMaterialEditor::updateLive(); } - // else we will get updateLive(obj, id) from aplied overrides + // else we will get updateLive(obj, id) from applied overrides } + bool getResult() { return mSuccess; } + private: LLMaterialEditor * mEditor; std::string mCapUrl; + LLUUID mObjectId; + S32 mObjectTE; + bool mSuccess; }; void LLMaterialEditor::applyToSelection() @@ -2363,9 +2313,11 @@ void LLMaterialEditor::applyToSelection() { mOverrideInProgress = true; LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); - LLRenderMaterialOverrideFunctor override_func(this, url); - if (!selected_objects->applyToTEs(&override_func)) + LLRenderMaterialOverrideFunctor override_func(this, url, mOverrideObjectId, mOverrideObjectTE); + selected_objects->applyToTEs(&override_func); + if (!override_func.getResult()) { + // OverrideFunctor didn't find expected object or face mOverrideInProgress = false; } diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h index 49f3baf0c7..0ffad5f54a 100644 --- a/indra/newview/llmaterialeditor.h +++ b/indra/newview/llmaterialeditor.h @@ -104,7 +104,6 @@ public: static void loadMaterialFromFile(const std::string& filename, S32 index = -1); void onSelectionChanged(); // live overrides selection changes - void saveLiveValues(); // for restoration on cancel static void updateLive(); static void updateLive(const LLUUID &object_id, S32 te); @@ -293,7 +292,6 @@ private: // for "cancel" support static LLUUID mOverrideObjectId; // static to avoid searching for the floater static S32 mOverrideObjectTE; - std::map mObjectOverridesSavedValues; boost::signals2::connection mSelectionUpdateSlot; }; diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index e1d0a0aef8..1c70649391 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -2816,11 +2816,11 @@ void LLPanelFace::updateVisibility() { updateShinyControls(); } - getChildView("shinyScaleU")->setVisible(show_shininess || show_pbr_normal); - getChildView("shinyScaleV")->setVisible(show_shininess || show_pbr_normal); - getChildView("shinyRot")->setVisible(show_shininess || show_pbr_normal); - getChildView("shinyOffsetU")->setVisible(show_shininess || show_pbr_normal); - getChildView("shinyOffsetV")->setVisible(show_shininess || show_pbr_normal); + getChildView("shinyScaleU")->setVisible(show_shininess || show_pbr_metallic); + getChildView("shinyScaleV")->setVisible(show_shininess || show_pbr_metallic); + getChildView("shinyRot")->setVisible(show_shininess || show_pbr_metallic); + getChildView("shinyOffsetU")->setVisible(show_shininess || show_pbr_metallic); + getChildView("shinyOffsetV")->setVisible(show_shininess || show_pbr_metallic); // Normal map controls if (show_bumpiness) @@ -2830,11 +2830,11 @@ void LLPanelFace::updateVisibility() getChildView("bumpytexture control")->setVisible(show_bumpiness); getChildView("combobox bumpiness")->setVisible(show_bumpiness); getChildView("label bumpiness")->setVisible(show_bumpiness); - getChildView("bumpyScaleU")->setVisible(show_bumpiness || show_pbr_metallic); - getChildView("bumpyScaleV")->setVisible(show_bumpiness || show_pbr_metallic); - getChildView("bumpyRot")->setVisible(show_bumpiness || show_pbr_metallic); - getChildView("bumpyOffsetU")->setVisible(show_bumpiness || show_pbr_metallic); - getChildView("bumpyOffsetV")->setVisible(show_bumpiness || show_pbr_metallic); + getChildView("bumpyScaleU")->setVisible(show_bumpiness || show_pbr_normal); + getChildView("bumpyScaleV")->setVisible(show_bumpiness || show_pbr_normal); + getChildView("bumpyRot")->setVisible(show_bumpiness || show_pbr_normal); + getChildView("bumpyOffsetU")->setVisible(show_bumpiness || show_pbr_normal); + getChildView("bumpyOffsetV")->setVisible(show_bumpiness || show_pbr_normal); // PBR controls getChildView("pbr_control")->setVisible(show_pbr); diff --git a/indra/newview/lltinygltfhelper.cpp b/indra/newview/lltinygltfhelper.cpp index c80e87652a..cff26ea51f 100644 --- a/indra/newview/lltinygltfhelper.cpp +++ b/indra/newview/lltinygltfhelper.cpp @@ -181,3 +181,127 @@ LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tiny return rawImage; } + +bool LLTinyGLTFHelper::getMaterialFromFile( + const std::string& filename, + S32 mat_index, + LLPointer < LLFetchedGLTFMaterial> material, + std::string& material_name, + LLPointer& base_color_tex, + LLPointer& normal_tex, + LLPointer& mr_tex, + LLPointer& emissive_tex) +{ + tinygltf::TinyGLTF loader; + std::string error_msg; + std::string warn_msg; + tinygltf::Model model_in; + std::string filename_lc = filename; + bool decode_successful = true; + + LLStringUtil::toLower(filename_lc); + + // Load a tinygltf model fom a file. Assumes that the input filename has already been + // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish. + if (std::string::npos == filename_lc.rfind(".gltf")) + { // file is binary + decode_successful = loader.LoadBinaryFromFile(&model_in, &error_msg, &warn_msg, filename_lc); + } + else + { // file is ascii + decode_successful = loader.LoadASCIIFromFile(&model_in, &error_msg, &warn_msg, filename_lc); + } + + if (!decode_successful) + { + LL_WARNS("GLTF") << "Cannot load Material, error: " << error_msg + << ", warning:" << warn_msg + << " file: " << filename + << LL_ENDL; + return false; + } + else if (model_in.materials.size() <= mat_index) + { + // materials are missing + LL_WARNS("GLTF") << "Cannot load Material, Material " << mat_index << " is missing, " << filename << LL_ENDL; + return false; + } + + material->setFromModel(model_in, mat_index); + + std::string folder = gDirUtilp->getDirName(filename_lc); + tinygltf::Material material_in = model_in.materials[mat_index]; + + material_name = material_in.name; + + // get base color texture + LLPointer base_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index); + // get normal map + LLPointer normal_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.normalTexture.index); + // get metallic-roughness texture + LLPointer mr_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index); + // get emissive texture + LLPointer emissive_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.emissiveTexture.index); + // get occlusion map if needed + LLPointer occlusion_img; + if (material_in.occlusionTexture.index != material_in.pbrMetallicRoughness.metallicRoughnessTexture.index) + { + occlusion_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.occlusionTexture.index); + } + + // todo: pass it into local bitmaps? + LLTinyGLTFHelper::initFetchedTextures(material_in, + base_img, normal_img, mr_img, emissive_img, occlusion_img, + base_color_tex, normal_tex, mr_tex, emissive_tex); + + if (base_color_tex) + { + base_color_tex->addTextureStats(64.f * 64.f, TRUE); + material->mBaseColorId = base_color_tex->getID(); + material->mBaseColorTexture = base_color_tex; + } + else + { + material->mBaseColorId = LLUUID::null; + material->mBaseColorTexture = nullptr; + } + + if (normal_tex) + { + normal_tex->addTextureStats(64.f * 64.f, TRUE); + material->mNormalId = normal_tex->getID(); + material->mNormalTexture = normal_tex; + } + else + { + material->mNormalId = LLUUID::null; + material->mNormalTexture = nullptr; + } + + if (mr_tex) + { + mr_tex->addTextureStats(64.f * 64.f, TRUE); + material->mMetallicRoughnessId = mr_tex->getID(); + material->mMetallicRoughnessTexture = mr_tex; + } + else + { + material->mMetallicRoughnessId = LLUUID::null; + material->mMetallicRoughnessTexture = nullptr; + } + + if (emissive_tex) + { + emissive_tex->addTextureStats(64.f * 64.f, TRUE); + material->mEmissiveId = emissive_tex->getID(); + material->mEmissiveTexture = emissive_tex; + } + else + { + material->mEmissiveId = LLUUID::null; + material->mEmissiveTexture = nullptr; + } + + return true; + +} diff --git a/indra/newview/lltinygltfhelper.h b/indra/newview/lltinygltfhelper.h index 9c2e5afc17..48a6985641 100644 --- a/indra/newview/lltinygltfhelper.h +++ b/indra/newview/lltinygltfhelper.h @@ -27,6 +27,7 @@ #pragma once #include "llgltfmaterial.h" +#include "llgltfmateriallist.h" #include "llpointer.h" #include "tinygltf/tiny_gltf.h" @@ -40,6 +41,18 @@ namespace LLTinyGLTFHelper LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index, std::string& name); LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index); + LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index); + + bool getMaterialFromFile( + const std::string& filename, + S32 mat_index, + LLPointer < LLFetchedGLTFMaterial> material, + std::string& material_name, + LLPointer& base_color_tex, + LLPointer& normal_tex, + LLPointer& mr_tex, + LLPointer& emissive_tex); + void initFetchedTextures(tinygltf::Material& material, LLPointer& base_color_img, LLPointer& normal_img, diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index b31b564efe..37facf3bda 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -418,6 +418,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("script_colors", "floater_script_ed_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("material_editor", "floater_material_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("live_material_editor", "floater_live_material_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("telehubs", "floater_telehub.xml",&LLFloaterReg::build); LLFloaterReg::add("test_inspectors", "floater_test_inspectors.xml", &LLFloaterReg::build); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 056b0b32c8..fec46b3a83 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -5523,6 +5523,7 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri S32 LLViewerObject::setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* override_mat) { + LL_PROFILE_ZONE_SCOPED; S32 retval = TEM_CHANGE_NONE; LLTextureEntry* tep = getTE(te); diff --git a/indra/newview/skins/default/xui/en/floater_live_material_editor.xml b/indra/newview/skins/default/xui/en/floater_live_material_editor.xml new file mode 100644 index 0000000000..317783f794 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_live_material_editor.xml @@ -0,0 +1,37 @@ + + + + + + diff --git a/indra/newview/skins/default/xui/en/floater_material_editor.xml b/indra/newview/skins/default/xui/en/floater_material_editor.xml index 84264cd2e6..29def9bd53 100644 --- a/indra/newview/skins/default/xui/en/floater_material_editor.xml +++ b/indra/newview/skins/default/xui/en/floater_material_editor.xml @@ -27,430 +27,17 @@ layout="topleft" color="DkGray2" opaque="true" - reserve_scroll_corner="false" - > + reserve_scroll_corner="false"> - - - - Base Color: - - - - No upload fee - - - Tint - - - - Transparency - - - - Alpha mode - - - - - - - - Alpha Cutoff - - - - - - Metallic-Roughness: - - - - No upload fee - - - Metallic Factor - - - - Roughness Factor - - - - - - Emissive: - - - - No upload fee - - - Tint - - - - - - - Normal: - - - - No upload fee - - - + name="panel_material" + filename="panel_gltf_material.xml" + border="false" + visible="true" + layout="topleft" + top="0" + left="0" + height="768" + width="247" /> + + + + + Base Color: + + + + No upload fee + + + Tint + + + + Transparency + + + + Alpha mode + + + + + + + + Alpha Cutoff + + + + + + Metallic-Roughness: + + + + No upload fee + + + Metallic Factor + + + + Roughness Factor + + + + + + Emissive: + + + + No upload fee + + + Tint + + + + + + Normal: + + + + No upload fee + + +