lltooldraganddrop.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:78k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lltooldraganddrop.cpp
  3.  * @brief LLToolDragAndDrop class implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "lltooldraganddrop.h"
  34. // library headers
  35. #include "llnotificationsutil.h"
  36. // project headers
  37. #include "llagent.h"
  38. #include "llagentui.h"
  39. #include "llagentwearables.h"
  40. #include "llappearancemgr.h"
  41. #include "lldictionary.h"
  42. //#include "llfirstuse.h"
  43. #include "llfloaterreg.h"
  44. #include "llfloatertools.h"
  45. #include "llgesturemgr.h"
  46. #include "llhudmanager.h"
  47. #include "llhudeffecttrail.h"
  48. #include "llimview.h"
  49. #include "llinventorybridge.h"
  50. #include "llmutelist.h"
  51. #include "llpreviewnotecard.h"
  52. #include "llrecentpeople.h"
  53. #include "llrootview.h"
  54. #include "llselectmgr.h"
  55. #include "lltoolmgr.h"
  56. #include "lltooltip.h"
  57. #include "lltrans.h"
  58. #include "llviewerobjectlist.h"
  59. #include "llviewerstats.h"
  60. #include "llviewerwindow.h"
  61. #include "llvoavatarself.h"
  62. #include "llworld.h"
  63. // MAX ITEMS is based on (sizeof(uuid)+2) * count must be < MTUBYTES
  64. // or 18 * count < 1200 => count < 1200/18 => 66. I've cut it down a
  65. // bit from there to give some pad.
  66. const S32 MAX_ITEMS = 42;
  67. // syntactic sugar
  68. #define callMemberFunction(object,ptrToMember)  ((object).*(ptrToMember))
  69. class LLNoPreferredType : public LLInventoryCollectFunctor
  70. {
  71. public:
  72. LLNoPreferredType() {}
  73. virtual ~LLNoPreferredType() {}
  74. virtual bool operator()(LLInventoryCategory* cat,
  75. LLInventoryItem* item)
  76. {
  77. if(cat && (cat->getPreferredType() == LLFolderType::FT_NONE))
  78. {
  79. return true;
  80. }
  81. return false;
  82. }
  83. };
  84. class LLNoPreferredTypeOrItem : public LLInventoryCollectFunctor
  85. {
  86. public:
  87. LLNoPreferredTypeOrItem() {}
  88. virtual ~LLNoPreferredTypeOrItem() {}
  89. virtual bool operator()(LLInventoryCategory* cat,
  90. LLInventoryItem* item)
  91. {
  92. if(item) return true;
  93. if(cat && (cat->getPreferredType() == LLFolderType::FT_NONE))
  94. {
  95. return true;
  96. }
  97. return false;
  98. }
  99. };
  100. class LLDroppableItem : public LLInventoryCollectFunctor
  101. {
  102. public:
  103. LLDroppableItem(BOOL is_transfer) :
  104. mCountLosing(0), mIsTransfer(is_transfer) {}
  105. virtual ~LLDroppableItem() {}
  106. virtual bool operator()(LLInventoryCategory* cat,
  107. LLInventoryItem* item);
  108. S32 countNoCopy() const { return mCountLosing; }
  109. protected:
  110. S32 mCountLosing;
  111. BOOL mIsTransfer;
  112. };
  113. bool LLDroppableItem::operator()(LLInventoryCategory* cat,
  114.  LLInventoryItem* item)
  115. {
  116. bool allowed = false;
  117. if(item)
  118. {
  119. allowed = itemTransferCommonlyAllowed(item);
  120. if(allowed
  121.    && mIsTransfer
  122.    && !item->getPermissions().allowOperationBy(PERM_TRANSFER,
  123.        gAgent.getID()))
  124. {
  125. allowed = false;
  126. }
  127. if(allowed && !item->getPermissions().allowCopyBy(gAgent.getID()))
  128. {
  129. ++mCountLosing;
  130. }
  131. }
  132. return allowed;
  133. }
  134. class LLUncopyableItems : public LLInventoryCollectFunctor
  135. {
  136. public:
  137. LLUncopyableItems() {}
  138. virtual ~LLUncopyableItems() {}
  139. virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
  140. };
  141. bool LLUncopyableItems::operator()(LLInventoryCategory* cat,
  142.    LLInventoryItem* item)
  143. {
  144. bool uncopyable = false;
  145. if(item)
  146. {
  147. if (itemTransferCommonlyAllowed(item) &&
  148.    !item->getPermissions().allowCopyBy(gAgent.getID()))
  149. {
  150. uncopyable = true;
  151. }
  152. }
  153. return uncopyable;
  154. }
  155. class LLDropCopyableItems : public LLInventoryCollectFunctor
  156. {
  157. public:
  158. LLDropCopyableItems() {}
  159. virtual ~LLDropCopyableItems() {}
  160. virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
  161. };
  162. bool LLDropCopyableItems::operator()(
  163. LLInventoryCategory* cat,
  164. LLInventoryItem* item)
  165. {
  166. bool allowed = false;
  167. if(item)
  168. {
  169. allowed = itemTransferCommonlyAllowed(item);
  170. if(allowed &&
  171.    !item->getPermissions().allowCopyBy(gAgent.getID()))
  172. {
  173. // whoops, can't copy it - don't allow it.
  174. allowed = false;
  175. }
  176. }
  177. return allowed;
  178. }
  179. class LLGiveable : public LLInventoryCollectFunctor
  180. {
  181. public:
  182. LLGiveable() : mCountLosing(0) {}
  183. virtual ~LLGiveable() {}
  184. virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
  185. S32 countNoCopy() const { return mCountLosing; }
  186. protected:
  187. S32 mCountLosing;
  188. };
  189. bool LLGiveable::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
  190. {
  191. // All categories can be given.
  192. if (cat)
  193. return true;
  194. bool allowed = false;
  195. if(item)
  196. {
  197. allowed = itemTransferCommonlyAllowed(item);
  198. if(allowed &&
  199.    !item->getPermissions().allowOperationBy(PERM_TRANSFER,
  200.     gAgent.getID()))
  201. {
  202. allowed = FALSE;
  203. }
  204. if(allowed &&
  205.    !item->getPermissions().allowCopyBy(gAgent.getID()))
  206. {
  207. ++mCountLosing;
  208. }
  209. }
  210. return allowed;
  211. }
  212. class LLCategoryFireAndForget : public LLInventoryFetchComboObserver
  213. {
  214. public:
  215. LLCategoryFireAndForget() {}
  216. ~LLCategoryFireAndForget() {}
  217. virtual void done()
  218. {
  219. /* no-op: it's fire n forget right? */
  220. lldebugs << "LLCategoryFireAndForget::done()" << llendl;
  221. }
  222. };
  223. class LLCategoryDropObserver : public LLInventoryFetchObserver
  224. {
  225. public:
  226. LLCategoryDropObserver(
  227. const LLUUID& obj_id, LLToolDragAndDrop::ESource src) :
  228. mObjectID(obj_id),
  229. mSource(src)
  230. {}
  231. ~LLCategoryDropObserver() {}
  232. virtual void done();
  233. protected:
  234. LLUUID mObjectID;
  235. LLToolDragAndDrop::ESource mSource;
  236. };
  237. void LLCategoryDropObserver::done()
  238. {
  239. gInventory.removeObserver(this);
  240. LLViewerObject* dst_obj = gObjectList.findObject(mObjectID);
  241. if(dst_obj)
  242. {
  243. // *FIX: coalesce these...
  244.   LLInventoryItem* item = NULL;
  245.    item_ref_t::iterator it = mComplete.begin();
  246.    item_ref_t::iterator end = mComplete.end();
  247.    for(; it < end; ++it)
  248.    {
  249.   item = gInventory.getItem(*it);
  250.   if(item)
  251.   {
  252.   LLToolDragAndDrop::dropInventory(
  253.   dst_obj,
  254.   item,
  255.   mSource,
  256.   LLUUID::null);
  257.   }
  258.    }
  259. }
  260. delete this;
  261. }
  262. class LLCategoryDropDescendentsObserver : public LLInventoryFetchDescendentsObserver
  263. {
  264. public:
  265. LLCategoryDropDescendentsObserver(
  266. const LLUUID& obj_id, LLToolDragAndDrop::ESource src) :
  267. mObjectID(obj_id),
  268. mSource(src)
  269. {}
  270. ~LLCategoryDropDescendentsObserver() {}
  271. virtual void done();
  272. protected:
  273. LLUUID mObjectID;
  274. LLToolDragAndDrop::ESource mSource;
  275. };
  276. void LLCategoryDropDescendentsObserver::done()
  277. {
  278. gInventory.removeObserver(this);
  279. folder_ref_t::iterator it = mCompleteFolders.begin();
  280. folder_ref_t::iterator end = mCompleteFolders.end();
  281. LLViewerInventoryCategory::cat_array_t cats;
  282. LLViewerInventoryItem::item_array_t items;
  283. for(; it != end; ++it)
  284. {
  285. gInventory.collectDescendents(
  286. (*it),
  287. cats,
  288. items,
  289. LLInventoryModel::EXCLUDE_TRASH);
  290. }
  291. S32 count = items.count();
  292. if(count)
  293. {
  294. std::set<LLUUID> unique_ids;
  295. for(S32 i = 0; i < count; ++i)
  296. {
  297. unique_ids.insert(items.get(i)->getUUID());
  298. }
  299. LLInventoryFetchObserver::item_ref_t ids;
  300. std::back_insert_iterator<LLInventoryFetchObserver::item_ref_t> copier(ids);
  301. std::copy(unique_ids.begin(), unique_ids.end(), copier);
  302. LLCategoryDropObserver* dropper;
  303. dropper = new LLCategoryDropObserver(mObjectID, mSource);
  304. dropper->fetchItems(ids);
  305. if(dropper->isEverythingComplete())
  306. {
  307. dropper->done();
  308. }
  309. else
  310. {
  311. gInventory.addObserver(dropper);
  312. }
  313. }
  314. delete this;
  315. }
  316. LLToolDragAndDrop::DragAndDropEntry::DragAndDropEntry(dragOrDrop3dImpl f_none,
  317.   dragOrDrop3dImpl f_self,
  318.   dragOrDrop3dImpl f_avatar,
  319.   dragOrDrop3dImpl f_object,
  320.   dragOrDrop3dImpl f_land) :
  321. LLDictionaryEntry("")
  322. {
  323. mFunctions[DT_NONE] = f_none;
  324. mFunctions[DT_SELF] = f_self;
  325. mFunctions[DT_AVATAR] = f_avatar;
  326. mFunctions[DT_OBJECT] = f_object;
  327. mFunctions[DT_LAND] = f_land;
  328. }
  329. LLToolDragAndDrop::dragOrDrop3dImpl LLToolDragAndDrop::LLDragAndDropDictionary::get(EDragAndDropType dad_type, LLToolDragAndDrop::EDropTarget drop_target)
  330. {
  331. const DragAndDropEntry *entry = lookup(dad_type);
  332. if (entry)
  333. {
  334. return (entry->mFunctions[(U8)drop_target]);
  335. }
  336. return &LLToolDragAndDrop::dad3dNULL;
  337. }
  338. LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary()
  339. {
  340.   //         DT_NONE        DT_SELF                     DT_AVATAR                   DT_OBJECT                       DT_LAND
  341. //       |--------------|---------------------------|---------------------------|-------------------------------|--------------|
  342. addEntry(DAD_NONE,  new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL));
  343. addEntry(DAD_TEXTURE,  new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dTextureObject, &LLToolDragAndDrop::dad3dNULL));
  344. addEntry(DAD_SOUND,  new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
  345. addEntry(DAD_CALLINGCARD,  new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory,  &LLToolDragAndDrop::dad3dUpdateInventory,  &LLToolDragAndDrop::dad3dNULL));
  346. addEntry(DAD_LANDMARK,  new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,  &LLToolDragAndDrop::dad3dNULL,  &LLToolDragAndDrop::dad3dGiveInventory,  &LLToolDragAndDrop::dad3dUpdateInventory,  &LLToolDragAndDrop::dad3dNULL));
  347. addEntry(DAD_SCRIPT,  new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,  &LLToolDragAndDrop::dad3dNULL,  &LLToolDragAndDrop::dad3dGiveInventory,  &LLToolDragAndDrop::dad3dRezScript,  &LLToolDragAndDrop::dad3dNULL));
  348. addEntry(DAD_CLOTHING,  new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,  &LLToolDragAndDrop::dad3dWearItem,  &LLToolDragAndDrop::dad3dGiveInventory,  &LLToolDragAndDrop::dad3dUpdateInventory,  &LLToolDragAndDrop::dad3dNULL));
  349. addEntry(DAD_OBJECT,  new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,  &LLToolDragAndDrop::dad3dRezAttachmentFromInv, &LLToolDragAndDrop::dad3dGiveInventoryObject, &LLToolDragAndDrop::dad3dRezObjectOnObject,  &LLToolDragAndDrop::dad3dRezObjectOnLand));
  350. addEntry(DAD_NOTECARD,  new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,  &LLToolDragAndDrop::dad3dNULL,  &LLToolDragAndDrop::dad3dGiveInventory,  &LLToolDragAndDrop::dad3dUpdateInventory,  &LLToolDragAndDrop::dad3dNULL));
  351. addEntry(DAD_CATEGORY,  new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,  &LLToolDragAndDrop::dad3dWearCategory, &LLToolDragAndDrop::dad3dGiveInventoryCategory,&LLToolDragAndDrop::dad3dUpdateInventoryCategory, &LLToolDragAndDrop::dad3dNULL));
  352. addEntry(DAD_ROOT_CATEGORY, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL));
  353. addEntry(DAD_BODYPART,  new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearItem, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
  354. addEntry(DAD_ANIMATION,  new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
  355. addEntry(DAD_GESTURE,  new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dActivateGesture, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
  356. addEntry(DAD_LINK,  new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL));
  357. // TODO: animation on self could play it?  edit it?
  358. // TODO: gesture on self could play it?  edit it?
  359. };
  360. LLToolDragAndDrop::LLToolDragAndDrop()
  361. :  LLTool(std::string("draganddrop"), NULL),
  362.  mDragStartX(0),
  363.  mDragStartY(0),
  364.  mSource(SOURCE_AGENT),
  365.  mCursor(UI_CURSOR_NO),
  366.  mLastAccept(ACCEPT_NO),
  367.  mDrop(FALSE),
  368.  mCurItemIndex(0)
  369. {
  370. }
  371. void LLToolDragAndDrop::setDragStart(S32 x, S32 y)
  372. {
  373. mDragStartX = x;
  374. mDragStartY = y;
  375. }
  376. BOOL LLToolDragAndDrop::isOverThreshold(S32 x,S32 y)
  377. {
  378. const S32 MIN_MANHATTAN_DIST = 3;
  379. S32 manhattan_dist = llabs( x - mDragStartX ) + llabs( y - mDragStartY );
  380. return manhattan_dist >= MIN_MANHATTAN_DIST;
  381. }
  382. void LLToolDragAndDrop::beginDrag(EDragAndDropType type,
  383.   const LLUUID& cargo_id,
  384.   ESource source,
  385.   const LLUUID& source_id,
  386.   const LLUUID& object_id)
  387. {
  388. if(type == DAD_NONE)
  389. {
  390. llwarns << "Attempted to start drag without a cargo type" << llendl;
  391. return;
  392. }
  393. mCargoTypes.clear();
  394. mCargoTypes.push_back(type);
  395. mCargoIDs.clear();
  396. mCargoIDs.push_back(cargo_id);
  397. mSource = source;
  398. mSourceID = source_id;
  399. mObjectID = object_id;
  400. setMouseCapture( TRUE );
  401. LLToolMgr::getInstance()->setTransientTool( this );
  402. mCursor = UI_CURSOR_NO;
  403. if((mCargoTypes[0] == DAD_CATEGORY)
  404.    && ((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY)))
  405. {
  406. LLInventoryCategory* cat = gInventory.getCategory(cargo_id);
  407. // go ahead and fire & forget the descendents if we are not
  408. // dragging a protected folder.
  409. if(cat)
  410. {
  411. LLViewerInventoryCategory::cat_array_t cats;
  412. LLViewerInventoryItem::item_array_t items;
  413. LLNoPreferredTypeOrItem is_not_preferred;
  414. LLInventoryFetchComboObserver::folder_ref_t folder_ids;
  415. LLInventoryFetchComboObserver::item_ref_t item_ids;
  416. if(is_not_preferred(cat, NULL))
  417. {
  418. folder_ids.push_back(cargo_id);
  419. }
  420. gInventory.collectDescendentsIf(
  421. cargo_id,
  422. cats,
  423. items,
  424. LLInventoryModel::EXCLUDE_TRASH,
  425. is_not_preferred);
  426. S32 count = cats.count();
  427. S32 i;
  428. for(i = 0; i < count; ++i)
  429. {
  430. folder_ids.push_back(cats.get(i)->getUUID());
  431. }
  432. count = items.count();
  433. for(i = 0; i < count; ++i)
  434. {
  435. item_ids.push_back(items.get(i)->getUUID());
  436. }
  437. if(!folder_ids.empty() || !item_ids.empty())
  438. {
  439. LLCategoryFireAndForget fetcher;
  440. fetcher.fetch(folder_ids, item_ids);
  441. }
  442. }
  443. }
  444. }
  445. void LLToolDragAndDrop::beginMultiDrag(
  446. const std::vector<EDragAndDropType> types,
  447. const std::vector<LLUUID>& cargo_ids,
  448. ESource source,
  449. const LLUUID& source_id)
  450. {
  451. // assert on public api is evil
  452. //llassert( type != DAD_NONE );
  453. std::vector<EDragAndDropType>::const_iterator types_it;
  454. for (types_it = types.begin(); types_it != types.end(); ++types_it)
  455. {
  456. if(DAD_NONE == *types_it)
  457. {
  458. llwarns << "Attempted to start drag without a cargo type" << llendl;
  459. return;
  460. }
  461. }
  462. mCargoTypes = types;
  463. mCargoIDs = cargo_ids;
  464. mSource = source;
  465. mSourceID = source_id;
  466. setMouseCapture( TRUE );
  467. LLToolMgr::getInstance()->setTransientTool( this );
  468. mCursor = UI_CURSOR_NO;
  469. if((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY))
  470. {
  471. // find categories (i.e. inventory folders) in the cargo.
  472. LLInventoryCategory* cat = NULL;
  473. S32 count = llmin(cargo_ids.size(), types.size());
  474. std::set<LLUUID> cat_ids;
  475. for(S32 i = 0; i < count; ++i)
  476. {
  477. cat = gInventory.getCategory(cargo_ids[i]);
  478. if(cat)
  479. {
  480. LLViewerInventoryCategory::cat_array_t cats;
  481. LLViewerInventoryItem::item_array_t items;
  482. LLNoPreferredType is_not_preferred;
  483. if(is_not_preferred(cat, NULL))
  484. {
  485. cat_ids.insert(cat->getUUID());
  486. }
  487. gInventory.collectDescendentsIf(
  488. cat->getUUID(),
  489. cats,
  490. items,
  491. LLInventoryModel::EXCLUDE_TRASH,
  492. is_not_preferred);
  493. S32 cat_count = cats.count();
  494. for(S32 i = 0; i < cat_count; ++i)
  495. {
  496. cat_ids.insert(cat->getUUID());
  497. }
  498. }
  499. }
  500. if(!cat_ids.empty())
  501. {
  502. LLInventoryFetchComboObserver::folder_ref_t folder_ids;
  503. LLInventoryFetchComboObserver::item_ref_t item_ids;
  504. std::back_insert_iterator<LLInventoryFetchDescendentsObserver::folder_ref_t> copier(folder_ids);
  505. std::copy(cat_ids.begin(), cat_ids.end(), copier);
  506. LLCategoryFireAndForget fetcher;
  507. fetcher.fetch(folder_ids, item_ids);
  508. }
  509. }
  510. }
  511. void LLToolDragAndDrop::endDrag()
  512. {
  513. mEndDragSignal();
  514. LLSelectMgr::getInstance()->unhighlightAll();
  515. setMouseCapture(FALSE);
  516. }
  517. void LLToolDragAndDrop::onMouseCaptureLost()
  518. {
  519. // Called whenever the drag ends or if mouse capture is simply lost
  520. LLToolMgr::getInstance()->clearTransientTool();
  521. mCargoTypes.clear();
  522. mCargoIDs.clear();
  523. mSource = SOURCE_AGENT;
  524. mSourceID.setNull();
  525. mObjectID.setNull();
  526. }
  527. BOOL LLToolDragAndDrop::handleMouseUp( S32 x, S32 y, MASK mask )
  528. {
  529. if( hasMouseCapture() )
  530. {
  531. EAcceptance acceptance = ACCEPT_NO;
  532. dragOrDrop( x, y, mask, TRUE, &acceptance );
  533. endDrag();
  534. }
  535. return TRUE;
  536. }
  537. ECursorType LLToolDragAndDrop::acceptanceToCursor( EAcceptance acceptance )
  538. {
  539. switch( acceptance )
  540. {
  541. case ACCEPT_YES_MULTI:
  542. if (mCargoIDs.size() > 1)
  543. {
  544. mCursor = UI_CURSOR_ARROWDRAGMULTI;
  545. }
  546. else
  547. {
  548. mCursor = UI_CURSOR_ARROWDRAG;
  549. }
  550. break;
  551. case ACCEPT_YES_SINGLE:
  552. if (mCargoIDs.size() > 1)
  553. {
  554. mToolTipMsg = LLTrans::getString("TooltipMustSingleDrop");
  555. mCursor = UI_CURSOR_NO;
  556. }
  557. else
  558. {
  559. mCursor = UI_CURSOR_ARROWDRAG;
  560. }
  561. break;
  562. case ACCEPT_NO_LOCKED:
  563. mCursor = UI_CURSOR_NOLOCKED;
  564. break;
  565. case ACCEPT_NO:
  566. mCursor = UI_CURSOR_NO;
  567. break;
  568. case ACCEPT_YES_COPY_MULTI:
  569. if (mCargoIDs.size() > 1)
  570. {
  571. mCursor = UI_CURSOR_ARROWCOPYMULTI;
  572. }
  573. else
  574. {
  575. mCursor = UI_CURSOR_ARROWCOPY;
  576. }
  577. break;
  578. case ACCEPT_YES_COPY_SINGLE:
  579. if (mCargoIDs.size() > 1)
  580. {
  581. mToolTipMsg = LLTrans::getString("TooltipMustSingleDrop");
  582. mCursor = UI_CURSOR_NO;
  583. }
  584. else
  585. {
  586. mCursor = UI_CURSOR_ARROWCOPY;
  587. }
  588. break;
  589. case ACCEPT_POSTPONED:
  590. break;
  591. default:
  592. llassert( FALSE );
  593. }
  594. return mCursor;
  595. }
  596. BOOL LLToolDragAndDrop::handleHover( S32 x, S32 y, MASK mask )
  597. {
  598. EAcceptance acceptance = ACCEPT_NO;
  599. dragOrDrop( x, y, mask, FALSE, &acceptance );
  600. ECursorType cursor = acceptanceToCursor(acceptance);
  601. gViewerWindow->getWindow()->setCursor( cursor );
  602. lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolDragAndDrop" << llendl;
  603. return TRUE;
  604. }
  605. BOOL LLToolDragAndDrop::handleKey(KEY key, MASK mask)
  606. {
  607. if (key == KEY_ESCAPE)
  608. {
  609. // cancel drag and drop operation
  610. endDrag();
  611. return TRUE;
  612. }
  613. return FALSE;
  614. }
  615. BOOL LLToolDragAndDrop::handleToolTip(S32 x, S32 y, MASK mask)
  616. {
  617. if (!mToolTipMsg.empty())
  618. {
  619. LLToolTipMgr::instance().show(LLToolTip::Params()
  620. .message(mToolTipMsg)
  621. .delay_time(gSavedSettings.getF32( "DragAndDropToolTipDelay" )));
  622. return TRUE;
  623. }
  624. return FALSE;
  625. }
  626. void LLToolDragAndDrop::handleDeselect()
  627. {
  628. mToolTipMsg.clear();
  629. }
  630. // protected
  631. void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, 
  632.    EAcceptance* acceptance)
  633. {
  634. *acceptance = ACCEPT_YES_MULTI;
  635. BOOL handled = FALSE;
  636. LLView* top_view = gFocusMgr.getTopCtrl();
  637. LLViewerInventoryItem* item;
  638. LLViewerInventoryCategory* cat;
  639. mToolTipMsg.clear();
  640. if(top_view)
  641. {
  642. handled = TRUE;
  643. for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
  644. {
  645. LLInventoryObject* cargo = locateInventory(item, cat);
  646. if (cargo)
  647. {
  648. S32 local_x, local_y;
  649. top_view->screenPointToLocal( x, y, &local_x, &local_y );
  650. EAcceptance item_acceptance = ACCEPT_NO;
  651. handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE,
  652. mCargoTypes[mCurItemIndex],
  653. (void*)cargo,
  654. &item_acceptance,
  655. mToolTipMsg);
  656. if (handled)
  657. {
  658. // use sort order to determine priority of acceptance
  659. *acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance);
  660. }
  661. }
  662. else
  663. {
  664. return;
  665. }
  666. }
  667. // all objects passed, go ahead and perform drop if necessary
  668. if (handled && drop && (U32)*acceptance >= ACCEPT_YES_COPY_SINGLE)
  669. {
  670. if ((U32)*acceptance < ACCEPT_YES_COPY_MULTI &&
  671.     mCargoIDs.size() > 1)
  672. {
  673. // tried to give multi-cargo to a single-acceptor - refuse and return.
  674. *acceptance = ACCEPT_NO;
  675. return;
  676. }
  677. for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
  678. {
  679. LLInventoryObject* cargo = locateInventory(item, cat);
  680. if (cargo)
  681. {
  682. S32 local_x, local_y;
  683. EAcceptance item_acceptance;
  684. top_view->screenPointToLocal( x, y, &local_x, &local_y );
  685. handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, TRUE,
  686. mCargoTypes[mCurItemIndex],
  687. (void*)cargo,
  688. &item_acceptance,
  689. mToolTipMsg);
  690. }
  691. }
  692. }
  693. if (handled)
  694. {
  695. mLastAccept = (EAcceptance)*acceptance;
  696. }
  697. }
  698. if(!handled)
  699. {
  700. handled = TRUE;
  701. LLRootView* root_view = gViewerWindow->getRootView();
  702. for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
  703. {
  704. LLInventoryObject* cargo = locateInventory(item, cat);
  705. // fix for EXT-3191
  706. if (NULL == cargo) return;
  707. EAcceptance item_acceptance = ACCEPT_NO;
  708. handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE,
  709. mCargoTypes[mCurItemIndex],
  710. (void*)cargo,
  711. &item_acceptance,
  712. mToolTipMsg);
  713. if (handled)
  714. {
  715. // use sort order to determine priority of acceptance
  716. *acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance);
  717. }
  718. }
  719. // all objects passed, go ahead and perform drop if necessary
  720. if (handled && drop && (U32)*acceptance > ACCEPT_NO_LOCKED)
  721. {
  722. if ((U32)*acceptance < ACCEPT_YES_COPY_MULTI &&
  723.     mCargoIDs.size() > 1)
  724. {
  725. // tried to give multi-cargo to a single-acceptor - refuse and return.
  726. *acceptance = ACCEPT_NO;
  727. return;
  728. }
  729. for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
  730. {
  731. LLInventoryObject* cargo = locateInventory(item, cat);
  732. if (cargo)
  733. {
  734. EAcceptance item_acceptance;
  735. handled = handled && root_view->handleDragAndDrop(x, y, mask, TRUE,
  736.   mCargoTypes[mCurItemIndex],
  737.   (void*)cargo,
  738.   &item_acceptance,
  739.   mToolTipMsg);
  740. }
  741. }
  742. }
  743. if (handled)
  744. {
  745. mLastAccept = (EAcceptance)*acceptance;
  746. }
  747. }
  748. if ( !handled )
  749. {
  750. dragOrDrop3D( x, y, mask, drop, acceptance );
  751. }
  752. }
  753. void LLToolDragAndDrop::dragOrDrop3D( S32 x, S32 y, MASK mask, BOOL drop, EAcceptance* acceptance )
  754. {
  755. mDrop = drop;
  756. if (mDrop)
  757. {
  758. // don't allow drag and drop onto transparent objects
  759. pick(gViewerWindow->pickImmediate(x, y, FALSE));
  760. }
  761. else
  762. {
  763. // don't allow drag and drop onto transparent objects
  764. gViewerWindow->pickAsync(x, y, mask, pickCallback, FALSE);
  765. }
  766. *acceptance = mLastAccept;
  767. }
  768. void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info)
  769. {
  770. if (getInstance() != NULL)
  771. {
  772. getInstance()->pick(pick_info);
  773. }
  774. }
  775. void LLToolDragAndDrop::pick(const LLPickInfo& pick_info)
  776. {
  777. EDropTarget target = DT_NONE;
  778. S32 hit_face = -1;
  779. LLViewerObject* hit_obj = pick_info.getObject();
  780. LLSelectMgr::getInstance()->unhighlightAll();
  781. // Treat attachments as part of the avatar they are attached to.
  782. if (hit_obj != NULL)
  783. {
  784. // don't allow drag and drop on grass, trees, etc.
  785. if (pick_info.mPickType == LLPickInfo::PICK_FLORA)
  786. {
  787. mCursor = UI_CURSOR_NO;
  788. gViewerWindow->getWindow()->setCursor( mCursor );
  789. return;
  790. }
  791. if (hit_obj->isAttachment() && !hit_obj->isHUDAttachment())
  792. {
  793. LLVOAvatar* avatar = LLVOAvatar::findAvatarFromAttachment( hit_obj );
  794. if( !avatar )
  795. {
  796. mLastAccept = ACCEPT_NO;
  797. mCursor = UI_CURSOR_NO;
  798. gViewerWindow->getWindow()->setCursor( mCursor );
  799. return;
  800. }
  801. hit_obj = avatar;
  802. }
  803. if (hit_obj->isAvatar())
  804. {
  805. if(((LLVOAvatar*) hit_obj)->isSelf())
  806. {
  807. target = DT_SELF;
  808. hit_face = -1;
  809. }
  810. else
  811. {
  812. target = DT_AVATAR;
  813. hit_face = -1;
  814. }
  815. }
  816. else
  817. {
  818. target = DT_OBJECT;
  819. hit_face = pick_info.mObjectFace;
  820. // if any item being dragged will be applied to the object under our cursor
  821. // highlight that object
  822. for (S32 i = 0; i < (S32)mCargoIDs.size(); i++)
  823. {
  824. if (mCargoTypes[i] != DAD_OBJECT || (pick_info.mKeyMask & MASK_CONTROL))
  825. {
  826. LLSelectMgr::getInstance()->highlightObjectAndFamily(hit_obj);
  827. break;
  828. }
  829. }
  830. }
  831. }
  832. else if (pick_info.mPickType == LLPickInfo::PICK_LAND)
  833. {
  834. target = DT_LAND;
  835. hit_face = -1;
  836. }
  837. mLastAccept = ACCEPT_YES_MULTI;
  838. for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
  839. {
  840. const S32 item_index = mCurItemIndex;
  841. const EDragAndDropType dad_type = mCargoTypes[item_index];
  842. // Call the right implementation function
  843. mLastAccept = (EAcceptance)llmin(
  844. (U32)mLastAccept,
  845. (U32)callMemberFunction(*this, 
  846. LLDragAndDropDictionary::instance().get(dad_type, target))
  847. (hit_obj, hit_face, pick_info.mKeyMask, FALSE));
  848. }
  849. if (mDrop && ((U32)mLastAccept >= ACCEPT_YES_COPY_SINGLE))
  850. {
  851. // if target allows multi-drop or there is only one item being dropped, go ahead
  852. if ((mLastAccept >= ACCEPT_YES_COPY_MULTI) || (mCargoIDs.size() == 1))
  853. {
  854. // Target accepts multi, or cargo is a single-drop
  855. for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
  856. {
  857. const S32 item_index = mCurItemIndex;
  858. const EDragAndDropType dad_type = mCargoTypes[item_index];
  859. // Call the right implementation function
  860. (U32)callMemberFunction(*this,
  861. LLDragAndDropDictionary::instance().get(dad_type, target))
  862. (hit_obj, hit_face, pick_info.mKeyMask, TRUE);
  863. }
  864. }
  865. else
  866. {
  867. // Target does not accept multi, but cargo is multi
  868. mLastAccept = ACCEPT_NO;
  869. }
  870. }
  871. ECursorType cursor = acceptanceToCursor( mLastAccept );
  872. gViewerWindow->getWindow()->setCursor( cursor );
  873. mLastHitPos = pick_info.mPosGlobal;
  874. mLastCameraPos = gAgent.getCameraPositionGlobal();
  875. }
  876. // static
  877. BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj,
  878.  LLInventoryItem* item,
  879.  LLToolDragAndDrop::ESource source,
  880.  const LLUUID& src_id)
  881. {
  882. // Always succeed if....
  883. // texture is from the library 
  884. // or already in the contents of the object
  885. if(SOURCE_LIBRARY == source)
  886. {
  887. // dropping a texture from the library always just works.
  888. return TRUE;
  889. }
  890. // In case the inventory has not been updated (e.g. due to some recent operation
  891. // causing a dirty inventory), stall the user while fetching the inventory.
  892. if (hit_obj->isInventoryDirty())
  893. {
  894. hit_obj->fetchInventoryFromServer();
  895. LLSD args;
  896. args["ERROR_MESSAGE"] = "Unable to add texture.nPlease wait a few seconds and try again.";
  897. LLNotificationsUtil::add("ErrorMessage", args);
  898. return FALSE;
  899. }
  900. if (hit_obj->getInventoryItemByAsset(item->getAssetUUID()))
  901. {
  902. // if the asset is already in the object's inventory 
  903. // then it can always be added to a side.
  904. // This saves some work if the task's inventory is already loaded
  905. // and ensures that the texture item is only added once.
  906. return TRUE;
  907. }
  908. if (!item) return FALSE;
  909. LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
  910. if(!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
  911. {
  912. // Check that we can add the texture as inventory to the object
  913. if (willObjectAcceptInventory(hit_obj,item) < ACCEPT_YES_COPY_SINGLE )
  914. {
  915. return FALSE;
  916. }
  917. // make sure the object has the texture in it's inventory.
  918. if(SOURCE_AGENT == source)
  919. {
  920. // Remove the texture from local inventory. The server
  921. // will actually remove the item from agent inventory.
  922. gInventory.deleteObject(item->getUUID());
  923. gInventory.notifyObservers();
  924. }
  925. else if(SOURCE_WORLD == source)
  926. {
  927. // *FIX: if the objects are in different regions, and the
  928. // source region has crashed, you can bypass these
  929. // permissions.
  930. LLViewerObject* src_obj = gObjectList.findObject(src_id);
  931. if(src_obj)
  932. {
  933. src_obj->removeInventory(item->getUUID());
  934. }
  935. else
  936. {
  937. llwarns << "Unable to find source object." << llendl;
  938. return FALSE;
  939. }
  940. }
  941. // Add the texture item to the target object's inventory.
  942. hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
  943.   // TODO: Check to see if adding the item was successful; if not, then
  944. // we should return false here.
  945. }
  946. else if(!item->getPermissions().allowOperationBy(PERM_TRANSFER,
  947.  gAgent.getID()))
  948. {
  949. // Check that we can add the texture as inventory to the object
  950. if (willObjectAcceptInventory(hit_obj,item) < ACCEPT_YES_COPY_SINGLE )
  951. {
  952. return FALSE;
  953. }
  954. // *FIX: may want to make sure agent can paint hit_obj.
  955. // Add the texture item to the target object's inventory.
  956. hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
  957. // Force the object to update its refetch its inventory so it has this texture.
  958. hit_obj->fetchInventoryFromServer();
  959.   // TODO: Check to see if adding the item was successful; if not, then
  960. // we should return false here.
  961. }
  962. return TRUE;
  963. }
  964. void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj,
  965. LLInventoryItem* item,
  966. LLToolDragAndDrop::ESource source,
  967. const LLUUID& src_id)
  968. {
  969. if (!item)
  970. {
  971. llwarns << "LLToolDragAndDrop::dropTextureAllFaces no texture item." << llendl;
  972. return;
  973. }
  974. LLUUID asset_id = item->getAssetUUID();
  975. BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
  976. if(!success)
  977. {
  978. return;
  979. }
  980. LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id);
  981. LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT );
  982. S32 num_faces = hit_obj->getNumTEs();
  983. for( S32 face = 0; face < num_faces; face++ )
  984. {
  985. // update viewer side image in anticipation of update from simulator
  986. hit_obj->setTEImage(face, image);
  987. dialog_refresh_all();
  988. }
  989. // send the update to the simulator
  990. hit_obj->sendTEUpdate();
  991. }
  992. /*
  993. void LLToolDragAndDrop::dropTextureOneFaceAvatar(LLVOAvatar* avatar, S32 hit_face, LLInventoryItem* item)
  994. {
  995. if (hit_face == -1) return;
  996. LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(item->getAssetUUID());
  997. avatar->userSetOptionalTE( hit_face, image);
  998. }
  999. */
  1000. void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj,
  1001.    S32 hit_face,
  1002.    LLInventoryItem* item,
  1003.    LLToolDragAndDrop::ESource source,
  1004.    const LLUUID& src_id)
  1005. {
  1006. if (hit_face == -1) return;
  1007. if (!item)
  1008. {
  1009. llwarns << "LLToolDragAndDrop::dropTextureOneFace no texture item." << llendl;
  1010. return;
  1011. }
  1012. LLUUID asset_id = item->getAssetUUID();
  1013. BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
  1014. if(!success)
  1015. {
  1016. return;
  1017. }
  1018. // update viewer side image in anticipation of update from simulator
  1019. LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id);
  1020. LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT );
  1021. hit_obj->setTEImage(hit_face, image);
  1022. dialog_refresh_all();
  1023. // send the update to the simulator
  1024. hit_obj->sendTEUpdate();
  1025. }
  1026. void LLToolDragAndDrop::dropScript(LLViewerObject* hit_obj,
  1027.    LLInventoryItem* item,
  1028.    BOOL active,
  1029.    ESource source,
  1030.    const LLUUID& src_id)
  1031. {
  1032. // *HACK: In order to resolve SL-22177, we need to block drags
  1033. // from notecards and objects onto other objects.
  1034. if((SOURCE_WORLD == LLToolDragAndDrop::getInstance()->mSource)
  1035.    || (SOURCE_NOTECARD == LLToolDragAndDrop::getInstance()->mSource))
  1036. {
  1037. llwarns << "Call to LLToolDragAndDrop::dropScript() from world"
  1038. << " or notecard." << llendl;
  1039. return;
  1040. }
  1041. if(hit_obj && item)
  1042. {
  1043. LLPointer<LLViewerInventoryItem> new_script = new LLViewerInventoryItem(item);
  1044. if(!item->getPermissions().allowCopyBy(gAgent.getID()))
  1045. {
  1046. if(SOURCE_AGENT == source)
  1047. {
  1048. // Remove the script from local inventory. The server
  1049. // will actually remove the item from agent inventory.
  1050. gInventory.deleteObject(item->getUUID());
  1051. gInventory.notifyObservers();
  1052. }
  1053. else if(SOURCE_WORLD == source)
  1054. {
  1055. // *FIX: if the objects are in different regions, and
  1056. // the source region has crashed, you can bypass
  1057. // these permissions.
  1058. LLViewerObject* src_obj = gObjectList.findObject(src_id);
  1059. if(src_obj)
  1060. {
  1061. src_obj->removeInventory(item->getUUID());
  1062. }
  1063. else
  1064. {
  1065. llwarns << "Unable to find source object." << llendl;
  1066. return;
  1067. }
  1068. }
  1069. }
  1070. hit_obj->saveScript(new_script, active, true);
  1071. gFloaterTools->dirty();
  1072. // VEFFECT: SetScript
  1073. LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
  1074. effectp->setSourceObject(gAgent.getAvatarObject());
  1075. effectp->setTargetObject(hit_obj);
  1076. effectp->setDuration(LL_HUD_DUR_SHORT);
  1077. effectp->setColor(LLColor4U(gAgent.getEffectColor()));
  1078. }
  1079. }
  1080. void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target,
  1081.    BOOL bypass_sim_raycast,
  1082.    BOOL from_task_inventory,
  1083.    BOOL remove_from_inventory)
  1084. {
  1085. LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal(mLastHitPos);
  1086. if (!regionp)
  1087. {
  1088. llwarns << "Couldn't find region to rez object" << llendl;
  1089. return;
  1090. }
  1091. //llinfos << "Rezzing object" << llendl;
  1092. make_ui_sound("UISndObjectRezIn");
  1093. LLViewerInventoryItem* item;
  1094. LLViewerInventoryCategory* cat;
  1095. locateInventory(item, cat);
  1096. if(!item || !item->isComplete()) return;
  1097. //if (regionp
  1098. // && (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX))
  1099. //{
  1100. // LLFirstUse::useSandbox();
  1101. //}
  1102. // check if it cannot be copied, and mark as remove if it is -
  1103. // this will remove the object from inventory after rez. Only
  1104. // bother with this check if we would not normally remove from
  1105. // inventory.
  1106. if(!remove_from_inventory
  1107. && !item->getPermissions().allowCopyBy(gAgent.getID()))
  1108. {
  1109. remove_from_inventory = TRUE;
  1110. }
  1111. // Limit raycast to a single object.  
  1112. // Speeds up server raycast + avoid problems with server ray
  1113. // hitting objects that were clipped by the near plane or culled
  1114. // on the viewer.
  1115. LLUUID ray_target_id;
  1116. if( raycast_target )
  1117. {
  1118. ray_target_id = raycast_target->getID();
  1119. }
  1120. else
  1121. {
  1122. ray_target_id.setNull();
  1123. }
  1124. // Check if it's in the trash.
  1125. bool is_in_trash = false;
  1126. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  1127. if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id))
  1128. {
  1129. is_in_trash = true;
  1130. remove_from_inventory = TRUE;
  1131. }
  1132. LLUUID source_id = from_task_inventory ? mSourceID : LLUUID::null;
  1133. // Select the object only if we're editing.
  1134. BOOL rez_selected = LLToolMgr::getInstance()->inEdit();
  1135. LLVector3 ray_start = regionp->getPosRegionFromGlobal(mLastCameraPos);
  1136. LLVector3 ray_end   = regionp->getPosRegionFromGlobal(mLastHitPos);
  1137. // currently the ray's end point is an approximation,
  1138. // and is sometimes too short (causing failure.)  so we
  1139. // double the ray's length:
  1140. if (bypass_sim_raycast == FALSE)
  1141. {
  1142. LLVector3 ray_direction = ray_start - ray_end;
  1143. ray_end = ray_end - ray_direction;
  1144. }
  1145. // Message packing code should be it's own uninterrupted block
  1146. LLMessageSystem* msg = gMessageSystem;
  1147. if (mSource == SOURCE_NOTECARD)
  1148. {
  1149. msg->newMessageFast(_PREHASH_RezObjectFromNotecard);
  1150. }
  1151. else
  1152. {
  1153. msg->newMessageFast(_PREHASH_RezObject);
  1154. }
  1155. msg->nextBlockFast(_PREHASH_AgentData);
  1156. msg->addUUIDFast(_PREHASH_AgentID,  gAgent.getID());
  1157. msg->addUUIDFast(_PREHASH_SessionID,  gAgent.getSessionID());
  1158. msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
  1159. msg->nextBlock("RezData");
  1160. // if it's being rezzed from task inventory, we need to enable
  1161. // saving it back into the task inventory.
  1162. // *FIX: We can probably compress this to a single byte, since I
  1163. // think folderid == mSourceID. This will be a later
  1164. // optimization.
  1165. msg->addUUIDFast(_PREHASH_FromTaskID, source_id);
  1166. msg->addU8Fast(_PREHASH_BypassRaycast, (U8) bypass_sim_raycast);
  1167. msg->addVector3Fast(_PREHASH_RayStart, ray_start);
  1168. msg->addVector3Fast(_PREHASH_RayEnd, ray_end);
  1169. msg->addUUIDFast(_PREHASH_RayTargetID, ray_target_id );
  1170. msg->addBOOLFast(_PREHASH_RayEndIsIntersection, FALSE);
  1171. msg->addBOOLFast(_PREHASH_RezSelected, rez_selected);
  1172. msg->addBOOLFast(_PREHASH_RemoveItem, remove_from_inventory);
  1173. // deal with permissions slam logic
  1174. pack_permissions_slam(msg, item->getFlags(), item->getPermissions());
  1175. LLUUID folder_id = item->getParentUUID();
  1176. if((SOURCE_LIBRARY == mSource) || (is_in_trash))
  1177. {
  1178. // since it's coming from the library or trash, we want to not
  1179. // 'take' it back to the same place.
  1180. item->setParent(LLUUID::null);
  1181. // *TODO this code isn't working - the parent (FolderID) is still
  1182. // set when the object is "taken".  so code on the "take" side is
  1183. // checking for trash and library as well (llviewermenu.cpp)
  1184. }
  1185. if (mSource == SOURCE_NOTECARD)
  1186. {
  1187. msg->nextBlockFast(_PREHASH_NotecardData);
  1188. msg->addUUIDFast(_PREHASH_NotecardItemID, mSourceID);
  1189. msg->addUUIDFast(_PREHASH_ObjectID, mObjectID);
  1190. msg->nextBlockFast(_PREHASH_InventoryData);
  1191. msg->addUUIDFast(_PREHASH_ItemID, item->getUUID());
  1192. }
  1193. else
  1194. {
  1195. msg->nextBlockFast(_PREHASH_InventoryData);
  1196. item->packMessage(msg);
  1197. }
  1198. msg->sendReliable(regionp->getHost());
  1199. // back out the change. no actual internal changes take place.
  1200. item->setParent(folder_id); 
  1201. // If we're going to select it, get ready for the incoming
  1202. // selected object.
  1203. if (rez_selected)
  1204. {
  1205. LLSelectMgr::getInstance()->deselectAll();
  1206. gViewerWindow->getWindow()->incBusyCount();
  1207. }
  1208. if(remove_from_inventory)
  1209. {
  1210. // Delete it from inventory immediately so that users cannot
  1211. // easily bypass copy protection in laggy situations. If the
  1212. // rez fails, we will put it back on the server.
  1213. gInventory.deleteObject(item->getUUID());
  1214. gInventory.notifyObservers();
  1215. }
  1216. // VEFFECT: DropObject
  1217. LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
  1218. effectp->setSourceObject(gAgent.getAvatarObject());
  1219. effectp->setPositionGlobal(mLastHitPos);
  1220. effectp->setDuration(LL_HUD_DUR_SHORT);
  1221. effectp->setColor(LLColor4U(gAgent.getEffectColor()));
  1222. LLViewerStats::getInstance()->incStat(LLViewerStats::ST_REZ_COUNT);
  1223. }
  1224. void LLToolDragAndDrop::dropInventory(LLViewerObject* hit_obj,
  1225.   LLInventoryItem* item,
  1226.   LLToolDragAndDrop::ESource source,
  1227.   const LLUUID& src_id)
  1228. {
  1229. // *HACK: In order to resolve SL-22177, we need to block drags
  1230. // from notecards and objects onto other objects.
  1231. if((SOURCE_WORLD == LLToolDragAndDrop::getInstance()->mSource)
  1232.    || (SOURCE_NOTECARD == LLToolDragAndDrop::getInstance()->mSource))
  1233. {
  1234. llwarns << "Call to LLToolDragAndDrop::dropInventory() from world"
  1235. << " or notecard." << llendl;
  1236. return;
  1237. }
  1238. LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
  1239. time_t creation_date = time_corrected();
  1240. new_item->setCreationDate(creation_date);
  1241. if(!item->getPermissions().allowCopyBy(gAgent.getID()))
  1242. {
  1243. if(SOURCE_AGENT == source)
  1244. {
  1245. // Remove the inventory item from local inventory. The
  1246. // server will actually remove the item from agent
  1247. // inventory.
  1248. gInventory.deleteObject(item->getUUID());
  1249. gInventory.notifyObservers();
  1250. }
  1251. else if(SOURCE_WORLD == source)
  1252. {
  1253. // *FIX: if the objects are in different regions, and the
  1254. // source region has crashed, you can bypass these
  1255. // permissions.
  1256. LLViewerObject* src_obj = gObjectList.findObject(src_id);
  1257. if(src_obj)
  1258. {
  1259. src_obj->removeInventory(item->getUUID());
  1260. }
  1261. else
  1262. {
  1263. llwarns << "Unable to find source object." << llendl;
  1264. return;
  1265. }
  1266. }
  1267. }
  1268. hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
  1269. if (LLFloaterReg::instanceVisible("build"))
  1270. {
  1271. // *FIX: only show this if panel not expanded?
  1272. LLFloaterReg::showInstance("build", "Content");
  1273. }
  1274. // VEFFECT: AddToInventory
  1275. LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
  1276. effectp->setSourceObject(gAgent.getAvatarObject());
  1277. effectp->setTargetObject(hit_obj);
  1278. effectp->setDuration(LL_HUD_DUR_SHORT);
  1279. effectp->setColor(LLColor4U(gAgent.getEffectColor()));
  1280. gFloaterTools->dirty();
  1281. }
  1282. void LLToolDragAndDrop::giveInventory(const LLUUID& to_agent,
  1283.   LLInventoryItem* item,
  1284.   const LLUUID& im_session_id)
  1285.   
  1286. {
  1287. llinfos << "LLToolDragAndDrop::giveInventory()" << llendl;
  1288. if(!isInventoryGiveAcceptable(item))
  1289. {
  1290. return;
  1291. }
  1292. if(item->getPermissions().allowCopyBy(gAgent.getID()))
  1293. {
  1294. // just give it away.
  1295. LLToolDragAndDrop::commitGiveInventoryItem(to_agent, item, im_session_id);
  1296. }
  1297. else
  1298. {
  1299. // ask if the agent is sure.
  1300. LLSD payload;
  1301. payload["agent_id"] = to_agent;
  1302. payload["item_id"] = item->getUUID();
  1303. LLNotificationsUtil::add("CannotCopyWarning", LLSD(), payload, 
  1304.         &LLToolDragAndDrop::handleCopyProtectedItem);
  1305. }
  1306. }
  1307. // static
  1308. bool LLToolDragAndDrop::handleCopyProtectedItem(const LLSD& notification, const LLSD& response)
  1309. {
  1310. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  1311. LLInventoryItem* item = NULL;
  1312. switch(option)
  1313. {
  1314. case 0:  // "Yes"
  1315. item = gInventory.getItem(notification["payload"]["item_id"].asUUID());
  1316. if(item)
  1317. {
  1318. LLToolDragAndDrop::commitGiveInventoryItem(notification["payload"]["agent_id"].asUUID(),
  1319.    item);
  1320. // delete it for now - it will be deleted on the server
  1321. // quickly enough.
  1322. gInventory.deleteObject(notification["payload"]["item_id"].asUUID());
  1323. gInventory.notifyObservers();
  1324. }
  1325. else
  1326. {
  1327. LLNotificationsUtil::add("CannotGiveItem");
  1328. }
  1329. break;
  1330. default: // no, cancel, whatever, who cares, not yes.
  1331. LLNotificationsUtil::add("TransactionCancelled");
  1332. break;
  1333. }
  1334. return false;
  1335. }
  1336. // static
  1337. void LLToolDragAndDrop::commitGiveInventoryItem(const LLUUID& to_agent,
  1338. LLInventoryItem* item,
  1339. const LLUUID& im_session_id)
  1340. {
  1341. if(!item) return;
  1342. std::string name;
  1343. LLAgentUI::buildFullname(name);
  1344. LLUUID transaction_id;
  1345. transaction_id.generate();
  1346. const S32 BUCKET_SIZE = sizeof(U8) + UUID_BYTES;
  1347. U8 bucket[BUCKET_SIZE];
  1348. bucket[0] = (U8)item->getType();
  1349. memcpy(&bucket[1], &(item->getUUID().mData), UUID_BYTES); /* Flawfinder: ignore */
  1350. pack_instant_message(
  1351. gMessageSystem,
  1352. gAgent.getID(),
  1353. FALSE,
  1354. gAgent.getSessionID(),
  1355. to_agent,
  1356. name,
  1357. item->getName(),
  1358. IM_ONLINE,
  1359. IM_INVENTORY_OFFERED,
  1360. transaction_id,
  1361. 0,
  1362. LLUUID::null,
  1363. gAgent.getPositionAgent(),
  1364. NO_TIMESTAMP,
  1365. bucket,
  1366. BUCKET_SIZE);
  1367. gAgent.sendReliableMessage(); 
  1368. // VEFFECT: giveInventory
  1369. LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
  1370. effectp->setSourceObject(gAgent.getAvatarObject());
  1371. effectp->setTargetObject(gObjectList.findObject(to_agent));
  1372. effectp->setDuration(LL_HUD_DUR_SHORT);
  1373. effectp->setColor(LLColor4U(gAgent.getEffectColor()));
  1374. gFloaterTools->dirty();
  1375. LLMuteList::getInstance()->autoRemove(to_agent, LLMuteList::AR_INVENTORY);
  1376. // If this item was given by drag-and-drop into an IM panel, log this action in the IM panel chat.
  1377. if (im_session_id != LLUUID::null)
  1378. {
  1379. LLSD args;
  1380. gIMMgr->addSystemMessage(im_session_id, "inventory_item_offered", args);
  1381. }
  1382. // add buddy to recent people list
  1383. LLRecentPeople::instance().add(to_agent);
  1384. }
  1385. void LLToolDragAndDrop::giveInventoryCategory(const LLUUID& to_agent,
  1386.   LLInventoryCategory* cat,
  1387.   const LLUUID& im_session_id)
  1388. {
  1389. if(!cat) return;
  1390. llinfos << "LLToolDragAndDrop::giveInventoryCategory() - "
  1391. << cat->getUUID() << llendl;
  1392. LLVOAvatar* my_avatar = gAgent.getAvatarObject();
  1393. if( !my_avatar )
  1394. {
  1395. return;
  1396. }
  1397. // Test out how many items are being given.
  1398. LLViewerInventoryCategory::cat_array_t cats;
  1399. LLViewerInventoryItem::item_array_t items;
  1400. LLGiveable giveable;
  1401. gInventory.collectDescendentsIf(cat->getUUID(),
  1402. cats,
  1403. items,
  1404. LLInventoryModel::EXCLUDE_TRASH,
  1405. giveable);
  1406. S32 count = cats.count();
  1407. bool complete = true;
  1408. for(S32 i = 0; i < count; ++i)
  1409. {
  1410. if(!gInventory.isCategoryComplete(cats.get(i)->getUUID()))
  1411. {
  1412. complete = false;
  1413. break;
  1414. }
  1415. }
  1416. if(!complete)
  1417. {
  1418. LLNotificationsUtil::add("IncompleteInventory");
  1419. return;
  1420. }
  1421.   count = items.count() + cats.count();
  1422.   if(count > MAX_ITEMS)
  1423.    {
  1424. LLNotificationsUtil::add("TooManyItems");
  1425.    return;
  1426.    }
  1427.   else if(count == 0)
  1428.    {
  1429. LLNotificationsUtil::add("NoItems");
  1430.    return;
  1431.    }
  1432. else
  1433. {
  1434. if(0 == giveable.countNoCopy())
  1435. {
  1436. LLToolDragAndDrop::commitGiveInventoryCategory(to_agent, cat, im_session_id);
  1437. }
  1438. else 
  1439. {
  1440. LLSD args;
  1441. args["COUNT"] = llformat("%d",giveable.countNoCopy());
  1442. LLSD payload;
  1443. payload["agent_id"] = to_agent;
  1444. payload["folder_id"] = cat->getUUID();
  1445. LLNotificationsUtil::add("CannotCopyCountItems", args, payload, &LLToolDragAndDrop::handleCopyProtectedCategory);
  1446. }
  1447. }
  1448. }
  1449. // static
  1450. bool LLToolDragAndDrop::handleCopyProtectedCategory(const LLSD& notification, const LLSD& response)
  1451. {
  1452. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  1453. LLInventoryCategory* cat = NULL;
  1454. switch(option)
  1455. {
  1456. case 0:  // "Yes"
  1457. cat = gInventory.getCategory(notification["payload"]["folder_id"].asUUID());
  1458. if(cat)
  1459. {
  1460. LLToolDragAndDrop::commitGiveInventoryCategory(notification["payload"]["agent_id"].asUUID(),
  1461.    cat);
  1462. LLViewerInventoryCategory::cat_array_t cats;
  1463. LLViewerInventoryItem::item_array_t items;
  1464. LLUncopyableItems remove;
  1465. gInventory.collectDescendentsIf(cat->getUUID(),
  1466. cats,
  1467. items,
  1468. LLInventoryModel::EXCLUDE_TRASH,
  1469. remove);
  1470. S32 count = items.count();
  1471. for(S32 i = 0; i < count; ++i)
  1472. {
  1473. gInventory.deleteObject(items.get(i)->getUUID());
  1474. }
  1475. gInventory.notifyObservers();
  1476. }
  1477. else
  1478. {
  1479. LLNotificationsUtil::add("CannotGiveCategory");
  1480. }
  1481. break;
  1482. default: // no, cancel, whatever, who cares, not yes.
  1483. LLNotificationsUtil::add("TransactionCancelled");
  1484. break;
  1485. }
  1486. return false;
  1487. }
  1488. // static
  1489. void LLToolDragAndDrop::commitGiveInventoryCategory(const LLUUID& to_agent,
  1490. LLInventoryCategory* cat,
  1491. const LLUUID& im_session_id)
  1492. {
  1493. if(!cat) return;
  1494. llinfos << "LLToolDragAndDrop::commitGiveInventoryCategory() - "
  1495. << cat->getUUID() << llendl;
  1496. // add buddy to recent people list
  1497. LLRecentPeople::instance().add(to_agent);
  1498. // Test out how many items are being given.
  1499. LLViewerInventoryCategory::cat_array_t cats;
  1500. LLViewerInventoryItem::item_array_t items;
  1501. LLGiveable giveable;
  1502. gInventory.collectDescendentsIf(cat->getUUID(),
  1503. cats,
  1504. items,
  1505. LLInventoryModel::EXCLUDE_TRASH,
  1506. giveable);
  1507. // MAX ITEMS is based on (sizeof(uuid)+2) * count must be <
  1508. // MTUBYTES or 18 * count < 1200 => count < 1200/18 =>
  1509. // 66. I've cut it down a bit from there to give some pad.
  1510.   S32 count = items.count() + cats.count();
  1511.   if(count > MAX_ITEMS)
  1512.    {
  1513. LLNotificationsUtil::add("TooManyItems");
  1514.    return;
  1515.    }
  1516.   else if(count == 0)
  1517.    {
  1518. LLNotificationsUtil::add("NoItems");
  1519.    return;
  1520.    }
  1521. else
  1522. {
  1523. std::string name;
  1524. LLAgentUI::buildFullname(name);
  1525. LLUUID transaction_id;
  1526. transaction_id.generate();
  1527. S32 bucket_size = (sizeof(U8) + UUID_BYTES) * (count + 1);
  1528. U8* bucket = new U8[bucket_size];
  1529. U8* pos = bucket;
  1530. U8 type = (U8)cat->getType();
  1531. memcpy(pos, &type, sizeof(U8)); /* Flawfinder: ignore */
  1532. pos += sizeof(U8);
  1533. memcpy(pos, &(cat->getUUID()), UUID_BYTES); /* Flawfinder: ignore */
  1534. pos += UUID_BYTES;
  1535. S32 i;
  1536. count = cats.count();
  1537. for(i = 0; i < count; ++i)
  1538. {
  1539. memcpy(pos, &type, sizeof(U8)); /* Flawfinder: ignore */
  1540. pos += sizeof(U8);
  1541. memcpy(pos, &(cats.get(i)->getUUID()), UUID_BYTES); /* Flawfinder: ignore */
  1542. pos += UUID_BYTES;
  1543. }
  1544. count = items.count();
  1545. for(i = 0; i < count; ++i)
  1546. {
  1547. type = (U8)items.get(i)->getType();
  1548. memcpy(pos, &type, sizeof(U8)); /* Flawfinder: ignore */
  1549. pos += sizeof(U8);
  1550. memcpy(pos, &(items.get(i)->getUUID()), UUID_BYTES); /* Flawfinder: ignore */
  1551. pos += UUID_BYTES;
  1552. }
  1553. pack_instant_message(
  1554. gMessageSystem,
  1555. gAgent.getID(),
  1556. FALSE,
  1557. gAgent.getSessionID(),
  1558. to_agent,
  1559. name,
  1560. cat->getName(),
  1561. IM_ONLINE,
  1562. IM_INVENTORY_OFFERED,
  1563. transaction_id,
  1564. 0,
  1565. LLUUID::null,
  1566. gAgent.getPositionAgent(),
  1567. NO_TIMESTAMP,
  1568. bucket,
  1569. bucket_size);
  1570. gAgent.sendReliableMessage();
  1571. delete[] bucket;
  1572. // VEFFECT: giveInventoryCategory
  1573. LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
  1574. effectp->setSourceObject(gAgent.getAvatarObject());
  1575. effectp->setTargetObject(gObjectList.findObject(to_agent));
  1576. effectp->setDuration(LL_HUD_DUR_SHORT);
  1577. effectp->setColor(LLColor4U(gAgent.getEffectColor()));
  1578. gFloaterTools->dirty();
  1579. LLMuteList::getInstance()->autoRemove(to_agent, LLMuteList::AR_INVENTORY);
  1580. // If this item was given by drag-and-drop into an IM panel, log this action in the IM panel chat.
  1581. if (im_session_id != LLUUID::null)
  1582. {
  1583. LLSD args;
  1584. gIMMgr->addSystemMessage(im_session_id, "inventory_item_offered", args);
  1585. }
  1586. }
  1587. }
  1588. // static
  1589. BOOL LLToolDragAndDrop::isInventoryGiveAcceptable(LLInventoryItem* item)
  1590. {
  1591. if(!item)
  1592. {
  1593. return FALSE;
  1594. }
  1595. if(!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
  1596. {
  1597. return FALSE;
  1598. }
  1599. BOOL copyable = FALSE;
  1600. if(item->getPermissions().allowCopyBy(gAgent.getID())) copyable = TRUE;
  1601. LLVOAvatarSelf* my_avatar = gAgent.getAvatarObject();
  1602. if(!my_avatar)
  1603. {
  1604. return FALSE;
  1605. }
  1606. BOOL acceptable = TRUE;
  1607. switch(item->getType())
  1608. {
  1609. case LLAssetType::AT_OBJECT:
  1610. if(my_avatar->isWearingAttachment(item->getUUID()))
  1611. {
  1612. acceptable = FALSE;
  1613. }
  1614. break;
  1615. case LLAssetType::AT_BODYPART:
  1616. case LLAssetType::AT_CLOTHING:
  1617. if(!copyable && gAgentWearables.isWearingItem(item->getUUID()))
  1618. {
  1619. acceptable = FALSE;
  1620. }
  1621. break;
  1622. default:
  1623. break;
  1624. }
  1625. return acceptable;
  1626. }
  1627. // Static
  1628. BOOL LLToolDragAndDrop::isInventoryGroupGiveAcceptable(LLInventoryItem* item)
  1629. {
  1630. if(!item)
  1631. {
  1632. return FALSE;
  1633. }
  1634. // These permissions are double checked in the simulator in
  1635. // LLGroupNoticeInventoryItemFetch::result().
  1636. if(!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
  1637. {
  1638. return FALSE;
  1639. }
  1640. if(!item->getPermissions().allowCopyBy(gAgent.getID()))
  1641. {
  1642. return FALSE;
  1643. }
  1644. LLVOAvatarSelf* my_avatar = gAgent.getAvatarObject();
  1645. if(!my_avatar)
  1646. {
  1647. return FALSE;
  1648. }
  1649. BOOL acceptable = TRUE;
  1650. switch(item->getType())
  1651. {
  1652. case LLAssetType::AT_OBJECT:
  1653. if(my_avatar->isWearingAttachment(item->getUUID()))
  1654. {
  1655. acceptable = FALSE;
  1656. }
  1657. break;
  1658. default:
  1659. break;
  1660. }
  1661. return acceptable;
  1662. }
  1663. // accessor that looks at permissions, copyability, and names of
  1664. // inventory items to determine if a drop would be ok.
  1665. EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item)
  1666. {
  1667. // check the basics
  1668. if (!item || !obj) return ACCEPT_NO;
  1669. // HACK: downcast
  1670. LLViewerInventoryItem* vitem = (LLViewerInventoryItem*)item;
  1671. if (!vitem->isComplete()) return ACCEPT_NO;
  1672. if (vitem->getIsLinkType()) return ACCEPT_NO; // No giving away links
  1673. // deny attempts to drop from an object onto itself. This is to
  1674. // help make sure that drops that are from an object to an object
  1675. // don't have to worry about order of evaluation. Think of this
  1676. // like check for self in assignment.
  1677. if(obj->getID() == item->getParentUUID())
  1678. {
  1679. return ACCEPT_NO;
  1680. }
  1681. //BOOL copy = (perm.allowCopyBy(gAgent.getID(),
  1682. //   gAgent.getGroupID())
  1683. //  && (obj->mPermModify || obj->mFlagAllowInventoryAdd));
  1684. BOOL worn = FALSE;
  1685. LLVOAvatarSelf* my_avatar = NULL;
  1686. switch(item->getType())
  1687. {
  1688. case LLAssetType::AT_OBJECT:
  1689. my_avatar = gAgent.getAvatarObject();
  1690. if(my_avatar && my_avatar->isWearingAttachment(item->getUUID()))
  1691. {
  1692. worn = TRUE;
  1693. }
  1694. break;
  1695. case LLAssetType::AT_BODYPART:
  1696. case LLAssetType::AT_CLOTHING:
  1697. if(gAgentWearables.isWearingItem(item->getUUID()))
  1698. {
  1699. worn = TRUE;
  1700. }
  1701. break;
  1702. default:
  1703. break;
  1704. }
  1705. const LLPermissions& perm = item->getPermissions();
  1706. BOOL modify = (obj->permModify() || obj->flagAllowInventoryAdd());
  1707. BOOL transfer = FALSE;
  1708. if((obj->permYouOwner() && (perm.getOwner() == gAgent.getID()))
  1709.    || perm.allowOperationBy(PERM_TRANSFER, gAgent.getID()))
  1710. {
  1711. transfer = TRUE;
  1712. }
  1713. BOOL volume = (LL_PCODE_VOLUME == obj->getPCode());
  1714. BOOL attached = obj->isAttachment();
  1715. BOOL unrestricted = ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) ? TRUE : FALSE;
  1716. if(attached && !unrestricted)
  1717. {
  1718. return ACCEPT_NO_LOCKED;
  1719. }
  1720. else if(modify && transfer && volume && !worn)
  1721. {
  1722. return ACCEPT_YES_MULTI;
  1723. }
  1724. else if(!modify)
  1725. {
  1726. return ACCEPT_NO_LOCKED;
  1727. }
  1728. return ACCEPT_NO;
  1729. }
  1730. // function used as drag-and-drop handler for simple agent give inventory requests
  1731. //static
  1732. bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_id, BOOL drop,
  1733.   EDragAndDropType cargo_type,
  1734.   void* cargo_data,
  1735.   EAcceptance* accept)
  1736. {
  1737. // check the type
  1738. switch(cargo_type)
  1739. {
  1740. case DAD_TEXTURE:
  1741. case DAD_SOUND:
  1742. case DAD_LANDMARK:
  1743. case DAD_SCRIPT:
  1744. case DAD_OBJECT:
  1745. case DAD_NOTECARD:
  1746. case DAD_CLOTHING:
  1747. case DAD_BODYPART:
  1748. case DAD_ANIMATION:
  1749. case DAD_GESTURE:
  1750. case DAD_CALLINGCARD:
  1751. {
  1752. LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
  1753. if(gInventory.getItem(inv_item->getUUID())
  1754.    && LLToolDragAndDrop::isInventoryGiveAcceptable(inv_item))
  1755. {
  1756. // *TODO: get multiple object transfers working
  1757. *accept = ACCEPT_YES_COPY_SINGLE;
  1758. if(drop)
  1759. {
  1760. LLToolDragAndDrop::giveInventory(dest_agent, inv_item, session_id);
  1761. }
  1762. }
  1763. else
  1764. {
  1765. // It's not in the user's inventory (it's probably
  1766. // in an object's contents), so disallow dragging
  1767. // it here.  You can't give something you don't
  1768. // yet have.
  1769. *accept = ACCEPT_NO;
  1770. }
  1771. break;
  1772. }
  1773. case DAD_CATEGORY:
  1774. {
  1775. LLViewerInventoryCategory* inv_cat = (LLViewerInventoryCategory*)cargo_data;
  1776. if( gInventory.getCategory( inv_cat->getUUID() ) )
  1777. {
  1778. // *TODO: get multiple object transfers working
  1779. *accept = ACCEPT_YES_COPY_SINGLE;
  1780. if(drop)
  1781. {
  1782. LLToolDragAndDrop::giveInventoryCategory(dest_agent, inv_cat, session_id);
  1783. }
  1784. }
  1785. else
  1786. {
  1787. // It's not in the user's inventory (it's probably
  1788. // in an object's contents), so disallow dragging
  1789. // it here.  You can't give something you don't
  1790. // yet have.
  1791. *accept = ACCEPT_NO;
  1792. }
  1793. break;
  1794. }
  1795. default:
  1796. *accept = ACCEPT_NO;
  1797. break;
  1798. }
  1799. return TRUE;
  1800. }
  1801. ///
  1802. /// Methods called in the drag & drop array
  1803. ///
  1804. EAcceptance LLToolDragAndDrop::dad3dNULL(
  1805. LLViewerObject*, S32, MASK, BOOL)
  1806. {
  1807. lldebugs << "LLToolDragAndDrop::dad3dNULL()" << llendl;
  1808. return ACCEPT_NO;
  1809. }
  1810. EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv(
  1811. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  1812. {
  1813. lldebugs << "LLToolDragAndDrop::dad3dRezAttachmentFromInv()" << llendl;
  1814. // must be in the user's inventory
  1815. if(mSource != SOURCE_AGENT && mSource != SOURCE_LIBRARY)
  1816. {
  1817. return ACCEPT_NO;
  1818. }
  1819. LLViewerInventoryItem* item;
  1820. LLViewerInventoryCategory* cat;
  1821. locateInventory(item, cat);
  1822. if(!item || !item->isComplete()) return ACCEPT_NO;
  1823. // must not be in the trash
  1824. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  1825. if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) )
  1826. {
  1827. return ACCEPT_NO;
  1828. }
  1829. // must not be already wearing it
  1830. LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
  1831. if( !avatar || avatar->isWearingAttachment(item->getUUID()) )
  1832. {
  1833. return ACCEPT_NO;
  1834. }
  1835. if( drop )
  1836. {
  1837. if(mSource == SOURCE_LIBRARY)
  1838. {
  1839. LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(0);
  1840. copy_inventory_item(
  1841. gAgent.getID(),
  1842. item->getPermissions().getOwner(),
  1843. item->getUUID(),
  1844. LLUUID::null,
  1845. std::string(),
  1846. cb);
  1847. }
  1848. else
  1849. {
  1850. rez_attachment(item, 0);
  1851. }
  1852. }
  1853. return ACCEPT_YES_SINGLE;
  1854. }
  1855. EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand(
  1856. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  1857. {
  1858. if (mSource == SOURCE_WORLD)
  1859. {
  1860. return dad3dRezFromObjectOnLand(obj, face, mask, drop);
  1861. }
  1862. lldebugs << "LLToolDragAndDrop::dad3dRezObjectOnLand()" << llendl;
  1863. LLViewerInventoryItem* item;
  1864. LLViewerInventoryCategory* cat;
  1865. locateInventory(item, cat);
  1866. if(!item || !item->isComplete()) return ACCEPT_NO;
  1867. LLVOAvatarSelf* my_avatar = gAgent.getAvatarObject();
  1868. if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) )
  1869. {
  1870. return ACCEPT_NO;
  1871. }
  1872. EAcceptance accept;
  1873. BOOL remove_inventory;
  1874. // Get initial settings based on shift key
  1875. if (mask & MASK_SHIFT)
  1876. {
  1877. // For now, always make copy
  1878. //accept = ACCEPT_YES_SINGLE;
  1879. //remove_inventory = TRUE;
  1880. accept = ACCEPT_YES_COPY_SINGLE;
  1881. remove_inventory = FALSE;
  1882. }
  1883. else
  1884. {
  1885. accept = ACCEPT_YES_COPY_SINGLE;
  1886. remove_inventory = FALSE;
  1887. }
  1888. // check if the item can be copied. If not, send that to the sim
  1889. // which will remove the inventory item.
  1890. if(!item->getPermissions().allowCopyBy(gAgent.getID()))
  1891. {
  1892. accept = ACCEPT_YES_SINGLE;
  1893. remove_inventory = TRUE;
  1894. }
  1895. // Check if it's in the trash.
  1896. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  1897. if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id))
  1898. {
  1899. accept = ACCEPT_YES_SINGLE;
  1900. remove_inventory = TRUE;
  1901. }
  1902. if(drop)
  1903. {
  1904. dropObject(obj, TRUE, FALSE, remove_inventory);
  1905. }
  1906. return accept;
  1907. }
  1908. EAcceptance LLToolDragAndDrop::dad3dRezObjectOnObject(
  1909. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  1910. {
  1911. // handle objects coming from object inventory
  1912. if (mSource == SOURCE_WORLD)
  1913. {
  1914. return dad3dRezFromObjectOnObject(obj, face, mask, drop);
  1915. }
  1916. lldebugs << "LLToolDragAndDrop::dad3dRezObjectOnObject()" << llendl;
  1917. LLViewerInventoryItem* item;
  1918. LLViewerInventoryCategory* cat;
  1919. locateInventory(item, cat);
  1920. if(!item || !item->isComplete()) return ACCEPT_NO;
  1921. LLVOAvatarSelf* my_avatar = gAgent.getAvatarObject();
  1922. if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) )
  1923. {
  1924. return ACCEPT_NO;
  1925. }
  1926. if((mask & MASK_CONTROL))
  1927. {
  1928. // *HACK: In order to resolve SL-22177, we need to block drags
  1929. // from notecards and objects onto other objects.
  1930. if(mSource == SOURCE_NOTECARD)
  1931. {
  1932. return ACCEPT_NO;
  1933. }
  1934. EAcceptance rv = willObjectAcceptInventory(obj, item);
  1935. if(drop && (ACCEPT_YES_SINGLE <= rv))
  1936. {
  1937. dropInventory(obj, item, mSource, mSourceID);
  1938. }
  1939. return rv;
  1940. }
  1941. EAcceptance accept;
  1942. BOOL remove_inventory;
  1943. if (mask & MASK_SHIFT)
  1944. {
  1945. // For now, always make copy
  1946. //accept = ACCEPT_YES_SINGLE;
  1947. //remove_inventory = TRUE;
  1948. accept = ACCEPT_YES_COPY_SINGLE;
  1949. remove_inventory = FALSE;
  1950. }
  1951. else
  1952. {
  1953. accept = ACCEPT_YES_COPY_SINGLE;
  1954. remove_inventory = FALSE;
  1955. }
  1956. // check if the item can be copied. If not, send that to the sim
  1957. // which will remove the inventory item.
  1958. if(!item->getPermissions().allowCopyBy(gAgent.getID()))
  1959. {
  1960. accept = ACCEPT_YES_SINGLE;
  1961. remove_inventory = TRUE;
  1962. }
  1963. // Check if it's in the trash.
  1964. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  1965. if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id))
  1966. {
  1967. accept = ACCEPT_YES_SINGLE;
  1968. remove_inventory = TRUE;
  1969. }
  1970. if(drop)
  1971. {
  1972. dropObject(obj, FALSE, FALSE, remove_inventory);
  1973. }
  1974. return accept;
  1975. }
  1976. EAcceptance LLToolDragAndDrop::dad3dRezScript(
  1977. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  1978. {
  1979. lldebugs << "LLToolDragAndDrop::dad3dRezScript()" << llendl;
  1980. // *HACK: In order to resolve SL-22177, we need to block drags
  1981. // from notecards and objects onto other objects.
  1982. if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource))
  1983. {
  1984. return ACCEPT_NO;
  1985. }
  1986. LLViewerInventoryItem* item;
  1987. LLViewerInventoryCategory* cat;
  1988. locateInventory(item, cat);
  1989. if(!item || !item->isComplete()) return ACCEPT_NO;
  1990. EAcceptance rv = willObjectAcceptInventory(obj, item);
  1991. if(drop && (ACCEPT_YES_SINGLE <= rv))
  1992. {
  1993. // rez in the script active by default, rez in inactive if the
  1994. // control key is being held down.
  1995. BOOL active = ((mask & MASK_CONTROL) == 0);
  1996. LLViewerObject* root_object = obj;
  1997. if (obj && obj->getParent())
  1998. {
  1999. LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent();
  2000. if (!parent_obj->isAvatar())
  2001. {
  2002. root_object = parent_obj;
  2003. }
  2004. }
  2005. dropScript(root_object, item, active, mSource, mSourceID);
  2006. }
  2007. return rv;
  2008. }
  2009. EAcceptance LLToolDragAndDrop::dad3dTextureObject(
  2010. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  2011. {
  2012. lldebugs << "LLToolDragAndDrop::dad3dTextureObject()" << llendl;
  2013. // *HACK: In order to resolve SL-22177, we need to block drags
  2014. // from notecards and objects onto other objects.
  2015. if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource))
  2016. {
  2017. return ACCEPT_NO;
  2018. }
  2019. LLViewerInventoryItem* item;
  2020. LLViewerInventoryCategory* cat;
  2021. locateInventory(item, cat);
  2022. if(!item || !item->isComplete()) return ACCEPT_NO;
  2023. EAcceptance rv = willObjectAcceptInventory(obj, item);
  2024. if((mask & MASK_CONTROL))
  2025. {
  2026. if((ACCEPT_YES_SINGLE <= rv) && drop)
  2027. {
  2028. dropInventory(obj, item, mSource, mSourceID);
  2029. }
  2030. return rv;
  2031. }
  2032. if(!obj->permModify())
  2033. {
  2034. return ACCEPT_NO_LOCKED;
  2035. }
  2036. //If texture !copyable don't texture or you'll never get it back.
  2037. if(!item->getPermissions().allowCopyBy(gAgent.getID()))
  2038. {
  2039. return ACCEPT_NO;
  2040. }
  2041. if(drop && (ACCEPT_YES_SINGLE <= rv))
  2042. {
  2043. if((mask & MASK_SHIFT))
  2044. {
  2045. dropTextureAllFaces(obj, item, mSource, mSourceID);
  2046. }
  2047. else
  2048. {
  2049. dropTextureOneFace(obj, face, item, mSource, mSourceID);
  2050. }
  2051. // VEFFECT: SetTexture
  2052. LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
  2053. effectp->setSourceObject(gAgent.getAvatarObject());
  2054. effectp->setTargetObject(obj);
  2055. effectp->setDuration(LL_HUD_DUR_SHORT);
  2056. effectp->setColor(LLColor4U(gAgent.getEffectColor()));
  2057. }
  2058. // enable multi-drop, although last texture will win
  2059. return ACCEPT_YES_MULTI;
  2060. }
  2061. /*
  2062. EAcceptance LLToolDragAndDrop::dad3dTextureSelf(
  2063. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  2064. {
  2065. lldebugs << "LLToolDragAndDrop::dad3dTextureAvatar()" << llendl;
  2066. if(drop)
  2067. {
  2068. if( !(mask & MASK_SHIFT) )
  2069. {
  2070. dropTextureOneFaceAvatar( (LLVOAvatar*)obj, face, (LLInventoryItem*)mCargoData);
  2071. }
  2072. }
  2073. return (mask & MASK_SHIFT) ? ACCEPT_NO : ACCEPT_YES_SINGLE;
  2074. }
  2075. */
  2076. EAcceptance LLToolDragAndDrop::dad3dWearItem(
  2077. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  2078. {
  2079. lldebugs << "LLToolDragAndDrop::dad3dWearItem()" << llendl;
  2080. LLViewerInventoryItem* item;
  2081. LLViewerInventoryCategory* cat;
  2082. locateInventory(item, cat);
  2083. if(!item || !item->isComplete()) return ACCEPT_NO;
  2084. if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY)
  2085. {
  2086. // it's in the agent inventory
  2087. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  2088. if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) )
  2089. {
  2090. return ACCEPT_NO;
  2091. }
  2092. if( drop )
  2093. {
  2094. // Don't wear anything until initial wearables are loaded, can
  2095. // destroy clothing items.
  2096. if (!gAgentWearables.areWearablesLoaded()) 
  2097. {
  2098. LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded");
  2099. return ACCEPT_NO;
  2100. }
  2101. if(mSource == SOURCE_LIBRARY)
  2102. {
  2103. // create item based on that one, and put it on if that
  2104. // was a success.
  2105. LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
  2106. copy_inventory_item(
  2107. gAgent.getID(),
  2108. item->getPermissions().getOwner(),
  2109. item->getUUID(),
  2110. LLUUID::null,
  2111. std::string(),
  2112. cb);
  2113. }
  2114. else
  2115. {
  2116. wear_inventory_item_on_avatar( item );
  2117. }
  2118. }
  2119. return ACCEPT_YES_MULTI;
  2120. }
  2121. else
  2122. {
  2123. // TODO: copy/move item to avatar's inventory and then wear it.
  2124. return ACCEPT_NO;
  2125. }
  2126. }
  2127. EAcceptance LLToolDragAndDrop::dad3dActivateGesture(
  2128. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  2129. {
  2130. lldebugs << "LLToolDragAndDrop::dad3dActivateGesture()" << llendl;
  2131. LLViewerInventoryItem* item;
  2132. LLViewerInventoryCategory* cat;
  2133. locateInventory(item, cat);
  2134. if(!item || !item->isComplete()) return ACCEPT_NO;
  2135. if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY)
  2136. {
  2137. // it's in the agent inventory
  2138. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  2139. if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) )
  2140. {
  2141. return ACCEPT_NO;
  2142. }
  2143. if( drop )
  2144. {
  2145. LLUUID item_id;
  2146. if(mSource == SOURCE_LIBRARY)
  2147. {
  2148. // create item based on that one, and put it on if that
  2149. // was a success.
  2150. LLPointer<LLInventoryCallback> cb = new ActivateGestureCallback();
  2151. copy_inventory_item(
  2152. gAgent.getID(),
  2153. item->getPermissions().getOwner(),
  2154. item->getUUID(),
  2155. LLUUID::null,
  2156. std::string(),
  2157. cb);
  2158. }
  2159. else
  2160. {
  2161. LLGestureManager::instance().activateGesture(item->getUUID());
  2162. gInventory.updateItem(item);
  2163. gInventory.notifyObservers();
  2164. }
  2165. }
  2166. return ACCEPT_YES_MULTI;
  2167. }
  2168. else
  2169. {
  2170. return ACCEPT_NO;
  2171. }
  2172. }
  2173. EAcceptance LLToolDragAndDrop::dad3dWearCategory(
  2174. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  2175. {
  2176. lldebugs << "LLToolDragAndDrop::dad3dWearCategory()" << llendl;
  2177. LLViewerInventoryItem* item;
  2178. LLViewerInventoryCategory* category;
  2179. locateInventory(item, category);
  2180. if(!category) return ACCEPT_NO;
  2181. if (drop)
  2182. {
  2183. // Don't wear anything until initial wearables are loaded, can
  2184. // destroy clothing items.
  2185. if (!gAgentWearables.areWearablesLoaded()) 
  2186. {
  2187. LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded");
  2188. return ACCEPT_NO;
  2189. }
  2190. }
  2191. if(mSource == SOURCE_AGENT)
  2192. {
  2193. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  2194. if( gInventory.isObjectDescendentOf( category->getUUID(), trash_id ) )
  2195. {
  2196. return ACCEPT_NO;
  2197. }
  2198. if(drop)
  2199. {
  2200.     BOOL append = ( (mask & MASK_SHIFT) ? TRUE : FALSE );
  2201. LLAppearanceManager::instance().wearInventoryCategory(category, false, append);
  2202. }
  2203. return ACCEPT_YES_MULTI;
  2204. }
  2205. else if(mSource == SOURCE_LIBRARY)
  2206. {
  2207. if(drop)
  2208. {
  2209. LLAppearanceManager::instance().wearInventoryCategory(category, true, false);
  2210. }
  2211. return ACCEPT_YES_MULTI;
  2212. }
  2213. else
  2214. {
  2215. // TODO: copy/move category to avatar's inventory and then wear it.
  2216. return ACCEPT_NO;
  2217. }
  2218. }
  2219. EAcceptance LLToolDragAndDrop::dad3dUpdateInventory(
  2220. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  2221. {
  2222. lldebugs << "LLToolDragAndDrop::dadUpdateInventory()" << llendl;
  2223. // *HACK: In order to resolve SL-22177, we need to block drags
  2224. // from notecards and objects onto other objects.
  2225. if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource))
  2226. {
  2227. return ACCEPT_NO;
  2228. }
  2229. LLViewerInventoryItem* item;
  2230. LLViewerInventoryCategory* cat;
  2231. locateInventory(item, cat);
  2232. if(!item || !item->isComplete()) return ACCEPT_NO;
  2233. LLViewerObject* root_object = obj;
  2234. if (obj && obj->getParent())
  2235. {
  2236. LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent();
  2237. if (!parent_obj->isAvatar())
  2238. {
  2239. root_object = parent_obj;
  2240. }
  2241. }
  2242. EAcceptance rv = willObjectAcceptInventory(root_object, item);
  2243. if(root_object && drop && (ACCEPT_YES_COPY_SINGLE <= rv))
  2244. {
  2245. dropInventory(root_object, item, mSource, mSourceID);
  2246. }
  2247. return rv;
  2248. }
  2249. BOOL LLToolDragAndDrop::dadUpdateInventory(LLViewerObject* obj, BOOL drop)
  2250. {
  2251. EAcceptance rv = dad3dUpdateInventory(obj, -1, MASK_NONE, drop);
  2252. return (rv >= ACCEPT_YES_COPY_SINGLE);
  2253. }
  2254. EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory(
  2255. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  2256. {
  2257. lldebugs << "LLToolDragAndDrop::dad3dUpdateInventoryCategory()" << llendl;
  2258. if (obj == NULL)
  2259. {
  2260. llwarns << "obj is NULL; aborting func with ACCEPT_NO" << llendl;
  2261. return ACCEPT_NO;
  2262. }
  2263. if ((mSource != SOURCE_AGENT) && (mSource != SOURCE_LIBRARY))
  2264. {
  2265. return ACCEPT_NO;
  2266. }
  2267. if (obj->isAttachment())
  2268. {
  2269. return ACCEPT_NO_LOCKED;
  2270. }
  2271. LLViewerInventoryItem* item = NULL;
  2272. LLViewerInventoryCategory* cat = NULL;
  2273. locateInventory(item, cat);
  2274. if (!cat) 
  2275. {
  2276. return ACCEPT_NO;
  2277. }
  2278. // Find all the items in the category
  2279. LLDroppableItem droppable(!obj->permYouOwner());
  2280. LLInventoryModel::cat_array_t cats;
  2281. LLInventoryModel::item_array_t items;
  2282. gInventory.collectDescendentsIf(cat->getUUID(),
  2283. cats,
  2284. items,
  2285. LLInventoryModel::EXCLUDE_TRASH,
  2286. droppable);
  2287. cats.put(cat);
  2288.   if (droppable.countNoCopy() > 0)
  2289.   {
  2290.   llwarns << "*** Need to confirm this step" << llendl;
  2291.   }
  2292. LLViewerObject* root_object = obj;
  2293. if (obj->getParent())
  2294. {
  2295. LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent();
  2296. if (!parent_obj->isAvatar())
  2297. {
  2298. root_object = parent_obj;
  2299. }
  2300. }
  2301. EAcceptance rv = ACCEPT_NO;
  2302. // Check for accept
  2303. for (LLInventoryModel::cat_array_t::const_iterator cat_iter = cats.begin();
  2304.  cat_iter != cats.end();
  2305.  ++cat_iter)
  2306. {
  2307. const LLViewerInventoryCategory *cat = (*cat_iter);
  2308. rv = gInventory.isCategoryComplete(cat->getUUID()) ? ACCEPT_YES_MULTI : ACCEPT_NO;
  2309. if(rv < ACCEPT_YES_SINGLE)
  2310. {
  2311. lldebugs << "Category " << cat->getUUID() << "is not complete." << llendl;
  2312. break;
  2313. }
  2314. }
  2315. if (ACCEPT_YES_COPY_SINGLE <= rv)
  2316. {
  2317. for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin();
  2318.  item_iter != items.end();
  2319.  ++item_iter)
  2320. {
  2321. LLViewerInventoryItem *item = (*item_iter);
  2322. /*
  2323. // Pass the base objects, not the links.
  2324. if (item && item->getIsLinkType())
  2325. {
  2326. item = item->getLinkedItem();
  2327. (*item_iter) = item;
  2328. }
  2329. */
  2330. rv = willObjectAcceptInventory(root_object, item);
  2331. if (rv < ACCEPT_YES_COPY_SINGLE)
  2332. {
  2333. lldebugs << "Object will not accept " << item->getUUID() << llendl;
  2334. break;
  2335. }
  2336. }
  2337. }
  2338. // If every item is accepted, send it on
  2339. if (drop && (ACCEPT_YES_COPY_SINGLE <= rv))
  2340. {
  2341. LLInventoryFetchObserver::item_ref_t ids;
  2342. for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin();
  2343.  item_iter != items.end();
  2344.  ++item_iter)
  2345. {
  2346. const LLViewerInventoryItem *item = (*item_iter);
  2347. ids.push_back(item->getUUID());
  2348. }
  2349. LLCategoryDropObserver* dropper = new LLCategoryDropObserver(obj->getID(), mSource);
  2350. dropper->fetchItems(ids);
  2351. if(dropper->isEverythingComplete())
  2352. {
  2353. dropper->done();
  2354. }
  2355. else
  2356. {
  2357. gInventory.addObserver(dropper);
  2358. }
  2359. }
  2360. return rv;
  2361. }
  2362. BOOL LLToolDragAndDrop::dadUpdateInventoryCategory(LLViewerObject* obj,
  2363.    BOOL drop)
  2364. {
  2365. EAcceptance rv = dad3dUpdateInventoryCategory(obj, -1, MASK_NONE, drop);
  2366. return (rv >= ACCEPT_YES_COPY_SINGLE);
  2367. }
  2368. EAcceptance LLToolDragAndDrop::dad3dGiveInventoryObject(
  2369. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  2370. {
  2371. lldebugs << "LLToolDragAndDrop::dad3dGiveInventoryObject()" << llendl;
  2372. // item has to be in agent inventory.
  2373. if(mSource != SOURCE_AGENT) return ACCEPT_NO;
  2374. // find the item now.
  2375. LLViewerInventoryItem* item;
  2376. LLViewerInventoryCategory* cat;
  2377. locateInventory(item, cat);
  2378. if(!item || !item->isComplete()) return ACCEPT_NO;
  2379. if(!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
  2380. {
  2381. // cannot give away no-transfer objects
  2382. return ACCEPT_NO;
  2383. }
  2384. LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
  2385. if(avatar && avatar->isWearingAttachment( item->getUUID() ) )
  2386. {
  2387. // You can't give objects that are attached to you
  2388. return ACCEPT_NO;
  2389. }
  2390. if( obj && avatar )
  2391. {
  2392. if(drop)
  2393. {
  2394. giveInventory(obj->getID(), item );
  2395. }
  2396. // *TODO: deal with all the issues surrounding multi-object
  2397. // inventory transfers.
  2398. return ACCEPT_YES_SINGLE;
  2399. }
  2400. return ACCEPT_NO;
  2401. }
  2402. EAcceptance LLToolDragAndDrop::dad3dGiveInventory(
  2403. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  2404. {
  2405. lldebugs << "LLToolDragAndDrop::dad3dGiveInventory()" << llendl;
  2406. // item has to be in agent inventory.
  2407. if(mSource != SOURCE_AGENT) return ACCEPT_NO;
  2408. LLViewerInventoryItem* item;
  2409. LLViewerInventoryCategory* cat;
  2410. locateInventory(item, cat);
  2411. if(!item || !item->isComplete()) return ACCEPT_NO;
  2412. if(!isInventoryGiveAcceptable(item))
  2413. {
  2414. return ACCEPT_NO;
  2415. }
  2416. if(drop && obj)
  2417. {
  2418. giveInventory(obj->getID(), item);
  2419. }
  2420. // *TODO: deal with all the issues surrounding multi-object
  2421. // inventory transfers.
  2422. return ACCEPT_YES_SINGLE;
  2423. }
  2424. EAcceptance LLToolDragAndDrop::dad3dGiveInventoryCategory(
  2425. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  2426. {
  2427. lldebugs << "LLToolDragAndDrop::dad3dGiveInventoryCategory()" << llendl;
  2428. if(drop && obj)
  2429. {
  2430. LLViewerInventoryItem* item;
  2431. LLViewerInventoryCategory* cat;
  2432. locateInventory(item, cat);
  2433. if(!cat) return ACCEPT_NO;
  2434. giveInventoryCategory(obj->getID(), cat);
  2435. }
  2436. // *TODO: deal with all the issues surrounding multi-object
  2437. // inventory transfers.
  2438. return ACCEPT_YES_SINGLE;
  2439. }
  2440. EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnLand(
  2441. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  2442. {
  2443. lldebugs << "LLToolDragAndDrop::dad3dRezFromObjectOnLand()" << llendl;
  2444. LLViewerInventoryItem* item = NULL;
  2445. LLViewerInventoryCategory* cat = NULL;
  2446. locateInventory(item, cat);
  2447. if(!item || !item->isComplete()) return ACCEPT_NO;
  2448. if(!gAgent.allowOperation(PERM_COPY, item->getPermissions())
  2449. || !item->getPermissions().allowTransferTo(LLUUID::null))
  2450. {
  2451. return ACCEPT_NO_LOCKED;
  2452. }
  2453. if(drop)
  2454. {
  2455. dropObject(obj, TRUE, TRUE, FALSE);
  2456. }
  2457. return ACCEPT_YES_SINGLE;
  2458. }
  2459. EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnObject(
  2460. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  2461. {
  2462. lldebugs << "LLToolDragAndDrop::dad3dRezFromObjectOnObject()" << llendl;
  2463. LLViewerInventoryItem* item;
  2464. LLViewerInventoryCategory* cat;
  2465. locateInventory(item, cat);
  2466. if(!item || !item->isComplete()) return ACCEPT_NO;
  2467. if((mask & MASK_CONTROL))
  2468. {
  2469. // *HACK: In order to resolve SL-22177, we need to block drags
  2470. // from notecards and objects onto other objects.
  2471. return ACCEPT_NO;
  2472. // *HACK: uncomment this when appropriate
  2473. //EAcceptance rv = willObjectAcceptInventory(obj, item);
  2474. //if(drop && (ACCEPT_YES_SINGLE <= rv))
  2475. //{
  2476. // dropInventory(obj, item, mSource, mSourceID);
  2477. //}
  2478. //return rv;
  2479. }
  2480. if(!item->getPermissions().allowCopyBy(gAgent.getID(),
  2481.    gAgent.getGroupID())
  2482.    || !item->getPermissions().allowTransferTo(LLUUID::null))
  2483. {
  2484. return ACCEPT_NO_LOCKED;
  2485. }
  2486. if(drop)
  2487. {
  2488. dropObject(obj, FALSE, TRUE, FALSE);
  2489. }
  2490. return ACCEPT_YES_SINGLE;
  2491. }
  2492. EAcceptance LLToolDragAndDrop::dad3dCategoryOnLand(
  2493. LLViewerObject *obj, S32 face, MASK mask, BOOL drop)
  2494. {
  2495. return ACCEPT_NO;
  2496. /*
  2497. lldebugs << "LLToolDragAndDrop::dad3dCategoryOnLand()" << llendl;
  2498. LLInventoryItem* item;
  2499. LLInventoryCategory* cat;
  2500. locateInventory(item, cat);
  2501. if(!cat) return ACCEPT_NO;
  2502. EAcceptance rv = ACCEPT_NO;
  2503. // find all the items in the category
  2504. LLViewerInventoryCategory::cat_array_t cats;
  2505. LLViewerInventoryItem::item_array_t items;
  2506. LLDropCopyableItems droppable;
  2507. gInventory.collectDescendentsIf(cat->getUUID(),
  2508. cats,
  2509. items,
  2510. LLInventoryModel::EXCLUDE_TRASH,
  2511. droppable);
  2512. if(items.count() > 0)
  2513. {
  2514. rv = ACCEPT_YES_SINGLE;
  2515. }
  2516. if((rv >= ACCEPT_YES_COPY_SINGLE) && drop)
  2517. {
  2518. createContainer(items, cat->getName());
  2519. return ACCEPT_NO;
  2520. }
  2521. return rv;
  2522. */
  2523. }
  2524. // This is based on ALOT of copied, special-cased code
  2525. // This shortcuts alot of steps to make a basic object
  2526. // w/ an inventory and a special permissions set
  2527. EAcceptance LLToolDragAndDrop::dad3dAssetOnLand(
  2528. LLViewerObject *obj, S32 face, MASK mask, BOOL drop)
  2529. {
  2530. return ACCEPT_NO;
  2531. /*
  2532. lldebugs << "LLToolDragAndDrop::dad3dAssetOnLand()" << llendl;
  2533. LLViewerInventoryCategory::cat_array_t cats;
  2534. LLViewerInventoryItem::item_array_t items;
  2535. LLViewerInventoryItem::item_array_t copyable_items;
  2536. locateMultipleInventory(items, cats);
  2537. if(!items.count()) return ACCEPT_NO;
  2538. EAcceptance rv = ACCEPT_NO;
  2539. for (S32 i = 0; i < items.count(); i++)
  2540. {
  2541. LLInventoryItem* item = items[i];
  2542. if(item->getPermissions().allowCopyBy(gAgent.getID()))
  2543. {
  2544. copyable_items.put(item);
  2545. rv = ACCEPT_YES_SINGLE;
  2546. }
  2547. }
  2548. if((rv >= ACCEPT_YES_COPY_SINGLE) && drop)
  2549. {
  2550. createContainer(copyable_items, NULL);
  2551. }
  2552. return rv;
  2553. */
  2554. }
  2555. LLInventoryObject* LLToolDragAndDrop::locateInventory(
  2556. LLViewerInventoryItem*& item,
  2557. LLViewerInventoryCategory*& cat)
  2558. {
  2559. item = NULL;
  2560. cat = NULL;
  2561. if(mCargoIDs.empty()) return NULL;
  2562. if((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY))
  2563. {
  2564. // The object should be in user inventory.
  2565. item = (LLViewerInventoryItem*)gInventory.getItem(mCargoIDs[mCurItemIndex]);
  2566. cat = (LLViewerInventoryCategory*)gInventory.getCategory(mCargoIDs[mCurItemIndex]);
  2567. }
  2568. else if(mSource == SOURCE_WORLD)
  2569. {
  2570. // This object is in some task inventory somewhere.
  2571. LLViewerObject* obj = gObjectList.findObject(mSourceID);
  2572. if(obj)
  2573. {
  2574. if((mCargoTypes[mCurItemIndex] == DAD_CATEGORY)
  2575.    || (mCargoTypes[mCurItemIndex] == DAD_ROOT_CATEGORY))
  2576. {
  2577. cat = (LLViewerInventoryCategory*)obj->getInventoryObject(mCargoIDs[mCurItemIndex]);
  2578. }
  2579. else
  2580. {
  2581.    item = (LLViewerInventoryItem*)obj->getInventoryObject(mCargoIDs[mCurItemIndex]);
  2582. }
  2583. }
  2584. }
  2585. else if(mSource == SOURCE_NOTECARD)
  2586. {
  2587. LLPreviewNotecard* preview = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", mSourceID);
  2588. if(preview)
  2589. {
  2590. item = (LLViewerInventoryItem*)preview->getDragItem();
  2591. }
  2592. }
  2593. if(item) return item;
  2594. if(cat) return cat;
  2595. return NULL;
  2596. }
  2597. /*
  2598. LLInventoryObject* LLToolDragAndDrop::locateMultipleInventory(LLViewerInventoryCategory::cat_array_t& cats,
  2599.   LLViewerInventoryItem::item_array_t& items)
  2600. {
  2601. if(mCargoIDs.count() == 0) return NULL;
  2602. if((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY))
  2603. {
  2604. // The object should be in user inventory.
  2605. for (S32 i = 0; i < mCargoIDs.count(); i++)
  2606. {
  2607. LLInventoryItem* item = gInventory.getItem(mCargoIDs[i]);
  2608. if (item)
  2609. {
  2610. items.put(item);
  2611. }
  2612. LLInventoryCategory* category = gInventory.getCategory(mCargoIDs[i]);
  2613. if (category)
  2614. {
  2615. cats.put(category);
  2616. }
  2617. }
  2618. }
  2619. else if(mSource == SOURCE_WORLD)
  2620. {
  2621. // This object is in some task inventory somewhere.
  2622. LLViewerObject* obj = gObjectList.findObject(mSourceID);
  2623. if(obj)
  2624. {
  2625. if((mCargoType == DAD_CATEGORY)
  2626.    || (mCargoType == DAD_ROOT_CATEGORY))
  2627. {
  2628. // The object should be in user inventory.
  2629. for (S32 i = 0; i < mCargoIDs.count(); i++)
  2630. {
  2631. LLInventoryCategory* category = (LLInventoryCategory*)obj->getInventoryObject(mCargoIDs[i]);
  2632. if (category)
  2633. {
  2634. cats.put(category);
  2635. }
  2636. }
  2637. }
  2638. else
  2639. {
  2640. for (S32 i = 0; i < mCargoIDs.count(); i++)
  2641. {
  2642. LLInventoryItem* item = (LLInventoryItem*)obj->getInventoryObject(mCargoIDs[i]);
  2643. if (item)
  2644. {
  2645. items.put(item);
  2646. }
  2647. }
  2648. }
  2649. }
  2650. }
  2651. else if(mSource == SOURCE_NOTECARD)
  2652. {
  2653. LLPreviewNotecard* card;
  2654. card = (LLPreviewNotecard*)LLPreview::find(mSourceID);
  2655. if(card)
  2656. {
  2657. items.put((LLInventoryItem*)card->getDragItem());
  2658. }
  2659. }
  2660. if(items.count()) return items[0];
  2661. if(cats.count()) return cats[0];
  2662. return NULL;
  2663. }
  2664. */
  2665. // void LLToolDragAndDrop::createContainer(LLViewerInventoryItem::item_array_t &items, const char* preferred_name )
  2666. // {
  2667. //  llwarns << "LLToolDragAndDrop::createContainer()" << llendl;
  2668. //  return;
  2669. // }
  2670. // utility functions
  2671. void pack_permissions_slam(LLMessageSystem* msg, U32 flags, const LLPermissions& perms)
  2672. {
  2673. // CRUFT -- the server no longer pays attention to this data
  2674. U32 group_mask = perms.getMaskGroup();
  2675. U32 everyone_mask = perms.getMaskEveryone();
  2676. U32 next_owner_mask = perms.getMaskNextOwner();
  2677. msg->addU32Fast(_PREHASH_ItemFlags, flags);
  2678. msg->addU32Fast(_PREHASH_GroupMask, group_mask);
  2679. msg->addU32Fast(_PREHASH_EveryoneMask, everyone_mask);
  2680. msg->addU32Fast(_PREHASH_NextOwnerMask, next_owner_mask);
  2681. }