void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object, InventoryObjectList* inv) { // find all of the lsl, leaving off duplicates. We'll remove // all matching asset uuids on compilation success. typedef std::multimap<LLUUID, LLPointer<LLInventoryItem> > uuid_item_map; uuid_item_map asset_item_map; InventoryObjectList::const_iterator it = inv->begin(); InventoryObjectList::const_iterator end = inv->end(); for ( ; it != end; ++it) { if((*it)->getType() == LLAssetType::AT_LSL_TEXT) { LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); // Check permissions before allowing the user to retrieve data. if (item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID()) && item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID()) ) { LLPointer<LLViewerInventoryItem> script = new LLViewerInventoryItem(item); mCurrentScripts.put(script); asset_item_map.insert(std::make_pair(item->getAssetUUID(), item)); } } } if (asset_item_map.empty()) { // There are no scripts in this object. move on. nextObject(); } else { // request all of the assets. uuid_item_map::iterator iter; for(iter = asset_item_map.begin(); iter != asset_item_map.end(); iter++) { LLInventoryItem *itemp = iter->second; LLScriptQueueData* datap = new LLScriptQueueData(getID(), itemp->getName(), viewer_object->getID(), itemp->getUUID()); //llinfos << "ITEM NAME 2: " << names.get(i) << llendl; gAssetStorage->getInvItemAsset(viewer_object->getRegion()->getHost(), gAgent.getID(), gAgent.getSessionID(), itemp->getPermissions().getOwner(), viewer_object->getID(), itemp->getUUID(), itemp->getAssetUUID(), itemp->getType(), LLFloaterCompileQueue::scriptArrived, (void*)datap); } } }
// static void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action, void* data) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)data; if (items.size()) { LLFolderViewItem* first_item = items.front(); LLInventoryItem* itemp = gInventory.getItem(first_item->getListener()->getUUID()); self->mNoCopyTextureSelected = FALSE; if (itemp) { // <dogmode> if (itemp->getPermissions().getMaskOwner() & PERM_ALL) self->childSetValue("texture_uuid", self->mImageAssetID); else self->childSetValue("texture_uuid", LLUUID::null.asString()); // </dogmode> if (!itemp->getPermissions().allowCopyBy(gAgent.getID())) { self->mNoCopyTextureSelected = TRUE; } self->mImageAssetID = itemp->getAssetUUID(); self->mIsDirty = TRUE; if (user_action) { // only commit intentional selections, not implicit ones self->commitIfImmediateSet(); } } } }
// virtual BOOL LLFloaterTexturePicker::handleDragAndDrop( S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg) { BOOL handled = FALSE; bool is_mesh = cargo_type == DAD_MESH; if ((cargo_type == DAD_TEXTURE) || is_mesh) { LLInventoryItem *item = (LLInventoryItem *)cargo_data; BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()); PermissionMask item_perm_mask = 0; if (copy) item_perm_mask |= PERM_COPY; if (mod) item_perm_mask |= PERM_MODIFY; if (xfer) item_perm_mask |= PERM_TRANSFER; //PermissionMask filter_perm_mask = getFilterPermMask(); Commented out due to no-copy texture loss. PermissionMask filter_perm_mask = mDnDFilterPermMask; if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask ) { if (drop) { // <FS:Ansariel> FIRE-8298: Apply now checkbox has no effect setCanApply(true, true); // </FS:Ansariel> setImageID( item->getAssetUUID() ); commitIfImmediateSet(); } *accept = ACCEPT_YES_SINGLE; } else { *accept = ACCEPT_NO; } } else { *accept = ACCEPT_NO; } handled = TRUE; lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFloaterTexturePicker " << getName() << llendl; return handled; }
// TODO: Sort the legacy and non-legacy together? void LLPreviewGesture::addAnimations() { LLComboBox* combo = mAnimationCombo; combo->removeall(); std::string none_text = getString("none_text"); combo->add(none_text, LLUUID::null); // Add all the default (legacy) animations S32 i; for (i = 0; i < gUserAnimStatesCount; ++i) { // Use the user-readable name std::string label = LLAnimStateLabels::getStateLabel( gUserAnimStates[i].mName ); const LLUUID& id = gUserAnimStates[i].mID; combo->add(label, id); } // Get all inventory items that are animations LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; LLIsTypeWithPermissions is_copyable_animation(LLAssetType::AT_ANIMATION, PERM_ITEM_UNRESTRICTED, gAgent.getID(), gAgent.getGroupID()); gInventory.collectDescendentsIf(gInventory.getRootFolderID(), cats, items, LLInventoryModel::EXCLUDE_TRASH, is_copyable_animation); // Copy into something we can sort std::vector<LLInventoryItem*> animations; S32 count = items.count(); for(i = 0; i < count; ++i) { animations.push_back( items.get(i) ); } // Do the sort std::sort(animations.begin(), animations.end(), SortItemPtrsByName()); // And load up the combobox std::vector<LLInventoryItem*>::iterator it; for (it = animations.begin(); it != animations.end(); ++it) { LLInventoryItem* item = *it; combo->add(item->getName(), item->getAssetUUID(), ADD_BOTTOM); } }
// virtual BOOL LLFloaterTexturePicker::handleDragAndDrop( S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg) { BOOL handled = FALSE; if (cargo_type == DAD_TEXTURE) { LLInventoryItem *item = (LLInventoryItem *)cargo_data; BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()); PermissionMask item_perm_mask = 0; if (copy) item_perm_mask |= PERM_COPY; if (mod) item_perm_mask |= PERM_MODIFY; if (xfer) item_perm_mask |= PERM_TRANSFER; // <edit> //PermissionMask filter_perm_mask = mImmediateFilterPermMask; //if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask ) // </edit> { if (drop) { setImageID( item->getAssetUUID() ); commitIfImmediateSet(); } *accept = ACCEPT_YES_SINGLE; } // <edit> /*else { *accept = ACCEPT_NO; }*/ // </edit> } else { *accept = ACCEPT_NO; } handled = TRUE; lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFloaterTexturePicker " << getName() << llendl; return handled; }
// override void fire(const LLUUID& inv_item) { if(!mTextEditor) { // The parent text editor may have vanished by now. // In that case just quit. return; } LLInventoryItem* item = gInventory.getItem(inv_item); if(!item) { LL_WARNS() << "Item add reported, but not found in inventory!: " << inv_item << LL_ENDL; } else { // [RLVa:KB] - Checked: 2009-11-11 (RLVa-1.1.0a) | Modified: RLVa-1.1.0a if (gRlvHandler.hasBehaviour(RLV_BHVR_VIEWNOTE)) { RlvUtil::notifyBlockedViewXXX(LLAssetType::AT_NOTECARD); return; } // [/RLVa:KB] // See if we can bring an existing preview to the front if(!LLPreview::show(item->getUUID(), true)) { if (gSavedSettings.getBOOL("ShowNewInventory")) // Singu Note: ShowNewInventory is true, not false, when they want a preview { // There isn't one, so make a new preview S32 left, top; gFloaterView->getNewFloaterPosition(&left, &top); LLRect rect = gSavedSettings.getRect("NotecardEditorRect"); rect.translate(left - rect.mLeft, top - rect.mTop); LLPreviewNotecard* preview; preview = new LLPreviewNotecard("preview notecard", rect, std::string("Embedded Note: ") + item->getName(), item->getUUID(), LLUUID::null, item->getAssetUUID(), true, (LLViewerInventoryItem*)item); preview->setSourceID(LLUUID::null); preview->setFocus(TRUE); // Force to be entirely onscreen. gFloaterView->adjustToFitScreen(preview, FALSE); } } } }
void LLFloaterWorldMap::buildLandmarkIDLists() { LLCtrlListInterface *list = childGetListInterface("landmark combo"); if (!list) { return; } // Delete all but the "None" entry S32 list_size = list->getItemCount(); if (list_size > 1) { list->selectItemRange(1, -1); list->operateOnSelection(LLCtrlListInterface::OP_DELETE); } mLandmarkItemIDList.reset(); mLandmarkAssetIDList.reset(); // Get all of the current landmarks mLandmarkAssetIDList.put( LLUUID::null ); mLandmarkItemIDList.put( LLUUID::null ); mLandmarkAssetIDList.put( sHomeID ); mLandmarkItemIDList.put( sHomeID ); LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; LLIsType is_landmark(LLAssetType::AT_LANDMARK); gInventory.collectDescendentsIf(gAgent.getInventoryRootID(), cats, items, LLInventoryModel::EXCLUDE_TRASH, is_landmark); std::sort(items.begin(), items.end(), LLViewerInventoryItem::comparePointers()); S32 count = items.count(); for(S32 i = 0; i < count; ++i) { LLInventoryItem* item = items.get(i); list->addSimpleElement(item->getName(), ADD_BOTTOM, item->getUUID()); mLandmarkAssetIDList.put( item->getAssetUUID() ); mLandmarkItemIDList.put( item->getUUID() ); } list->sortByColumn(std::string("landmark name"), TRUE); list->selectFirstItem(); }
BOOL LLPanelOutfitEdit::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg) { if (cargo_data == NULL) { llwarns << "cargo_data is NULL" << llendl; return TRUE; } switch (cargo_type) { case DAD_BODYPART: case DAD_CLOTHING: case DAD_OBJECT: case DAD_LINK: *accept = ACCEPT_YES_MULTI; break; default: *accept = ACCEPT_NO; } if (drop) { LLInventoryItem* item = static_cast<LLInventoryItem*>(cargo_data); if (LLAssetType::lookupIsAssetIDKnowable(item->getType())) { mCOFDragAndDropObserver->watchAsset(item->getAssetUUID()); /* * Adding request to wear item. If the item is a link, then getLinkedUUID() will * return the ID of the linked item. Otherwise it will return the item's ID. The * second argument is used to delay the appearance update until all dragged items * are added to optimize user experience. */ LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), false); } else { // if asset id is not available for the item we must wear it immediately (attachments only) LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), true); } } return TRUE; }
// static void LLFloaterWorldMap::onLandmarkComboCommit( LLUICtrl* ctrl, void* userdata ) { LLFloaterWorldMap* self = gFloaterWorldMap; if( !self || self->mIsClosing ) { return; } LLCtrlListInterface *list = gFloaterWorldMap->childGetListInterface("landmark combo"); if (!list) return; LLUUID asset_id; LLUUID item_id = list->getCurrentID(); LLTracker::stopTracking(NULL); //RN: stopTracking() clears current combobox selection, need to reassert it here list->setCurrentByID(item_id); if( item_id.isNull() ) { } else if( item_id == sHomeID ) { asset_id = sHomeID; } else { LLInventoryItem* item = gInventory.getItem( item_id ); if( item ) { asset_id = item->getAssetUUID(); } else { // Something went wrong, so revert to a safe value. item_id.setNull(); } } self->trackLandmark( item_id); onShowTargetBtn(self); // Reset to user postion if nothing is tracked self->mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING ); }
void LLPreviewGesture::addSounds() { LLComboBox* combo = mSoundCombo; combo->removeall(); std::string none_text = getString("none_text"); combo->add(none_text, LLUUID::null); // Get all inventory items that are sounds LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; LLIsTypeWithPermissions is_copyable_sound(LLAssetType::AT_SOUND, PERM_ITEM_UNRESTRICTED, gAgent.getID(), gAgent.getGroupID()); gInventory.collectDescendentsIf(gInventory.getRootFolderID(), cats, items, LLInventoryModel::EXCLUDE_TRASH, is_copyable_sound); // Copy sounds into something we can sort std::vector<LLInventoryItem*> sounds; S32 i; S32 count = items.count(); for(i = 0; i < count; ++i) { sounds.push_back( items.get(i) ); } // Do the sort std::sort(sounds.begin(), sounds.end(), SortItemPtrsByName()); // And load up the combobox std::vector<LLInventoryItem*>::iterator it; for (it = sounds.begin(); it != sounds.end(); ++it) { LLInventoryItem* item = *it; combo->add(item->getName(), item->getAssetUUID(), ADD_BOTTOM); } }
// override void fire(const LLUUID& inv_item) { if(!mTextEditor) { // The parent text editor may have vanished by now. // In that case just quit. return; } LLInventoryItem* item = gInventory.getItem(inv_item); if(!item) { llwarns << "Item add reported, but not found in inventory!: " << inv_item << llendl; } else { // See if we can bring an existing preview to the front if(!LLPreview::show(item->getUUID(), true)) { if(!gSavedSettings.getBOOL("ShowNewInventory")) { // There isn't one, so make a new preview S32 left, top; gFloaterView->getNewFloaterPosition(&left, &top); LLRect rect = gSavedSettings.getRect("NotecardEditorRect"); rect.translate(left - rect.mLeft, top - rect.mTop); LLPreviewNotecard* preview; preview = new LLPreviewNotecard("preview notecard", rect, std::string("Embedded Note: ") + item->getName(), item->getUUID(), LLUUID::null, item->getAssetUUID(), true, (LLViewerInventoryItem*)item); preview->setSourceID(LLUUID::null); preview->setFocus(TRUE); // Force to be entirely onscreen. gFloaterView->adjustToFitScreen(preview, FALSE); } } } }
void LLFloaterAO::addAnimations() { mAnimListCombo->removeall(); std::string none_text = getString("none_text"); mAnimListCombo->add(none_text, LLUUID::null); // Add all the default (legacy) animations S32 i; // Get all inventory items that are animations LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; LLIsTypeWithPermissions is_copyable_animation(LLAssetType::AT_ANIMATION, PERM_NONE, gAgent.getID(), gAgent.getGroupID()); gInventory.collectDescendentsIf(gAgent.getInventoryRootID(), cats, items, LLInventoryModel::EXCLUDE_TRASH, is_copyable_animation); // Copy into something we can sort std::vector<LLInventoryItem*> animations; S32 count = items.count(); for(i = 0; i < count; ++i) { animations.push_back( items.get(i) ); } // Do the sort std::sort(animations.begin(), animations.end(), SortItemPtrsByName()); // And load up the combobox std::vector<LLInventoryItem*>::iterator it; for (it = animations.begin(); it != animations.end(); ++it) { LLInventoryItem* item = *it; mAnimListCombo->add(item->getName(), item->getAssetUUID(), ADD_BOTTOM); } }
/*virtual*/ void done() { std::vector<LLUUID>::const_iterator it = mAdded.begin(), end = mAdded.end(); for(; it != end; ++it) { LLInventoryItem* item = gInventory.getItem(*it); if (!item || item->getType() != LLAssetType::AT_LANDMARK) continue; // Start loading the landmark. LLLandmark* lm = gLandmarkList.getAsset( item->getAssetUUID(), boost::bind(&LLLocationInputCtrl::onLandmarkLoaded, mInput, _1)); if (lm) { // Already loaded? Great, handle it immediately (the callback won't be called). mInput->onLandmarkLoaded(lm); } } mAdded.clear(); }
void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action) { if (items.size()) { LLFolderViewItem* first_item = items.front(); LLInventoryItem* itemp = gInventory.getItem(first_item->getListener()->getUUID()); mNoCopyTextureSelected = FALSE; if (itemp) { if (!itemp->getPermissions().allowCopyBy(gAgent.getID())) { mNoCopyTextureSelected = TRUE; } mImageAssetID = itemp->getAssetUUID(); mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? if (user_action) { // only commit intentional selections, not implicit ones commitIfImmediateSet(); } } } }
// static void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action) { if (items.size()) { LLFolderViewItem* first_item = items.front(); LLInventoryItem* itemp = gInventory.getItem(first_item->getListener()->getUUID()); mNoCopyTextureSelected = FALSE; if (itemp) { if (!mTextureSelectedCallback.empty()) { mTextureSelectedCallback(itemp); } // <dogmode> if (itemp->getPermissions().getMaskOwner() & PERM_ALL) childSetValue("texture_uuid", mImageAssetID); else childSetValue("texture_uuid", LLUUID::null.asString()); // </dogmode> if (!itemp->getPermissions().allowCopyBy(gAgent.getID())) { mNoCopyTextureSelected = TRUE; } // <FS:Ansariel> FIRE-8298: Apply now checkbox has no effect setCanApply(true, true); // </FS:Ansariel> mImageAssetID = itemp->getAssetUUID(); mIsDirty = TRUE; if (user_action && mCanPreview) { // only commit intentional selections, not implicit ones commitIfImmediateSet(); } } } }
// static void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action, void* data) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)data; if (items.size()) { LLFolderViewItem* first_item = items.front(); LLInventoryItem* itemp = gInventory.getItem(first_item->getListener()->getUUID()); self->mNoCopyTextureSelected = FALSE; if (itemp) { if (!itemp->getPermissions().allowCopyBy(gAgent.getID())) { self->mNoCopyTextureSelected = TRUE; } self->mImageAssetID = itemp->getAssetUUID(); self->mIsDirty = TRUE; if (user_action) { // only commit intentional selections, not implicit ones self->commitIfImmediateSet(); } } } }
// virtual BOOL LLPreviewGesture::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, LLString& tooltip_msg) { BOOL handled = TRUE; switch(cargo_type) { case DAD_ANIMATION: case DAD_SOUND: { // TODO: Don't allow this if you can't transfer the sound/animation // make a script step LLInventoryItem* item = (LLInventoryItem*)cargo_data; if (item && gInventory.getItem(item->getUUID())) { LLPermissions perm = item->getPermissions(); if (!((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)) { *accept = ACCEPT_NO; if (tooltip_msg.empty()) { tooltip_msg.assign("Only animations and sounds\n" "with unrestricted permissions\n" "can be added to a gesture."); } break; } else if (drop) { LLScrollListItem* line = NULL; if (cargo_type == DAD_ANIMATION) { line = addStep("Animation"); LLGestureStepAnimation* anim = (LLGestureStepAnimation*)line->getUserdata(); anim->mAnimAssetID = item->getAssetUUID(); anim->mAnimName = item->getName(); } else if (cargo_type == DAD_SOUND) { line = addStep("Sound"); LLGestureStepSound* sound = (LLGestureStepSound*)line->getUserdata(); sound->mSoundAssetID = item->getAssetUUID(); sound->mSoundName = item->getName(); } updateLabel(line); mDirty = TRUE; refresh(); } *accept = ACCEPT_YES_COPY_MULTI; } else { // Not in user's inventory means it was in object inventory *accept = ACCEPT_NO; } break; } default: *accept = ACCEPT_NO; if (tooltip_msg.empty()) { tooltip_msg.assign("Only animations and sounds\n" "can be added to a gesture."); } break; } return handled; }
void LLFloaterWorldMap::buildLandmarkIDLists() { LLCtrlListInterface *list = mListLandmarkCombo; if (!list) return; // Delete all but the "None" entry S32 list_size = list->getItemCount(); if (list_size > 1) { list->selectItemRange(1, -1); list->operateOnSelection(LLCtrlListInterface::OP_DELETE); } mLandmarkItemIDList.reset(); mLandmarkAssetIDList.reset(); // Get all of the current landmarks mLandmarkAssetIDList.put( LLUUID::null ); mLandmarkItemIDList.put( LLUUID::null ); mLandmarkAssetIDList.put( sHomeID ); mLandmarkItemIDList.put( sHomeID ); LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; LLIsType is_landmark(LLAssetType::AT_LANDMARK); gInventory.collectDescendentsIf(gInventory.getRootFolderID(), cats, items, LLInventoryModel::EXCLUDE_TRASH, is_landmark); std::sort(items.begin(), items.end(), LLViewerInventoryItem::comparePointers()); std::list<LLInventoryItem*> usedLMs; BOOL filterLandmarks = gSavedSettings.getBOOL("WorldmapFilterDuplicateLandmarks"); S32 count = items.count(); for(S32 i = 0; i < count; ++i) { LLInventoryItem* item = items.get(i); if (filterLandmarks) { bool skip = false; for (std::list<LLInventoryItem*>::iterator it = usedLMs.begin(); it != usedLMs.end(); ++it) { if ((*it)->getAssetUUID() == item->getAssetUUID()) { skip = true; break; } } if (skip) continue; usedLMs.push_front(item); } list->addSimpleElement(item->getName(), ADD_BOTTOM, item->getUUID()); mLandmarkAssetIDList.put( item->getAssetUUID() ); mLandmarkItemIDList.put( item->getUUID() ); } list->selectFirstItem(); }
BOOL LLFloaterAO::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg) { BOOL handled = TRUE; switch(cargo_type) { case DAD_NOTECARD: { // Pop off to Lua LLInventoryItem* item = (LLInventoryItem*)cargo_data; if (item && gInventory.getItem(item->getAssetUUID())) { // @hook OnAONotecard(asset_id) LUA_CALL("OnAONotecard") << item->getAssetUUID() << LUA_END; } *accept = ACCEPT_YES_COPY_MULTI; break; } case DAD_ANIMATION: { LLInventoryItem* item = (LLInventoryItem*)cargo_data; if (item && gInventory.getItem(item->getUUID())) { if (drop) { if (cargo_type == DAD_ANIMATION) { std::string anim_name = item->getName(); if (anim_name == "") return true; LLUUID id(LLAO::getAssetIDByName(anim_name)); #ifdef AO_DEBUG llinfos << "Actually adding animation, this should be refreshed. Count:" << LLAO::mAnimationOverrides[mCurrentAnimType].size() << llendl; #endif LLAO::mAnimationOverrides[mCurrentAnimType].append(anim_name); #ifdef AO_DEBUG llinfos << "Added animation. Count:" << LLAO::mAnimationOverrides[mCurrentAnimType].size() << llendl; #endif //LLAO::mTimer->reset(); onCommitAnim(NULL,this); } refresh(); } *accept = ACCEPT_YES_COPY_MULTI; } else { // Not in user's inventory means it was in object inventory *accept = ACCEPT_NO; } break; } default: *accept = ACCEPT_NO; if (tooltip_msg.empty()) { tooltip_msg.assign("Only animations can be added to the AO."); } break; } return handled; }