00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "message.h"
00035 #include "lltooldraganddrop.h"
00036
00037 #include "llinstantmessage.h"
00038 #include "lldir.h"
00039
00040 #include "llagent.h"
00041 #include "llviewercontrol.h"
00042 #include "llfirstuse.h"
00043 #include "llfloater.h"
00044 #include "llfloatertools.h"
00045 #include "llgesturemgr.h"
00046 #include "llhudeffecttrail.h"
00047 #include "llhudmanager.h"
00048 #include "llinventorymodel.h"
00049 #include "llinventoryview.h"
00050 #include "llnotify.h"
00051 #include "llpreviewnotecard.h"
00052 #include "llselectmgr.h"
00053 #include "lltoolmgr.h"
00054 #include "llui.h"
00055 #include "llviewerimagelist.h"
00056 #include "llviewerinventory.h"
00057 #include "llviewerobject.h"
00058 #include "llviewerobjectlist.h"
00059 #include "llviewerregion.h"
00060 #include "llviewerstats.h"
00061 #include "llviewerwindow.h"
00062 #include "llvoavatar.h"
00063 #include "llvolume.h"
00064 #include "llworld.h"
00065 #include "object_flags.h"
00066 #include "viewer.h"
00067
00068 LLToolDragAndDrop *gToolDragAndDrop = NULL;
00069
00070
00071
00072
00073 const S32 MAX_ITEMS = 42;
00074 const char* FOLDER_INCLUDES_ATTACHMENTS_BEING_WORN =
00075 "Cannot give folders that contain objects that are attached to you.\n"
00076 "Detach the object(s) and then try again.";
00077
00078
00079
00080 #define callMemberFunction(object,ptrToMember) ((object).*(ptrToMember))
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 class LLNoPreferredType : public LLInventoryCollectFunctor
00114 {
00115 public:
00116 LLNoPreferredType() {}
00117 virtual ~LLNoPreferredType() {}
00118 virtual bool operator()(LLInventoryCategory* cat,
00119 LLInventoryItem* item)
00120 {
00121 if(cat && (cat->getPreferredType() == LLAssetType::AT_NONE))
00122 {
00123 return true;
00124 }
00125 return false;
00126 }
00127 };
00128
00129 class LLNoPreferredTypeOrItem : public LLInventoryCollectFunctor
00130 {
00131 public:
00132 LLNoPreferredTypeOrItem() {}
00133 virtual ~LLNoPreferredTypeOrItem() {}
00134 virtual bool operator()(LLInventoryCategory* cat,
00135 LLInventoryItem* item)
00136 {
00137 if(item) return true;
00138 if(cat && (cat->getPreferredType() == LLAssetType::AT_NONE))
00139 {
00140 return true;
00141 }
00142 return false;
00143 }
00144 };
00145
00146 class LLDroppableItem : public LLInventoryCollectFunctor
00147 {
00148 public:
00149 LLDroppableItem(BOOL is_transfer) :
00150 mCountLosing(0), mIsTransfer(is_transfer) {}
00151 virtual ~LLDroppableItem() {}
00152 virtual bool operator()(LLInventoryCategory* cat,
00153 LLInventoryItem* item);
00154 S32 countNoCopy() const { return mCountLosing; }
00155
00156 protected:
00157 S32 mCountLosing;
00158 BOOL mIsTransfer;
00159 };
00160
00161 bool LLDroppableItem::operator()(LLInventoryCategory* cat,
00162 LLInventoryItem* item)
00163 {
00164 bool allowed = false;
00165 if(item)
00166 {
00167 LLVOAvatar* my_avatar = NULL;
00168 switch(item->getType())
00169 {
00170 case LLAssetType::AT_CALLINGCARD:
00171
00172 break;
00173
00174 case LLAssetType::AT_OBJECT:
00175 my_avatar = gAgent.getAvatarObject();
00176 if(my_avatar && !my_avatar->isWearingAttachment(item->getUUID()))
00177 {
00178 allowed = true;
00179 }
00180 break;
00181
00182 case LLAssetType::AT_BODYPART:
00183 case LLAssetType::AT_CLOTHING:
00184 if(!gAgent.isWearingItem(item->getUUID()))
00185 {
00186 allowed = true;
00187 }
00188 break;
00189
00190 default:
00191 allowed = true;
00192 break;
00193 }
00194 if(mIsTransfer
00195 && !item->getPermissions().allowOperationBy(PERM_TRANSFER,
00196 gAgent.getID()))
00197 {
00198 allowed = false;
00199 }
00200 if(allowed && !item->getPermissions().allowCopyBy(gAgent.getID()))
00201 {
00202 ++mCountLosing;
00203 }
00204 }
00205 return allowed;
00206 }
00207
00208 class LLUncopyableItems : public LLInventoryCollectFunctor
00209 {
00210 public:
00211 LLUncopyableItems() {}
00212 virtual ~LLUncopyableItems() {}
00213 virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
00214 };
00215
00216 bool LLUncopyableItems::operator()(LLInventoryCategory* cat,
00217 LLInventoryItem* item)
00218 {
00219 BOOL uncopyable = FALSE;
00220 if(item)
00221 {
00222 BOOL allowed = FALSE;
00223 LLVOAvatar* my_avatar = NULL;
00224 switch(item->getType())
00225 {
00226 case LLAssetType::AT_CALLINGCARD:
00227
00228 break;
00229
00230 case LLAssetType::AT_OBJECT:
00231 my_avatar = gAgent.getAvatarObject();
00232 if(my_avatar && !my_avatar->isWearingAttachment(item->getUUID()))
00233 {
00234 allowed = TRUE;
00235 }
00236 break;
00237
00238 case LLAssetType::AT_BODYPART:
00239 case LLAssetType::AT_CLOTHING:
00240 if(!gAgent.isWearingItem(item->getUUID()))
00241 {
00242 allowed = TRUE;
00243 }
00244 break;
00245
00246 default:
00247 allowed = TRUE;
00248 break;
00249 }
00250 if(allowed && !item->getPermissions().allowCopyBy(gAgent.getID()))
00251 {
00252 uncopyable = TRUE;
00253 }
00254 }
00255 return (uncopyable ? true : false);
00256 }
00257
00258 class LLDropCopyableItems : public LLInventoryCollectFunctor
00259 {
00260 public:
00261 LLDropCopyableItems() {}
00262 virtual ~LLDropCopyableItems() {}
00263 virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
00264 };
00265
00266
00267 bool LLDropCopyableItems::operator()(
00268 LLInventoryCategory* cat, LLInventoryItem* item)
00269 {
00270 BOOL allowed = FALSE;
00271 if(item)
00272 {
00273 LLVOAvatar* my_avatar = NULL;
00274 switch(item->getType())
00275 {
00276 case LLAssetType::AT_CALLINGCARD:
00277
00278 break;
00279
00280 case LLAssetType::AT_OBJECT:
00281 my_avatar = gAgent.getAvatarObject();
00282 if(my_avatar && !my_avatar->isWearingAttachment(item->getUUID()))
00283 {
00284 allowed = TRUE;
00285 }
00286 break;
00287
00288 case LLAssetType::AT_BODYPART:
00289 case LLAssetType::AT_CLOTHING:
00290 if(!gAgent.isWearingItem(item->getUUID()))
00291 {
00292 allowed = TRUE;
00293 }
00294 break;
00295
00296 default:
00297 allowed = TRUE;
00298 break;
00299 }
00300 if(allowed && !item->getPermissions().allowCopyBy(gAgent.getID()))
00301 {
00302
00303 allowed = FALSE;
00304 }
00305 }
00306 return (allowed ? true : false);
00307 }
00308
00309 class LLGiveable : public LLInventoryCollectFunctor
00310 {
00311 public:
00312 LLGiveable() : mCountLosing(0) {}
00313 virtual ~LLGiveable() {}
00314 virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
00315
00316 S32 countNoCopy() const { return mCountLosing; }
00317 protected:
00318 S32 mCountLosing;
00319 };
00320
00321 bool LLGiveable::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
00322 {
00323
00324 if(cat) return TRUE;
00325 BOOL allowed = FALSE;
00326 if(item)
00327 {
00328 LLVOAvatar* my_avatar = NULL;
00329 switch(item->getType())
00330 {
00331 case LLAssetType::AT_CALLINGCARD:
00332
00333 break;
00334
00335 case LLAssetType::AT_OBJECT:
00336 my_avatar = gAgent.getAvatarObject();
00337 if(my_avatar && !my_avatar->isWearingAttachment(item->getUUID()))
00338 {
00339 allowed = TRUE;
00340 }
00341 break;
00342
00343 case LLAssetType::AT_BODYPART:
00344 case LLAssetType::AT_CLOTHING:
00345 if(!gAgent.isWearingItem(item->getUUID()))
00346 {
00347 allowed = TRUE;
00348 }
00349 break;
00350
00351 default:
00352 allowed = TRUE;
00353 break;
00354 }
00355 if(!item->getPermissions().allowOperationBy(PERM_TRANSFER,
00356 gAgent.getID()))
00357 {
00358 allowed = FALSE;
00359 }
00360 if(allowed && !item->getPermissions().allowCopyBy(gAgent.getID()))
00361 {
00362 ++mCountLosing;
00363 }
00364 }
00365 return (allowed ? true : false);
00366 }
00367
00368 class LLCategoryFireAndForget : public LLInventoryFetchComboObserver
00369 {
00370 public:
00371 LLCategoryFireAndForget() {}
00372 ~LLCategoryFireAndForget() {}
00373 virtual void done()
00374 {
00375
00376 lldebugs << "LLCategoryFireAndForget::done()" << llendl;
00377 }
00378 };
00379
00380 class LLCategoryDropObserver : public LLInventoryFetchObserver
00381 {
00382 public:
00383 LLCategoryDropObserver(
00384 const LLUUID& obj_id, LLToolDragAndDrop::ESource src) :
00385 mObjectID(obj_id),
00386 mSource(src)
00387 {}
00388 ~LLCategoryDropObserver() {}
00389 virtual void done();
00390
00391 protected:
00392 LLUUID mObjectID;
00393 LLToolDragAndDrop::ESource mSource;
00394 };
00395
00396 void LLCategoryDropObserver::done()
00397 {
00398 gInventory.removeObserver(this);
00399 LLViewerObject* dst_obj = gObjectList.findObject(mObjectID);
00400 if(dst_obj)
00401 {
00402
00403 LLInventoryItem* item = NULL;
00404 item_ref_t::iterator it = mComplete.begin();
00405 item_ref_t::iterator end = mComplete.end();
00406 for(; it < end; ++it)
00407 {
00408 item = gInventory.getItem(*it);
00409 if(item)
00410 {
00411 LLToolDragAndDrop::dropInventory(
00412 dst_obj,
00413 item,
00414 mSource,
00415 LLUUID::null);
00416 }
00417 }
00418 }
00419 delete this;
00420 }
00421
00422 class LLCategoryDropDescendentsObserver : public LLInventoryFetchDescendentsObserver
00423 {
00424 public:
00425 LLCategoryDropDescendentsObserver(
00426 const LLUUID& obj_id, LLToolDragAndDrop::ESource src) :
00427 mObjectID(obj_id),
00428 mSource(src)
00429 {}
00430 ~LLCategoryDropDescendentsObserver() {}
00431 virtual void done();
00432
00433 protected:
00434 LLUUID mObjectID;
00435 LLToolDragAndDrop::ESource mSource;
00436 };
00437
00438 void LLCategoryDropDescendentsObserver::done()
00439 {
00440
00441 gInventory.removeObserver(this);
00442 folder_ref_t::iterator it = mCompleteFolders.begin();
00443 folder_ref_t::iterator end = mCompleteFolders.end();
00444 LLViewerInventoryCategory::cat_array_t cats;
00445 LLViewerInventoryItem::item_array_t items;
00446 for(; it != end; ++it)
00447 {
00448 gInventory.collectDescendents(
00449 (*it),
00450 cats,
00451 items,
00452 LLInventoryModel::EXCLUDE_TRASH);
00453 }
00454
00455 S32 count = items.count();
00456 if(count)
00457 {
00458 std::set<LLUUID> unique_ids;
00459 for(S32 i = 0; i < count; ++i)
00460 {
00461 unique_ids.insert(items.get(i)->getUUID());
00462 }
00463 LLInventoryFetchObserver::item_ref_t ids;
00464 std::back_insert_iterator<LLInventoryFetchObserver::item_ref_t> copier(ids);
00465 std::copy(unique_ids.begin(), unique_ids.end(), copier);
00466 LLCategoryDropObserver* dropper;
00467 dropper = new LLCategoryDropObserver(mObjectID, mSource);
00468 dropper->fetchItems(ids);
00469 if(dropper->isEverythingComplete())
00470 {
00471 dropper->done();
00472 }
00473 else
00474 {
00475 gInventory.addObserver(dropper);
00476 }
00477 }
00478 delete this;
00479 }
00480
00481
00482
00483
00484
00485 LLToolDragAndDrop::dragOrDrop3dImpl LLToolDragAndDrop::sDragAndDrop3d[DAD_COUNT][LLToolDragAndDrop::DT_COUNT] =
00486 {
00487
00488 {
00489 &LLToolDragAndDrop::dad3dNULL,
00490 &LLToolDragAndDrop::dad3dNULL,
00491 &LLToolDragAndDrop::dad3dNULL,
00492 &LLToolDragAndDrop::dad3dNULL,
00493 &LLToolDragAndDrop::dad3dNULL,
00494 },
00495
00496 {
00497 &LLToolDragAndDrop::dad3dNULL,
00498 &LLToolDragAndDrop::dad3dNULL,
00499 &LLToolDragAndDrop::dad3dGiveInventory,
00500 &LLToolDragAndDrop::dad3dTextureObject,
00501 &LLToolDragAndDrop::dad3dNULL,
00502 },
00503
00504 {
00505 &LLToolDragAndDrop::dad3dNULL,
00506 &LLToolDragAndDrop::dad3dNULL,
00507 &LLToolDragAndDrop::dad3dGiveInventory,
00508 &LLToolDragAndDrop::dad3dUpdateInventory,
00509 &LLToolDragAndDrop::dad3dNULL,
00510 },
00511
00512 {
00513 &LLToolDragAndDrop::dad3dNULL,
00514 &LLToolDragAndDrop::dad3dNULL,
00515 &LLToolDragAndDrop::dad3dNULL,
00516 &LLToolDragAndDrop::dad3dNULL,
00517 &LLToolDragAndDrop::dad3dNULL,
00518 },
00519
00520 {
00521 &LLToolDragAndDrop::dad3dNULL,
00522 &LLToolDragAndDrop::dad3dNULL,
00523 &LLToolDragAndDrop::dad3dGiveInventory,
00524 &LLToolDragAndDrop::dad3dUpdateInventory,
00525 &LLToolDragAndDrop::dad3dNULL,
00526 },
00527
00528 {
00529 &LLToolDragAndDrop::dad3dNULL,
00530 &LLToolDragAndDrop::dad3dNULL,
00531 &LLToolDragAndDrop::dad3dGiveInventory,
00532 &LLToolDragAndDrop::dad3dRezScript,
00533 &LLToolDragAndDrop::dad3dNULL,
00534 },
00535
00536 {
00537 &LLToolDragAndDrop::dad3dNULL,
00538 &LLToolDragAndDrop::dad3dWearItem,
00539 &LLToolDragAndDrop::dad3dGiveInventory,
00540 &LLToolDragAndDrop::dad3dUpdateInventory,
00541 &LLToolDragAndDrop::dad3dNULL,
00542 },
00543
00544 {
00545 &LLToolDragAndDrop::dad3dNULL,
00546 &LLToolDragAndDrop::dad3dRezAttachmentFromInv,
00547 &LLToolDragAndDrop::dad3dGiveInventoryObject,
00548 &LLToolDragAndDrop::dad3dRezObjectOnObject,
00549 &LLToolDragAndDrop::dad3dRezObjectOnLand,
00550 },
00551
00552 {
00553 &LLToolDragAndDrop::dad3dNULL,
00554 &LLToolDragAndDrop::dad3dNULL,
00555 &LLToolDragAndDrop::dad3dGiveInventory,
00556 &LLToolDragAndDrop::dad3dUpdateInventory,
00557 &LLToolDragAndDrop::dad3dNULL,
00558 },
00559
00560 {
00561 &LLToolDragAndDrop::dad3dNULL,
00562 &LLToolDragAndDrop::dad3dWearCategory,
00563 &LLToolDragAndDrop::dad3dGiveInventoryCategory,
00564 &LLToolDragAndDrop::dad3dUpdateInventoryCategory,
00565 &LLToolDragAndDrop::dad3dNULL,
00566 },
00567
00568 {
00569 &LLToolDragAndDrop::dad3dNULL,
00570 &LLToolDragAndDrop::dad3dNULL,
00571 &LLToolDragAndDrop::dad3dNULL,
00572 &LLToolDragAndDrop::dad3dNULL,
00573 &LLToolDragAndDrop::dad3dNULL,
00574 },
00575
00576 {
00577 &LLToolDragAndDrop::dad3dNULL,
00578 &LLToolDragAndDrop::dad3dWearItem,
00579 &LLToolDragAndDrop::dad3dGiveInventory,
00580 &LLToolDragAndDrop::dad3dUpdateInventory,
00581 &LLToolDragAndDrop::dad3dNULL,
00582 },
00583
00584
00585 {
00586 &LLToolDragAndDrop::dad3dNULL,
00587 &LLToolDragAndDrop::dad3dNULL,
00588 &LLToolDragAndDrop::dad3dGiveInventory,
00589 &LLToolDragAndDrop::dad3dUpdateInventory,
00590 &LLToolDragAndDrop::dad3dNULL,
00591 },
00592
00593
00594 {
00595 &LLToolDragAndDrop::dad3dNULL,
00596 &LLToolDragAndDrop::dad3dActivateGesture,
00597 &LLToolDragAndDrop::dad3dGiveInventory,
00598 &LLToolDragAndDrop::dad3dUpdateInventory,
00599 &LLToolDragAndDrop::dad3dNULL,
00600 },
00601 };
00602
00603 LLToolDragAndDrop::LLToolDragAndDrop()
00604 :
00605 LLTool("draganddrop", NULL),
00606 mDragStartX(0),
00607 mDragStartY(0),
00608 mSource(SOURCE_AGENT),
00609 mCursor(UI_CURSOR_NO),
00610 mLastAccept(ACCEPT_NO),
00611 mDrop(FALSE),
00612 mCurItemIndex(0)
00613 {
00614
00615
00616
00617
00618
00619 }
00620
00621 void LLToolDragAndDrop::setDragStart(S32 x, S32 y)
00622 {
00623 mDragStartX = x;
00624 mDragStartY = y;
00625 }
00626
00627 BOOL LLToolDragAndDrop::isOverThreshold(S32 x,S32 y)
00628 {
00629 const S32 MIN_MANHATTAN_DIST = 3;
00630 S32 manhattan_dist = llabs( x - mDragStartX ) + llabs( y - mDragStartY );
00631 return manhattan_dist >= MIN_MANHATTAN_DIST;
00632 }
00633
00634 void LLToolDragAndDrop::beginDrag(EDragAndDropType type,
00635 const LLUUID& cargo_id,
00636 ESource source,
00637 const LLUUID& source_id,
00638 const LLUUID& object_id)
00639 {
00640 if(type == DAD_NONE)
00641 {
00642 llwarns << "Attempted to start drag without a cargo type" << llendl;
00643 return;
00644 }
00645 mCargoTypes.clear();
00646 mCargoTypes.push_back(type);
00647 mCargoIDs.clear();
00648 mCargoIDs.push_back(cargo_id);
00649 mSource = source;
00650 mSourceID = source_id;
00651 mObjectID = object_id;
00652
00653 setMouseCapture( TRUE );
00654 gToolMgr->setTransientTool( this );
00655 mCursor = UI_CURSOR_NO;
00656 if((mCargoTypes[0] == DAD_CATEGORY)
00657 && ((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY)))
00658 {
00659 LLInventoryCategory* cat = gInventory.getCategory(cargo_id);
00660
00661
00662 if(cat)
00663 {
00664 LLViewerInventoryCategory::cat_array_t cats;
00665 LLViewerInventoryItem::item_array_t items;
00666 LLNoPreferredTypeOrItem is_not_preferred;
00667 LLInventoryFetchComboObserver::folder_ref_t folder_ids;
00668 LLInventoryFetchComboObserver::item_ref_t item_ids;
00669 if(is_not_preferred(cat, NULL))
00670 {
00671 folder_ids.push_back(cargo_id);
00672 }
00673 gInventory.collectDescendentsIf(
00674 cargo_id,
00675 cats,
00676 items,
00677 LLInventoryModel::EXCLUDE_TRASH,
00678 is_not_preferred);
00679 S32 count = cats.count();
00680 S32 i;
00681 for(i = 0; i < count; ++i)
00682 {
00683 folder_ids.push_back(cats.get(i)->getUUID());
00684 }
00685 count = items.count();
00686 for(i = 0; i < count; ++i)
00687 {
00688 item_ids.push_back(items.get(i)->getUUID());
00689 }
00690 if(!folder_ids.empty() || !item_ids.empty())
00691 {
00692 LLCategoryFireAndForget fetcher;
00693 fetcher.fetch(folder_ids, item_ids);
00694 }
00695 }
00696 }
00697 }
00698
00699 void LLToolDragAndDrop::beginMultiDrag(
00700 const std::vector<EDragAndDropType> types,
00701 const std::vector<LLUUID>& cargo_ids,
00702 ESource source,
00703 const LLUUID& source_id)
00704 {
00705
00706
00707
00708 std::vector<EDragAndDropType>::const_iterator types_it;
00709 for (types_it = types.begin(); types_it != types.end(); ++types_it)
00710 {
00711 if(DAD_NONE == *types_it)
00712 {
00713 llwarns << "Attempted to start drag without a cargo type" << llendl;
00714 return;
00715 }
00716 }
00717 mCargoTypes = types;
00718 mCargoIDs = cargo_ids;
00719 mSource = source;
00720 mSourceID = source_id;
00721
00722 setMouseCapture( TRUE );
00723 gToolMgr->setTransientTool( this );
00724 mCursor = UI_CURSOR_NO;
00725 if((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY))
00726 {
00727
00728 LLInventoryCategory* cat = NULL;
00729 S32 count = llmin(cargo_ids.size(), types.size());
00730 std::set<LLUUID> cat_ids;
00731 for(S32 i = 0; i < count; ++i)
00732 {
00733 cat = gInventory.getCategory(cargo_ids[i]);
00734 if(cat)
00735 {
00736 LLViewerInventoryCategory::cat_array_t cats;
00737 LLViewerInventoryItem::item_array_t items;
00738 LLNoPreferredType is_not_preferred;
00739 if(is_not_preferred(cat, NULL))
00740 {
00741 cat_ids.insert(cat->getUUID());
00742 }
00743 gInventory.collectDescendentsIf(
00744 cat->getUUID(),
00745 cats,
00746 items,
00747 LLInventoryModel::EXCLUDE_TRASH,
00748 is_not_preferred);
00749 S32 cat_count = cats.count();
00750 for(S32 i = 0; i < cat_count; ++i)
00751 {
00752 cat_ids.insert(cat->getUUID());
00753 }
00754 }
00755 }
00756 if(!cat_ids.empty())
00757 {
00758 LLInventoryFetchComboObserver::folder_ref_t folder_ids;
00759 LLInventoryFetchComboObserver::item_ref_t item_ids;
00760 std::back_insert_iterator<LLInventoryFetchDescendentsObserver::folder_ref_t> copier(folder_ids);
00761 std::copy(cat_ids.begin(), cat_ids.end(), copier);
00762 LLCategoryFireAndForget fetcher;
00763 fetcher.fetch(folder_ids, item_ids);
00764 }
00765 }
00766 }
00767
00768 void LLToolDragAndDrop::endDrag()
00769 {
00770 gSelectMgr->unhighlightAll();
00771 setMouseCapture(FALSE);
00772 }
00773
00774 void LLToolDragAndDrop::onMouseCaptureLost()
00775 {
00776
00777 gToolMgr->clearTransientTool();
00778 mCargoTypes.clear();
00779 mCargoIDs.clear();
00780 mSource = SOURCE_AGENT;
00781 mSourceID.setNull();
00782 mObjectID.setNull();
00783 }
00784
00785 BOOL LLToolDragAndDrop::handleMouseUp( S32 x, S32 y, MASK mask )
00786 {
00787 if( hasMouseCapture() )
00788 {
00789 EAcceptance acceptance = ACCEPT_NO;
00790 dragOrDrop( x, y, mask, TRUE, &acceptance );
00791 endDrag();
00792 }
00793 return TRUE;
00794 }
00795
00796 BOOL LLToolDragAndDrop::handleHover( S32 x, S32 y, MASK mask )
00797 {
00798 EAcceptance acceptance = ACCEPT_NO;
00799 dragOrDrop( x, y, mask, FALSE, &acceptance );
00800
00801 switch( acceptance )
00802 {
00803 case ACCEPT_YES_MULTI:
00804 if (mCargoIDs.size() > 1)
00805 {
00806 mCursor = UI_CURSOR_ARROWDRAGMULTI;
00807 }
00808 else
00809 {
00810 mCursor = UI_CURSOR_ARROWDRAG;
00811 }
00812 break;
00813 case ACCEPT_YES_SINGLE:
00814 mCursor = UI_CURSOR_ARROWDRAG;
00815 break;
00816
00817 case ACCEPT_NO_LOCKED:
00818 mCursor = UI_CURSOR_NOLOCKED;
00819 break;
00820
00821 case ACCEPT_NO:
00822 mCursor = UI_CURSOR_NO;
00823 break;
00824
00825 case ACCEPT_YES_COPY_MULTI:
00826 if (mCargoIDs.size() > 1)
00827 {
00828 mCursor = UI_CURSOR_ARROWCOPYMULTI;
00829 }
00830 else
00831 {
00832 mCursor = UI_CURSOR_ARROWCOPY;
00833 }
00834 break;
00835 case ACCEPT_YES_COPY_SINGLE:
00836 mCursor = UI_CURSOR_ARROWCOPY;
00837 break;
00838 case ACCEPT_POSTPONED:
00839 break;
00840 default:
00841 llassert( FALSE );
00842 }
00843
00844 gViewerWindow->getWindow()->setCursor( mCursor );
00845 lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolDragAndDrop" << llendl;
00846 return TRUE;
00847 }
00848
00849 BOOL LLToolDragAndDrop::handleKey(KEY key, MASK mask)
00850 {
00851 if (key == KEY_ESCAPE)
00852 {
00853
00854 endDrag();
00855 return TRUE;
00856 }
00857
00858 return FALSE;
00859 }
00860
00861 BOOL LLToolDragAndDrop::handleToolTip(S32 x, S32 y, LLString& msg, LLRect *sticky_rect_screen)
00862 {
00863 if (!mToolTipMsg.empty())
00864 {
00865 msg = mToolTipMsg;
00866
00867 return TRUE;
00868 }
00869 return FALSE;
00870 }
00871
00872 void LLToolDragAndDrop::handleDeselect()
00873 {
00874 mToolTipMsg.clear();
00875 }
00876
00877
00878 void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,
00879 EAcceptance* acceptance)
00880 {
00881 *acceptance = ACCEPT_YES_MULTI;
00882
00883 BOOL handled = FALSE;
00884
00885 LLView* top_view = gViewerWindow->getTopCtrl();
00886 LLViewerInventoryItem* item;
00887 LLViewerInventoryCategory* cat;
00888
00889 mToolTipMsg.assign("");
00890
00891 if(top_view)
00892 {
00893 handled = TRUE;
00894
00895 for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
00896 {
00897 LLInventoryObject* cargo = locateInventory(item, cat);
00898
00899 if (cargo)
00900 {
00901 S32 local_x, local_y;
00902 top_view->screenPointToLocal( x, y, &local_x, &local_y );
00903 EAcceptance item_acceptance = ACCEPT_NO;
00904 handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE,
00905 mCargoTypes[mCurItemIndex],
00906 (void*)cargo,
00907 &item_acceptance,
00908 mToolTipMsg);
00909 if (handled)
00910 {
00911
00912 *acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance);
00913 }
00914 }
00915 else
00916 {
00917 return;
00918 }
00919 }
00920
00921
00922 if (handled && drop && (U32)*acceptance >= ACCEPT_YES_COPY_SINGLE)
00923 {
00924
00925 if ((U32)*acceptance >= ACCEPT_YES_COPY_MULTI)
00926 {
00927 mCurItemIndex = 0;
00928 }
00929
00930 else
00931 {
00932 mCurItemIndex = mCargoIDs.size() - 1;
00933 }
00934 for (; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
00935 {
00936 LLInventoryObject* cargo = locateInventory(item, cat);
00937
00938 if (cargo)
00939 {
00940 S32 local_x, local_y;
00941
00942 EAcceptance item_acceptance;
00943 top_view->screenPointToLocal( x, y, &local_x, &local_y );
00944 handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, TRUE,
00945 mCargoTypes[mCurItemIndex],
00946 (void*)cargo,
00947 &item_acceptance,
00948 mToolTipMsg);
00949 }
00950 }
00951 }
00952 if (handled)
00953 {
00954 mLastAccept = (EAcceptance)*acceptance;
00955 }
00956 }
00957
00958 if(!handled)
00959 {
00960 handled = TRUE;
00961
00962 LLView* root_view = gViewerWindow->getRootView();
00963
00964 for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
00965 {
00966 LLInventoryObject* cargo = locateInventory(item, cat);
00967
00968 EAcceptance item_acceptance = ACCEPT_NO;
00969 handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE,
00970 mCargoTypes[mCurItemIndex],
00971 (void*)cargo,
00972 &item_acceptance,
00973 mToolTipMsg);
00974 if (handled)
00975 {
00976
00977 *acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance);
00978 }
00979 }
00980
00981 if (handled && drop && (U32)*acceptance > ACCEPT_NO_LOCKED)
00982 {
00983
00984 if ((U32)*acceptance >= ACCEPT_YES_COPY_MULTI)
00985 {
00986 mCurItemIndex = 0;
00987 }
00988
00989 else
00990 {
00991 mCurItemIndex = mCargoIDs.size() - 1;
00992 }
00993 for (; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++)
00994 {
00995 LLInventoryObject* cargo = locateInventory(item, cat);
00996
00997 if (cargo)
00998 {
00999
01000
01001 EAcceptance item_acceptance;
01002 handled = handled && root_view->handleDragAndDrop(x, y, mask, TRUE,
01003 mCargoTypes[mCurItemIndex],
01004 (void*)cargo,
01005 &item_acceptance,
01006 mToolTipMsg);
01007 }
01008 }
01009 }
01010
01011 if (handled)
01012 {
01013 mLastAccept = (EAcceptance)*acceptance;
01014 }
01015 }
01016
01017 if ( !handled )
01018 {
01019 dragOrDrop3D( x, y, mask, drop, acceptance );
01020 }
01021 }
01022
01023 void LLToolDragAndDrop::dragOrDrop3D( S32 x, S32 y, MASK mask, BOOL drop, EAcceptance* acceptance )
01024 {
01025 mDrop = drop;
01026 if (mDrop)
01027 {
01028 gPickFaces = TRUE;
01029
01030 gViewerWindow->hitObjectOrLandGlobalImmediate(x, y, pickCallback, FALSE);
01031 }
01032 else
01033 {
01034
01035
01036
01037 gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback, FALSE);
01038 }
01039
01040 *acceptance = mLastAccept;
01041 }
01042
01043 void LLToolDragAndDrop::pickCallback(S32 x, S32 y, MASK mask)
01044 {
01045 EDropTarget target = DT_NONE;
01046 S32 hit_face = -1;
01047
01048 LLViewerObject* hit_obj = gViewerWindow->lastNonFloraObjectHit();
01049 gSelectMgr->unhighlightAll();
01050
01051
01052 if (hit_obj)
01053 {
01054 if(hit_obj->isAttachment() && !hit_obj->isHUDAttachment())
01055 {
01056 LLVOAvatar* avatar = LLVOAvatar::findAvatarFromAttachment( hit_obj );
01057 if( !avatar )
01058 {
01059 gToolDragAndDrop->mLastAccept = ACCEPT_NO;
01060 gToolDragAndDrop->mCursor = UI_CURSOR_NO;
01061 gViewerWindow->getWindow()->setCursor( gToolDragAndDrop->mCursor );
01062 return;
01063 }
01064
01065 hit_obj = avatar;
01066 }
01067
01068 if(hit_obj->isAvatar())
01069 {
01070 if(((LLVOAvatar*) hit_obj)->mIsSelf)
01071 {
01072 target = DT_SELF;
01073 hit_face = -1;
01074 }
01075 else
01076 {
01077 target = DT_AVATAR;
01078 hit_face = -1;
01079 }
01080 }
01081 else
01082 {
01083 target = DT_OBJECT;
01084 hit_face = gLastHitNonFloraObjectFace;
01085
01086
01087 for (S32 i = 0; i < (S32)gToolDragAndDrop->mCargoIDs.size(); i++)
01088 {
01089 if (gToolDragAndDrop->mCargoTypes[i] != DAD_OBJECT || (mask & MASK_CONTROL))
01090 {
01091 gSelectMgr->highlightObjectAndFamily(hit_obj);
01092 break;
01093 }
01094 }
01095 }
01096 }
01097 else if(gLastHitLand)
01098 {
01099 target = DT_LAND;
01100 hit_face = -1;
01101 }
01102
01103 gToolDragAndDrop->mLastAccept = ACCEPT_YES_MULTI;
01104
01105 for (gToolDragAndDrop->mCurItemIndex = 0; gToolDragAndDrop->mCurItemIndex < (S32)gToolDragAndDrop->mCargoIDs.size();
01106 gToolDragAndDrop->mCurItemIndex++)
01107 {
01108
01109 gToolDragAndDrop->mLastAccept = (EAcceptance)llmin(
01110 (U32)gToolDragAndDrop->mLastAccept,
01111 (U32)callMemberFunction((*gToolDragAndDrop),
01112 gToolDragAndDrop->sDragAndDrop3d[gToolDragAndDrop->mCargoTypes[gToolDragAndDrop->mCurItemIndex]][target])
01113 (hit_obj, hit_face, mask, FALSE));
01114 }
01115
01116 if (gToolDragAndDrop->mDrop && (U32)gToolDragAndDrop->mLastAccept >= ACCEPT_YES_COPY_SINGLE)
01117 {
01118
01119 if (gToolDragAndDrop->mLastAccept >= ACCEPT_YES_COPY_MULTI)
01120 {
01121 gToolDragAndDrop->mCurItemIndex = 0;
01122 }
01123
01124 else
01125 {
01126 gToolDragAndDrop->mCurItemIndex = gToolDragAndDrop->mCargoIDs.size() - 1;
01127 }
01128
01129 for (; gToolDragAndDrop->mCurItemIndex < (S32)gToolDragAndDrop->mCargoIDs.size();
01130 gToolDragAndDrop->mCurItemIndex++)
01131 {
01132
01133 (U32)callMemberFunction((*gToolDragAndDrop),
01134 gToolDragAndDrop->sDragAndDrop3d[gToolDragAndDrop->mCargoTypes[gToolDragAndDrop->mCurItemIndex]][target])
01135 (hit_obj, hit_face, mask, TRUE);
01136 }
01137 }
01138
01139 switch( gToolDragAndDrop->mLastAccept )
01140 {
01141 case ACCEPT_YES_MULTI:
01142 if (gToolDragAndDrop->mCargoIDs.size() > 1)
01143 {
01144 gToolDragAndDrop->mCursor = UI_CURSOR_ARROWDRAGMULTI;
01145 }
01146 else
01147 {
01148 gToolDragAndDrop->mCursor = UI_CURSOR_ARROWDRAG;
01149 }
01150 break;
01151 case ACCEPT_YES_SINGLE:
01152 gToolDragAndDrop->mCursor = UI_CURSOR_ARROWDRAG;
01153 break;
01154
01155 case ACCEPT_NO_LOCKED:
01156 gToolDragAndDrop->mCursor = UI_CURSOR_NOLOCKED;
01157 break;
01158
01159 case ACCEPT_NO:
01160 gToolDragAndDrop->mCursor = UI_CURSOR_NO;
01161 break;
01162
01163 case ACCEPT_YES_COPY_MULTI:
01164 if (gToolDragAndDrop->mCargoIDs.size() > 1)
01165 {
01166 gToolDragAndDrop->mCursor = UI_CURSOR_ARROWCOPYMULTI;
01167 }
01168 else
01169 {
01170 gToolDragAndDrop->mCursor = UI_CURSOR_ARROWCOPY;
01171 }
01172 break;
01173 case ACCEPT_YES_COPY_SINGLE:
01174 gToolDragAndDrop->mCursor = UI_CURSOR_ARROWCOPY;
01175 break;
01176 case ACCEPT_POSTPONED:
01177 break;
01178 default:
01179 llassert( FALSE );
01180 }
01181
01182 gToolDragAndDrop->mLastHitPos = gLastHitPosGlobal + gLastHitObjectOffset;
01183 gToolDragAndDrop->mLastCameraPos = gAgent.getCameraPositionGlobal();
01184
01185 gViewerWindow->getWindow()->setCursor( gToolDragAndDrop->mCursor );
01186 }
01187
01188
01189 BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj,
01190 LLInventoryItem* item,
01191 LLToolDragAndDrop::ESource source,
01192 const LLUUID& src_id)
01193 {
01194
01195
01196
01197 if(SOURCE_LIBRARY == source)
01198 {
01199
01200 return TRUE;
01201 }
01202
01203 if (hit_obj->getInventoryItemByAsset(item->getAssetUUID()))
01204 {
01205
01206
01207
01208 return TRUE;
01209 }
01210
01211 if (!item) return FALSE;
01212
01213 LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
01214 if(!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
01215 {
01216
01217 if (willObjectAcceptInventory(hit_obj,item) < ACCEPT_YES_COPY_SINGLE )
01218 {
01219 return FALSE;
01220 }
01221
01222 if(SOURCE_AGENT == source)
01223 {
01224
01225
01226 gInventory.deleteObject(item->getUUID());
01227 gInventory.notifyObservers();
01228 }
01229 else if(SOURCE_WORLD == source)
01230 {
01231
01232
01233
01234 LLViewerObject* src_obj = gObjectList.findObject(src_id);
01235 if(src_obj)
01236 {
01237 src_obj->removeInventory(item->getUUID());
01238 }
01239 else
01240 {
01241 llwarns << "Unable to find source object." << llendl;
01242 return FALSE;
01243 }
01244 }
01245 hit_obj->updateInventory(new_item, TASK_INVENTORY_ASSET_KEY, true);
01246 }
01247 else if(!item->getPermissions().allowOperationBy(PERM_TRANSFER,
01248 gAgent.getID()))
01249 {
01250
01251 if (willObjectAcceptInventory(hit_obj,item) < ACCEPT_YES_COPY_SINGLE )
01252 {
01253 return FALSE;
01254 }
01255
01256
01257
01258 hit_obj->updateInventory(new_item, TASK_INVENTORY_ASSET_KEY, true);
01259 }
01260 return TRUE;
01261 }
01262
01263 void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj,
01264 LLInventoryItem* item,
01265 LLToolDragAndDrop::ESource source,
01266 const LLUUID& src_id)
01267 {
01268 if (!item)
01269 {
01270 llwarns << "LLToolDragAndDrop::dropTextureAllFaces no texture item." << llendl;
01271 return;
01272 }
01273 LLUUID asset_id = item->getAssetUUID();
01274 BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
01275 if(!success)
01276 {
01277 return;
01278 }
01279 LLViewerImage* image = gImageList.getImage(asset_id);
01280 gViewerStats->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT );
01281 S32 num_faces = hit_obj->getNumTEs();
01282 for( S32 face = 0; face < num_faces; face++ )
01283 {
01284
01285
01286 hit_obj->setTEImage(face, image);
01287 dialog_refresh_all();
01288 }
01289
01290 hit_obj->sendTEUpdate();
01291 }
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303 void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj,
01304 S32 hit_face,
01305 LLInventoryItem* item,
01306 LLToolDragAndDrop::ESource source,
01307 const LLUUID& src_id)
01308 {
01309 if (hit_face == -1) return;
01310 if (!item)
01311 {
01312 llwarns << "LLToolDragAndDrop::dropTextureOneFace no texture item." << llendl;
01313 return;
01314 }
01315 LLUUID asset_id = item->getAssetUUID();
01316 BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
01317 if(!success)
01318 {
01319 return;
01320 }
01321
01322 LLViewerImage* image = gImageList.getImage(asset_id);
01323 gViewerStats->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT );
01324 hit_obj->setTEImage(hit_face, image);
01325 dialog_refresh_all();
01326
01327
01328 hit_obj->sendTEUpdate();
01329 }
01330
01331
01332 void LLToolDragAndDrop::dropScript(LLViewerObject* hit_obj,
01333 LLInventoryItem* item,
01334 BOOL active,
01335 ESource source,
01336 const LLUUID& src_id)
01337 {
01338
01339
01340 if((SOURCE_WORLD == gToolDragAndDrop->mSource)
01341 || (SOURCE_NOTECARD == gToolDragAndDrop->mSource))
01342 {
01343 llwarns << "Call to LLToolDragAndDrop::dropScript() from world"
01344 << " or notecard." << llendl;
01345 return;
01346 }
01347 if(hit_obj && item)
01348 {
01349 LLPointer<LLViewerInventoryItem> new_script = new LLViewerInventoryItem(item);
01350 if(!item->getPermissions().allowCopyBy(gAgent.getID()))
01351 {
01352 if(SOURCE_AGENT == source)
01353 {
01354
01355
01356 gInventory.deleteObject(item->getUUID());
01357 gInventory.notifyObservers();
01358 }
01359 else if(SOURCE_WORLD == source)
01360 {
01361
01362
01363
01364 LLViewerObject* src_obj = gObjectList.findObject(src_id);
01365 if(src_obj)
01366 {
01367 src_obj->removeInventory(item->getUUID());
01368 }
01369 else
01370 {
01371 llwarns << "Unable to find source object." << llendl;
01372 return;
01373 }
01374 }
01375 }
01376 hit_obj->saveScript(new_script, active, true);
01377 gFloaterTools->dirty();
01378
01379
01380 LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
01381 effectp->setSourceObject(gAgent.getAvatarObject());
01382 effectp->setTargetObject(hit_obj);
01383 effectp->setDuration(LL_HUD_DUR_SHORT);
01384 effectp->setColor(LLColor4U(gAgent.getEffectColor()));
01385 }
01386 }
01387
01388 void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target,
01389 BOOL bypass_sim_raycast,
01390 BOOL from_task_inventory,
01391 BOOL remove_from_inventory)
01392 {
01393 LLViewerRegion* regionp = gWorldp->getRegionFromPosGlobal(mLastHitPos);
01394 if (!regionp)
01395 {
01396 llwarns << "Couldn't find region to rez object" << llendl;
01397 return;
01398 }
01399
01400
01401 make_ui_sound("UISndObjectRezIn");
01402 LLViewerInventoryItem* item;
01403 LLViewerInventoryCategory* cat;
01404 locateInventory(item, cat);
01405 if(!item || !item->isComplete()) return;
01406
01407 if (regionp
01408 && (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX))
01409 {
01410 LLFirstUse::useSandbox();
01411 }
01412
01413
01414
01415
01416 if(!remove_from_inventory
01417 && !item->getPermissions().allowCopyBy(gAgent.getID()))
01418 {
01419 remove_from_inventory = TRUE;
01420 }
01421
01422
01423
01424
01425
01426 LLUUID ray_target_id;
01427 if( raycast_target )
01428 {
01429 ray_target_id = raycast_target->getID();
01430 }
01431 else
01432 {
01433 ray_target_id.setNull();
01434 }
01435
01436
01437 bool is_in_trash = false;
01438 LLUUID trash_id;
01439 trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
01440 if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id))
01441 {
01442 is_in_trash = true;
01443 remove_from_inventory = TRUE;
01444 }
01445
01446 LLUUID source_id = from_task_inventory ? mSourceID : LLUUID::null;
01447
01448
01449 BOOL rez_selected = gToolMgr->inEdit();
01450
01451
01452 LLMessageSystem* msg = gMessageSystem;
01453 if (mSource == SOURCE_NOTECARD)
01454 {
01455 msg->newMessageFast(_PREHASH_RezObjectFromNotecard);
01456 }
01457 else
01458 {
01459 msg->newMessageFast(_PREHASH_RezObject);
01460 }
01461 msg->nextBlockFast(_PREHASH_AgentData);
01462 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
01463 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
01464 msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
01465
01466 msg->nextBlock("RezData");
01467
01468
01469
01470
01471
01472 msg->addUUIDFast(_PREHASH_FromTaskID, source_id);
01473 msg->addU8Fast(_PREHASH_BypassRaycast, (U8) bypass_sim_raycast);
01474 msg->addVector3Fast(_PREHASH_RayStart, regionp->getPosRegionFromGlobal(mLastCameraPos));
01475 msg->addVector3Fast(_PREHASH_RayEnd, regionp->getPosRegionFromGlobal(mLastHitPos));
01476 msg->addUUIDFast(_PREHASH_RayTargetID, ray_target_id );
01477 msg->addBOOLFast(_PREHASH_RayEndIsIntersection, FALSE);
01478 msg->addBOOLFast(_PREHASH_RezSelected, rez_selected);
01479 msg->addBOOLFast(_PREHASH_RemoveItem, remove_from_inventory);
01480
01481
01482 pack_permissions_slam(msg, item->getFlags(), item->getPermissions());
01483
01484 LLUUID folder_id = item->getParentUUID();
01485 if((SOURCE_LIBRARY == mSource) || (is_in_trash))
01486 {
01487
01488
01489 item->setParent(LLUUID::null);
01490
01491
01492
01493 }
01494 if (mSource == SOURCE_NOTECARD)
01495 {
01496 msg->nextBlockFast(_PREHASH_NotecardData);
01497 msg->addUUIDFast(_PREHASH_NotecardItemID, mSourceID);
01498 msg->addUUIDFast(_PREHASH_ObjectID, mObjectID);
01499 msg->nextBlockFast(_PREHASH_InventoryData);
01500 msg->addUUIDFast(_PREHASH_ItemID, item->getUUID());
01501 }
01502 else
01503 {
01504 msg->nextBlockFast(_PREHASH_InventoryData);
01505 item->packMessage(msg);
01506 }
01507 msg->sendReliable(regionp->getHost());
01508
01509 item->setParent(folder_id);
01510
01511
01512
01513 if (rez_selected)
01514 {
01515 gSelectMgr->deselectAll();
01516 gViewerWindow->getWindow()->incBusyCount();
01517 }
01518
01519 if(remove_from_inventory)
01520 {
01521
01522
01523
01524 gInventory.deleteObject(item->getUUID());
01525 gInventory.notifyObservers();
01526 }
01527
01528
01529 LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
01530 effectp->setSourceObject(gAgent.getAvatarObject());
01531 effectp->setPositionGlobal(mLastHitPos);
01532 effectp->setDuration(LL_HUD_DUR_SHORT);
01533 effectp->setColor(LLColor4U(gAgent.getEffectColor()));
01534
01535 gViewerStats->incStat(LLViewerStats::ST_REZ_COUNT);
01536 }
01537
01538 void LLToolDragAndDrop::dropInventory(LLViewerObject* hit_obj,
01539 LLInventoryItem* item,
01540 LLToolDragAndDrop::ESource source,
01541 const LLUUID& src_id)
01542 {
01543
01544
01545 if((SOURCE_WORLD == gToolDragAndDrop->mSource)
01546 || (SOURCE_NOTECARD == gToolDragAndDrop->mSource))
01547 {
01548 llwarns << "Call to LLToolDragAndDrop::dropInventory() from world"
01549 << " or notecard." << llendl;
01550 return;
01551 }
01552
01553 LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
01554 S32 creation_date = time_corrected();
01555 new_item->setCreationDate(creation_date);
01556
01557 if(!item->getPermissions().allowCopyBy(gAgent.getID()))
01558 {
01559 if(SOURCE_AGENT == source)
01560 {
01561
01562
01563
01564 gInventory.deleteObject(item->getUUID());
01565 gInventory.notifyObservers();
01566 }
01567 else if(SOURCE_WORLD == source)
01568 {
01569
01570
01571
01572 LLViewerObject* src_obj = gObjectList.findObject(src_id);
01573 if(src_obj)
01574 {
01575 src_obj->removeInventory(item->getUUID());
01576 }
01577 else
01578 {
01579 llwarns << "Unable to find source object." << llendl;
01580 return;
01581 }
01582 }
01583 }
01584 hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true);
01585 if (gFloaterTools->getVisible())
01586 {
01587
01588 gFloaterTools->showPanel(LLFloaterTools::PANEL_CONTENTS);
01589 }
01590
01591
01592 LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
01593 effectp->setSourceObject(gAgent.getAvatarObject());
01594 effectp->setTargetObject(hit_obj);
01595 effectp->setDuration(LL_HUD_DUR_SHORT);
01596 effectp->setColor(LLColor4U(gAgent.getEffectColor()));
01597 gFloaterTools->dirty();
01598 }
01599
01600 struct LLGiveInventoryInfo
01601 {
01602 LLUUID mToAgentID;
01603 LLUUID mInventoryObjectID;
01604 LLGiveInventoryInfo(const LLUUID& to_agent, const LLUUID& obj_id) :
01605 mToAgentID(to_agent), mInventoryObjectID(obj_id) {}
01606 };
01607
01608 void LLToolDragAndDrop::giveInventory(const LLUUID& to_agent,
01609 LLInventoryItem* item)
01610 {
01611 llinfos << "LLToolDragAndDrop::giveInventory()" << llendl;
01612 if(!isInventoryGiveAcceptable(item))
01613 {
01614 return;
01615 }
01616 if(item->getPermissions().allowCopyBy(gAgent.getID()))
01617 {
01618
01619 LLToolDragAndDrop::commitGiveInventoryItem(to_agent, item);
01620 }
01621 else
01622 {
01623
01624 LLGiveInventoryInfo* info = new LLGiveInventoryInfo(to_agent,
01625 item->getUUID());
01626
01627 gViewerWindow->alertXml("CannotCopyWarning",
01628 &LLToolDragAndDrop::handleCopyProtectedItem,
01629 (void*)info);
01630 }
01631 }
01632
01633
01634 void LLToolDragAndDrop::handleCopyProtectedItem(S32 option, void* data)
01635 {
01636 LLGiveInventoryInfo* info = (LLGiveInventoryInfo*)data;
01637 LLInventoryItem* item = NULL;
01638 switch(option)
01639 {
01640 case 0:
01641 item = gInventory.getItem(info->mInventoryObjectID);
01642 if(item)
01643 {
01644 LLToolDragAndDrop::commitGiveInventoryItem(info->mToAgentID,
01645 item);
01646
01647
01648 gInventory.deleteObject(info->mInventoryObjectID);
01649 gInventory.notifyObservers();
01650 }
01651 else
01652 {
01653 gViewerWindow->alertXml("CannotGiveItem");
01654 }
01655 break;
01656
01657 default:
01658 gViewerWindow->alertXml("TransactionCancelled");
01659 break;
01660 }
01661 }
01662
01663
01664 void LLToolDragAndDrop::commitGiveInventoryItem(const LLUUID& to_agent,
01665 LLInventoryItem* item)
01666 {
01667 if(!item) return;
01668 std::string name;
01669 gAgent.buildFullname(name);
01670 LLUUID transaction_id;
01671 transaction_id.generate();
01672 const S32 BUCKET_SIZE = sizeof(U8) + UUID_BYTES;
01673 U8 bucket[BUCKET_SIZE];
01674 bucket[0] = (U8)item->getType();
01675 memcpy(&bucket[1], &(item->getUUID().mData), UUID_BYTES);
01676 pack_instant_message(
01677 gMessageSystem,
01678 gAgent.getID(),
01679 FALSE,
01680 gAgent.getSessionID(),
01681 to_agent,
01682 name.c_str(),
01683 item->getName().c_str(),
01684 IM_ONLINE,
01685 IM_INVENTORY_OFFERED,
01686 transaction_id,
01687 0,
01688 LLUUID::null,
01689 gAgent.getPositionAgent(),
01690 NO_TIMESTAMP,
01691 bucket,
01692 BUCKET_SIZE);
01693 gAgent.sendReliableMessage();
01694
01695
01696 LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
01697 effectp->setSourceObject(gAgent.getAvatarObject());
01698 effectp->setTargetObject(gObjectList.findObject(to_agent));
01699 effectp->setDuration(LL_HUD_DUR_SHORT);
01700 effectp->setColor(LLColor4U(gAgent.getEffectColor()));
01701 gFloaterTools->dirty();
01702 }
01703
01704 void LLToolDragAndDrop::giveInventoryCategory(const LLUUID& to_agent,
01705 LLInventoryCategory* cat)
01706 {
01707 if(!cat) return;
01708 llinfos << "LLToolDragAndDrop::giveInventoryCategory() - "
01709 << cat->getUUID() << llendl;
01710
01711 LLVOAvatar* my_avatar = gAgent.getAvatarObject();
01712 if( !my_avatar )
01713 {
01714 return;
01715 }
01716
01717
01718 LLViewerInventoryCategory::cat_array_t cats;
01719 LLViewerInventoryItem::item_array_t items;
01720 LLGiveable giveable;
01721 gInventory.collectDescendentsIf(cat->getUUID(),
01722 cats,
01723 items,
01724 LLInventoryModel::EXCLUDE_TRASH,
01725 giveable);
01726 S32 count = cats.count();
01727 bool complete = true;
01728 for(S32 i = 0; i < count; ++i)
01729 {
01730 if(!gInventory.isCategoryComplete(cats.get(i)->getUUID()))
01731 {
01732 complete = false;
01733 break;
01734 }
01735 }
01736 if(!complete)
01737 {
01738 LLNotifyBox::showXml("IncompleteInventory");
01739 return;
01740 }
01741 count = items.count() + cats.count();
01742 if(count > MAX_ITEMS)
01743 {
01744 gViewerWindow->alertXml("TooManyItems");
01745 return;
01746 }
01747 else if(count == 0)
01748 {
01749 gViewerWindow->alertXml("NoItems");
01750 return;
01751 }
01752 else
01753 {
01754 if(0 == giveable.countNoCopy())
01755 {
01756 LLToolDragAndDrop::commitGiveInventoryCategory(to_agent, cat);
01757 }
01758 else
01759 {
01760 LLGiveInventoryInfo* info = NULL;
01761 info = new LLGiveInventoryInfo(to_agent, cat->getUUID());
01762 LLStringBase<char>::format_map_t args;
01763 args["[COUNT]"] = llformat("%d",giveable.countNoCopy());
01764 gViewerWindow->alertXml("CannotCopyCountItems", args,
01765 &LLToolDragAndDrop::handleCopyProtectedCategory,
01766 (void*)info);
01767
01768 }
01769 }
01770 }
01771
01772
01773
01774 void LLToolDragAndDrop::handleCopyProtectedCategory(S32 option, void* data)
01775 {
01776 LLGiveInventoryInfo* info = (LLGiveInventoryInfo*)data;
01777 LLInventoryCategory* cat = NULL;
01778 switch(option)
01779 {
01780 case 0:
01781 cat = gInventory.getCategory(info->mInventoryObjectID);
01782 if(cat)
01783 {
01784 LLToolDragAndDrop::commitGiveInventoryCategory(info->mToAgentID,
01785 cat);
01786 LLViewerInventoryCategory::cat_array_t cats;
01787 LLViewerInventoryItem::item_array_t items;
01788 LLUncopyableItems remove;
01789 gInventory.collectDescendentsIf(cat->getUUID(),
01790 cats,
01791 items,
01792 LLInventoryModel::EXCLUDE_TRASH,
01793 remove);
01794 S32 count = items.count();
01795 for(S32 i = 0; i < count; ++i)
01796 {
01797 gInventory.deleteObject(items.get(i)->getUUID());
01798 }
01799 gInventory.notifyObservers();
01800 }
01801 else
01802 {
01803 gViewerWindow->alertXml("CannotGiveCategory");
01804 }
01805 break;
01806
01807 default:
01808 gViewerWindow->alertXml("TransactionCancelled");
01809 break;
01810 }
01811 }
01812
01813
01814 void LLToolDragAndDrop::commitGiveInventoryCategory(const LLUUID& to_agent,
01815 LLInventoryCategory* cat)
01816 {
01817 if(!cat) return;
01818 llinfos << "LLToolDragAndDrop::commitGiveInventoryCategory() - "
01819 << cat->getUUID() << llendl;
01820
01821
01822 LLViewerInventoryCategory::cat_array_t cats;
01823 LLViewerInventoryItem::item_array_t items;
01824 LLGiveable giveable;
01825 gInventory.collectDescendentsIf(cat->getUUID(),
01826 cats,
01827 items,
01828 LLInventoryModel::EXCLUDE_TRASH,
01829 giveable);
01830
01831
01832
01833
01834 S32 count = items.count() + cats.count();
01835 if(count > MAX_ITEMS)
01836 {
01837 gViewerWindow->alertXml("TooManyItems");
01838 return;
01839 }
01840 else if(count == 0)
01841 {
01842 gViewerWindow->alertXml("NoItems");
01843 return;
01844 }
01845 else
01846 {
01847 std::string name;
01848 gAgent.buildFullname(name);
01849 LLUUID transaction_id;
01850 transaction_id.generate();
01851 S32 bucket_size = (sizeof(U8) + UUID_BYTES) * (count + 1);
01852 U8* bucket = new U8[bucket_size];
01853 U8* pos = bucket;
01854 U8 type = (U8)cat->getType();
01855 memcpy(pos, &type, sizeof(U8));
01856 pos += sizeof(U8);
01857 memcpy(pos, &(cat->getUUID()), UUID_BYTES);
01858 pos += UUID_BYTES;
01859 S32 i;
01860 count = cats.count();
01861 for(i = 0; i < count; ++i)
01862 {
01863 memcpy(pos, &type, sizeof(U8));
01864 pos += sizeof(U8);
01865 memcpy(pos, &(cats.get(i)->getUUID()), UUID_BYTES);
01866 pos += UUID_BYTES;
01867 }
01868 count = items.count();
01869 for(i = 0; i < count; ++i)
01870 {
01871 type = (U8)items.get(i)->getType();
01872 memcpy(pos, &type, sizeof(U8));
01873 pos += sizeof(U8);
01874 memcpy(pos, &(items.get(i)->getUUID()), UUID_BYTES);
01875 pos += UUID_BYTES;
01876 }
01877 pack_instant_message(
01878 gMessageSystem,
01879 gAgent.getID(),
01880 FALSE,
01881 gAgent.getSessionID(),
01882 to_agent,
01883 name.c_str(),
01884 cat->getName().c_str(),
01885 IM_ONLINE,
01886 IM_INVENTORY_OFFERED,
01887 transaction_id,
01888 0,
01889 LLUUID::null,
01890 gAgent.getPositionAgent(),
01891 NO_TIMESTAMP,
01892 bucket,
01893 bucket_size);
01894 gAgent.sendReliableMessage();
01895 delete[] bucket;
01896
01897
01898 LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
01899 effectp->setSourceObject(gAgent.getAvatarObject());
01900 effectp->setTargetObject(gObjectList.findObject(to_agent));
01901 effectp->setDuration(LL_HUD_DUR_SHORT);
01902 effectp->setColor(LLColor4U(gAgent.getEffectColor()));
01903 gFloaterTools->dirty();
01904 }
01905 }
01906
01907
01908 BOOL LLToolDragAndDrop::isInventoryGiveAcceptable(LLInventoryItem* item)
01909 {
01910 if(!item)
01911 {
01912 return FALSE;
01913 }
01914 if(!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
01915 {
01916 return FALSE;
01917 }
01918 BOOL copyable = FALSE;
01919 if(item->getPermissions().allowCopyBy(gAgent.getID())) copyable = TRUE;
01920 LLVOAvatar* my_avatar = gAgent.getAvatarObject();
01921 if(!my_avatar)
01922 {
01923 return FALSE;
01924 }
01925 BOOL acceptable = TRUE;
01926 switch(item->getType())
01927 {
01928 case LLAssetType::AT_CALLINGCARD:
01929 acceptable = FALSE;
01930 break;
01931 case LLAssetType::AT_OBJECT:
01932 if(my_avatar->isWearingAttachment(item->getUUID()))
01933 {
01934 acceptable = FALSE;
01935 }
01936 break;
01937 case LLAssetType::AT_BODYPART:
01938 case LLAssetType::AT_CLOTHING:
01939 if(!copyable && gAgent.isWearingItem(item->getUUID()))
01940 {
01941 acceptable = FALSE;
01942 }
01943 break;
01944 default:
01945 break;
01946 }
01947 return acceptable;
01948 }
01949
01950
01951 BOOL LLToolDragAndDrop::isInventoryGroupGiveAcceptable(LLInventoryItem* item)
01952 {
01953 if(!item)
01954 {
01955 return FALSE;
01956 }
01957
01958
01959
01960 if(!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
01961 {
01962 return FALSE;
01963 }
01964 if(!item->getPermissions().allowCopyBy(gAgent.getID()))
01965 {
01966 return FALSE;
01967 }
01968
01969 LLVOAvatar* my_avatar = gAgent.getAvatarObject();
01970 if(!my_avatar)
01971 {
01972 return FALSE;
01973 }
01974
01975 BOOL acceptable = TRUE;
01976 switch(item->getType())
01977 {
01978 case LLAssetType::AT_CALLINGCARD:
01979 acceptable = FALSE;
01980 break;
01981 case LLAssetType::AT_OBJECT:
01982 if(my_avatar->isWearingAttachment(item->getUUID()))
01983 {
01984 acceptable = FALSE;
01985 }
01986 break;
01987 default:
01988 break;
01989 }
01990 return acceptable;
01991 }
01992
01993
01994
01995 EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item)
01996 {
01997
01998 if(!item || !obj) return ACCEPT_NO;
01999
02000 LLViewerInventoryItem* vitem = (LLViewerInventoryItem*)item;
02001 if(!vitem->isComplete()) return ACCEPT_NO;
02002
02003
02004
02005
02006
02007 if(obj->getID() == item->getParentUUID())
02008 {
02009 return ACCEPT_NO;
02010 }
02011
02012
02013
02014
02015 BOOL worn = FALSE;
02016 LLVOAvatar* my_avatar = NULL;
02017 switch(item->getType())
02018 {
02019 case LLAssetType::AT_OBJECT:
02020 my_avatar = gAgent.getAvatarObject();
02021 if(my_avatar && my_avatar->isWearingAttachment(item->getUUID()))
02022 {
02023 worn = TRUE;
02024 }
02025 break;
02026 case LLAssetType::AT_BODYPART:
02027 case LLAssetType::AT_CLOTHING:
02028 if(gAgent.isWearingItem(item->getUUID()))
02029 {
02030 worn = TRUE;
02031 }
02032 break;
02033 default:
02034 break;
02035 }
02036 const LLPermissions& perm = item->getPermissions();
02037 BOOL modify = (obj->permModify() || obj->flagAllowInventoryAdd());
02038 BOOL transfer = FALSE;
02039 if((obj->permYouOwner() && (perm.getOwner() == gAgent.getID()))
02040 || perm.allowOperationBy(PERM_TRANSFER, gAgent.getID()))
02041 {
02042 transfer = TRUE;
02043 }
02044 BOOL volume = (LL_PCODE_VOLUME == obj->getPCode());
02045 BOOL attached = obj->isAttachment();
02046 BOOL unrestricted = ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) ? TRUE : FALSE;
02047 if(attached && !unrestricted)
02048 {
02049 return ACCEPT_NO_LOCKED;
02050 }
02051 else if(modify && transfer && volume && !worn)
02052 {
02053 return ACCEPT_YES_MULTI;
02054 }
02055 else if(!modify)
02056 {
02057 return ACCEPT_NO_LOCKED;
02058 }
02059 return ACCEPT_NO;
02060 }
02061
02065
02066 EAcceptance LLToolDragAndDrop::dad3dNULL(
02067 LLViewerObject*, S32, MASK, BOOL)
02068 {
02069 lldebugs << "LLToolDragAndDrop::dad3dNULL()" << llendl;
02070 return ACCEPT_NO;
02071 }
02072
02073 EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv(
02074 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
02075 {
02076 lldebugs << "LLToolDragAndDrop::dad3dRezAttachmentFromInv()" << llendl;
02077
02078 if(mSource != SOURCE_AGENT && mSource != SOURCE_LIBRARY)
02079 {
02080 return ACCEPT_NO;
02081 }
02082
02083 LLViewerInventoryItem* item;
02084 LLViewerInventoryCategory* cat;
02085 locateInventory(item, cat);
02086 if(!item || !item->isComplete()) return ACCEPT_NO;
02087
02088
02089 LLUUID trash_id(gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH));
02090 if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) )
02091 {
02092 return ACCEPT_NO;
02093 }
02094
02095
02096 LLVOAvatar* avatar = gAgent.getAvatarObject();
02097 if( !avatar || avatar->isWearingAttachment(item->getUUID()) )
02098 {
02099 return ACCEPT_NO;
02100 }
02101
02102 if( drop )
02103 {
02104 if(mSource == SOURCE_LIBRARY)
02105 {
02106 LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(0);
02107 copy_inventory_item(
02108 gAgent.getID(),
02109 item->getPermissions().getOwner(),
02110 item->getUUID(),
02111 LLUUID::null,
02112 std::string(),
02113 cb);
02114 }
02115 else
02116 {
02117 rez_attachment(item, 0);
02118 }
02119 }
02120 return ACCEPT_YES_SINGLE;
02121 }
02122
02123
02124 EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand(
02125 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
02126 {
02127 if (mSource == SOURCE_WORLD)
02128 {
02129 return dad3dRezFromObjectOnLand(obj, face, mask, drop);
02130 }
02131
02132 lldebugs << "LLToolDragAndDrop::dad3dRezObjectOnLand()" << llendl;
02133 LLViewerInventoryItem* item;
02134 LLViewerInventoryCategory* cat;
02135 locateInventory(item, cat);
02136 if(!item || !item->isComplete()) return ACCEPT_NO;
02137
02138 LLVOAvatar* my_avatar = gAgent.getAvatarObject();
02139 if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) )
02140 {
02141 return ACCEPT_NO;
02142 }
02143
02144 EAcceptance accept;
02145 BOOL remove_inventory;
02146
02147
02148 if (mask & MASK_SHIFT)
02149 {
02150
02151
02152
02153 accept = ACCEPT_YES_COPY_SINGLE;
02154 remove_inventory = FALSE;
02155 }
02156 else
02157 {
02158 accept = ACCEPT_YES_COPY_SINGLE;
02159 remove_inventory = FALSE;
02160 }
02161
02162
02163
02164 if(!item->getPermissions().allowCopyBy(gAgent.getID()))
02165 {
02166 accept = ACCEPT_YES_SINGLE;
02167 remove_inventory = TRUE;
02168 }
02169
02170
02171 LLUUID trash_id;
02172 trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
02173 if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id))
02174 {
02175 accept = ACCEPT_YES_SINGLE;
02176 remove_inventory = TRUE;
02177 }
02178
02179 if(drop)
02180 {
02181 dropObject(obj, TRUE, FALSE, remove_inventory);
02182 }
02183
02184 return accept;
02185 }
02186
02187 EAcceptance LLToolDragAndDrop::dad3dRezObjectOnObject(
02188 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
02189 {
02190
02191 if (mSource == SOURCE_WORLD)
02192 {
02193 return dad3dRezFromObjectOnObject(obj, face, mask, drop);
02194 }
02195
02196 lldebugs << "LLToolDragAndDrop::dad3dRezObjectOnObject()" << llendl;
02197 LLViewerInventoryItem* item;
02198 LLViewerInventoryCategory* cat;
02199 locateInventory(item, cat);
02200 if(!item || !item->isComplete()) return ACCEPT_NO;
02201 LLVOAvatar* my_avatar = gAgent.getAvatarObject();
02202 if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) )
02203 {
02204 return ACCEPT_NO;
02205 }
02206
02207 if((mask & MASK_CONTROL))
02208 {
02209
02210
02211 if(mSource == SOURCE_NOTECARD)
02212 {
02213 return ACCEPT_NO;
02214 }
02215
02216 EAcceptance rv = willObjectAcceptInventory(obj, item);
02217 if(drop && (ACCEPT_YES_SINGLE <= rv))
02218 {
02219 dropInventory(obj, item, mSource, mSourceID);
02220 }
02221 return rv;
02222 }
02223
02224 EAcceptance accept;
02225 BOOL remove_inventory;
02226
02227 if (mask & MASK_SHIFT)
02228 {
02229
02230
02231
02232 accept = ACCEPT_YES_COPY_SINGLE;
02233 remove_inventory = FALSE;
02234 }
02235 else
02236 {
02237 accept = ACCEPT_YES_COPY_SINGLE;
02238 remove_inventory = FALSE;
02239 }
02240
02241
02242
02243 if(!item->getPermissions().allowCopyBy(gAgent.getID()))
02244 {
02245 accept = ACCEPT_YES_SINGLE;
02246 remove_inventory = TRUE;
02247 }
02248
02249
02250 LLUUID trash_id;
02251 trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
02252 if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id))
02253 {
02254 accept = ACCEPT_YES_SINGLE;
02255 remove_inventory = TRUE;
02256 }
02257
02258 if(drop)
02259 {
02260 dropObject(obj, FALSE, FALSE, remove_inventory);
02261 }
02262
02263 return accept;
02264 }
02265
02266 EAcceptance LLToolDragAndDrop::dad3dRezScript(
02267 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
02268 {
02269 lldebugs << "LLToolDragAndDrop::dad3dRezScript()" << llendl;
02270
02271
02272
02273 if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource))
02274 {
02275 return ACCEPT_NO;
02276 }
02277
02278 LLViewerInventoryItem* item;
02279 LLViewerInventoryCategory* cat;
02280 locateInventory(item, cat);
02281 if(!item || !item->isComplete()) return ACCEPT_NO;
02282 EAcceptance rv = willObjectAcceptInventory(obj, item);
02283 if(drop && (ACCEPT_YES_SINGLE <= rv))
02284 {
02285
02286
02287 BOOL active = ((mask & MASK_CONTROL) == 0);
02288
02289 LLViewerObject* root_object = obj;
02290 if (obj && obj->getParent())
02291 {
02292 LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent();
02293 if (!parent_obj->isAvatar())
02294 {
02295 root_object = parent_obj;
02296 }
02297 }
02298
02299 dropScript(root_object, item, active, mSource, mSourceID);
02300 }
02301 return rv;
02302 }
02303
02304 EAcceptance LLToolDragAndDrop::dad3dTextureObject(
02305 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
02306 {
02307 lldebugs << "LLToolDragAndDrop::dad3dTextureObject()" << llendl;
02308
02309
02310
02311 if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource))
02312 {
02313 return ACCEPT_NO;
02314 }
02315
02316 LLViewerInventoryItem* item;
02317 LLViewerInventoryCategory* cat;
02318 locateInventory(item, cat);
02319 if(!item || !item->isComplete()) return ACCEPT_NO;
02320 EAcceptance rv = willObjectAcceptInventory(obj, item);
02321 if((mask & MASK_CONTROL))
02322 {
02323 if((ACCEPT_YES_SINGLE <= rv) && drop)
02324 {
02325 dropInventory(obj, item, mSource, mSourceID);
02326 }
02327 return rv;
02328 }
02329 if(!obj->permModify())
02330 {
02331 return ACCEPT_NO_LOCKED;
02332 }
02333
02334 if(!item->getPermissions().allowCopyBy(gAgent.getID()))
02335 {
02336 return ACCEPT_NO;
02337 }
02338
02339 if(drop && (ACCEPT_YES_SINGLE <= rv))
02340 {
02341 if((mask & MASK_SHIFT))
02342 {
02343 dropTextureAllFaces(obj, item, mSource, mSourceID);
02344 }
02345 else
02346 {
02347 dropTextureOneFace(obj, face, item, mSource, mSourceID);
02348 }
02349
02350
02351 LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
02352 effectp->setSourceObject(gAgent.getAvatarObject());
02353 effectp->setTargetObject(obj);
02354 effectp->setDuration(LL_HUD_DUR_SHORT);
02355 effectp->setColor(LLColor4U(gAgent.getEffectColor()));
02356 }
02357
02358
02359 return ACCEPT_YES_MULTI;
02360 }
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377 EAcceptance LLToolDragAndDrop::dad3dWearItem(
02378 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
02379 {
02380 lldebugs << "LLToolDragAndDrop::dad3dWearItem()" << llendl;
02381 LLViewerInventoryItem* item;
02382 LLViewerInventoryCategory* cat;
02383 locateInventory(item, cat);
02384 if(!item || !item->isComplete()) return ACCEPT_NO;
02385
02386 if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY)
02387 {
02388
02389 LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
02390 if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) )
02391 {
02392 return ACCEPT_NO;
02393 }
02394
02395 if( drop )
02396 {
02397
02398
02399 if (!gAgent.areWearablesLoaded())
02400 {
02401 gViewerWindow->alertXml("CanNotChangeAppearanceUntilLoaded");
02402 return ACCEPT_NO;
02403 }
02404
02405 if(mSource == SOURCE_LIBRARY)
02406 {
02407
02408
02409 LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
02410 copy_inventory_item(
02411 gAgent.getID(),
02412 item->getPermissions().getOwner(),
02413 item->getUUID(),
02414 LLUUID::null,
02415 std::string(),
02416 cb);
02417 }
02418 else
02419 {
02420 wear_inventory_item_on_avatar( item );
02421 }
02422 }
02423 return ACCEPT_YES_MULTI;
02424 }
02425 else
02426 {
02427
02428 return ACCEPT_NO;
02429 }
02430 }
02431
02432 EAcceptance LLToolDragAndDrop::dad3dActivateGesture(
02433 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
02434 {
02435 lldebugs << "LLToolDragAndDrop::dad3dActivateGesture()" << llendl;
02436 LLViewerInventoryItem* item;
02437 LLViewerInventoryCategory* cat;
02438 locateInventory(item, cat);
02439 if(!item || !item->isComplete()) return ACCEPT_NO;
02440
02441 if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY)
02442 {
02443
02444 LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
02445 if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) )
02446 {
02447 return ACCEPT_NO;
02448 }
02449
02450 if( drop )
02451 {
02452 LLUUID item_id;
02453 if(mSource == SOURCE_LIBRARY)
02454 {
02455
02456
02457 LLPointer<LLInventoryCallback> cb = new ActivateGestureCallback();
02458 copy_inventory_item(
02459 gAgent.getID(),
02460 item->getPermissions().getOwner(),
02461 item->getUUID(),
02462 LLUUID::null,
02463 std::string(),
02464 cb);
02465 }
02466 else
02467 {
02468 gGestureManager.activateGesture(item->getUUID());
02469 gInventory.updateItem(item);
02470 gInventory.notifyObservers();
02471 }
02472 }
02473 return ACCEPT_YES_MULTI;
02474 }
02475 else
02476 {
02477 return ACCEPT_NO;
02478 }
02479 }
02480
02481 EAcceptance LLToolDragAndDrop::dad3dWearCategory(
02482 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
02483 {
02484 lldebugs << "LLToolDragAndDrop::dad3dWearCategory()" << llendl;
02485 LLViewerInventoryItem* item;
02486 LLViewerInventoryCategory* category;
02487 locateInventory(item, category);
02488 if(!category) return ACCEPT_NO;
02489
02490 if (drop)
02491 {
02492
02493
02494 if (!gAgent.areWearablesLoaded())
02495 {
02496 gViewerWindow->alertXml("CanNotChangeAppearanceUntilLoaded");
02497 return ACCEPT_NO;
02498 }
02499 }
02500
02501 if(mSource == SOURCE_AGENT)
02502 {
02503 LLUUID trash_id(gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH));
02504 if( gInventory.isObjectDescendentOf( category->getUUID(), trash_id ) )
02505 {
02506 return ACCEPT_NO;
02507 }
02508
02509 if(drop)
02510 {
02511 BOOL append = ( (mask & MASK_SHIFT) ? TRUE : FALSE );
02512 wear_inventory_category(category, false, append);
02513 }
02514 return ACCEPT_YES_MULTI;
02515 }
02516 else if(mSource == SOURCE_LIBRARY)
02517 {
02518 if(drop)
02519 {
02520 wear_inventory_category(category, true, false);
02521 }
02522 return ACCEPT_YES_MULTI;
02523 }
02524 else
02525 {
02526
02527 return ACCEPT_NO;
02528 }
02529 }
02530
02531
02532 EAcceptance LLToolDragAndDrop::dad3dUpdateInventory(
02533 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
02534 {
02535 lldebugs << "LLToolDragAndDrop::dadUpdateInventory()" << llendl;
02536
02537
02538
02539 if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource))
02540 {
02541 return ACCEPT_NO;
02542 }
02543
02544 LLViewerInventoryItem* item;
02545 LLViewerInventoryCategory* cat;
02546 locateInventory(item, cat);
02547 if(!item || !item->isComplete()) return ACCEPT_NO;
02548 LLViewerObject* root_object = obj;
02549 if (obj && obj->getParent())
02550 {
02551 LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent();
02552 if (!parent_obj->isAvatar())
02553 {
02554 root_object = parent_obj;
02555 }
02556 }
02557
02558 EAcceptance rv = willObjectAcceptInventory(root_object, item);
02559 if(root_object && drop && (ACCEPT_YES_COPY_SINGLE <= rv))
02560 {
02561 dropInventory(root_object, item, mSource, mSourceID);
02562 }
02563 return rv;
02564 }
02565
02566 BOOL LLToolDragAndDrop::dadUpdateInventory(LLViewerObject* obj, BOOL drop)
02567 {
02568 EAcceptance rv = dad3dUpdateInventory(obj, -1, MASK_NONE, drop);
02569 return (rv >= ACCEPT_YES_COPY_SINGLE);
02570 }
02571
02572 EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory(
02573 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
02574 {
02575 lldebugs << "LLToolDragAndDrop::dad3dUpdateInventoryCategory()" << llendl;
02576 if (NULL==obj)
02577 {
02578 llwarns << "obj is NULL; aborting func with ACCEPT_NO" << llendl;
02579 return ACCEPT_NO;
02580 }
02581
02582 if (mSource != SOURCE_AGENT && mSource != SOURCE_LIBRARY)
02583 {
02584 return ACCEPT_NO;
02585 }
02586 if(obj->isAttachment()) return ACCEPT_NO_LOCKED;
02587 LLViewerInventoryItem* item;
02588 LLViewerInventoryCategory* cat;
02589 locateInventory(item, cat);
02590 if(!cat) return ACCEPT_NO;
02591 EAcceptance rv = ACCEPT_NO;
02592
02593
02594 LLDroppableItem droppable(!obj->permYouOwner());
02595 LLInventoryModel::cat_array_t cats;
02596 LLInventoryModel::item_array_t items;
02597 gInventory.collectDescendentsIf(cat->getUUID(),
02598 cats,
02599 items,
02600 LLInventoryModel::EXCLUDE_TRASH,
02601 droppable);
02602 cats.put(cat);
02603 if(droppable.countNoCopy() > 0)
02604 {
02605 llwarns << "*** Need to confirm this step" << llendl;
02606 }
02607 LLViewerObject* root_object = obj;
02608 if (obj->getParent())
02609 {
02610 LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent();
02611 if (!parent_obj->isAvatar())
02612 {
02613 root_object = parent_obj;
02614 }
02615 }
02616
02617
02618 S32 i;
02619 S32 count = cats.count();
02620 for(i = 0; i < count; ++i)
02621 {
02622 rv = gInventory.isCategoryComplete(cats.get(i)->getUUID()) ? ACCEPT_YES_MULTI : ACCEPT_NO;
02623 if(rv < ACCEPT_YES_SINGLE)
02624 {
02625 lldebugs << "Category " << cats.get(i)->getUUID()
02626 << "is not complete." << llendl;
02627 break;
02628 }
02629 }
02630 if(ACCEPT_YES_COPY_SINGLE <= rv)
02631 {
02632 count = items.count();
02633 for(i = 0; i < count; ++i)
02634 {
02635 rv = willObjectAcceptInventory(root_object, items.get(i));
02636 if(rv < ACCEPT_YES_COPY_SINGLE)
02637 {
02638 lldebugs << "Object will not accept "
02639 << items.get(i)->getUUID() << llendl;
02640 break;
02641 }
02642 }
02643 }
02644
02645
02646 if(drop && (ACCEPT_YES_COPY_SINGLE <= rv))
02647 {
02648 S32 count = items.count();
02649 LLInventoryFetchObserver::item_ref_t ids;
02650 for(i = 0; i < count; ++i)
02651 {
02652
02653 ids.push_back(items.get(i)->getUUID());
02654 }
02655 LLCategoryDropObserver* dropper;
02656 dropper = new LLCategoryDropObserver(obj->getID(), mSource);
02657 dropper->fetchItems(ids);
02658 if(dropper->isEverythingComplete())
02659 {
02660 dropper->done();
02661 }
02662 else
02663 {
02664 gInventory.addObserver(dropper);
02665 }
02666 }
02667 return rv;
02668 }
02669
02670 BOOL LLToolDragAndDrop::dadUpdateInventoryCategory(LLViewerObject* obj,
02671 BOOL drop)
02672 {
02673 EAcceptance rv = dad3dUpdateInventoryCategory(obj, -1, MASK_NONE, drop);
02674 return (rv >= ACCEPT_YES_COPY_SINGLE);
02675 }
02676
02677 EAcceptance LLToolDragAndDrop::dad3dGiveInventoryObject(
02678 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
02679 {
02680 lldebugs << "LLToolDragAndDrop::dad3dGiveInventoryObject()" << llendl;
02681
02682
02683 if(mSource != SOURCE_AGENT) return ACCEPT_NO;
02684
02685
02686 LLViewerInventoryItem* item;
02687 LLViewerInventoryCategory* cat;
02688 locateInventory(item, cat);
02689 if(!item || !item->isComplete()) return ACCEPT_NO;
02690 if(!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
02691 {
02692
02693 return ACCEPT_NO;
02694 }
02695 LLVOAvatar* avatar = gAgent.getAvatarObject();
02696 if(avatar && avatar->isWearingAttachment( item->getUUID() ) )
02697 {
02698
02699 return ACCEPT_NO;
02700 }
02701 if( obj && avatar )
02702 {
02703 if(drop)
02704 {
02705 giveInventory(obj->getID(), item );
02706 }
02707
02708
02709 return ACCEPT_YES_SINGLE;
02710 }
02711 return ACCEPT_NO;
02712 }
02713
02714
02715 EAcceptance LLToolDragAndDrop::dad3dGiveInventory(
02716 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
02717 {
02718 lldebugs << "LLToolDragAndDrop::dad3dGiveInventory()" << llendl;
02719
02720 if(mSource != SOURCE_AGENT) return ACCEPT_NO;
02721 LLViewerInventoryItem* item;
02722 LLViewerInventoryCategory* cat;
02723 locateInventory(item, cat);
02724 if(!item || !item->isComplete()) return ACCEPT_NO;
02725 if(!isInventoryGiveAcceptable(item))
02726 {
02727 return ACCEPT_NO;
02728 }
02729 if(drop && obj)
02730 {
02731 giveInventory(obj->getID(), item);
02732 }
02733
02734
02735 return ACCEPT_YES_SINGLE;
02736 }
02737
02738 EAcceptance LLToolDragAndDrop::dad3dGiveInventoryCategory(
02739 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
02740 {
02741 lldebugs << "LLToolDragAndDrop::dad3dGiveInventoryCategory()" << llendl;
02742 if(drop && obj)
02743 {
02744 LLViewerInventoryItem* item;
02745 LLViewerInventoryCategory* cat;
02746 locateInventory(item, cat);
02747 if(!cat) return ACCEPT_NO;
02748 giveInventoryCategory(obj->getID(), cat);
02749 }
02750
02751
02752 return ACCEPT_YES_SINGLE;
02753 }
02754
02755
02756 EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnLand(
02757 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
02758 {
02759 lldebugs << "LLToolDragAndDrop::dad3dRezFromObjectOnLand()" << llendl;
02760 LLViewerInventoryItem* item = NULL;
02761 LLViewerInventoryCategory* cat = NULL;
02762 locateInventory(item, cat);
02763 if(!item || !item->isComplete()) return ACCEPT_NO;
02764 if(!item->getPermissions().allowCopyBy(gAgent.getID(),
02765 gAgent.getGroupID())
02766 || !item->getPermissions().allowTransferTo(LLUUID::null))
02767 {
02768 return ACCEPT_NO_LOCKED;
02769 }
02770 if(drop)
02771 {
02772 dropObject(obj, TRUE, TRUE, FALSE);
02773 }
02774 return ACCEPT_YES_SINGLE;
02775 }
02776
02777 EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnObject(
02778 LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
02779 {
02780 lldebugs << "LLToolDragAndDrop::dad3dRezFromObjectOnObject()" << llendl;
02781 LLViewerInventoryItem* item;
02782 LLViewerInventoryCategory* cat;
02783 locateInventory(item, cat);
02784 if(!item || !item->isComplete()) return ACCEPT_NO;
02785 if((mask & MASK_CONTROL))
02786 {
02787
02788
02789 return ACCEPT_NO;
02790
02791
02792
02793
02794
02795
02796
02797
02798 }
02799 if(!item->getPermissions().allowCopyBy(gAgent.getID(),
02800 gAgent.getGroupID())
02801 || !item->getPermissions().allowTransferTo(LLUUID::null))
02802 {
02803 return ACCEPT_NO_LOCKED;
02804 }
02805 if(drop)
02806 {
02807 dropObject(obj, FALSE, TRUE, FALSE);
02808 }
02809 return ACCEPT_YES_SINGLE;
02810 }
02811
02812 EAcceptance LLToolDragAndDrop::dad3dCategoryOnLand(
02813 LLViewerObject *obj, S32 face, MASK mask, BOOL drop)
02814 {
02815 return ACCEPT_NO;
02816
02817
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831
02832
02833
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844 }
02845
02846
02847
02848
02849
02850 EAcceptance LLToolDragAndDrop::dad3dAssetOnLand(
02851 LLViewerObject *obj, S32 face, MASK mask, BOOL drop)
02852 {
02853 return ACCEPT_NO;
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879 }
02880
02881 LLInventoryObject* LLToolDragAndDrop::locateInventory(
02882 LLViewerInventoryItem*& item,
02883 LLViewerInventoryCategory*& cat)
02884 {
02885 item = NULL;
02886 cat = NULL;
02887 if(mCargoIDs.empty()) return NULL;
02888 if((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY))
02889 {
02890
02891 item = (LLViewerInventoryItem*)gInventory.getItem(mCargoIDs[mCurItemIndex]);
02892 cat = (LLViewerInventoryCategory*)gInventory.getCategory(mCargoIDs[mCurItemIndex]);
02893 }
02894 else if(mSource == SOURCE_WORLD)
02895 {
02896
02897 LLViewerObject* obj = gObjectList.findObject(mSourceID);
02898 if(obj)
02899 {
02900 if((mCargoTypes[mCurItemIndex] == DAD_CATEGORY)
02901 || (mCargoTypes[mCurItemIndex] == DAD_ROOT_CATEGORY))
02902 {
02903 cat = (LLViewerInventoryCategory*)obj->getInventoryObject(mCargoIDs[mCurItemIndex]);
02904 }
02905 else
02906 {
02907 item = (LLViewerInventoryItem*)obj->getInventoryObject(mCargoIDs[mCurItemIndex]);
02908 }
02909 }
02910 }
02911 else if(mSource == SOURCE_NOTECARD)
02912 {
02913 LLPreviewNotecard* card;
02914 card = (LLPreviewNotecard*)LLPreview::find(mSourceID);
02915 if(card)
02916 {
02917 item = (LLViewerInventoryItem*)card->getDragItem();
02918 }
02919 }
02920 if(item) return item;
02921 if(cat) return cat;
02922 return NULL;
02923 }
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953
02954
02955
02956
02957
02958
02959
02960
02961
02962
02963
02964
02965
02966
02967
02968
02969
02970
02971
02972
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994 void LLToolDragAndDrop::createContainer(LLViewerInventoryItem::item_array_t &items, const char* preferred_name )
02995 {
02996 llwarns << "LLToolDragAndDrop::createContainer()" << llendl;
02997 return;
02998 }
02999
03000
03001
03002
03003 void pack_permissions_slam(LLMessageSystem* msg, U32 flags, const LLPermissions& perms)
03004 {
03005 U32 group_mask = perms.getMaskGroup();
03006 U32 everyone_mask = perms.getMaskEveryone();
03007 U32 next_owner_mask = perms.getMaskNextOwner();
03008
03009 msg->addU32Fast(_PREHASH_ItemFlags, flags);
03010 msg->addU32Fast(_PREHASH_GroupMask, group_mask);
03011 msg->addU32Fast(_PREHASH_EveryoneMask, everyone_mask);
03012 msg->addU32Fast(_PREHASH_NextOwnerMask, next_owner_mask);
03013 }