diff options
author | Loren Shih <seraph@lindenlab.com> | 2009-11-30 17:17:59 -0500 |
---|---|---|
committer | Loren Shih <seraph@lindenlab.com> | 2009-11-30 17:17:59 -0500 |
commit | 1f1afc253d31e0afc3a0de2718e31d03cfca7f43 (patch) | |
tree | 6dfb0ddaf4569d4fc0aafb80ec3ae753a121a31a /indra | |
parent | 7e2b88a32b0bed07abcf760bd0adf3403ec2ede2 (diff) |
INFRASTRUCTURE: LLToolDragAndDrop cleanup
Includes removal of unused header files.
Includes changing big static map into a lldictionary.
--HG--
branch : avatar-pipeline
Diffstat (limited to 'indra')
-rw-r--r-- | indra/newview/lltooldraganddrop.cpp | 276 | ||||
-rw-r--r-- | indra/newview/lltooldraganddrop.h | 23 |
2 files changed, 114 insertions, 185 deletions
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index fbd86d0edf..93910ce4a5 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -31,50 +31,34 @@ */ #include "llviewerprecompiledheaders.h" - -#include "message.h" #include "lltooldraganddrop.h" -#include "llfloaterreg.h" -#include "llinstantmessage.h" -#include "lldir.h" - #include "llagent.h" +#include "llagentui.h" #include "llagentwearables.h" -#include "llviewercontrol.h" +#include "llappearancemgr.h" +#include "lldictionary.h" #include "llfirstuse.h" -#include "llfloater.h" +#include "llfloaterreg.h" #include "llfloatertools.h" -#include "llfocusmgr.h" #include "llgesturemgr.h" -#include "llhudeffecttrail.h" #include "llhudmanager.h" +#include "llhudeffecttrail.h" +#include "llimview.h" #include "llinventorybridge.h" -#include "llinventorymodel.h" #include "llmutelist.h" -#include "llnotify.h" #include "llpreviewnotecard.h" #include "llrecentpeople.h" +#include "llrootview.h" #include "llselectmgr.h" #include "lltoolmgr.h" #include "lltooltip.h" #include "lltrans.h" -#include "llui.h" -#include "llviewertexturelist.h" -#include "llviewerinventory.h" -#include "llviewerobject.h" #include "llviewerobjectlist.h" -#include "llviewerregion.h" #include "llviewerstats.h" #include "llviewerwindow.h" #include "llvoavatarself.h" -#include "llvolume.h" #include "llworld.h" -#include "object_flags.h" -#include "llimview.h" -#include "llrootview.h" -#include "llagentui.h" -#include "llappearancemgr.h" // MAX ITEMS is based on (sizeof(uuid)+2) * count must be < MTUBYTES // or 18 * count < 1200 => count < 1200/18 => 66. I've cut it down a @@ -355,134 +339,50 @@ void LLCategoryDropDescendentsObserver::done() delete this; } -// This array is used to more easily control what happens when a 3d -// drag and drop event occurs. Since there's an array of drop target -// and cargo type, it's implemented as an array of pointers to member -// functions which correctly carry out the actual drop. -LLToolDragAndDrop::dragOrDrop3dImpl LLToolDragAndDrop::sDragAndDrop3d[DAD_COUNT][LLToolDragAndDrop::DT_COUNT] = -{ - // Source: DAD_NONE - { - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_AVATAR - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_OBJECT - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_LAND - }, - // Source: DAD_TEXTURE - { - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF - &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR - &LLToolDragAndDrop::dad3dTextureObject, // Dest: DT_OBJECT - &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND - }, - // Source: DAD_SOUND - { - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF - &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR - &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT - &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND - }, - // Source: DAD_CALLINGCARD - { - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF - &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR - &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_LAND - }, - // Source: DAD_LANDMARK - { - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF - &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR - &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT - &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND - }, - // Source: DAD_SCRIPT - { - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF - &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR - &LLToolDragAndDrop::dad3dRezScript, // Dest: DT_OBJECT - &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND - }, - // Source: DAD_CLOTHING - { - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE - &LLToolDragAndDrop::dad3dWearItem, // Dest: DT_SELF - &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR - &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT - &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND - }, - // Source: DAD_OBJECT - { - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE - &LLToolDragAndDrop::dad3dRezAttachmentFromInv, // Dest: DT_SELF - &LLToolDragAndDrop::dad3dGiveInventoryObject, // Dest: DT_AVATAR - &LLToolDragAndDrop::dad3dRezObjectOnObject, // Dest: DT_OBJECT - &LLToolDragAndDrop::dad3dRezObjectOnLand, // Dest: DT_LAND - }, - // Source: DAD_NOTECARD - { - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF - &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR - &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT - &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND - }, - // Source: DAD_CATEGORY - { - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE - &LLToolDragAndDrop::dad3dWearCategory, // Dest: DT_SELF - &LLToolDragAndDrop::dad3dGiveInventoryCategory, // Dest: DT_AVATAR - &LLToolDragAndDrop::dad3dUpdateInventoryCategory, // Dest: DT_OBJECT - &LLToolDragAndDrop::dad3dNULL,//dad3dCategoryOnLand, // Dest: DT_LAND - }, - // Source: DAD_ROOT - { - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_AVATAR - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_OBJECT - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_LAND - }, - // Source: DAD_BODYPART - { - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE - &LLToolDragAndDrop::dad3dWearItem, // Dest: DT_SELF - &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR - &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT - &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND - }, - // Source: DAD_ANIMATION - // TODO: animation on self could play it? edit it? +LLToolDragAndDrop::DragAndDropEntry::DragAndDropEntry(dragOrDrop3dImpl f_none, + dragOrDrop3dImpl f_self, + dragOrDrop3dImpl f_avatar, + dragOrDrop3dImpl f_object, + dragOrDrop3dImpl f_land) : + LLDictionaryEntry("") +{ + mFunctions[DT_NONE] = f_none; + mFunctions[DT_SELF] = f_self; + mFunctions[DT_AVATAR] = f_avatar; + mFunctions[DT_OBJECT] = f_object; + mFunctions[DT_LAND] = f_land; +} + +LLToolDragAndDrop::dragOrDrop3dImpl LLToolDragAndDrop::LLDragAndDropDictionary::get(EDragAndDropType dad_type, LLToolDragAndDrop::EDropTarget drop_target) +{ + const DragAndDropEntry *entry = lookup(dad_type); + if (entry) { - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF - &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR - &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT - &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND - }, - // Source: DAD_GESTURE - // TODO: gesture on self could play it? edit it? - { - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE - &LLToolDragAndDrop::dad3dActivateGesture, // Dest: DT_SELF - &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR - &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT - &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND - }, - // Source: DAD_LINK - { - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_AVATAR - &LLToolDragAndDrop::dad3dNULL, // Dest: DT_OBJECT - &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND - }, + return (entry->mFunctions[(U8)drop_target]); + } + return &dad3dNULL; +} + +LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary() +{ + // DT_NONE DT_SELF DT_AVATAR DT_OBJECT DT_LAND + // |--------------|---------------------------|---------------------------|-------------------------------|--------------| + addEntry(DAD_NONE, new DragAndDropEntry(&dad3dNULL, &dad3dNULL, &dad3dNULL, &dad3dNULL, &dad3dNULL)); + addEntry(DAD_TEXTURE, new DragAndDropEntry(&dad3dNULL, &dad3dNULL, &dad3dGiveInventory, &dad3dTextureObject, &dad3dNULL)); + addEntry(DAD_SOUND, new DragAndDropEntry(&dad3dNULL, &dad3dNULL, &dad3dGiveInventory, &dad3dUpdateInventory, &dad3dNULL)); + addEntry(DAD_CALLINGCARD, new DragAndDropEntry(&dad3dNULL, &dad3dNULL, &dad3dGiveInventory, &dad3dUpdateInventory, &dad3dNULL)); + addEntry(DAD_LANDMARK, new DragAndDropEntry(&dad3dNULL, &dad3dNULL, &dad3dGiveInventory, &dad3dUpdateInventory, &dad3dNULL)); + addEntry(DAD_SCRIPT, new DragAndDropEntry(&dad3dNULL, &dad3dNULL, &dad3dGiveInventory, &dad3dRezScript, &dad3dNULL)); + addEntry(DAD_CLOTHING, new DragAndDropEntry(&dad3dNULL, &dad3dWearItem, &dad3dGiveInventory, &dad3dUpdateInventory, &dad3dNULL)); + addEntry(DAD_OBJECT, new DragAndDropEntry(&dad3dNULL, &dad3dRezAttachmentFromInv, &dad3dGiveInventoryObject, &dad3dRezObjectOnObject, &dad3dRezObjectOnLand)); + addEntry(DAD_NOTECARD, new DragAndDropEntry(&dad3dNULL, &dad3dNULL, &dad3dGiveInventory, &dad3dUpdateInventory, &dad3dNULL)); + addEntry(DAD_CATEGORY, new DragAndDropEntry(&dad3dNULL, &dad3dWearCategory, &dad3dGiveInventoryCategory,&dad3dUpdateInventoryCategory, &dad3dNULL)); + addEntry(DAD_ROOT_CATEGORY, new DragAndDropEntry(&dad3dNULL, &dad3dNULL, &dad3dNULL, &dad3dNULL, &dad3dNULL)); + addEntry(DAD_BODYPART, new DragAndDropEntry(&dad3dNULL, &dad3dWearItem, &dad3dGiveInventory, &dad3dUpdateInventory, &dad3dNULL)); + addEntry(DAD_ANIMATION, new DragAndDropEntry(&dad3dNULL, &dad3dNULL, &dad3dGiveInventory, &dad3dUpdateInventory, &dad3dNULL)); + addEntry(DAD_GESTURE, new DragAndDropEntry(&dad3dNULL, &dad3dActivateGesture, &dad3dGiveInventory, &dad3dUpdateInventory, &dad3dNULL)); + addEntry(DAD_LINK, new DragAndDropEntry(&dad3dNULL, &dad3dNULL, &dad3dNULL, &dad3dNULL, &dad3dNULL)); + // TODO: animation on self could play it? edit it? }; LLToolDragAndDrop::LLToolDragAndDrop() @@ -925,7 +825,7 @@ void LLToolDragAndDrop::dragOrDrop3D( S32 x, S32 y, MASK mask, BOOL drop, EAccep if (mDrop) { // don't allow drag and drop onto transparent objects - pickCallback(gViewerWindow->pickImmediate(x, y, FALSE)); + pick(gViewerWindow->pickImmediate(x, y, FALSE)); } else { @@ -938,6 +838,14 @@ void LLToolDragAndDrop::dragOrDrop3D( S32 x, S32 y, MASK mask, BOOL drop, EAccep void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info) { + if (getInstance() != NULL) + { + getInstance()->pick(pick_info); + } +} + +void LLToolDragAndDrop::pick(const LLPickInfo& pick_info) +{ EDropTarget target = DT_NONE; S32 hit_face = -1; @@ -945,31 +853,30 @@ void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info) LLSelectMgr::getInstance()->unhighlightAll(); // Treat attachments as part of the avatar they are attached to. - if (hit_obj) + if (hit_obj != NULL) { // don't allow drag and drop on grass, trees, etc. - if(pick_info.mPickType == LLPickInfo::PICK_FLORA) + if (pick_info.mPickType == LLPickInfo::PICK_FLORA) { - LLToolDragAndDrop::getInstance()->mCursor = UI_CURSOR_NO; - gViewerWindow->getWindow()->setCursor( LLToolDragAndDrop::getInstance()->mCursor ); + mCursor = UI_CURSOR_NO; + gViewerWindow->getWindow()->setCursor( mCursor ); return; } - if(hit_obj->isAttachment() && !hit_obj->isHUDAttachment()) + if (hit_obj->isAttachment() && !hit_obj->isHUDAttachment()) { LLVOAvatar* avatar = LLVOAvatar::findAvatarFromAttachment( hit_obj ); if( !avatar ) { - LLToolDragAndDrop::getInstance()->mLastAccept = ACCEPT_NO; - LLToolDragAndDrop::getInstance()->mCursor = UI_CURSOR_NO; - gViewerWindow->getWindow()->setCursor( LLToolDragAndDrop::getInstance()->mCursor ); + mLastAccept = ACCEPT_NO; + mCursor = UI_CURSOR_NO; + gViewerWindow->getWindow()->setCursor( mCursor ); return; } - hit_obj = avatar; } - if(hit_obj->isAvatar()) + if (hit_obj->isAvatar()) { if(((LLVOAvatar*) hit_obj)->isSelf()) { @@ -988,9 +895,9 @@ void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info) hit_face = pick_info.mObjectFace; // if any item being dragged will be applied to the object under our cursor // highlight that object - for (S32 i = 0; i < (S32)LLToolDragAndDrop::getInstance()->mCargoIDs.size(); i++) + for (S32 i = 0; i < (S32)mCargoIDs.size(); i++) { - if (LLToolDragAndDrop::getInstance()->mCargoTypes[i] != DAD_OBJECT || (pick_info.mKeyMask & MASK_CONTROL)) + if (mCargoTypes[i] != DAD_OBJECT || (pick_info.mKeyMask & MASK_CONTROL)) { LLSelectMgr::getInstance()->highlightObjectAndFamily(hit_obj); break; @@ -998,55 +905,54 @@ void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info) } } } - else if(pick_info.mPickType == LLPickInfo::PICK_LAND) + else if (pick_info.mPickType == LLPickInfo::PICK_LAND) { target = DT_LAND; hit_face = -1; } - LLToolDragAndDrop::getInstance()->mLastAccept = ACCEPT_YES_MULTI; + mLastAccept = ACCEPT_YES_MULTI; - for (LLToolDragAndDrop::getInstance()->mCurItemIndex = 0; LLToolDragAndDrop::getInstance()->mCurItemIndex < (S32)LLToolDragAndDrop::getInstance()->mCargoIDs.size(); - LLToolDragAndDrop::getInstance()->mCurItemIndex++) + for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) { + const S32 item_index = mCurItemIndex; + const EDragAndDropType dad_type = mCargoTypes[item_index]; // Call the right implementation function - LLToolDragAndDrop::getInstance()->mLastAccept = (EAcceptance)llmin( - (U32)LLToolDragAndDrop::getInstance()->mLastAccept, - (U32)callMemberFunction((*LLToolDragAndDrop::getInstance()), - LLToolDragAndDrop::getInstance()->sDragAndDrop3d[LLToolDragAndDrop::getInstance()->mCargoTypes[LLToolDragAndDrop::getInstance()->mCurItemIndex]][target]) - (hit_obj, hit_face, pick_info.mKeyMask, FALSE)); + mLastAccept = (EAcceptance)llmin( + (U32)mLastAccept, + (U32)callMemberFunction(*this, + LLDragAndDropDictionary::instance().get(dad_type, target)) + (hit_obj, hit_face, pick_info.mKeyMask, FALSE)); } - if (LLToolDragAndDrop::getInstance()->mDrop && - (U32)LLToolDragAndDrop::getInstance()->mLastAccept >= ACCEPT_YES_COPY_SINGLE) + if (mDrop && ((U32)mLastAccept >= ACCEPT_YES_COPY_SINGLE)) { // if target allows multi-drop or there is only one item being dropped, go ahead - if (LLToolDragAndDrop::getInstance()->mLastAccept >= ACCEPT_YES_COPY_MULTI || - LLToolDragAndDrop::getInstance()->mCargoIDs.size() == 1) + if ((mLastAccept >= ACCEPT_YES_COPY_MULTI) || (mCargoIDs.size() == 1)) { // Target accepts multi, or cargo is a single-drop - for (LLToolDragAndDrop::getInstance()->mCurItemIndex = 0; - LLToolDragAndDrop::getInstance()->mCurItemIndex < (S32)LLToolDragAndDrop::getInstance()->mCargoIDs.size(); - LLToolDragAndDrop::getInstance()->mCurItemIndex++) + for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) { + const S32 item_index = mCurItemIndex; + const EDragAndDropType dad_type = mCargoTypes[item_index]; // Call the right implementation function - (U32)callMemberFunction((*LLToolDragAndDrop::getInstance()), - LLToolDragAndDrop::getInstance()->sDragAndDrop3d[LLToolDragAndDrop::getInstance()->mCargoTypes[LLToolDragAndDrop::getInstance()->mCurItemIndex]][target]) + (U32)callMemberFunction(*this, + LLDragAndDropDictionary::instance().get(dad_type, target)) (hit_obj, hit_face, pick_info.mKeyMask, TRUE); } } else { // Target does not accept multi, but cargo is multi - LLToolDragAndDrop::getInstance()->mLastAccept = ACCEPT_NO; + mLastAccept = ACCEPT_NO; } } - ECursorType cursor = LLToolDragAndDrop::getInstance()->acceptanceToCursor( LLToolDragAndDrop::getInstance()->mLastAccept ); + ECursorType cursor = acceptanceToCursor( mLastAccept ); gViewerWindow->getWindow()->setCursor( cursor ); - LLToolDragAndDrop::getInstance()->mLastHitPos = pick_info.mPosGlobal; - LLToolDragAndDrop::getInstance()->mLastCameraPos = gAgent.getCameraPositionGlobal(); + mLastHitPos = pick_info.mPosGlobal; + mLastCameraPos = gAgent.getCameraPositionGlobal(); } // static diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index e1536acf75..7f352db15f 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -33,6 +33,7 @@ #ifndef LL_TOOLDRAGANDDROP_H #define LL_TOOLDRAGANDDROP_H +#include "lldictionary.h" #include "lltool.h" #include "llview.h" #include "lluuid.h" @@ -102,6 +103,7 @@ protected: DT_COUNT = 5 }; +protected: // dragOrDrop3dImpl points to a member of LLToolDragAndDrop that // takes parameters (LLViewerObject* obj, S32 face, MASK, BOOL // drop) and returns a BOOL if drop is ok @@ -112,7 +114,9 @@ protected: EAcceptance* acceptance); void dragOrDrop3D(S32 x, S32 y, MASK mask, BOOL drop, EAcceptance* acceptance); + static void pickCallback(const LLPickInfo& pick_info); + void pick(const LLPickInfo& pick_info); protected: @@ -272,6 +276,25 @@ public: EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept); + + // Classes used for determining 3d drag and drop types. +private: + struct DragAndDropEntry : public LLDictionaryEntry + { + DragAndDropEntry(dragOrDrop3dImpl f_none, + dragOrDrop3dImpl f_self, + dragOrDrop3dImpl f_avatar, + dragOrDrop3dImpl f_object, + dragOrDrop3dImpl f_land); + dragOrDrop3dImpl mFunctions[DT_COUNT]; + }; + class LLDragAndDropDictionary : public LLSingleton<LLDragAndDropDictionary>, + public LLDictionary<EDragAndDropType, DragAndDropEntry> + { + public: + LLDragAndDropDictionary(); + dragOrDrop3dImpl get(EDragAndDropType dad_type, EDropTarget drop_target); + }; }; // utility functions |