diff options
Diffstat (limited to 'indra/newview')
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 ¬ification, 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 ¬ification, 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 ¬ification, 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" |