phoenix-firestorm/indra/newview/llpathfindingpathtool.cpp

480 lines
13 KiB
C++

/**
* @file llpathfindingpathtool.cpp
* @brief Implementation of llpathfindingpathtool
* @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 "llpathfindingpathtool.h"
#include <boost/function.hpp>
#include <boost/signals2.hpp>
#include "llagent.h"
#include "llpathfindingmanager.h"
#include "llviewercamera.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
#define PATH_TOOL_NAME "PathfindingPathTool"
LLPathfindingPathTool::LLPathfindingPathTool()
: LLTool(PATH_TOOL_NAME),
mFinalPathData(),
mTempPathData(),
mPathResult(LLPathingLib::LLPL_NO_PATH),
mCharacterType(kCharacterTypeNone),
mPathEventSignal(),
mIsLeftMouseButtonHeld(false),
mIsMiddleMouseButtonHeld(false),
mIsRightMouseButtonHeld(false)
{
setCharacterWidth(1.0f);
setCharacterType(mCharacterType);
}
LLPathfindingPathTool::~LLPathfindingPathTool()
{
}
bool LLPathfindingPathTool::handleMouseDown(S32 pX, S32 pY, MASK pMask)
{
bool returnVal = false;
if (!mIsLeftMouseButtonHeld && !mIsMiddleMouseButtonHeld && !mIsRightMouseButtonHeld)
{
if (isAnyPathToolModKeys(pMask))
{
gViewerWindow->setCursor(isPointAModKeys(pMask)
? UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD
: UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD);
computeFinalPoints(pX, pY, pMask);
mIsLeftMouseButtonHeld = true;
setMouseCapture(true);
returnVal = true;
}
else if (!isCameraModKeys(pMask))
{
gViewerWindow->setCursor(UI_CURSOR_TOOLNO);
mIsLeftMouseButtonHeld = true;
setMouseCapture(true);
returnVal = true;
}
}
mIsLeftMouseButtonHeld = true;
return returnVal;
}
bool LLPathfindingPathTool::handleMouseUp(S32 pX, S32 pY, MASK pMask)
{
bool returnVal = false;
if (mIsLeftMouseButtonHeld && !mIsMiddleMouseButtonHeld && !mIsRightMouseButtonHeld)
{
computeFinalPoints(pX, pY, pMask);
setMouseCapture(false);
returnVal = true;
}
mIsLeftMouseButtonHeld = false;
return returnVal;
}
bool LLPathfindingPathTool::handleMiddleMouseDown(S32 pX, S32 pY, MASK pMask)
{
setMouseCapture(true);
mIsMiddleMouseButtonHeld = true;
gViewerWindow->setCursor(UI_CURSOR_TOOLNO);
return true;
}
bool LLPathfindingPathTool::handleMiddleMouseUp(S32 pX, S32 pY, MASK pMask)
{
if (!mIsLeftMouseButtonHeld && mIsMiddleMouseButtonHeld && !mIsRightMouseButtonHeld)
{
setMouseCapture(false);
}
mIsMiddleMouseButtonHeld = false;
return true;
}
bool LLPathfindingPathTool::handleRightMouseDown(S32 pX, S32 pY, MASK pMask)
{
setMouseCapture(true);
mIsRightMouseButtonHeld = true;
gViewerWindow->setCursor(UI_CURSOR_TOOLNO);
return true;
}
bool LLPathfindingPathTool::handleRightMouseUp(S32 pX, S32 pY, MASK pMask)
{
if (!mIsLeftMouseButtonHeld && !mIsMiddleMouseButtonHeld && mIsRightMouseButtonHeld)
{
setMouseCapture(false);
}
mIsRightMouseButtonHeld = false;
return true;
}
bool LLPathfindingPathTool::handleDoubleClick(S32 pX, S32 pY, MASK pMask)
{
return true;
}
bool LLPathfindingPathTool::handleHover(S32 pX, S32 pY, MASK pMask)
{
bool returnVal = false;
if (!mIsLeftMouseButtonHeld && !mIsMiddleMouseButtonHeld && !mIsRightMouseButtonHeld && !isAnyPathToolModKeys(pMask))
{
gViewerWindow->setCursor(UI_CURSOR_TOOLPATHFINDING);
}
if (!mIsMiddleMouseButtonHeld && !mIsRightMouseButtonHeld && isAnyPathToolModKeys(pMask))
{
gViewerWindow->setCursor(isPointAModKeys(pMask)
? (mIsLeftMouseButtonHeld ? UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD : UI_CURSOR_TOOLPATHFINDING_PATH_START)
: (mIsLeftMouseButtonHeld ? UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD : UI_CURSOR_TOOLPATHFINDING_PATH_END));
computeTempPoints(pX, pY, pMask);
returnVal = true;
}
else
{
clearTemp();
computeFinalPath();
}
return returnVal;
}
bool LLPathfindingPathTool::handleKey(KEY pKey, MASK pMask)
{
// Eat the escape key or else the camera tool will pick up and reset to default view. This,
// in turn, will cause some other methods to get called. And one of those methods will reset
// the current toolset back to the basic toolset. This means that the pathfinding path toolset
// will no longer be active, but typically with pathfinding path elements on screen.
return (pKey == KEY_ESCAPE);
}
LLPathfindingPathTool::EPathStatus LLPathfindingPathTool::getPathStatus() const
{
EPathStatus status = kPathStatusUnknown;
if (LLPathingLib::getInstance() == NULL)
{
status = kPathStatusNotImplemented;
}
else if ((gAgent.getRegion() != NULL) && !gAgent.getRegion()->capabilitiesReceived())
{
status = kPathStatusUnknown;
}
else if (!LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion())
{
status = kPathStatusNotEnabled;
}
else if (!hasFinalA() && !hasFinalB())
{
status = kPathStatusChooseStartAndEndPoints;
}
else if (!hasFinalA())
{
status = kPathStatusChooseStartPoint;
}
else if (!hasFinalB())
{
status = kPathStatusChooseEndPoint;
}
else if (mPathResult == LLPathingLib::LLPL_PATH_GENERATED_OK)
{
status = kPathStatusHasValidPath;
}
else if (mPathResult == LLPathingLib::LLPL_NO_PATH)
{
status = kPathStatusHasInvalidPath;
}
else
{
status = kPathStatusError;
}
return status;
}
F32 LLPathfindingPathTool::getCharacterWidth() const
{
#ifdef HAVOK_TPV
return mFinalPathData.mCharacterWidth;
#else
return (F32)mFinalPathData.mCharacterWidth;
#endif
}
void LLPathfindingPathTool::setCharacterWidth(F32 pCharacterWidth)
{
mFinalPathData.mCharacterWidth = pCharacterWidth;
mTempPathData.mCharacterWidth = pCharacterWidth;
computeFinalPath();
}
LLPathfindingPathTool::ECharacterType LLPathfindingPathTool::getCharacterType() const
{
return mCharacterType;
}
void LLPathfindingPathTool::setCharacterType(ECharacterType pCharacterType)
{
mCharacterType = pCharacterType;
LLPathingLib::LLPLCharacterType characterType;
switch (pCharacterType)
{
case kCharacterTypeNone :
characterType = LLPathingLib::LLPL_CHARACTER_TYPE_NONE;
break;
case kCharacterTypeA :
characterType = LLPathingLib::LLPL_CHARACTER_TYPE_A;
break;
case kCharacterTypeB :
characterType = LLPathingLib::LLPL_CHARACTER_TYPE_B;
break;
case kCharacterTypeC :
characterType = LLPathingLib::LLPL_CHARACTER_TYPE_C;
break;
case kCharacterTypeD :
characterType = LLPathingLib::LLPL_CHARACTER_TYPE_D;
break;
default :
characterType = LLPathingLib::LLPL_CHARACTER_TYPE_NONE;
llassert(0);
break;
}
mFinalPathData.mCharacterType = characterType;
mTempPathData.mCharacterType = characterType;
computeFinalPath();
}
bool LLPathfindingPathTool::isRenderPath() const
{
return (hasFinalA() || hasFinalB() || hasTempA() || hasTempB());
}
void LLPathfindingPathTool::clearPath()
{
clearFinal();
clearTemp();
computeFinalPath();
}
LLPathfindingPathTool::path_event_slot_t LLPathfindingPathTool::registerPathEventListener(path_event_callback_t pPathEventCallback)
{
return mPathEventSignal.connect(pPathEventCallback);
}
bool LLPathfindingPathTool::isAnyPathToolModKeys(MASK pMask) const
{
return ((pMask & (MASK_CONTROL|MASK_SHIFT)) != 0);
}
bool LLPathfindingPathTool::isPointAModKeys(MASK pMask) const
{
return ((pMask & MASK_CONTROL) != 0);
}
bool LLPathfindingPathTool::isPointBModKeys(MASK pMask) const
{
return ((pMask & MASK_SHIFT) != 0);
}
bool LLPathfindingPathTool::isCameraModKeys(MASK pMask) const
{
return ((pMask & MASK_ALT) != 0);
}
void LLPathfindingPathTool::getRayPoints(S32 pX, S32 pY, LLVector3 &pRayStart, LLVector3 &pRayEnd) const
{
LLVector3 dv = gViewerWindow->mouseDirectionGlobal(pX, pY);
LLVector3 mousePos = LLViewerCamera::getInstance()->getOrigin();
pRayStart = mousePos;
pRayEnd = mousePos + dv * 150;
}
void LLPathfindingPathTool::computeFinalPoints(S32 pX, S32 pY, MASK pMask)
{
LLVector3 rayStart, rayEnd;
getRayPoints(pX, pY, rayStart, rayEnd);
if (isPointAModKeys(pMask))
{
setFinalA(rayStart, rayEnd);
}
else if (isPointBModKeys(pMask))
{
setFinalB(rayStart, rayEnd);
}
computeFinalPath();
}
void LLPathfindingPathTool::computeTempPoints(S32 pX, S32 pY, MASK pMask)
{
LLVector3 rayStart, rayEnd;
getRayPoints(pX, pY, rayStart, rayEnd);
if (isPointAModKeys(pMask))
{
setTempA(rayStart, rayEnd);
if (hasFinalB())
{
setTempB(getFinalBStart(), getFinalBEnd());
}
}
else if (isPointBModKeys(pMask))
{
if (hasFinalA())
{
setTempA(getFinalAStart(), getFinalAEnd());
}
setTempB(rayStart, rayEnd);
}
computeTempPath();
}
void LLPathfindingPathTool::setFinalA(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint)
{
mFinalPathData.mStartPointA = pStartPoint;
mFinalPathData.mEndPointA = pEndPoint;
mFinalPathData.mHasPointA = true;
}
bool LLPathfindingPathTool::hasFinalA() const
{
return mFinalPathData.mHasPointA;
}
// <FS:ND> Cannot return reference here, due to stub returning a temporary
//const LLVector3 &LLPathfindingPathTool::getFinalAStart() const
LLVector3 LLPathfindingPathTool::getFinalAStart() const
//</FS:ND>
{
return mFinalPathData.mStartPointA;
}
// <FS:ND> Cannot return reference here, due to stub returning a temporary
//const LLVector3 &LLPathfindingPathTool::getFinalAEnd() const
LLVector3 LLPathfindingPathTool::getFinalAEnd() const
//</FS:ND>
{
return mFinalPathData.mEndPointA;
}
void LLPathfindingPathTool::setTempA(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint)
{
mTempPathData.mStartPointA = pStartPoint;
mTempPathData.mEndPointA = pEndPoint;
mTempPathData.mHasPointA = true;
}
bool LLPathfindingPathTool::hasTempA() const
{
return mTempPathData.mHasPointA;
}
void LLPathfindingPathTool::setFinalB(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint)
{
mFinalPathData.mStartPointB = pStartPoint;
mFinalPathData.mEndPointB = pEndPoint;
mFinalPathData.mHasPointB = true;
}
bool LLPathfindingPathTool::hasFinalB() const
{
return mFinalPathData.mHasPointB;
}
// <FS:ND> Cannot return reference here, due to stub returning a temporary
//const LLVector3 &LLPathfindingPathTool::getFinalBStart() const
LLVector3 LLPathfindingPathTool::getFinalBStart() const
// </FS:ND>
{
return mFinalPathData.mStartPointB;
}
// <FS:ND> Cannot return reference here, due to stub returning a temporary
//const LLVector3 &LLPathfindingPathTool::getFinalBEnd() const
LLVector3 LLPathfindingPathTool::getFinalBEnd() const
// </FS:ND>
{
return mFinalPathData.mEndPointB;
}
void LLPathfindingPathTool::setTempB(const LLVector3 &pStartPoint, const LLVector3 &pEndPoint)
{
mTempPathData.mStartPointB = pStartPoint;
mTempPathData.mEndPointB = pEndPoint;
mTempPathData.mHasPointB = true;
}
bool LLPathfindingPathTool::hasTempB() const
{
return mTempPathData.mHasPointB;
}
void LLPathfindingPathTool::clearFinal()
{
mFinalPathData.mHasPointA = false;
mFinalPathData.mHasPointB = false;
}
void LLPathfindingPathTool::clearTemp()
{
mTempPathData.mHasPointA = false;
mTempPathData.mHasPointB = false;
}
void LLPathfindingPathTool::computeFinalPath()
{
mPathResult = LLPathingLib::LLPL_NO_PATH;
if (LLPathingLib::getInstance() != NULL)
{
mPathResult = LLPathingLib::getInstance()->generatePath(mFinalPathData);
}
mPathEventSignal();
}
void LLPathfindingPathTool::computeTempPath()
{
mPathResult = LLPathingLib::LLPL_NO_PATH;
if (LLPathingLib::getInstance() != NULL)
{
mPathResult = LLPathingLib::getInstance()->generatePath(mTempPathData);
}
mPathEventSignal();
}