diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 2b85c62edb..8553f10f4f 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -6793,6 +6793,37 @@ void handle_attachment_touch(const LLUUID& idItem)
}
//
+// Texture Refresh on worn attachments
+void handle_attachment_texture_refresh(const LLUUID& idItem)
+{
+ // get the associated worn attachment's UUID
+ const LLInventoryItem* pItem = gInventory.getItem(idItem);
+ if ( (!isAgentAvatarValid()) || (!pItem) )
+ {
+ return;
+ }
+
+ LLViewerObject* pAttachObj = gAgentAvatarp->getWornAttachment(pItem->getLinkedUUID());
+ if (!pAttachObj)
+ return;
+
+ // iterate through the list of child prims, call texture refresh on each one of them
+ LLViewerObject::const_child_list_t& children = pAttachObj->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = children.begin();
+ iter != children.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+
+ // NULL means, we don't have individual texture faces selected,
+ // so refresh them all
+ handle_object_tex_refresh(child, NULL);
+ }
+
+ // texture refresh the root prim, too
+ handle_object_tex_refresh(pAttachObj, NULL);
+}
+//
+
// virtual
void LLObjectBridge::performAction(LLInventoryModel* model, std::string action)
{
@@ -6839,6 +6870,12 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action)
handle_attachment_touch(mUUID);
}
//
+ // Texture Refresh on worn attachments
+ else if ("texture_refresh_attachment" == action)
+ {
+ handle_attachment_texture_refresh(mUUID);
+ }
+ //
else if (isRemoveAction(action))
{
LLAppearanceMgr::instance().removeItemFromAvatar(mUUID);
@@ -7029,6 +7066,13 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
if ( ((flags & FIRST_SELECTED_ITEM) == 0) || (!enable_attachment_touch(mUUID)) )
disabled_items.push_back(std::string("Touch Attachment"));
+ // Texture Refresh on worn attachments
+ if (item->getType() == LLAssetType::AT_OBJECT)
+ {
+ items.push_back(std::string("Texture Refresh Attachment"));
+ }
+ //
+
items.push_back(std::string("Detach From Yourself"));
// [RLVa:KB] - Checked: 2010-02-27 (RLVa-1.2.0a) | Modified: RLVa-1.2.0a
if ( (rlv_handler_t::isEnabled()) && (!gRlvAttachmentLocks.canDetach(item)) )
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index bb502ea7e1..db15723267 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -3120,6 +3120,67 @@ void destroy_texture(const LLUUID& id) // will be used by the texture refresh f
LLAppViewer::getTextureCache()->removeFromCache(id);
}
+void handle_object_tex_refresh(LLViewerObject* object, LLSelectNode* node)
+{
+ U8 te_count = object->getNumTEs();
+ // map from texture ID to list of faces using it
+ typedef std::map< LLUUID, std::vector > map_t;
+ map_t faces_per_texture;
+ for (U8 i = 0; i < te_count; ++i)
+ {
+ // "node" will be NULL when invoked from inventory menu,
+ // otherwise it will hold the root node of the selection and we
+ // need to make sure only to refresh the selected faces
+ if (node && !node->isTESelected(i)) continue;
+
+ LLViewerTexture* img = object->getTEImage(i);
+ faces_per_texture[img->getID()].push_back(i);
+
+ if (object->getTE(i)->getMaterialParams().notNull())
+ {
+ LLViewerTexture* norm_img = object->getTENormalMap(i);
+ faces_per_texture[norm_img->getID()].push_back(i);
+
+ LLViewerTexture* spec_img = object->getTESpecularMap(i);
+ faces_per_texture[spec_img->getID()].push_back(i);
+ }
+ }
+
+ map_t::iterator it;
+ for (it = faces_per_texture.begin(); it != faces_per_texture.end(); ++it)
+ {
+ destroy_texture(it->first);
+ }
+
+ // Refresh sculpt texture
+ if (object->isSculpted())
+ {
+ LLSculptParams *sculpt_params = (LLSculptParams *)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ if (sculpt_params)
+ {
+ LLUUID sculpt_uuid = sculpt_params->getSculptTexture();
+
+ LLViewerFetchedTexture* tx = LLViewerTextureManager::getFetchedTexture(sculpt_uuid);
+ if (tx)
+ {
+ S32 num_volumes = tx->getNumVolumes(LLRender::SCULPT_TEX);
+ const LLViewerTexture::ll_volume_list_t* pVolumeList = tx->getVolumeList(LLRender::SCULPT_TEX);
+
+ destroy_texture(sculpt_uuid);
+
+ for (S32 idxVolume = 0; idxVolume < num_volumes; ++idxVolume)
+ {
+ LLVOVolume* pVolume = pVolumeList->at(idxVolume);
+ if (pVolume)
+ {
+ pVolume->notifyMeshLoaded();
+ }
+ }
+ }
+ }
+ }
+}
+
class LLObjectTexRefresh : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -3129,61 +3190,7 @@ class LLObjectTexRefresh : public view_listener_t
iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++)
{
LLSelectNode* node = *iter;
-
- U8 te_count = node->getObject()->getNumTEs();
- // map from texture ID to list of faces using it
- typedef std::map< LLUUID, std::vector > map_t;
- map_t faces_per_texture;
- for (U8 i = 0; i < te_count; ++i)
- {
- if (!node->isTESelected(i)) continue;
-
- LLViewerTexture* img = node->getObject()->getTEImage(i);
- faces_per_texture[img->getID()].push_back(i);
-
- if (node->getObject()->getTE(i)->getMaterialParams().notNull())
- {
- LLViewerTexture* norm_img = node->getObject()->getTENormalMap(i);
- faces_per_texture[norm_img->getID()].push_back(i);
-
- LLViewerTexture* spec_img = node->getObject()->getTESpecularMap(i);
- faces_per_texture[spec_img->getID()].push_back(i);
- }
- }
-
- map_t::iterator it;
- for (it = faces_per_texture.begin(); it != faces_per_texture.end(); ++it)
- {
- destroy_texture(it->first);
- }
-
- // Refresh sculpt texture
- if (node->getObject()->isSculpted())
- {
- LLSculptParams *sculpt_params = (LLSculptParams *)node->getObject()->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
- if (sculpt_params)
- {
- LLUUID sculpt_uuid = sculpt_params->getSculptTexture();
-
- LLViewerFetchedTexture* tx = LLViewerTextureManager::getFetchedTexture(sculpt_uuid);
- if (tx)
- {
- S32 num_volumes = tx->getNumVolumes(LLRender::SCULPT_TEX);
- const LLViewerTexture::ll_volume_list_t* pVolumeList = tx->getVolumeList(LLRender::SCULPT_TEX);
-
- destroy_texture(sculpt_uuid);
-
- for (S32 idxVolume = 0; idxVolume < num_volumes; ++idxVolume)
- {
- LLVOVolume* pVolume = pVolumeList->at(idxVolume);
- if (pVolume)
- {
- pVolume->notifyMeshLoaded();
- }
- }
- }
- }
- }
+ handle_object_tex_refresh(node->getObject(),node);
}
return true;
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index d40dcdfce4..b84d55ff83 100644
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -38,6 +38,7 @@ class LLView;
class LLParcelSelection;
class LLObjectSelection;
class LLSelectNode;
+class LLViewerObject;
// [RLVa:KB] - Checked: RLVa-2.0.0
void set_use_wireframe(bool useWireframe);
@@ -103,6 +104,7 @@ void handle_object_build(void*);
void handle_object_touch();
bool enable_object_open();
void handle_object_open();
+void handle_object_tex_refresh(LLViewerObject* object, LLSelectNode* node);
bool visible_take_object();
bool tools_visible_take_object();
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index fd6853a102..fe026e75e3 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -855,6 +855,14 @@
function="Inventory.DoToSelected"
parameter="touch" />
+
+
+