diff options
author | Erik Kundiman <erik@megapahit.org> | 2023-11-07 06:50:28 +0800 |
---|---|---|
committer | Erik Kundiman <erik@megapahit.org> | 2023-11-07 06:50:28 +0800 |
commit | 3d1d8bf5f12ce91c5d9b764bd2b5aacfe44549ee (patch) | |
tree | e025b95df00631c9d97c5406d6d744d0009899a9 | |
parent | cd8470549bb2550acedca9bb78cb9b4580059170 (diff) | |
parent | afa45530f745af8c9d595948ac957b12664cca2c (diff) |
Merge remote-tracking branch 'secondlife/DRTVWR-559' into DRTVWR-559
-rw-r--r-- | indra/llinventory/llinventory.cpp | 173 | ||||
-rw-r--r-- | indra/llprimitive/llgltfmaterial.cpp | 52 | ||||
-rw-r--r-- | indra/llprimitive/llgltfmaterial.h | 13 | ||||
-rw-r--r-- | indra/newview/llfetchedgltfmaterial.cpp | 77 | ||||
-rw-r--r-- | indra/newview/llfetchedgltfmaterial.h | 7 | ||||
-rw-r--r-- | indra/newview/llfloaterchangeitemthumbnail.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llinventorymodel.cpp | 15 | ||||
-rw-r--r-- | indra/newview/lllocalbitmaps.cpp | 159 | ||||
-rw-r--r-- | indra/newview/lllocalbitmaps.h | 38 | ||||
-rw-r--r-- | indra/newview/lllocalgltfmaterials.cpp | 9 | ||||
-rw-r--r-- | indra/newview/lllocalgltfmaterials.h | 4 | ||||
-rw-r--r-- | indra/newview/llmaterialeditor.cpp | 297 | ||||
-rw-r--r-- | indra/newview/llmaterialeditor.h | 13 | ||||
-rw-r--r-- | indra/newview/llpanelprofile.cpp | 4 | ||||
-rw-r--r-- | indra/newview/lltexturectrl.cpp | 27 | ||||
-rw-r--r-- | indra/newview/lltexturectrl.h | 12 | ||||
-rw-r--r-- | indra/newview/llviewerobject.cpp | 5 |
17 files changed, 695 insertions, 212 deletions
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 2de5af94a3..55bcc7c5b2 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -905,155 +905,7 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) mAssetUUID.setNull(); } -#if 0 // old implementation. makes a LOT of temporary copies and LLSD::safe(impl) calls - std::string w; - - w = INV_ITEM_ID_LABEL; - if (sd.has(w)) - { - mUUID = sd[w]; - } - w = INV_PARENT_ID_LABEL; - if (sd.has(w)) - { - mParentUUID = sd[w]; - } - mThumbnailUUID.setNull(); - w = INV_THUMBNAIL_LABEL; - if (sd.has(w)) - { - const LLSD &thumbnail_map = sd[w]; - w = INV_ASSET_ID_LABEL; - if (thumbnail_map.has(w)) - { - mThumbnailUUID = thumbnail_map[w]; - } - /* Example: - <key> asset_id </key> - <uuid> acc0ec86 - 17f2 - 4b92 - ab41 - 6718b1f755f7 </uuid> - <key> perms </key> - <integer> 8 </integer> - <key>service</key> - <integer> 3 </integer> - <key>version</key> - <integer> 1 </key> - */ - } - else - { - w = INV_THUMBNAIL_ID_LABEL; - if (sd.has(w)) - { - mThumbnailUUID = sd[w].asUUID(); - } - } - w = INV_PERMISSIONS_LABEL; - if (sd.has(w)) - { - mPermissions = ll_permissions_from_sd(sd[w]); - } - w = INV_SALE_INFO_LABEL; - if (sd.has(w)) - { - // Sale info used to contain next owner perm. It is now in - // the permissions. Thus, we read that out, and fix legacy - // objects. It's possible this op would fail, but it - // should pick up the vast majority of the tasks. - BOOL has_perm_mask = FALSE; - U32 perm_mask = 0; - if (!mSaleInfo.fromLLSD(sd[w], has_perm_mask, perm_mask)) - { - goto fail; - } - if (has_perm_mask) - { - if(perm_mask == PERM_NONE) - { - perm_mask = mPermissions.getMaskOwner(); - } - // fair use fix. - if(!(perm_mask & PERM_COPY)) - { - perm_mask |= PERM_TRANSFER; - } - mPermissions.setMaskNext(perm_mask); - } - } - w = INV_SHADOW_ID_LABEL; - if (sd.has(w)) - { - mAssetUUID = sd[w]; - LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); - cipher.decrypt(mAssetUUID.mData, UUID_BYTES); - } - w = INV_ASSET_ID_LABEL; - if (sd.has(w)) - { - mAssetUUID = sd[w]; - } - w = INV_LINKED_ID_LABEL; - if (sd.has(w)) - { - mAssetUUID = sd[w]; - } - w = INV_ASSET_TYPE_LABEL; - if (sd.has(w)) - { - if (sd[w].isString()) - { - mType = LLAssetType::lookup(sd[w].asString().c_str()); - } - else if (sd[w].isInteger()) - { - S8 type = (U8)sd[w].asInteger(); - mType = static_cast<LLAssetType::EType>(type); - } - } - w = INV_INVENTORY_TYPE_LABEL; - if (sd.has(w)) - { - if (sd[w].isString()) - { - mInventoryType = LLInventoryType::lookup(sd[w].asString().c_str()); - } - else if (sd[w].isInteger()) - { - S8 type = (U8)sd[w].asInteger(); - mInventoryType = static_cast<LLInventoryType::EType>(type); - } - } - w = INV_FLAGS_LABEL; - if (sd.has(w)) - { - if (sd[w].isBinary()) - { - mFlags = ll_U32_from_sd(sd[w]); - } - else if(sd[w].isInteger()) - { - mFlags = sd[w].asInteger(); - } - } - w = INV_NAME_LABEL; - if (sd.has(w)) - { - mName = sd[w].asString(); - LLStringUtil::replaceNonstandardASCII(mName, ' '); - LLStringUtil::replaceChar(mName, '|', ' '); - } - w = INV_DESC_LABEL; - if (sd.has(w)) - { - mDescription = sd[w].asString(); - LLStringUtil::replaceNonstandardASCII(mDescription, ' '); - } - w = INV_CREATION_DATE_LABEL; - if (sd.has(w)) - { - mCreationDate = sd[w].asInteger(); - } -#else // if 0 - new implementation follows - + // TODO - figure out if this should be moved into the noclobber fields above mThumbnailUUID.setNull(); // iterate as map to avoid making unnecessary temp copies of everything @@ -1064,11 +916,13 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) if (i->first == INV_ITEM_ID_LABEL) { mUUID = i->second; + continue; } if (i->first == INV_PARENT_ID_LABEL) { mParentUUID = i->second; + continue; } if (i->first == INV_THUMBNAIL_LABEL) @@ -1089,16 +943,19 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) <key>version</key> <integer> 1 </key> */ - } + continue; + } if (i->first == INV_THUMBNAIL_ID_LABEL) { mThumbnailUUID = i->second.asUUID(); + continue; } if (i->first == INV_PERMISSIONS_LABEL) { mPermissions = ll_permissions_from_sd(i->second); + continue; } if (i->first == INV_SALE_INFO_LABEL) @@ -1111,7 +968,7 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) U32 perm_mask = 0; if (!mSaleInfo.fromLLSD(i->second, has_perm_mask, perm_mask)) { - goto fail; + return false; } if (has_perm_mask) { @@ -1126,6 +983,7 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) } mPermissions.setMaskNext(perm_mask); } + continue; } if (i->first == INV_SHADOW_ID_LABEL) @@ -1133,16 +991,19 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) mAssetUUID = i->second; LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); cipher.decrypt(mAssetUUID.mData, UUID_BYTES); + continue; } if (i->first == INV_ASSET_ID_LABEL) { mAssetUUID = i->second; + continue; } if (i->first == INV_LINKED_ID_LABEL) { mAssetUUID = i->second; + continue; } if (i->first == INV_ASSET_TYPE_LABEL) @@ -1157,6 +1018,7 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) S8 type = (U8) label.asInteger(); mType = static_cast<LLAssetType::EType>(type); } + continue; } if (i->first == INV_INVENTORY_TYPE_LABEL) @@ -1171,6 +1033,7 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) S8 type = (U8) label.asInteger(); mInventoryType = static_cast<LLInventoryType::EType>(type); } + continue; } if (i->first == INV_FLAGS_LABEL) @@ -1184,6 +1047,7 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) { mFlags = label.asInteger(); } + continue; } if (i->first == INV_NAME_LABEL) @@ -1191,20 +1055,22 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) mName = i->second.asString(); LLStringUtil::replaceNonstandardASCII(mName, ' '); LLStringUtil::replaceChar(mName, '|', ' '); + continue; } if (i->first == INV_DESC_LABEL) { mDescription = i->second.asString(); LLStringUtil::replaceNonstandardASCII(mDescription, ' '); + continue; } if (i->first == INV_CREATION_DATE_LABEL) { mCreationDate = i->second.asInteger(); + continue; } } -#endif // new version // Need to convert 1.0 simstate files to a useful inventory type // and potentially deal with bad inventory tyes eg, a landmark @@ -1219,9 +1085,6 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) mPermissions.initMasks(mInventoryType); return true; -fail: - return false; - } ///---------------------------------------------------------------------------- diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp index f42c11ee21..d2c911a189 100644 --- a/indra/llprimitive/llgltfmaterial.cpp +++ b/indra/llprimitive/llgltfmaterial.cpp @@ -89,6 +89,10 @@ LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs) mOverrideDoubleSided = rhs.mOverrideDoubleSided; mOverrideAlphaMode = rhs.mOverrideAlphaMode; + mTrackingIdToLocalTexture = rhs.mTrackingIdToLocalTexture; + + updateTextureTracking(); + return *this; } @@ -601,6 +605,10 @@ void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat) mTextureTransform[i].mRotation = override_mat.mTextureTransform[i].mRotation; } } + + mTrackingIdToLocalTexture.insert(override_mat.mTrackingIdToLocalTexture.begin(), override_mat.mTrackingIdToLocalTexture.begin()); + + updateTextureTracking(); } void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& data) @@ -765,3 +773,47 @@ LLUUID LLGLTFMaterial::getHash() const return hash; } +void LLGLTFMaterial::addLocalTextureTracking(const LLUUID& tracking_id, const LLUUID& tex_id) +{ + mTrackingIdToLocalTexture[tracking_id] = tex_id; +} + +void LLGLTFMaterial::removeLocalTextureTracking(const LLUUID& tracking_id) +{ + mTrackingIdToLocalTexture.erase(tracking_id); +} + +bool LLGLTFMaterial::replaceLocalTexture(const LLUUID& tracking_id, const LLUUID& old_id, const LLUUID& new_id) +{ + bool res = false; + + for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) + { + if (mTextureId[i] == old_id) + { + mTextureId[i] = new_id; + res = true; + } + else if (mTextureId[i] == new_id) + { + res = true; + } + } + + if (res) + { + mTrackingIdToLocalTexture[tracking_id] = new_id; + } + else + { + mTrackingIdToLocalTexture.erase(tracking_id); + } + + return res; +} + +void LLGLTFMaterial::updateTextureTracking() +{ + // setTEGLTFMaterialOverride is responsible for tracking + // for material overrides editor will set it +} diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h index 0b6e5ca03b..6ccc8bd473 100644 --- a/indra/llprimitive/llgltfmaterial.h +++ b/indra/llprimitive/llgltfmaterial.h @@ -197,7 +197,7 @@ public: // write to given tinygltf::Model void writeToModel(tinygltf::Model& model, S32 mat_index) const; - void applyOverride(const LLGLTFMaterial& override_mat); + virtual void applyOverride(const LLGLTFMaterial& override_mat); // apply the given LLSD override data void applyOverrideLLSD(const LLSD& data); @@ -223,6 +223,17 @@ public: virtual void addTextureEntry(LLTextureEntry* te) {}; virtual void removeTextureEntry(LLTextureEntry* te) {}; + // For local textures so that editor will know to track changes + void addLocalTextureTracking(const LLUUID& tracking_id, const LLUUID &tex_id); + void removeLocalTextureTracking(const LLUUID& tracking_id); + bool hasLocalTextures() { return !mTrackingIdToLocalTexture.empty(); } + virtual bool replaceLocalTexture(const LLUUID& tracking_id, const LLUUID &old_id, const LLUUID& new_id); + virtual void updateTextureTracking(); + + // These fields are local to viewer and are a part of local bitmap support + typedef std::map<LLUUID, LLUUID> local_tex_map_t; + local_tex_map_t mTrackingIdToLocalTexture; + protected: static LLVector2 vec2FromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const LLVector2& default_value); static F32 floatFromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const F32 default_value); diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index fc9d42bfb6..1a47293523 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -144,6 +144,83 @@ void LLFetchedGLTFMaterial::bind(LLViewerTexture* media_tex) } +LLViewerFetchedTexture* fetch_texture(const LLUUID& id) +{ + LLViewerFetchedTexture* img = nullptr; + if (id.notNull()) + { + img = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + img->addTextureStats(64.f * 64.f, TRUE); + } + return img; +}; + +bool LLFetchedGLTFMaterial::replaceLocalTexture(const LLUUID& tracking_id, const LLUUID& old_id, const LLUUID& new_id) +{ + bool res = false; + if (mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] == old_id) + { + mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] = new_id; + mBaseColorTexture = fetch_texture(new_id); + res = true; + } + if (mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] == old_id) + { + mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] = new_id; + mNormalTexture = fetch_texture(new_id); + res = true; + } + if (mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] == old_id) + { + mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] = new_id; + mMetallicRoughnessTexture = fetch_texture(new_id); + res = true; + } + if (mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] == old_id) + { + mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] = new_id; + mEmissiveTexture = fetch_texture(new_id); + res = true; + } + + for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) + { + if (mTextureId[i] == new_id) + { + res = true; + } + } + + if (res) + { + mTrackingIdToLocalTexture[tracking_id] = new_id; + } + else + { + mTrackingIdToLocalTexture.erase(tracking_id); + } + + return res; +} + +void LLFetchedGLTFMaterial::addTextureEntry(LLTextureEntry* te) +{ + mTextureEntires.insert(te); +} + +void LLFetchedGLTFMaterial::removeTextureEntry(LLTextureEntry* te) +{ + mTextureEntires.erase(te); +} + +void LLFetchedGLTFMaterial::updateTextureTracking() +{ + for (local_tex_map_t::value_type &val : mTrackingIdToLocalTexture) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(val.first, this); + } +} + void LLFetchedGLTFMaterial::materialBegin() { llassert(!mFetching); diff --git a/indra/newview/llfetchedgltfmaterial.h b/indra/newview/llfetchedgltfmaterial.h index 1668657281..2559aa46cc 100644 --- a/indra/newview/llfetchedgltfmaterial.h +++ b/indra/newview/llfetchedgltfmaterial.h @@ -50,12 +50,19 @@ public: bool isFetching() const { return mFetching; } + void addTextureEntry(LLTextureEntry* te) override; + void removeTextureEntry(LLTextureEntry* te) override; + virtual bool replaceLocalTexture(const LLUUID& tracking_id, const LLUUID& old_id, const LLUUID& new_id) override; + virtual void updateTextureTracking() override; + // Textures used for fetching/rendering LLPointer<LLViewerFetchedTexture> mBaseColorTexture; LLPointer<LLViewerFetchedTexture> mNormalTexture; LLPointer<LLViewerFetchedTexture> mMetallicRoughnessTexture; LLPointer<LLViewerFetchedTexture> mEmissiveTexture; + std::set<LLTextureEntry*> mTextureEntires; + protected: // Lifetime management diff --git a/indra/newview/llfloaterchangeitemthumbnail.cpp b/indra/newview/llfloaterchangeitemthumbnail.cpp index f54240f6f4..0301627c15 100644 --- a/indra/newview/llfloaterchangeitemthumbnail.cpp +++ b/indra/newview/llfloaterchangeitemthumbnail.cpp @@ -760,7 +760,7 @@ void LLFloaterChangeItemThumbnail::showTexturePicker(const LLUUID &thumbnail_id) { //texture_floaterp->setTextureSelectedCallback(); //texture_floaterp->setOnUpdateImageStatsCallback(); - texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource, const LLUUID&, const LLUUID&) + texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource, const LLUUID&, const LLUUID&, const LLUUID&) { if (op == LLTextureCtrl::TEXTURE_SELECT) { diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 74a5442586..8583cca103 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -3342,7 +3342,7 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, is_cache_obsolete = true; // Obsolete until proven current - U64 lines_count = 0U; + //U64 lines_count = 0U; std::string line; LLPointer<LLSDParser> parser = new LLSDNotationParser(); while (std::getline(file, line)) @@ -3408,12 +3408,13 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, } } - static constexpr U64 BATCH_SIZE = 512U; - if ((++lines_count % BATCH_SIZE) == 0) - { - // SL-19968 - make sure message system code gets a chance to run every so often - pump_idle_startup_network(); - } +// TODO(brad) - figure out how to reenable this without breaking everything else +// static constexpr U64 BATCH_SIZE = 512U; +// if ((++lines_count % BATCH_SIZE) == 0) +// { +// // SL-19968 - make sure message system code gets a chance to run every so often +// pump_idle_startup_network(); +// } } file.close(); diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 257208470e..5a5fb7474c 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -46,6 +46,7 @@ #include <ctime> /* misc headers */ +#include "llgltfmaterial.h" #include "llscrolllistctrl.h" #include "lllocaltextureobject.h" #include "llviewertexturelist.h" @@ -131,6 +132,14 @@ LLLocalBitmap::~LLLocalBitmap() LLLocalBitmapMgr::getInstance()->doRebake(); } + for (LLPointer<LLGLTFMaterial> &mat : mGLTFMaterialWithLocalTextures) + { + mat->removeLocalTextureTracking(getTrackingID()); + } + + mChangedSignal(getTrackingID(), getWorldID(), LLUUID()); + mChangedSignal.disconnect_all_slots(); + // delete self from gimagelist LLViewerFetchedTexture* image = gTextureList.findImage(mWorldID, TEX_LIST_STANDARD); gTextureList.deleteImage(image); @@ -142,27 +151,27 @@ LLLocalBitmap::~LLLocalBitmap() } /* accessors */ -std::string LLLocalBitmap::getFilename() +std::string LLLocalBitmap::getFilename() const { return mFilename; } -std::string LLLocalBitmap::getShortName() +std::string LLLocalBitmap::getShortName() const { return mShortName; } -LLUUID LLLocalBitmap::getTrackingID() +LLUUID LLLocalBitmap::getTrackingID() const { return mTrackingID; } -LLUUID LLLocalBitmap::getWorldID() +LLUUID LLLocalBitmap::getWorldID() const { return mWorldID; } -bool LLLocalBitmap::getValid() +bool LLLocalBitmap::getValid() const { return mValid; } @@ -273,6 +282,41 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate) return updated; } +boost::signals2::connection LLLocalBitmap::setChangedCallback(const LLLocalTextureCallback& cb) +{ + return mChangedSignal.connect(cb); +} + +void LLLocalBitmap::addGLTFMaterial(LLGLTFMaterial* mat) +{ + if (!mat) + { + return; + } + + mat_list_t::iterator end = mGLTFMaterialWithLocalTextures.end(); + for (mat_list_t::iterator it = mGLTFMaterialWithLocalTextures.begin(); it != end;) + { + if (it->get() == mat) + { + return; + } + + if ((*it)->getNumRefs() == 1) + { + it = mGLTFMaterialWithLocalTextures.erase(it); + end = mGLTFMaterialWithLocalTextures.end(); + } + else + { + it++; + } + } + + mat->addLocalTextureTracking(getTrackingID(), getWorldID()); + mGLTFMaterialWithLocalTextures.push_back(mat); +} + bool LLLocalBitmap::decodeBitmap(LLPointer<LLImageRaw> rawimg) { bool decode_successful = false; @@ -340,7 +384,7 @@ bool LLLocalBitmap::decodeBitmap(LLPointer<LLImageRaw> rawimg) return decode_successful; } -void LLLocalBitmap::replaceIDs(LLUUID old_id, LLUUID new_id) +void LLLocalBitmap::replaceIDs(const LLUUID& old_id, LLUUID new_id) { // checking for misuse. if (old_id == new_id) @@ -350,6 +394,8 @@ void LLLocalBitmap::replaceIDs(LLUUID old_id, LLUUID new_id) return; } + mChangedSignal(getTrackingID(), old_id, new_id); + // processing updates per channel; makes the process scalable. // the only actual difference is in SetTE* call i.e. SetTETexture, SetTENormal, etc. updateUserPrims(old_id, new_id, LLRender::DIFFUSE_MAP); @@ -381,6 +427,8 @@ void LLLocalBitmap::replaceIDs(LLUUID old_id, LLUUID new_id) updateUserLayers(old_id, new_id, LLWearableType::WT_UNIVERSAL); updateUserLayers(old_id, new_id, LLWearableType::WT_UNDERPANTS); updateUserLayers(old_id, new_id, LLWearableType::WT_UNDERSHIRT); + + updateGLTFMaterials(old_id, new_id); } // this function sorts the faces from a getFaceList[getNumFaces] into a list of objects @@ -578,6 +626,67 @@ void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableTyp } } +void LLLocalBitmap::updateGLTFMaterials(LLUUID old_id, LLUUID new_id) +{ + // Might be a better idea to hold this in LLGLTFMaterialList + mat_list_t::iterator end = mGLTFMaterialWithLocalTextures.end(); + for (mat_list_t::iterator it = mGLTFMaterialWithLocalTextures.begin(); it != end;) + { + if ((*it)->getNumRefs() == 1) + { + // render and override materials are often recreated, + // clean up any remains + it = mGLTFMaterialWithLocalTextures.erase(it); + end = mGLTFMaterialWithLocalTextures.end(); + } + else if ((*it)->replaceLocalTexture(mTrackingID, old_id, new_id)) + { + it++; + } + else + { + // Matching id not found, no longer in use + // material would clean itself, remove from the list + it = mGLTFMaterialWithLocalTextures.erase(it); + end = mGLTFMaterialWithLocalTextures.end(); + } + } + + // Render material consists of base and override materials, make sure replaceLocalTexture + // gets called for base and override before applyOverride + end = mGLTFMaterialWithLocalTextures.end(); + for (mat_list_t::iterator it = mGLTFMaterialWithLocalTextures.begin(); it != end;) + { + LLFetchedGLTFMaterial* fetched_mat = dynamic_cast<LLFetchedGLTFMaterial*>((*it).get()); + if (fetched_mat) + { + for (LLTextureEntry* entry : fetched_mat->mTextureEntires) + { + // Normally a change in applied material id is supposed to + // drop overrides thus reset material, but local materials + // currently reuse their existing asset id, and purpose is + // to preview how material will work in-world, overrides + // included, so do an override to render update instead. + LLGLTFMaterial* override_mat = entry->getGLTFMaterialOverride(); + if (override_mat) + { + // do not create a new material, reuse existing pointer + LLFetchedGLTFMaterial* render_mat = (LLFetchedGLTFMaterial*)entry->getGLTFRenderMaterial(); + if (render_mat) + { + llassert(dynamic_cast<LLFetchedGLTFMaterial*>(entry->getGLTFRenderMaterial()) != nullptr); + { + *render_mat = *fetched_mat; + } + render_mat->applyOverride(*override_mat); + } + } + } + } + ++it; + } +} + LLAvatarAppearanceDefines::ETextureIndex LLLocalBitmap::getTexIndex( LLWearableType::EType type, LLAvatarAppearanceDefines::EBakedTextureIndex baked_texind) { @@ -1020,11 +1129,11 @@ void LLLocalBitmapMgr::delUnit(LLUUID tracking_id) } } -LLUUID LLLocalBitmapMgr::getWorldID(LLUUID tracking_id) +LLUUID LLLocalBitmapMgr::getWorldID(const LLUUID &tracking_id) const { LLUUID world_id = LLUUID::null; - for (local_list_iter iter = mBitmapList.begin(); iter != mBitmapList.end(); iter++) + for (local_list_citer iter = mBitmapList.begin(); iter != mBitmapList.end(); iter++) { LLLocalBitmap* unit = *iter; if (unit->getTrackingID() == tracking_id) @@ -1036,9 +1145,9 @@ LLUUID LLLocalBitmapMgr::getWorldID(LLUUID tracking_id) return world_id; } -bool LLLocalBitmapMgr::isLocal(const LLUUID world_id) +bool LLLocalBitmapMgr::isLocal(const LLUUID &world_id) const { - for (local_list_iter iter = mBitmapList.begin(); iter != mBitmapList.end(); iter++) + for (local_list_citer iter = mBitmapList.begin(); iter != mBitmapList.end(); iter++) { LLLocalBitmap* unit = *iter; if (unit->getWorldID() == world_id) @@ -1049,11 +1158,11 @@ bool LLLocalBitmapMgr::isLocal(const LLUUID world_id) return false; } -std::string LLLocalBitmapMgr::getFilename(LLUUID tracking_id) +std::string LLLocalBitmapMgr::getFilename(const LLUUID &tracking_id) const { std::string filename = ""; - for (local_list_iter iter = mBitmapList.begin(); iter != mBitmapList.end(); iter++) + for (local_list_citer iter = mBitmapList.begin(); iter != mBitmapList.end(); iter++) { LLLocalBitmap* unit = *iter; if (unit->getTrackingID() == tracking_id) @@ -1065,6 +1174,32 @@ std::string LLLocalBitmapMgr::getFilename(LLUUID tracking_id) return filename; } +boost::signals2::connection LLLocalBitmapMgr::setOnChangedCallback(const LLUUID tracking_id, const LLLocalBitmap::LLLocalTextureCallback &cb) +{ + for (local_list_iter iter = mBitmapList.begin(); iter != mBitmapList.end(); iter++) + { + LLLocalBitmap* unit = *iter; + if (unit->getTrackingID() == tracking_id) + { + return unit->setChangedCallback(cb); + } + } + + return boost::signals2::connection(); +} + +void LLLocalBitmapMgr::associateGLTFMaterial(const LLUUID tracking_id, LLGLTFMaterial* mat) +{ + for (local_list_iter iter = mBitmapList.begin(); iter != mBitmapList.end(); iter++) + { + LLLocalBitmap* unit = *iter; + if (unit->getTrackingID() == tracking_id) + { + unit->addGLTFMaterial(mat); + } + } +} + void LLLocalBitmapMgr::feedScrollList(LLScrollListCtrl* ctrl) { if (ctrl) diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h index bb026ed3aa..1fdf9dccbf 100644 --- a/indra/newview/lllocalbitmaps.h +++ b/indra/newview/lllocalbitmaps.h @@ -36,6 +36,7 @@ class LLScrollListCtrl; class LLImageRaw; class LLViewerObject; +class LLGLTFMaterial; class LLLocalBitmap { @@ -44,11 +45,11 @@ class LLLocalBitmap ~LLLocalBitmap(); public: /* accessors */ - std::string getFilename(); - std::string getShortName(); - LLUUID getTrackingID(); - LLUUID getWorldID(); - bool getValid(); + std::string getFilename() const; + std::string getShortName() const; + LLUUID getTrackingID() const; + LLUUID getWorldID() const; + bool getValid() const; public: /* self update public section */ enum EUpdateType @@ -59,13 +60,21 @@ class LLLocalBitmap bool updateSelf(EUpdateType = UT_REGUPDATE); + typedef boost::signals2::signal<void(const LLUUID& tracking_id, + const LLUUID& old_id, + const LLUUID& new_id)> LLLocalTextureChangedSignal; + typedef LLLocalTextureChangedSignal::slot_type LLLocalTextureCallback; + boost::signals2::connection setChangedCallback(const LLLocalTextureCallback& cb); + void addGLTFMaterial(LLGLTFMaterial* mat); + private: /* self update private section */ bool decodeBitmap(LLPointer<LLImageRaw> raw); - void replaceIDs(LLUUID old_id, LLUUID new_id); + void replaceIDs(const LLUUID &old_id, LLUUID new_id); std::vector<LLViewerObject*> prepUpdateObjects(LLUUID old_id, U32 channel); void updateUserPrims(LLUUID old_id, LLUUID new_id, U32 channel); void updateUserVolumes(LLUUID old_id, LLUUID new_id, U32 channel); void updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableType::EType type); + void updateGLTFMaterials(LLUUID old_id, LLUUID new_id); LLAvatarAppearanceDefines::ETextureIndex getTexIndex(LLWearableType::EType type, LLAvatarAppearanceDefines::EBakedTextureIndex baked_texind); private: /* private enums */ @@ -93,6 +102,12 @@ class LLLocalBitmap EExtension mExtension; ELinkStatus mLinkStatus; S32 mUpdateRetries; + LLLocalTextureChangedSignal mChangedSignal; + + // Store a list of accosiated materials + // Might be a better idea to hold this in LLGLTFMaterialList + typedef std::vector<LLPointer<LLGLTFMaterial> > mat_list_t; + mat_list_t mGLTFMaterialWithLocalTextures; }; @@ -120,10 +135,12 @@ public: void delUnit(LLUUID tracking_id); bool checkTextureDimensions(std::string filename); - LLUUID getWorldID(LLUUID tracking_id); - bool isLocal(LLUUID world_id); - std::string getFilename(LLUUID tracking_id); - + LLUUID getWorldID(const LLUUID &tracking_id) const; + bool isLocal(const LLUUID& world_id) const; + std::string getFilename(const LLUUID &tracking_id) const; + boost::signals2::connection setOnChangedCallback(const LLUUID tracking_id, const LLLocalBitmap::LLLocalTextureCallback& cb); + void associateGLTFMaterial(const LLUUID tracking_id, LLGLTFMaterial* mat); + void feedScrollList(LLScrollListCtrl* ctrl); void doUpdates(); void setNeedsRebake(); @@ -134,6 +151,7 @@ private: LLLocalBitmapTimer mTimer; bool mNeedsRebake; typedef std::list<LLLocalBitmap*>::iterator local_list_iter; + typedef std::list<LLLocalBitmap*>::const_iterator local_list_citer; }; #endif diff --git a/indra/newview/lllocalgltfmaterials.cpp b/indra/newview/lllocalgltfmaterials.cpp index b7fdead3f9..61e0163798 100644 --- a/indra/newview/lllocalgltfmaterials.cpp +++ b/indra/newview/lllocalgltfmaterials.cpp @@ -119,15 +119,6 @@ S32 LLLocalGLTFMaterial::getIndexInFile() const return mMaterialIndex; } -void LLLocalGLTFMaterial::addTextureEntry(LLTextureEntry* te) -{ - mTextureEntires.insert(te); -} -void LLLocalGLTFMaterial::removeTextureEntry(LLTextureEntry* te) -{ - mTextureEntires.erase(te); -} - /* update functions */ bool LLLocalGLTFMaterial::updateSelf() { diff --git a/indra/newview/lllocalgltfmaterials.h b/indra/newview/lllocalgltfmaterials.h index 1442b83a40..13b7577e96 100644 --- a/indra/newview/lllocalgltfmaterials.h +++ b/indra/newview/lllocalgltfmaterials.h @@ -49,9 +49,6 @@ public: /* accessors */ LLUUID getWorldID() const; S32 getIndexInFile() const; - void addTextureEntry(LLTextureEntry* te) override; - void removeTextureEntry(LLTextureEntry* te) override; - public: bool updateSelf(); @@ -81,7 +78,6 @@ private: /* members */ ELinkStatus mLinkStatus; S32 mUpdateRetries; S32 mMaterialIndex; // Single file can have more than one - std::set<LLTextureEntry*> mTextureEntires; }; class LLLocalGLTFMaterialTimer : public LLEventTimer diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 7a65231a2d..11a528314e 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -343,6 +343,39 @@ bool LLSelectedTEGetMatData::apply(LLViewerObject* objectp, S32 te_index) return false; } +class LLSelectedTEUpdateOverrides: public LLSelectedNodeFunctor +{ +public: + LLSelectedTEUpdateOverrides(LLMaterialEditor* me) : mEditor(me) {} + + virtual bool apply(LLSelectNode* nodep); + + LLMaterialEditor* mEditor; +}; + +bool LLSelectedTEUpdateOverrides::apply(LLSelectNode* nodep) +{ + LLViewerObject* objectp = nodep->getObject(); + if (!objectp) + { + return false; + } + S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); // avatars have TEs but no faces + for (S32 te_index = 0; te_index < num_tes; ++te_index) + { + + LLTextureEntry* tep = objectp->getTE(te_index); + LLGLTFMaterial* override_mat = tep->getGLTFMaterialOverride(); + if (mEditor->updateMaterialLocalSubscription(override_mat)) + { + LLGLTFMaterial* render_mat = tep->getGLTFRenderMaterial(); + mEditor->updateMaterialLocalSubscription(render_mat); + } + } + + return true; +} + ///---------------------------------------------------------------------------- /// Class LLMaterialEditor ///---------------------------------------------------------------------------- @@ -363,6 +396,10 @@ LLMaterialEditor::LLMaterialEditor(const LLSD& key) } } +LLMaterialEditor::~LLMaterialEditor() +{ +} + void LLMaterialEditor::setObjectID(const LLUUID& object_id) { LLPreview::setObjectID(object_id); @@ -531,6 +568,11 @@ void LLMaterialEditor::onClose(bool app_quitting) { mSelectionUpdateSlot.disconnect(); } + for (mat_connection_map_t::value_type &cn : mTextureChangesUpdates) + { + cn.second.mConnection.disconnect(); + } + mTextureChangesUpdates.clear(); LLPreview::onClose(app_quitting); } @@ -861,6 +903,118 @@ void LLMaterialEditor::setEnableEditing(bool can_modify) mNormalTextureCtrl->setEnabled(can_modify); } +void LLMaterialEditor::subscribeToLocalTexture(S32 dirty_flag, const LLUUID& tracking_id) +{ + if (mTextureChangesUpdates[dirty_flag].mTrackingId != tracking_id) + { + mTextureChangesUpdates[dirty_flag].mConnection.disconnect(); + mTextureChangesUpdates[dirty_flag].mTrackingId = tracking_id; + mTextureChangesUpdates[dirty_flag].mConnection = LLLocalBitmapMgr::getInstance()->setOnChangedCallback(tracking_id, + [this, dirty_flag](const LLUUID& tracking_id, const LLUUID& old_id, const LLUUID& new_id) + { + if (new_id.isNull()) + { + mTextureChangesUpdates[dirty_flag].mConnection.disconnect(); + //mTextureChangesUpdates.erase(dirty_flag); + } + else + { + replaceLocalTexture(old_id, new_id); + } + }); + } +} + +LLUUID LLMaterialEditor::getLocalTextureTrackingIdFromFlag(U32 flag) +{ + mat_connection_map_t::iterator found = mTextureChangesUpdates.find(flag); + if (found != mTextureChangesUpdates.end()) + { + return found->second.mTrackingId; + } + return LLUUID(); +} + +bool LLMaterialEditor::updateMaterialLocalSubscription(LLGLTFMaterial* mat) +{ + if (!mat) + { + return false; + } + + bool res = false; + for (mat_connection_map_t::value_type& cn : mTextureChangesUpdates) + { + LLUUID world_id = LLLocalBitmapMgr::getInstance()->getWorldID(cn.second.mTrackingId); + if (world_id == mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(cn.second.mTrackingId, mat); + res = true; + continue; + } + if (world_id == mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(cn.second.mTrackingId, mat); + res = true; + continue; + } + if (world_id == mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(cn.second.mTrackingId, mat); + res = true; + continue; + } + if (world_id == mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(cn.second.mTrackingId, mat); + res = true; + continue; + } + } + return res; +} + +void LLMaterialEditor::replaceLocalTexture(const LLUUID& old_id, const LLUUID& new_id) +{ + // todo: might be a good idea to set mBaseColorTextureUploadId here + // and when texturectrl picks a local texture + if (getBaseColorId() == old_id) + { + mBaseColorTextureCtrl->setValue(new_id); + } + if (mBaseColorTextureCtrl->getDefaultImageAssetID() == old_id) + { + mBaseColorTextureCtrl->setDefaultImageAssetID(new_id); + } + + if (getMetallicRoughnessId() == old_id) + { + mMetallicTextureCtrl->setValue(new_id); + } + if (mMetallicTextureCtrl->getDefaultImageAssetID() == old_id) + { + mMetallicTextureCtrl->setDefaultImageAssetID(new_id); + } + + if (getEmissiveId() == old_id) + { + mEmissiveTextureCtrl->setValue(new_id); + } + if (mEmissiveTextureCtrl->getDefaultImageAssetID() == old_id) + { + mEmissiveTextureCtrl->setDefaultImageAssetID(new_id); + } + + if (getNormalId() == old_id) + { + mNormalTextureCtrl->setValue(new_id); + } + if (mNormalTextureCtrl->getDefaultImageAssetID() == old_id) + { + mNormalTextureCtrl->setDefaultImageAssetID(new_id); + } +} + void LLMaterialEditor::onCommitTexture(LLUICtrl* ctrl, const LLSD& data, S32 dirty_flag) { if (!mIsOverride) @@ -913,6 +1067,21 @@ void LLMaterialEditor::onCommitTexture(LLUICtrl* ctrl, const LLSD& data, S32 dir } } + LLTextureCtrl* tex_ctrl = (LLTextureCtrl*)ctrl; + if (tex_ctrl->isImageLocal()) + { + subscribeToLocalTexture(dirty_flag, tex_ctrl->getLocalTrackingID()); + } + else + { + // unsubcribe potential old callabck + mat_connection_map_t::iterator found = mTextureChangesUpdates.find(dirty_flag); + if (found != mTextureChangesUpdates.end()) + { + found->second.mConnection.disconnect(); + } + } + markChangesUnsaved(dirty_flag); applyToSelection(); } @@ -923,6 +1092,16 @@ void LLMaterialEditor::onCancelCtrl(LLUICtrl* ctrl, const LLSD& data, S32 dirty_ applyToSelection(); } +void update_local_texture(LLUICtrl* ctrl, LLGLTFMaterial* mat) +{ + LLTextureCtrl* tex_ctrl = (LLTextureCtrl*)ctrl; + if (tex_ctrl->isImageLocal()) + { + // subscrive material to updates of local textures + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(tex_ctrl->getLocalTrackingID(), mat); + } +} + void LLMaterialEditor::onSelectCtrl(LLUICtrl* ctrl, const LLSD& data, S32 dirty_flag) { mUnsavedChanges |= dirty_flag; @@ -958,21 +1137,25 @@ void LLMaterialEditor::onSelectCtrl(LLUICtrl* ctrl, const LLSD& data, S32 dirty_ case MATERIAL_BASE_COLOR_TEX_DIRTY: { nodep->mSavedGLTFOverrideMaterials[te]->setBaseColorId(mCtrl->getValue().asUUID(), true); + update_local_texture(mCtrl, nodep->mSavedGLTFOverrideMaterials[te].get()); break; } case MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY: { nodep->mSavedGLTFOverrideMaterials[te]->setOcclusionRoughnessMetallicId(mCtrl->getValue().asUUID(), true); + update_local_texture(mCtrl, nodep->mSavedGLTFOverrideMaterials[te].get()); break; } case MATERIAL_EMISIVE_TEX_DIRTY: { nodep->mSavedGLTFOverrideMaterials[te]->setEmissiveId(mCtrl->getValue().asUUID(), true); + update_local_texture(mCtrl, nodep->mSavedGLTFOverrideMaterials[te].get()); break; } case MATERIAL_NORMAL_TEX_DIRTY: { nodep->mSavedGLTFOverrideMaterials[te]->setNormalId(mCtrl->getValue().asUUID(), true); + update_local_texture(mCtrl, nodep->mSavedGLTFOverrideMaterials[te].get()); break; } // Colors @@ -1390,6 +1573,20 @@ void LLMaterialEditor::finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, L { me->refreshFromInventory(itemId); } + + if (me && !me->mTextureChangesUpdates.empty()) + { + const LLInventoryItem* item = me->getItem(); + if (item) + { + // local materials were assigned, force load material and init tracking + LLGLTFMaterial* mat = gGLTFMaterialList.getMaterial(item->getAssetUUID()); + for (mat_connection_map_t::value_type &val : me->mTextureChangesUpdates) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(val.second.mTrackingId, mat); + } + } + } } } @@ -1404,6 +1601,16 @@ void LLMaterialEditor::finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUID me->setAssetId(newAssetId); me->refreshFromInventory(); me->setEnabled(true); + + if (me && !me->mTextureChangesUpdates.empty()) + { + // local materials were assigned, force load material and init tracking + LLGLTFMaterial* mat = gGLTFMaterialList.getMaterial(newAssetId); + for (mat_connection_map_t::value_type &val : me->mTextureChangesUpdates) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(val.second.mTrackingId, mat); + } + } } } @@ -1437,6 +1644,17 @@ void LLMaterialEditor::finishSaveAs( { me->loadAsset(); me->setEnabled(true); + + // Local texure support + if (!me->mTextureChangesUpdates.empty()) + { + // local materials were assigned, force load material and init tracking + LLGLTFMaterial* mat = gGLTFMaterialList.getMaterial(item->getAssetUUID()); + for (mat_connection_map_t::value_type &val : me->mTextureChangesUpdates) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(val.second.mTrackingId, mat); + } + } } } else if(has_unsaved_changes) @@ -2691,28 +2909,58 @@ public: if (changed_flags & MATERIAL_BASE_COLOR_TEX_DIRTY) { material->setBaseColorId(mEditor->getBaseColorId(), true); + LLUUID tracking_id = mEditor->getLocalTextureTrackingIdFromFlag(MATERIAL_BASE_COLOR_TEX_DIRTY); + if (tracking_id.notNull()) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(tracking_id, material); + } } else if ((reverted_flags & MATERIAL_BASE_COLOR_TEX_DIRTY) && revert_mat.notNull()) { material->setBaseColorId(revert_mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR], false); + LLUUID tracking_id = mEditor->getLocalTextureTrackingIdFromFlag(MATERIAL_BASE_COLOR_TEX_DIRTY); + if (tracking_id.notNull()) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(tracking_id, material); + } } if (changed_flags & MATERIAL_NORMAL_TEX_DIRTY) { material->setNormalId(mEditor->getNormalId(), true); + LLUUID tracking_id = mEditor->getLocalTextureTrackingIdFromFlag(MATERIAL_NORMAL_TEX_DIRTY); + if (tracking_id.notNull()) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(tracking_id, material); + } } else if ((reverted_flags & MATERIAL_NORMAL_TEX_DIRTY) && revert_mat.notNull()) { material->setNormalId(revert_mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL], false); + LLUUID tracking_id = mEditor->getLocalTextureTrackingIdFromFlag(MATERIAL_NORMAL_TEX_DIRTY); + if (tracking_id.notNull()) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(tracking_id, material); + } } if (changed_flags & MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY) { material->setOcclusionRoughnessMetallicId(mEditor->getMetallicRoughnessId(), true); + LLUUID tracking_id = mEditor->getLocalTextureTrackingIdFromFlag(MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY); + if (tracking_id.notNull()) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(tracking_id, material); + } } else if ((reverted_flags & MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY) && revert_mat.notNull()) { material->setOcclusionRoughnessMetallicId(revert_mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS], false); + LLUUID tracking_id = mEditor->getLocalTextureTrackingIdFromFlag(MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY); + if (tracking_id.notNull()) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(tracking_id, material); + } } if (changed_flags & MATERIAL_METALLIC_ROUGHTNESS_METALNESS_DIRTY) @@ -2745,10 +2993,20 @@ public: if (changed_flags & MATERIAL_EMISIVE_TEX_DIRTY) { material->setEmissiveId(mEditor->getEmissiveId(), true); + LLUUID tracking_id = mEditor->getLocalTextureTrackingIdFromFlag(MATERIAL_EMISIVE_TEX_DIRTY); + if (tracking_id.notNull()) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(tracking_id, material); + } } else if ((reverted_flags & MATERIAL_EMISIVE_TEX_DIRTY) && revert_mat.notNull()) { material->setEmissiveId(revert_mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE], false); + LLUUID tracking_id = mEditor->getLocalTextureTrackingIdFromFlag(MATERIAL_EMISIVE_TEX_DIRTY); + if (tracking_id.notNull()) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(tracking_id, material); + } } if (changed_flags & MATERIAL_DOUBLE_SIDED_DIRTY) @@ -2900,6 +3158,34 @@ void LLMaterialEditor::setFromGLTFMaterial(LLGLTFMaterial* mat) setDoubleSided(mat->mDoubleSided); setAlphaMode(mat->getAlphaMode()); setAlphaCutoff(mat->mAlphaCutoff); + + if (mat->hasLocalTextures()) + { + for (LLGLTFMaterial::local_tex_map_t::value_type &val : mat->mTrackingIdToLocalTexture) + { + LLUUID world_id = LLLocalBitmapMgr::getInstance()->getWorldID(val.first); + if (val.second != world_id) + { + LL_WARNS() << "world id mismatch" << LL_ENDL; + } + if (world_id == mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]) + { + subscribeToLocalTexture(MATERIAL_BASE_COLOR_TEX_DIRTY, val.first); + } + if (world_id == mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]) + { + subscribeToLocalTexture(MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY, val.first); + } + if (world_id == mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]) + { + subscribeToLocalTexture(MATERIAL_EMISIVE_TEX_DIRTY, val.first); + } + if (world_id == mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]) + { + subscribeToLocalTexture(MATERIAL_NORMAL_TEX_DIRTY, val.first); + } + } + } } bool LLMaterialEditor::setFromSelection() @@ -2918,6 +3204,8 @@ bool LLMaterialEditor::setFromSelection() const LLViewerInventoryItem* item = selected_object->getInventoryItemByAsset(func.mMaterialId); const bool allow_modify = !item || canModify(selected_object, item); setEnableEditing(allow_modify); + + // todo: apply local texture data to all materials in selection } else { @@ -2940,6 +3228,15 @@ bool LLMaterialEditor::setFromSelection() // Memorize selection data for filtering further updates mOverrideObjectId = func.mObjectId; mOverrideObjectTE = func.mObjectTE; + + // Ovverdired might have been updated, + // refresh state of local textures in overrides + // + // Todo: this probably shouldn't be here, but in localbitmap, + // subscried to all material overrides if we want copied + // objects to get properly updated as well + LLSelectedTEUpdateOverrides local_tex_func(this); + selected_objects->applyToNodes(&local_tex_func); } return func.mMaterial.notNull(); diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h index 1c40fcc348..95a4c4572d 100644 --- a/indra/newview/llmaterialeditor.h +++ b/indra/newview/llmaterialeditor.h @@ -87,6 +87,7 @@ protected: class LLMaterialEditor : public LLPreview, public LLVOInventoryListener { public: LLMaterialEditor(const LLSD& key); + ~LLMaterialEditor(); bool setFromGltfModel(const tinygltf::Model& model, S32 index, bool set_textures = false); @@ -219,6 +220,8 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener void setCanSave(bool value); void setEnableEditing(bool can_modify); + void subscribeToLocalTexture(S32 dirty_flag, const LLUUID& tracking_id); + void replaceLocalTexture(const LLUUID& old_id, const LLUUID& new_id); // Local texture support void onCommitTexture(LLUICtrl* ctrl, const LLSD& data, S32 dirty_flag); void onCancelCtrl(LLUICtrl* ctrl, const LLSD& data, S32 dirty_flag); void onSelectCtrl(LLUICtrl* ctrl, const LLSD& data, S32 dirty_flag); @@ -228,6 +231,8 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener U32 getUnsavedChangesFlags() { return mUnsavedChanges; } U32 getRevertedChangesFlags() { return mRevertedChanges; } + LLUUID getLocalTextureTrackingIdFromFlag(U32 flag); + bool updateMaterialLocalSubscription(LLGLTFMaterial* mat); static bool capabilitiesAvailable(); @@ -306,5 +311,13 @@ private: static bool mOverrideInProgress; static bool mSelectionNeedsUpdate; boost::signals2::connection mSelectionUpdateSlot; + + struct LocalTextureConnection + { + LLUUID mTrackingId; + boost::signals2::connection mConnection; + }; + typedef std::map<S32, LocalTextureConnection> mat_connection_map_t; + mat_connection_map_t mTextureChangesUpdates; }; diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 1a4546875d..c2c9139c19 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -1959,7 +1959,7 @@ void LLPanelProfileSecondLife::onShowTexturePicker() mFloaterTexturePickerHandle = texture_floaterp->getHandle(); - texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID&) + texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID&, const LLUUID&) { if (op == LLTextureCtrl::TEXTURE_SELECT) { @@ -2285,7 +2285,7 @@ void LLPanelProfileFirstLife::onChangePhoto() mFloaterTexturePickerHandle = texture_floaterp->getHandle(); - texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID&) + texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID&, const LLUUID&) { if (op == LLTextureCtrl::TEXTURE_SELECT) { diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 10667b02d9..3988bceb4e 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -846,6 +846,7 @@ void LLFloaterTexturePicker::commitCallback(LLTextureCtrl::ETexturePickOp op) } LLUUID asset_id = mImageAssetID; LLUUID inventory_id; + LLUUID tracking_id; LLPickerSource mode = (LLPickerSource)mModeSelector->getValue().asInteger(); switch (mode) @@ -886,16 +887,16 @@ void LLFloaterTexturePicker::commitCallback(LLTextureCtrl::ETexturePickOp op) if (!mLocalScrollCtrl->getAllSelected().empty()) { LLSD data = mLocalScrollCtrl->getFirstSelected()->getValue(); - LLUUID temp_id = data["id"]; + tracking_id = data["id"]; S32 asset_type = data["type"].asInteger(); if (LLAssetType::AT_MATERIAL == asset_type) { - asset_id = LLLocalGLTFMaterialMgr::getInstance()->getWorldID(temp_id); + asset_id = LLLocalGLTFMaterialMgr::getInstance()->getWorldID(tracking_id); } else { - asset_id = LLLocalBitmapMgr::getInstance()->getWorldID(temp_id); + asset_id = LLLocalBitmapMgr::getInstance()->getWorldID(tracking_id); } } else @@ -912,13 +913,13 @@ void LLFloaterTexturePicker::commitCallback(LLTextureCtrl::ETexturePickOp op) break; } - mOnFloaterCommitCallback(op, mode, asset_id, inventory_id); + mOnFloaterCommitCallback(op, mode, asset_id, inventory_id, tracking_id); } void LLFloaterTexturePicker::commitCancel() { if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply) { - mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, PICKER_UNKNOWN, mOriginalImageAssetID, LLUUID::null); + mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, PICKER_UNKNOWN, mOriginalImageAssetID, LLUUID::null, LLUUID::null); } } @@ -972,7 +973,7 @@ void LLFloaterTexturePicker::onBtnCancel(void* userdata) self->setImageID( self->mOriginalImageAssetID ); if (self->mOnFloaterCommitCallback) { - self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, PICKER_UNKNOWN, self->mOriginalImageAssetID, LLUUID::null); + self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, PICKER_UNKNOWN, self->mOriginalImageAssetID, LLUUID::null, LLUUID::null); } self->mViewModel->resetDirty(); self->closeFloater(); @@ -1177,7 +1178,7 @@ void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata) { if (self->mOnFloaterCommitCallback) { - self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, PICKER_LOCAL, inworld_id, LLUUID::null); + self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, PICKER_LOCAL, inworld_id, LLUUID::null, tracking_id); } } } @@ -1804,7 +1805,7 @@ void LLTextureCtrl::showPicker(BOOL take_focus) } if (texture_floaterp) { - texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLTextureCtrl::onFloaterCommit, this, _1, _2, _3, _4)); + texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLTextureCtrl::onFloaterCommit, this, _1, _2, _3, _4, _5)); } if (texture_floaterp) { @@ -1928,7 +1929,7 @@ void LLTextureCtrl::onFloaterClose() mFloaterHandle.markDead(); } -void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID& inv_id) +void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID& inv_id, const LLUUID& tracking_id) { LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); @@ -1951,16 +1952,23 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLPickerSource source, co case PICKER_INVENTORY: mImageItemID = inv_id; mImageAssetID = asset_id; + mLocalTrackingID.setNull(); break; case PICKER_BAKE: + mImageItemID = LLUUID::null; + mImageAssetID = asset_id; + mLocalTrackingID.setNull(); + break; case PICKER_LOCAL: mImageItemID = LLUUID::null; mImageAssetID = asset_id; + mLocalTrackingID = tracking_id; break; case PICKER_UNKNOWN: default: mImageItemID = floaterp->findItemID(asset_id, FALSE); mImageAssetID = asset_id; + mLocalTrackingID.setNull(); break; } @@ -2018,6 +2026,7 @@ void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id ) { mImageItemID.setNull(); mImageAssetID = asset_id; + mLocalTrackingID.setNull(); LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); if( floaterp && getEnabled() ) { diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 180c4fa4b8..c47df5accb 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -200,7 +200,11 @@ public: void closeDependentFloater(); void onFloaterClose(); - void onFloaterCommit(ETexturePickOp op, LLPickerSource source, const LLUUID& local_id, const LLUUID& inv_id); + void onFloaterCommit(ETexturePickOp op, + LLPickerSource source, + const LLUUID& local_id, + const LLUUID& inv_id, + const LLUUID& tracking_id); // This call is returned when a drag is detected. Your callback // should return TRUE if the drag is acceptable. @@ -230,6 +234,9 @@ public: void setInventoryPickType(EPickInventoryType type); EPickInventoryType getInventoryPickType() { return mInventoryPickType; }; + bool isImageLocal() { return mLocalTrackingID.notNull(); } + LLUUID getLocalTrackingID() { return mLocalTrackingID; } + private: BOOL allowDrop(LLInventoryItem* item, EDragAndDropType cargo_type, std::string& tooltip_msg); BOOL doDrop(LLInventoryItem* item); @@ -247,6 +254,7 @@ private: LLUUID mImageAssetID; LLUUID mDefaultImageAssetID; LLUUID mBlankImageAssetID; + LLUUID mLocalTrackingID; LLUIImagePtr mFallbackImage; std::string mDefaultImageName; LLHandle<LLFloater> mFloaterHandle; @@ -272,7 +280,7 @@ private: ////////////////////////////////////////////////////////////////////////////////////////// // LLFloaterTexturePicker -typedef boost::function<void(LLTextureCtrl::ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID& inventory_id)> floater_commit_callback; +typedef boost::function<void(LLTextureCtrl::ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID& inventory_id, const LLUUID& tracking_id)> floater_commit_callback; typedef boost::function<void()> floater_close_callback; typedef boost::function<void(const LLUUID& asset_id)> set_image_asset_id_callback; typedef boost::function<void(LLPointer<LLViewerTexture> texture)> set_on_update_image_stats_callback; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 3b5b986725..2bcd0858d3 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -5475,6 +5475,11 @@ S32 LLViewerObject::setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* override_ma tep->setGLTFRenderMaterial(render_mat); retval = TEM_CHANGE_TEXTURE; + for (LLGLTFMaterial::local_tex_map_t::value_type &val : override_mat->mTrackingIdToLocalTexture) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(val.first, override_mat); + } + } else if (tep->setGLTFRenderMaterial(nullptr)) { |