From 19283d87a5275f04e9b849e6942a2013cfc10b36 Mon Sep 17 00:00:00 2001
From: cinder <cinder@cinderblocks.biz>
Date: Sat, 19 Nov 2022 16:02:58 -0600
Subject: [PATCH] Add Refresh textures commands

---
 indra/newview/alviewermenu.cpp                | 87 +++++++++++++++++++
 .../default/xui/en/menu_attachment_other.xml  |  8 +-
 .../default/xui/en/menu_attachment_self.xml   |  6 ++
 .../default/xui/en/menu_avatar_other.xml      |  6 ++
 .../skins/default/xui/en/menu_avatar_self.xml |  6 ++
 .../skins/default/xui/en/menu_object.xml      |  6 ++
 6 files changed, 118 insertions(+), 1 deletion(-)

diff --git a/indra/newview/alviewermenu.cpp b/indra/newview/alviewermenu.cpp
index 23018b8f867..9a1a8d3becb 100644
--- a/indra/newview/alviewermenu.cpp
+++ b/indra/newview/alviewermenu.cpp
@@ -32,10 +32,13 @@
 #include "alcinematicmode.h"
 #include "alfloaterparticleeditor.h"
 #include "llagent.h"
+#include "llappviewer.h"
+#include "llavatarpropertiesprocessor.h"
 #include "llhudobject.h"
 #include "llnotifications.h"
 #include "llnotificationsutil.h"
 #include "llselectmgr.h"
+#include "lltexturecache.h"
 #include "llviewercontrol.h"
 #include "llviewermenu.h"
 #include "llviewerobject.h"
@@ -321,6 +324,88 @@ namespace
 			LLFloaterReg::showInstance("generic_text", args);
 		}
 	}
+
+    void destroy_texture(const LLUUID& id)
+    {
+        if (id.isNull() || id == IMG_DEFAULT)
+            return;
+        LLViewerFetchedTexture* texture = LLViewerTextureManager::getFetchedTexture(id);
+        if (texture)
+            texture->clearFetchedResults();
+        LLAppViewer::getTextureCache()->removeFromCache(id);
+    }
+
+    void object_texture_refresh()
+	{
+        for (LLObjectSelection::valid_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_begin();
+             iter != LLSelectMgr::getInstance()->getSelection()->valid_end();
+             ++iter)
+        {
+            LLSelectNode* node = *iter;
+            if (!node)
+                continue;
+            std::map<LLUUID, std::vector<U8>> faces_per_tex;
+            for (U8 i = 0; i < node->getObject()->getNumTEs(); ++i)
+            {
+                if (!node->isTESelected(i))
+                continue;
+                LLViewerTexture* img = node->getObject()->getTEImage(i);
+                faces_per_tex[img->getID()].push_back(i);
+
+                if (node->getObject()->getTE(i)->getMaterialParams().notNull())
+                {
+                LLViewerTexture* norm_img = node->getObject()->getTENormalMap(i);
+                faces_per_tex[norm_img->getID()].push_back(i);
+                LLViewerTexture* spec_img = node->getObject()->getTESpecularMap(i);
+                faces_per_tex[spec_img->getID()].push_back(i);
+                }
+            }
+
+            for (auto const& it : faces_per_tex)
+            {
+                destroy_texture(it.first);
+            }
+
+            if (node->getObject()->isSculpted() && !node->getObject()->isMesh())
+            {
+                const LLSculptParams* sculpt_params = node->getObject()->getSculptParams();
+                if (sculpt_params)
+                {
+                LLUUID                  sculptie = sculpt_params->getSculptTexture();
+                LLViewerFetchedTexture* tx       = LLViewerTextureManager::getFetchedTexture(sculptie);
+                if (tx)
+                {
+                        const LLViewerTexture::ll_volume_list_t* pVolumeList = tx->getVolumeList(LLRender::SCULPT_TEX);
+                        destroy_texture(sculptie);
+                        for (S32 idxVolume = 0; idxVolume < tx->getNumVolumes(LLRender::SCULPT_TEX); ++idxVolume)
+                        {
+                            LLVOVolume* pVolume = pVolumeList->at(idxVolume);
+                            if (pVolume)
+                                pVolume->notifyMeshLoaded();
+                        }
+                }
+                }
+            }
+        }
+	}
+
+    void avatar_texture_refresh()
+	{
+        LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
+        if (!avatar) { return; }
+
+        for (U32 baked_idx = 0; baked_idx < LLAvatarAppearanceDefines::BAKED_NUM_INDICES; ++baked_idx)
+        {
+            LLAvatarAppearanceDefines::ETextureIndex te_idx =
+                LLAvatarAppearance::getDictionary()->bakedToLocalTextureIndex(
+					static_cast<LLAvatarAppearanceDefines::EBakedTextureIndex>(baked_idx));
+            destroy_texture(avatar->getTE(te_idx)->getID());
+        }
+        LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(avatar->getID());
+
+        // *TODO: We want to refresh their attachments too!
+	}
+
 }
 
 ////////////////////////////////////////////////////////
