From dd2bb260217a68d9686e26d0f3514a68008f5ab1 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 30 Jun 2022 23:33:08 +0300
Subject: [PATCH] SL-17640 Handle unsaved changes better

---
 indra/newview/llmaterialeditor.cpp | 84 +++++++++++++++++++-----------
 indra/newview/llmaterialeditor.h   |  8 +++
 2 files changed, 63 insertions(+), 29 deletions(-)

diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
index 67d963bb63d..52979259dfb 100644
--- a/indra/newview/llmaterialeditor.cpp
+++ b/indra/newview/llmaterialeditor.cpp
@@ -365,7 +365,11 @@ void LLMaterialEditor::onCommitAlbedoTexture(LLUICtrl * ctrl, const LLSD & data)
     }
     else
     {
-        mAlbedoJ2C = nullptr;
+        // Texture picker has 'apply now' with 'cancel' support.
+        // Keep mAlbedoJ2C and mAlbedoFetched, it's our storage in
+        // case user decides to cancel changes.
+        // Without mAlbedoFetched, viewer will eventually cleanup
+        // the texture that is not in use
         childSetValue("albedo_upload_fee", getString("no_upload_fee_string"));
     }
     setHasUnsavedChanges(true);
@@ -381,7 +385,6 @@ void LLMaterialEditor::onCommitMetallicTexture(LLUICtrl * ctrl, const LLSD & dat
     }
     else
     {
-        mMetallicRoughnessJ2C = nullptr;
         childSetValue("metallic_upload_fee", getString("no_upload_fee_string"));
     }
     setHasUnsavedChanges(true);
@@ -397,7 +400,6 @@ void LLMaterialEditor::onCommitEmissiveTexture(LLUICtrl * ctrl, const LLSD & dat
     }
     else
     {
-        mEmissiveJ2C = nullptr;
         childSetValue("emissive_upload_fee", getString("no_upload_fee_string"));
     }
     setHasUnsavedChanges(true);
@@ -413,7 +415,6 @@ void LLMaterialEditor::onCommitNormalTexture(LLUICtrl * ctrl, const LLSD & data)
     }
     else
     {
-        mNormalJ2C = nullptr;
         childSetValue("normal_upload_fee", getString("no_upload_fee_string"));
     }
     setHasUnsavedChanges(true);
@@ -666,6 +667,10 @@ bool LLMaterialEditor::saveIfNeeded(LLInventoryItem* copyitem, bool sync)
         {
             closeFloater();
         }
+        else
+        {
+            setHasUnsavedChanges(false);
+        }
     }
     else
     { //make a new inventory item
@@ -706,6 +711,9 @@ bool LLMaterialEditor::saveIfNeeded(LLInventoryItem* copyitem, bool sync)
                 }
                 })
         );
+
+        // We do not update floater with uploaded asset yet, so just close it.
+        closeFloater();
 #endif
     }
     
@@ -912,8 +920,6 @@ static void pack_textures(tinygltf::Model& model, tinygltf::Material& material,
     LLPointer<LLImageJ2C>& mr_j2c,
     LLPointer<LLImageJ2C>& emissive_j2c)
 {
-    // todo: consider using LLLocalBitmapMgr or storing textures' pointers somewhere in floater
-    // otherwise images won't exist for long if texture ctrl temporaly switches to something else
     if (albedo_img)
     {
         albedo_tex = LLViewerTextureManager::getFetchedTexture(albedo_img, FTType::FTT_LOCAL_FILE, true);
@@ -1046,40 +1052,36 @@ void LLMaterialFilePicker::loadMaterial(const std::string& filename)
         occlusion_img = get_texture(folder, model_in, material_in.occlusionTexture.index, tmp);
     }
 
-    LLPointer<LLViewerFetchedTexture> albedo_tex;
-    LLPointer<LLViewerFetchedTexture> normal_tex;
-    LLPointer<LLViewerFetchedTexture> mr_tex;
-    LLPointer<LLViewerFetchedTexture> emissive_tex;
-    
     pack_textures(model_in, material_in, albedo_img, normal_img, mr_img, emissive_img, occlusion_img,
-        albedo_tex, normal_tex, mr_tex, emissive_tex, mME->mAlbedoJ2C, mME->mNormalJ2C, mME->mMetallicRoughnessJ2C, mME->mEmissiveJ2C);
+        mME->mAlbedoFetched, mME->mNormalFetched, mME->mMetallicRoughnessFetched, mME->mEmissiveFetched,
+        mME->mAlbedoJ2C, mME->mNormalJ2C, mME->mMetallicRoughnessJ2C, mME->mEmissiveJ2C);
     
     LLUUID albedo_id;
-    if (albedo_tex != nullptr)
+    if (mME->mAlbedoFetched.notNull())
     {
-        albedo_tex->forceToSaveRawImage(0, F32_MAX);
-        albedo_id = albedo_tex->getID();
+        mME->mAlbedoFetched->forceToSaveRawImage(0, F32_MAX);
+        albedo_id = mME->mAlbedoFetched->getID();
     }
 
     LLUUID normal_id;
