diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
index 1e752160793b7b934bfd44de2d8e59d47e39cf78..58804a901f9c7233ece5f407aac9dc05e4d898b8 100644
--- a/indra/newview/llmaterialeditor.cpp
+++ b/indra/newview/llmaterialeditor.cpp
@@ -67,6 +67,24 @@ const std::string MATERIAL_EMISSIVE_DEFAULT_NAME = "Emissive";
 
 const LLUUID LIVE_MATERIAL_EDITOR_KEY("6cf97162-8b68-49eb-b627-79886c9fd17d");
 
+// 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_NORMAL_TEX_DIRTY = 0x1 << 3;
+
+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_EMISIVE_COLOR_DIRTY = 0x1 << 7;
+static const U32 MATERIAL_EMISIVE_TEX_DIRTY = 0x1 << 8;
+
+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;
+
 LLFloaterComboOptions::LLFloaterComboOptions()
     : LLFloater(LLSD())
 {
@@ -199,7 +217,7 @@ class LLMaterialEditorCopiedCallback : public LLInventoryCallback
 // Default constructor
 LLMaterialEditor::LLMaterialEditor(const LLSD& key)
     : LLPreview(key)
-    , mHasUnsavedChanges(false)
+    , mUnsavedChanges(0)
     , mExpectedUploadCost(0)
     , mUploadingTexturesCount(0)
 {
@@ -251,33 +269,30 @@ BOOL LLMaterialEditor::postBuild()
     getChild<LLUICtrl>("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
     getChild<LLUICtrl>("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
 
-    boost::function<void(LLUICtrl*, void*)> changes_callback = [this](LLUICtrl * ctrl, void*)
+    boost::function<void(LLUICtrl*, void*)> changes_callback = [this](LLUICtrl * ctrl, void* userData)
     {
-        setHasUnsavedChanges(true);
+        const U32 *flag = (const U32*)userData;
+        markChangesUnsaved(*flag);
         // Apply changes to object live
         applyToSelection();
     };
  
-    childSetCommitCallback("double sided", changes_callback, NULL);
+    childSetCommitCallback("double sided", changes_callback, (void*)&MATERIAL_DOUBLE_SIDED_DIRTY);
 
     // BaseColor
-    childSetCommitCallback("base color", changes_callback, NULL);
-    childSetCommitCallback("transparency", changes_callback, NULL);
-    childSetCommitCallback("alpha mode", changes_callback, NULL);
-    childSetCommitCallback("alpha cutoff", changes_callback, NULL);
+    childSetCommitCallback("base color", changes_callback, (void*)&MATERIAL_BASE_COLOR_DIRTY);
+    childSetCommitCallback("transparency", changes_callback, (void*)&MATERIAL_BASE_TRANSPARENCY_DIRTY);
+    childSetCommitCallback("alpha mode", changes_callback, (void*)&MATERIAL_ALPHA_MODE_DIRTY);
+    childSetCommitCallback("alpha cutoff", changes_callback, (void*)&MATERIAL_ALPHA_CUTOFF_DIRTY);
 
     // Metallic-Roughness
-    childSetCommitCallback("metalness factor", changes_callback, NULL);
-    childSetCommitCallback("roughness factor", changes_callback, NULL);
-
-    // Metallic-Roughness
-    childSetCommitCallback("metalness factor", changes_callback, NULL);
-    childSetCommitCallback("roughness factor", changes_callback, NULL);
+    childSetCommitCallback("metalness factor", changes_callback, (void*)&MATERIAL_METALLIC_ROUGHTNESS_METALNESS_DIRTY);
+    childSetCommitCallback("roughness factor", changes_callback, (void*)&MATERIAL_METALLIC_ROUGHTNESS_ROUGHNESS_DIRTY);
 
     // Emissive
-    childSetCommitCallback("emissive color", changes_callback, NULL);
+    childSetCommitCallback("emissive color", changes_callback, (void*)&MATERIAL_EMISIVE_COLOR_DIRTY);
 
-    childSetVisible("unsaved_changes", mHasUnsavedChanges);
+    childSetVisible("unsaved_changes", mUnsavedChanges);
 
     getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", 0));
 
@@ -333,7 +348,7 @@ void LLMaterialEditor::setBaseColorUploadId(const LLUUID& id)
         // Only set if we will need to upload this texture
         mBaseColorTextureUploadId = id;
     }
-    setHasUnsavedChanges(true);
+    markChangesUnsaved(MATERIAL_BASE_COLOR_TEX_DIRTY);
 }
 
 LLColor4 LLMaterialEditor::getBaseColor()
@@ -405,7 +420,7 @@ void LLMaterialEditor::setMetallicRoughnessUploadId(const LLUUID& id)
         childSetValue("metallic_upload_fee", getString("upload_fee_string"));
         mMetallicTextureUploadId = id;
     }
-    setHasUnsavedChanges(true);
+    markChangesUnsaved(MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY);
 }
 
 F32 LLMaterialEditor::getMetalnessFactor()