@@ -338,6 +423,7 @@ void ALViewerMenu::initialize_menus()
 	commit.add("Avatar.CopyData",		[](LLUICtrl* ctrl, const LLSD& param) { avatar_copy_data(param); });
 	commit.add("Avatar.ManageEstate", [](LLUICtrl* ctrl, const LLSD& param) { manage_estate(param); });
 	commit.add("Avatar.TeleportTo", [](LLUICtrl* ctrl, const LLSD& param) { teleport_to(); });
+    commit.add("Avatar.RefreshTexture", [](LLUICtrl* ctrl, const LLSD& param) { avatar_texture_refresh(); });
 
 	commit.add("Advanced.DebugSimFeatures", [](LLUICtrl* ctrl, const LLSD& param) { spawn_debug_simfeatures(); });
 
@@ -346,6 +432,7 @@ void ALViewerMenu::initialize_menus()
 	commit.add("Object.AlchemyExplode", [](LLUICtrl* ctrl, const LLSD& param) { object_explode(); });
 	commit.add("Object.AlchemyDestroy", [](LLUICtrl* ctrl, const LLSD& param) { object_destroy(); });
 	commit.add("Object.AlchemyForceDelete", [](LLUICtrl* ctrl, const LLSD& param) { object_force_delete(); });
+    commit.add("Object.RefreshTexture", [](LLUICtrl* ctrl, const LLSD& param) { object_texture_refresh(); });
 
 	commit.add("Tools.UndeformSelf", [](LLUICtrl* ctrl, const LLSD& param) { avatar_undeform_self(); });
 
diff --git a/indra/newview/skins/default/xui/en/menu_attachment_other.xml b/indra/newview/skins/default/xui/en/menu_attachment_other.xml
index 49c0f93d8ce..a8b4778ed52 100644
--- a/indra/newview/skins/default/xui/en/menu_attachment_other.xml
+++ b/indra/newview/skins/default/xui/en/menu_attachment_other.xml
@@ -51,7 +51,13 @@
   <context_menu
    label="Appearance"
    name="Appearance">
-    <menu_item_call
+      <menu_item_call
+       label="Refresh Textures"
+       name="Refresh Textures">
+        <menu_item_call.on_click
+         function="Avatar.RefreshTexture" />
+	  </menu_item_call>
+	  <menu_item_call
       label="Reset Skeleton"
       name="Reset Skeleton">
       <menu_item_call.on_click
diff --git a/indra/newview/skins/default/xui/en/menu_attachment_self.xml b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
index 31f12d10970..9fd37581ed7 100644
--- a/indra/newview/skins/default/xui/en/menu_attachment_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_attachment_self.xml
@@ -307,6 +307,12 @@
      function="Tools.StopAllAnimations" />
   </menu_item_call>
   <menu_item_separator/>
+  <menu_item_call
+   label="Refresh Textures"
+   name="Refresh Textures">
+    <menu_item_call.on_click
+     function="Avatar.RefreshTexture" />
+  </menu_item_call>
   <menu_item_call label="Reset skeleton"
        layout="topleft"
        name="Reset Skeleton">
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_other.xml b/indra/newview/skins/default/xui/en/menu_avatar_other.xml
index aaf5b784e3b..c5ff32ccf67 100644
--- a/indra/newview/skins/default/xui/en/menu_avatar_other.xml
+++ b/indra/newview/skins/default/xui/en/menu_avatar_other.xml
@@ -59,6 +59,12 @@
       <menu_item_call.on_click
        function="Avatar.ResetSkeleton" />
     </menu_item_call>
+    <menu_item_call
+     label="Refresh Textures"
+     name="Refresh Textures">
+      <menu_item_call.on_click
+       function="Avatar.RefreshTexture" />
+    </menu_item_call>
     <menu_item_call
      label="Reset Skeleton And Animations"
      name="Reset Skeleton And Animations">
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_self.xml b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
index c22d98a61c2..d5421874c8e 100644
--- a/indra/newview/skins/default/xui/en/menu_avatar_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
@@ -277,6 +277,12 @@
          function="Tools.StopAllAnimations" />
   </menu_item_call>
   <menu_item_separator/>
+  <menu_item_call
+   label="Refresh Textures"
+   name="Refresh Textures">
+    <menu_item_call.on_click
+     function="Avatar.RefreshTexture" />
+  </menu_item_call>
   <menu_item_call label="Reset skeleton"
      layout="topleft"
      name="Reset Skeleton">
diff --git a/indra/newview/skins/default/xui/en/menu_object.xml b/indra/newview/skins/default/xui/en/menu_object.xml
index 1530a59caaf..5d50f3e80ef 100644
--- a/indra/newview/skins/default/xui/en/menu_object.xml
+++ b/indra/newview/skins/default/xui/en/menu_object.xml
@@ -162,6 +162,12 @@
     <menu_item_call.on_click
         function="Object.ZoomIn" />
   </menu_item_call>
+  <menu_item_call
+    label="Refresh Textures"
+    name="RefreshTextures">
+     <menu_item_call.on_click
+      function="Object.RefreshTexture" />
+  </menu_item_call>
   <menu_item_call
       label="Show in linksets"
       name="show_in_linksets">
-- 
GitLab