From a27e701530e3498f71b828d7639024330cd0ccb7 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 17 Oct 2022 23:33:27 +0300
Subject: SL-18008 Add Save and Edit buttons to right click menu for materials

---
 indra/newview/llmaterialeditor.cpp                 |  44 ++++++
 indra/newview/llmaterialeditor.h                   |   4 +
 indra/newview/llviewermenu.cpp                     | 159 +++++++++++++++++----
 indra/newview/llviewermenu.h                       |   4 +
 indra/newview/skins/default/xui/en/menu_object.xml |  16 +++
 5 files changed, 199 insertions(+), 28 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
index c23f9ec4e7..80a0583fd0 100644
--- a/indra/newview/llmaterialeditor.cpp
+++ b/indra/newview/llmaterialeditor.cpp
@@ -1401,6 +1401,16 @@ void LLMaterialEditor::loadMaterialFromFile(const std::string& filename, S32 ind
     }
 }
 
+void LLMaterialEditor::loadLiveMaterial(LLGLTFMaterial * material, bool make_copy)
+{
+    if (!material)
+    {
+        return;
+    }
+    LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor");
+    me->loadMaterial(material, make_copy);
+}
+
 void LLMaterialEditor::loadMaterial(const tinygltf::Model &model_in, const std::string &filename_lc, S32 index)
 {
     if (model_in.materials.size() <= index)
@@ -1505,6 +1515,40 @@ void LLMaterialEditor::loadMaterial(const tinygltf::Model &model_in, const std::
     applyToSelection();
 }
 
+void LLMaterialEditor::loadMaterial(LLGLTFMaterial * material, bool make_copy)
+{
+    setBaseColorId(material->mBaseColorId);
+    setMetallicRoughnessId(material->mMetallicRoughnessId);
+    setEmissiveId(material->mEmissiveId);
+    setNormalId(material->mNormalId);
+
+    setAlphaMode(material->getAlphaMode());
+    setAlphaCutoff(material->mAlphaCutoff);
+
+    setBaseColor(material->mBaseColor);
+    setEmissiveColor(material->mEmissiveColor);
+
+    setMetalnessFactor(material->mMetallicFactor);
+    setRoughnessFactor(material->mRoughnessFactor);
+
+    setDoubleSided(material->mDoubleSided);
+
+    if (make_copy)
+    {
+        setTitle(LLTrans::getString("New Material"));
+    }
+    // else ??? Think of a name for live editing
+
+    // Todo: At the moment it always makes a 'copy'
+    // Will need a way to expand existing material
+    // once overrides are done
+
+    setHasUnsavedChanges(make_copy);
+
+    openFloater();
+    setFocus(TRUE);
+}
+
 bool LLMaterialEditor::setFromGltfModel(const tinygltf::Model& model, S32 index, bool set_textures)
 {
     if (model.materials.size() > index)
diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h
index 96bf8cc7a2..3dabc6e26a 100644
--- a/indra/newview/llmaterialeditor.h
+++ b/indra/newview/llmaterialeditor.h
@@ -104,6 +104,7 @@ public:
     // @index if -1 and file contains more than one material,
     // will promt to select specific one
     static void loadMaterialFromFile(const std::string& filename, S32 index = -1);
+    static void loadLiveMaterial(LLGLTFMaterial * material, bool make_copy);
 
     static void onLoadComplete(const LLUUID& asset_uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status);
 
@@ -221,6 +222,9 @@ public:
 
 private:
     void loadMaterial(const tinygltf::Model &model, const std::string &filename_lc, S32 index);
+    // if make_copy is set, will make a copy for saving,
+    // otherwise will edit existing material
+    void loadMaterial(LLGLTFMaterial * material, bool make_copy);
 
     friend class LLMaterialFilePicker;
 
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 31c629fae8..8a92d9062f 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -92,6 +92,7 @@
 #include "llpanelblockedlist.h"
 #include "llpanelmaininventory.h"
 #include "llmarketplacefunctions.h"
+#include "llmaterialeditor.h"
 #include "llmenuoptionpathfindingrebakenavmesh.h"
 #include "llmoveview.h"
 #include "llnavigationbar.h"
@@ -2781,6 +2782,50 @@ void handle_object_open()
 	LLFloaterReg::showInstance("openobject");
 }
 
+bool enable_object_edit_gltf_material()
+{
+    struct LLSelectedTEGetmatId : public LLSelectedTEGetFunctor<LLUUID>
+    {
+        LLSelectedTEGetmatId() : mCanModify(true) {}
+        LLUUID get(LLViewerObject* object, S32 te_index)
+        {
+            mCanModify &= (bool)object->permModify();
+            // Todo: probabnly should compare material
+            // pointers instead
+            return object->getRenderMaterialID(te_index);
+        }
+        bool mCanModify;
+    } func;
+    LLUUID mat_id;
+    bool identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&func, mat_id);
+    LL_INFOS() << " Placeholder " << identical << " " << mat_id << LL_ENDL;
+    // Todo: this is a placeholder for overrides,
+    // it will have to make sure all selection is identical
+    return func.mCanModify;
+}
+
+bool enable_object_save_gltf_material()
+{
+    struct LLSelectedTEGetmatId : public LLSelectedTEGetFunctor<LLUUID>
+    {
+        LLSelectedTEGetmatId() : mCanCopy(true) {}
+        LLUUID get(LLViewerObject* object, S32 te_index)
+        {
+            mCanCopy &= (bool)object->permCopy();
+            // permTransfer probably should be passed to editor instead
+            mCanCopy &= (bool)object->permTransfer();
+            return object->getRenderMaterialID(te_index);
+        }
+        bool mCanCopy;
+    } func;
+    LLUUID mat_id;
+    bool identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&func, mat_id);
+    LL_INFOS() << " Placeholder " << identical << " " << mat_id << LL_ENDL;
+    // Todo: this is a placeholder for overrides,
+    // it will have to make sure all selection is identical
+    return func.mCanCopy;
+}
+
 bool enable_object_open()
 {
 	// Look for contents in root object, which is all the LLFloaterOpenObject
@@ -2846,37 +2891,42 @@ class LLObjectBuild : public view_listener_t
 	}
 };
 
