summaryrefslogtreecommitdiff
path: root/indra/newview/lltooldraganddrop.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/lltooldraganddrop.cpp')
-rw-r--r--indra/newview/lltooldraganddrop.cpp679
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