diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 2e3a62c647..22b93d4cda 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -714,6 +714,40 @@ void AISAPI::FetchCOF(completion_t callback) EnqueueAISCommand("FetchCOF", proc); } +void AISAPI::FetchCategoryLinks(const LLUUID &catId, completion_t callback) +{ + std::string cap = getInvCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + if (callback) + { + callback(LLUUID::null); + } + return; + } + std::string url = cap + std::string("/category/") + catId.asString() + "/links"; + + invokationFn_t getFn = boost::bind( + // Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload. + static_cast + //---- + // _1 -> httpAdapter + // _2 -> httpRequest + // _3 -> url + // _4 -> body + // _5 -> httpOptions + // _6 -> httpHeaders + (&LLCoreHttpUtil::HttpCoroutineAdapter::getAndSuspend), + _1, _2, _3, _5, _6); + + LLCoprocedureManager::CoProcedure_t proc( + boost::bind(&AISAPI::InvokeAISCommandCoro, _1, getFn, url, LLUUID::null, LLSD(), callback, FETCHCATEGORYLINKS)); + + EnqueueAISCommand("FetchCategoryLinks", proc); +} + /*static*/ void AISAPI::FetchOrphans(completion_t callback) { @@ -942,6 +976,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht case FETCHCATEGORYCATEGORIES: case FETCHCATEGORYCHILDREN: case FETCHCATEGORYSUBSET: + case FETCHCATEGORYLINKS: case FETCHCOF: if (result.has("category_id")) { @@ -995,6 +1030,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht //case FETCHCATEGORYCATEGORIES: //case FETCHCATEGORYCHILDREN: //case FETCHCATEGORYSUBSET: + //case FETCHCATEGORYLINKS: //case FETCHCOF: // if (result.has("category_id")) // { @@ -1059,6 +1095,7 @@ AISUpdate::AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD& || (type == AISAPI::FETCHCATEGORYCATEGORIES) || (type == AISAPI::FETCHCATEGORYSUBSET) || (type == AISAPI::FETCHCOF) + || (type == AISAPI::FETCHCATEGORYLINKS) || (type == AISAPI::FETCHORPHANS); // parse update llsd into stuff to do or parse received items. mFetchDepth = MAX_FOLDER_DEPTH_REQUEST; diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index b3c09ed8fa..99d3bb8d8e 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -62,6 +62,7 @@ public: static void FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0); static void FetchCategorySubset(const LLUUID& catId, const uuid_vec_t specificChildren, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0); static void FetchCOF(completion_t callback = completion_t()); + static void FetchCategoryLinks(const LLUUID &catId, completion_t callback = completion_t()); static void FetchOrphans(completion_t callback = completion_t() ); static void CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback = completion_t()); @@ -81,6 +82,7 @@ public: FETCHCATEGORYSUBSET, FETCHCOF, FETCHORPHANS, + FETCHCATEGORYLINKS } COMMAND_TYPE; private: diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index b0644d9e69..bc689ab050 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -5182,6 +5182,35 @@ void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb) } } +void callAfterCategoryLinksFetch(const LLUUID &cat_id, nullary_func_t cb) +{ + LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); + if (AISAPI::isAvailable()) + { + // Mark folder (update timer) so that background fetch won't request it + cat->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE); + // Assume that we have no relevant cache. Fetch folder, and items folder's links point to. + AISAPI::FetchCategoryLinks(cat_id, + [cb, cat_id](const LLUUID &id) + { + cb(); + LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); + if (cat) + { + cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); + } + }); + } + else + { + LL_WARNS() << "AIS API v3 not available, can't use AISAPI::FetchCOF" << LL_ENDL; + // startup should have marked folder as fetching, remove that + cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); + callAfterCategoryFetch(cat_id, cb); + } + +} + void add_wearable_type_counts(const uuid_vec_t& ids, S32& clothing_count, S32& bodypart_count, diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index faf6b68a91..7ebcea5599 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -369,6 +369,7 @@ LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& // Invoke a given callable after category contents are fully fetched. void callAfterCOFFetch(nullary_func_t cb); void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb); +void callAfterCategoryLinksFetch(const LLUUID &cat_id, nullary_func_t cb); // Wear all items in a uuid vector. void wear_multiple(const uuid_vec_t& ids, bool replace); diff --git a/indra/newview/llfloaterchangeitemthumbnail.cpp b/indra/newview/llfloaterchangeitemthumbnail.cpp index f18629762c..66a12113bb 100644 --- a/indra/newview/llfloaterchangeitemthumbnail.cpp +++ b/indra/newview/llfloaterchangeitemthumbnail.cpp @@ -699,11 +699,11 @@ void LLFloaterChangeItemThumbnail::showTexturePicker(const LLUUID &thumbnail_id) { //texture_floaterp->setTextureSelectedCallback(); //texture_floaterp->setOnUpdateImageStatsCallback(); - texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLUUID id) + texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource, const LLUUID&, const LLUUID&) { if (op == LLTextureCtrl::TEXTURE_SELECT) { - onTexturePickerCommit(id); + onTexturePickerCommit(); } } ); @@ -723,7 +723,7 @@ void LLFloaterChangeItemThumbnail::showTexturePicker(const LLUUID &thumbnail_id) floaterp->setFocus(TRUE); } -void LLFloaterChangeItemThumbnail::onTexturePickerCommit(LLUUID id) +void LLFloaterChangeItemThumbnail::onTexturePickerCommit() { LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mPickerHandle.get(); diff --git a/indra/newview/llfloaterchangeitemthumbnail.h b/indra/newview/llfloaterchangeitemthumbnail.h index de2a20bf2a..02f934337b 100644 --- a/indra/newview/llfloaterchangeitemthumbnail.h +++ b/indra/newview/llfloaterchangeitemthumbnail.h @@ -92,7 +92,7 @@ private: void* userdata); void showTexturePicker(const LLUUID &thumbnail_id); - void onTexturePickerCommit(LLUUID id); + void onTexturePickerCommit(); void setThumbnailId(const LLUUID &new_thumbnail_id); static void setThumbnailId(const LLUUID& new_thumbnail_id, const LLUUID& object_id); diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 025ee61f3b..d88f325a38 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -107,6 +107,7 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) mIsInitialized(false), mRootDirty(false), mNeedsArrange(false), + mNeedsSelection(false), mSearchType(LLInventoryFilter::SEARCHTYPE_NAME), mSortOrder(LLInventoryFilter::SO_DATE) { @@ -221,6 +222,7 @@ void LLInventoryGallery::setRootFolder(const LLUUID cat_id) mItemToSelect.setNull(); mItemBuildQuery.clear(); mNeedsArrange = false; + mNeedsSelection = false; dirtyRootFolder(); } @@ -829,14 +831,15 @@ void LLInventoryGallery::onIdle(void* userdata) self->updateMessageVisibility(); } - if (self->mItemToSelect.notNull()) + if (self->mNeedsSelection) { LLUUID item_to_select = self->mItemToSelect; self->mItemToSelect = LLUUID::null; + self->mNeedsSelection = false; self->changeItemSelection(item_to_select, true); } - if (self->mItemToSelect.isNull() && self->mItemBuildQuery.empty()) + if (!self->mNeedsSelection && self->mItemBuildQuery.empty()) { gIdleCallbacks.deleteFunction(onIdle, (void*)self); } @@ -908,7 +911,6 @@ bool LLInventoryGallery::updateAddedItem(LLUUID item_id) LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getCreationDate(), obj->getIsLinkType(), is_worn); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); - item->setRightMouseDownCallback(boost::bind(&LLInventoryGallery::showContextMenu, this, _1, _2, _3, item_id)); item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::changeItemSelection, this, item_id, false)); if (mGalleryCreated) { @@ -1000,15 +1002,21 @@ void LLInventoryGallery::updateItemThumbnail(LLUUID item_id) BOOL LLInventoryGallery::handleRightMouseDown(S32 x, S32 y, MASK mask) { - if(mItemMap[mSelectedItemID]) + if (mSelectedItemIDs.size() > 0) { - mItemMap[mSelectedItemID]->setFocus(false); - setFocus(true); + selection_deque::iterator iter = mSelectedItemIDs.begin(); + if (mItemMap[*iter]) + { + mItemMap[*iter]->setFocus(false); + setFocus(true); + } } clearSelection(); + + // Scroll is going to always return true BOOL res = LLPanel::handleRightMouseDown(x, y, mask); - if (mSelectedItemID.isNull()) + if (mSelectedItemIDs.empty()) { if (mInventoryGalleryMenu && mFolderID.notNull()) { @@ -1029,20 +1037,21 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) { case KEY_RETURN: // Open selected items if enter key hit on the inventory panel - if (mask == MASK_NONE && mInventoryGalleryMenu && mSelectedItemID.notNull()) + if (mask == MASK_NONE && mInventoryGalleryMenu && mSelectedItemIDs.size() == 1) { - LLViewerInventoryCategory* category = gInventory.getCategory(mSelectedItemID); + selection_deque::iterator iter = mSelectedItemIDs.begin(); + LLViewerInventoryCategory* category = gInventory.getCategory(*iter); if (category) { - setRootFolder(mSelectedItemID); + setRootFolder(*iter); handled = TRUE; } else { - LLViewerInventoryItem* item = gInventory.getItem(mSelectedItemID); + LLViewerInventoryItem* item = gInventory.getItem(*iter); if (item) { - LLInvFVBridgeAction::doAction(item->getType(), mSelectedItemID, &gInventory); + LLInvFVBridgeAction::doAction(item->getType(), *iter, &gInventory); } } } @@ -1063,9 +1072,10 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) case KEY_F2: mFilterSubString.clear(); - if (mInventoryGalleryMenu && mSelectedItemID.notNull()) + if (mInventoryGalleryMenu && mSelectedItemIDs.size() == 1) { - mInventoryGalleryMenu->doToSelected("rename", mSelectedItemID); + selection_deque::iterator iter = mSelectedItemIDs.begin(); + mInventoryGalleryMenu->doToSelected("rename", *iter); } handled = TRUE; break; @@ -1142,9 +1152,9 @@ void LLInventoryGallery::moveUp() { mFilterSubString.clear(); - if (mInventoryGalleryMenu && mSelectedItemID.notNull() && mItemsAddedCount > 1) + if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = getSelectedItem(); + LLInventoryGalleryItem* item = getFirstSelectedItem(); if (item) { S32 n = mItemIndexMap[item]; @@ -1165,9 +1175,9 @@ void LLInventoryGallery::moveDown() { mFilterSubString.clear(); - if (mInventoryGalleryMenu && mSelectedItemID.notNull() && mItemsAddedCount > 1) + if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = getSelectedItem(); + LLInventoryGalleryItem* item = getFirstSelectedItem(); if (item) { S32 n = mItemIndexMap[item]; @@ -1188,9 +1198,9 @@ void LLInventoryGallery::moveLeft() { mFilterSubString.clear(); - if (mInventoryGalleryMenu && mSelectedItemID.notNull() && mItemsAddedCount > 1) + if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = getSelectedItem(); + LLInventoryGalleryItem* item = getFirstSelectedItem(); if (item) { // Might be better to get item from panel @@ -1213,9 +1223,9 @@ void LLInventoryGallery::moveRight() { mFilterSubString.clear(); - if (mInventoryGalleryMenu && mSelectedItemID.notNull() && mItemsAddedCount > 1) + if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = getSelectedItem(); + LLInventoryGalleryItem* item = getFirstSelectedItem(); if (item) { S32 n = mItemIndexMap[item]; @@ -1243,9 +1253,12 @@ void LLInventoryGallery::onFocusLost() LLPanel::onFocusLost(); - if (mSelectedItemID.notNull() && mItemMap[mSelectedItemID]) + for (const LLUUID& id : mSelectedItemIDs) { - mItemMap[mSelectedItemID]->setSelected(false); + if (mItemMap[id]) + { + mItemMap[id]->setSelected(false); + } } } @@ -1255,13 +1268,19 @@ void LLInventoryGallery::onFocusReceived() gEditMenuHandler = this; // Tab support, when tabbing into this view, select first item - if (mSelectedItemID.notNull() && mItemMap[mSelectedItemID]) + if (mSelectedItemIDs.size() > 0) { - LLInventoryGalleryItem* focus_item = mItemMap[mSelectedItemID]; - focus_item->setSelected(true); - focus_item->setFocus(TRUE); + for (const LLUUID& id : mSelectedItemIDs) + { + if (mItemMap[id]) + { + LLInventoryGalleryItem* focus_item = mItemMap[id]; + focus_item->setSelected(true); + focus_item->setFocus(TRUE); + } + } } - else if (mIndexToItemMap.size() > 0 && mItemToSelect.isNull()) + else if (mIndexToItemMap.size() > 0 && !mNeedsSelection) { // choose any items from visible rect S32 vert_offset = mScrollPanel->getDocPosVertical(); @@ -1280,6 +1299,11 @@ void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLU { if (mInventoryGalleryMenu && item_id.notNull()) { + if (std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), item_id) == mSelectedItemIDs.end()) + { + mSelectedItemIDs.clear(); + changeItemSelection(item_id, false); + } uuid_vec_t selected_uuids; selected_uuids.push_back(item_id); mInventoryGalleryMenu->show(ctrl, selected_uuids, x, y); @@ -1291,32 +1315,35 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_ if ((mItemMap.count(item_id) == 0) || mNeedsArrange) { mItemToSelect = item_id; + mNeedsSelection = true; return; } - if (mSelectedItemID == item_id) + if (mSelectedItemIDs.size() == 1 + && std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), item_id) != mSelectedItemIDs.end()) { - return; - } - if (mNeedsArrange && item_id.notNull()) - { - mItemToSelect = item_id; + // Already selected return; } - if (mItemMap[mSelectedItemID]) + for (const LLUUID& id : mSelectedItemIDs) { - mItemMap[mSelectedItemID]->setSelected(FALSE); + if (mItemMap[id]) + { + mItemMap[id]->setSelected(FALSE); + } } + mSelectedItemIDs.clear(); + if (mItemMap[item_id]) { mItemMap[item_id]->setSelected(TRUE); } - mSelectedItemID = item_id; + mSelectedItemIDs.push_back(item_id); signalSelectionItemID(item_id); if (scroll_to_selection) { - scrollToShowItem(mSelectedItemID); + scrollToShowItem(item_id); } } @@ -1347,31 +1374,45 @@ void LLInventoryGallery::scrollToShowItem(const LLUUID& item_id) } } -LLInventoryGalleryItem* LLInventoryGallery::getSelectedItem() +LLInventoryGalleryItem* LLInventoryGallery::getFirstSelectedItem() { - return mItemMap[mSelectedItemID]; + if (mSelectedItemIDs.size() > 0) + { + selection_deque::iterator iter = mSelectedItemIDs.begin(); + return mItemMap[*iter]; + } + return NULL; } void LLInventoryGallery::copy() { - LLClipboard::instance().reset(); - if (getVisible() && getEnabled() && mSelectedItemID.notNull()) + if (!getVisible() || !getEnabled()) { - LLClipboard::instance().addToClipboard(mSelectedItemID); + return; + } + + LLClipboard::instance().reset(); + + for (const LLUUID& id : mSelectedItemIDs) + { + LLClipboard::instance().addToClipboard(id); } mFilterSubString.clear(); } BOOL LLInventoryGallery::canCopy() const { - if (!getVisible() || !getEnabled() || mSelectedItemID.isNull()) + if (!getVisible() || !getEnabled() || mSelectedItemIDs.empty()) { return FALSE; } - if (!isItemCopyable(mSelectedItemID)) + for (const LLUUID& id : mSelectedItemIDs) { - return FALSE; + if (!isItemCopyable(id)) + { + return FALSE; + } } return TRUE; @@ -1379,36 +1420,45 @@ BOOL LLInventoryGallery::canCopy() const void LLInventoryGallery::cut() { + if (!getVisible() || !getEnabled()) + { + return; + } + // clear the inventory clipboard LLClipboard::instance().reset(); - if (getVisible() && getEnabled() && mSelectedItemID.notNull()) + LLClipboard::instance().setCutMode(true); + for (const LLUUID& id : mSelectedItemIDs) { // todo: fade out selected item - LLClipboard::instance().setCutMode(true); - LLClipboard::instance().addToClipboard(mSelectedItemID); + LLClipboard::instance().addToClipboard(id); } + mFilterSubString.clear(); } BOOL LLInventoryGallery::canCut() const { - if (!getVisible() || !getEnabled() || mSelectedItemID.isNull()) + if (!getVisible() || !getEnabled() || mSelectedItemIDs.empty()) { return FALSE; } - LLViewerInventoryCategory* cat = gInventory.getCategory(mSelectedItemID); - if (cat) + for (const LLUUID& id : mSelectedItemIDs) { - if (!get_is_category_removable(&gInventory, mSelectedItemID)) + LLViewerInventoryCategory* cat = gInventory.getCategory(id); + if (cat) + { + if (!get_is_category_removable(&gInventory, id)) + { + return FALSE; + } + } + else if (!get_is_item_removable(&gInventory, id)) { return FALSE; } } - else if (!get_is_item_removable(&gInventory, mSelectedItemID)) - { - return FALSE; - } return TRUE; } @@ -1421,14 +1471,20 @@ void LLInventoryGallery::paste() } const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); - if (!mSelectedItemID.isNull() && gInventory.isObjectDescendentOf(mSelectedItemID, marketplacelistings_id)) + if (mSelectedItemIDs.size() == 1 && gInventory.isObjectDescendentOf(*mSelectedItemIDs.begin(), marketplacelistings_id)) { return; } - LLInventoryObject* obj = gInventory.getObject(mSelectedItemID); + LLUUID first_selected_id; + if (mSelectedItemIDs.size() > 0) + { + first_selected_id = *mSelectedItemIDs.begin(); + } + + LLInventoryObject* obj = gInventory.getObject(first_selected_id); bool is_folder = obj && (obj->getType() == LLAssetType::AT_CATEGORY); - LLUUID dest = is_folder ? mSelectedItemID : mFolderID; + LLUUID dest = is_folder ? first_selected_id : mFolderID; bool is_cut_mode = LLClipboard::instance().isCutMode(); std::vector objects; @@ -1463,6 +1519,7 @@ void LLInventoryGallery::paste() gInventory.changeCategoryParent(cat, dest, false); // Don't select immediately, wait for item to arrive mItemToSelect = item_id; + mNeedsSelection = true; } else { @@ -1479,6 +1536,7 @@ void LLInventoryGallery::paste() gInventory.changeItemParent(item, dest, false); // Don't select immediately, wait for item to arrive mItemToSelect = item_id; + mNeedsSelection = true; } else { @@ -1535,28 +1593,31 @@ BOOL LLInventoryGallery::canPaste() const return TRUE; } -void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response, const LLUUID& selected_id) +void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response, const selection_deque selected_ids) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { - LLInventoryObject* obj = gInventory.getObject(selected_id); - if (!obj) + for (const LLUUID& id : selected_ids) { - return; - } - if (obj->getType() == LLAssetType::AT_CATEGORY) - { - if (get_is_category_removable(&gInventory, selected_id)) + LLInventoryObject* obj = gInventory.getObject(id); + if (!obj) { - gInventory.removeCategory(selected_id); + return; } - } - else - { - if (get_is_item_removable(&gInventory, selected_id)) + if (obj->getType() == LLAssetType::AT_CATEGORY) { - gInventory.removeItem(selected_id); + if (get_is_category_removable(&gInventory, id)) + { + gInventory.removeCategory(id); + } + } + else + { + if (get_is_item_removable(&gInventory, id)) + { + gInventory.removeItem(id); + } } } } @@ -1578,31 +1639,39 @@ void LLInventoryGallery::deleteSelection() args["COUNT_TOTAL"] = 1; args["QUESTION"] = LLTrans::getString("DeleteItem", args); // - LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemID)); + LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemIDs)); } bool LLInventoryGallery::canDeleteSelection() { - if (mSelectedItemID.isNull()) - { - return false; - } - - LLViewerInventoryCategory* cat = gInventory.getCategory(mSelectedItemID); - if (cat) - { - if (!get_is_category_removable(&gInventory, mSelectedItemID)) - { - return false; - } - } - else if (!get_is_item_removable(&gInventory, mSelectedItemID)) + if (mSelectedItemIDs.empty()) { return false; } const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - return !gInventory.isObjectDescendentOf(mSelectedItemID, trash_id); + if (mFolderID == trash_id || gInventory.isObjectDescendentOf(mFolderID, trash_id)) + { + return false; + } + + for (const LLUUID& id : mSelectedItemIDs) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(id); + if (cat) + { + if (!get_is_category_removable(&gInventory, id)) + { + return false; + } + } + else if (!get_is_item_removable(&gInventory, id)) + { + return false; + } + } + + return true; } void LLInventoryGallery::pasteAsLink() @@ -1617,12 +1686,12 @@ void LLInventoryGallery::pasteAsLink() const LLUUID& my_outifts_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); LLUUID dest; - LLInventoryObject* obj = gInventory.getObject(mSelectedItemID); - if (obj && obj->getType() == LLAssetType::AT_CATEGORY) + if (mSelectedItemIDs.size() > 0) { - dest = mSelectedItemID; + dest = *mSelectedItemIDs.begin(); } - else + LLInventoryObject* obj = gInventory.getObject(dest); + if (!obj || obj->getType() != LLAssetType::AT_CATEGORY) { dest = mFolderID; } @@ -1900,18 +1969,35 @@ void LLInventoryGallery::onGesturesChanged() void LLInventoryGallery::deselectItem(const LLUUID& category_id) { // Reset selection if the item is selected. - if (category_id == mSelectedItemID) + LLInventoryGalleryItem* item = mItemMap[category_id]; + if (item && item->isSelected()) { - mSelectedItemID = LLUUID::null; - signalSelectionItemID(mSelectedItemID); + mItemMap[category_id]->setSelected(FALSE); + setFocus(true); + // Todo: support multiselect + signalSelectionItemID(LLUUID::null); + } + + selection_deque::iterator found = std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), category_id); + if (found != mSelectedItemIDs.end()) + { + mSelectedItemIDs.erase(found); } } void LLInventoryGallery::clearSelection() { - if(mSelectedItemID != LLUUID::null) + for (const LLUUID& id: mSelectedItemIDs) { - changeItemSelection(LLUUID::null); + if (mItemMap[id]) + { + mItemMap[id]->setSelected(FALSE); + } + } + if (!mSelectedItemIDs.empty()) + { + mSelectedItemIDs.clear(); + signalSelectionItemID(LLUUID::null); } } @@ -1925,6 +2011,15 @@ boost::signals2::connection LLInventoryGallery::setSelectionChangeCallback(selec return mSelectionChangeSignal.connect(cb); } +LLUUID LLInventoryGallery::getFirstSelectedItemID() +{ + if (mSelectedItemIDs.size() > 0) + { + return *mSelectedItemIDs.begin(); + } + return LLUUID::null; +} + LLUUID LLInventoryGallery::getOutfitImageID(LLUUID outfit_id) { LLUUID thumbnail_id; @@ -2144,7 +2239,9 @@ LLInventoryGalleryItem::LLInventoryGalleryItem(const Params& p) mHidden(false), mGallery(NULL), mType(LLAssetType::AT_NONE), - mSortGroup(SG_ITEM) + mSortGroup(SG_ITEM), + mCutGeneration(0), + mSelectedForCut(false) { buildFromFile("panel_inventory_gallery_item.xml"); } @@ -2242,13 +2339,24 @@ void LLInventoryGalleryItem::setThumbnail(LLUUID id) void LLInventoryGalleryItem::draw() { - LLPanel::draw(); + if (isFadeItem()) + { + // Fade out to indicate it's being cut + LLViewDrawContext context(0.5f); + LLPanel::draw(); + } + else + { + LLPanel::draw(); + + // Draw border + LLUIColor border_color = LLUIColorTable::instance().getColor(mSelected ? "MenuItemHighlightBgColor" : "TextFgTentativeColor", LLColor4::white); + LLRect border = getChildView("preview_thumbnail")->getRect(); + border.mRight = border.mRight + 1; + gl_rect_2d(border, border_color.get(), FALSE); + } + - // Draw border - LLUIColor border_color = LLUIColorTable::instance().getColor(mSelected ? "MenuItemHighlightBgColor" : "TextFgTentativeColor", LLColor4::white); - LLRect border = getChildView("preview_thumbnail")->getRect(); - border.mRight = border.mRight + 1; - gl_rect_2d(border, border_color.get(), FALSE); } void LLInventoryGalleryItem::setItemName(std::string name) @@ -2289,6 +2397,7 @@ BOOL LLInventoryGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask) { setFocus(TRUE); mGallery->claimEditHandler(); + mGallery->showContextMenu(this, x, y, mUUID); LLUICtrl::handleRightMouseDown(x, y, mask); return TRUE; @@ -2453,6 +2562,19 @@ void LLInventoryGalleryItem::updateNameText() getChild("preview_thumbnail")->setToolTip(mItemName + mPermSuffix + mWornSuffix); } +bool LLInventoryGalleryItem::isFadeItem() +{ + LLClipboard& clipboard = LLClipboard::instance(); + if (mCutGeneration == clipboard.getGeneration()) + { + return mSelectedForCut; + } + + mCutGeneration = clipboard.getGeneration(); + mSelectedForCut = clipboard.isCutMode() && clipboard.isOnClipboard(mUUID); + return mSelectedForCut; +} + //----------------------------- // LLThumbnailsObserver //----------------------------- @@ -2538,6 +2660,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, { // Don't select immediately, wait for item to arrive mItemToSelect = inv_item->getUUID(); + mNeedsSelection = true; } break; case DAD_LINK: @@ -2559,6 +2682,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, if (accepted && drop && inv_item) { mItemToSelect = inv_item->getUUID(); + mNeedsSelection = true; } break; case DAD_CATEGORY: @@ -2573,6 +2697,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, if (accepted && drop) { mItemToSelect = cat_ptr->getUUID(); + mNeedsSelection = true; } } break; diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h index 5f9c191fc5..f2e5e38940 100644 --- a/indra/newview/llinventorygallery.h +++ b/indra/newview/llinventorygallery.h @@ -51,6 +51,7 @@ public: typedef boost::signals2::signal selection_change_signal_t; typedef boost::function selection_change_callback_t; + typedef std::deque selection_deque; struct Params : public LLInitParam::Block @@ -132,7 +133,7 @@ public: void scrollToShowItem(const LLUUID& item_id); void signalSelectionItemID(const LLUUID& category_id); boost::signals2::connection setSelectionChangeCallback(selection_change_callback_t cb); - LLUUID getSelectedItemID() { return mSelectedItemID; } + LLUUID getFirstSelectedItemID(); void setSearchType(LLInventoryFilter::ESearchType type); LLInventoryFilter::ESearchType getSearchType() { return mSearchType; } @@ -142,7 +143,7 @@ public: bool hasVisibleItems(); void handleModifiedFilter(); LLScrollContainer* getScrollableContainer() { return mScrollPanel; } - LLInventoryGalleryItem* getSelectedItem(); + LLInventoryGalleryItem* getFirstSelectedItem(); // Copy & paste (LLEditMenuHandler) void copy() override; @@ -155,7 +156,7 @@ public: BOOL canPaste() const override; // Copy & paste & delete - static void onDelete(const LLSD& notification, const LLSD& response, const LLUUID& selected_id); + static void onDelete(const LLSD& notification, const LLSD& response, const selection_deque selected_ids); void deleteSelection(); bool canDeleteSelection(); void pasteAsLink(); @@ -170,10 +171,10 @@ public: BOOL baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg); -protected: - void showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id); +protected: + bool applyFilter(LLInventoryGalleryItem* item, const std::string& filter_substring); bool checkAgainstFilters(LLInventoryGalleryItem* item, const std::string& filter_substring); static void onIdle(void* userdata); @@ -183,8 +184,9 @@ protected: LLThumbnailsObserver* mThumbnailsObserver; LLGalleryGestureObserver* mGestureObserver; LLInventoryObserver* mInventoryObserver; - LLUUID mSelectedItemID; + selection_deque mSelectedItemIDs; LLUUID mItemToSelect; + bool mNeedsSelection; bool mIsInitialized; bool mRootDirty; @@ -300,6 +302,7 @@ public: LLFontGL* getTextFont(); void setItemName(std::string name); + bool isSelected() { return mSelected; } void setSelected(bool value); void setWorn(bool value); void setUUID(LLUUID id) {mUUID = id;} @@ -332,6 +335,8 @@ public: void updateNameText(); private: + bool isFadeItem(); + LLUUID mUUID; LLTextBox* mNameText; LLPanel* mTextBgPanel; @@ -341,6 +346,8 @@ private: bool mHidden; bool mIsFolder; bool mIsLink; + S32 mCutGeneration; + bool mSelectedForCut; std::string mAssetIDStr; std::string mDesc; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 5b6fa89d52..c1c24397b2 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -95,6 +95,8 @@ const S32 LLInventoryModel::sCurrentInvCacheVersion = 3; BOOL LLInventoryModel::sFirstTimeInViewer2 = TRUE; +S32 LLInventoryModel::sPendingSystemFolders = 0; + ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs ///---------------------------------------------------------------------------- @@ -929,8 +931,9 @@ void LLInventoryModel::ensureCategoryForTypeExists(LLFolderType::EType preferred } else { - LL_DEBUGS("Inventory") << "Created category: " << new_cat_id + LL_WARNS("Inventory") << "Created category: " << new_cat_id << " for type: " << preferred_type << LL_ENDL; + sPendingSystemFolders--; } } ); @@ -941,6 +944,10 @@ void LLInventoryModel::ensureCategoryForTypeExists(LLFolderType::EType preferred << " because inventory is not usable" << LL_ENDL; } } + else + { + sPendingSystemFolders--; + } } const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot( @@ -3535,6 +3542,9 @@ LLCore::HttpHandle LLInventoryModel::requestPost(bool foreground, void LLInventoryModel::createCommonSystemCategories() { + //amount of System Folder we should wait for + sPendingSystemFolders = 8; + gInventory.ensureCategoryForTypeExists(LLFolderType::FT_TRASH); gInventory.ensureCategoryForTypeExists(LLFolderType::FT_FAVORITE); gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CALLINGCARD); diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index c8bf297863..ebc19cdeba 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -238,10 +238,14 @@ private: //-------------------------------------------------------------------- public: static BOOL getIsFirstTimeInViewer2(); + static bool isSysFoldersReady() { return (sPendingSystemFolders == 0); } + private: static BOOL sFirstTimeInViewer2; const static S32 sCurrentInvCacheVersion; // expected inventory cache version + static S32 sPendingSystemFolders; + /** Initialization/Setup ** ** *******************************************************************************/ diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 08afbf57a4..bbc93385a9 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -2238,7 +2238,7 @@ void LLPanelMainInventory::saveTexture(const LLSD& userdata) LLUUID item_id; if(mSingleFolderMode && isGalleryViewMode()) { - item_id = mCombinationGalleryPanel->getSelectedItemID(); + item_id = mCombinationGalleryPanel->getFirstSelectedItemID(); if (item_id.isNull()) return; } else @@ -2344,7 +2344,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) { if(mSingleFolderMode && isGalleryViewMode()) { - LLInventoryObject *obj = gInventory.getObject(mCombinationGalleryPanel->getSelectedItemID()); + LLInventoryObject *obj = gInventory.getObject(mCombinationGalleryPanel->getFirstSelectedItemID()); if (obj && obj->getIsLinkType()) { show_item_original(obj->getUUID()); @@ -2374,7 +2374,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); if (main_inventory) { - LLInventoryObject *obj = gInventory.getObject(mCombinationGalleryPanel->getSelectedItemID()); + LLInventoryObject *obj = gInventory.getObject(mCombinationGalleryPanel->getFirstSelectedItemID()); if (obj) { main_inventory->findLinks(obj->getUUID(), obj->getName()); @@ -2401,7 +2401,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) LLSD params; if(mSingleFolderMode && isGalleryViewMode()) { - params = LLSD(mCombinationGalleryPanel->getSelectedItemID()); + params = LLSD(mCombinationGalleryPanel->getFirstSelectedItemID()); } else { @@ -2461,7 +2461,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) { if(mSingleFolderMode && isGalleryViewMode()) { - std::set uuids{ mCombinationGalleryPanel->getSelectedItemID()}; + std::set uuids{ mCombinationGalleryPanel->getFirstSelectedItemID()}; LLAvatarActions::shareWithAvatars(uuids, gFloaterView->getParentFloater(this)); } else @@ -2512,7 +2512,7 @@ bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata) LLViewerInventoryItem *inv_item = NULL; if(mSingleFolderMode && isGalleryViewMode()) { - inv_item = gInventory.getItem(mCombinationGalleryPanel->getSelectedItemID()); + inv_item = gInventory.getItem(mCombinationGalleryPanel->getFirstSelectedItemID()); } else { @@ -2564,7 +2564,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) LLUUID item_id; if(mSingleFolderMode && isGalleryViewMode()) { - item_id = mCombinationGalleryPanel->getSelectedItemID(); + item_id = mCombinationGalleryPanel->getFirstSelectedItemID(); } else{ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); @@ -2584,7 +2584,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) LLUUID item_id; if(mSingleFolderMode && isGalleryViewMode()) { - item_id = mCombinationGalleryPanel->getSelectedItemID(); + item_id = mCombinationGalleryPanel->getFirstSelectedItemID(); } else{ LLFolderView* root = getActivePanel()->getRootFolder(); @@ -2619,7 +2619,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) { if(mSingleFolderMode && isGalleryViewMode()) { - return can_share_item(mCombinationGalleryPanel->getSelectedItemID()); + return can_share_item(mCombinationGalleryPanel->getFirstSelectedItemID()); } else{ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); @@ -3328,7 +3328,7 @@ void LLPanelMainInventory::setGallerySelection(const LLUUID& item_id, bool new_w void LLPanelMainInventory::scrollToGallerySelection() { - mCombinationGalleryPanel->scrollToShowItem(mCombinationGalleryPanel->getSelectedItemID()); + mCombinationGalleryPanel->scrollToShowItem(mCombinationGalleryPanel->getFirstSelectedItemID()); } void LLPanelMainInventory::scrollToInvPanelSelection() diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 3499a74151..c4f1dcbf35 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -2502,25 +2502,11 @@ void LLPanelProfileSecondLife::onShowTexturePicker() mFloaterTexturePickerHandle = texture_floaterp->getHandle(); - texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLUUID id) + texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID&) { if (op == LLTextureCtrl::TEXTURE_SELECT) { - LLUUID image_asset_id; - LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterTexturePickerHandle.get(); - if (floaterp) - { - if (id.notNull()) - { - image_asset_id = id; - } - else - { - image_asset_id = floaterp->getAssetID(); - } - } - - onCommitProfileImage(image_asset_id); + onCommitProfileImage(asset_id); } }); texture_floaterp->setLocalTextureEnabled(FALSE); @@ -2910,25 +2896,11 @@ void LLPanelProfileFirstLife::onChangePhoto() mFloaterTexturePickerHandle = texture_floaterp->getHandle(); - texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLUUID id) + texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID&) { if (op == LLTextureCtrl::TEXTURE_SELECT) { - LLUUID image_asset_id; - LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterTexturePickerHandle.get(); - if (floaterp) - { - if (id.notNull()) - { - image_asset_id = id; - } - else - { - image_asset_id = floaterp->getAssetID(); - } - } - - onCommitPhoto(image_asset_id); + onCommitPhoto(asset_id); } }); texture_floaterp->setLocalTextureEnabled(FALSE); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 675afc96bd..84470fe8ba 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2660,7 +2660,22 @@ bool idle_startup() LLInventoryModelBackgroundFetch::instance().start(); gInventory.createCommonSystemCategories(); + LLStartUp::setStartupState(STATE_INVENTORY_CALLBACKS ); + display_startup(); + return FALSE; + } + + //--------------------------------------------------------------------- + // STATE_INVENTORY_CALLBACKS + //--------------------------------------------------------------------- + if (STATE_INVENTORY_CALLBACKS == LLStartUp::getStartupState()) + { + if (!LLInventoryModel::isSysFoldersReady()) + { + display_startup(); + return FALSE; + } LLInventoryModelBackgroundFetch::instance().start(); LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); LLViewerInventoryCategory* cof = gInventory.getCategory(cof_id); @@ -3770,8 +3785,15 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, bool do_append = false; LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); // Need to fetch cof contents before we can wear. - callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(), + if (do_copy) + { + callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(), boost::bind(&LLAppearanceMgr::wearInventoryCategory, LLAppearanceMgr::getInstance(), cat, do_copy, do_append)); + } + else + { + callAfterCategoryLinksFetch(cat_id, boost::bind(&LLAppearanceMgr::wearInventoryCategory, LLAppearanceMgr::getInstance(), cat, do_copy, do_append)); + } LL_DEBUGS() << "initial outfit category id: " << cat_id << LL_ENDL; } @@ -3829,6 +3851,7 @@ std::string LLStartUp::startupStateToString(EStartupState state) RTNENUM( STATE_AGENT_SEND ); RTNENUM( STATE_AGENT_WAIT ); RTNENUM( STATE_INVENTORY_SEND ); + RTNENUM(STATE_INVENTORY_CALLBACKS ); RTNENUM( STATE_MISC ); RTNENUM( STATE_PRECACHE ); RTNENUM( STATE_WEARABLES_WAIT ); diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index d31d3b61fe..4e2940c024 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -81,6 +81,7 @@ typedef enum { STATE_AGENT_SEND, // Connect to a region STATE_AGENT_WAIT, // Wait for region STATE_INVENTORY_SEND, // Do inventory transfer + STATE_INVENTORY_CALLBACKS, // Wait for missing system folders and register callbacks STATE_MISC, // Do more things (set bandwidth, start audio, save location, etc) STATE_PRECACHE, // Wait a bit for textures to download STATE_WEARABLES_WAIT, // Wait for clothing to download diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 4cb997297a..ffdf8e4a21 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -788,19 +788,78 @@ PermissionMask LLFloaterTexturePicker::getFilterPermMask() void LLFloaterTexturePicker::commitIfImmediateSet() { // FIRE-8298: Apply now checkbox has no effect - //if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply) - if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply && mCanPreview) + //if (!mNoCopyTextureSelected && mCanApply) + if (!mNoCopyTextureSelected && mCanApply && mCanPreview) // { - mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, LLUUID::null); + commitCallback(); } } +void LLFloaterTexturePicker::commitCallback() +{ + if (!mOnFloaterCommitCallback) + { + return; + } + LLUUID asset_id = mImageAssetID; + LLUUID inventory_id; + LLPickerSource mode = (LLPickerSource)mModeSelector->getValue().asInteger(); + + switch (mode) + { + case PICKER_INVENTORY: + { + LLFolderView* root_folder = mInventoryPanel->getRootFolder(); + if (root_folder && root_folder->getCurSelectedItem()) + { + LLFolderViewItem* last_selected = root_folder->getCurSelectedItem(); + LLFolderViewModelItemInventory* inv_view = static_cast(last_selected->getViewModelItem()); + + LLInventoryItem* itemp = gInventory.getItem(inv_view->getUUID()); + if (itemp && itemp->getAssetUUID() == mImageAssetID) + { + inventory_id = inv_view->getUUID(); + } + else + { + mode = PICKER_UNKNOWN; // source of id unknown + } + } + else + { + mode = PICKER_UNKNOWN; // source of id unknown + } + break; + } + case PICKER_LOCAL: + { + if (!mLocalScrollCtrl->getAllSelected().empty()) + { + LLUUID temp_id = mLocalScrollCtrl->getFirstSelected()->getColumn(LOCAL_TRACKING_ID_COLUMN)->getValue().asUUID(); + asset_id = LLLocalBitmapMgr::getInstance()->getWorldID(temp_id); + } + else + { + asset_id = mImageAssetID; + mode = PICKER_UNKNOWN; // source of id unknown + } + break; + } + case PICKER_BAKE: + break; + default: + mode = PICKER_UNKNOWN; // source of id unknown + break; + } + + mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, mode, asset_id, inventory_id); +} void LLFloaterTexturePicker::commitCancel() { if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply) { - mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, LLUUID::null); + mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, PICKER_UNKNOWN, mOriginalImageAssetID, LLUUID::null); } } @@ -874,7 +933,7 @@ void LLFloaterTexturePicker::onBtnCancel(void* userdata) self->setImageID( self->mOriginalImageAssetID ); if (self->mOnFloaterCommitCallback) { - self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, LLUUID::null); + self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, PICKER_UNKNOWN, self->mOriginalImageAssetID, LLUUID::null); } self->mViewModel->resetDirty(); self->closeFloater(); @@ -884,20 +943,7 @@ void LLFloaterTexturePicker::onBtnCancel(void* userdata) void LLFloaterTexturePicker::onBtnSelect(void* userdata) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; - LLUUID local_id = LLUUID::null; - if (self->mOwner) - { - if (self->mLocalScrollCtrl->getVisible() && !self->mLocalScrollCtrl->getAllSelected().empty()) - { - LLUUID temp_id = self->mLocalScrollCtrl->getFirstSelected()->getColumn(LOCAL_TRACKING_ID_COLUMN)->getValue().asUUID(); - local_id = LLLocalBitmapMgr::getInstance()->getWorldID(temp_id); - } - } - - if (self->mOnFloaterCommitCallback) - { - self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_SELECT, local_id); - } + self->commitCallback(); self->closeFloater(); } @@ -993,26 +1039,26 @@ void LLFloaterTexturePicker::onModeSelect(LLUICtrl* ctrl, void *userdata) //int index = self->mModeSelector->getValue().asInteger(); int index = self->mModeSelector->getSelectedIndex(); - self->mDefaultBtn->setVisible(index == 0 ? TRUE : FALSE); - self->mBlankBtn->setVisible(index == 0 ? TRUE : FALSE); - self->mNoneBtn->setVisible(index == 0 ? TRUE : FALSE); - self->mPipetteBtn->setVisible(index == 0 ? TRUE : FALSE); - self->mTransparentBtn->setVisible(index == 0 ? TRUE : FALSE); // FIRE-5082: "Transparent" button in Texture Panel - self->getChild("inventory search editor")->setVisible(index == 0 ? TRUE : FALSE); - self->getChild("inventory panel")->setVisible(index == 0 ? TRUE : FALSE); + self->mDefaultBtn->setVisible(index == PICKER_INVENTORY ? TRUE : FALSE); + self->mBlankBtn->setVisible(index == PICKER_INVENTORY ? TRUE : FALSE); + self->mNoneBtn->setVisible(index == PICKER_INVENTORY ? TRUE : FALSE); + self->mPipetteBtn->setVisible(index == PICKER_INVENTORY ? TRUE : FALSE); + self->mTransparentBtn->setVisible(index == PICKER_INVENTORY ? TRUE : FALSE); // FIRE-5082: "Transparent" button in Texture Panel + self->getChild("inventory search editor")->setVisible(index == PICKER_INVENTORY ? TRUE : FALSE); + self->getChild("inventory panel")->setVisible(index == PICKER_INVENTORY ? TRUE : FALSE); /*self->getChild("show_folders_check")->setVisible(mode); no idea under which conditions the above is even shown, needs testing. */ - self->getChild("l_add_btn")->setVisible(index == 1 ? TRUE : FALSE); - self->getChild("l_rem_btn")->setVisible(index == 1 ? TRUE : FALSE); - self->getChild("l_upl_btn")->setVisible(index == 1 ? TRUE : FALSE); - self->getChild("l_name_list")->setVisible(index == 1 ? TRUE : FALSE); + self->getChild("l_add_btn")->setVisible(index == PICKER_LOCAL ? TRUE : FALSE); + self->getChild("l_rem_btn")->setVisible(index == PICKER_LOCAL ? TRUE : FALSE); + self->getChild("l_upl_btn")->setVisible(index == PICKER_LOCAL ? TRUE : FALSE); + self->getChild("l_name_list")->setVisible(index == PICKER_LOCAL ? TRUE : FALSE); - self->getChild("l_bake_use_texture_combo_box")->setVisible(index == 2 ? TRUE : FALSE); + self->getChild("l_bake_use_texture_combo_box")->setVisible(index == PICKER_BAKE ? TRUE : FALSE); self->getChild("hide_base_mesh_region")->setVisible(FALSE);// index == 2 ? TRUE : FALSE); - if (index == 2) + if (index == PICKER_BAKE) { self->stopUsingPipette(); @@ -1166,7 +1212,7 @@ void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata) { if (self->mOnFloaterCommitCallback) { - self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, inworld_id); + self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, PICKER_LOCAL, inworld_id, LLUUID::null); } } } @@ -1642,7 +1688,7 @@ void LLTextureCtrl::showPicker(BOOL take_focus) } if (texture_floaterp) { - texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLTextureCtrl::onFloaterCommit, this, _1, _2)); + texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLTextureCtrl::onFloaterCommit, this, _1, _2, _3, _4)); } if (texture_floaterp) { @@ -1770,7 +1816,7 @@ void LLTextureCtrl::onFloaterClose() mFloaterHandle.markDead(); } -void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id) +void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID& inv_id) { LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); @@ -1784,22 +1830,29 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id) else if (mCommitOnSelection || op == TEXTURE_SELECT) mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? - if(floaterp->isDirty() || id.notNull()) // mModelView->setDirty does not work. + if(floaterp->isDirty() || asset_id.notNull()) // mModelView->setDirty does not work. { setTentative( FALSE ); - if (id.notNull()) - { - mImageItemID = id; - mImageAssetID = id; - } - else - { - mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE); - LL_DEBUGS() << "mImageItemID: " << mImageItemID << LL_ENDL; - mImageAssetID = floaterp->getAssetID(); - LL_DEBUGS() << "mImageAssetID: " << mImageAssetID << LL_ENDL; - } + switch(source) + { + case PICKER_INVENTORY: + mImageItemID = inv_id; + mImageAssetID = asset_id; + break; + case PICKER_BAKE: + case PICKER_LOCAL: + mImageItemID = LLUUID::null; + mImageAssetID = asset_id; + break; + case PICKER_UNKNOWN: + default: + mImageItemID = floaterp->findItemID(asset_id, FALSE); + mImageAssetID = asset_id; + break; + } + + LL_DEBUGS() << "mImageAssetID: " << mImageAssetID << ", mImageItemID: " << mImageItemID << LL_ENDL; if (op == TEXTURE_SELECT && mOnSelectCallback) { diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 2074d33de2..33c1eda16a 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -65,6 +65,14 @@ bool get_is_predefined_texture(LLUUID asset_id); LLUUID get_copy_free_item_by_asset_id(LLUUID image_id, bool no_trans_perm = false); bool get_can_copy_texture(LLUUID image_id); +enum LLPickerSource +{ + PICKER_INVENTORY, + PICKER_LOCAL, + PICKER_BAKE, + PICKER_UNKNOWN, // on cancel, default ids +}; + ////////////////////////////////////////////////////////////////////////////////////////// // LLTextureCtrl @@ -192,7 +200,7 @@ public: void closeDependentFloater(); void onFloaterClose(); - void onFloaterCommit(ETexturePickOp op, LLUUID id); + void onFloaterCommit(ETexturePickOp op, LLPickerSource source, const LLUUID& local_id, const LLUUID& inv_id); // This call is returned when a drag is detected. Your callback // should return TRUE if the drag is acceptable. @@ -267,7 +275,7 @@ private: ////////////////////////////////////////////////////////////////////////////////////////// // LLFloaterTexturePicker -typedef boost::function floater_commit_callback; +typedef boost::function floater_commit_callback; typedef boost::function floater_close_callback; typedef boost::function set_image_asset_id_callback; typedef boost::function texture)> set_on_update_image_stats_callback; @@ -322,6 +330,7 @@ public: void updateFilterPermMask(); void commitIfImmediateSet(); + void commitCallback(); void commitCancel(); void onFilterEdit(const std::string& search_string);