diff options
Diffstat (limited to 'indra/newview/lltooldraganddrop.cpp')
-rw-r--r-- | indra/newview/lltooldraganddrop.cpp | 679 |
1 files changed, 571 insertions, 108 deletions
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 54484a1dbb..1e81e675e6 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -2,25 +2,31 @@ * @file lltooldraganddrop.cpp * @brief LLToolDragAndDrop class implementation * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ @@ -32,6 +38,7 @@ // project headers #include "llagent.h" #include "llagentcamera.h" +#include "llagentui.h" #include "llagentwearables.h" #include "llappearancemgr.h" #include "lldictionary.h" @@ -39,26 +46,31 @@ #include "llfloaterreg.h" #include "llfloatertools.h" #include "llgesturemgr.h" -#include "llgiveinventory.h" #include "llhudmanager.h" #include "llhudeffecttrail.h" #include "llimview.h" #include "llinventorybridge.h" #include "llinventorydefines.h" #include "llinventoryfunctions.h" +#include "llmutelist.h" #include "llpreviewnotecard.h" +#include "llrecentpeople.h" #include "llrootview.h" #include "llselectmgr.h" #include "lltoolmgr.h" #include "lltooltip.h" #include "lltrans.h" #include "llviewerobjectlist.h" -#include "llviewerregion.h" #include "llviewerstats.h" #include "llviewerwindow.h" #include "llvoavatarself.h" #include "llworld.h" +// MAX ITEMS is based on (sizeof(uuid)+2) * count must be < MTUBYTES +// or 18 * count < 1200 => count < 1200/18 => 66. I've cut it down a +// bit from there to give some pad. +const S32 MAX_ITEMS = 42; + // syntactic sugar #define callMemberFunction(object,ptrToMember) ((object).*(ptrToMember)) @@ -133,6 +145,29 @@ bool LLDroppableItem::operator()(LLInventoryCategory* cat, return allowed; } +class LLUncopyableItems : public LLInventoryCollectFunctor +{ +public: + LLUncopyableItems() {} + virtual ~LLUncopyableItems() {} + virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item); +}; + +bool LLUncopyableItems::operator()(LLInventoryCategory* cat, + LLInventoryItem* item) +{ + bool uncopyable = false; + if (item) + { + if (itemTransferCommonlyAllowed(item) && + !item->getPermissions().allowCopyBy(gAgent.getID())) + { + uncopyable = true; + } + } + return uncopyable; +} + class LLDropCopyableItems : public LLInventoryCollectFunctor { public: @@ -160,16 +195,47 @@ bool LLDropCopyableItems::operator()( return allowed; } -// Starts a fetch on folders and items. This is really not used -// as an observer in the traditional sense; we're just using it to -// request a fetch and we don't care about when/if the response arrives. +class LLGiveable : public LLInventoryCollectFunctor +{ +public: + LLGiveable() : mCountLosing(0) {} + virtual ~LLGiveable() {} + virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item); + + S32 countNoCopy() const { return mCountLosing; } +protected: + S32 mCountLosing; +}; + +bool LLGiveable::operator()(LLInventoryCategory* cat, LLInventoryItem* item) +{ + // All categories can be given. + if (cat) + return true; + + bool allowed = false; + if (item) + { + allowed = itemTransferCommonlyAllowed(item); + if (allowed && + !item->getPermissions().allowOperationBy(PERM_TRANSFER, + gAgent.getID())) + { + allowed = FALSE; + } + if (allowed && + !item->getPermissions().allowCopyBy(gAgent.getID())) + { + ++mCountLosing; + } + } + return allowed; +} + class LLCategoryFireAndForget : public LLInventoryFetchComboObserver { public: - LLCategoryFireAndForget(const uuid_vec_t& folder_ids, - const uuid_vec_t& item_ids) : - LLInventoryFetchComboObserver(folder_ids, item_ids) - {} + LLCategoryFireAndForget() {} ~LLCategoryFireAndForget() {} virtual void done() { @@ -178,13 +244,11 @@ public: } }; -class LLCategoryDropObserver : public LLInventoryFetchItemsObserver +class LLCategoryDropObserver : public LLInventoryFetchObserver { public: LLCategoryDropObserver( - const uuid_vec_t& ids, const LLUUID& obj_id, LLToolDragAndDrop::ESource src) : - LLInventoryFetchItemsObserver(ids), mObjectID(obj_id), mSource(src) {} @@ -221,7 +285,7 @@ void LLCategoryDropObserver::done() } delete this; } -/* Doesn't seem to be used anymore. + class LLCategoryDropDescendentsObserver : public LLInventoryFetchDescendentsObserver { public: @@ -267,9 +331,9 @@ void LLCategoryDropDescendentsObserver::done() std::back_insert_iterator<uuid_vec_t> copier(ids); std::copy(unique_ids.begin(), unique_ids.end(), copier); LLCategoryDropObserver* dropper; - dropper = new LLCategoryDropObserver(ids, mObjectID, mSource); - dropper->startFetch(); - if (dropper->isDone()) + dropper = new LLCategoryDropObserver(mObjectID, mSource); + dropper->fetch(ids); + if (dropper->isEverythingComplete()) { dropper->done(); } @@ -280,7 +344,6 @@ void LLCategoryDropDescendentsObserver::done() } delete this; } -*/ LLToolDragAndDrop::DragAndDropEntry::DragAndDropEntry(dragOrDrop3dImpl f_none, dragOrDrop3dImpl f_self, @@ -416,9 +479,8 @@ void LLToolDragAndDrop::beginDrag(EDragAndDropType type, } if (!folder_ids.empty() || !item_ids.empty()) { - LLCategoryFireAndForget *fetcher = new LLCategoryFireAndForget(folder_ids, item_ids); - fetcher->startFetch(); - delete fetcher; + LLCategoryFireAndForget fetcher; + fetcher.fetch(folder_ids, item_ids); } } } @@ -487,7 +549,8 @@ void LLToolDragAndDrop::beginMultiDrag( uuid_vec_t item_ids; std::back_insert_iterator<uuid_vec_t> copier(folder_ids); std::copy(cat_ids.begin(), cat_ids.end(), copier); - LLCategoryFireAndForget fetcher(folder_ids, item_ids); + LLCategoryFireAndForget fetcher; + fetcher.fetch(folder_ids, item_ids); } } } @@ -1140,7 +1203,7 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target, LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if (!item || !item->isFinished()) return; + if (!item || !item->isComplete()) return; //if (regionp // && (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX)) @@ -1347,6 +1410,422 @@ void LLToolDragAndDrop::dropInventory(LLViewerObject* hit_obj, gFloaterTools->dirty(); } +void LLToolDragAndDrop::giveInventory(const LLUUID& to_agent, + LLInventoryItem* item, + const LLUUID& im_session_id) + +{ + llinfos << "LLToolDragAndDrop::giveInventory()" << llendl; + if (!isInventoryGiveAcceptable(item)) + { + return; + } + if (item->getPermissions().allowCopyBy(gAgent.getID())) + { + // just give it away. + LLToolDragAndDrop::commitGiveInventoryItem(to_agent, item, im_session_id); + } + else + { + // ask if the agent is sure. + LLSD payload; + payload["agent_id"] = to_agent; + payload["item_id"] = item->getUUID(); + LLNotificationsUtil::add("CannotCopyWarning", LLSD(), payload, + &LLToolDragAndDrop::handleCopyProtectedItem); + } +} +// static +bool LLToolDragAndDrop::handleCopyProtectedItem(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + LLInventoryItem* item = NULL; + switch(option) + { + case 0: // "Yes" + item = gInventory.getItem(notification["payload"]["item_id"].asUUID()); + if (item) + { + LLToolDragAndDrop::commitGiveInventoryItem(notification["payload"]["agent_id"].asUUID(), + item); + // delete it for now - it will be deleted on the server + // quickly enough. + gInventory.deleteObject(notification["payload"]["item_id"].asUUID()); + gInventory.notifyObservers(); + } + else + { + LLNotificationsUtil::add("CannotGiveItem"); + } + break; + + default: // no, cancel, whatever, who cares, not yes. + LLNotificationsUtil::add("TransactionCancelled"); + break; + } + return false; +} + +// static +void LLToolDragAndDrop::commitGiveInventoryItem(const LLUUID& to_agent, + LLInventoryItem* item, + const LLUUID& im_session_id) +{ + if (!item) return; + std::string name; + LLAgentUI::buildFullname(name); + LLUUID transaction_id; + transaction_id.generate(); + const S32 BUCKET_SIZE = sizeof(U8) + UUID_BYTES; + U8 bucket[BUCKET_SIZE]; + bucket[0] = (U8)item->getType(); + memcpy(&bucket[1], &(item->getUUID().mData), UUID_BYTES); /* Flawfinder: ignore */ + pack_instant_message( + gMessageSystem, + gAgent.getID(), + FALSE, + gAgent.getSessionID(), + to_agent, + name, + item->getName(), + IM_ONLINE, + IM_INVENTORY_OFFERED, + transaction_id, + 0, + LLUUID::null, + gAgent.getPositionAgent(), + NO_TIMESTAMP, + bucket, + BUCKET_SIZE); + gAgent.sendReliableMessage(); + + // VEFFECT: giveInventory + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); + effectp->setSourceObject(gAgentAvatarp); + effectp->setTargetObject(gObjectList.findObject(to_agent)); + effectp->setDuration(LL_HUD_DUR_SHORT); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + gFloaterTools->dirty(); + + LLMuteList::getInstance()->autoRemove(to_agent, LLMuteList::AR_INVENTORY); + + logInventoryOffer(to_agent, im_session_id); + + // add buddy to recent people list + LLRecentPeople::instance().add(to_agent); +} + +//static +void LLToolDragAndDrop::logInventoryOffer(const LLUUID& to_agent, const LLUUID &im_session_id) +{ + // compute id of possible IM session with agent that has "to_agent" id + LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, to_agent); + // If this item was given by drag-and-drop into an IM panel, log this action in the IM panel chat. + if (im_session_id.notNull()) + { + LLSD args; + gIMMgr->addSystemMessage(im_session_id, "inventory_item_offered", args); + } + // If this item was given by drag-and-drop on avatar while IM panel was open, log this action in the IM panel chat. + else if (LLIMModel::getInstance()->findIMSession(session_id)) + { + LLSD args; + gIMMgr->addSystemMessage(session_id, "inventory_item_offered", args); + } + // If this item was given by drag-and-drop on avatar while IM panel wasn't open, log this action to IM history. + else + { + std::string full_name; + if (gCacheName->getFullName(to_agent, full_name)) + { + LLIMModel::instance().logToFile(full_name, LLTrans::getString("SECOND_LIFE"), im_session_id, LLTrans::getString("inventory_item_offered-im")); + } + } +} + +void LLToolDragAndDrop::giveInventoryCategory(const LLUUID& to_agent, + LLInventoryCategory* cat, + const LLUUID& im_session_id) + +{ + if (!cat) return; + llinfos << "LLToolDragAndDrop::giveInventoryCategory() - " + << cat->getUUID() << llendl; + + if (!isAgentAvatarValid()) return; + + // Test out how many items are being given. + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLGiveable giveable; + gInventory.collectDescendentsIf (cat->getUUID(), + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + giveable); + S32 count = cats.count(); + bool complete = true; + for(S32 i = 0; i < count; ++i) + { + if (!gInventory.isCategoryComplete(cats.get(i)->getUUID())) + { + complete = false; + break; + } + } + if (!complete) + { + LLNotificationsUtil::add("IncompleteInventory"); + return; + } + count = items.count() + cats.count(); + if (count > MAX_ITEMS) + { + LLNotificationsUtil::add("TooManyItems"); + return; + } + else if (count == 0) + { + LLNotificationsUtil::add("NoItems"); + return; + } + else + { + if (0 == giveable.countNoCopy()) + { + LLToolDragAndDrop::commitGiveInventoryCategory(to_agent, cat, im_session_id); + } + else + { + LLSD args; + args["COUNT"] = llformat("%d",giveable.countNoCopy()); + LLSD payload; + payload["agent_id"] = to_agent; + payload["folder_id"] = cat->getUUID(); + LLNotificationsUtil::add("CannotCopyCountItems", args, payload, &LLToolDragAndDrop::handleCopyProtectedCategory); + } + } +} + + +// static +bool LLToolDragAndDrop::handleCopyProtectedCategory(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + LLInventoryCategory* cat = NULL; + switch(option) + { + case 0: // "Yes" + cat = gInventory.getCategory(notification["payload"]["folder_id"].asUUID()); + if (cat) + { + LLToolDragAndDrop::commitGiveInventoryCategory(notification["payload"]["agent_id"].asUUID(), + cat); + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLUncopyableItems remove; + gInventory.collectDescendentsIf (cat->getUUID(), + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + remove); + S32 count = items.count(); + for(S32 i = 0; i < count; ++i) + { + gInventory.deleteObject(items.get(i)->getUUID()); + } + gInventory.notifyObservers(); + } + else + { + LLNotificationsUtil::add("CannotGiveCategory"); + } + break; + + default: // no, cancel, whatever, who cares, not yes. + LLNotificationsUtil::add("TransactionCancelled"); + break; + } + return false; +} + +// static +void LLToolDragAndDrop::commitGiveInventoryCategory(const LLUUID& to_agent, + LLInventoryCategory* cat, + const LLUUID& im_session_id) + +{ + if (!cat) return; + llinfos << "LLToolDragAndDrop::commitGiveInventoryCategory() - " + << cat->getUUID() << llendl; + + // add buddy to recent people list + LLRecentPeople::instance().add(to_agent); + + // Test out how many items are being given. + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLGiveable giveable; + gInventory.collectDescendentsIf (cat->getUUID(), + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + giveable); + + // MAX ITEMS is based on (sizeof(uuid)+2) * count must be < + // MTUBYTES or 18 * count < 1200 => count < 1200/18 => + // 66. I've cut it down a bit from there to give some pad. + S32 count = items.count() + cats.count(); + if (count > MAX_ITEMS) + { + LLNotificationsUtil::add("TooManyItems"); + return; + } + else if (count == 0) + { + LLNotificationsUtil::add("NoItems"); + return; + } + else + { + std::string name; + LLAgentUI::buildFullname(name); + LLUUID transaction_id; + transaction_id.generate(); + S32 bucket_size = (sizeof(U8) + UUID_BYTES) * (count + 1); + U8* bucket = new U8[bucket_size]; + U8* pos = bucket; + U8 type = (U8)cat->getType(); + memcpy(pos, &type, sizeof(U8)); /* Flawfinder: ignore */ + pos += sizeof(U8); + memcpy(pos, &(cat->getUUID()), UUID_BYTES); /* Flawfinder: ignore */ + pos += UUID_BYTES; + S32 i; + count = cats.count(); + for(i = 0; i < count; ++i) + { + memcpy(pos, &type, sizeof(U8)); /* Flawfinder: ignore */ + pos += sizeof(U8); + memcpy(pos, &(cats.get(i)->getUUID()), UUID_BYTES); /* Flawfinder: ignore */ + pos += UUID_BYTES; + } + count = items.count(); + for(i = 0; i < count; ++i) + { + type = (U8)items.get(i)->getType(); + memcpy(pos, &type, sizeof(U8)); /* Flawfinder: ignore */ + pos += sizeof(U8); + memcpy(pos, &(items.get(i)->getUUID()), UUID_BYTES); /* Flawfinder: ignore */ + pos += UUID_BYTES; + } + pack_instant_message( + gMessageSystem, + gAgent.getID(), + FALSE, + gAgent.getSessionID(), + to_agent, + name, + cat->getName(), + IM_ONLINE, + IM_INVENTORY_OFFERED, + transaction_id, + 0, + LLUUID::null, + gAgent.getPositionAgent(), + NO_TIMESTAMP, + bucket, + bucket_size); + gAgent.sendReliableMessage(); + delete[] bucket; + + // VEFFECT: giveInventoryCategory + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); + effectp->setSourceObject(gAgentAvatarp); + effectp->setTargetObject(gObjectList.findObject(to_agent)); + effectp->setDuration(LL_HUD_DUR_SHORT); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + gFloaterTools->dirty(); + + LLMuteList::getInstance()->autoRemove(to_agent, LLMuteList::AR_INVENTORY); + + logInventoryOffer(to_agent, im_session_id); + } +} + +// static +BOOL LLToolDragAndDrop::isInventoryGiveAcceptable(LLInventoryItem* item) +{ + if (!item) + { + return FALSE; + } + if (!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID())) + { + return FALSE; + } + BOOL copyable = FALSE; + if (item->getPermissions().allowCopyBy(gAgent.getID())) copyable = TRUE; + + if (!isAgentAvatarValid()) return FALSE; + + BOOL acceptable = TRUE; + switch(item->getType()) + { + case LLAssetType::AT_OBJECT: + if (gAgentAvatarp->isWearingAttachment(item->getUUID())) + { + acceptable = FALSE; + } + break; + case LLAssetType::AT_BODYPART: + case LLAssetType::AT_CLOTHING: + if (!copyable && gAgentWearables.isWearingItem(item->getUUID())) + { + acceptable = FALSE; + } + break; + default: + break; + } + return acceptable; +} + +// Static +BOOL LLToolDragAndDrop::isInventoryGroupGiveAcceptable(LLInventoryItem* item) +{ + if (!item) + { + return FALSE; + } + + // These permissions are double checked in the simulator in + // LLGroupNoticeInventoryItemFetch::result(). + if (!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID())) + { + return FALSE; + } + if (!item->getPermissions().allowCopyBy(gAgent.getID())) + { + return FALSE; + } + + if (!isAgentAvatarValid()) return FALSE; + + BOOL acceptable = TRUE; + switch(item->getType()) + { + case LLAssetType::AT_OBJECT: + if (gAgentAvatarp->isWearingAttachment(item->getUUID())) + { + acceptable = FALSE; + } + break; + default: + break; + } + return acceptable; +} + // accessor that looks at permissions, copyability, and names of // inventory items to determine if a drop would be ok. EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item) @@ -1355,7 +1834,7 @@ EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LL if (!item || !obj) return ACCEPT_NO; // HACK: downcast LLViewerInventoryItem* vitem = (LLViewerInventoryItem*)item; - if (!vitem->isFinished()) return ACCEPT_NO; + if (!vitem->isComplete()) return ACCEPT_NO; if (vitem->getIsLinkType()) return ACCEPT_NO; // No giving away links // deny attempts to drop from an object onto itself. This is to @@ -1416,42 +1895,12 @@ EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LL } -static void give_inventory_cb(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - // if Cancel pressed - if (option == 1) - { - return; - } - - LLSD payload = notification["payload"]; - const LLUUID& session_id = payload["session_id"]; - const LLUUID& agent_id = payload["agent_id"]; - LLViewerInventoryItem * inv_item = gInventory.getItem(payload["item_id"]); - if (NULL == inv_item) - { - llassert(NULL != inv_item); - return; - } - - if (LLGiveInventory::doGiveInventoryItem(agent_id, inv_item, session_id)) - { - if ("avatarpicker" == payload["d&d_dest"].asString()) - { - LLFloaterReg::hideInstance("avatar_picker"); - } - LLNotificationsUtil::add("ItemsShared"); - } -} - // function used as drag-and-drop handler for simple agent give inventory requests //static bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_id, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, - EAcceptance* accept, - const LLSD& dest) + EAcceptance* accept) { // check the type switch(cargo_type) @@ -1470,27 +1919,13 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_ { LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data; if (gInventory.getItem(inv_item->getUUID()) - && LLGiveInventory::isInventoryGiveAcceptable(inv_item)) + && LLToolDragAndDrop::isInventoryGiveAcceptable(inv_item)) { // *TODO: get multiple object transfers working *accept = ACCEPT_YES_COPY_SINGLE; if (drop) { - LLIMModel::LLIMSession * session = LLIMModel::instance().findIMSession(session_id); - if (NULL == session) - { - llassert(NULL != session); - return false; - } - LLSD substitutions; - substitutions["RESIDENTS"] = session->mName; - substitutions["ITEMS"] = inv_item->getName(); - LLSD payload; - payload["agent_id"] = dest_agent; - payload["item_id"] = inv_item->getUUID(); - payload["session_id"] = session_id; - payload["d&d_dest"] = dest.asString(); - LLNotificationsUtil::add("ShareItemsConfirmation", substitutions, payload, &give_inventory_cb); + LLToolDragAndDrop::giveInventory(dest_agent, inv_item, session_id); } } else @@ -1512,7 +1947,7 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_ *accept = ACCEPT_YES_COPY_SINGLE; if (drop) { - LLGiveInventory::doGiveInventoryCategory(dest_agent, inv_cat, session_id); + LLToolDragAndDrop::giveInventoryCategory(dest_agent, inv_cat, session_id); } } else @@ -1559,7 +1994,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; + if (!item || !item->isComplete()) return ACCEPT_NO; // must not be in the trash const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); @@ -1608,7 +2043,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; + if (!item || !item->isComplete()) return ACCEPT_NO; if (!isAgentAvatarValid() || gAgentAvatarp->isWearingAttachment(item->getUUID())) { @@ -1670,7 +2105,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezObjectOnObject( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; + if (!item || !item->isComplete()) return ACCEPT_NO; if (!isAgentAvatarValid() || gAgentAvatarp->isWearingAttachment(item->getUUID())) { return ACCEPT_NO; @@ -1749,7 +2184,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezScript( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; + if (!item || !item->isComplete()) return ACCEPT_NO; EAcceptance rv = willObjectAcceptInventory(obj, item); if (drop && (ACCEPT_YES_SINGLE <= rv)) { @@ -1787,7 +2222,7 @@ EAcceptance LLToolDragAndDrop::dad3dTextureObject( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; + if (!item || !item->isComplete()) return ACCEPT_NO; EAcceptance rv = willObjectAcceptInventory(obj, item); if ((mask & MASK_CONTROL)) { @@ -1852,7 +2287,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearItem( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; + if (!item || !item->isComplete()) return ACCEPT_NO; if (mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY) { @@ -1865,9 +2300,31 @@ EAcceptance LLToolDragAndDrop::dad3dWearItem( if (drop) { - // TODO: investigate wearables may not be loaded at this point EXT-8231 + // Don't wear anything until initial wearables are loaded, can + // destroy clothing items. + if (!gAgentWearables.areWearablesLoaded()) + { + LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded"); + return ACCEPT_NO; + } - LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(),true, !(mask & MASK_CONTROL)); + if (mSource == SOURCE_LIBRARY) + { + // create item based on that one, and put it on if that + // was a success. + LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + else + { + wear_inventory_item_on_avatar( item ); + } } return ACCEPT_YES_MULTI; } @@ -1885,7 +2342,7 @@ EAcceptance LLToolDragAndDrop::dad3dActivateGesture( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; + if (!item || !item->isComplete()) return ACCEPT_NO; if (mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY) { @@ -1938,7 +2395,13 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory( if (drop) { - // TODO: investigate wearables may not be loaded at this point EXT-8231 + // Don't wear anything until initial wearables are loaded, can + // destroy clothing items. + if (!gAgentWearables.areWearablesLoaded()) + { + LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded"); + return ACCEPT_NO; + } } if (mSource == SOURCE_AGENT) @@ -1987,7 +2450,7 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventory( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; + if (!item || !item->isComplete()) return ACCEPT_NO; LLViewerObject* root_object = obj; if (obj && obj->getParent()) { @@ -2113,9 +2576,9 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory( const LLViewerInventoryItem *item = (*item_iter); ids.push_back(item->getUUID()); } - LLCategoryDropObserver* dropper = new LLCategoryDropObserver(ids, obj->getID(), mSource); - dropper->startFetch(); - if (dropper->isFinished()) + LLCategoryDropObserver* dropper = new LLCategoryDropObserver(obj->getID(), mSource); + dropper->fetch(ids); + if (dropper->isEverythingComplete()) { dropper->done(); } @@ -2146,7 +2609,7 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventoryObject( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; + if (!item || !item->isComplete()) return ACCEPT_NO; if (!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID())) { // cannot give away no-transfer objects @@ -2161,7 +2624,7 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventoryObject( { if (drop) { - LLGiveInventory::doGiveInventoryItem(obj->getID(), item ); + giveInventory(obj->getID(), item ); } // *TODO: deal with all the issues surrounding multi-object // inventory transfers. @@ -2180,14 +2643,14 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventory( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; - if (!LLGiveInventory::isInventoryGiveAcceptable(item)) + if (!item || !item->isComplete()) return ACCEPT_NO; + if (!isInventoryGiveAcceptable(item)) { return ACCEPT_NO; } if (drop && obj) { - LLGiveInventory::doGiveInventoryItem(obj->getID(), item); + giveInventory(obj->getID(), item); } // *TODO: deal with all the issues surrounding multi-object // inventory transfers. @@ -2204,7 +2667,7 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventoryCategory( LLViewerInventoryCategory* cat; locateInventory(item, cat); if (!cat) return ACCEPT_NO; - LLGiveInventory::doGiveInventoryCategory(obj->getID(), cat); + giveInventoryCategory(obj->getID(), cat); } // *TODO: deal with all the issues surrounding multi-object // inventory transfers. @@ -2219,7 +2682,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnLand( LLViewerInventoryItem* item = NULL; LLViewerInventoryCategory* cat = NULL; locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; + if (!item || !item->isComplete()) return ACCEPT_NO; if (!gAgent.allowOperation(PERM_COPY, item->getPermissions()) || !item->getPermissions().allowTransferTo(LLUUID::null)) @@ -2240,7 +2703,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnObject( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; + if (!item || !item->isComplete()) return ACCEPT_NO; if ((mask & MASK_CONTROL)) { // *HACK: In order to resolve SL-22177, we need to block drags |