PageRenderTime 55ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/lltooldraganddrop.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2332 lines | 1792 code | 213 blank | 327 comment | 371 complexity | 15e4b703e8f763512171ef56912241da MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lltooldraganddrop.cpp
  3. * @brief LLToolDragAndDrop class implementation
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "lltooldraganddrop.h"
  28. // library headers
  29. #include "llnotificationsutil.h"
  30. // project headers
  31. #include "llagent.h"
  32. #include "llagentcamera.h"
  33. #include "llagentwearables.h"
  34. #include "llappearancemgr.h"
  35. #include "lldictionary.h"
  36. #include "llfloaterreg.h"
  37. #include "llfloatertools.h"
  38. #include "llgesturemgr.h"
  39. #include "llgiveinventory.h"
  40. #include "llhudmanager.h"
  41. #include "llhudeffecttrail.h"
  42. #include "llimview.h"
  43. #include "llinventorybridge.h"
  44. #include "llinventorydefines.h"
  45. #include "llinventoryfunctions.h"
  46. #include "llpreviewnotecard.h"
  47. #include "llrootview.h"
  48. #include "llselectmgr.h"
  49. #include "lltoolmgr.h"
  50. #include "lltooltip.h"
  51. #include "lltrans.h"
  52. #include "llviewerobjectlist.h"
  53. #include "llviewerregion.h"
  54. #include "llviewerstats.h"
  55. #include "llviewerwindow.h"
  56. #include "llvoavatarself.h"
  57. #include "llworld.h"
  58. #include "llclipboard.h"
  59. // syntactic sugar
  60. #define callMemberFunction(object,ptrToMember) ((object).*(ptrToMember))
  61. class LLNoPreferredType : public LLInventoryCollectFunctor
  62. {
  63. public:
  64. LLNoPreferredType() {}
  65. virtual ~LLNoPreferredType() {}
  66. virtual bool operator()(LLInventoryCategory* cat,
  67. LLInventoryItem* item)
  68. {
  69. if (cat && (cat->getPreferredType() == LLFolderType::FT_NONE))
  70. {
  71. return true;
  72. }
  73. return false;
  74. }
  75. };
  76. class LLNoPreferredTypeOrItem : public LLInventoryCollectFunctor
  77. {
  78. public:
  79. LLNoPreferredTypeOrItem() {}
  80. virtual ~LLNoPreferredTypeOrItem() {}
  81. virtual bool operator()(LLInventoryCategory* cat,
  82. LLInventoryItem* item)
  83. {
  84. if (item) return true;
  85. if (cat && (cat->getPreferredType() == LLFolderType::FT_NONE))
  86. {
  87. return true;
  88. }
  89. return false;
  90. }
  91. };
  92. class LLDroppableItem : public LLInventoryCollectFunctor
  93. {
  94. public:
  95. LLDroppableItem(BOOL is_transfer) :
  96. mCountLosing(0), mIsTransfer(is_transfer) {}
  97. virtual ~LLDroppableItem() {}
  98. virtual bool operator()(LLInventoryCategory* cat,
  99. LLInventoryItem* item);
  100. S32 countNoCopy() const { return mCountLosing; }
  101. protected:
  102. S32 mCountLosing;
  103. BOOL mIsTransfer;
  104. };
  105. bool LLDroppableItem::operator()(LLInventoryCategory* cat,
  106. LLInventoryItem* item)
  107. {
  108. bool allowed = false;
  109. if (item)
  110. {
  111. allowed = itemTransferCommonlyAllowed(item);
  112. if (allowed
  113. && mIsTransfer
  114. && !item->getPermissions().allowOperationBy(PERM_TRANSFER,
  115. gAgent.getID()))
  116. {
  117. allowed = false;
  118. }
  119. if (allowed && !item->getPermissions().allowCopyBy(gAgent.getID()))
  120. {
  121. ++mCountLosing;
  122. }
  123. }
  124. return allowed;
  125. }
  126. class LLDropCopyableItems : public LLInventoryCollectFunctor
  127. {
  128. public:
  129. LLDropCopyableItems() {}
  130. virtual ~LLDropCopyableItems() {}
  131. virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
  132. };
  133. bool LLDropCopyableItems::operator()(
  134. LLInventoryCategory* cat,
  135. LLInventoryItem* item)
  136. {
  137. bool allowed = false;
  138. if (item)
  139. {
  140. allowed = itemTransferCommonlyAllowed(item);
  141. if (allowed &&
  142. !item->getPermissions().allowCopyBy(gAgent.getID()))
  143. {
  144. // whoops, can't copy it - don't allow it.
  145. allowed = false;
  146. }
  147. }
  148. return allowed;
  149. }
  150. // Starts a fetch on folders and items. This is really not used
  151. // as an observer in the traditional sense; we're just using it to
  152. // request a fetch and we don't care about when/if the response arrives.
  153. class LLCategoryFireAndForget : public LLInventoryFetchComboObserver
  154. {
  155. public:
  156. LLCategoryFireAndForget(const uuid_vec_t& folder_ids,
  157. const uuid_vec_t& item_ids) :
  158. LLInventoryFetchComboObserver(folder_ids, item_ids)
  159. {}
  160. ~LLCategoryFireAndForget() {}
  161. virtual void done()
  162. {
  163. /* no-op: it's fire n forget right? */
  164. lldebugs << "LLCategoryFireAndForget::done()" << llendl;
  165. }
  166. };
  167. class LLCategoryDropObserver : public LLInventoryFetchItemsObserver
  168. {
  169. public:
  170. LLCategoryDropObserver(
  171. const uuid_vec_t& ids,
  172. const LLUUID& obj_id, LLToolDragAndDrop::ESource src) :
  173. LLInventoryFetchItemsObserver(ids),
  174. mObjectID(obj_id),
  175. mSource(src)
  176. {}
  177. ~LLCategoryDropObserver() {}
  178. virtual void done();
  179. protected:
  180. LLUUID mObjectID;
  181. LLToolDragAndDrop::ESource mSource;
  182. };
  183. void LLCategoryDropObserver::done()
  184. {
  185. gInventory.removeObserver(this);
  186. LLViewerObject* dst_obj = gObjectList.findObject(mObjectID);
  187. if (dst_obj)
  188. {
  189. // *FIX: coalesce these...
  190. LLInventoryItem* item = NULL;
  191. uuid_vec_t::iterator it = mComplete.begin();
  192. uuid_vec_t::iterator end = mComplete.end();
  193. for(; it < end; ++it)
  194. {
  195. item = gInventory.getItem(*it);
  196. if (item)
  197. {
  198. LLToolDragAndDrop::dropInventory(
  199. dst_obj,
  200. item,
  201. mSource,
  202. LLUUID::null);
  203. }
  204. }
  205. }
  206. delete this;
  207. }
  208. /* Doesn't seem to be used anymore.
  209. class LLCategoryDropDescendentsObserver : public LLInventoryFetchDescendentsObserver
  210. {
  211. public:
  212. LLCategoryDropDescendentsObserver(
  213. const LLUUID& obj_id, LLToolDragAndDrop::ESource src) :
  214. mObjectID(obj_id),
  215. mSource(src)
  216. {}
  217. ~LLCategoryDropDescendentsObserver() {}
  218. virtual void done();
  219. protected:
  220. LLUUID mObjectID;
  221. LLToolDragAndDrop::ESource mSource;
  222. };
  223. void LLCategoryDropDescendentsObserver::done()
  224. {
  225. gInventory.removeObserver(this);
  226. uuid_vec_t::iterator it = mComplete.begin();
  227. uuid_vec_t::iterator end = mComplete.end();
  228. LLViewerInventoryCategory::cat_array_t cats;
  229. LLViewerInventoryItem::item_array_t items;
  230. for(; it != end; ++it)
  231. {
  232. gInventory.collectDescendents(
  233. (*it),
  234. cats,
  235. items,
  236. LLInventoryModel::EXCLUDE_TRASH);
  237. }
  238. S32 count = items.count();
  239. if (count)
  240. {
  241. std::set<LLUUID> unique_ids;
  242. for(S32 i = 0; i < count; ++i)
  243. {
  244. unique_ids.insert(items.get(i)->getUUID());
  245. }
  246. uuid_vec_t ids;
  247. std::back_insert_iterator<uuid_vec_t> copier(ids);
  248. std::copy(unique_ids.begin(), unique_ids.end(), copier);
  249. LLCategoryDropObserver* dropper;
  250. dropper = new LLCategoryDropObserver(ids, mObjectID, mSource);
  251. dropper->startFetch();
  252. if (dropper->isDone())
  253. {
  254. dropper->done();
  255. }
  256. else
  257. {
  258. gInventory.addObserver(dropper);
  259. }
  260. }
  261. delete this;
  262. }
  263. */
  264. S32 LLToolDragAndDrop::sOperationId = 0;
  265. LLToolDragAndDrop::DragAndDropEntry::DragAndDropEntry(dragOrDrop3dImpl f_none,
  266. dragOrDrop3dImpl f_self,
  267. dragOrDrop3dImpl f_avatar,
  268. dragOrDrop3dImpl f_object,
  269. dragOrDrop3dImpl f_land) :
  270. LLDictionaryEntry("")
  271. {
  272. mFunctions[DT_NONE] = f_none;
  273. mFunctions[DT_SELF] = f_self;
  274. mFunctions[DT_AVATAR] = f_avatar;
  275. mFunctions[DT_OBJECT] = f_object;
  276. mFunctions[DT_LAND] = f_land;
  277. }
  278. LLToolDragAndDrop::dragOrDrop3dImpl LLToolDragAndDrop::LLDragAndDropDictionary::get(EDragAndDropType dad_type, LLToolDragAndDrop::EDropTarget drop_target)
  279. {
  280. const DragAndDropEntry *entry = lookup(dad_type);
  281. if (entry)
  282. {
  283. return (entry->mFunctions[(U8)drop_target]);
  284. }
  285. return &LLToolDragAndDrop::dad3dNULL;
  286. }
  287. LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary()
  288. {
  289. // DT_NONE DT_SELF DT_AVATAR DT_OBJECT DT_LAND
  290. // |-------------------------------|----------------------------------------------|-----------------------------------------------|---------------------------------------------------|--------------------------------|
  291. addEntry(DAD_NONE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL));
  292. addEntry(DAD_TEXTURE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dTextureObject, &LLToolDragAndDrop::dad3dNULL));
  293. addEntry(DAD_SOUND, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
  294. addEntry(DAD_CALLINGCARD, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
  295. addEntry(DAD_LANDMARK, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
  296. addEntry(DAD_SCRIPT, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dRezScript, &LLToolDragAndDrop::dad3dNULL));
  297. addEntry(DAD_CLOTHING, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearItem, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
  298. addEntry(DAD_OBJECT, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dRezAttachmentFromInv, &LLToolDragAndDrop::dad3dGiveInventoryObject, &LLToolDragAndDrop::dad3dRezObjectOnObject, &LLToolDragAndDrop::dad3dRezObjectOnLand));
  299. addEntry(DAD_NOTECARD, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
  300. addEntry(DAD_CATEGORY, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearCategory, &LLToolDragAndDrop::dad3dGiveInventoryCategory, &LLToolDragAndDrop::dad3dUpdateInventoryCategory, &LLToolDragAndDrop::dad3dNULL));
  301. addEntry(DAD_ROOT_CATEGORY, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL));
  302. addEntry(DAD_BODYPART, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearItem, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
  303. addEntry(DAD_ANIMATION, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
  304. addEntry(DAD_GESTURE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dActivateGesture, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
  305. addEntry(DAD_LINK, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL));
  306. addEntry(DAD_MESH, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dMeshObject, &LLToolDragAndDrop::dad3dNULL));
  307. // TODO: animation on self could play it? edit it?
  308. // TODO: gesture on self could play it? edit it?
  309. };
  310. LLToolDragAndDrop::LLToolDragAndDrop()
  311. : LLTool(std::string("draganddrop"), NULL),
  312. mDragStartX(0),
  313. mDragStartY(0),
  314. mSource(SOURCE_AGENT),
  315. mCursor(UI_CURSOR_NO),
  316. mLastAccept(ACCEPT_NO),
  317. mDrop(FALSE),
  318. mCurItemIndex(0)
  319. {
  320. }
  321. void LLToolDragAndDrop::setDragStart(S32 x, S32 y)
  322. {
  323. mDragStartX = x;
  324. mDragStartY = y;
  325. }
  326. BOOL LLToolDragAndDrop::isOverThreshold(S32 x,S32 y)
  327. {
  328. static LLCachedControl<S32> drag_and_drop_threshold(gSavedSettings,"DragAndDropDistanceThreshold");
  329. S32 mouse_delta_x = x - mDragStartX;
  330. S32 mouse_delta_y = y - mDragStartY;
  331. return (mouse_delta_x * mouse_delta_x) + (mouse_delta_y * mouse_delta_y) > drag_and_drop_threshold * drag_and_drop_threshold;
  332. }
  333. void LLToolDragAndDrop::beginDrag(EDragAndDropType type,
  334. const LLUUID& cargo_id,
  335. ESource source,
  336. const LLUUID& source_id,
  337. const LLUUID& object_id)
  338. {
  339. if (type == DAD_NONE)
  340. {
  341. llwarns << "Attempted to start drag without a cargo type" << llendl;
  342. return;
  343. }
  344. mCargoTypes.clear();
  345. mCargoTypes.push_back(type);
  346. mCargoIDs.clear();
  347. mCargoIDs.push_back(cargo_id);
  348. mSource = source;
  349. mSourceID = source_id;
  350. mObjectID = object_id;
  351. setMouseCapture( TRUE );
  352. LLToolMgr::getInstance()->setTransientTool( this );
  353. mCursor = UI_CURSOR_NO;
  354. if ((mCargoTypes[0] == DAD_CATEGORY)
  355. && ((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY)))
  356. {
  357. LLInventoryCategory* cat = gInventory.getCategory(cargo_id);
  358. // go ahead and fire & forget the descendents if we are not
  359. // dragging a protected folder.
  360. if (cat)
  361. {
  362. LLViewerInventoryCategory::cat_array_t cats;
  363. LLViewerInventoryItem::item_array_t items;
  364. LLNoPreferredTypeOrItem is_not_preferred;
  365. uuid_vec_t folder_ids;
  366. uuid_vec_t item_ids;
  367. if (is_not_preferred(cat, NULL))
  368. {
  369. folder_ids.push_back(cargo_id);
  370. }
  371. gInventory.collectDescendentsIf(
  372. cargo_id,
  373. cats,
  374. items,
  375. LLInventoryModel::EXCLUDE_TRASH,
  376. is_not_preferred);
  377. S32 count = cats.count();
  378. S32 i;
  379. for(i = 0; i < count; ++i)
  380. {
  381. folder_ids.push_back(cats.get(i)->getUUID());
  382. }
  383. count = items.count();
  384. for(i = 0; i < count; ++i)
  385. {
  386. item_ids.push_back(items.get(i)->getUUID());
  387. }
  388. if (!folder_ids.empty() || !item_ids.empty())
  389. {
  390. LLCategoryFireAndForget *fetcher = new LLCategoryFireAndForget(folder_ids, item_ids);
  391. fetcher->startFetch();
  392. delete fetcher;
  393. }
  394. }
  395. }
  396. }
  397. void LLToolDragAndDrop::beginMultiDrag(
  398. const std::vector<EDragAndDropType> types,
  399. const uuid_vec_t& cargo_ids,
  400. ESource source,
  401. const LLUUID& source_id)
  402. {
  403. // assert on public api is evil
  404. //llassert( type != DAD_NONE );
  405. std::vector<EDragAndDropType>::const_iterator types_it;
  406. for (types_it = types.begin(); types_it != types.end(); ++types_it)
  407. {
  408. if (DAD_NONE == *types_it)
  409. {
  410. llwarns << "Attempted to start drag without a cargo type" << llendl;
  411. return;
  412. }
  413. }
  414. mCargoTypes = types;
  415. mCargoIDs = cargo_ids;
  416. mSource = source;
  417. mSourceID = source_id;
  418. setMouseCapture( TRUE );
  419. LLToolMgr::getInstance()->setTransientTool( this );
  420. mCursor = UI_CURSOR_NO;
  421. if ((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY))
  422. {
  423. // find categories (i.e. inventory folders) in the cargo.
  424. LLInventoryCategory* cat = NULL;
  425. S32 count = llmin(cargo_ids.size(), types.size());
  426. std::set<LLUUID> cat_ids;
  427. for(S32 i = 0; i < count; ++i)
  428. {
  429. cat = gInventory.getCategory(cargo_ids[i]);
  430. if (cat)
  431. {
  432. LLViewerInventoryCategory::cat_array_t cats;
  433. LLViewerInventoryItem::item_array_t items;
  434. LLNoPreferredType is_not_preferred;
  435. if (is_not_preferred(cat, NULL))
  436. {
  437. cat_ids.insert(cat->getUUID());
  438. }
  439. gInventory.collectDescendentsIf(
  440. cat->getUUID(),
  441. cats,
  442. items,
  443. LLInventoryModel::EXCLUDE_TRASH,
  444. is_not_preferred);
  445. S32 cat_count = cats.count();
  446. for(S32 i = 0; i < cat_count; ++i)
  447. {
  448. cat_ids.insert(cat->getUUID());
  449. }
  450. }
  451. }
  452. if (!cat_ids.empty())
  453. {
  454. uuid_vec_t folder_ids;
  455. uuid_vec_t item_ids;
  456. std::back_insert_iterator<uuid_vec_t> copier(folder_ids);
  457. std::copy(cat_ids.begin(), cat_ids.end(), copier);
  458. LLCategoryFireAndForget fetcher(folder_ids, item_ids);
  459. }
  460. }
  461. }
  462. void LLToolDragAndDrop::endDrag()
  463. {
  464. mEndDragSignal();
  465. LLSelectMgr::getInstance()->unhighlightAll();
  466. setMouseCapture(FALSE);
  467. }
  468. void LLToolDragAndDrop::onMouseCaptureLost()
  469. {
  470. // Called whenever the drag ends or if mouse capture is simply lost
  471. LLToolMgr::getInstance()->clearTransientTool();
  472. mCargoTypes.clear();
  473. mCargoIDs.clear();
  474. mSource = SOURCE_AGENT;
  475. mSourceID.setNull();
  476. mObjectID.setNull();
  477. }
  478. BOOL LLToolDragAndDrop::handleMouseUp( S32 x, S32 y, MASK mask )
  479. {
  480. if (hasMouseCapture())
  481. {
  482. EAcceptance acceptance = ACCEPT_NO;
  483. dragOrDrop( x, y, mask, TRUE, &acceptance );
  484. endDrag();
  485. }
  486. return TRUE;
  487. }
  488. ECursorType LLToolDragAndDrop::acceptanceToCursor( EAcceptance acceptance )
  489. {
  490. switch (acceptance)
  491. {
  492. case ACCEPT_YES_MULTI:
  493. if (mCargoIDs.size() > 1)
  494. {
  495. mCursor = UI_CURSOR_ARROWDRAGMULTI;
  496. }
  497. else
  498. {
  499. mCursor = UI_CURSOR_ARROWDRAG;
  500. }
  501. break;
  502. case ACCEPT_YES_SINGLE:
  503. if (mCargoIDs.size() > 1)
  504. {
  505. mToolTipMsg = LLTrans::getString("TooltipMustSingleDrop");
  506. mCursor = UI_CURSOR_NO;
  507. }
  508. else
  509. {
  510. mCursor = UI_CURSOR_ARROWDRAG;
  511. }
  512. break;
  513. case ACCEPT_NO_LOCKED:
  514. mCursor = UI_CURSOR_NOLOCKED;
  515. break;
  516. case ACCEPT_NO:
  517. mCursor = UI_CURSOR_NO;
  518. break;
  519. case ACCEPT_YES_COPY_MULTI:
  520. if (mCargoIDs.size() > 1)
  521. {
  522. mCursor = UI_CURSOR_ARROWCOPYMULTI;
  523. }
  524. else
  525. {
  526. mCursor = UI_CURSOR_ARROWCOPY;
  527. }
  528. break;
  529. case ACCEPT_YES_COPY_SINGLE:
  530. if (mCargoIDs.size() > 1)
  531. {
  532. mToolTipMsg = LLTrans::getString("TooltipMustSingleDrop");
  533. mCursor = UI_CURSOR_NO;
  534. }
  535. else
  536. {
  537. mCursor = UI_CURSOR_ARROWCOPY;
  538. }
  539. break;
  540. case ACCEPT_POSTPONED:
  541. break;
  542. default:
  543. llassert( FALSE );
  544. }
  545. return mCursor;
  546. }
  547. BOOL LLToolDragAndDrop::handleHover( S32 x, S32 y, MASK mask )
  548. {
  549. EAcceptance acceptance = ACCEPT_NO;
  550. dragOrDrop( x, y, mask, FALSE, &acceptance );
  551. ECursorType cursor = acceptanceToCursor(acceptance);
  552. gViewerWindow->getWindow()->setCursor( cursor );
  553. lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolDragAndDrop" << llendl;
  554. return TRUE;
  555. }
  556. BOOL LLToolDragAndDrop::handleKey(KEY key, MASK mask)
  557. {
  558. if (key == KEY_ESCAPE)
  559. {
  560. // cancel drag and drop operation
  561. endDrag();
  562. return TRUE;
  563. }
  564. return FALSE;
  565. }
  566. BOOL LLToolDragAndDrop::handleToolTip(S32 x, S32 y, MASK mask)
  567. {
  568. if (!mToolTipMsg.empty())
  569. {
  570. LLToolTipMgr::instance().unblockToolTips();
  571. LLToolTipMgr::instance().show(LLToolTip::Params()
  572. .message(mToolTipMsg)
  573. .delay_time(gSavedSettings.getF32( "DragAndDropToolTipDelay" )));
  574. return TRUE;
  575. }
  576. return FALSE;
  577. }
  578. void LLToolDragAndDrop::handleDeselect()
  579. {
  580. mToolTipMsg.clear();
  581. LLToolTipMgr::instance().blockToolTips();
  582. }
  583. // protected
  584. void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,
  585. EAcceptance* acceptance)
  586. {
  587. *acceptance = ACCEPT_YES_MULTI;
  588. BOOL handled = FALSE;
  589. LLView* top_view = gFocusMgr.getTopCtrl();
  590. LLViewerInventoryItem* item;
  591. LLViewerInventoryCategory* cat;
  592. mToolTipMsg.clear();
  593. // Increment the operation id for every drop
  594. if (drop)
  595. {
  596. sOperationId++;
  597. }
  598. if (top_view)
  599. {
  600. handled = TRUE;
  601. for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
  602. {
  603. LLInventoryObject* cargo = locateInventory(item, cat);
  604. if (cargo)
  605. {
  606. S32 local_x, local_y;
  607. top_view->screenPointToLocal( x, y, &local_x, &local_y );
  608. EAcceptance item_acceptance = ACCEPT_NO;
  609. handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE,
  610. mCargoTypes[mCurItemIndex],
  611. (void*)cargo,
  612. &item_acceptance,
  613. mToolTipMsg);
  614. if (handled)
  615. {
  616. // use sort order to determine priority of acceptance
  617. *acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance);
  618. }
  619. }
  620. else
  621. {
  622. return;
  623. }
  624. }
  625. // all objects passed, go ahead and perform drop if necessary
  626. if (handled && drop && (U32)*acceptance >= ACCEPT_YES_COPY_SINGLE)
  627. {
  628. if ((U32)*acceptance < ACCEPT_YES_COPY_MULTI &&
  629. mCargoIDs.size() > 1)
  630. {
  631. // tried to give multi-cargo to a single-acceptor - refuse and return.
  632. *acceptance = ACCEPT_NO;
  633. return;
  634. }
  635. for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
  636. {
  637. LLInventoryObject* cargo = locateInventory(item, cat);
  638. if (cargo)
  639. {
  640. S32 local_x, local_y;
  641. EAcceptance item_acceptance;
  642. top_view->screenPointToLocal( x, y, &local_x, &local_y );
  643. handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, TRUE,
  644. mCargoTypes[mCurItemIndex],
  645. (void*)cargo,
  646. &item_acceptance,
  647. mToolTipMsg);
  648. }
  649. }
  650. }
  651. if (handled)
  652. {
  653. mLastAccept = (EAcceptance)*acceptance;
  654. }
  655. }
  656. if (!handled)
  657. {
  658. handled = TRUE;
  659. LLRootView* root_view = gViewerWindow->getRootView();
  660. for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
  661. {
  662. LLInventoryObject* cargo = locateInventory(item, cat);
  663. // fix for EXT-3191
  664. if (NULL == cargo) return;
  665. EAcceptance item_acceptance = ACCEPT_NO;
  666. handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE,
  667. mCargoTypes[mCurItemIndex],
  668. (void*)cargo,
  669. &item_acceptance,
  670. mToolTipMsg);
  671. if (handled)
  672. {
  673. // use sort order to determine priority of acceptance
  674. *acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance);
  675. }
  676. }
  677. // all objects passed, go ahead and perform drop if necessary
  678. if (handled && drop && (U32)*acceptance > ACCEPT_NO_LOCKED)
  679. {
  680. if ((U32)*acceptance < ACCEPT_YES_COPY_MULTI &&
  681. mCargoIDs.size() > 1)
  682. {
  683. // tried to give multi-cargo to a single-acceptor - refuse and return.
  684. *acceptance = ACCEPT_NO;
  685. return;
  686. }
  687. for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
  688. {
  689. LLInventoryObject* cargo = locateInventory(item, cat);
  690. if (cargo)
  691. {
  692. EAcceptance item_acceptance;
  693. handled = handled && root_view->handleDragAndDrop(x, y, mask, TRUE,
  694. mCargoTypes[mCurItemIndex],
  695. (void*)cargo,
  696. &item_acceptance,
  697. mToolTipMsg);
  698. }
  699. }
  700. }
  701. if (handled)
  702. {
  703. mLastAccept = (EAcceptance)*acceptance;
  704. }
  705. }
  706. if (!handled)
  707. {
  708. // Disallow drag and drop to 3D from the outbox
  709. const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false);
  710. if (outbox_id.notNull())
  711. {
  712. for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++)
  713. {
  714. if (gInventory.isObjectDescendentOf(mCargoIDs[item_index], outbox_id))
  715. {
  716. *acceptance = ACCEPT_NO;
  717. mToolTipMsg = LLTrans::getString("TooltipOutboxDragToWorld");
  718. return;
  719. }
  720. }
  721. }
  722. dragOrDrop3D( x, y, mask, drop, acceptance );
  723. }
  724. }
  725. void LLToolDragAndDrop::dragOrDrop3D( S32 x, S32 y, MASK mask, BOOL drop, EAcceptance* acceptance )
  726. {
  727. mDrop = drop;
  728. if (mDrop)
  729. {
  730. // don't allow drag and drop onto transparent objects
  731. pick(gViewerWindow->pickImmediate(x, y, FALSE));
  732. }
  733. else
  734. {
  735. // don't allow drag and drop onto transparent objects
  736. gViewerWindow->pickAsync(x, y, mask, pickCallback, FALSE);
  737. }
  738. *acceptance = mLastAccept;
  739. }
  740. void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info)
  741. {
  742. if (getInstance() != NULL)
  743. {
  744. getInstance()->pick(pick_info);
  745. }
  746. }
  747. void LLToolDragAndDrop::pick(const LLPickInfo& pick_info)
  748. {
  749. EDropTarget target = DT_NONE;
  750. S32 hit_face = -1;
  751. LLViewerObject* hit_obj = pick_info.getObject();
  752. LLSelectMgr::getInstance()->unhighlightAll();
  753. bool highlight_object = false;
  754. // Treat attachments as part of the avatar they are attached to.
  755. if (hit_obj != NULL)
  756. {
  757. // don't allow drag and drop on grass, trees, etc.
  758. if (pick_info.mPickType == LLPickInfo::PICK_FLORA)
  759. {
  760. mCursor = UI_CURSOR_NO;
  761. gViewerWindow->getWindow()->setCursor( mCursor );
  762. return;
  763. }
  764. if (hit_obj->isAttachment() && !hit_obj->isHUDAttachment())
  765. {
  766. LLVOAvatar* avatar = LLVOAvatar::findAvatarFromAttachment( hit_obj );
  767. if (!avatar)
  768. {
  769. mLastAccept = ACCEPT_NO;
  770. mCursor = UI_CURSOR_NO;
  771. gViewerWindow->getWindow()->setCursor( mCursor );
  772. return;
  773. }
  774. hit_obj = avatar;
  775. }
  776. if (hit_obj->isAvatar())
  777. {
  778. if (((LLVOAvatar*) hit_obj)->isSelf())
  779. {
  780. target = DT_SELF;
  781. hit_face = -1;
  782. }
  783. else
  784. {
  785. target = DT_AVATAR;
  786. hit_face = -1;
  787. }
  788. }
  789. else
  790. {
  791. target = DT_OBJECT;
  792. hit_face = pick_info.mObjectFace;
  793. highlight_object = true;
  794. }
  795. }
  796. else if (pick_info.mPickType == LLPickInfo::PICK_LAND)
  797. {
  798. target = DT_LAND;
  799. hit_face = -1;
  800. }
  801. mLastAccept = ACCEPT_YES_MULTI;
  802. for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
  803. {
  804. const S32 item_index = mCurItemIndex;
  805. const EDragAndDropType dad_type = mCargoTypes[item_index];
  806. // Call the right implementation function
  807. mLastAccept = (EAcceptance)llmin(
  808. (U32)mLastAccept,
  809. (U32)callMemberFunction(*this,
  810. LLDragAndDropDictionary::instance().get(dad_type, target))
  811. (hit_obj, hit_face, pick_info.mKeyMask, FALSE));
  812. }
  813. if (mDrop && ((U32)mLastAccept >= ACCEPT_YES_COPY_SINGLE))
  814. {
  815. // if target allows multi-drop or there is only one item being dropped, go ahead
  816. if ((mLastAccept >= ACCEPT_YES_COPY_MULTI) || (mCargoIDs.size() == 1))
  817. {
  818. // Target accepts multi, or cargo is a single-drop
  819. for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
  820. {
  821. const S32 item_index = mCurItemIndex;
  822. const EDragAndDropType dad_type = mCargoTypes[item_index];
  823. // Call the right implementation function
  824. (U32)callMemberFunction(*this,
  825. LLDragAndDropDictionary::instance().get(dad_type, target))
  826. (hit_obj, hit_face, pick_info.mKeyMask, TRUE);
  827. }
  828. }
  829. else
  830. {
  831. // Target does not accept multi, but cargo is multi
  832. mLastAccept = ACCEPT_NO;
  833. }
  834. }
  835. if (highlight_object && mLastAccept > ACCEPT_NO_LOCKED)
  836. {
  837. // if any item being dragged will be applied to the object under our cursor
  838. // highlight that object
  839. for (S32 i = 0; i < (S32)mCargoIDs.size(); i++)
  840. {
  841. if (mCargoTypes[i] != DAD_OBJECT || (pick_info.mKeyMask & MASK_CONTROL))
  842. {
  843. LLSelectMgr::getInstance()->highlightObjectAndFamily(hit_obj);
  844. break;
  845. }
  846. }
  847. }
  848. ECursorType cursor = acceptanceToCursor( mLastAccept );
  849. gViewerWindow->getWindow()->setCursor( cursor );
  850. mLastHitPos = pick_info.mPosGlobal;
  851. mLastCameraPos = gAgentCamera.getCameraPositionGlobal();
  852. }
  853. // static
  854. BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj,
  855. LLInventoryItem* item,
  856. LLToolDragAndDrop::ESource source,
  857. const LLUUID& src_id)
  858. {
  859. // Always succeed if....
  860. // texture is from the library
  861. // or already in the contents of the object
  862. if (SOURCE_LIBRARY == source)
  863. {
  864. // dropping a texture from the library always just works.
  865. return TRUE;
  866. }
  867. // In case the inventory has not been updated (e.g. due to some recent operation
  868. // causing a dirty inventory), stall the user while fetching the inventory.
  869. if (hit_obj->isInventoryDirty())
  870. {
  871. hit_obj->fetchInventoryFromServer();
  872. LLSD args;
  873. args["ERROR_MESSAGE"] = "Unable to add texture.\nPlease wait a few seconds and try again.";
  874. LLNotificationsUtil::add("ErrorMessage", args);
  875. return FALSE;
  876. }
  877. if (hit_obj->getInventoryItemByAsset(item->getAssetUUID()))
  878. {
  879. // if the asset is already in the object's inventory
  880. // then it can always be added to a side.
  881. // This saves some work if the task's inventory is already loaded
  882. // and ensures that the texture item is only added once.
  883. return TRUE;
  884. }
  885. if (!item) return FALSE;
  886. LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
  887. if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
  888. {
  889. // Check that we can add the texture as inventory to the object
  890. if (willObjectAcceptInventory(hit_obj,item) < ACCEPT_YES_COPY_SINGLE )
  891. {
  892. return FALSE;
  893. }
  894. // make sure the object has the texture in it's inventory.
  895. if (SOURCE_AGENT == source)
  896. {
  897. // Remove the texture from local inventory. The server
  898. // will actually remove the item from agent inventory.
  899. gInventory.deleteObject(item->getUUID());
  900. gInventory.notifyObservers();
  901. }
  902. else if (SOURCE_WORLD == source)
  903. {
  904. // *FIX: if the objects are in different regions, and the
  905. // source region has crashed, you can bypass these
  906. // permissions.
  907. LLViewerObject* src_obj = gObjectList.findObject(src_id);
  908. if (src_obj)
  909. {
  910. src_obj->removeInventory(item->getUUID());
  911. }
  912. else
  913. {
  914. llwarns << "Unable to find source object." << llendl;
  915. return FALSE;
  916. }
  917. }
  918. // Add the texture item to the target object's inventory.
  919. hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
  920. // TODO: Check to see if adding the item was successful; if not, then
  921. // we should return false here.
  922. }
  923. else if (!item->getPermissions().allowOperationBy(PERM_TRANSFER,
  924. gAgent.getID()))
  925. {
  926. // Check that we can add the texture as inventory to the object
  927. if (willObjectAcceptInventory(hit_obj,item) < ACCEPT_YES_COPY_SINGLE )
  928. {
  929. return FALSE;
  930. }
  931. // *FIX: may want to make sure agent can paint hit_obj.
  932. // Add the texture item to the target object's inventory.
  933. hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
  934. // Force the object to update its refetch its inventory so it has this texture.
  935. hit_obj->fetchInventoryFromServer();
  936. // TODO: Check to see if adding the item was successful; if not, then
  937. // we should return false here.
  938. }
  939. return TRUE;
  940. }
  941. void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj,
  942. LLInventoryItem* item,
  943. LLToolDragAndDrop::ESource source,
  944. const LLUUID& src_id)
  945. {
  946. if (!item)
  947. {
  948. llwarns << "LLToolDragAndDrop::dropTextureAllFaces no texture item." << llendl;
  949. return;
  950. }
  951. LLUUID asset_id = item->getAssetUUID();
  952. BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
  953. if (!success)
  954. {
  955. return;
  956. }
  957. LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id);
  958. LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT );
  959. S32 num_faces = hit_obj->getNumTEs();
  960. for( S32 face = 0; face < num_faces; face++ )
  961. {
  962. // update viewer side image in anticipation of update from simulator
  963. hit_obj->setTEImage(face, image);
  964. dialog_refresh_all();
  965. }
  966. // send the update to the simulator
  967. hit_obj->sendTEUpdate();
  968. }
  969. void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj,
  970. LLInventoryItem* item,
  971. LLToolDragAndDrop::ESource source,
  972. const LLUUID& src_id)
  973. {
  974. if (!item)
  975. {
  976. llwarns << "no inventory item." << llendl;
  977. return;
  978. }
  979. LLUUID asset_id = item->getAssetUUID();
  980. BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
  981. if(!success)
  982. {
  983. return;
  984. }
  985. LLSculptParams sculpt_params;
  986. sculpt_params.setSculptTexture(asset_id);
  987. sculpt_params.setSculptType(LL_SCULPT_TYPE_MESH);
  988. hit_obj->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE);
  989. dialog_refresh_all();
  990. }
  991. /*
  992. void LLToolDragAndDrop::dropTextureOneFaceAvatar(LLVOAvatar* avatar, S32 hit_face, LLInventoryItem* item)
  993. {
  994. if (hit_face == -1) return;
  995. LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(item->getAssetUUID());
  996. avatar->userSetOptionalTE( hit_face, image);
  997. }
  998. */
  999. void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj,
  1000. S32 hit_face,
  1001. LLInventoryItem* item,
  1002. LLToolDragAndDrop::ESource source,
  1003. const LLUUID& src_id)
  1004. {
  1005. if (hit_face == -1) return;
  1006. if (!item)
  1007. {
  1008. llwarns << "LLToolDragAndDrop::dropTextureOneFace no texture item." << llendl;
  1009. return;
  1010. }
  1011. LLUUID asset_id = item->getAssetUUID();
  1012. BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
  1013. if (!success)
  1014. {
  1015. return;
  1016. }
  1017. // update viewer side image in anticipation of update from simulator
  1018. LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id);
  1019. LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT );
  1020. hit_obj->setTEImage(hit_face, image);
  1021. dialog_refresh_all();
  1022. // send the update to the simulator
  1023. hit_obj->sendTEUpdate();
  1024. }
  1025. void LLToolDragAndDrop::dropScript(LLViewerObject* hit_obj,
  1026. LLInventoryItem* item,
  1027. BOOL active,
  1028. ESource source,
  1029. const LLUUID& src_id)
  1030. {
  1031. // *HACK: In order to resolve SL-22177, we need to block drags
  1032. // from notecards and objects onto other objects.
  1033. if ((SOURCE_WORLD == LLToolDragAndDrop::getInstance()->mSource)
  1034. || (SOURCE_NOTECARD == LLToolDragAndDrop::getInstance()->mSource))
  1035. {
  1036. llwarns << "Call to LLToolDragAndDrop::dropScript() from world"
  1037. << " or notecard." << llendl;
  1038. return;
  1039. }
  1040. if (hit_obj && item)
  1041. {
  1042. LLPointer<LLViewerInventoryItem> new_script = new LLViewerInventoryItem(item);
  1043. if (!item->getPermissions().allowCopyBy(gAgent.getID()))
  1044. {
  1045. if (SOURCE_AGENT == source)
  1046. {
  1047. // Remove the script from local inventory. The server
  1048. // will actually remove the item from agent inventory.
  1049. gInventory.deleteObject(item->getUUID());
  1050. gInventory.notifyObservers();
  1051. }
  1052. else if (SOURCE_WORLD == source)
  1053. {
  1054. // *FIX: if the objects are in different regions, and
  1055. // the source region has crashed, you can bypass
  1056. // these permissions.
  1057. LLViewerObject* src_obj = gObjectList.findObject(src_id);
  1058. if (src_obj)
  1059. {
  1060. src_obj->removeInventory(item->getUUID());
  1061. }
  1062. else
  1063. {
  1064. llwarns << "Unable to find source object." << llendl;
  1065. return;
  1066. }
  1067. }
  1068. }
  1069. hit_obj->saveScript(new_script, active, true);
  1070. gFloaterTools->dirty();
  1071. // VEFFECT: SetScript
  1072. LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
  1073. effectp->setSourceObject(gAgentAvatarp);
  1074. effectp->setTargetObject(hit_obj);
  1075. effectp->setDuration(LL_HUD_DUR_SHORT);
  1076. effectp->setColor(LLColor4U(gAgent.getEffectColor()));
  1077. }
  1078. }
  1079. void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target,
  1080. BOOL bypass_sim_raycast,
  1081. BOOL from_task_inventory,
  1082. BOOL remove_from_inventory)
  1083. {
  1084. LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal(mLastHitPos);
  1085. if (!regionp)
  1086. {
  1087. llwarns << "Couldn't find region to rez object" << llendl;
  1088. return;
  1089. }
  1090. //llinfos << "Rezzing object" << llendl;
  1091. make_ui_sound("UISndObjectRezIn");
  1092. LLViewerInventoryItem* item;
  1093. LLViewerInventoryCategory* cat;
  1094. locateInventory(item, cat);
  1095. if (!item || !item->isFinished()) return;
  1096. //if (regionp
  1097. // && (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX))
  1098. //{
  1099. // LLFirstUse::useSandbox();
  1100. //}
  1101. // check if it cannot be copied, and mark as remove if it is -
  1102. // this will remove the object from inventory after rez. Only
  1103. // bother with this check if we would not normally remove from
  1104. // inventory.
  1105. if (!remove_from_inventory
  1106. && !item->getPermissions().allowCopyBy(gAgent.getID()))
  1107. {
  1108. remove_from_inventory = TRUE;
  1109. }
  1110. // Limit raycast to a single object.
  1111. // Speeds up server raycast + avoid problems with server ray
  1112. // hitting objects that were clipped by the near plane or culled
  1113. // on the viewer.
  1114. LLUUID ray_target_id;
  1115. if (raycast_target)
  1116. {
  1117. ray_target_id = raycast_target->getID();
  1118. }
  1119. else
  1120. {
  1121. ray_target_id.setNull();
  1122. }
  1123. // Check if it's in the trash.
  1124. bool is_in_trash = false;
  1125. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  1126. if (gInventory.isObjectDescendentOf(item->getUUID(), trash_id))
  1127. {
  1128. is_in_trash = true;
  1129. remove_from_inventory = TRUE;
  1130. }
  1131. LLUUID source_id = from_task_inventory ? mSourceID : LLUUID::null;
  1132. // Select the object only if we're editing.
  1133. BOOL rez_selected = LLToolMgr::getInstance()->inEdit();
  1134. LLVector3 ray_start = regionp->getPosRegionFromGlobal(mLastCameraPos);
  1135. LLVector3 ray_end = regionp->getPosRegionFromGlobal(mLastHitPos);
  1136. // currently the ray's end point is an approximation,
  1137. // and is sometimes too short (causing failure.) so we
  1138. // double the ray's length:
  1139. if (bypass_sim_raycast == FALSE)
  1140. {
  1141. LLVector3 ray_direction = ray_start - ray_end;
  1142. ray_end = ray_end - ray_direction;
  1143. }
  1144. // Message packing code should be it's own uninterrupted block
  1145. LLMessageSystem* msg = gMessageSystem;
  1146. if (mSource == SOURCE_NOTECARD)
  1147. {
  1148. msg->newMessageFast(_PREHASH_RezObjectFromNotecard);
  1149. }
  1150. else
  1151. {
  1152. msg->newMessageFast(_PREHASH_RezObject);
  1153. }
  1154. msg->nextBlockFast(_PREHASH_AgentData);
  1155. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  1156. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  1157. msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
  1158. msg->nextBlock("RezData");
  1159. // if it's being rezzed from task inventory, we need to enable
  1160. // saving it back into the task inventory.
  1161. // *FIX: We can probably compress this to a single byte, since I
  1162. // think folderid == mSourceID. This will be a later
  1163. // optimization.
  1164. msg->addUUIDFast(_PREHASH_FromTaskID, source_id);
  1165. msg->addU8Fast(_PREHASH_BypassRaycast, (U8) bypass_sim_raycast);
  1166. msg->addVector3Fast(_PREHASH_RayStart, ray_start);
  1167. msg->addVector3Fast(_PREHASH_RayEnd, ray_end);
  1168. msg->addUUIDFast(_PREHASH_RayTargetID, ray_target_id );
  1169. msg->addBOOLFast(_PREHASH_RayEndIsIntersection, FALSE);
  1170. msg->addBOOLFast(_PREHASH_RezSelected, rez_selected);
  1171. msg->addBOOLFast(_PREHASH_RemoveItem, remove_from_inventory);
  1172. // deal with permissions slam logic
  1173. pack_permissions_slam(msg, item->getFlags(), item->getPermissions());
  1174. LLUUID folder_id = item->getParentUUID();
  1175. if ((SOURCE_LIBRARY == mSource) || (is_in_trash))
  1176. {
  1177. // since it's coming from the library or trash, we want to not
  1178. // 'take' it back to the same place.
  1179. item->setParent(LLUUID::null);
  1180. // *TODO this code isn't working - the parent (FolderID) is still
  1181. // set when the object is "taken". so code on the "take" side is
  1182. // checking for trash and library as well (llviewermenu.cpp)
  1183. }
  1184. if (mSource == SOURCE_NOTECARD)
  1185. {
  1186. msg->nextBlockFast(_PREHASH_NotecardData);
  1187. msg->addUUIDFast(_PREHASH_NotecardItemID, mSourceID);
  1188. msg->addUUIDFast(_PREHASH_ObjectID, mObjectID);
  1189. msg->nextBlockFast(_PREHASH_InventoryData);
  1190. msg->addUUIDFast(_PREHASH_ItemID, item->getUUID());
  1191. }
  1192. else
  1193. {
  1194. msg->nextBlockFast(_PREHASH_InventoryData);
  1195. item->packMessage(msg);
  1196. }
  1197. msg->sendReliable(regionp->getHost());
  1198. // back out the change. no actual internal changes take place.
  1199. item->setParent(folder_id);
  1200. // If we're going to select it, get ready for the incoming
  1201. // selected object.
  1202. if (rez_selected)
  1203. {
  1204. LLSelectMgr::getInstance()->deselectAll();
  1205. gViewerWindow->getWindow()->incBusyCount();
  1206. }
  1207. if (remove_from_inventory)
  1208. {
  1209. // Delete it from inventory immediately so that users cannot
  1210. // easily bypass copy protection in laggy situations. If the
  1211. // rez fails, we will put it back on the server.
  1212. gInventory.deleteObject(item->getUUID());
  1213. gInventory.notifyObservers();
  1214. }
  1215. // VEFFECT: DropObject
  1216. LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
  1217. effectp->setSourceObject(gAgentAvatarp);
  1218. effectp->setPositionGlobal(mLastHitPos);
  1219. effectp->setDuration(LL_HUD_DUR_SHORT);
  1220. effectp->setColor(LLColor4U(gAgent.getEffectColor()));
  1221. LLViewerStats::getInstance()->incStat(LLViewerStats::ST_REZ_COUNT);
  1222. }
  1223. void LLToolDragAndDrop::dropInventory(LLViewerObject* hit_obj,
  1224. LLInventoryItem* item,
  1225. LLToolDragAndDrop::ESource source,
  1226. const LLUUID& src_id)
  1227. {
  1228. // *HACK: In order to resolve SL-22177, we need to block drags
  1229. // from notecards and objects onto other objects.
  1230. if ((SOURCE_WORLD == LLToolDragAndDrop::getInstance()->mSource)
  1231. || (SOURCE_NOTECARD == LLToolDragAndDrop::getInstance()->mSource))
  1232. {
  1233. llwarns << "Call to LLToolDragAndDrop::dropInventory() from world"
  1234. << " or notecard." << llendl;
  1235. return;
  1236. }
  1237. LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
  1238. time_t creation_date = time_corrected();
  1239. new_item->setCreationDate(creation_date);
  1240. if (!item->getPermissions().allowCopyBy(gAgent.getID()))
  1241. {
  1242. if (SOURCE_AGENT == source)
  1243. {
  1244. // Remove the inventory item from local inventory. The
  1245. // server will actually remove the item from agent
  1246. // inventory.
  1247. gInventory.deleteObject(item->getUUID());
  1248. gInventory.notifyObservers();
  1249. }
  1250. else if (SOURCE_WORLD == source)
  1251. {
  1252. // *FIX: if the objects are in different regions, and the
  1253. // source region has crashed, you can bypass these
  1254. // permissions.
  1255. LLViewerObject* src_obj = gObjectList.findObject(src_id);
  1256. if (src_obj)
  1257. {
  1258. src_obj->removeInventory(item->getUUID());
  1259. }
  1260. else
  1261. {
  1262. llwarns << "Unable to find source object." << llendl;
  1263. return;
  1264. }
  1265. }
  1266. }
  1267. hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
  1268. if (LLFloaterReg::instanceVisible("build"))
  1269. {
  1270. // *FIX: only show this if panel not expanded?
  1271. LLFloaterReg::showInstance("build", "Content");
  1272. }
  1273. // VEFFECT: AddToInventory
  1274. LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
  1275. effectp->setSourceObject(gAgentAvatarp);
  1276. effectp->setTargetObject(hit_obj);
  1277. effectp->setDuration(LL_HUD_DUR_SHORT);
  1278. effectp->setColor(LLColor4U(gAgent.getEffectColor()));
  1279. gFloaterTools->dirty();
  1280. }
  1281. // accessor that looks at permissions, copyability, and names of
  1282. // inventory items to determine if a drop would be ok.
  1283. EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item)
  1284. {
  1285. // check the basics
  1286. if (!item || !obj) return ACCEPT_NO;
  1287. // HACK: downcast
  1288. LLViewerInventoryItem* vitem = (LLViewerInventoryItem*)item;
  1289. if (!vitem->isFinished()) return ACCEPT_NO;
  1290. if (vitem->getIsLinkType()) return ACCEPT_NO; // No giving away links
  1291. // deny attempts to drop from an object onto itself. This is to
  1292. // help make sure that drops that are from an object to an object
  1293. // don't have to worry about order of evaluation. Think of this
  1294. // like check for self in assignment.
  1295. if(obj->getID() == item->getParentUUID())
  1296. {
  1297. return ACCEPT_NO;
  1298. }
  1299. //BOOL copy = (perm.allowCopyBy(gAgent.getID(),
  1300. // gAgent.getGroupID())
  1301. // && (obj->mPermModify || obj->mFlagAllowInventoryAdd));
  1302. BOOL worn = FALSE;
  1303. LLVOAvatarSelf* my_avatar = NULL;
  1304. switch(item->getType())
  1305. {
  1306. case LLAssetType::AT_OBJECT:
  1307. my_avatar = gAgentAvatarp;
  1308. if(my_avatar && my_avatar->isWearingAttachment(item->getUUID()))
  1309. {
  1310. worn = TRUE;
  1311. }
  1312. break;
  1313. case LLAssetType::AT_BODYPART:
  1314. case LLAssetType::AT_CLOTHING:
  1315. if(gAgentWearables.isWearingItem(item->getUUID()))
  1316. {
  1317. worn = TRUE;
  1318. }
  1319. break;
  1320. case LLAssetType::AT_CALLINGCARD:
  1321. // Calling Cards in object are disabled for now
  1322. // because of incomplete LSL support. See STORM-1117.
  1323. return ACCEPT_NO;
  1324. default:
  1325. break;
  1326. }
  1327. const LLPermissions& perm = item->getPermissions();
  1328. BOOL modify = (obj->permModify() || obj->flagAllowInventoryAdd());
  1329. BOOL transfer = FALSE;
  1330. if((obj->permYouOwner() && (perm.getOwner() == gAgent.getID()))
  1331. || perm.allowOperationBy(PERM_TRANSFER, gAgent.getID()))
  1332. {
  1333. transfer = TRUE;
  1334. }
  1335. BOOL volume = (LL_PCODE_VOLUME == obj->getPCode());
  1336. BOOL attached = obj->isAttachment();
  1337. BOOL unrestricted = ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) ? TRUE : FALSE;
  1338. if(attached && !unrestricted)
  1339. {
  1340. return ACCEPT_NO_LOCKED;
  1341. }
  1342. else if(modify && transfer && volume && !worn)
  1343. {
  1344. return ACCEPT_YES_MULTI;
  1345. }
  1346. else if(!modify)
  1347. {
  1348. return ACCEPT_NO_LOCKED;
  1349. }
  1350. return ACCEPT_NO;
  1351. }
  1352. static void give_inventory_cb(const LLSD& notification, const LLSD& response)
  1353. {
  1354. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  1355. // if Cancel pressed
  1356. if (option == 1)
  1357. {
  1358. return;
  1359. }
  1360. LLSD payload = notification["payload"];
  1361. const LLUUID& session_id = payload["session_id"];
  1362. const LLUUID& agent_id = payload["agent_id"];
  1363. LLViewerInventoryItem * inv_item = gInventory.getItem(payload["item_id"]);
  1364. if (NULL == inv_item)
  1365. {
  1366. llassert(NULL != inv_item);
  1367. return;
  1368. }
  1369. if (LLGiveInventory::doGiveInventoryItem(agent_id, inv_item, session_id))
  1370. {
  1371. if ("avatarpicker" == payload["d&d_dest"].asString())
  1372. {
  1373. LLFloaterReg::hideInstance("avatar_picker");
  1374. }
  1375. LLNotificationsUtil::add("ItemsShared");
  1376. }
  1377. }
  1378. static void show_item_sharing_confirmation(const std::string name,
  1379. LLViewerInventoryItem* inv_item,
  1380. const LLSD& dest,
  1381. const LLUUID& dest_agent,
  1382. const LLUUID& session_id = LLUUID::null)
  1383. {
  1384. if (!inv_item)
  1385. {
  1386. llassert(NULL != inv_item);
  1387. return;
  1388. }
  1389. LLSD substitutions;
  1390. substitutions["RESIDENTS"] = name;
  1391. substitutions["ITEMS"] = inv_item->getName();
  1392. LLSD payload;
  1393. payload["agent_id"] = dest_agent;
  1394. payload["item_id"] = inv_item->getUUID();
  1395. payload["session_id"] = session_id;
  1396. payload["d&d_dest"] = dest.asString();
  1397. LLNotificationsUtil::add("ShareItemsConfirmation", substitutions, payload, &give_inventory_cb);
  1398. }
  1399. static void get_name_cb(const LLUUID& id,
  1400. const std::string& full_name,
  1401. LLViewerInventoryItem* inv_item,
  1402. const LLSD& dest,
  1403. const LLUUID& dest_agent)
  1404. {
  1405. show_item_sharing_confirmation(full_name,
  1406. inv_item,
  1407. dest,
  1408. id,
  1409. LLUUID::null);
  1410. }
  1411. // function used as drag-and-drop handler for simple agent give inventory requests
  1412. //static
  1413. bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_id, BOOL drop,
  1414. EDragAndDropType cargo_type,
  1415. void* cargo_data,
  1416. EAcceptance* accept,
  1417. const LLSD& dest)
  1418. {
  1419. // check the type
  1420. switch(cargo_type)
  1421. {
  1422. case DAD_TEXTURE:
  1423. case DAD_SOUND:
  1424. case DAD_LANDMARK:
  1425. case DAD_SCRIPT:
  1426. case DAD_OBJECT:
  1427. case DAD_NOTECARD:
  1428. case DAD_CLOTHING:
  1429. case DAD_BODYPART:
  1430. case DAD_ANIMATION:
  1431. case DAD_GESTURE:
  1432. case DAD_CALLINGCARD:
  1433. case DAD_MESH:
  1434. {
  1435. LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
  1436. if(gInventory.getItem(inv_item->getUUID())
  1437. && LLGiveInventory::isInventoryGiveAcceptable(inv_item))
  1438. {
  1439. // *TODO: get multiple object transfers working
  1440. *accept = ACCEPT_YES_COPY_SINGLE;
  1441. if(drop)
  1442. {
  1443. LLIMModel::LLIMSession * session = LLIMModel::instance().findIMSession(session_id);
  1444. // If no IM session found get the destination agent's name by id.
  1445. if (NULL == session)
  1446. {
  1447. std::string fullname;
  1448. // If destination agent's name is found in cash proceed to showing the confirmation dialog.
  1449. // Otherwise set up a callback to show the dialog when the name arrives.
  1450. if (gCacheName->getFullName(dest_agent, fullname))
  1451. {
  1452. show_item_sharing_confirmation(fullname, inv_item, dest, dest_agent, LLUUID::null);
  1453. }
  1454. else
  1455. {
  1456. gCacheName->get(dest_agent, false, boost::bind(&get_name_cb, _1, _2, inv_item, dest, dest_agent));
  1457. }
  1458. return true;
  1459. }
  1460. // If an IM session with destination agent is found item offer will be logged in this session.
  1461. show_item_sharing_confirmation(session->mName, inv_item, dest, dest_agent, session_id);
  1462. }
  1463. }
  1464. else
  1465. {
  1466. // It's not in the user's inventory (it's probably
  1467. // in an object's contents), so disallow dragging
  1468. // it here. You can't give something you don't
  1469. // yet have.
  1470. *accept = ACCEPT_NO;
  1471. }
  1472. break;
  1473. }
  1474. case DAD_CATEGORY:
  1475. {
  1476. LLViewerInventoryCategory* inv_cat = (LLViewerInventoryCategory*)cargo_data;
  1477. if( gInventory.getCategory( inv_cat->getUUID() ) )
  1478. {
  1479. // *TODO: get multiple object transfers working
  1480. *accept = ACCEPT_YES_COPY_SINGLE;
  1481. if(drop)
  1482. {
  1483. LLGiveInventory::doGiveInventoryCategory(dest_agent, inv_cat, session_id);
  1484. }
  1485. }
  1486. else
  1487. {
  1488. // It's not in the user's inventory (it's probably
  1489. // in an object's contents), so disallow dragging
  1490. // it here. You can't give something you don't
  1491. // yet have.
  1492. *accept = ACCEPT_NO;
  1493. }
  1494. break;
  1495. }
  1496. default:
  1497. *accept = ACCEPT_NO;
  1498. break;
  1499. }
  1500. return TRUE;
  1501. }
  1502. ///
  1503. /// Methods called in the drag & drop array
  1504. ///
  1505. EAcceptance LLToolDragAndDrop::dad3dNULL(
  1506. LLViewerObject*, S32, MASK, BOOL)
  1507. {
  1508. lldebugs << "LLToolDragAndDrop::dad3dNULL()" << llendl;
  1509. return ACCEPT_NO;
  1510. }
  1511. EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv(
  1512. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  1513. {
  1514. lldebugs << "LLToolDragAndDrop::dad3dRezAttachmentFromInv()" << llendl;
  1515. // must be in the user's inventory
  1516. if(mSource != SOURCE_AGENT && mSource != SOURCE_LIBRARY)
  1517. {
  1518. return ACCEPT_NO;
  1519. }
  1520. LLViewerInventoryItem* item;
  1521. LLViewerInventoryCategory* cat;
  1522. locateInventory(item, cat);
  1523. if (!item || !item->isFinished()) return ACCEPT_NO;
  1524. // must not be in the trash
  1525. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  1526. if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) )
  1527. {
  1528. return ACCEPT_NO;
  1529. }
  1530. // must not be already wearing it
  1531. LLVOAvatarSelf* avatar = gAgentAvatarp;
  1532. if( !avatar || avatar->isWearingAttachment(item->getUUID()) )
  1533. {
  1534. return ACCEPT_NO;
  1535. }
  1536. const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
  1537. if(gInventory.isObjectDescendentOf(item->getUUID(), outbox_id))
  1538. {
  1539. return ACCEPT_NO;
  1540. }
  1541. if( drop )
  1542. {
  1543. if(mSource == SOURCE_LIBRARY)
  1544. {
  1545. LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(0);
  1546. copy_inventory_item(
  1547. gAgent.getID(),
  1548. item->getPermissions().getOwner(),
  1549. item->getUUID(),
  1550. LLUUID::null,
  1551. std::string(),
  1552. cb);
  1553. }
  1554. else
  1555. {
  1556. rez_attachment(item, 0);
  1557. }
  1558. }
  1559. return ACCEPT_YES_SINGLE;
  1560. }
  1561. EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand(
  1562. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  1563. {
  1564. if (mSource == SOURCE_WORLD)
  1565. {
  1566. return dad3dRezFromObjectOnLand(obj, face, mask, drop);
  1567. }
  1568. lldebugs << "LLToolDragAndDrop::dad3dRezObjectOnLand()" << llendl;
  1569. LLViewerInventoryItem* item;
  1570. LLViewerInventoryCategory* cat;
  1571. locateInventory(item, cat);
  1572. if (!item || !item->isFinished()) return ACCEPT_NO;
  1573. LLVOAvatarSelf* my_avatar = gAgentAvatarp;
  1574. if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) )
  1575. {
  1576. return ACCEPT_NO;
  1577. }
  1578. EAcceptance accept;
  1579. BOOL remove_inventory;
  1580. // Get initial settings based on shift key
  1581. if (mask & MASK_SHIFT)
  1582. {
  1583. // For now, always make copy
  1584. //accept = ACCEPT_YES_SINGLE;
  1585. //remove_inventory = TRUE;
  1586. accept = ACCEPT_YES_COPY_SINGLE;
  1587. remove_inventory = FALSE;
  1588. }
  1589. else
  1590. {
  1591. accept = ACCEPT_YES_COPY_SINGLE;
  1592. remove_inventory = FALSE;
  1593. }
  1594. // check if the item can be copied. If not, send that to the sim
  1595. // which will remove the inventory item.
  1596. if(!item->getPermissions().allowCopyBy(gAgent.getID()))
  1597. {
  1598. accept = ACCEPT_YES_SINGLE;
  1599. remove_inventory = TRUE;
  1600. }
  1601. // Check if it's in the trash.
  1602. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  1603. if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id))
  1604. {
  1605. accept = ACCEPT_YES_SINGLE;
  1606. remove_inventory = TRUE;
  1607. }
  1608. if(drop)
  1609. {
  1610. dropObject(obj, TRUE, FALSE, remove_inventory);
  1611. }
  1612. return accept;
  1613. }
  1614. EAcceptance LLToolDragAndDrop::dad3dRezObjectOnObject(
  1615. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  1616. {
  1617. // handle objects coming from object inventory
  1618. if (mSource == SOURCE_WORLD)
  1619. {
  1620. return dad3dRezFromObjectOnObject(obj, face, mask, drop);
  1621. }
  1622. lldebugs << "LLToolDragAndDrop::dad3dRezObjectOnObject()" << llendl;
  1623. LLViewerInventoryItem* item;
  1624. LLViewerInventoryCategory* cat;
  1625. locateInventory(item, cat);
  1626. if (!item || !item->isFinished()) return ACCEPT_NO;
  1627. LLVOAvatarSelf* my_avatar = gAgentAvatarp;
  1628. if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) )
  1629. {
  1630. return ACCEPT_NO;
  1631. }
  1632. if((mask & MASK_CONTROL))
  1633. {
  1634. // *HACK: In order to resolve SL-22177, we need to block drags
  1635. // from notecards and objects onto other objects.
  1636. if(mSource == SOURCE_NOTECARD)
  1637. {
  1638. return ACCEPT_NO;
  1639. }
  1640. EAcceptance rv = willObjectAcceptInventory(obj, item);
  1641. if(drop && (ACCEPT_YES_SINGLE <= rv))
  1642. {
  1643. dropInventory(obj, item, mSource, mSourceID);
  1644. }
  1645. return rv;
  1646. }
  1647. EAcceptance accept;
  1648. BOOL remove_inventory;
  1649. if (mask & MASK_SHIFT)
  1650. {
  1651. // For now, always make copy
  1652. //accept = ACCEPT_YES_SINGLE;
  1653. //remove_inventory = TRUE;
  1654. accept = ACCEPT_YES_COPY_SINGLE;
  1655. remove_inventory = FALSE;
  1656. }
  1657. else
  1658. {
  1659. accept = ACCEPT_YES_COPY_SINGLE;
  1660. remove_inventory = FALSE;
  1661. }
  1662. // check if the item can be copied. If not, send that to the sim
  1663. // which will remove the inventory item.
  1664. if(!item->getPermissions().allowCopyBy(gAgent.getID()))
  1665. {
  1666. accept = ACCEPT_YES_SINGLE;
  1667. remove_inventory = TRUE;
  1668. }
  1669. // Check if it's in the trash.
  1670. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  1671. if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id))
  1672. {
  1673. accept = ACCEPT_YES_SINGLE;
  1674. remove_inventory = TRUE;
  1675. }
  1676. if(drop)
  1677. {
  1678. dropObject(obj, FALSE, FALSE, remove_inventory);
  1679. }
  1680. return accept;
  1681. }
  1682. EAcceptance LLToolDragAndDrop::dad3dRezScript(
  1683. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  1684. {
  1685. lldebugs << "LLToolDragAndDrop::dad3dRezScript()" << llendl;
  1686. // *HACK: In order to resolve SL-22177, we need to block drags
  1687. // from notecards and objects onto other objects.
  1688. if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource))
  1689. {
  1690. return ACCEPT_NO;
  1691. }
  1692. LLViewerInventoryItem* item;
  1693. LLViewerInventoryCategory* cat;
  1694. locateInventory(item, cat);
  1695. if (!item || !item->isFinished()) return ACCEPT_NO;
  1696. EAcceptance rv = willObjectAcceptInventory(obj, item);
  1697. if(drop && (ACCEPT_YES_SINGLE <= rv))
  1698. {
  1699. // rez in the script active by default, rez in inactive if the
  1700. // control key is being held down.
  1701. BOOL active = ((mask & MASK_CONTROL) == 0);
  1702. LLViewerObject* root_object = obj;
  1703. if (obj && obj->getParent())
  1704. {
  1705. LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent();
  1706. if (!parent_obj->isAvatar())
  1707. {
  1708. root_object = parent_obj;
  1709. }
  1710. }
  1711. dropScript(root_object, item, active, mSource, mSourceID);
  1712. }
  1713. return rv;
  1714. }
  1715. EAcceptance LLToolDragAndDrop::dad3dApplyToObject(
  1716. LLViewerObject* obj, S32 face, MASK mask, BOOL drop, EDragAndDropType cargo_type)
  1717. {
  1718. lldebugs << "LLToolDragAndDrop::dad3dApplyToObject()" << llendl;
  1719. // *HACK: In order to resolve SL-22177, we need to block drags
  1720. // from notecards and objects onto other objects.
  1721. if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource))
  1722. {
  1723. return ACCEPT_NO;
  1724. }
  1725. LLViewerInventoryItem* item;
  1726. LLViewerInventoryCategory* cat;
  1727. locateInventory(item, cat);
  1728. if (!item || !item->isFinished()) return ACCEPT_NO;
  1729. EAcceptance rv = willObjectAcceptInventory(obj, item);
  1730. if((mask & MASK_CONTROL))
  1731. {
  1732. if((ACCEPT_YES_SINGLE <= rv) && drop)
  1733. {
  1734. dropInventory(obj, item, mSource, mSourceID);
  1735. }
  1736. return rv;
  1737. }
  1738. if(!obj->permModify())
  1739. {
  1740. return ACCEPT_NO_LOCKED;
  1741. }
  1742. //If texture !copyable don't texture or you'll never get it back.
  1743. if(!item->getPermissions().allowCopyBy(gAgent.getID()))
  1744. {
  1745. return ACCEPT_NO;
  1746. }
  1747. if(drop && (ACCEPT_YES_SINGLE <= rv))
  1748. {
  1749. if (cargo_type == DAD_TEXTURE)
  1750. {
  1751. if((mask & MASK_SHIFT))
  1752. {
  1753. dropTextureAllFaces(obj, item, mSource, mSourceID);
  1754. }
  1755. else
  1756. {
  1757. dropTextureOneFace(obj, face, item, mSource, mSourceID);
  1758. }
  1759. }
  1760. else if (cargo_type == DAD_MESH)
  1761. {
  1762. dropMesh(obj, item, mSource, mSourceID);
  1763. }
  1764. else
  1765. {
  1766. llwarns << "unsupported asset type" << llendl;
  1767. }
  1768. // VEFFECT: SetTexture
  1769. LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
  1770. effectp->setSourceObject(gAgentAvatarp);
  1771. effectp->setTargetObject(obj);
  1772. effectp->setDuration(LL_HUD_DUR_SHORT);
  1773. effectp->setColor(LLColor4U(gAgent.getEffectColor()));
  1774. }
  1775. // enable multi-drop, although last texture will win
  1776. return ACCEPT_YES_MULTI;
  1777. }
  1778. EAcceptance LLToolDragAndDrop::dad3dTextureObject(
  1779. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  1780. {
  1781. return dad3dApplyToObject(obj, face, mask, drop, DAD_TEXTURE);
  1782. }
  1783. EAcceptance LLToolDragAndDrop::dad3dMeshObject(
  1784. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  1785. {
  1786. return dad3dApplyToObject(obj, face, mask, drop, DAD_MESH);
  1787. }
  1788. /*
  1789. EAcceptance LLToolDragAndDrop::dad3dTextureSelf(
  1790. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  1791. {
  1792. lldebugs << "LLToolDragAndDrop::dad3dTextureAvatar()" << llendl;
  1793. if(drop)
  1794. {
  1795. if( !(mask & MASK_SHIFT) )
  1796. {
  1797. dropTextureOneFaceAvatar( (LLVOAvatar*)obj, face, (LLInventoryItem*)mCargoData);
  1798. }
  1799. }
  1800. return (mask & MASK_SHIFT) ? ACCEPT_NO : ACCEPT_YES_SINGLE;
  1801. }
  1802. */
  1803. EAcceptance LLToolDragAndDrop::dad3dWearItem(
  1804. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  1805. {
  1806. lldebugs << "LLToolDragAndDrop::dad3dWearItem()" << llendl;
  1807. LLViewerInventoryItem* item;
  1808. LLViewerInventoryCategory* cat;
  1809. locateInventory(item, cat);
  1810. if (!item || !item->isFinished()) return ACCEPT_NO;
  1811. if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY)
  1812. {
  1813. // it's in the agent inventory
  1814. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  1815. if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) )
  1816. {
  1817. return ACCEPT_NO;
  1818. }
  1819. if( drop )
  1820. {
  1821. // TODO: investigate wearables may not be loaded at this point EXT-8231
  1822. LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(),true, !(mask & MASK_CONTROL));
  1823. }
  1824. return ACCEPT_YES_MULTI;
  1825. }
  1826. else
  1827. {
  1828. // TODO: copy/move item to avatar's inventory and then wear it.
  1829. return ACCEPT_NO;
  1830. }
  1831. }
  1832. EAcceptance LLToolDragAndDrop::dad3dActivateGesture(
  1833. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  1834. {
  1835. lldebugs << "LLToolDragAndDrop::dad3dActivateGesture()" << llendl;
  1836. LLViewerInventoryItem* item;
  1837. LLViewerInventoryCategory* cat;
  1838. locateInventory(item, cat);
  1839. if (!item || !item->isFinished()) return ACCEPT_NO;
  1840. if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY)
  1841. {
  1842. // it's in the agent inventory
  1843. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  1844. if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) )
  1845. {
  1846. return ACCEPT_NO;
  1847. }
  1848. if( drop )
  1849. {
  1850. LLUUID item_id;
  1851. if(mSource == SOURCE_LIBRARY)
  1852. {
  1853. // create item based on that one, and put it on if that
  1854. // was a success.
  1855. LLPointer<LLInventoryCallback> cb = new ActivateGestureCallback();
  1856. copy_inventory_item(
  1857. gAgent.getID(),
  1858. item->getPermissions().getOwner(),
  1859. item->getUUID(),
  1860. LLUUID::null,
  1861. std::string(),
  1862. cb);
  1863. }
  1864. else
  1865. {
  1866. LLGestureMgr::instance().activateGesture(item->getUUID());
  1867. gInventory.updateItem(item);
  1868. gInventory.notifyObservers();
  1869. }
  1870. }
  1871. return ACCEPT_YES_MULTI;
  1872. }
  1873. else
  1874. {
  1875. return ACCEPT_NO;
  1876. }
  1877. }
  1878. EAcceptance LLToolDragAndDrop::dad3dWearCategory(
  1879. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  1880. {
  1881. lldebugs << "LLToolDragAndDrop::dad3dWearCategory()" << llendl;
  1882. LLViewerInventoryItem* item;
  1883. LLViewerInventoryCategory* category;
  1884. locateInventory(item, category);
  1885. if(!category) return ACCEPT_NO;
  1886. if (drop)
  1887. {
  1888. // TODO: investigate wearables may not be loaded at this point EXT-8231
  1889. }
  1890. if(mSource == SOURCE_AGENT)
  1891. {
  1892. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  1893. if( gInventory.isObjectDescendentOf( category->getUUID(), trash_id ) )
  1894. {
  1895. return ACCEPT_NO;
  1896. }
  1897. const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
  1898. if(gInventory.isObjectDescendentOf(category->getUUID(), outbox_id))
  1899. {
  1900. return ACCEPT_NO;
  1901. }
  1902. if(drop)
  1903. {
  1904. BOOL append = ( (mask & MASK_SHIFT) ? TRUE : FALSE );
  1905. LLAppearanceMgr::instance().wearInventoryCategory(category, false, append);
  1906. }
  1907. return ACCEPT_YES_MULTI;
  1908. }
  1909. else if(mSource == SOURCE_LIBRARY)
  1910. {
  1911. if(drop)
  1912. {
  1913. LLAppearanceMgr::instance().wearInventoryCategory(category, true, false);
  1914. }
  1915. return ACCEPT_YES_MULTI;
  1916. }
  1917. else
  1918. {
  1919. // TODO: copy/move category to avatar's inventory and then wear it.
  1920. return ACCEPT_NO;
  1921. }
  1922. }
  1923. EAcceptance LLToolDragAndDrop::dad3dUpdateInventory(
  1924. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  1925. {
  1926. lldebugs << "LLToolDragAndDrop::dadUpdateInventory()" << llendl;
  1927. // *HACK: In order to resolve SL-22177, we need to block drags
  1928. // from notecards and objects onto other objects.
  1929. if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource))
  1930. {
  1931. return ACCEPT_NO;
  1932. }
  1933. LLViewerInventoryItem* item;
  1934. LLViewerInventoryCategory* cat;
  1935. locateInventory(item, cat);
  1936. if (!item || !item->isFinished()) return ACCEPT_NO;
  1937. LLViewerObject* root_object = obj;
  1938. if (obj && obj->getParent())
  1939. {
  1940. LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent();
  1941. if (!parent_obj->isAvatar())
  1942. {
  1943. root_object = parent_obj;
  1944. }
  1945. }
  1946. EAcceptance rv = willObjectAcceptInventory(root_object, item);
  1947. if(root_object && drop && (ACCEPT_YES_COPY_SINGLE <= rv))
  1948. {
  1949. dropInventory(root_object, item, mSource, mSourceID);
  1950. }
  1951. return rv;
  1952. }
  1953. BOOL LLToolDragAndDrop::dadUpdateInventory(LLViewerObject* obj, BOOL drop)
  1954. {
  1955. EAcceptance rv = dad3dUpdateInventory(obj, -1, MASK_NONE, drop);
  1956. return (rv >= ACCEPT_YES_COPY_SINGLE);
  1957. }
  1958. EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory(
  1959. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  1960. {
  1961. lldebugs << "LLToolDragAndDrop::dad3dUpdateInventoryCategory()" << llendl;
  1962. if (obj == NULL)
  1963. {
  1964. llwarns << "obj is NULL; aborting func with ACCEPT_NO" << llendl;
  1965. return ACCEPT_NO;
  1966. }
  1967. if ((mSource != SOURCE_AGENT) && (mSource != SOURCE_LIBRARY))
  1968. {
  1969. return ACCEPT_NO;
  1970. }
  1971. if (obj->isAttachment())
  1972. {
  1973. return ACCEPT_NO_LOCKED;
  1974. }
  1975. LLViewerInventoryItem* item = NULL;
  1976. LLViewerInventoryCategory* cat = NULL;
  1977. locateInventory(item, cat);
  1978. if (!cat)
  1979. {
  1980. return ACCEPT_NO;
  1981. }
  1982. // Find all the items in the category
  1983. LLDroppableItem droppable(!obj->permYouOwner());
  1984. LLInventoryModel::cat_array_t cats;
  1985. LLInventoryModel::item_array_t items;
  1986. gInventory.collectDescendentsIf(cat->getUUID(),
  1987. cats,
  1988. items,
  1989. LLInventoryModel::EXCLUDE_TRASH,
  1990. droppable);
  1991. cats.put(cat);
  1992. if (droppable.countNoCopy() > 0)
  1993. {
  1994. llwarns << "*** Need to confirm this step" << llendl;
  1995. }
  1996. LLViewerObject* root_object = obj;
  1997. if (obj->getParent())
  1998. {
  1999. LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent();
  2000. if (!parent_obj->isAvatar())
  2001. {
  2002. root_object = parent_obj;
  2003. }
  2004. }
  2005. EAcceptance rv = ACCEPT_NO;
  2006. // Check for accept
  2007. for (LLInventoryModel::cat_array_t::const_iterator cat_iter = cats.begin();
  2008. cat_iter != cats.end();
  2009. ++cat_iter)
  2010. {
  2011. const LLViewerInventoryCategory *cat = (*cat_iter);
  2012. rv = gInventory.isCategoryComplete(cat->getUUID()) ? ACCEPT_YES_MULTI : ACCEPT_NO;
  2013. if(rv < ACCEPT_YES_SINGLE)
  2014. {
  2015. lldebugs << "Category " << cat->getUUID() << "is not complete." << llendl;
  2016. break;
  2017. }
  2018. }
  2019. if (ACCEPT_YES_COPY_SINGLE <= rv)
  2020. {
  2021. for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin();
  2022. item_iter != items.end();
  2023. ++item_iter)
  2024. {
  2025. LLViewerInventoryItem *item = (*item_iter);
  2026. /*
  2027. // Pass the base objects, not the links.
  2028. if (item && item->getIsLinkType())
  2029. {
  2030. item = item->getLinkedItem();
  2031. (*item_iter) = item;
  2032. }
  2033. */
  2034. rv = willObjectAcceptInventory(root_object, item);
  2035. if (rv < ACCEPT_YES_COPY_SINGLE)
  2036. {
  2037. lldebugs << "Object will not accept " << item->getUUID() << llendl;
  2038. break;
  2039. }
  2040. }
  2041. }
  2042. // If every item is accepted, send it on
  2043. if (drop && (ACCEPT_YES_COPY_SINGLE <= rv))
  2044. {
  2045. uuid_vec_t ids;
  2046. for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin();
  2047. item_iter != items.end();
  2048. ++item_iter)
  2049. {
  2050. const LLViewerInventoryItem *item = (*item_iter);
  2051. ids.push_back(item->getUUID());
  2052. }
  2053. LLCategoryDropObserver* dropper = new LLCategoryDropObserver(ids, obj->getID(), mSource);
  2054. dropper->startFetch();
  2055. if (dropper->isFinished())
  2056. {
  2057. dropper->done();
  2058. }
  2059. else
  2060. {
  2061. gInventory.addObserver(dropper);
  2062. }
  2063. }
  2064. return rv;
  2065. }
  2066. BOOL LLToolDragAndDrop::dadUpdateInventoryCategory(LLViewerObject* obj,
  2067. BOOL drop)
  2068. {
  2069. EAcceptance rv = dad3dUpdateInventoryCategory(obj, -1, MASK_NONE, drop);
  2070. return (rv >= ACCEPT_YES_COPY_SINGLE);
  2071. }
  2072. EAcceptance LLToolDragAndDrop::dad3dGiveInventoryObject(
  2073. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  2074. {
  2075. lldebugs << "LLToolDragAndDrop::dad3dGiveInventoryObject()" << llendl;
  2076. // item has to be in agent inventory.
  2077. if(mSource != SOURCE_AGENT) return ACCEPT_NO;
  2078. // find the item now.
  2079. LLViewerInventoryItem* item;
  2080. LLViewerInventoryCategory* cat;
  2081. locateInventory(item, cat);
  2082. if (!item || !item->isFinished()) return ACCEPT_NO;
  2083. if(!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
  2084. {
  2085. // cannot give away no-transfer objects
  2086. return ACCEPT_NO;
  2087. }
  2088. LLVOAvatarSelf* avatar = gAgentAvatarp;
  2089. if(avatar && avatar->isWearingAttachment( item->getUUID() ) )
  2090. {
  2091. // You can't give objects that are attached to you
  2092. return ACCEPT_NO;
  2093. }
  2094. if( obj && avatar )
  2095. {
  2096. if(drop)
  2097. {
  2098. LLGiveInventory::doGiveInventoryItem(obj->getID(), item );
  2099. }
  2100. // *TODO: deal with all the issues surrounding multi-object
  2101. // inventory transfers.
  2102. return ACCEPT_YES_SINGLE;
  2103. }
  2104. return ACCEPT_NO;
  2105. }
  2106. EAcceptance LLToolDragAndDrop::dad3dGiveInventory(
  2107. LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
  2108. {
  2109. lldebugs << "LLToolDragAndDrop::dad3dGiveInventory()" << llendl;
  2110. // item has to be in agent inventory.
  2111. if(mSource != SOURCE_AGENT) return ACCEPT_NO;
  2112. LLViewerInventoryItem* item;
  2113. LLViewerInventoryCategory* cat;
  2114. locateInventory(