diff options
Diffstat (limited to 'indra')
-rw-r--r-- | indra/newview/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/newview/llgiveinventory.cpp | 541 | ||||
-rw-r--r-- | indra/newview/llgiveinventory.h | 99 | ||||
-rw-r--r-- | indra/newview/llinventorybridge.cpp | 5 | ||||
-rw-r--r-- | indra/newview/llpanelgroupnotices.cpp | 4 | ||||
-rw-r--r-- | indra/newview/lltooldraganddrop.cpp | 502 | ||||
-rw-r--r-- | indra/newview/lltooldraganddrop.h | 29 |
7 files changed, 657 insertions, 525 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index d77d53f6af..df98b420a2 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -224,6 +224,7 @@ set(viewer_SOURCE_FILES llfollowcam.cpp llfriendcard.cpp llgesturemgr.cpp + llgiveinventory.cpp llglsandbox.cpp llgroupactions.cpp llgroupiconctrl.cpp @@ -740,6 +741,7 @@ set(viewer_HEADER_FILES llfollowcam.h llfriendcard.h llgesturemgr.h + llgiveinventory.h llgroupactions.h llgroupiconctrl.h llgrouplist.h diff --git a/indra/newview/llgiveinventory.cpp b/indra/newview/llgiveinventory.cpp new file mode 100644 index 0000000000..d83d895dd0 --- /dev/null +++ b/indra/newview/llgiveinventory.cpp @@ -0,0 +1,541 @@ +/** + * @file llgiveinventory.cpp + * @brief LLGiveInventory class implementation + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * 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 + * + * 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 + * + * 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. + * + * 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$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llgiveinventory.h" + +// library includes +#include "llnotificationsutil.h" +#include "lltrans.h" + +// newview includes +#include "llagent.h" +#include "llagentdata.h" +#include "llagentui.h" +#include "llagentwearables.h" +#include "llfloatertools.h" // for gFloaterTool +#include "llhudeffecttrail.h" +#include "llhudmanager.h" +#include "llimview.h" +#include "llinventory.h" +#include "llinventoryfunctions.h" +#include "llmutelist.h" +#include "llrecentpeople.h" +#include "llviewerobjectlist.h" +#include "llvoavatarself.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; + +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 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; +} + +// static +bool LLGiveInventory::isInventoryGiveAcceptable(const LLInventoryItem* item) +{ + if (!item) return false; + + if (!isAgentAvatarValid()) return false; + + if (!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgentID)) + { + 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: + { + BOOL copyable = false; + if (item->getPermissions().allowCopyBy(gAgentID)) copyable = true; + + if (!copyable && gAgentWearables.isWearingItem(item->getUUID())) + { + acceptable = false; + } + } + break; + default: + break; + } + return acceptable; +} + +// static +bool LLGiveInventory::isInventoryGroupGiveAcceptable(const LLInventoryItem* item) +{ + if (!item) return false; + + if (!isAgentAvatarValid()) return false; + + // These permissions are double checked in the simulator in + // LLGroupNoticeInventoryItemFetch::result(). + if (!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgentID)) + { + return false; + } + if (!item->getPermissions().allowCopyBy(gAgent.getID())) + { + return false; + } + + + bool acceptable = true; + switch(item->getType()) + { + case LLAssetType::AT_OBJECT: + if (gAgentAvatarp->isWearingAttachment(item->getUUID())) + { + acceptable = false; + } + break; + default: + break; + } + return acceptable; +} + +// static +void LLGiveInventory::doGiveInventoryItem(const LLUUID& to_agent, + const LLInventoryItem* item, + const LLUUID& im_session_id/* = LLUUID::null*/) + +{ + llinfos << "LLGiveInventory::giveInventory()" << llendl; + if (!isInventoryGiveAcceptable(item)) + { + return; + } + if (item->getPermissions().allowCopyBy(gAgentID)) + { + // just give it away. + LLGiveInventory::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, + &LLGiveInventory::handleCopyProtectedItem); + } +} + +void LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent, + const LLInventoryCategory* cat, + const LLUUID& im_session_id) + +{ + if (!cat) return; + llinfos << "LLGiveInventory::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()) + { + LLGiveInventory::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, &LLGiveInventory::handleCopyProtectedCategory); + } + } +} + +////////////////////////////////////////////////////////////////////////// +// PRIVATE METHODS +////////////////////////////////////////////////////////////////////////// + +//static +void LLGiveInventory::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")); + } + } +} + +// static +bool LLGiveInventory::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) + { + LLGiveInventory::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 LLGiveInventory::commitGiveInventoryItem(const LLUUID& to_agent, + const 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, + gAgentID, + FALSE, + gAgentSessionID, + 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 +bool LLGiveInventory::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) + { + LLGiveInventory::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 LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, + const LLInventoryCategory* cat, + const LLUUID& im_session_id) + +{ + if (!cat) return; + llinfos << "LLGiveInventory::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); + } +} + +// EOF diff --git a/indra/newview/llgiveinventory.h b/indra/newview/llgiveinventory.h new file mode 100644 index 0000000000..38077fcca7 --- /dev/null +++ b/indra/newview/llgiveinventory.h @@ -0,0 +1,99 @@ +/** + * @file llgiveinventory.cpp + * @brief LLGiveInventory class declaration + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * 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 + * + * 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 + * + * 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. + * + * 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$ + */ + +#ifndef LL_LLGIVEINVENTORY_H +#define LL_LLGIVEINVENTORY_H + +class LLInventoryItem; +class LLInventoryCategory; + +/** + * Class represented give inventory related actions. + * + * It has only static methods and is not intended to be instantiated for now. + */ +class LLGiveInventory +{ +public: + /** + * Checks if inventory item you are attempting to transfer to a resident can be given. + * + * @return true if you can give, otherwise false. + */ + static bool isInventoryGiveAcceptable(const LLInventoryItem* item); + + /** + * Checks if inventory item you are attempting to transfer to a group can be given. + * + * @return true if you can give, otherwise false. + */ + static bool isInventoryGroupGiveAcceptable(const LLInventoryItem* item); + + /** + * Gives passed inventory item to specified avatar in specified session. + */ + static void LLGiveInventory::doGiveInventoryItem(const LLUUID& to_agent, + const LLInventoryItem* item, + const LLUUID& im_session_id = LLUUID::null); + + /** + * Gives passed inventory category to specified avatar in specified session. + */ + static void doGiveInventoryCategory(const LLUUID& to_agent, + const LLInventoryCategory* item, + const LLUUID &session_id = LLUUID::null); + +private: + // this class is not intended to be instantiated. + LLGiveInventory(); + + /** + * logs "Inventory item offered" to IM + */ + static void logInventoryOffer(const LLUUID& to_agent, + const LLUUID &im_session_id = LLUUID::null); + + // give inventory item functionality + static bool handleCopyProtectedItem(const LLSD& notification, const LLSD& response); + static void commitGiveInventoryItem(const LLUUID& to_agent, + const LLInventoryItem* item, + const LLUUID &im_session_id = LLUUID::null); + + // give inventory category functionality + static bool handleCopyProtectedCategory(const LLSD& notification, const LLSD& response); + static void commitGiveInventoryCategory(const LLUUID& to_agent, + const LLInventoryCategory* cat, + const LLUUID &im_session_id = LLUUID::null); + +}; + +#endif // LL_LLGIVEINVENTORY_H diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index ab7eeae3e8..2c59cee2ee 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -47,6 +47,7 @@ #include "llfloaterworldmap.h" #include "llfriendcard.h" #include "llgesturemgr.h" +#include "llgiveinventory.h" #include "llimfloater.h" #include "llimview.h" #include "llinventoryclipboard.h" @@ -3755,7 +3756,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, rv = TRUE; if(drop) { - LLToolDragAndDrop::giveInventory(item->getCreatorUUID(), + LLGiveInventory::doGiveInventoryItem(item->getCreatorUUID(), (LLInventoryItem*)cargo_data); } } @@ -3776,7 +3777,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, rv = TRUE; if(drop) { - LLToolDragAndDrop::giveInventoryCategory( + LLGiveInventory::doGiveInventoryCategory( item->getCreatorUUID(), inv_cat); } diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 362d8581f3..42ff514f09 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -44,7 +44,6 @@ #include "llfloaterinventory.h" #include "llagent.h" #include "llagentui.h" -#include "lltooldraganddrop.h" #include "lllineeditor.h" #include "lltexteditor.h" @@ -60,6 +59,7 @@ #include "llviewerwindow.h" #include "llviewermessage.h" #include "llnotificationsutil.h" +#include "llgiveinventory.h" static LLRegisterPanelClassWrapper<LLPanelGroupNotices> t_panel_group_notices("panel_group_notices"); @@ -162,7 +162,7 @@ BOOL LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, { LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data; if(gInventory.getItem(inv_item->getUUID()) - && LLToolDragAndDrop::isInventoryGroupGiveAcceptable(inv_item)) + && LLGiveInventory::isInventoryGroupGiveAcceptable(inv_item)) { // *TODO: get multiple object transfers working *accept = ACCEPT_YES_COPY_SINGLE; diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 774626f19d..8a8bdd2dba 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -38,7 +38,6 @@ // project headers #include "llagent.h" #include "llagentcamera.h" -#include "llagentui.h" #include "llagentwearables.h" #include "llappearancemgr.h" #include "lldictionary.h" @@ -46,31 +45,26 @@ #include "llfloaterreg.h" #include "llfloatertools.h" #include "llgesturemgr.h" +#include "llgiveinventory.h" #include "llhudmanager.h" #include "llhudeffecttrail.h" -#include "llimview.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)) @@ -145,29 +139,6 @@ 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: @@ -195,43 +166,6 @@ bool LLDropCopyableItems::operator()( return allowed; } -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; -} - // 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. @@ -1419,422 +1353,6 @@ 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) @@ -1928,13 +1446,13 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_ { LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data; if (gInventory.getItem(inv_item->getUUID()) - && LLToolDragAndDrop::isInventoryGiveAcceptable(inv_item)) + && LLGiveInventory::isInventoryGiveAcceptable(inv_item)) { // *TODO: get multiple object transfers working *accept = ACCEPT_YES_COPY_SINGLE; if (drop) { - LLToolDragAndDrop::giveInventory(dest_agent, inv_item, session_id); + LLGiveInventory::doGiveInventoryItem(dest_agent, inv_item, session_id); } } else @@ -1956,7 +1474,7 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_ *accept = ACCEPT_YES_COPY_SINGLE; if (drop) { - LLToolDragAndDrop::giveInventoryCategory(dest_agent, inv_cat, session_id); + LLGiveInventory::doGiveInventoryCategory(dest_agent, inv_cat, session_id); } } else @@ -2633,7 +2151,7 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventoryObject( { if (drop) { - giveInventory(obj->getID(), item ); + LLGiveInventory::doGiveInventoryItem(obj->getID(), item ); } // *TODO: deal with all the issues surrounding multi-object // inventory transfers. @@ -2653,13 +2171,13 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventory( LLViewerInventoryCategory* cat; locateInventory(item, cat); if (!item || !item->isFinished()) return ACCEPT_NO; - if (!isInventoryGiveAcceptable(item)) + if (!LLGiveInventory::isInventoryGiveAcceptable(item)) { return ACCEPT_NO; } if (drop && obj) { - giveInventory(obj->getID(), item); + LLGiveInventory::doGiveInventoryItem(obj->getID(), item); } // *TODO: deal with all the issues surrounding multi-object // inventory transfers. @@ -2676,7 +2194,7 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventoryCategory( LLViewerInventoryCategory* cat; locateInventory(item, cat); if (!cat) return ACCEPT_NO; - giveInventoryCategory(obj->getID(), cat); + LLGiveInventory::doGiveInventoryCategory(obj->getID(), cat); } // *TODO: deal with all the issues surrounding multi-object // inventory transfers. diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 85d003e5fc..18334b5ee1 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -214,32 +214,10 @@ protected: LLToolDragAndDrop::ESource source, const LLUUID& src_id); - - // give inventory item functionality - static bool handleCopyProtectedItem(const LLSD& notification, const LLSD& response); - static void commitGiveInventoryItem(const LLUUID& to_agent, - LLInventoryItem* item, - const LLUUID &im_session_id = LLUUID::null); - - // give inventory category functionality - static bool handleCopyProtectedCategory(const LLSD& notification, const LLSD& response); - static void commitGiveInventoryCategory(const LLUUID& to_agent, - LLInventoryCategory* cat, - const LLUUID &im_session_id = LLUUID::null); - - // log "Inventory item offered" to IM - static void logInventoryOffer(const LLUUID& to_agent, - const LLUUID &im_session_id = LLUUID::null); - public: // helper functions static BOOL isInventoryDropAcceptable(LLViewerObject* obj, LLInventoryItem* item) { return (ACCEPT_YES_COPY_SINGLE <= willObjectAcceptInventory(obj, item)); } - // This simple helper function assumes you are attempting to - // transfer item. returns true if you can give, otherwise false. - static BOOL isInventoryGiveAcceptable(LLInventoryItem* item); - static BOOL isInventoryGroupGiveAcceptable(LLInventoryItem* item); - BOOL dadUpdateInventory(LLViewerObject* obj, BOOL drop); BOOL dadUpdateInventoryCategory(LLViewerObject* obj, BOOL drop); @@ -265,13 +243,6 @@ public: ESource source, const LLUUID& src_id); - static void giveInventory(const LLUUID& to_agent, - LLInventoryItem* item, - const LLUUID &session_id = LLUUID::null); - static void giveInventoryCategory(const LLUUID& to_agent, - LLInventoryCategory* item, - const LLUUID &session_id = LLUUID::null); - static bool handleGiveDragAndDrop(LLUUID agent, LLUUID session, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, |