-    if (normal_tex != nullptr)
+    if (mME->mNormalFetched.notNull())
     {
-        normal_tex->forceToSaveRawImage(0, F32_MAX);
-        normal_id = normal_tex->getID();
+        mME->mNormalFetched->forceToSaveRawImage(0, F32_MAX);
+        normal_id = mME->mNormalFetched->getID();
     }
 
     LLUUID mr_id;
-    if (mr_tex != nullptr)
+    if (mME->mMetallicRoughnessFetched.notNull())
     {
-        mr_tex->forceToSaveRawImage(0, F32_MAX);
-        mr_id = mr_tex->getID();
+        mME->mMetallicRoughnessFetched->forceToSaveRawImage(0, F32_MAX);
+        mr_id = mME->mMetallicRoughnessFetched->getID();
     }
 
     LLUUID emissive_id;
-    if (emissive_tex != nullptr)
+    if (mME->mEmissiveFetched.notNull())
     {
-        emissive_tex->forceToSaveRawImage(0, F32_MAX);
-        emissive_id = emissive_tex->getID();
+        mME->mEmissiveFetched->forceToSaveRawImage(0, F32_MAX);
+        emissive_id = mME->mEmissiveFetched->getID();
     }
 
     mME->setAlbedoId(albedo_id);
@@ -1426,7 +1428,9 @@ void LLMaterialEditor::inventoryChanged(LLViewerObject* object,
 
 void LLMaterialEditor::saveTexture(LLImageJ2C* img, const std::string& name, const LLUUID& asset_id)
 {
-    if (img == nullptr || img->getDataSize() == 0)
+    if (asset_id.isNull()
+        || img == nullptr
+        || img->getDataSize() == 0)
     {
         return;
     }
@@ -1459,15 +1463,37 @@ void LLMaterialEditor::saveTexture(LLImageJ2C* img, const std::string& name, con
 
 void LLMaterialEditor::saveTextures()
 {
-    saveTexture(mAlbedoJ2C, mAlbedoName, mAlbedoTextureUploadId);
-    saveTexture(mNormalJ2C, mNormalName, mNormalTextureUploadId);
-    saveTexture(mEmissiveJ2C, mEmissiveName, mEmissiveTextureUploadId);
-    saveTexture(mMetallicRoughnessJ2C, mMetallicRoughnessName, mMetallicTextureUploadId);
+    if (mAlbedoTextureUploadId == getAlbedoId())
+    {
+        saveTexture(mAlbedoJ2C, mAlbedoName, mAlbedoTextureUploadId);
+    }
+    if (mNormalTextureUploadId == getNormalId())
+    {
+        saveTexture(mNormalJ2C, mNormalName, mNormalTextureUploadId);
+    }
+    if (mMetallicTextureUploadId == getMetallicRoughnessId())
+    {
+        saveTexture(mMetallicRoughnessJ2C, mMetallicRoughnessName, mMetallicTextureUploadId);
+    }
+    if (mEmissiveTextureUploadId == getEmissiveId())
+    {
+        saveTexture(mEmissiveJ2C, mEmissiveName, mEmissiveTextureUploadId);
+    }
 
     // discard upload buffers once textures have been saved
     mAlbedoJ2C = nullptr;
     mNormalJ2C = nullptr;
     mEmissiveJ2C = nullptr;
     mMetallicRoughnessJ2C = nullptr;
+
+    mAlbedoFetched = nullptr;
+    mNormalFetched = nullptr;
+    mMetallicRoughnessFetched = nullptr;
+    mEmissiveFetched = nullptr;
+
+    mAlbedoTextureUploadId.setNull();
+    mNormalTextureUploadId.setNull();
+    mMetallicTextureUploadId.setNull();
+    mEmissiveTextureUploadId.setNull();
 }
 
diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h
index b2a6e96eac3..a632d5c8231 100644
--- a/indra/newview/llmaterialeditor.h
+++ b/indra/newview/llmaterialeditor.h
@@ -29,6 +29,7 @@
 #include "llpreview.h"
 #include "llvoinventorylistener.h"
 #include "llimagej2c.h"
+#include "llviewertexture.h"
 
 class LLTextureCtrl;
 
@@ -171,6 +172,13 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
     std::string mMetallicRoughnessName;
     std::string mEmissiveName;
 
+    // keep pointers to fetched textures or viewer will remove them
+    // if user temporary selects something else with 'apply now'
+    LLPointer<LLViewerFetchedTexture> mAlbedoFetched;
+    LLPointer<LLViewerFetchedTexture> mNormalFetched;
+    LLPointer<LLViewerFetchedTexture> mMetallicRoughnessFetched;
+    LLPointer<LLViewerFetchedTexture> mEmissiveFetched;
+
     // J2C versions of packed buffers for uploading
     LLPointer<LLImageJ2C> mAlbedoJ2C;
     LLPointer<LLImageJ2C> mNormalJ2C;
-- 
GitLab