/** * @file llfloaterpathfindingcharacters.cpp * @brief "Pathfinding characters" floater, allowing for identification of pathfinding characters and their cpu usage. * @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 "llfloaterpathfindingcharacters.h" #include <string> #include "llcheckboxctrl.h" #include "llfloaterreg.h" #include "llfloaterpathfindingobjects.h" #include "llhandle.h" #include "llpathfindingcharacter.h" #include "llpathfindingcharacterlist.h" #include "llpathfindingmanager.h" #include "llpathfindingobject.h" #include "llpathfindingobjectlist.h" #include "llpathinglib.h" #include "llquaternion.h" #include "llsd.h" #include "lluicolortable.h" #include "lluuid.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" #include "pipeline.h" #include "v3math.h" #include "v4color.h" LLHandle<LLFloaterPathfindingCharacters> LLFloaterPathfindingCharacters::sInstanceHandle; //--------------------------------------------------------------------------- // LLFloaterPathfindingCharacters //--------------------------------------------------------------------------- void LLFloaterPathfindingCharacters::onClose(bool pIsAppQuitting) { // Hide any capsule that might be showing on floater close hideCapsule(); LLFloaterPathfindingObjects::onClose( pIsAppQuitting ); } bool LLFloaterPathfindingCharacters::isShowPhysicsCapsule() const { return mShowPhysicsCapsuleCheckBox->get(); } void LLFloaterPathfindingCharacters::setShowPhysicsCapsule(bool pIsShowPhysicsCapsule) { mShowPhysicsCapsuleCheckBox->set(pIsShowPhysicsCapsule && (LLPathingLib::getInstance() != NULL)); } bool LLFloaterPathfindingCharacters::isPhysicsCapsuleEnabled(LLUUID& id, LLVector3& pos, LLQuaternion& rot) const { id = mSelectedCharacterId; // Physics capsule is enable if the checkbox is enabled and if we can get the required render // parameters for any selected object return (isShowPhysicsCapsule() && getCapsuleRenderData(pos, rot )); } void LLFloaterPathfindingCharacters::openCharactersWithSelectedObjects() { LLFloaterPathfindingCharacters *charactersFloater = LLFloaterReg::getTypedInstance<LLFloaterPathfindingCharacters>("pathfinding_characters"); charactersFloater->showFloaterWithSelectionObjects(); } LLHandle<LLFloaterPathfindingCharacters> LLFloaterPathfindingCharacters::getInstanceHandle() { if ( sInstanceHandle.isDead() ) { LLFloaterPathfindingCharacters *floaterInstance = LLFloaterReg::findTypedInstance<LLFloaterPathfindingCharacters>("pathfinding_characters"); if (floaterInstance != NULL) { sInstanceHandle = floaterInstance->mSelfHandle; } } return sInstanceHandle; } LLFloaterPathfindingCharacters::LLFloaterPathfindingCharacters(const LLSD& pSeed) : LLFloaterPathfindingObjects(pSeed), mShowPhysicsCapsuleCheckBox(NULL), mSelectedCharacterId(), mBeaconColor(), mSelfHandle() { mSelfHandle.bind(this); } LLFloaterPathfindingCharacters::~LLFloaterPathfindingCharacters() { } bool LLFloaterPathfindingCharacters::postBuild() { mBeaconColor = LLUIColorTable::getInstance()->getColor("PathfindingCharacterBeaconColor"); mShowPhysicsCapsuleCheckBox = findChild<LLCheckBoxCtrl>("show_physics_capsule"); llassert(mShowPhysicsCapsuleCheckBox != NULL); mShowPhysicsCapsuleCheckBox->setCommitCallback(boost::bind(&LLFloaterPathfindingCharacters::onShowPhysicsCapsuleClicked, this)); mShowPhysicsCapsuleCheckBox->setEnabled(LLPathingLib::getInstance() != NULL); return LLFloaterPathfindingObjects::postBuild(); } void LLFloaterPathfindingCharacters::requestGetObjects() { LLPathfindingManager::getInstance()->requestGetCharacters(getNewRequestId(), boost::bind(&LLFloaterPathfindingCharacters::handleNewObjectList, this, _1, _2, _3)); } void LLFloaterPathfindingCharacters::buildObjectsScrollList(const LLPathfindingObjectListPtr pObjectListPtr) { llassert(pObjectListPtr != NULL); llassert(!pObjectListPtr->isEmpty()); for (LLPathfindingObjectList::const_iterator objectIter = pObjectListPtr->begin(); objectIter != pObjectListPtr->end(); ++objectIter) { const LLPathfindingObjectPtr objectPtr = objectIter->second; const LLPathfindingCharacter *characterPtr = dynamic_cast<const LLPathfindingCharacter *>(objectPtr.get()); llassert(characterPtr != NULL); LLSD scrollListItemData = buildCharacterScrollListItemData(characterPtr); addObjectToScrollList(objectPtr, scrollListItemData); } } void LLFloaterPathfindingCharacters::updateControlsOnScrollListChange() { LLFloaterPathfindingObjects::updateControlsOnScrollListChange(); updateStateOnDisplayControls(); showSelectedCharacterCapsules(); } S32 LLFloaterPathfindingCharacters::getNameColumnIndex() const { return 0; } S32 LLFloaterPathfindingCharacters::getOwnerNameColumnIndex() const { return 2; } std::string LLFloaterPathfindingCharacters::getOwnerName(const LLPathfindingObject *pObject) const { return (pObject->hasOwner() ? (pObject->hasOwnerName() ? (pObject->isGroupOwned() ? (pObject->getOwnerName() + " " + getString("character_owner_group")) : pObject->getOwnerName()) : getString("character_owner_loading")) : getString("character_owner_unknown")); } const LLColor4 &LLFloaterPathfindingCharacters::getBeaconColor() const { return mBeaconColor; } LLPathfindingObjectListPtr LLFloaterPathfindingCharacters::getEmptyObjectList() const { LLPathfindingObjectListPtr objectListPtr(new LLPathfindingCharacterList()); return objectListPtr; } void LLFloaterPathfindingCharacters::onShowPhysicsCapsuleClicked() { if (LLPathingLib::getInstance() == NULL) { if (isShowPhysicsCapsule()) { setShowPhysicsCapsule(false); } } else { if (mSelectedCharacterId.notNull() && isShowPhysicsCapsule()) { showCapsule(); } else { hideCapsule(); } } } LLSD LLFloaterPathfindingCharacters::buildCharacterScrollListItemData(const LLPathfindingCharacter *pCharacterPtr) const { LLSD columns = LLSD::emptyArray(); columns[0]["column"] = "name"; columns[0]["value"] = pCharacterPtr->getName(); columns[1]["column"] = "description"; columns[1]["value"] = pCharacterPtr->getDescription(); columns[2]["column"] = "owner"; columns[2]["value"] = getOwnerName(pCharacterPtr); S32 cpuTime = ll_round(pCharacterPtr->getCPUTime()); std::string cpuTimeString = llformat("%d", cpuTime); LLStringUtil::format_map_t string_args; string_args["[CPU_TIME]"] = cpuTimeString; columns[3]["column"] = "cpu_time"; columns[3]["value"] = getString("character_cpu_time", string_args); columns[4]["column"] = "altitude"; columns[4]["value"] = llformat("%1.0f m", pCharacterPtr->getLocation()[2]); return columns; } void LLFloaterPathfindingCharacters::updateStateOnDisplayControls() { int numSelectedItems = getNumSelectedObjects();; bool isEditEnabled = ((numSelectedItems == 1) && (LLPathingLib::getInstance() != NULL)); mShowPhysicsCapsuleCheckBox->setEnabled(isEditEnabled); if (!isEditEnabled) { setShowPhysicsCapsule(false); } } void LLFloaterPathfindingCharacters::showSelectedCharacterCapsules() { // Hide any previous capsule hideCapsule(); // Get the only selected object, or set the selected object to null if we do not have exactly // one object selected if (getNumSelectedObjects() == 1) { LLPathfindingObjectPtr selectedObjectPtr = getFirstSelectedObject(); mSelectedCharacterId = selectedObjectPtr->getUUID(); } else { mSelectedCharacterId.setNull(); } // Show any capsule if enabled showCapsule(); } void LLFloaterPathfindingCharacters::showCapsule() const { if (mSelectedCharacterId.notNull() && isShowPhysicsCapsule()) { LLPathfindingObjectPtr objectPtr = getFirstSelectedObject(); llassert(objectPtr != NULL); if (objectPtr != NULL) { const LLPathfindingCharacter *character = dynamic_cast<const LLPathfindingCharacter *>(objectPtr.get()); llassert(mSelectedCharacterId == character->getUUID()); if (LLPathingLib::getInstance() != NULL) { LLPathingLib::getInstance()->createPhysicsCapsuleRep(character->getLength(), character->getRadius(), (BOOL)character->isHorizontal(), character->getUUID()); } } gPipeline.hideObject(mSelectedCharacterId); } } void LLFloaterPathfindingCharacters::hideCapsule() const { if (mSelectedCharacterId.notNull()) { gPipeline.restoreHiddenObject(mSelectedCharacterId); } if (LLPathingLib::getInstance() != NULL) { LLPathingLib::getInstance()->cleanupPhysicsCapsuleRepResiduals(); } } bool LLFloaterPathfindingCharacters::getCapsuleRenderData(LLVector3& pPosition, LLQuaternion& rot) const { bool result = false; // If we have a selected object, find the object on the viewer object list and return its // position. Else, return false indicating that we either do not have a selected object // or we cannot find the selected object on the viewer object list if (mSelectedCharacterId.notNull()) { LLViewerObject *viewerObject = gObjectList.findObject(mSelectedCharacterId); if ( viewerObject != NULL ) { rot = viewerObject->getRotation() ; pPosition = viewerObject->getRenderPosition(); result = true; } } return result; }