490 lines
12 KiB
C++
490 lines
12 KiB
C++
/**
|
|
* @file llpathfindingpathtool.cpp
|
|
* @author William Todd Stinson
|
|
* @brief XXX
|
|
*
|
|
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2010, 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 "llagent.h"
|
|
#include "llsingleton.h"
|
|
#include "lltool.h"
|
|
#include "llviewercamera.h"
|
|
#include "llviewerregion.h"
|
|
#include "llviewerwindow.h"
|
|
#include "llpathfindingmanager.h"
|
|
#include "llpathinglib.h"
|
|
|
|
#include <boost/function.hpp>
|
|
#include <boost/signals2.hpp>
|
|
|
|
#define PATH_TOOL_NAME "PathfindingPathTool"
|
|
|
|
LLPathfindingPathTool::LLPathfindingPathTool()
|
|
: LLTool(PATH_TOOL_NAME),
|
|
LLSingleton<LLPathfindingPathTool>(),
|
|
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))
|
|
{
|
|
if (isPointAModKeys(pMask))
|
|
{
|
|
gViewerWindow->setCursor(UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD);
|
|
}
|
|
else if (isPointBModKeys(pMask))
|
|
{
|
|
gViewerWindow->setCursor(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))
|
|
{
|
|
if (isPointAModKeys(pMask))
|
|
{
|
|
if (mIsLeftMouseButtonHeld)
|
|
{
|
|
gViewerWindow->setCursor(UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD);
|
|
}
|
|
else
|
|
{
|
|
gViewerWindow->setCursor(UI_CURSOR_TOOLPATHFINDING_PATH_START);
|
|
}
|
|
}
|
|
else if (isPointBModKeys(pMask))
|
|
{
|
|
if (mIsLeftMouseButtonHeld)
|
|
{
|
|
gViewerWindow->setCursor(UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD);
|
|
}
|
|
else
|
|
{
|
|
gViewerWindow->setCursor(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
|
|
{
|
|
return mFinalPathData.mCharacterWidth;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
const LLVector3 &LLPathfindingPathTool::getFinalAStart() const
|
|
{
|
|
return mFinalPathData.mStartPointA;
|
|
}
|
|
|
|
const LLVector3 &LLPathfindingPathTool::getFinalAEnd() const
|
|
{
|
|
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;
|
|
}
|
|
|
|
const LLVector3 &LLPathfindingPathTool::getFinalBStart() const
|
|
{
|
|
return mFinalPathData.mStartPointB;
|
|
}
|
|
|
|
const LLVector3 &LLPathfindingPathTool::getFinalBEnd() const
|
|
{
|
|
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();
|
|
}
|