/** * @file llfloaterpathfindingobjects.cpp * @brief Base class for both the pathfinding linksets and characters floater. * @author Stinson@lindenlab.com * * $LicenseInfo:firstyear=2012&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2012, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" #include "llfloaterpathfindingobjects.h" #include #include #include #include #include #include "llagent.h" #include "llavatarname.h" #include "llavatarnamecache.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llfloater.h" #include "llfontgl.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llpathfindingmanager.h" #include "llresmgr.h" #include "llscrolllistcell.h" #include "llscrolllistctrl.h" #include "llscrolllistitem.h" #include "llselectmgr.h" #include "llsd.h" #include "llstring.h" #include "llstyle.h" #include "lltextbase.h" #include "lluicolortable.h" #include "llviewermenu.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" #include "v3dmath.h" #include "v3math.h" #include "v4color.h" #define DEFAULT_BEACON_WIDTH 6 //--------------------------------------------------------------------------- // LLFloaterPathfindingObjects //--------------------------------------------------------------------------- void LLFloaterPathfindingObjects::onOpen(const LLSD &pKey) { LLFloater::onOpen(pKey); selectNoneObjects(); mObjectsScrollList->setCommitOnSelectionChange(true); if (!mSelectionUpdateSlot.connected()) { mSelectionUpdateSlot = LLSelectMgr::getInstance()->mUpdateSignal.connect(boost::bind(&LLFloaterPathfindingObjects::onInWorldSelectionListChanged, this)); } if (!mRegionBoundaryCrossingSlot.connected()) { mRegionBoundaryCrossingSlot = gAgent.addRegionChangedCallback(boost::bind(&LLFloaterPathfindingObjects::onRegionBoundaryCrossed, this)); } if (!mGodLevelChangeSlot.connected()) { mGodLevelChangeSlot = gAgent.registerGodLevelChanageListener(boost::bind(&LLFloaterPathfindingObjects::onGodLevelChange, this, _1)); } requestGetObjects(); } void LLFloaterPathfindingObjects::onClose(bool pIsAppQuitting) { if (mGodLevelChangeSlot.connected()) { mGodLevelChangeSlot.disconnect(); } if (mRegionBoundaryCrossingSlot.connected()) { mRegionBoundaryCrossingSlot.disconnect(); } if (mSelectionUpdateSlot.connected()) { mSelectionUpdateSlot.disconnect(); } mObjectsScrollList->setCommitOnSelectionChange(false); selectNoneObjects(); if (mObjectsSelection.notNull()) { mObjectsSelection.clear(); } if (pIsAppQuitting) { clearAllObjects(); } } void LLFloaterPathfindingObjects::draw() { LLFloater::draw(); if (isShowBeacons()) { std::vector selectedItems = mObjectsScrollList->getAllSelected(); if (!selectedItems.empty()) { auto numSelectedItems = selectedItems.size(); S32 nameColumnIndex = getNameColumnIndex(); const LLColor4 &beaconColor = getBeaconColor(); const LLColor4 &beaconTextColor = getBeaconTextColor(); S32 beaconWidth = getBeaconWidth(); std::vector viewerObjects; viewerObjects.reserve(numSelectedItems); for (std::vector::const_iterator selectedItemIter = selectedItems.begin(); selectedItemIter != selectedItems.end(); ++selectedItemIter) { const LLScrollListItem *selectedItem = *selectedItemIter; LLViewerObject *viewerObject = gObjectList.findObject(selectedItem->getUUID()); if (viewerObject != NULL) { const std::string &objectName = selectedItem->getColumn(nameColumnIndex)->getValue().asString(); gObjectList.addDebugBeacon(viewerObject->getPositionAgent(), objectName, beaconColor, beaconTextColor, beaconWidth); } } } } } LLFloaterPathfindingObjects::LLFloaterPathfindingObjects(const LLSD &pSeed) : LLFloater(pSeed), mObjectsScrollList(NULL), mMessagingStatus(NULL), mRefreshListButton(NULL), mSelectAllButton(NULL), mSelectNoneButton(NULL), mShowBeaconCheckBox(NULL), mTakeButton(NULL), mTakeCopyButton(NULL), mReturnButton(NULL), mDeleteButton(NULL), mTeleportButton(NULL), mDefaultBeaconColor(), mDefaultBeaconTextColor(), mErrorTextColor(), mWarningTextColor(), mMessagingState(kMessagingUnknown), mMessagingRequestId(0U), mMissingNameObjectsScrollListItems(), mObjectList(), mObjectsSelection(), mHasObjectsToBeSelected(false), mObjectsToBeSelected(), mSelectionUpdateSlot(), mRegionBoundaryCrossingSlot() { } LLFloaterPathfindingObjects::~LLFloaterPathfindingObjects() { clearAllObjects(); } bool LLFloaterPathfindingObjects::postBuild() { mDefaultBeaconColor = LLUIColorTable::getInstance()->getColor("PathfindingDefaultBeaconColor"); mDefaultBeaconTextColor = LLUIColorTable::getInstance()->getColor("PathfindingDefaultBeaconTextColor"); mErrorTextColor = LLUIColorTable::getInstance()->getColor("PathfindingErrorColor"); mWarningTextColor = LLUIColorTable::getInstance()->getColor("PathfindingWarningColor"); mObjectsScrollList = findChild("objects_scroll_list"); llassert(mObjectsScrollList != NULL); mObjectsScrollList->setCommitCallback(boost::bind(&LLFloaterPathfindingObjects::onScrollListSelectionChanged, this)); mObjectsScrollList->sortByColumnIndex(static_cast(getNameColumnIndex()), true); mMessagingStatus = findChild("messaging_status"); llassert(mMessagingStatus != NULL); mRefreshListButton = findChild("refresh_objects_list"); llassert(mRefreshListButton != NULL); mRefreshListButton->setCommitCallback(boost::bind(&LLFloaterPathfindingObjects::onRefreshObjectsClicked, this)); mSelectAllButton = findChild("select_all_objects"); llassert(mSelectAllButton != NULL); mSelectAllButton->setCommitCallback(boost::bind(&LLFloaterPathfindingObjects::onSelectAllObjectsClicked, this)); mSelectNoneButton = findChild("select_none_objects"); llassert(mSelectNoneButton != NULL); mSelectNoneButton->setCommitCallback(boost::bind(&LLFloaterPathfindingObjects::onSelectNoneObjectsClicked, this)); mShowBeaconCheckBox = findChild("show_beacon"); llassert(mShowBeaconCheckBox != NULL); mTakeButton = findChild("take_objects"); llassert(mTakeButton != NULL); mTakeButton->setCommitCallback(boost::bind(&LLFloaterPathfindingObjects::onTakeClicked, this)); mTakeCopyButton = findChild("take_copy_objects"); llassert(mTakeCopyButton != NULL); mTakeCopyButton->setCommitCallback(boost::bind(&LLFloaterPathfindingObjects::onTakeCopyClicked, this)); mReturnButton = findChild("return_objects"); llassert(mReturnButton != NULL); mReturnButton->setCommitCallback(boost::bind(&LLFloaterPathfindingObjects::onReturnClicked, this)); mDeleteButton = findChild("delete_objects"); llassert(mDeleteButton != NULL); mDeleteButton->setCommitCallback(boost::bind(&LLFloaterPathfindingObjects::onDeleteClicked, this)); mTeleportButton = findChild("teleport_me_to_object"); llassert(mTeleportButton != NULL); mTeleportButton->setCommitCallback(boost::bind(&LLFloaterPathfindingObjects::onTeleportClicked, this)); return LLFloater::postBuild(); } void LLFloaterPathfindingObjects::requestGetObjects() { llassert(0); } LLPathfindingManager::request_id_t LLFloaterPathfindingObjects::getNewRequestId() { return ++mMessagingRequestId; } void LLFloaterPathfindingObjects::handleNewObjectList(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::ERequestStatus pRequestStatus, LLPathfindingObjectListPtr pObjectList) { llassert(pRequestId <= mMessagingRequestId); if (pRequestId == mMessagingRequestId) { switch (pRequestStatus) { case LLPathfindingManager::kRequestStarted : setMessagingState(kMessagingGetRequestSent); break; case LLPathfindingManager::kRequestCompleted : mObjectList = pObjectList; rebuildObjectsScrollList(); setMessagingState(kMessagingComplete); break; case LLPathfindingManager::kRequestNotEnabled : clearAllObjects(); setMessagingState(kMessagingNotEnabled); break; case LLPathfindingManager::kRequestError : clearAllObjects(); setMessagingState(kMessagingGetError); break; default : clearAllObjects(); setMessagingState(kMessagingGetError); llassert(0); break; } } } void LLFloaterPathfindingObjects::handleUpdateObjectList(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::ERequestStatus pRequestStatus, LLPathfindingObjectListPtr pObjectList) { // We current assume that handleUpdateObjectList is called only when objects are being SET llassert(pRequestId <= mMessagingRequestId); if (pRequestId == mMessagingRequestId) { switch (pRequestStatus) { case LLPathfindingManager::kRequestStarted : setMessagingState(kMessagingSetRequestSent); break; case LLPathfindingManager::kRequestCompleted : if (mObjectList == NULL) { mObjectList = pObjectList; } else { mObjectList->update(pObjectList); } rebuildObjectsScrollList(); setMessagingState(kMessagingComplete); break; case LLPathfindingManager::kRequestNotEnabled : clearAllObjects(); setMessagingState(kMessagingNotEnabled); break; case LLPathfindingManager::kRequestError : clearAllObjects(); setMessagingState(kMessagingSetError); break; default : clearAllObjects(); setMessagingState(kMessagingSetError); llassert(0); break; } } } void LLFloaterPathfindingObjects::rebuildObjectsScrollList(bool update_if_needed) { if (!mHasObjectsToBeSelected) { std::vector selectedItems = mObjectsScrollList->getAllSelected(); auto numSelectedItems = selectedItems.size(); if (numSelectedItems > 0) { mObjectsToBeSelected.reserve(selectedItems.size()); for (std::vector::const_iterator itemIter = selectedItems.begin(); itemIter != selectedItems.end(); ++itemIter) { const LLScrollListItem *listItem = *itemIter; mObjectsToBeSelected.push_back(listItem->getUUID()); } } } S32 origScrollPosition = mObjectsScrollList->getScrollPos(); mObjectsScrollList->deleteAllItems(); mMissingNameObjectsScrollListItems.clear(); if ((mObjectList != NULL) && !mObjectList->isEmpty()) { buildObjectsScrollList(mObjectList); if(mObjectsScrollList->selectMultiple(mObjectsToBeSelected) == 0) { if(update_if_needed && mRefreshListButton->getEnabled()) { requestGetObjects(); return; } } if (mHasObjectsToBeSelected) { mObjectsScrollList->scrollToShowSelected(); } else { mObjectsScrollList->setScrollPos(origScrollPosition); } } mObjectsToBeSelected.clear(); mHasObjectsToBeSelected = false; updateControlsOnScrollListChange(); } void LLFloaterPathfindingObjects::buildObjectsScrollList(const LLPathfindingObjectListPtr pObjectListPtr) { llassert(0); } void LLFloaterPathfindingObjects::addObjectToScrollList(const LLPathfindingObjectPtr pObjectPtr, const LLSD &pScrollListItemData) { LLScrollListCell::Params cellParams; cellParams.font = LLFontGL::getFontSansSerif(); LLScrollListItem::Params rowParams; rowParams.value = pObjectPtr->getUUID().asString(); llassert(pScrollListItemData.isArray()); for (LLSD::array_const_iterator cellIter = pScrollListItemData.beginArray(); cellIter != pScrollListItemData.endArray(); ++cellIter) { const LLSD &cellElement = *cellIter; llassert(cellElement.has("column")); llassert(cellElement.get("column").isString()); cellParams.column = cellElement.get("column").asString(); llassert(cellElement.has("value")); llassert(cellElement.get("value").isString()); cellParams.value = cellElement.get("value").asString(); rowParams.columns.add(cellParams); } LLScrollListItem *scrollListItem = mObjectsScrollList->addRow(rowParams); if (pObjectPtr->hasOwner() && !pObjectPtr->hasOwnerName()) { mMissingNameObjectsScrollListItems.insert(scroll_list_item_map::value_type(pObjectPtr->getUUID().asString(), scrollListItem)); pObjectPtr->registerOwnerNameListener(boost::bind(&LLFloaterPathfindingObjects::handleObjectNameResponse, this, _1)); } } void LLFloaterPathfindingObjects::updateControlsOnScrollListChange() { updateMessagingStatus(); updateStateOnListControls(); selectScrollListItemsInWorld(); updateStateOnActionControls(); } void LLFloaterPathfindingObjects::updateControlsOnInWorldSelectionChange() { updateStateOnActionControls(); } S32 LLFloaterPathfindingObjects::getNameColumnIndex() const { return 0; } S32 LLFloaterPathfindingObjects::getOwnerNameColumnIndex() const { return 2; } std::string LLFloaterPathfindingObjects::getOwnerName(const LLPathfindingObject *pObject) const { llassert(0); std::string returnVal; return returnVal; } const LLColor4 &LLFloaterPathfindingObjects::getBeaconColor() const { return mDefaultBeaconColor; } const LLColor4 &LLFloaterPathfindingObjects::getBeaconTextColor() const { return mDefaultBeaconTextColor; } S32 LLFloaterPathfindingObjects::getBeaconWidth() const { return DEFAULT_BEACON_WIDTH; } void LLFloaterPathfindingObjects::showFloaterWithSelectionObjects() { mObjectsToBeSelected.clear(); LLObjectSelectionHandle selectedObjectsHandle = LLSelectMgr::getInstance()->getSelection(); if (selectedObjectsHandle.notNull()) { LLObjectSelection *selectedObjects = selectedObjectsHandle.get(); if (!selectedObjects->isEmpty()) { for (LLObjectSelection::valid_iterator objectIter = selectedObjects->valid_begin(); objectIter != selectedObjects->valid_end(); ++objectIter) { LLSelectNode *object = *objectIter; LLViewerObject *viewerObject = object->getObject(); mObjectsToBeSelected.push_back(viewerObject->getID()); } } } mHasObjectsToBeSelected = true; if (!isShown()) { openFloater(); setVisibleAndFrontmost(); } else { rebuildObjectsScrollList(true); if (isMinimized()) { setMinimized(false); } setVisibleAndFrontmost(); } setFocus(true); } bool LLFloaterPathfindingObjects::isShowBeacons() const { return mShowBeaconCheckBox->get(); } void LLFloaterPathfindingObjects::clearAllObjects() { selectNoneObjects(); mObjectsScrollList->deleteAllItems(); mMissingNameObjectsScrollListItems.clear(); mObjectList.reset(); } void LLFloaterPathfindingObjects::selectAllObjects() { mObjectsScrollList->selectAll(); } void LLFloaterPathfindingObjects::selectNoneObjects() { mObjectsScrollList->deselectAllItems(); } void LLFloaterPathfindingObjects::teleportToSelectedObject() { std::vector selectedItems = mObjectsScrollList->getAllSelected(); llassert(selectedItems.size() == 1); if (selectedItems.size() == 1) { std::vector::const_reference selectedItemRef = selectedItems.front(); const LLScrollListItem *selectedItem = selectedItemRef; llassert(mObjectList != NULL); LLVector3d teleportLocation; LLViewerObject *viewerObject = gObjectList.findObject(selectedItem->getUUID()); if (viewerObject == NULL) { // If we cannot find the object in the viewer list, teleport to the last reported position const LLPathfindingObjectPtr objectPtr = mObjectList->find(selectedItem->getUUID().asString()); teleportLocation = gAgent.getPosGlobalFromAgent(objectPtr->getLocation()); } else { // If we can find the object in the viewer list, teleport to the known current position teleportLocation = viewerObject->getPositionGlobal(); } gAgent.teleportViaLocationLookAt(teleportLocation); } } LLPathfindingObjectListPtr LLFloaterPathfindingObjects::getEmptyObjectList() const { llassert(0); LLPathfindingObjectListPtr objectListPtr(new LLPathfindingObjectList()); return objectListPtr; } int LLFloaterPathfindingObjects::getNumSelectedObjects() const { return mObjectsScrollList->getNumSelected(); } LLPathfindingObjectListPtr LLFloaterPathfindingObjects::getSelectedObjects() const { LLPathfindingObjectListPtr selectedObjects = getEmptyObjectList(); std::vector selectedItems = mObjectsScrollList->getAllSelected(); if (!selectedItems.empty()) { for (std::vector::const_iterator itemIter = selectedItems.begin(); itemIter != selectedItems.end(); ++itemIter) { LLPathfindingObjectPtr objectPtr = findObject(*itemIter); if (objectPtr != NULL) { selectedObjects->update(objectPtr); } } } return selectedObjects; } LLPathfindingObjectPtr LLFloaterPathfindingObjects::getFirstSelectedObject() const { LLPathfindingObjectPtr objectPtr; std::vector selectedItems = mObjectsScrollList->getAllSelected(); if (!selectedItems.empty()) { objectPtr = findObject(selectedItems.front()); } return objectPtr; } LLFloaterPathfindingObjects::EMessagingState LLFloaterPathfindingObjects::getMessagingState() const { return mMessagingState; } void LLFloaterPathfindingObjects::setMessagingState(EMessagingState pMessagingState) { mMessagingState = pMessagingState; updateControlsOnScrollListChange(); } void LLFloaterPathfindingObjects::onRefreshObjectsClicked() { requestGetObjects(); } void LLFloaterPathfindingObjects::onSelectAllObjectsClicked() { selectAllObjects(); } void LLFloaterPathfindingObjects::onSelectNoneObjectsClicked() { selectNoneObjects(); } void LLFloaterPathfindingObjects::onTakeClicked() { handle_take(); requestGetObjects(); } void LLFloaterPathfindingObjects::onTakeCopyClicked() { handle_take_copy(); } void LLFloaterPathfindingObjects::onReturnClicked() { LLNotification::Params params("PathfindingReturnMultipleItems"); params.functor.function(boost::bind(&LLFloaterPathfindingObjects::handleReturnItemsResponse, this, _1, _2)); LLSD substitutions; int numItems = getNumSelectedObjects(); substitutions["NUM_ITEMS"] = static_cast(numItems); params.substitutions = substitutions; if (numItems == 1) { LLNotifications::getInstance()->forceResponse(params, 0); } else if (numItems > 1) { LLNotifications::getInstance()->add(params); } } void LLFloaterPathfindingObjects::onDeleteClicked() { LLNotification::Params params("PathfindingDeleteMultipleItems"); params.functor.function(boost::bind(&LLFloaterPathfindingObjects::handleDeleteItemsResponse, this, _1, _2)); LLSD substitutions; int numItems = getNumSelectedObjects(); substitutions["NUM_ITEMS"] = static_cast(numItems); params.substitutions = substitutions; if (numItems == 1) { LLNotifications::getInstance()->forceResponse(params, 0); } else if (numItems > 1) { LLNotifications::getInstance()->add(params); } } void LLFloaterPathfindingObjects::onTeleportClicked() { teleportToSelectedObject(); } void LLFloaterPathfindingObjects::onScrollListSelectionChanged() { updateControlsOnScrollListChange(); } void LLFloaterPathfindingObjects::onInWorldSelectionListChanged() { updateControlsOnInWorldSelectionChange(); } void LLFloaterPathfindingObjects::onRegionBoundaryCrossed() { requestGetObjects(); } void LLFloaterPathfindingObjects::onGodLevelChange(U8 pGodLevel) { requestGetObjects(); } void LLFloaterPathfindingObjects::handleObjectNameResponse(const LLPathfindingObject *pObject) { llassert(pObject != NULL); const std::string uuid = pObject->getUUID().asString(); scroll_list_item_map::iterator scrollListItemIter = mMissingNameObjectsScrollListItems.find(uuid); if (scrollListItemIter != mMissingNameObjectsScrollListItems.end()) { LLScrollListItem *scrollListItem = scrollListItemIter->second; llassert(scrollListItem != NULL); LLScrollListCell *scrollListCell = scrollListItem->getColumn(getOwnerNameColumnIndex()); LLSD ownerName = getOwnerName(pObject); scrollListCell->setValue(ownerName); mMissingNameObjectsScrollListItems.erase(scrollListItemIter); } } void LLFloaterPathfindingObjects::updateMessagingStatus() { std::string statusText(""); LLStyle::Params styleParams; switch (getMessagingState()) { case kMessagingUnknown: statusText = getString("messaging_initial"); styleParams.color = mErrorTextColor; break; case kMessagingGetRequestSent : statusText = getString("messaging_get_inprogress"); styleParams.color = mWarningTextColor; break; case kMessagingGetError : statusText = getString("messaging_get_error"); styleParams.color = mErrorTextColor; break; case kMessagingSetRequestSent : statusText = getString("messaging_set_inprogress"); styleParams.color = mWarningTextColor; break; case kMessagingSetError : statusText = getString("messaging_set_error"); styleParams.color = mErrorTextColor; break; case kMessagingComplete : if (mObjectsScrollList->isEmpty()) { statusText = getString("messaging_complete_none_found"); } else { S32 numItems = mObjectsScrollList->getItemCount(); S32 numSelectedItems = mObjectsScrollList->getNumSelected(); LLLocale locale(LLStringUtil::getLocale()); std::string numItemsString; LLResMgr::getInstance()->getIntegerString(numItemsString, numItems); std::string numSelectedItemsString; LLResMgr::getInstance()->getIntegerString(numSelectedItemsString, numSelectedItems); LLStringUtil::format_map_t string_args; string_args["[NUM_SELECTED]"] = numSelectedItemsString; string_args["[NUM_TOTAL]"] = numItemsString; statusText = getString("messaging_complete_available", string_args); } break; case kMessagingNotEnabled : statusText = getString("messaging_not_enabled"); styleParams.color = mErrorTextColor; break; default: statusText = getString("messaging_initial"); styleParams.color = mErrorTextColor; llassert(0); break; } mMessagingStatus->setText((LLStringExplicit)statusText, styleParams); } void LLFloaterPathfindingObjects::updateStateOnListControls() { switch (getMessagingState()) { case kMessagingUnknown: case kMessagingGetRequestSent : case kMessagingSetRequestSent : mRefreshListButton->setEnabled(false); mSelectAllButton->setEnabled(false); mSelectNoneButton->setEnabled(false); break; case kMessagingGetError : case kMessagingSetError : case kMessagingNotEnabled : mRefreshListButton->setEnabled(true); mSelectAllButton->setEnabled(false); mSelectNoneButton->setEnabled(false); break; case kMessagingComplete : { int numItems = mObjectsScrollList->getItemCount(); int numSelectedItems = mObjectsScrollList->getNumSelected(); mRefreshListButton->setEnabled(true); mSelectAllButton->setEnabled(numSelectedItems < numItems); mSelectNoneButton->setEnabled(numSelectedItems > 0); } break; default: llassert(0); break; } } void LLFloaterPathfindingObjects::updateStateOnActionControls() { int numSelectedItems = mObjectsScrollList->getNumSelected(); bool isEditEnabled = (numSelectedItems > 0); mShowBeaconCheckBox->setEnabled(isEditEnabled); mTakeButton->setEnabled(isEditEnabled && visible_take_object()); mTakeCopyButton->setEnabled(isEditEnabled && enable_object_take_copy()); mReturnButton->setEnabled(isEditEnabled && enable_object_return()); mDeleteButton->setEnabled(isEditEnabled && enable_object_delete()); mTeleportButton->setEnabled(numSelectedItems == 1); } void LLFloaterPathfindingObjects::selectScrollListItemsInWorld() { mObjectsSelection.clear(); LLSelectMgr::getInstance()->deselectAll(); std::vector selectedItems = mObjectsScrollList->getAllSelected(); if (!selectedItems.empty()) { auto numSelectedItems = selectedItems.size(); std::vectorviewerObjects; viewerObjects.reserve(numSelectedItems); for (std::vector::const_iterator selectedItemIter = selectedItems.begin(); selectedItemIter != selectedItems.end(); ++selectedItemIter) { const LLScrollListItem *selectedItem = *selectedItemIter; LLViewerObject *viewerObject = gObjectList.findObject(selectedItem->getUUID()); if (viewerObject != NULL) { viewerObjects.push_back(viewerObject); } } if (!viewerObjects.empty()) { mObjectsSelection = LLSelectMgr::getInstance()->selectObjectAndFamily(viewerObjects); } } } void LLFloaterPathfindingObjects::handleReturnItemsResponse(const LLSD &pNotification, const LLSD &pResponse) { if (LLNotificationsUtil::getSelectedOption(pNotification, pResponse) == 0) { handle_object_return(); requestGetObjects(); } } void LLFloaterPathfindingObjects::handleDeleteItemsResponse(const LLSD &pNotification, const LLSD &pResponse) { if (LLNotificationsUtil::getSelectedOption(pNotification, pResponse) == 0) { handle_object_delete(); requestGetObjects(); } } LLPathfindingObjectPtr LLFloaterPathfindingObjects::findObject(const LLScrollListItem *pListItem) const { LLPathfindingObjectPtr objectPtr; LLUUID uuid = pListItem->getUUID(); const std::string &uuidString = uuid.asString(); llassert(mObjectList != NULL); objectPtr = mObjectList->find(uuidString); return objectPtr; }