-void handle_object_edit()
+void update_camera()
 {
-	LLViewerParcelMgr::getInstance()->deselectLand();
+    LLViewerParcelMgr::getInstance()->deselectLand();
 
-	if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit())
-	{
-		LLFloaterTools::sPreviousFocusOnAvatar = true;
-		LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+    if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit())
+    {
+        LLFloaterTools::sPreviousFocusOnAvatar = true;
+        LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+
+        if (selection->getSelectType() == SELECT_TYPE_HUD || !gSavedSettings.getBOOL("EditCameraMovement"))
+        {
+            // always freeze camera in space, even if camera doesn't move
+            // so, for example, follow cam scripts can't affect you when in build mode
+            gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null);
+            gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+        }
+        else
+        {
+            gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+            LLViewerObject* selected_objectp = selection->getFirstRootObject();
+            if (selected_objectp)
+            {
+                // zoom in on object center instead of where we clicked, as we need to see the manipulator handles
+                gAgentCamera.setFocusGlobal(selected_objectp->getPositionGlobal(), selected_objectp->getID());
+                gAgentCamera.cameraZoomIn(0.666f);
+                gAgentCamera.cameraOrbitOver(30.f * DEG_TO_RAD);
+                gViewerWindow->moveCursorToCenter();
+            }
+        }
+    }
+}
+
+void handle_object_edit()
+{
+    update_camera();
 
-		if (selection->getSelectType() == SELECT_TYPE_HUD || !gSavedSettings.getBOOL("EditCameraMovement"))
-		{
-			// always freeze camera in space, even if camera doesn't move
-			// so, for example, follow cam scripts can't affect you when in build mode
-			gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null);
-			gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
-		}
-		else
-		{
-			gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
-			LLViewerObject* selected_objectp = selection->getFirstRootObject();
-			if (selected_objectp)
-			{
-			  // zoom in on object center instead of where we clicked, as we need to see the manipulator handles
-			  gAgentCamera.setFocusGlobal(selected_objectp->getPositionGlobal(), selected_objectp->getID());
-			  gAgentCamera.cameraZoomIn(0.666f);
-			  gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD );
-			  gViewerWindow->moveCursorToCenter();
-			}
-		}
-	}
-	
 	LLFloaterReg::showInstance("build");
 	
 	LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
@@ -2890,6 +2940,54 @@ void handle_object_edit()
 	return;
 }
 
