summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/app_settings/settings.xml2
-rw-r--r--indra/newview/llagent.cpp3
-rw-r--r--indra/newview/llappviewer.cpp1
-rw-r--r--indra/newview/llappviewermacosx-objc.mm2
-rw-r--r--indra/newview/llappviewermacosx.cpp2
-rw-r--r--indra/newview/lldrawpoolbump.cpp8
-rw-r--r--indra/newview/llfasttimerview.cpp2
-rw-r--r--indra/newview/llfavoritesbar.cpp364
-rw-r--r--indra/newview/llfavoritesbar.h39
-rw-r--r--indra/newview/llfloater360capture.cpp4
-rw-r--r--indra/newview/llfloaterauction.cpp2
-rw-r--r--indra/newview/llfloatercolorpicker.cpp2
-rw-r--r--indra/newview/llfloaterimagepreview.cpp1
-rw-r--r--indra/newview/llfloaterpreference.cpp23
-rw-r--r--indra/newview/llfloaterpreference.h10
-rw-r--r--indra/newview/llfloaterpreferencesgraphicsadvanced.cpp2
-rw-r--r--indra/newview/llinventorybridge.cpp6
-rw-r--r--indra/newview/llinventorygallery.cpp33
-rw-r--r--indra/newview/llinventorygallery.h1
-rw-r--r--indra/newview/llinventorygallerymenu.cpp288
-rw-r--r--indra/newview/llmaterialeditor.cpp10
-rw-r--r--indra/newview/llmeshrepository.cpp20
-rw-r--r--indra/newview/llnetmap.cpp2
-rw-r--r--indra/newview/llpanelavatar.cpp5
-rw-r--r--indra/newview/llpanelavatar.h2
-rw-r--r--indra/newview/llpanelgroupnotices.cpp7
-rw-r--r--indra/newview/llpanelmaininventory.cpp1
-rw-r--r--indra/newview/llpanelprofile.cpp46
-rw-r--r--indra/newview/llpanelprofile.h6
-rw-r--r--indra/newview/llsnapshotlivepreview.cpp10
-rw-r--r--indra/newview/llspatialpartition.h1
-rw-r--r--indra/newview/lltexturecache.cpp11
-rw-r--r--indra/newview/lltexturecache.h2
-rw-r--r--indra/newview/lltexturefetch.cpp7
-rw-r--r--indra/newview/lltinygltfhelper.cpp9
-rw-r--r--indra/newview/lltooldraganddrop.cpp11
-rw-r--r--indra/newview/llviewerassetupload.cpp2
-rw-r--r--indra/newview/llviewercontrol.cpp1
-rw-r--r--indra/newview/llviewerjoystick.cpp2
-rw-r--r--indra/newview/llviewermenu.cpp79
-rw-r--r--indra/newview/llviewermenu.h2
-rw-r--r--indra/newview/llviewerobject.cpp324
-rw-r--r--indra/newview/llviewerobject.h2
-rwxr-xr-xindra/newview/llviewerparceloverlay.cpp2
-rw-r--r--indra/newview/llviewertexture.cpp3
-rw-r--r--indra/newview/llviewertexturelist.cpp4
-rw-r--r--indra/newview/llviewerwindow.cpp6
-rw-r--r--indra/newview/llvoavatar.cpp25
-rw-r--r--indra/newview/llvoavatar.h2
-rw-r--r--indra/newview/llvoicevivox.cpp2
-rw-r--r--indra/newview/llvosky.cpp4
-rw-r--r--indra/newview/llvosky.h2
-rw-r--r--indra/newview/llvotree.cpp4
-rw-r--r--indra/newview/llvovolume.cpp30
-rw-r--r--indra/newview/llwebprofile.cpp4
-rw-r--r--indra/newview/skins/default/xui/en/menu_gallery_inventory.xml228
-rw-r--r--indra/newview/skins/default/xui/en/menu_object.xml48
57 files changed, 1238 insertions, 483 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 00b59f9a4d..8f651a0294 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -9022,7 +9022,7 @@
<key>RenderHiDPI</key>
<map>
<key>Comment</key>
- <string>Enable support for HiDPI displays, like Retina (MacOS X ONLY, requires restart)</string>
+ <string>Enable support for HiDPI displays, like Retina (macOS ONLY, requires restart)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 3853aaa8fd..e7234303a8 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -1473,8 +1473,9 @@ void LLAgent::pitch(F32 angle)
// after left-clicking the mouse on the avatar and dragging down
//
// The issue is observed on angle below 10 degrees
+ bool isMouseLookOn = mControlFlags & AGENT_CONTROL_MOUSELOOK;
const F32 look_down_limit = 179.f * DEG_TO_RAD;
- const F32 look_up_limit = 10.f * DEG_TO_RAD;
+ const F32 look_up_limit = (isMouseLookOn ? 1.f : 10.f) * DEG_TO_RAD;
F32 angle_from_skyward = acos(mFrameAgent.getAtAxis() * skyward);
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 4a43133ff6..557ee1ab16 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2342,6 +2342,7 @@ void LLAppViewer::initLoggingAndGetLastDuration()
// Set the log file to SecondLife.log
LLError::logToFile(log_file);
+ LL_INFOS() << "Started logging to " << log_file << LL_ENDL;
if (!duration_log_msg.empty())
{
LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL;
diff --git a/indra/newview/llappviewermacosx-objc.mm b/indra/newview/llappviewermacosx-objc.mm
index 17301847e8..81ab4e0feb 100644
--- a/indra/newview/llappviewermacosx-objc.mm
+++ b/indra/newview/llappviewermacosx-objc.mm
@@ -25,7 +25,7 @@
*/
#if !defined LL_DARWIN
- #error "Use only with Mac OS X"
+ #error "Use only with macOS"
#endif
#import <Cocoa/Cocoa.h>
diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index 8b313a321b..72e38cc1ea 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -27,7 +27,7 @@
#include "llviewerprecompiledheaders.h"
#if !defined LL_DARWIN
- #error "Use only with Mac OS X"
+ #error "Use only with macOS"
#endif
#define LL_CARBON_CRASH_HANDLER 1
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index a0ce0ef6cf..77a196380b 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -849,11 +849,14 @@ void LLBumpImageList::onSourceStandardLoaded( BOOL success, LLViewerFetchedTextu
void LLBumpImageList::generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nrm_image)
{
+ LLImageDataSharedLock lockIn(src);
+ LLImageDataLock lockOut(nrm_image);
+
U8* nrm_data = nrm_image->getData();
S32 resX = src->getWidth();
S32 resY = src->getHeight();
- U8* src_data = src->getData();
+ const U8* src_data = src->getData();
S32 src_cmp = src->getComponents();
@@ -911,6 +914,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
+ LLImageDataSharedLock lock(src);
bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries );
bump_image_map_t::iterator iter = entries_list.find(source_asset_id);
@@ -933,7 +937,7 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI
U8* dst_data = dst_image->getData();
S32 dst_data_size = dst_image->getDataSize();
- U8* src_data = src->getData();
+ const U8* src_data = src->getData();
S32 src_data_size = src->getDataSize();
S32 src_components = src->getComponents();
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index 5b8ca6c49c..9cf9f45bfb 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -448,6 +448,8 @@ void saveChart(const std::string& label, const char* suffix, LLImageRaw* scratch
// disable use of glReadPixels which messes up nVidia nSight graphics debugging
if (!LLRender::sNsightDebugSupport)
{
+ LLImageDataSharedLock lock(scratch);
+
//read result back into raw image
glReadPixels(0, 0, 1024, 512, GL_RGB, GL_UNSIGNED_BYTE, scratch->getData());
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index cdce6f7156..f926a8a6d5 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -79,7 +79,7 @@ public:
}
void setLandmarkID(const LLUUID& id) { mLandmarkID = id; }
- const LLUUID& getLandmarkId() const { return mLandmarkID; }
+ const LLUUID& getLandmarkID() const { return mLandmarkID; }
const std::string& getName()
{
@@ -192,7 +192,7 @@ public:
}
void setLandmarkID(const LLUUID& id){ mLandmarkInfoGetter.setLandmarkID(id); }
- const LLUUID& getLandmarkId() const { return mLandmarkInfoGetter.getLandmarkId(); }
+ const LLUUID& getLandmarkID() const { return mLandmarkInfoGetter.getLandmarkID(); }
void onMouseEnter(S32 x, S32 y, MASK mask)
{
@@ -237,7 +237,8 @@ public:
return TRUE;
}
- void setLandmarkID(const LLUUID& id){ mLandmarkInfoGetter.setLandmarkID(id); }
+ const LLUUID& getLandmarkID() const { return mLandmarkInfoGetter.getLandmarkID(); }
+ void setLandmarkID(const LLUUID& id) { mLandmarkInfoGetter.setLandmarkID(id); }
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask)
{
@@ -285,15 +286,44 @@ private:
class LLFavoriteLandmarkToggleableMenu : public LLToggleableMenu
{
public:
- virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg)
- {
- *accept = ACCEPT_NO;
- return TRUE;
- }
+ // virtual
+ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type,
+ void* cargo_data, EAcceptance* accept, std::string& tooltip_msg) override
+ {
+ mToolbar->handleDragAndDropToMenu(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+ return TRUE;
+ }
+
+ // virtual
+ BOOL handleHover(S32 x, S32 y, MASK mask) override
+ {
+ mIsHovering = true;
+ LLToggleableMenu::handleHover(x, y, mask);
+ mIsHovering = false;
+ return TRUE;
+ }
+
+ // virtual
+ void setVisible(BOOL visible) override
+ {
+ // Avoid of hiding the menu during hovering
+ if (visible || !mIsHovering)
+ {
+ LLToggleableMenu::setVisible(visible);
+ }
+ }
+
+ void setToolbar(LLFavoritesBarCtrl* toolbar)
+ {
+ mToolbar = toolbar;
+ }
+
+ ~LLFavoriteLandmarkToggleableMenu()
+ {
+ // Enable subsequent setVisible(FALSE)
+ mIsHovering = false;
+ setVisible(FALSE);
+ }
protected:
LLFavoriteLandmarkToggleableMenu(const LLToggleableMenu::Params& p):
@@ -301,6 +331,10 @@ protected:
{
}
+private:
+ LLFavoritesBarCtrl* mToolbar { nullptr };
+ bool mIsHovering { false };
+
friend class LLUICtrlFactory;
};
@@ -378,12 +412,12 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)
mOverflowMenuHandle(),
mContextMenuHandle(),
mImageDragIndication(p.image_drag_indication),
- mShowDragMarker(FALSE),
+ mShowDragMarker(false),
mLandingTab(NULL),
mLastTab(NULL),
- mTabsHighlightEnabled(TRUE),
mUpdateDropDownItems(true),
mRestoreOverflowMenu(false),
+ mDragToOverflowMenu(false),
mGetPrevItems(true),
mMouseX(0),
mMouseY(0),
@@ -416,17 +450,16 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)
LLFavoritesBarCtrl::~LLFavoritesBarCtrl()
{
- gInventory.removeObserver(this);
+ gInventory.removeObserver(this);
- if (mOverflowMenuHandle.get()) mOverflowMenuHandle.get()->die();
- if (mContextMenuHandle.get()) mContextMenuHandle.get()->die();
+ if (mOverflowMenuHandle.get())
+ mOverflowMenuHandle.get()->die();
+ if (mContextMenuHandle.get())
+ mContextMenuHandle.get()->die();
}
BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg)
+ EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg)
{
*accept = ACCEPT_NO;
@@ -452,26 +485,52 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
// Copy the item into the favorites folder (if it's not already there).
LLInventoryItem *item = (LLInventoryItem *)cargo_data;
- if (LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(findChildByLocalCoords(x, y)))
+ if (mDragToOverflowMenu)
{
- setLandingTab(dest);
+ LLView* overflow_menu = mOverflowMenuHandle.get();
+ if (overflow_menu && !overflow_menu->isDead() && overflow_menu->getVisible())
+ {
+ overflow_menu->handleHover(x, y, mask);
+ }
}
- else if (mLastTab && (x >= mLastTab->getRect().mRight))
+ else // Drag to the toolbar itself
{
- /*
- * the condition dest == NULL can be satisfied not only in the case
- * of dragging to the right from the last tab of the favbar. there is a
- * small gap between each tab. if the user drags something exactly there
- * then mLandingTab will be set to NULL and the dragged item will be pushed
- * to the end of the favorites bar. this is incorrect behavior. that's why
- * we need an additional check which excludes the case described previously
- * making sure that the mouse pointer is beyond the last tab.
- */
- setLandingTab(NULL);
+ // Drag to a landmark button?
+ if (LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(findChildByLocalCoords(x, y)))
+ {
+ setLandingTab(dest);
+ }
+ else
+ {
+ // Drag to the "More" button?
+ if (mMoreTextBox && mMoreTextBox->getVisible() && mMoreTextBox->getRect().pointInRect(x, y))
+ {
+ LLView* overflow_menu = mOverflowMenuHandle.get();
+ if (!overflow_menu || overflow_menu->isDead() || !overflow_menu->getVisible())
+ {
+ showDropDownMenu();
+ }
+ }
+
+ // Drag to the right of the last landmark button?
+ if (mLastTab && (x >= mLastTab->getRect().mRight))
+ {
+ /*
+ * the condition dest == NULL can be satisfied not only in the case
+ * of dragging to the right from the last tab of the favbar. there is a
+ * small gap between each tab. if the user drags something exactly there
+ * then mLandingTab will be set to NULL and the dragged item will be pushed
+ * to the end of the favorites bar. this is incorrect behavior. that's why
+ * we need an additional check which excludes the case described previously
+ * making sure that the mouse pointer is beyond the last tab.
+ */
+ setLandingTab(NULL);
+ }
+ }
}
- // check if we are dragging an existing item from the favorites bar
- bool existing_drop = false;
+ // Check whether we are dragging an existing item from the favorites bar
+ bool existing_item = false;
if (item && mDragItemId == item->getUUID())
{
// There is a chance of mDragItemId being obsolete
@@ -479,21 +538,19 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
// results in viewer not geting a 'mouse up' signal
for (LLInventoryModel::item_array_t::iterator i = mItems.begin(); i != mItems.end(); ++i)
{
- LLViewerInventoryItem* currItem = *i;
-
- if (currItem->getUUID() == mDragItemId)
+ if ((*i)->getUUID() == mDragItemId)
{
- existing_drop = true;
+ existing_item = true;
break;
}
}
}
- if (existing_drop)
+ if (existing_item)
{
*accept = ACCEPT_YES_SINGLE;
- showDragMarker(TRUE);
+ showDragMarker(true);
if (drop)
{
@@ -511,14 +568,14 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
*accept = ACCEPT_YES_COPY_MULTI;
- showDragMarker(TRUE);
+ showDragMarker(true);
if (drop)
{
if (mItems.empty())
{
setLandingTab(NULL);
- mLastTab = NULL;
+ mLastTab = NULL;
}
handleNewFavoriteDragAndDrop(item, favorites_id, x, y);
}
@@ -532,82 +589,56 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
return TRUE;
}
+bool LLFavoritesBarCtrl::handleDragAndDropToMenu(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg)
+{
+ mDragToOverflowMenu = true;
+ BOOL handled = handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+ mDragToOverflowMenu = false;
+ return handled;
+}
+
void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y)
{
- if (mItems.empty())
- {
- // Isn't supposed to be empty
+ if (LL_UNLIKELY(mItems.empty()))
return;
- }
- // Identify the button hovered and the side to drop
- LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(mLandingTab);
- bool insert_before = true;
- if (!dest)
- {
- insert_before = false;
- dest = dynamic_cast<LLFavoriteLandmarkButton*>(mLastTab);
- }
-
- // There is no need to handle if an item was dragged onto itself
- if (dest && dest->getLandmarkId() == mDragItemId)
- {
- return;
- }
-
- // Insert the dragged item in the right place
- if (dest)
- {
- LLInventoryModel::updateItemsOrder(mItems, mDragItemId, dest->getLandmarkId(), insert_before);
- }
- else
- {
- // This can happen when the item list is empty
- mItems.push_back(gInventory.getItem(mDragItemId));
- }
+ LLUUID target_id;
+ bool insert_before = false;
+ if (!findDragAndDropTarget(target_id, insert_before, x, y))
+ return;
- LLFavoritesOrderStorage::instance().saveItemsOrder(mItems);
+ // There is no need to handle if an item was dragged onto itself
+ if (target_id == mDragItemId)
+ return;
- LLToggleableMenu* menu = (LLToggleableMenu*) mOverflowMenuHandle.get();
+ // Move the dragged item to the right place in the array
+ LLInventoryModel::updateItemsOrder(mItems, mDragItemId, target_id, insert_before);
+ LLFavoritesOrderStorage::instance().saveItemsOrder(mItems);
- if (menu && menu->getVisible())
- {
- menu->setVisible(FALSE);
- showDropDownMenu();
- }
+ LLView* menu = mOverflowMenuHandle.get();
+ if (menu && !menu->isDead() && menu->getVisible())
+ {
+ updateOverflowMenuItems();
+ positionAndShowOverflowMenu();
+ }
}
void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, const LLUUID& favorites_id, S32 x, S32 y)
{
// Identify the button hovered and the side to drop
- LLFavoriteLandmarkButton* dest = NULL;
- bool insert_before = true;
- if (!mItems.empty())
- {
- // [MAINT-2386] When multiple landmarks are selected and dragged onto an empty favorites bar,
- // the viewer would crash when casting mLastTab below, as mLastTab is still null when the
- // second landmark is being added.
- // To ensure mLastTab is valid, we need to call updateButtons() at the end of this function
- dest = dynamic_cast<LLFavoriteLandmarkButton*>(mLandingTab);
- if (!dest)
- {
- insert_before = false;
- dest = dynamic_cast<LLFavoriteLandmarkButton*>(mLastTab);
- }
- }
-
- // There is no need to handle if an item was dragged onto itself
- if (dest && dest->getLandmarkId() == mDragItemId)
- {
- return;
- }
-
+ LLUUID target_id;
+ bool insert_before = false;
+ // There is no need to handle if an item was dragged onto itself
+ if (findDragAndDropTarget(target_id, insert_before, x, y) && (target_id == mDragItemId))
+ return;
+
LLPointer<LLViewerInventoryItem> viewer_item = new LLViewerInventoryItem(item);
- // Insert the dragged item in the right place
- if (dest)
+ // Insert the dragged item to the right place
+ if (target_id.notNull())
{
- insertItem(mItems, dest->getLandmarkId(), viewer_item, insert_before);
+ insertItem(mItems, target_id, viewer_item, insert_before);
}
else
{
@@ -663,10 +694,75 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con
// This also ensures that mLastTab will be valid when dropping multiple
// landmarks to an empty favorites bar.
updateButtons();
-
+
+ LLView* overflow_menu = mOverflowMenuHandle.get();
+ if (overflow_menu && !overflow_menu->isDead() && overflow_menu->getVisible())
+ {
+ updateOverflowMenuItems();
+ positionAndShowOverflowMenu();
+ }
+
LL_INFOS("FavoritesBar") << "Copied inventory item #" << item->getUUID() << " to favorites." << LL_ENDL;
}
+bool LLFavoritesBarCtrl::findDragAndDropTarget(LLUUID& target_id, bool& insert_before, S32 x, S32 y)
+{
+ if (mItems.empty())
+ return false;
+
+ if (mDragToOverflowMenu)
+ {
+ LLView* overflow_menu = mOverflowMenuHandle.get();
+ if (LL_UNLIKELY(!overflow_menu || overflow_menu->isDead() || !overflow_menu->getVisible()))
+ return false;
+
+ // Identify the menu item hovered and the side to drop
+ LLFavoriteLandmarkMenuItem* target_item = dynamic_cast<LLFavoriteLandmarkMenuItem*>(overflow_menu->childFromPoint(x, y));
+ if (target_item)
+ {
+ insert_before = true;
+ }
+ else
+ {
+ // Choose the bottom landmark menu item
+ auto begin = overflow_menu->getChildList()->begin();
+ auto end = overflow_menu->getChildList()->end();
+ auto check = [](const LLView* child) -> bool
+ {
+ return dynamic_cast<const LLFavoriteLandmarkMenuItem*>(child);
+ };
+ // Menu items are placed in the backward order, so the bottom goes first
+ auto it = std::find_if(begin, end, check);
+ if (LL_UNLIKELY(it == end))
+ return false;
+ target_item = (LLFavoriteLandmarkMenuItem*)*it;
+ insert_before = false;
+ }
+ target_id = target_item->getLandmarkID();
+ }
+ else
+ {
+ // Identify the button hovered and the side to drop
+ LLFavoriteLandmarkButton* hovered_button = dynamic_cast<LLFavoriteLandmarkButton*>(mLandingTab);
+ if (hovered_button)
+ {
+ insert_before = true;
+ }
+ else
+ {
+ // Choose the right landmark button
+ hovered_button = dynamic_cast<LLFavoriteLandmarkButton*>(mLastTab);
+ if (LL_UNLIKELY(!hovered_button))
+ return false;
+
+ insert_before = false;
+ }
+ target_id = hovered_button->getLandmarkID();
+ }
+
+ return true;
+}
+
//virtual
void LLFavoritesBarCtrl::changed(U32 mask)
{
@@ -737,7 +833,7 @@ void LLFavoritesBarCtrl::draw()
mImageDragIndication->draw(rect.mRight, rect.getHeight(), w, h);
}
// Once drawn, mark this false so we won't draw it again (unless we hit the favorite bar again)
- mShowDragMarker = FALSE;
+ mShowDragMarker = false;
}
if (mItemsChangedTimer.getStarted())
{
@@ -833,7 +929,7 @@ void LLFavoritesBarCtrl::updateButtons(bool force_update)
if (item)
{
// an child's order and mItems should be same
- if (button->getLandmarkId() != item->getUUID() // sort order has been changed
+ if (button->getLandmarkID() != item->getUUID() // sort order has been changed
|| button->getLabelSelected() != item->getName()) // favorite's name has been changed
{
break;
@@ -907,11 +1003,7 @@ void LLFavoritesBarCtrl::updateButtons(bool force_update)
{
// mMoreTextBox was removed, so LLFavoriteLandmarkButtons
// should be the only ones in the list
- LLFavoriteLandmarkButton* button = dynamic_cast<LLFavoriteLandmarkButton*> (childs->back());
- if (button)
- {
- mLastTab = button;
- }
+ mLastTab = dynamic_cast<LLFavoriteLandmarkButton*>(childs->back());
}
mFirstDropDownItem = j;
@@ -919,15 +1011,13 @@ void LLFavoritesBarCtrl::updateButtons(bool force_update)
if (mFirstDropDownItem < mItems.size())
{
// if updateButton had been called it means:
- //or there are some new favorites, or width had been changed
+ // or there are some new favorites, or width had been changed
// so if we need to display chevron button, we must update dropdown items too.
mUpdateDropDownItems = true;
S32 buttonHGap = button_params.rect.left; // default value
- LLRect rect;
// Chevron button should stay right aligned
- rect.setOriginAndSize(getRect().mRight - mMoreTextBox->getRect().getWidth() - buttonHGap, 0,
- mMoreTextBox->getRect().getWidth(),
- mMoreTextBox->getRect().getHeight());
+ LLRect rect(mMoreTextBox->getRect());
+ rect.translate(getRect().mRight - rect.mRight - buttonHGap, 0);
addChild(mMoreTextBox);
mMoreTextBox->setRect(rect);
@@ -1060,14 +1150,16 @@ void LLFavoritesBarCtrl::showDropDownMenu()
{
if (mUpdateDropDownItems)
{
- updateMenuItems(menu);
+ updateOverflowMenuItems();
+ }
+ else
+ {
+ menu->buildDrawLabels();
}
- menu->buildDrawLabels();
menu->updateParent(LLMenuGL::sMenuContainer);
menu->setButtonRect(mMoreTextBox->getRect(), this);
- positionAndShowMenu(menu);
- mDropDownItemsCount = menu->getItemCount();
+ positionAndShowOverflowMenu();
}
}
@@ -1081,12 +1173,14 @@ void LLFavoritesBarCtrl::createOverflowMenu()
menu_p.max_scrollable_items = 10;
menu_p.preferred_width = DROP_DOWN_MENU_WIDTH;
- LLToggleableMenu* menu = LLUICtrlFactory::create<LLFavoriteLandmarkToggleableMenu>(menu_p);
+ LLFavoriteLandmarkToggleableMenu* menu = LLUICtrlFactory::create<LLFavoriteLandmarkToggleableMenu>(menu_p);
+ menu->setToolbar(this);
mOverflowMenuHandle = menu->getHandle();
}
-void LLFavoritesBarCtrl::updateMenuItems(LLToggleableMenu* menu)
+void LLFavoritesBarCtrl::updateOverflowMenuItems()
{
+ LLToggleableMenu* menu = (LLToggleableMenu*)mOverflowMenuHandle.get();
menu->empty();
U32 widest_item = 0;
@@ -1115,6 +1209,8 @@ void LLFavoritesBarCtrl::updateMenuItems(LLToggleableMenu* menu)
menu->addChild(menu_item);
}
+ menu->buildDrawLabels();
+ mDropDownItemsCount = menu->getItemCount();
addOpenLandmarksMenuItem(menu);
mUpdateDropDownItems = false;
}
@@ -1171,8 +1267,9 @@ void LLFavoritesBarCtrl::addOpenLandmarksMenuItem(LLToggleableMenu* menu)
menu->addChild(menu_item);
}
-void LLFavoritesBarCtrl::positionAndShowMenu(LLToggleableMenu* menu)
+void LLFavoritesBarCtrl::positionAndShowOverflowMenu()
{
+ LLToggleableMenu* menu = (LLToggleableMenu*)mOverflowMenuHandle.get();
U32 max_width = llmin(DROP_DOWN_MENU_WIDTH, getRect().getWidth());
S32 menu_x = getRect().getWidth() - max_width;
@@ -1460,7 +1557,7 @@ void LLFavoritesBarCtrl::onButtonMouseDown(LLUUID id, LLUICtrl* ctrl, S32 x, S32
}
mDragItemId = id;
- mStartDrag = TRUE;
+ mStartDrag = true;
S32 screenX, screenY;
localPointToScreen(x, y, &screenX, &screenY);
@@ -1470,7 +1567,7 @@ void LLFavoritesBarCtrl::onButtonMouseDown(LLUUID id, LLUICtrl* ctrl, S32 x, S32
void LLFavoritesBarCtrl::onButtonMouseUp(LLUUID id, LLUICtrl* ctrl, S32 x, S32 y, MASK mask)
{
- mStartDrag = FALSE;
+ mStartDrag = false;
mDragItemId = LLUUID::null;
}
@@ -1478,7 +1575,7 @@ void LLFavoritesBarCtrl::onEndDrag()
{
mEndDragConnection.disconnect();
- showDragMarker(FALSE);
+ showDragMarker(false);
mDragItemId = LLUUID::null;
LLView::getWindow()->setCursor(UI_CURSOR_ARROW);
}
@@ -1496,7 +1593,7 @@ BOOL LLFavoritesBarCtrl::handleHover(S32 x, S32 y, MASK mask)
DAD_LANDMARK, mDragItemId,
LLToolDragAndDrop::SOURCE_LIBRARY);
- mStartDrag = FALSE;
+ mStartDrag = false;
return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask);
}
@@ -1525,6 +1622,7 @@ LLUICtrl* LLFavoritesBarCtrl::findChildByLocalCoords(S32 x, S32 y)
}
}
}
+
return ctrl;
}
@@ -2134,8 +2232,10 @@ bool LLFavoritesOrderStorage::isStorageUpdateNeeded()
void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id)
{
- if (mTargetLandmarkId.isNull()) return;
-
- LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId);
+ if (!mTargetLandmarkId.isNull())
+ {
+ LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId);
+ }
}
+
// EOF
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index 3b439b31fd..6b9f2cee69 100644
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -56,22 +56,21 @@ protected:
public:
virtual ~LLFavoritesBarCtrl();
- /*virtual*/ BOOL postBuild();
+ /*virtual*/ BOOL postBuild() override;
/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg);
+ EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg) override;
+ bool handleDragAndDropToMenu(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg);
- /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
- /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) override;
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override;
// LLInventoryObserver observer trigger
- virtual void changed(U32 mask);
- virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
- virtual void draw();
+ /*virtual*/ void changed(U32 mask) override;
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override;
+ /*virtual*/ void draw() override;
- void showDragMarker(BOOL show) { mShowDragMarker = show; }
+ void showDragMarker(bool show) { mShowDragMarker = show; }
void setLandingTab(LLUICtrl* tab) { mLandingTab = tab; }
protected:
@@ -108,7 +107,7 @@ protected:
S32 mDropDownItemsCount;
bool mUpdateDropDownItems;
bool mRestoreOverflowMenu;
-
+ bool mDragToOverflowMenu;
bool mGetPrevItems;
LLUUID mSelectedItemID;
@@ -118,19 +117,21 @@ protected:
private:
/*
* Helper function to make code more readable. It handles all drag and drop
- * operations of the existing favorites items on the favorites bar.
+ * operations of the existing favorites items to the favorites bar to on the overflow menu.
*/
void handleExistingFavoriteDragAndDrop(S32 x, S32 y);
/*
* Helper function to make code more readable. It handles all drag and drop
- * operations of the new landmark to the favorites bar.
+ * operations of the new landmark to the favorites bar or to the overflow menu.
*/
void handleNewFavoriteDragAndDrop(LLInventoryItem *item, const LLUUID& favorites_id, S32 x, S32 y);
// finds a control under the specified LOCAL point
LLUICtrl* findChildByLocalCoords(S32 x, S32 y);
+ bool findDragAndDropTarget(LLUUID &target_id, bool &insert_before, S32 x, S32 y);
+
// checks if the current order of the favorites items must be saved
BOOL needToSaveItemsOrder(const LLInventoryModel::item_array_t& items);
@@ -145,27 +146,25 @@ private:
void createOverflowMenu();
- void updateMenuItems(LLToggleableMenu* menu);
+ void updateOverflowMenuItems();
// Fits menu item label width with favorites menu width
void fitLabelWidth(LLMenuItemCallGL* menu_item);
void addOpenLandmarksMenuItem(LLToggleableMenu* menu);
- void positionAndShowMenu(LLToggleableMenu* menu);
+ void positionAndShowOverflowMenu();
- BOOL mShowDragMarker;
+ bool mShowDragMarker;
LLUICtrl* mLandingTab;
LLUICtrl* mLastTab;
LLTextBox* mMoreTextBox;
LLTextBox* mBarLabel;
LLUUID mDragItemId;
- BOOL mStartDrag;
+ bool mStartDrag;
LLInventoryModel::item_array_t mItems;
- BOOL mTabsHighlightEnabled;
-
S32 mMouseX;
S32 mMouseY;
diff --git a/indra/newview/llfloater360capture.cpp b/indra/newview/llfloater360capture.cpp
index 2c638fa959..a0890b7f9d 100644
--- a/indra/newview/llfloater360capture.cpp
+++ b/indra/newview/llfloater360capture.cpp
@@ -360,6 +360,8 @@ void LLFloater360Capture::encodeAndSave(LLPointer<LLImageRaw> raw_image, const s
int jpeg_encode_quality = gSavedSettings.getU32("360CaptureJPEGEncodeQuality");
LLPointer<LLImageJPEG> jpeg_image = new LLImageJPEG(jpeg_encode_quality);
+ LLImageDataSharedLock lock(raw_image);
+
// Actually encode the JPEG image. This is where a lot of time
// is spent now that the snapshot capture process has been
// optimized. The encode_time parameter doesn't appear to be
@@ -410,6 +412,8 @@ void LLFloater360Capture::suspendForAFrame()
// Probably not needed anymore but saving here just in case.
void LLFloater360Capture::mockSnapShot(LLImageRaw* raw)
{
+ LLImageDataLock lock(raw);
+
unsigned int width = raw->getWidth();
unsigned int height = raw->getHeight();
unsigned int depth = raw->getComponents();
diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp
index 9813156bf2..6996224dcb 100644
--- a/indra/newview/llfloaterauction.cpp
+++ b/indra/newview/llfloaterauction.cpp
@@ -190,6 +190,8 @@ void LLFloaterAuction::onClickSnapshot(void* data)
if (success)
{
+ LLImageDataLock lock(raw);
+
self->mTransactionID.generate();
self->mImageID = self->mTransactionID.makeAssetID(gAgent.getSecureSessionID());
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp
index ba91277c79..af96fdbcfd 100644
--- a/indra/newview/llfloatercolorpicker.cpp
+++ b/indra/newview/llfloatercolorpicker.cpp
@@ -135,6 +135,8 @@ void LLFloaterColorPicker::createUI ()
// create RGB type area (not really RGB but it's got R,G & B in it.,..
LLPointer<LLImageRaw> raw = new LLImageRaw ( mRGBViewerImageWidth, mRGBViewerImageHeight, mComponents );
+ LLImageDataLock lock(raw);
+
U8* bits = raw->getData();
S32 linesize = mRGBViewerImageWidth * mComponents;
for ( S32 y = 0; y < mRGBViewerImageHeight; ++y )
diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp
index ba0f97e2e1..5e7978e224 100644
--- a/indra/newview/llfloaterimagepreview.cpp
+++ b/indra/newview/llfloaterimagepreview.cpp
@@ -789,6 +789,7 @@ void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance)
if (imagep)
{
+ LLImageDataSharedLock lock(imagep);
mVolume->sculpt(imagep->getWidth(), imagep->getHeight(), imagep->getComponents(), imagep->getData(), 0, false);
}
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index aa723eb3a8..d15c52cc24 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -620,7 +620,7 @@ void LLFloaterPreference::apply()
saveAvatarProperties();
}
-void LLFloaterPreference::cancel()
+void LLFloaterPreference::cancel(const std::vector<std::string> settings_to_skip)
{
LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
// Call cancel() on all panels that derive from LLPanelPreference
@@ -630,7 +630,7 @@ void LLFloaterPreference::cancel()
LLView* view = *iter;
LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view);
if (panel)
- panel->cancel();
+ panel->cancel(settings_to_skip);
}
// hide joystick pref floater
LLFloaterReg::hideInstance("pref_joystick");
@@ -1011,15 +1011,16 @@ void LLFloaterPreference::onBtnCancel(const LLSD& userdata)
}
refresh();
}
- cancel();
-
+
if (userdata.asString() == "closeadvanced")
{
+ cancel({"RenderQualityPerformance"});
LLFloaterReg::hideInstance("prefs_graphics_advanced");
updateMaxComplexity();
}
else
{
+ cancel();
closeFloater();
}
}
@@ -2206,7 +2207,7 @@ void LLPanelPreference::toggleMuteWhenMinimized()
}
}
-void LLPanelPreference::cancel()
+void LLPanelPreference::cancel(const std::vector<std::string> settings_to_skip)
{
for (control_values_map_t::iterator iter = mSavedValues.begin();
iter != mSavedValues.end(); ++iter)
@@ -2219,6 +2220,12 @@ void LLPanelPreference::cancel()
continue;
}
+ auto found = std::find(settings_to_skip.begin(), settings_to_skip.end(), control->getName());
+ if (found != settings_to_skip.end())
+ {
+ continue;
+ }
+
control->set(ctrl_value);
}
@@ -2461,9 +2468,9 @@ void LLPanelPreferenceGraphics::resetDirtyChilds()
}
}
-void LLPanelPreferenceGraphics::cancel()
+void LLPanelPreferenceGraphics::cancel(const std::vector<std::string> settings_to_skip)
{
- LLPanelPreference::cancel();
+ LLPanelPreference::cancel(settings_to_skip);
}
void LLPanelPreferenceGraphics::saveSettings()
{
@@ -2751,7 +2758,7 @@ void LLPanelPreferenceControls::apply()
}
}
-void LLPanelPreferenceControls::cancel()
+void LLPanelPreferenceControls::cancel(const std::vector<std::string> settings_to_skip)
{
for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
{
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 04ac87364d..bdade3c1b9 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -79,7 +79,7 @@ public:
~LLFloaterPreference();
void apply();
- void cancel();
+ void cancel(const std::vector<std::string> settings_to_skip = {});
/*virtual*/ void draw();
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
@@ -251,7 +251,7 @@ public:
virtual ~LLPanelPreference();
virtual void apply();
- virtual void cancel();
+ virtual void cancel(const std::vector<std::string> settings_to_skip = {});
void setControlFalse(const LLSD& user_data);
virtual void setHardwareDefaults();
@@ -294,14 +294,12 @@ class LLPanelPreferenceGraphics : public LLPanelPreference
public:
BOOL postBuild();
void draw();
- void cancel();
+ void cancel(const std::vector<std::string> settings_to_skip = {});
void saveSettings();
void resetDirtyChilds();
void setHardwareDefaults();
void setPresetText();
- static const std::string getPresetsPath();
-
protected:
bool hasDirtyChilds();
@@ -320,7 +318,7 @@ public:
BOOL postBuild();
void apply();
- void cancel();
+ void cancel(const std::vector<std::string> settings_to_skip = {});
void saveSettings();
void resetDirtyChilds();
diff --git a/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp b/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp
index a91f0ec060..f83ce868a3 100644
--- a/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp
+++ b/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp
@@ -93,7 +93,7 @@ void LLFloaterPreferenceGraphicsAdvanced::onClickCloseBtn(bool app_quitting)
LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
if (instance)
{
- instance->cancel();
+ instance->cancel({"RenderQualityPerformance"});
}
updateMaxComplexity();
}
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 932a0316dd..b44fcf3e03 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -4360,12 +4360,10 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
if (!isInboxFolder() // don't allow creation in inbox
&& outfits_id != mUUID)
{
- bool menu_items_added = false;
// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
{
items.push_back(std::string("New Folder"));
- menu_items_added = true;
}
if (!isMarketplaceListingsFolder())
{
@@ -4383,10 +4381,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
disabled_items.push_back("New Settings");
}
}
- if (menu_items_added)
- {
- items.push_back(std::string("Create Separator"));
- }
}
getClipboardEntries(false, items, disabled_items, flags);
}
diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp
index 68581d04eb..7ded32cf19 100644
--- a/indra/newview/llinventorygallery.cpp
+++ b/indra/newview/llinventorygallery.cpp
@@ -2022,6 +2022,39 @@ void LLInventoryGallery::pasteAsLink(const LLUUID& dest,
}
}
+void LLInventoryGallery::doCreate(const LLUUID& dest, const LLSD& userdata)
+{
+
+ LLViewerInventoryCategory* cat = gInventory.getCategory(dest);
+ if (cat && mFolderID != dest)
+ {
+ menu_create_inventory_item(NULL, dest, userdata, LLUUID::null);
+ }
+ else
+ {
+ // todo: needs to reset current floater's filter,
+ // like reset_inventory_filter()
+
+ LLHandle<LLPanel> handle = getHandle();
+ std::function<void(const LLUUID&)> callback_cat_created =
+ [handle](const LLUUID& new_id)
+ {
+ gInventory.notifyObservers();
+ LLInventoryGallery* panel = static_cast<LLInventoryGallery*>(handle.get());
+ if (panel && new_id.notNull())
+ {
+ panel->clearSelection();
+ if (panel->mItemMap.count(new_id) != 0)
+ {
+ panel->addItemSelection(new_id, true);
+ }
+ }
+ };
+
+ menu_create_inventory_item(NULL, mFolderID, userdata, LLUUID::null, callback_cat_created);
+ }
+}
+
void LLInventoryGallery::claimEditHandler()
{
gEditMenuHandler = this;
diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h
index 0c52e7b713..bc4ac7db2a 100644
--- a/indra/newview/llinventorygallery.h
+++ b/indra/newview/llinventorygallery.h
@@ -166,6 +166,7 @@ public:
void deleteSelection();
bool canDeleteSelection();
void pasteAsLink();
+ void doCreate(const LLUUID& dest, const LLSD& userdata);
void setSortOrder(U32 order, bool update = false);
U32 getSortOrder() { return mSortOrder; };
diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp
index 5f4b816b99..e966514955 100644
--- a/indra/newview/llinventorygallerymenu.cpp
+++ b/indra/newview/llinventorygallerymenu.cpp
@@ -32,9 +32,11 @@
#include "llappearancemgr.h"
#include "llavataractions.h"
#include "llclipboard.h"
+#include "llenvironment.h"
#include "llfloaterreg.h"
#include "llfloatersidepanelcontainer.h"
#include "llfloaterworldmap.h"
+#include "llfriendcard.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
@@ -48,6 +50,41 @@
#include "llviewerwindow.h"
#include "llvoavatarself.h"
+
+void modify_outfit(BOOL append, const LLUUID& cat_id, LLInventoryModel* model)
+{
+ LLViewerInventoryCategory* cat = model->getCategory(cat_id);
+ if (!cat) return;
+
+ // checking amount of items to wear
+ static LLCachedControl<U32> max_items(gSavedSettings, "WearFolderLimit", 125);
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false);
+ model->collectDescendentsIf(cat_id,
+ cats,
+ items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ not_worn);
+
+ if (items.size() > max_items())
+ {
+ LLSD args;
+ args["AMOUNT"] = llformat("%u", max_items());
+ LLNotificationsUtil::add("TooManyWearables", args);
+ return;
+ }
+ if (model->isObjectDescendentOf(cat_id, gInventory.getRootFolderID()))
+ {
+ LLAppearanceMgr::instance().wearInventoryCategory(cat, FALSE, append);
+ }
+ else
+ {
+ // Library, we need to copy content first
+ LLAppearanceMgr::instance().wearInventoryCategory(cat, TRUE, append);
+ }
+}
+
LLContextMenu* LLInventoryGalleryContextMenu::createMenu()
{
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
@@ -57,11 +94,33 @@ LLContextMenu* LLInventoryGalleryContextMenu::createMenu()
registrar.add("Inventory.FileUploadLocation", boost::bind(&LLInventoryGalleryContextMenu::fileUploadLocation, this, _2));
registrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH));
registrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND));
+ registrar.add("Inventory.DoCreate", [this](LLUICtrl*, const LLSD& data)
+ {
+ if (mRootFolder)
+ {
+ mGallery->doCreate(mGallery->getRootFolder(), data);
+ }
+ else
+ {
+ mGallery->doCreate(mUUIDs.front(), data);
+ }
+ });
std::set<LLUUID> uuids(mUUIDs.begin(), mUUIDs.end());
registrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, uuids, gFloaterView->getParentFloater(mGallery)));
enable_registrar.add("Inventory.CanSetUploadLocation", boost::bind(&LLInventoryGalleryContextMenu::canSetUploadLocation, this, _2));
+ enable_registrar.add("Inventory.EnvironmentEnabled", [](LLUICtrl*, const LLSD&)
+ {
+ return LLEnvironment::instance().isInventoryEnabled();
+ });
+ enable_registrar.add("Inventory.MaterialsEnabled", [](LLUICtrl*, const LLSD&)
+ {
+ std::string agent_url = gAgent.getRegionCapability("UpdateMaterialAgentInventory");
+ std::string task_url = gAgent.getRegionCapability("UpdateMaterialTaskInventory");
+
+ return (!agent_url.empty() && !task_url.empty());
+ });
LLContextMenu* menu = createFromFile("menu_gallery_inventory.xml");
@@ -186,6 +245,22 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata)
{
ungroup_folder_items(mUUIDs.front());
}
+ else if ("replaceoutfit" == action)
+ {
+ modify_outfit(FALSE, mUUIDs.front(), &gInventory);
+ }
+ else if ("addtooutfit" == action)
+ {
+ modify_outfit(TRUE, mUUIDs.front(), &gInventory);
+ }
+ else if ("removefromoutfit" == action)
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(mUUIDs.front());
+ if (cat)
+ {
+ LLAppearanceMgr::instance().takeOffOutfit(cat->getLinkedUUID());
+ }
+ }
else if ("take_off" == action || "detach" == action)
{
for (LLUUID& selected_id : mUUIDs)
@@ -295,6 +370,54 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata)
preview_texture->saveAs();
}
}
+ else if (("copy_to_marketplace_listings" == action)
+ || ("move_to_marketplace_listings" == action))
+ {
+ LLViewerInventoryItem* itemp = gInventory.getItem(mUUIDs.front());
+ bool copy_operation = "copy_to_marketplace_listings" == action;
+ bool can_copy = itemp ? itemp->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()) : false;
+
+
+ if (can_copy)
+ {
+ const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ if (itemp)
+ {
+ move_item_to_marketplacelistings(itemp, marketplacelistings_id, copy_operation);
+ }
+ }
+ else
+ {
+ uuid_vec_t lamdba_list = mUUIDs;
+ LLNotificationsUtil::add(
+ "ConfirmCopyToMarketplace",
+ LLSD(),
+ LLSD(),
+ [lamdba_list](const LLSD& notification, const LLSD& response)
+ {
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ // option == 0 Move no copy item(s)
+ // option == 1 Don't move no copy item(s) (leave them behind)
+ bool copy_and_move = option == 0;
+ const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+
+ // main inventory only allows one item?
+ LLViewerInventoryItem* itemp = gInventory.getItem(lamdba_list.front());
+ if (itemp)
+ {
+ if (itemp->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
+ {
+ move_item_to_marketplacelistings(itemp, marketplacelistings_id, true);
+ }
+ else if (copy_and_move)
+ {
+ move_item_to_marketplacelistings(itemp, marketplacelistings_id, false);
+ }
+ }
+ }
+ );
+ }
+ }
}
void LLInventoryGalleryContextMenu::rename(const LLUUID& item_id)
@@ -388,6 +511,56 @@ bool is_inbox_folder(LLUUID item_id)
return gInventory.isObjectDescendentOf(item_id, inbox_id);
}
+bool can_list_on_marketplace(const LLUUID &id)
+{
+ const LLInventoryObject* obj = gInventory.getObject(id);
+ bool can_list = (obj != NULL);
+
+ if (can_list)
+ {
+ const LLUUID& object_id = obj->getLinkedUUID();
+ can_list = object_id.notNull();
+
+ if (can_list)
+ {
+ std::string error_msg;
+ const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ if (marketplacelistings_id.notNull())
+ {
+ LLViewerInventoryCategory* master_folder = gInventory.getCategory(marketplacelistings_id);
+ LLInventoryCategory* cat = gInventory.getCategory(id);
+ if (cat)
+ {
+ can_list = can_move_folder_to_marketplace(master_folder, master_folder, cat, error_msg);
+ }
+ else
+ {
+ LLInventoryItem* item = gInventory.getItem(id);
+ can_list = (item ? can_move_item_to_marketplace(master_folder, master_folder, item, error_msg) : false);
+ }
+ }
+ else
+ {
+ can_list = false;
+ }
+ }
+ }
+
+ return can_list;
+}
+
+bool check_folder_for_contents_of_type(const LLUUID &id, LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
+{
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ model->collectDescendentsIf(id,
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_type);
+ return item_array.size() > 0;
+}
+
void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* menu)
{
LLUUID selected_id = mUUIDs.front();
@@ -409,6 +582,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
bool is_in_trash = gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH));
bool is_lost_and_found = (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
bool is_outfits= (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS));
+ bool is_in_favorites = gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE));
//bool is_favorites= (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE));
bool is_system_folder = false;
@@ -456,6 +630,49 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
items.push_back(std::string("open_in_new_window"));
items.push_back(std::string("Open Folder Separator"));
}
+
+ // wearables related functionality for folders.
+ LLFindWearables is_wearable;
+ LLIsType is_object(LLAssetType::AT_OBJECT);
+ LLIsType is_gesture(LLAssetType::AT_GESTURE);
+
+ if (check_folder_for_contents_of_type(selected_id, &gInventory, is_wearable)
+ || check_folder_for_contents_of_type(selected_id, &gInventory, is_object)
+ || check_folder_for_contents_of_type(selected_id, &gInventory, is_gesture))
+ {
+ // Only enable add/replace outfit for non-system folders.
+ if (!is_system_folder)
+ {
+ // Adding an outfit onto another (versus replacing) doesn't make sense.
+ if (folder_type != LLFolderType::FT_OUTFIT)
+ {
+ items.push_back(std::string("Add To Outfit"));
+ if (!LLAppearanceMgr::instance().getCanAddToCOF(selected_id))
+ {
+ disabled_items.push_back(std::string("Add To Outfit"));
+ }
+ }
+
+ items.push_back(std::string("Replace Outfit"));
+ if (!LLAppearanceMgr::instance().getCanReplaceCOF(selected_id))
+ {
+ disabled_items.push_back(std::string("Replace Outfit"));
+ }
+ }
+ if (is_agent_inventory)
+ {
+ items.push_back(std::string("Folder Wearables Separator"));
+ // Note: If user tries to unwear "My Inventory", it's going to deactivate everything including gestures
+ // Might be safer to disable this for "My Inventory"
+ items.push_back(std::string("Remove From Outfit"));
+ if (folder_type != LLFolderType::FT_ROOT_INVENTORY // Unless COF is empty, whih shouldn't be, warrantied to have worn items
+ && !LLAppearanceMgr::getCanRemoveFromCOF(selected_id)) // expensive from root!
+ {
+ disabled_items.push_back(std::string("Remove From Outfit"));
+ }
+ }
+ items.push_back(std::string("Outfit Separator"));
+ }
}
else
{
@@ -503,11 +720,30 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
}
else
{
+ if (is_agent_inventory && !is_inbox && !is_cof && !is_in_favorites && !is_outfits)
+ {
+ LLViewerInventoryCategory* category = gInventory.getCategory(selected_id);
+ if (!category || !LLFriendCardsManager::instance().isCategoryInFriendFolder(category))
+ {
+ items.push_back(std::string("New Folder"));
+ }
+
+ items.push_back(std::string("create_new"));
+ items.push_back(std::string("New Script"));
+ items.push_back(std::string("New Note"));
+ items.push_back(std::string("New Gesture"));
+ items.push_back(std::string("New Material"));
+ items.push_back(std::string("New Clothes"));
+ items.push_back(std::string("New Body Parts"));
+ items.push_back(std::string("New Settings"));
+ }
+
if(can_share_item(selected_id))
{
items.push_back(std::string("Share"));
}
- if (LLClipboard::instance().hasContents() && is_agent_inventory && !is_cof && !is_inbox_folder(selected_id))
+
+ if (LLClipboard::instance().hasContents() && is_agent_inventory && !is_cof && !is_inbox)
{
items.push_back(std::string("Paste"));
@@ -519,7 +755,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
}
if (is_folder && is_agent_inventory)
{
- if (!is_cof && (folder_type != LLFolderType::FT_OUTFIT) && !is_outfits && !is_inbox_folder(selected_id))
+ if (!is_cof && (folder_type != LLFolderType::FT_OUTFIT) && !is_outfits && !is_inbox)
{
if (!gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD)) && !isRootFolder())
{
@@ -706,6 +942,54 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
disabled_items.push_back(std::string("New Folder"));
disabled_items.push_back(std::string("upload_def"));
+ disabled_items.push_back(std::string("create_new"));
+ }
+
+ if (is_agent_inventory && !mRootFolder)
+ {
+ items.push_back(std::string("New folder from selected"));
+ items.push_back(std::string("Subfolder Separator"));
+ if (!is_only_items_selected(mUUIDs) && !is_only_cats_selected(mUUIDs))
+ {
+ disabled_items.push_back(std::string("New folder from selected"));
+ }
+ }
+
+ // Marketplace
+ bool can_list = false;
+ const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS);
+ if (marketplacelistings_id.notNull() && !is_inbox && !obj->getIsLinkType())
+ {
+ if (is_folder)
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(selected_id);
+ if (cat
+ && !LLFolderType::lookupIsProtectedType(cat->getPreferredType())
+ && gInventory.isObjectDescendentOf(selected_id, gInventory.getRootFolderID()))
+ {
+ can_list = true;
+ }
+ }
+ else if (selected_item
+ && selected_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID())
+ && selected_item->getPermissions().getOwner() != ALEXANDRIA_LINDEN_ID
+ && LLAssetType::AT_CALLINGCARD != selected_item->getType())
+ {
+ can_list = true;
+ }
+ }
+
+ if (can_list)
+ {
+ items.push_back(std::string("Marketplace Separator"));
+ items.push_back(std::string("Marketplace Copy"));
+ items.push_back(std::string("Marketplace Move"));
+
+ if (!can_list_on_marketplace(selected_id))
+ {
+ disabled_items.push_back(std::string("Marketplace Copy"));
+ disabled_items.push_back(std::string("Marketplace Move"));
+ }
}
}
diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
index 292ddb765f..c066a7b5c3 100644
--- a/indra/newview/llmaterialeditor.cpp
+++ b/indra/newview/llmaterialeditor.cpp
@@ -2228,7 +2228,7 @@ bool LLMaterialEditor::canModifyObjectsMaterial()
LLSelectedTEGetMatData func(true);
LLPermissions permissions;
LLViewerInventoryItem* item_out;
- return can_use_objects_material(func, std::vector({PERM_MODIFY}), ItemSource::OBJECT, permissions, item_out);
+ return can_use_objects_material(func, std::vector<PermissionBit>({PERM_MODIFY}), ItemSource::OBJECT, permissions, item_out);
}
bool LLMaterialEditor::canSaveObjectsMaterial()
@@ -2236,7 +2236,7 @@ bool LLMaterialEditor::canSaveObjectsMaterial()
LLSelectedTEGetMatData func(true);
LLPermissions permissions;
LLViewerInventoryItem* item_out;
- return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), ItemSource::AGENT, permissions, item_out);
+ return can_use_objects_material(func, std::vector<PermissionBit>({PERM_COPY, PERM_MODIFY}), ItemSource::AGENT, permissions, item_out);
}
bool LLMaterialEditor::canClipboardObjectsMaterial()
@@ -2262,7 +2262,7 @@ bool LLMaterialEditor::canClipboardObjectsMaterial()
LLSelectedTEGetMatData func(true);
LLPermissions permissions;
LLViewerInventoryItem* item_out;
- return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY, PERM_TRANSFER}), ItemSource::OBJECT, permissions, item_out);
+ return can_use_objects_material(func, std::vector<PermissionBit>({PERM_COPY, PERM_MODIFY, PERM_TRANSFER}), ItemSource::OBJECT, permissions, item_out);
}
void LLMaterialEditor::saveObjectsMaterialAs()
@@ -2270,7 +2270,7 @@ void LLMaterialEditor::saveObjectsMaterialAs()
LLSelectedTEGetMatData func(true);
LLPermissions permissions;
LLViewerInventoryItem* item = nullptr;
- bool allowed = can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), ItemSource::AGENT, permissions, item);
+ bool allowed = can_use_objects_material(func, std::vector<PermissionBit>({PERM_COPY, PERM_MODIFY}), ItemSource::AGENT, permissions, item);
if (!allowed)
{
LL_WARNS("MaterialEditor") << "Failed to save GLTF material from object" << LL_ENDL;
@@ -3468,6 +3468,8 @@ void LLMaterialEditor::inventoryChanged(LLViewerObject* object,
void LLMaterialEditor::saveTexture(LLImageJ2C* img, const std::string& name, const LLUUID& asset_id, upload_callback_f cb)
{
+ LLImageDataSharedLock lock(img);
+
if (asset_id.isNull()
|| img == nullptr
|| img->getDataSize() == 0)
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 01d6469010..2622c23314 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -2360,17 +2360,19 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
std::stringstream texture_str;
if (texture != NULL && include_textures && mUploadTextures)
{
- if(texture->hasSavedRawImage())
- {
+ if (texture->hasSavedRawImage())
+ {
+ LLImageDataLock lock(texture->getSavedRawImage());
+
LLPointer<LLImageJ2C> upload_file =
LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
if (!upload_file.isNull() && upload_file->getDataSize())
{
- texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
+ texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
+ }
}
}
- }
if (texture != NULL &&
mUploadTextures &&
@@ -2514,17 +2516,19 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
std::stringstream texture_str;
if (texture != NULL && include_textures && mUploadTextures)
{
- if(texture->hasSavedRawImage())
- {
+ if (texture->hasSavedRawImage())
+ {
+ LLImageDataLock lock(texture->getSavedRawImage());
+
LLPointer<LLImageJ2C> upload_file =
LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
if (!upload_file.isNull() && upload_file->getDataSize())
{
- texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
+ texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
+ }
}
}
- }
if (texture != NULL &&
mUploadTextures &&
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index 0ba3c3d691..e7f9d0e5df 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -345,6 +345,7 @@ void LLNetMap::draw()
mObjectImageCenterGlobal = viewPosToGlobal(llfloor(new_center.mV[VX]), llfloor(new_center.mV[VY]));
// Create the base texture.
+ LLImageDataLock lock(mObjectRawImagep);
U8 *default_texture = mObjectRawImagep->getData();
memset( default_texture, 0, mObjectImagep->getWidth() * mObjectImagep->getHeight() * mObjectImagep->getComponents() );
@@ -915,6 +916,7 @@ void LLNetMap::renderPoint(const LLVector3 &pos_local, const LLColor4U &color,
return;
}
+ LLImageDataLock lock(mObjectRawImagep);
U8 *datap = mObjectRawImagep->getData();
S32 neg_radius = diameter / 2;
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index ff33efe4aa..e3d887d943 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -39,11 +39,6 @@ LLProfileDropTarget::LLProfileDropTarget(const LLProfileDropTarget::Params& p)
mAgentID(p.agent_id)
{}
-void LLProfileDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data)
-{
- LL_INFOS() << "LLProfileDropTarget::doDrop()" << LL_ENDL;
-}
-
BOOL LLProfileDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h
index f182660c8e..bfde921df0 100644
--- a/indra/newview/llpanelavatar.h
+++ b/indra/newview/llpanelavatar.h
@@ -59,8 +59,6 @@ public:
LLProfileDropTarget(const Params&);
~LLProfileDropTarget() {}
- void doDrop(EDragAndDropType cargo_type, void* cargo_data);
-
//
// LLView functionality
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp
index 82f880c9ee..54121c2656 100644
--- a/indra/newview/llpanelgroupnotices.cpp
+++ b/indra/newview/llpanelgroupnotices.cpp
@@ -89,8 +89,6 @@ public:
LLGroupDropTarget(const Params&);
~LLGroupDropTarget() {};
- void doDrop(EDragAndDropType cargo_type, void* cargo_data);
-
//
// LLView functionality
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
@@ -114,11 +112,6 @@ LLGroupDropTarget::LLGroupDropTarget(const LLGroupDropTarget::Params& p)
mGroupID(p.group_id)
{}
-void LLGroupDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data)
-{
- LL_INFOS() << "LLGroupDropTarget::doDrop()" << LL_ENDL;
-}
-
BOOL LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 20241aac24..a5a768776a 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -56,6 +56,7 @@
#include "lltrans.h"
#include "llviewermenu.h"
#include "llviewertexturelist.h"
+#include "llviewerinventory.h"
#include "llsidepanelinventory.h"
#include "llfolderview.h"
#include "llradiogroup.h"
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index ffbed778c1..00fa3853f7 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -46,6 +46,7 @@
#include "lltexteditor.h"
#include "lltexturectrl.h"
#include "lltoggleablemenu.h"
+#include "lltooldraganddrop.h"
#include "llgrouplist.h"
#include "llurlaction.h"
@@ -1012,6 +1013,51 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key)
mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2));
}
+
+BOOL LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg)
+{
+ // Try children first
+ if (LLPanelProfileTab::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg)
+ && *accept != ACCEPT_NO)
+ {
+ return TRUE;
+ }
+
+ // No point sharing with own profile
+ if (getSelfProfile())
+ {
+ return FALSE;
+ }
+
+ // Exclude fields that look like they are editable.
+ S32 child_x = 0;
+ S32 child_y = 0;
+ if (localPointToOtherView(x, y, &child_x, &child_y, mDescriptionEdit)
+ && mDescriptionEdit->pointInView(child_x, child_y))
+ {
+ return FALSE;
+ }
+
+ if (localPointToOtherView(x, y, &child_x, &child_y, mGroupList)
+ && mGroupList->pointInView(child_x, child_y))
+ {
+ return FALSE;
+ }
+
+ // Share
+ LLToolDragAndDrop::handleGiveDragAndDrop(getAvatarId(),
+ LLUUID::null,
+ drop,
+ cargo_type,
+ cargo_data,
+ accept);
+ return TRUE;
+}
+
void LLPanelProfileSecondLife::updateData()
{
LLUUID avatar_id = getAvatarId();
diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h
index 11632a10ae..45655cd67b 100644
--- a/indra/newview/llpanelprofile.h
+++ b/indra/newview/llpanelprofile.h
@@ -78,6 +78,12 @@ public:
void onOpen(const LLSD& key) override;
+ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg) override;
+
/**
* LLFriendObserver trigger
*/
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 2ff8f50277..863cd13678 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -768,6 +768,8 @@ void LLSnapshotLivePreview::prepareFreezeFrame()
// Get the decoded version of the formatted image
getEncodedImage();
+ LLImageDataSharedLock lock(mPreviewImageEncoded);
+
// We need to scale that a bit for display...
LLPointer<LLImageRaw> scaled = new LLImageRaw(
mPreviewImageEncoded->getData(),
@@ -827,13 +829,15 @@ LLPointer<LLImageRaw> LLSnapshotLivePreview::getEncodedImage()
{
if (!mPreviewImageEncoded)
{
+ LLImageDataSharedLock lock(mPreviewImage);
+
mPreviewImageEncoded = new LLImageRaw;
-
+
mPreviewImageEncoded->resize(
mPreviewImage->getWidth(),
mPreviewImage->getHeight(),
mPreviewImage->getComponents());
-
+
if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
// We don't store the intermediate formatted image in mFormattedImage in the J2C case
@@ -980,6 +984,8 @@ void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name)
{
+ LLImageDataSharedLock lock(mPreviewImage);
+
LL_DEBUGS("Snapshot") << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << LL_ENDL;
// gen a new uuid for this asset
LLTransactionID tid;
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 758e716c00..19408ec5de 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -729,7 +729,6 @@ class LLControlAVBridge : public LLVolumeBridge
using super = LLVolumeBridge;
public:
LLControlAVBridge(LLDrawable* drawablep, LLViewerRegion* regionp);
- virtual void updateSpatialExtents();
};
class LLHUDBridge : public LLVolumeBridge
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index a14d4f7a30..dfaeeaab62 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -96,7 +96,7 @@ private:
public:
LLTextureCacheWorker(LLTextureCache* cache, const LLUUID& id,
- U8* data, S32 datasize, S32 offset,
+ const U8* data, S32 datasize, S32 offset,
S32 imagesize, // for writes
LLTextureCache::Responder* responder)
: LLWorkerClass(cache, "LLTextureCacheWorker"),
@@ -145,7 +145,7 @@ protected:
LLUUID mID;
U8* mReadData;
- U8* mWriteData;
+ const U8* mWriteData;
S32 mDataSize;
S32 mOffset;
S32 mImageSize;
@@ -239,7 +239,7 @@ class LLTextureCacheRemoteWorker : public LLTextureCacheWorker
{
public:
LLTextureCacheRemoteWorker(LLTextureCache* cache, const LLUUID& id,
- U8* data, S32 datasize, S32 offset,
+ const U8* data, S32 datasize, S32 offset,
S32 imagesize, // for writes
LLPointer<LLImageRaw> raw, S32 discardlevel,
LLTextureCache::Responder* responder)
@@ -1961,7 +1961,7 @@ bool LLTextureCache::readComplete(handle_t handle, bool abort)
}
LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id,
- U8* data, S32 datasize, S32 imagesize,
+ const U8* data, S32 datasize, S32 imagesize,
LLPointer<LLImageRaw> rawimage, S32 discardlevel,
WriteResponder* responder)
{
@@ -2047,6 +2047,9 @@ LLPointer<LLImageRaw> LLTextureCache::readFromFastCache(const LLUUID& id, S32& d
bool LLTextureCache::writeToFastCache(LLUUID image_id, S32 id, LLPointer<LLImageRaw> raw, S32 discardlevel)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+
+ LLImageDataSharedLock lock(raw);
+
//rescale image if needed
if (raw.isNull() || raw->isBufferInvalid() || !raw->getData())
{
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index 43e91b3e4c..cba45393f9 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -125,7 +125,7 @@ public:
handle_t readFromCache(const LLUUID& id, S32 offset, S32 size,
ReadResponder* responder);
bool readComplete(handle_t handle, bool abort);
- handle_t writeToCache(const LLUUID& id, U8* data, S32 datasize, S32 imagesize, LLPointer<LLImageRaw> rawimage, S32 discardlevel,
+ handle_t writeToCache(const LLUUID& id, const U8* data, S32 datasize, S32 imagesize, LLPointer<LLImageRaw> rawimage, S32 discardlevel,
WriteResponder* responder);
LLPointer<LLImageRaw> readFromFastCache(const LLUUID& id, S32& discardlevel);
bool writeComplete(handle_t handle, bool abort = false);
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 38c9b3717d..4ecabf666b 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1699,7 +1699,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
mFormattedImage = new LLImageJ2C; // default
}
}
-
+
+ LLImageDataLock lock(mFormattedImage);
+
if (mHaveAllData) //the image file is fully loaded.
{
mFileSize = total_size;
@@ -1857,6 +1859,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
//return false;
return doWork(param);
}
+
+ LLImageDataSharedLock lock(mFormattedImage);
+
S32 datasize = mFormattedImage->getDataSize();
if(mFileSize < datasize)//This could happen when http fetching and sim fetching mixed.
{
diff --git a/indra/newview/lltinygltfhelper.cpp b/indra/newview/lltinygltfhelper.cpp
index 999be07dba..cee18489f0 100644
--- a/indra/newview/lltinygltfhelper.cpp
+++ b/indra/newview/lltinygltfhelper.cpp
@@ -31,7 +31,7 @@
#include "llviewertexture.h"
#include "llviewertexturelist.h"
-void strip_alpha_channel(LLPointer<LLImageRaw>& img)
+static void strip_alpha_channel(LLPointer<LLImageRaw>& img)
{
if (img->getComponents() == 4)
{
@@ -45,13 +45,13 @@ void strip_alpha_channel(LLPointer<LLImageRaw>& img)
// PRECONDITIONS:
// dst_img must be 3 component
// src_img and dst_image must have the same dimensions
-void copy_red_channel(LLPointer<LLImageRaw>& src_img, LLPointer<LLImageRaw>& dst_img)
+static void copy_red_channel(const LLPointer<LLImageRaw>& src_img, LLPointer<LLImageRaw>& dst_img)
{
llassert(src_img->getWidth() == dst_img->getWidth() && src_img->getHeight() == dst_img->getHeight());
llassert(dst_img->getComponents() == 3);
U32 pixel_count = dst_img->getWidth() * dst_img->getHeight();
- U8* src = src_img->getData();
+ const U8* src = src_img->getData();
U8* dst = dst_img->getData();
S8 src_components = src_img->getComponents();
@@ -95,6 +95,8 @@ void LLTinyGLTFHelper::initFetchedTextures(tinygltf::Material& material,
int mr_idx = material.pbrMetallicRoughness.metallicRoughnessTexture.index;
if (occlusion_idx != mr_idx)
{
+ LLImageDataLock lockIn(occlusion_img);
+ LLImageDataLock lockOut(mr_img);
//scale occlusion image to match resolution of mr image
occlusion_img->scale(mr_img->getWidth(), mr_img->getHeight());
@@ -104,6 +106,7 @@ void LLTinyGLTFHelper::initFetchedTextures(tinygltf::Material& material,
}
else if (occlusion_img)
{
+ LLImageDataSharedLock lock(occlusion_img);
//no mr but occlusion exists, make a white mr_img and copy occlusion red channel over
mr_img = new LLImageRaw(occlusion_img->getWidth(), occlusion_img->getHeight(), 3);
mr_img->clear(255, 255, 255);
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index e7f96239fd..055058e4eb 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -47,6 +47,7 @@
#include "llinventorybridge.h"
#include "llinventorydefines.h"
#include "llinventoryfunctions.h"
+#include "llinventorymodelbackgroundfetch.h"
#include "llpreviewnotecard.h"
#include "llrootview.h"
#include "llselectmgr.h"
@@ -320,6 +321,16 @@ void LLToolDragAndDrop::beginDrag(EDragAndDropType type,
LL_WARNS() << "Attempted to start drag without a cargo type" << LL_ENDL;
return;
}
+
+ if (type != DAD_CATEGORY)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(cargo_id);
+ if (item && !item->isFinished())
+ {
+ LLInventoryModelBackgroundFetch::instance().start(item->getUUID(), false);
+ }
+ }
+
mCargoTypes.clear();
mCargoTypes.push_back(type);
mCargoIDs.clear();
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index a2b0b04092..dcb14eb383 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -654,6 +654,8 @@ LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLPointer<LL
{
setItemId(itemId);
+ LLImageDataSharedLock lock(image);
+
EImageCodec codec = static_cast<EImageCodec>(image->getCodec());
switch (codec)
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 7738cb904e..61cc1dee25 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -450,6 +450,7 @@ static bool handleLogFileChanged(const LLSD& newvalue)
std::string log_filename = newvalue.asString();
LLFile::remove(log_filename);
LLError::logToFile(log_filename);
+ LL_INFOS() << "Logging switched to " << log_filename << LL_ENDL;
return true;
}
diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp
index e35cb26ce1..dfa47e82b3 100644
--- a/indra/newview/llviewerjoystick.cpp
+++ b/indra/newview/llviewerjoystick.cpp
@@ -1414,7 +1414,7 @@ void LLViewerJoystick::setSNDefaults()
#if LL_DARWIN || LL_LINUX
const float platformScale = 20.f;
const float platformScaleAvXZ = 1.f;
- // The SpaceNavigator doesn't act as a 3D cursor on OS X / Linux.
+ // The SpaceNavigator doesn't act as a 3D cursor on macOS / Linux.
const bool is_3d_cursor = false;
#else
const float platformScale = 1.f;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 9db9d97ddc..ae365de6fc 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -233,6 +233,7 @@ BOOL enable_take();
void handle_object_show_inspector();
void handle_avatar_show_inspector();
bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection_handle);
+bool confirm_take_separate(const LLSD &notification, const LLSD &response, LLObjectSelectionHandle selection_handle);
void handle_buy_object(LLSaleInfo sale_info);
void handle_buy_contents(LLSaleInfo sale_info);
@@ -4866,6 +4867,24 @@ static void derez_objects(EDeRezDestination dest, const LLUUID& dest_id)
derez_objects(dest, dest_id, first_region, error, NULL);
}
+static void derez_objects_separate(EDeRezDestination dest, const LLUUID &dest_id)
+{
+ std::vector<LLViewerObjectPtr> derez_object_list;
+ std::string error;
+ LLViewerRegion* first_region = NULL;
+ if (!get_derezzable_objects(dest, error, first_region, &derez_object_list, false))
+ {
+ LL_WARNS() << "No objects to derez" << LL_ENDL;
+ return;
+ }
+ for (LLViewerObject *opjectp : derez_object_list)
+ {
+ std::vector<LLViewerObjectPtr> buf_list;
+ buf_list.push_back(opjectp);
+ derez_objects(dest, dest_id, first_region, error, &buf_list);
+ }
+}
+
void handle_take_copy()
{
if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
@@ -4874,6 +4893,15 @@ void handle_take_copy()
derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id);
}
+void handle_take_separate_copy()
+{
+ if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
+ return;
+
+ const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
+ derez_objects_separate(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id);
+}
+
void handle_link_objects()
{
if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
@@ -4967,7 +4995,7 @@ void force_take_copy(void*)
derez_objects(DRD_FORCE_TO_GOD_INVENTORY, category_id);
}
-void handle_take()
+void handle_take(bool take_separate)
{
// we want to use the folder this was derezzed from if it's
// available. Otherwise, derez to the normal place.
@@ -5056,7 +5084,17 @@ void handle_take()
// MAINT-290
// Reason: Showing the confirmation dialog resets object selection, thus there is nothing to derez.
// Fix: pass selection to the confirm_take, so that selection doesn't "die" after confirmation dialog is opened
- params.functor.function(boost::bind(confirm_take, _1, _2, LLSelectMgr::instance().getSelection()));
+ params.functor.function([take_separate](const LLSD &notification, const LLSD &response)
+ {
+ if (take_separate)
+ {
+ confirm_take_separate(notification, response, LLSelectMgr::instance().getSelection());
+ }
+ else
+ {
+ confirm_take(notification, response, LLSelectMgr::instance().getSelection());
+ }
+ });
if(locked_but_takeable_object ||
!you_own_everything)
@@ -5119,6 +5157,16 @@ bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelect
return false;
}
+bool confirm_take_separate(const LLSD &notification, const LLSD &response, LLObjectSelectionHandle selection_handle)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (enable_take() && (option == 0))
+ {
+ derez_objects_separate(DRD_TAKE_INTO_AGENT_INVENTORY, notification["payload"]["folder_id"].asUUID());
+ }
+ return false;
+}
+
// You can take an item when it is public and transferrable, or when
// you own it. We err on the side of enabling the item when at least
// one item selected can be copied to inventory.
@@ -5201,6 +5249,21 @@ bool visible_take_object()
return !is_selection_buy_not_take() && enable_take();
}
+bool is_multiple_selection()
+{
+ return (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() > 1);
+}
+
+bool is_single_selection()
+{
+ return !is_multiple_selection();
+}
+
+bool enable_take_objects()
+{
+ return visible_take_object() && is_multiple_selection();
+}
+
bool tools_visible_buy_object()
{
return is_selection_buy_not_take();
@@ -7968,6 +8031,10 @@ bool enable_object_take_copy()
return all_valid;
}
+bool enable_take_copy_objects()
+{
+ return enable_object_take_copy() && is_multiple_selection();
+}
class LLHasAsset : public LLInventoryCollectFunctor
{
@@ -9438,6 +9505,7 @@ void initialize_menus()
enable.add("Tools.EnableUnlink", boost::bind(&LLSelectMgr::enableUnlinkObjects, LLSelectMgr::getInstance()));
view_listener_t::addMenu(new LLToolsEnableBuyOrTake(), "Tools.EnableBuyOrTake");
enable.add("Tools.EnableTakeCopy", boost::bind(&enable_object_take_copy));
+ enable.add("Tools.EnableCopySeparate", boost::bind(&enable_take_copy_objects));
enable.add("Tools.VisibleBuyObject", boost::bind(&tools_visible_buy_object));
enable.add("Tools.VisibleTakeObject", boost::bind(&tools_visible_take_object));
view_listener_t::addMenu(new LLToolsEnableSaveToObjectInventory(), "Tools.EnableSaveToObjectInventory");
@@ -9698,6 +9766,9 @@ void initialize_menus()
view_listener_t::addMenu(new LLObjectMute(), "Object.Mute");
enable.add("Object.VisibleTake", boost::bind(&visible_take_object));
+ enable.add("Object.VisibleTakeMultiple", boost::bind(&is_multiple_selection));
+ enable.add("Object.VisibleTakeSingle", boost::bind(&is_single_selection));
+ enable.add("Object.EnableTakeMultiple", boost::bind(&enable_take_objects));
enable.add("Object.VisibleBuy", boost::bind(&visible_buy_object));
commit.add("Object.Buy", boost::bind(&handle_buy));
@@ -9706,7 +9777,9 @@ void initialize_menus()
commit.add("Object.EditGLTFMaterial", boost::bind(&handle_object_edit_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.Take", boost::bind(&handle_take, false));
+ commit.add("Object.TakeSeparate", boost::bind(&handle_take, true));
+ commit.add("Object.TakeSeparateCopy", boost::bind(&handle_take_separate_copy));
commit.add("Object.ShowInspector", boost::bind(&handle_object_show_inspector));
enable.add("Object.EnableInspect", boost::bind(&enable_object_inspect));
enable.add("Object.EnableEditGLTFMaterial", boost::bind(&enable_object_edit_gltf_material));
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index 7142763451..b1ab7a2688 100644
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -103,7 +103,7 @@ bool enable_object_delete();
// Buy either contents or object itself
void handle_buy();
-void handle_take();
+void handle_take(bool take_separate = false);
void handle_take_copy();
void handle_look_at_selection(const LLSD& param);
void handle_zoom_to_object(LLUUID object_id);
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index d4346ee2d9..c4e5fcc7b6 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -1159,6 +1159,20 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
LL_DEBUGS("ObjectUpdate") << " mesgsys " << mesgsys << " dp " << dp << " id " << getID() << " update_type " << (S32) update_type << LL_ENDL;
dumpStack("ObjectUpdateStack");
+ // The new OBJECTDATA_FIELD_SIZE_124, OBJECTDATA_FIELD_SIZE_140, OBJECTDATA_FIELD_SIZE_80
+ // and OBJECTDATA_FIELD_SIZE_64 lengths should be supported in the existing cases below.
+ // Each case should start at the beginning of the buffer and extract all known
+ // values, and ignore any unknown data at the end of the buffer.
+ // This allows new data in the future without breaking current viewers.
+ const S32 OBJECTDATA_FIELD_SIZE_140 = 140; // Full precision avatar update for future extended data
+ const S32 OBJECTDATA_FIELD_SIZE_124 = 124; // Full precision object update for future extended data
+ const S32 OBJECTDATA_FIELD_SIZE_76 = 76; // Full precision avatar update
+ const S32 OBJECTDATA_FIELD_SIZE_60 = 60; // Full precision object update
+ const S32 OBJECTDATA_FIELD_SIZE_80 = 80; // Terse avatar update, 16 bit precision for future extended data
+ const S32 OBJECTDATA_FIELD_SIZE_64 = 64; // Terse object update, 16 bit precision for future extended data
+ const S32 OBJECTDATA_FIELD_SIZE_48 = 48; // Terse avatar update, 16 bit precision
+ const S32 OBJECTDATA_FIELD_SIZE_32 = 32; // Terse object update, 16 bit precision
+
U32 retval = 0x0;
// If region is removed from the list it is also deleted.
@@ -1206,7 +1220,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
U32 x, y;
from_region_handle(region_handle, &x, &y);
- LL_ERRS() << "Object has invalid region " << x << ":" << y << "!" << LL_ENDL;
+ LL_WARNS("UpdateFail") << "Object has invalid region " << x << ":" << y << "!" << LL_ENDL;
return retval;
}
@@ -1233,8 +1247,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
const F32 size = LLWorld::getInstance()->getRegionWidthInMeters();
const F32 MAX_HEIGHT = LLWorld::getInstance()->getRegionMaxHeight();
const F32 MIN_HEIGHT = LLWorld::getInstance()->getRegionMinHeight();
- S32 length;
- S32 count;
+ S32 length = 0;
+ S32 count = 0;
S32 this_update_precision = 32; // in bits
// Temporaries, because we need to compare w/ previous to set dirty flags...
@@ -1295,6 +1309,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_Scale, new_scale, block_num );
length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData);
mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num, MAX_OBJECT_BINARY_DATA_SIZE);
+ length = llmin(length, MAX_OBJECT_BINARY_DATA_SIZE); // getBinaryDataFast() safely fills the buffer to max_size
mTotalCRC = crc;
// Might need to update mSourceMuted here to properly pick up new radius
@@ -1314,20 +1329,22 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
}
setClickAction(click_action);
- count = 0;
- LLVector4 collision_plane;
-
+ count = 0;
+ LLVector4 collision_plane;
+
switch(length)
{
- case (60 + 16):
+ case OBJECTDATA_FIELD_SIZE_140:
+ case OBJECTDATA_FIELD_SIZE_76:
// pull out collision normal for avatar
htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
((LLVOAvatar*)this)->setFootPlane(collision_plane);
count += sizeof(LLVector4);
- // fall through
- case 60:
+
+ case OBJECTDATA_FIELD_SIZE_124:
+ case OBJECTDATA_FIELD_SIZE_60:
this_update_precision = 32;
- // this is a terse update
+ // this is a full precision update
// pos
htolememcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
@@ -1352,117 +1369,21 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
resetRot();
}
setAngularVelocity(new_angv);
+ count += sizeof(LLVector3);
#if LL_DARWIN
- if (length == 76)
+ if (length == OBJECTDATA_FIELD_SIZE_76 ||
+ length == OBJECTDATA_FIELD_SIZE_140)
{
setAngularVelocity(LLVector3::zero);
}
#endif
break;
- case(32 + 16):
- // pull out collision normal for avatar
- htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
- ((LLVOAvatar*)this)->setFootPlane(collision_plane);
- count += sizeof(LLVector4);
- // fall through
- case 32:
- this_update_precision = 16;
- test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
- // This is a terse 16 update, so treat data as an array of U16's.
-#ifdef LL_BIG_ENDIAN
- htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
- val = valswizzle;
-#else
- val = (U16 *) &data[count];
-#endif
- count += sizeof(U16)*3;
- new_pos_parent.mV[VX] = U16_to_F32(val[VX], -0.5f*size, 1.5f*size);
- new_pos_parent.mV[VY] = U16_to_F32(val[VY], -0.5f*size, 1.5f*size);
- new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT);
-
-#ifdef LL_BIG_ENDIAN
- htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
- val = valswizzle;
-#else
- val = (U16 *) &data[count];
-#endif
- count += sizeof(U16)*3;
- setVelocity(LLVector3(U16_to_F32(val[VX], -size, size),
- U16_to_F32(val[VY], -size, size),
- U16_to_F32(val[VZ], -size, size)));
-
-#ifdef LL_BIG_ENDIAN
- htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
- val = valswizzle;
-#else
- val = (U16 *) &data[count];
-#endif
- count += sizeof(U16)*3;
- setAcceleration(LLVector3(U16_to_F32(val[VX], -size, size),
- U16_to_F32(val[VY], -size, size),
- U16_to_F32(val[VZ], -size, size)));
-
-#ifdef LL_BIG_ENDIAN
- htolememcpy(valswizzle, &data[count], MVT_U16Quat, 4);
- val = valswizzle;
-#else
- val = (U16 *) &data[count];
-#endif
- count += sizeof(U16)*4;
- new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f);
- new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f);
- new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f);
- new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f);
-
-#ifdef LL_BIG_ENDIAN
- htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
- val = valswizzle;
-#else
- val = (U16 *) &data[count];
-#endif
- new_angv.setVec(U16_to_F32(val[VX], -size, size),
- U16_to_F32(val[VY], -size, size),
- U16_to_F32(val[VZ], -size, size));
- if (new_angv.isExactlyZero())
- {
- // reset rotation time
- resetRot();
- }
- setAngularVelocity(new_angv);
- break;
-
- case 16:
- this_update_precision = 8;
- test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
- // this is a terse 8 update
- new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size);
- new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size);
- new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT);
-
- setVelocity(U8_to_F32(data[3], -size, size),
- U8_to_F32(data[4], -size, size),
- U8_to_F32(data[5], -size, size) );
-
- setAcceleration(U8_to_F32(data[6], -size, size),
- U8_to_F32(data[7], -size, size),
- U8_to_F32(data[8], -size, size) );
-
- new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f);
- new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f);
- new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f);
- new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f);
-
- new_angv.setVec(U8_to_F32(data[13], -size, size),
- U8_to_F32(data[14], -size, size),
- U8_to_F32(data[15], -size, size) );
- if (new_angv.isExactlyZero())
- {
- // reset rotation time
- resetRot();
- }
- setAngularVelocity(new_angv);
- break;
+ // length values 48, 32 and 16 were once in viewer code but
+ // are never sent by the SL simulator
+ default:
+ LL_WARNS("UpdateFail") << "Unexpected ObjectData buffer size " << length
+ << " for " << getID() << " with OUT_FULL message" << LL_ENDL;
}
////////////////////////////////////////////////////
@@ -1496,20 +1417,45 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
if (mData)
{
delete [] mData;
- }
+ mData = NULL;
+ }
- // Check for appended generic data
- S32 data_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Data);
- if (data_size <= 0)
- {
- mData = NULL;
- }
- else
- {
- // ...has generic data
- mData = new U8[data_size];
- mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, mData, data_size, block_num);
- }
+ // Dec 2023 new generic data:
+ // Trees work as before, this field contains genome data
+ // Not a tree: root objects send 1 byte with the number of
+ // total prims in the linkset
+ // If the generic data size is zero, then number of prims is 1
+ //
+ // Viewers should not check for specific data sizes exactly, but if
+ // the field has data, process it from the start and ignore the remainder.
+
+ // Check for appended generic data
+ const S32 GENERIC_DATA_BUFFER_SIZE = 16;
+ S32 data_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Data);
+ if (data_size > 0)
+ { // has generic data
+ if (getPCode() == LL_PCODE_LEGACY_TREE || getPCode() == LL_PCODE_TREE_NEW)
+ {
+ mData = new U8[data_size];
+ mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, mData, data_size, block_num);
+ LL_DEBUGS("NewObjectData") << "Read " << data_size << " bytes tree genome data for " << getID() << ", pcode "
+ << getPCodeString() << ", value " << (S32) mData[0] << LL_ENDL;
+ }
+ else
+ { // Extract number of prims
+ U8 generic_data[GENERIC_DATA_BUFFER_SIZE];
+ mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data,
+ &generic_data[0], llmin(data_size, GENERIC_DATA_BUFFER_SIZE), block_num);
+ // This is sample code to extract the number of prims
+ // Future viewers should use it for their own purposes
+ if (!isAvatar())
+ {
+ S32 num_prims = (S32) generic_data[0];
+ LL_DEBUGS("NewObjectData") << "Root prim " << getID() << " has "
+ << num_prims << " prims in linkset" << LL_ENDL;
+ }
+ }
+ }
S32 text_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Text);
if (text_size > 1)
@@ -1605,60 +1551,23 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
#endif
length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData);
mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num, MAX_OBJECT_BINARY_DATA_SIZE);
- count = 0;
+ length = llmin(length, MAX_OBJECT_BINARY_DATA_SIZE); // getBinaryDataFast() safely fills the buffer to max_size
+ count = 0;
LLVector4 collision_plane;
-
+
switch(length)
{
- case(60 + 16):
- // pull out collision normal for avatar
- htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
- ((LLVOAvatar*)this)->setFootPlane(collision_plane);
- count += sizeof(LLVector4);
- // fall through
- case 60:
- // this is a terse 32 update
- // pos
- this_update_precision = 32;
- htolememcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
- count += sizeof(LLVector3);
- // vel
- htolememcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
- count += sizeof(LLVector3);
- // acc
- htolememcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
- count += sizeof(LLVector3);
- // theta
- {
- LLVector3 vec;
- htolememcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
- new_rot.unpackFromVector3(vec);
- }
- count += sizeof(LLVector3);
- // omega
- htolememcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
- if (new_angv.isExactlyZero())
- {
- // reset rotation time
- resetRot();
- }
- setAngularVelocity(new_angv);
-#if LL_DARWIN
- if (length == 76)
- {
- setAngularVelocity(LLVector3::zero);
- }
-#endif
- break;
- case(32 + 16):
+ case OBJECTDATA_FIELD_SIZE_80:
+ case OBJECTDATA_FIELD_SIZE_48:
// pull out collision normal for avatar
htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
((LLVOAvatar*)this)->setFootPlane(collision_plane);
count += sizeof(LLVector4);
- // fall through
- case 32:
- // this is a terse 16 update
- this_update_precision = 16;
+
+ case OBJECTDATA_FIELD_SIZE_64:
+ case OBJECTDATA_FIELD_SIZE_32:
+ // this is a terse 16 bit quantized update
+ this_update_precision = 16;
test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
#ifdef LL_BIG_ENDIAN
@@ -1718,33 +1627,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
setAngularVelocity(new_angv);
break;
- case 16:
- // this is a terse 8 update
- this_update_precision = 8;
- test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
- new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size);
- new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size);
- new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT);
-
- setVelocity(U8_to_F32(data[3], -size, size),
- U8_to_F32(data[4], -size, size),
- U8_to_F32(data[5], -size, size) );
-
- setAcceleration(U8_to_F32(data[6], -size, size),
- U8_to_F32(data[7], -size, size),
- U8_to_F32(data[8], -size, size) );
-
- new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f);
- new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f);
- new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f);
- new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f);
-
- new_angv.set(U8_to_F32(data[13], -size, size),
- U8_to_F32(data[14], -size, size),
- U8_to_F32(data[15], -size, size) );
- setAngularVelocity(new_angv);
- break;
- }
+ // Previous viewers had code for length 76, 60 or 16 byte length
+ // with full precision or 8 bit quanitzation, but the
+ // SL servers will never send those data formats. If you ever see this
+ // warning in Second Life, please file a bug report
+ default:
+ LL_WARNS("UpdateFail") << "Unexpected ObjectData buffer size " << length << " for " << getID()
+ << " with OUT_FULL message" << LL_ENDL;
+ }
U8 state;
mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num );
@@ -1753,13 +1643,13 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
}
default:
+ LL_WARNS("UpdateFail") << "Unknown uncompressed update type " << update_type << " for " << getID() << LL_ENDL;
break;
-
}
}
else
{
- // handle the compressed case
+ // handle the compressed case - have dp datapacker
LLUUID sound_uuid;
LLUUID owner_id;
F32 gain = 0;
@@ -2013,6 +1903,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
break;
default:
+ LL_WARNS("UpdateFail") << "Unknown compressed update type " << update_type << " for " << getID() << LL_ENDL;
break;
}
}
@@ -2060,7 +1951,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
if (sent_parentp && sent_parentp->getParent() == this)
{
// Try to recover if we attempt to attach a parent to its child
- LL_WARNS() << "Attempt to attach a parent to it's child: " << this->getID() << " to " << sent_parentp->getID() << LL_ENDL;
+ LL_WARNS("UpdateFail") << "Attempt to attach a parent to it's child: " << this->getID() << " to "
+ << sent_parentp->getID() << LL_ENDL;
this->removeChild(sent_parentp);
sent_parentp->setDrawableParent(NULL);
}
@@ -2084,7 +1976,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
{
if (mDrawable->isDead() || !mDrawable->getVObj())
{
- LL_WARNS() << "Drawable is dead or no VObj!" << LL_ENDL;
+ LL_WARNS("UpdateFail") << "Drawable is dead or no VObj!" << LL_ENDL;
sent_parentp->addChild(this);
}
else
@@ -2094,9 +1986,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
// Bad, we got a cycle somehow.
// Kill both the parent and the child, and
// set cache misses for both of them.
- LL_WARNS() << "Attempting to recover from parenting cycle!" << LL_ENDL;
- LL_WARNS() << "Killing " << sent_parentp->getID() << " and " << getID() << LL_ENDL;
- LL_WARNS() << "Adding to cache miss list" << LL_ENDL;
+ LL_WARNS("UpdateFail") << "Attempting to recover from parenting cycle! "
+ << "Killing " << sent_parentp->getID() << " and " << getID()
+ << ", Adding to cache miss list" << LL_ENDL;
setParent(NULL);
sent_parentp->setParent(NULL);
getRegion()->addCacheMissFull(getLocalID());
@@ -2751,22 +2643,6 @@ void LLViewerObject::interpolateLinearMotion(const F64SecondsImplicit& frame_tim
-BOOL LLViewerObject::setData(const U8 *datap, const U32 data_size)
-{
- delete [] mData;
-
- if (datap)
- {
- mData = new U8[data_size];
- if (!mData)
- {
- return FALSE;
- }
- memcpy(mData, datap, data_size); /* Flawfinder: ignore */
- }
- return TRUE;
-}
-
// delete an item in the inventory, but don't tell the server. This is
// used internally by remove, update, and savescript.
// This will only delete the first item with an item_id in the list
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 80da7b2f73..b85dcc5da2 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -779,8 +779,6 @@ protected:
static LLViewerObject *createObject(const LLUUID &id, LLPCode pcode, LLViewerRegion *regionp, S32 flags = 0);
- BOOL setData(const U8 *datap, const U32 data_size);
-
// Hide or show HUD, icon and particles
void hideExtraDisplayItems( BOOL hidden );
diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp
index 785c84c38d..e1f372d396 100755
--- a/indra/newview/llviewerparceloverlay.cpp
+++ b/indra/newview/llviewerparceloverlay.cpp
@@ -344,6 +344,8 @@ void LLViewerParcelOverlay::updateOverlayTexture()
const LLColor4U for_sale = LLUIColorTable::instance().getColor("PropertyColorForSale").get();
const LLColor4U auction = LLUIColorTable::instance().getColor("PropertyColorAuction").get();
+ LLImageDataLock lock(mImageRaw);
+
// Create the base texture.
U8 *raw = mImageRaw->getData();
const S32 COUNT = mParcelGridsPerEdge * mParcelGridsPerEdge;
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 56bba51692..c4a681f2b7 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -285,6 +285,7 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 wid
LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(const LLImageRaw* raw, FTType type, bool usemipmaps)
{
+ LLImageDataSharedLock lock(raw);
LLViewerFetchedTexture* ret = new LLViewerFetchedTexture(raw, type, usemipmaps);
gTextureList.addImage(ret, TEX_LIST_STANDARD);
return ret;
@@ -2902,6 +2903,8 @@ void LLViewerFetchedTexture::saveRawImage()
return;
}
+ LLImageDataSharedLock lock(mRawImage);
+
mSavedRawDiscardLevel = mRawDiscardLevel;
if (mBoostLevel == LLGLTexture::BOOST_ICON)
{
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 9a6d40ab0a..daf3a5a20f 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -1258,6 +1258,8 @@ bool LLViewerTextureList::createUploadFile(LLPointer<LLImageRaw> raw_image,
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+ LLImageDataSharedLock lock(raw_image);
+
// make a copy, since convertToUploadFile scales raw image
LLPointer<LLImageRaw> scale_image = new LLImageRaw(
raw_image->getData(),
@@ -1363,6 +1365,8 @@ BOOL LLViewerTextureList::createUploadFile(const std::string& filename,
LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImageRaw> raw_image, const S32 max_image_dimentions, bool force_square, bool force_lossless)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+ LLImageDataLock lock(raw_image);
+
if (force_square)
{
S32 biggest_side = llmax(raw_image->getWidth(), raw_image->getHeight());
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index ed671fe849..f661887c65 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -4891,6 +4891,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
{
return FALSE;
}
+
//check if there is enough memory for the snapshot image
if(image_width * image_height > (1 << 22)) //if snapshot image is larger than 2K by 2K
{
@@ -5010,6 +5011,9 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
image_buffer_x = llfloor(snapshot_width * scale_factor) ;
image_buffer_y = llfloor(snapshot_height * scale_factor) ;
}
+
+ LLImageDataLock lock(raw);
+
if ((image_buffer_x > 0) && (image_buffer_y > 0))
{
raw->resize(image_buffer_x, image_buffer_y, 3);
@@ -5269,6 +5273,8 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_
display(do_rebuild, zoom, subfield, for_snapshot);
}
+ LLImageDataSharedLock lock(raw);
+
glReadPixels(
0, 0,
image_width,
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index fee00eb6f4..c95648d62e 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -8894,7 +8894,7 @@ void LLVOAvatar::clearChat()
}
-void LLVOAvatar::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index)
+void LLVOAvatar::applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index)
{
if (index >= BAKED_NUM_INDICES)
{
@@ -9269,7 +9269,7 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe
//mesgsys->getU32Fast(_PREHASH_AppearanceData, _PREHASH_Flags, appearance_flags, 0);
}
- // Parse the AppearanceData field, if any.
+ // Parse the AppearanceHover field, if any.
contents.mHoverOffsetWasSet = false;
if (mesgsys->has(_PREHASH_AppearanceHover))
{
@@ -9279,7 +9279,24 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe
contents.mHoverOffset = hover;
contents.mHoverOffsetWasSet = true;
}
-
+
+ // Get attachment info, if sent
+ LLUUID attachment_id;
+ U8 attach_point;
+ S32 attach_count = mesgsys->getNumberOfBlocksFast(_PREHASH_AttachmentBlock);
+ LL_DEBUGS("AVAppearanceAttachments") << "Agent " << getID() << " has "
+ << attach_count << " attachments" << LL_ENDL;
+
+ for (S32 attach_i = 0; attach_i < attach_count; attach_i++)
+ {
+ mesgsys->getUUIDFast(_PREHASH_AttachmentBlock, _PREHASH_ID, attachment_id, attach_i);
+ mesgsys->getU8Fast(_PREHASH_AttachmentBlock, _PREHASH_AttachmentPoint, attach_point, attach_i);
+ LL_DEBUGS("AVAppearanceAttachments") << "AV " << getID() << " has attachment " << attach_i << " "
+ << (attachment_id.isNull() ? "pending" : attachment_id.asString())
+ << " on point " << (S32)attach_point << LL_ENDL;
+ // To do - store and use this information as needed
+ }
+
// Parse visual params, if any.
S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam);
static LLCachedControl<bool> block_some_avatars(gSavedSettings, "BlockSomeAvatarAppearanceVisualParams");
@@ -9770,6 +9787,8 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture
{
if(aux_src && aux_src->getComponents() == 1)
{
+ LLImageDataSharedLock lock(aux_src);
+
if (!aux_src->getData())
{
LL_ERRS() << "No auxiliary source (morph mask) data for image id " << id << LL_ENDL;
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 48bfd5293a..759d02959c 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -590,7 +590,7 @@ public:
// Morph masks
//--------------------------------------------------------------------
public:
- /*virtual*/ void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES);
+ /*virtual*/ void applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES);
BOOL morphMaskNeedsUpdate(LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES);
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 3725510b6a..c4cd1779b7 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -5314,7 +5314,7 @@ std::string LLVivoxVoiceClient::nameFromID(const LLUUID &uuid)
LLStringUtil::replaceChar(result, '+', '-');
LLStringUtil::replaceChar(result, '/', '_');
- // If you need to transform a GUID to this form on the Mac OS X command line, this will do so:
+ // If you need to transform a GUID to this form on the macOS command line, this will do so:
// echo -n x && (echo e669132a-6c43-4ee1-a78d-6c82fff59f32 |xxd -r -p |openssl base64|tr '/+' '_-')
// The reverse transform can be done with:
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 20621665fa..db197335f2 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -166,6 +166,7 @@ S32 LLSkyTex::getWhich(const BOOL curr)
void LLSkyTex::initEmpty(const S32 tex)
{
+ LLImageDataLock lock(mImageRaw[tex]);
U8* data = mImageRaw[tex]->getData();
for (S32 i = 0; i < SKYTEX_RESOLUTION; ++i)
{
@@ -187,7 +188,8 @@ void LLSkyTex::initEmpty(const S32 tex)
void LLSkyTex::create()
{
- U8* data = mImageRaw[sCurrent]->getData();
+ LLImageDataSharedLock lock(mImageRaw[sCurrent]);
+ const U8* data = mImageRaw[sCurrent]->getData();
for (S32 i = 0; i < SKYTEX_RESOLUTION; ++i)
{
for (S32 j = 0; j < SKYTEX_RESOLUTION; ++j)
diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h
index 5941ab6e3b..509ad97786 100644
--- a/indra/newview/llvosky.h
+++ b/indra/newview/llvosky.h
@@ -101,6 +101,7 @@ protected:
void setPixel(const LLColor4U &col, const S32 i, const S32 j)
{
+ LLImageDataSharedLock lock(mImageRaw[sCurrent]);
S32 offset = (i * SKYTEX_RESOLUTION + j) * SKYTEX_COMPONENTS;
U32* pix = (U32*) &(mImageRaw[sCurrent]->getData()[offset]);
*pix = col.asRGBA();
@@ -109,6 +110,7 @@ protected:
LLColor4U getPixel(const S32 i, const S32 j)
{
LLColor4U col;
+ LLImageDataSharedLock lock(mImageRaw[sCurrent]);
S32 offset = (i * SKYTEX_RESOLUTION + j) * SKYTEX_COMPONENTS;
U32* pix = (U32*) &(mImageRaw[sCurrent]->getData()[offset]);
col.fromRGBA( *pix );
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 36e6da802b..575b1dbe7e 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -865,6 +865,10 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
mReferenceBuffer->unmapBuffer();
llassert(vertex_count == max_vertices);
llassert(index_count == max_indices);
+#ifndef SHOW_ASSERT
+ (void)vertex_count;
+ (void)index_count;
+#endif
}
//generate tree mesh
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index ec2f490742..ad6c39de48 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1311,11 +1311,13 @@ void LLVOVolume::sculpt()
}
}
else
- {
+ {
+ LLImageDataSharedLock lock(raw_image);
+
sculpt_height = raw_image->getHeight();
sculpt_width = raw_image->getWidth();
sculpt_components = raw_image->getComponents();
-
+
sculpt_data = raw_image->getData();
if(LLViewerTextureManager::sTesterp)
@@ -5054,30 +5056,6 @@ LLControlAVBridge::LLControlAVBridge(LLDrawable* drawablep, LLViewerRegion* regi
mPartitionType = LLViewerRegion::PARTITION_CONTROL_AV;
}
-void LLControlAVBridge::updateSpatialExtents()
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE
-
- LLSpatialGroup* root = (LLSpatialGroup*)mOctree->getListener(0);
-
- bool rootWasDirty = root->isDirty();
-
- super::updateSpatialExtents(); // root becomes non-dirty here
-
- // SL-18251 "On-screen animesh characters using pelvis offset animations
- // disappear when root goes off-screen"
- //
- // Expand extents to include Control Avatar placed outside of the bounds
- LLControlAvatar* controlAvatar = getVObj() ? getVObj()->getControlAvatar() : NULL;
- if (controlAvatar
- && controlAvatar->mDrawable
- && controlAvatar->mDrawable->getEntry()
- && (rootWasDirty || controlAvatar->mPlaying))
- {
- root->expandExtents(controlAvatar->mDrawable->getSpatialExtents(), *mDrawable->getXform());
- }
-}
-
bool can_batch_texture(LLFace* facep)
{
if (facep->getTextureEntry()->getBumpmap())
diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp
index f2d7e4585a..ade9bbd847 100644
--- a/indra/newview/llwebprofile.cpp
+++ b/indra/newview/llwebprofile.cpp
@@ -239,10 +239,12 @@ LLCore::BufferArray::ptr_t LLWebProfile::buildPostData(const LLSD &data, LLPoint
<< "Content-Disposition: form-data; name=\"file\"; filename=\"snapshot.png\"\r\n"
<< "Content-Type: image/png\r\n\r\n";
+ LLImageDataSharedLock lock(image);
+
// Insert the image data.
//char *datap = (char *)(image->getData());
//bas.write(datap, image->getDataSize());
- U8* image_data = image->getData();
+ const U8* image_data = image->getData();
for (S32 i = 0; i < image->getDataSize(); ++i)
{
bas << image_data[i];
diff --git a/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml b/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml
index d82c453e5f..feaba45cf8 100644
--- a/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml
@@ -426,6 +426,234 @@
<menu_item_separator
layout="topleft"
name="Subfolder Separator" />
+ <menu
+ label="Create new"
+ layout="topleft"
+ name="create_new">
+ <menu_item_call
+ label="New Folder"
+ layout="topleft"
+ name="New Folder">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="category" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Script"
+ layout="topleft"
+ name="New Script">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="lsl" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Notecard"
+ layout="topleft"
+ name="New Note">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="notecard" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gesture"
+ layout="topleft"
+ name="New Gesture">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="gesture" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Material"
+ layout="topleft"
+ name="New Material">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="material" />
+ <menu_item_call.on_enable
+ function="Inventory.MaterialsEnabled" />
+ </menu_item_call>
+ <menu
+ label="New Clothes"
+ layout="topleft"
+ name="New Clothes">
+ <menu_item_call
+ label="New Shirt"
+ layout="topleft"
+ name="New Shirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Pants"
+ layout="topleft"
+ name="New Pants">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="pants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Shoes"
+ layout="topleft"
+ name="New Shoes">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shoes" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Socks"
+ layout="topleft"
+ name="New Socks">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="socks" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Jacket"
+ layout="topleft"
+ name="New Jacket">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="jacket" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skirt"
+ layout="topleft"
+ name="New Skirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="skirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gloves"
+ layout="topleft"
+ name="New Gloves">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="gloves" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Undershirt"
+ layout="topleft"
+ name="New Undershirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="undershirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Underpants"
+ layout="topleft"
+ name="New Underpants">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="underpants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Alpha Mask"
+ layout="topleft"
+ name="New Alpha Mask">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="alpha" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Tattoo"
+ layout="topleft"
+ name="New Tattoo">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="tattoo" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Universal"
+ layout="topleft"
+ name="New Universal">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="universal" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Physics"
+ layout="topleft"
+ name="New Physics">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="physics" />
+ </menu_item_call>
+ </menu>
+ <menu
+ label="New Body Parts"
+ layout="topleft"
+ name="New Body Parts">
+ <menu_item_call
+ label="New Shape"
+ layout="topleft"
+ name="New Shape">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shape" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skin"
+ layout="topleft"
+ name="New Skin">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="skin" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Hair"
+ layout="topleft"
+ name="New Hair">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="hair" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Eyes"
+ layout="topleft"
+ name="New Eyes">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="eyes" />
+ </menu_item_call>
+ </menu>
+ <menu
+ label="New Settings"
+ layout="topleft"
+ name="New Settings">
+ <menu_item_call
+ label="New Sky"
+ layout="topleft"
+ name="New Sky">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="sky"/>
+ <menu_item_call.on_enable
+ function="Inventory.EnvironmentEnabled" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Water"
+ layout="topleft"
+ name="New Water">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="water"/>
+ <menu_item_call.on_enable
+ function="Inventory.EnvironmentEnabled" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Day Cycle"
+ layout="topleft"
+ name="New Day Cycle">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="daycycle"/>
+ <menu_item_call.on_enable
+ function="Inventory.EnvironmentEnabled" />
+ </menu_item_call>
+ </menu>
+ </menu>
<menu_item_call
label="Create folder from selected"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/menu_object.xml b/indra/newview/skins/default/xui/en/menu_object.xml
index 5507c9f3a1..d652b721a4 100644
--- a/indra/newview/skins/default/xui/en/menu_object.xml
+++ b/indra/newview/skins/default/xui/en/menu_object.xml
@@ -173,6 +173,8 @@
function="Object.Take"/>
<menu_item_call.on_enable
function="Object.VisibleTake"/>
+ <menu_item_call.on_visible
+ function="Object.VisibleTakeSingle"/>
</menu_item_call>
<menu_item_call
enabled="false"
@@ -182,6 +184,52 @@
function="Tools.TakeCopy" />
<menu_item_call.on_enable
function="Tools.EnableTakeCopy" />
+ <menu_item_call.on_visible
+ function="Object.VisibleTakeSingle"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Take as combined item"
+ layout="topleft"
+ name="Take combined">
+ <menu_item_call.on_click
+ function="Object.Take"/>
+ <menu_item_call.on_enable
+ function="Object.VisibleTake"/>
+ <menu_item_call.on_visible
+ function="Object.VisibleTakeMultiple"/>
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Take copy as combined item"
+ name="Take Copy combined">
+ <menu_item_call.on_click
+ function="Tools.TakeCopy" />
+ <menu_item_call.on_enable
+ function="Tools.EnableTakeCopy" />
+ <menu_item_call.on_visible
+ function="Object.VisibleTakeMultiple"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Take as separate items"
+ layout="topleft"
+ name="Take Separate">
+ <menu_item_call.on_click
+ function="Object.TakeSeparate"/>
+ <menu_item_call.on_enable
+ function="Object.EnableTakeMultiple"/>
+ <menu_item_call.on_visible
+ function="Object.VisibleTakeMultiple"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Take copies as separate items"
+ layout="topleft"
+ name="Take Copy Separate">
+ <menu_item_call.on_click
+ function="Object.TakeSeparateCopy"/>
+ <menu_item_call.on_enable
+ function="Tools.EnableCopySeparate"/>
+ <menu_item_call.on_visible
+ function="Object.VisibleTakeMultiple"/>
</menu_item_call>
<menu_item_call
enabled="false"