@@ -448,7 +463,7 @@ void LLMaterialEditor::setEmissiveUploadId(const LLUUID& id)
         childSetValue("emissive_upload_fee", getString("upload_fee_string"));
         mEmissiveTextureUploadId = id;
     }
-    setHasUnsavedChanges(true);
+    markChangesUnsaved(MATERIAL_EMISIVE_TEX_DIRTY);
 }
 
 LLColor4 LLMaterialEditor::getEmissiveColor()
@@ -481,7 +496,7 @@ void LLMaterialEditor::setNormalUploadId(const LLUUID& id)
         childSetValue("normal_upload_fee", getString("upload_fee_string"));
         mNormalTextureUploadId = id;
     }
-    setHasUnsavedChanges(true);
+    markChangesUnsaved(MATERIAL_NORMAL_TEX_DIRTY);
 }
 
 bool LLMaterialEditor::getDoubleSided()
@@ -494,12 +509,22 @@ void LLMaterialEditor::setDoubleSided(bool double_sided)
     childSetValue("double sided", double_sided);
 }
 
-void LLMaterialEditor::setHasUnsavedChanges(bool value)
+void LLMaterialEditor::resetUnsavedChanges()
+{
+    mUnsavedChanges = 0;
+    childSetVisible("unsaved_changes", false);
+    setCanSave(false);
+
+    mExpectedUploadCost = 0;
+    getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", mExpectedUploadCost));
+}
+
+void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag)
 {
-    mHasUnsavedChanges = value;
-    childSetVisible("unsaved_changes", value);
+    mUnsavedChanges |= dirty_flag;
+    childSetVisible("unsaved_changes", mUnsavedChanges);
 
-    if (mHasUnsavedChanges)
+    if (mUnsavedChanges)
     {
         const LLInventoryItem* item = getItem();
         if (item)
@@ -594,7 +619,7 @@ void LLMaterialEditor::onCommitBaseColorTexture(LLUICtrl * ctrl, const LLSD & da
         // the texture that is not in use
         childSetValue("base_color_upload_fee", getString("no_upload_fee_string"));
     }
-    setHasUnsavedChanges(true);
+    markChangesUnsaved(MATERIAL_BASE_COLOR_TEX_DIRTY);
     applyToSelection();
 }
 
@@ -609,7 +634,7 @@ void LLMaterialEditor::onCommitMetallicTexture(LLUICtrl * ctrl, const LLSD & dat
     {
         childSetValue("metallic_upload_fee", getString("no_upload_fee_string"));
     }
-    setHasUnsavedChanges(true);
+    markChangesUnsaved(MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY);
     applyToSelection();
 }
 
@@ -624,7 +649,7 @@ void LLMaterialEditor::onCommitEmissiveTexture(LLUICtrl * ctrl, const LLSD & dat
     {
         childSetValue("emissive_upload_fee", getString("no_upload_fee_string"));
     }
-    setHasUnsavedChanges(true);
+    markChangesUnsaved(MATERIAL_EMISIVE_TEX_DIRTY);
     applyToSelection();
 }
 
@@ -639,7 +664,7 @@ void LLMaterialEditor::onCommitNormalTexture(LLUICtrl * ctrl, const LLSD & data)
     {
         childSetValue("normal_upload_fee", getString("no_upload_fee_string"));
     }
-    setHasUnsavedChanges(true);
+    markChangesUnsaved(MATERIAL_NORMAL_TEX_DIRTY);
     applyToSelection();
 }
 