+void load_life_gltf_material(bool copy)
+{
+    LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+    // All materials are supposed to be identical, so pcik any node
+    LLViewerObject* object = selection->getFirstNode()->getObject();
+    if (!object)
+    {
+        return;
+    }
+
+    // This functionality is a plcaholder for overrides
+    // so id doesn't load object by id, but instead gets material directly
+    LLGLTFMaterial * mat = NULL;
+
+    const S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces()); // avatars have TEs but no faces
+    for (S32 face = 0; face < num_tes; ++face)
+    {
+        LLTextureEntry *te = object->getTE(face);
+        if (te->isSelected())
+        {
+            mat = te->getGLTFMaterial();
+            break;
+        }
+    }
+
+    if (mat == NULL)
+    {
+        return;
+    }
+
+    update_camera();
+
+    LLMaterialEditor::loadLiveMaterial(mat, copy);
+
+    LLViewerJoystick::getInstance()->moveObjects(true);
+    LLViewerJoystick::getInstance()->setNeedsReset(true);
+}
+
+void handle_object_edit_gltf_material()
+{
+    load_life_gltf_material(false);
+}
+
+void handle_object_save_gltf_material()
+{
+    load_life_gltf_material(true);
+}
+
 void handle_attachment_edit(const LLUUID& inv_item_id)
 {
 	if (isAgentAvatarValid())
@@ -9560,10 +9658,15 @@ void initialize_menus()
 
 	commit.add("Object.Buy", boost::bind(&handle_buy));
 	commit.add("Object.Edit", boost::bind(&handle_object_edit));
+    commit.add("Object.Edit", boost::bind(&handle_object_edit));
+    commit.add("Object.EditGLTFMaterial", boost::bind(&handle_object_edit_gltf_material));
+    commit.add("Object.SaveGLTFMaterial", boost::bind(&handle_object_save_gltf_material));
 	commit.add("Object.Inspect", boost::bind(&handle_object_inspect));
 	commit.add("Object.Open", boost::bind(&handle_object_open));
 	commit.add("Object.Take", boost::bind(&handle_take));
 	commit.add("Object.ShowInspector", boost::bind(&handle_object_show_inspector));
+    enable.add("Object.EnableEditGLTFMaterial", boost::bind(&enable_object_edit_gltf_material));
+    enable.add("Object.EnableSaveGLTFMaterial", boost::bind(&enable_object_save_gltf_material));
 	enable.add("Object.EnableOpen", boost::bind(&enable_object_open));
 	enable.add("Object.EnableTouch", boost::bind(&enable_object_touch, _1));
 	enable.add("Object.EnableDelete", boost::bind(&enable_object_delete));
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index a90b32c984..0673652e61 100644
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -90,6 +90,8 @@ void handle_gestures(void*);
 void handle_sit_down(void*);
 void handle_object_build(void*);
 void handle_object_touch();
+bool enable_object_edit_gltf_material();
+bool enable_object_save_gltf_material();
 bool enable_object_open();
 void handle_object_open();
 
@@ -108,6 +110,8 @@ void handle_zoom_to_object(LLUUID object_id);
 void handle_object_return();
 void handle_object_delete();
 void handle_object_edit();
+void handle_object_edit_gltf_material();
+void handle_object_save_gltf_material();
 
 void handle_attachment_edit(const LLUUID& inv_item_id);
 void handle_attachment_touch(const LLUUID& inv_item_id);
diff --git a/indra/newview/skins/default/xui/en/menu_object.xml b/indra/newview/skins/default/xui/en/menu_object.xml
index ce34508303..6d37c15815 100644
--- a/indra/newview/skins/default/xui/en/menu_object.xml
+++ b/indra/newview/skins/default/xui/en/menu_object.xml
@@ -21,6 +21,22 @@
     <menu_item_call.on_enable
         function="EnableEdit"/>
   </menu_item_call>
+  <menu_item_call
+      label="Edit PBR Material"
+      name="EditGLTFMaterial">
+    <menu_item_call.on_click
+        function="Object.EditGLTFMaterial" />
+    <menu_item_call.on_enable
+        function="Object.EnableEditGLTFMaterial"/>
+  </menu_item_call>
+  <menu_item_call
+      label="Save material to inventory"
+      name="SaveGLTFMaterial">
+    <menu_item_call.on_click
+        function="Object.SaveGLTFMaterial" />
+    <menu_item_call.on_enable
+        function="Object.EnableSaveGLTFMaterial"/>
+  </menu_item_call>
   <menu_item_call
       label="Build"
       name="Build">
-- 
cgit v1.2.3