From f3216ca1cd6e63a254123635c18ba661297e8eef Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 24 Jun 2020 18:57:49 +0300
Subject: [PATCH] SL-12688 Warnings part #2

---
 indra/newview/llpanelface.cpp                 | 64 ++++++++++++++++++-
 indra/newview/lltexturectrl.cpp               | 19 +++---
 indra/newview/lltexturectrl.h                 |  2 +-
 .../skins/default/xui/en/notifications.xml    | 15 ++++-
 .../default/xui/en/panel_tools_texture.xml    |  4 ++
 5 files changed, 89 insertions(+), 15 deletions(-)

diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 3849e5c8f76..641a3602c81 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -2869,7 +2869,8 @@ void LLPanelFace::onCopyTexture()
                 {
                     LLUUID item_id;
                     LLUUID id = te_data["te"]["imageid"].asUUID();
-                    bool full_perm = get_is_library_texture(id) || (objectp->permCopy() && objectp->permTransfer() && objectp->permModify());
+                    bool from_library = get_is_predefined_texture(id);
+                    bool full_perm = from_library || (objectp->permCopy() && objectp->permTransfer() && objectp->permModify());
 
                     if (id.notNull() && !full_perm)
                     {
@@ -2890,6 +2891,12 @@ void LLPanelFace::onCopyTexture()
                         }
                     }
 
+                    if (item_id.notNull() && gInventory.isObjectDescendentOf(item_id, gInventory.getLibraryRootFolderID()))
+                    {
+                        full_perm = true;
+                        from_library = true;
+                    }
+
                     if (id.isNull()
                         || (!full_perm && item_id.isNull()))
                     {
@@ -2899,10 +2906,15 @@ void LLPanelFace::onCopyTexture()
                             te_data["te"]["imageid"] = LLUUID(gSavedSettings.getString("DefaultObjectTexture"));
                         }
                         te_data["te"]["itemfullperm"] = true;
+                        te_data["te"]["fromlibrary"] = true;
                     }
                     else
                     {
                         te_data["te"]["itemfullperm"] = full_perm;
+                        // from_library is unreliable since we don't get texture item if source object
+                        // is fullperm but it merely means additional checks when assigning texture
+                        te_data["te"]["fromlibrary"] = from_library; 
+
                         // If full permission object, texture is free to copy,
                         // but otherwise we need to check inventory and extract permissions
                         //
@@ -3046,6 +3058,40 @@ void LLPanelFace::onPasteTexture()
         return;
     }
 
+    bool full_perm = true;
+    LLSD::array_const_iterator iter = clipboard.beginArray();
+    LLSD::array_const_iterator end = clipboard.endArray();
+    for (; iter != end; ++iter)
+    {
+        const LLSD& te_data = *iter;
+        if (te_data.has("te"))
+        {
+            full_perm &= te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean();
+            if (te_data["te"].has("imageitemid"))
+            {
+                LLUUID item_id = te_data["te"]["imageitemid"].asUUID();
+                if (item_id.notNull())
+                {
+                    LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
+                    if (!itemp)
+                    {
+                        // image might be in object's inventory, but it can be not up to date
+                        LLSD notif_args;
+                        static std::string reason = getString("paste_error_inventory_not_found");
+                        notif_args["REASON"] = reason;
+                        LLNotificationsUtil::add("FacePasteFailed", notif_args);
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    if (!full_perm)
+    {
+        LLNotificationsUtil::add("FacePasteTexturePermissions");
+    }
+
     LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
 
     LLPanelFacePasteTexFunctor paste_func(this, PASTE_TEXTURE);
@@ -3082,6 +3128,7 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te)
         {
             // Texture
             bool full_perm = te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean();
+            bool from_library = te_data["te"].has("fromlibrary") && te_data["te"]["fromlibrary"].asBoolean();
             if (te_data["te"].has("imageid"))
             {
                 const LLUUID& imageid = te_data["te"]["imageid"].asUUID(); //texture or asset id
@@ -3098,12 +3145,21 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te)
                             // dropTextureAllFaces will fail if incomplete
                             itemp_res = itemp;
                         }
+                        else
+                        {
+                            // Theoretically shouldn't happend, but if it does happen, we
+                            // might need to add a notification to user that paste will fail
+                            // since inventory isn't fully loaded
+                            LL_WARNS() << "Item " << item_id << " is incomplete, paste might fail silently." << LL_ENDL;
+                        }
                     }
                 }
                 // for case when item got removed from inventory after we pressed 'copy'
                 // or texture got pasted into previous object
                 if (!itemp_res && !full_perm)
                 {
+                    // Due to checks for imageitemid in LLPanelFace::onPasteTexture() this should no longer be reachable.
+                    LL_INFOS() << "Item " << te_data["te"]["imageitemid"].asUUID() << " no longer in inventory." << LL_ENDL;
                     // Todo: fix this, we are often searching same texture multiple times (equal to number of faces)
                     // Perhaps just mPanelFace->onPasteTexture(objectp, te, &asset_to_item_id_map); ? Not pretty, but will work
                     LLViewerInventoryCategory::cat_array_t cats;
@@ -3137,11 +3193,13 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te)
 
                 if (itemp_res)
                 {
+                    // from_library is unreliable since we don't get texture item if object is
+                    // fullperm but it merely means additional checks when assigning texture
                     if (te == -1) // all faces
                     {
                         LLToolDragAndDrop::dropTextureAllFaces(objectp,
                             itemp_res,
-                            LLToolDragAndDrop::SOURCE_AGENT,
+                            from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT,
                             LLUUID::null);
                     }
                     else // one face
@@ -3149,7 +3207,7 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te)
                         LLToolDragAndDrop::dropTextureOneFace(objectp,
                             te,
                             itemp_res,
-                            LLToolDragAndDrop::SOURCE_AGENT,
+                            from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT,
                             LLUUID::null);
                     }
                 }
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 2f5be2b32ef..b5e4b3608ac 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -82,24 +82,23 @@ static const S32 LOCAL_TRACKING_ID_COLUMN = 1;
 
 
 //static