@@ -1223,7 +1248,7 @@ void LLMaterialEditor::onSaveAsMsgCallback(const LLSD& notification, const LLSD&
                 else
                 {
                     std::string buffer = getEncodedAsset();
-                    LLPointer<LLInventoryCallback> cb = new LLMaterialEditorCopiedCallback(buffer, getKey(), mHasUnsavedChanges);
+                    LLPointer<LLInventoryCallback> cb = new LLMaterialEditorCopiedCallback(buffer, getKey(), mUnsavedChanges);
                     copy_inventory_item(
                         gAgent.getID(),
                         item->getPermissions().getOwner(),
@@ -1251,7 +1276,7 @@ void LLMaterialEditor::onSaveAsMsgCallback(const LLSD& notification, const LLSD&
 
 void LLMaterialEditor::onClickCancel()
 {
-    if (mHasUnsavedChanges)
+    if (mUnsavedChanges)
     {
         LLNotificationsUtil::add("UsavedMaterialChanges", LLSD(), LLSD(), boost::bind(&LLMaterialEditor::onCancelMsgCallback, this, _1, _2));
     }
@@ -1470,7 +1495,7 @@ void LLMaterialEditor::loadMaterialFromFile(const std::string& filename, S32 ind
 }
 void LLMaterialEditor::onSelectionChanged()
 {
-    mHasUnsavedChanges = false;
+    mUnsavedChanges = 0;
     clearTextures();
     setFromSelection();
     saveLiveValues();
@@ -1551,7 +1576,6 @@ void LLMaterialEditor::loadFromGLTFMaterial(LLUUID &asset_id)
     LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor");
     me->mMaterialName = LLTrans::getString("New Material");
     me->setTitle(me->mMaterialName);
-    me->setHasUnsavedChanges(true);
     me->setFromGLTFMaterial(gGLTFMaterialList.getMaterial(asset_id));
     me->openFloater();
     me->setFocus(TRUE);
@@ -1653,7 +1677,7 @@ void LLMaterialEditor::loadMaterial(const tinygltf::Model &model_in, const std::
 
     setFromGltfMetaData(filename_lc, model_in, index);
 
-    setHasUnsavedChanges(true);
+    markChangesUnsaved(U32_MAX);
 
     openFloater();
     setFocus(TRUE);
@@ -1991,8 +2015,8 @@ class LLRenderMaterialFunctor : public LLSelectedTEFunctor
 class LLRenderMaterialOverrideFunctor : public LLSelectedTEFunctor
 {
 public:
-    LLRenderMaterialOverrideFunctor(LLMaterialEditor * me, std::string const & url, LLUUID const & asset_id)
-    : mEditor(me), mCapUrl(url), mAssetID(asset_id)
+    LLRenderMaterialOverrideFunctor(LLMaterialEditor * me, std::string const & url)
+    : mEditor(me), mCapUrl(url)
     {
 
     }
@@ -2007,9 +2031,69 @@ class LLRenderMaterialOverrideFunctor : public LLSelectedTEFunctor
 
         if (objectp && objectp->permModify() && objectp->getVolume())
         {
-            LLPointer<LLGLTFMaterial> material = new LLGLTFMaterial();
-            
-            mEditor->getGLTFMaterial(material);
+            // Get material from object
+            // Selection can cover multiple objects, and live editor is
+            // supposed to overwrite changed values only
+            LLTextureEntry* tep = objectp->getTE(te);
+            LLPointer<LLGLTFMaterial> material = tep->getGLTFMaterial();
+            if (material.isNull())
+            {
+                material = new LLGLTFMaterial();
+            }
+
+            // 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();
+            }
+            if (mEditor->getUnsavedChangesFlags() & MATERIAL_BASE_COLOR_TEX_DIRTY)
+            {
+                material->mBaseColorId = mEditor->getBaseColorId();
+            }
+
+            if (mEditor->getUnsavedChangesFlags() & MATERIAL_NORMAL_TEX_DIRTY)
+            {
+                material->mNormalId = mEditor->getNormalId();
+            }
+
+            if (mEditor->getUnsavedChangesFlags() & MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY)
+            {
+                material->mMetallicRoughnessId = mEditor->getMetallicRoughnessId();
+            }
+            if (mEditor->getUnsavedChangesFlags() & MATERIAL_METALLIC_ROUGHTNESS_METALNESS_DIRTY)
+            {
+                material->mMetallicFactor = mEditor->getMetalnessFactor();
+            }
+            if (mEditor->getUnsavedChangesFlags() & MATERIAL_METALLIC_ROUGHTNESS_ROUGHNESS_DIRTY)
+            {
+                material->mRoughnessFactor = mEditor->getRoughnessFactor();
+            }
+
+            if (mEditor->getUnsavedChangesFlags() & MATERIAL_EMISIVE_COLOR_DIRTY)
+            {
+                material->mEmissiveColor = mEditor->getEmissiveColor();
+            }
+            if (mEditor->getUnsavedChangesFlags() & MATERIAL_EMISIVE_TEX_DIRTY)
+            {
+                material->mEmissiveId = mEditor->getEmissiveId();
+            }
+
+            if (mEditor->getUnsavedChangesFlags() & MATERIAL_DOUBLE_SIDED_DIRTY)
+            {
+                material->mDoubleSided = mEditor->getDoubleSided();
+            }
+            if (mEditor->getUnsavedChangesFlags() & MATERIAL_ALPHA_MODE_DIRTY)
+            {
+                material->setAlphaMode(mEditor->getAlphaMode());
+            }
+            if (mEditor->getUnsavedChangesFlags() & MATERIAL_ALPHA_CUTOFF_DIRTY)
+            {
+                material->mAlphaCutoff = mEditor->getAlphaCutoff();
+            }
 
             std::string overrides_json = material->asJSON();
             
@@ -2026,7 +2110,6 @@ class LLRenderMaterialOverrideFunctor : public LLSelectedTEFunctor
 private:
     LLMaterialEditor * mEditor;
     std::string mCapUrl;
-    LLUUID mAssetID;
 };
 
 void LLMaterialEditor::applyToSelection()
@@ -2045,7 +2128,7 @@ void LLMaterialEditor::applyToSelection()
     {
         LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
         // TODO figure out how to get the right asset id in cases where we don't have a good one
-        LLRenderMaterialOverrideFunctor override_func(this, url, mAssetID);
+        LLRenderMaterialOverrideFunctor override_func(this, url);
         selected_objects->applyToTEs(&override_func);
     }
     else
@@ -2162,7 +2245,7 @@ void LLMaterialEditor::loadAsset()
             {
                 mAssetStatus = PREVIEW_ASSET_LOADED;
                 loadDefaults();
-                setHasUnsavedChanges(false);
+                resetUnsavedChanges();
                 setEnableEditing(allow_modify && !source_library);
             }
             else
@@ -2187,7 +2270,7 @@ void LLMaterialEditor::loadAsset()
                         LL_WARNS() << "Can't find object " << mObjectUUID << " associated with notecard." << LL_ENDL;
                         mAssetID.setNull();
                         mAssetStatus = PREVIEW_ASSET_LOADED;
-                        setHasUnsavedChanges(false);
+                        resetUnsavedChanges();
                         setEnableEditing(allow_modify && !source_library);
                         return;
                     }
@@ -2274,7 +2357,7 @@ void LLMaterialEditor::onLoadComplete(const LLUUID& asset_uuid,
             BOOL allow_modify = editor->canModify(editor->mObjectUUID, editor->getItem());
             BOOL source_library = editor->mObjectUUID.isNull() && gInventory.isObjectDescendentOf(editor->mItemUUID, gInventory.getLibraryRootFolderID());
             editor->setEnableEditing(allow_modify && !source_library);
-            editor->setHasUnsavedChanges(false);
+            editor->resetUnsavedChanges();
             editor->mAssetStatus = PREVIEW_ASSET_LOADED;
             editor->setEnabled(true); // ready for use
         }
diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h
index 438acb532b7cbf1b216d6b59e4e417fba8e51620..040dbe99da4d1385be0cf8b257ae31a7b0c7d68b 100644
--- a/indra/newview/llmaterialeditor.h
+++ b/indra/newview/llmaterialeditor.h
@@ -209,7 +209,6 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
     bool getDoubleSided();
     void setDoubleSided(bool double_sided);
 
-    void setHasUnsavedChanges(bool value);
     void setCanSaveAs(bool value);
     void setCanSave(bool value);
     void setEnableEditing(bool can_modify);
@@ -224,6 +223,8 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
 
     void modifyMaterialCoro(std::string cap_url, LLSD overrides);
 
+    U32 getUnsavedChangesFlags() { return mUnsavedChanges; }
+
 private:
     void setFromGLTFMaterial(LLGLTFMaterial* mat);
     bool setFromSelection();
@@ -271,7 +272,10 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
     // based on what we know about it.
     const std::string buildMaterialDescription();
 
-    bool mHasUnsavedChanges;
+    void resetUnsavedChanges();
+    void markChangesUnsaved(U32 dirty_flag);
+
+    U32 mUnsavedChanges; // flags to indicate individual changed parameters
     S32 mUploadingTexturesCount;
     S32 mExpectedUploadCost;
     std::string mMaterialNameShort;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 18d215f9f4c38d80aa96318fde5af9b261c1939d..e1b92e5f2ed35963d64ca5634da0d6c4f7c8cb1a 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -2956,30 +2956,20 @@ void handle_object_edit()
 	return;
 }
 
-void load_life_gltf_material(bool copy)
+void handle_object_edit_gltf_material()
 {
-    update_camera();
-
-    LLSelectedTEGetmatIdAndPermissions func;
-    LLUUID mat_id;
-    LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&func, mat_id);
-
-    if (copy)
+    if (!LLFloaterReg::instanceVisible("build"))
     {
-        LLMaterialEditor::loadFromGLTFMaterial(mat_id);
+        handle_object_edit(); // does update_camera();
     }
     else
     {
-        LLMaterialEditor::loadLive();
-    }
+        update_camera();
 
-    LLViewerJoystick::getInstance()->moveObjects(true);
-    LLViewerJoystick::getInstance()->setNeedsReset(true);
-}
+        LLViewerJoystick::getInstance()->moveObjects(true);
+        LLViewerJoystick::getInstance()->setNeedsReset(true);
+    }
 
-void handle_object_edit_gltf_material()
-{
-    handle_object_edit();
     LLMaterialEditor::loadLive();
 }