-bool get_is_library_texture(LLUUID image_id)
+bool get_is_predefined_texture(LLUUID asset_id)
 {
-    if (gInventory.isObjectDescendentOf(image_id, gInventory.getLibraryRootFolderID())
-        || image_id == LLUUID(gSavedSettings.getString("DefaultObjectTexture"))
-        || image_id == LLUUID(gSavedSettings.getString("UIImgWhiteUUID"))
-        || image_id == LLUUID(gSavedSettings.getString("UIImgInvisibleUUID"))
-        || image_id == LLUUID(SCULPT_DEFAULT_TEXTURE))
+    if (asset_id == LLUUID(gSavedSettings.getString("DefaultObjectTexture"))
+        || asset_id == LLUUID(gSavedSettings.getString("UIImgWhiteUUID"))
+        || asset_id == LLUUID(gSavedSettings.getString("UIImgInvisibleUUID"))
+        || asset_id == LLUUID(SCULPT_DEFAULT_TEXTURE))
     {
         return true;
     }
     return false;
 }
 
-LLUUID get_copy_free_item_by_asset_id(LLUUID image_id)
+LLUUID get_copy_free_item_by_asset_id(LLUUID asset_id)
 {
     LLViewerInventoryCategory::cat_array_t cats;
     LLViewerInventoryItem::item_array_t items;
-    LLAssetIDMatches asset_id_matches(image_id);
+    LLAssetIDMatches asset_id_matches(asset_id);
     gInventory.collectDescendentsIf(LLUUID::null,
         cats,
         items,
@@ -125,13 +124,13 @@ LLUUID get_copy_free_item_by_asset_id(LLUUID image_id)
     return LLUUID::null;
 }
 
-bool get_can_copy_texture(LLUUID image_id)
+bool get_can_copy_texture(LLUUID asset_id)
 {
     // User is allowed to copy a texture if:
     // library asset or default texture,
     // or copy perm asset exists in user's inventory
 
-    return get_is_library_texture(image_id) || get_copy_free_item_by_asset_id(image_id).notNull();
+    return get_is_predefined_texture(asset_id) || get_copy_free_item_by_asset_id(asset_id).notNull();
 }
 
 LLFloaterTexturePicker::LLFloaterTexturePicker(	
diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h
index 2b2c5fa2377..97e7bb0d20d 100644
--- a/indra/newview/lltexturectrl.h
+++ b/indra/newview/lltexturectrl.h
@@ -54,7 +54,7 @@ typedef boost::function<BOOL (LLUICtrl*, LLInventoryItem*)> drag_n_drop_callback
 typedef boost::function<void (LLInventoryItem*)> texture_selected_callback;
 
 // Helper functions for UI that work with picker
-bool get_is_library_texture(LLUUID image_id);
+bool get_is_predefined_texture(LLUUID asset_id);
 
 // texture picker works by asset ids since objects normaly do
 // not retain inventory ids as result these functions are looking
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index f59ac450f24..196d507507b 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -8946,7 +8946,7 @@ We cannot display a preview of this texture because it is no-copy and/or no-tran
     name="okignore"
     yestext="OK"/>
   </notification>
-  
+
   <notification
    icon="alertmodal.tga"
    name="FacePasteFailed"
@@ -8957,6 +8957,19 @@ Paste failed. [REASON]
     yestext="OK"/>
   </notification>
 
+  <notification
+   icon="alertmodal.tga"
+   name="FacePasteTexturePermissions"
+   type="alertmodal">
+    You applied a texture with limited permissions, object will inherit permissions from texture.
+    <usetemplate
+     ignoretext="Paste: You applied a texture with limited permissions"
+     name="notifyignore"/>
+    <usetemplate
+     name="okbutton"
+     yestext="OK"/>
+  </notification>
+
   <notification
    icon="alertmodal.tga"
    name="ConfirmLeaveCall"
diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
index d7bccd3aeae..a33d4259647 100644
--- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
@@ -19,6 +19,10 @@
              name="paste_error_object_face_count_mismatch">
               When all faces of an object are copied, the target object must have the same number of faces.
             </panel.string>
+            <panel.string
+             name="paste_error_inventory_not_found">
+              One or more texture not found in inventory.
+            </panel.string>
 
             <menu_button
              menu_filename="menu_copy_paste_color.xml"
-- 
GitLab