Fix for path-506. Removed usevbo flag from stitchnavmesh api
parent
4888f7d349
commit
cc49d9d1a7
|
|
@ -1,465 +1,465 @@
|
|||
/**
|
||||
* @file llpathfindingnavmeshzone.cpp
|
||||
* @author William Todd Stinson
|
||||
* @brief A class for representing the zone of navmeshes containing and possible surrounding the current region.
|
||||
*
|
||||
* $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 "llsd.h"
|
||||
#include "lluuid.h"
|
||||
#include "llagent.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llpathfindingnavmesh.h"
|
||||
#include "llpathfindingnavmeshzone.h"
|
||||
#include "llpathfindingmanager.h"
|
||||
#include "llviewercontrol.h"
|
||||
|
||||
#include "LLPathingLib.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#define CENTER_REGION 99
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// LLPathfindingNavMeshZone
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
LLPathfindingNavMeshZone::LLPathfindingNavMeshZone()
|
||||
: mNavMeshLocationPtrs(),
|
||||
mNavMeshZoneRequestStatus(kNavMeshZoneRequestUnknown),
|
||||
mNavMeshZoneSignal()
|
||||
{
|
||||
}
|
||||
|
||||
LLPathfindingNavMeshZone::~LLPathfindingNavMeshZone()
|
||||
{
|
||||
}
|
||||
|
||||
LLPathfindingNavMeshZone::navmesh_zone_slot_t LLPathfindingNavMeshZone::registerNavMeshZoneListener(navmesh_zone_callback_t pNavMeshZoneCallback)
|
||||
{
|
||||
return mNavMeshZoneSignal.connect(pNavMeshZoneCallback);
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::initialize()
|
||||
{
|
||||
mNavMeshLocationPtrs.clear();
|
||||
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
LLViewerRegion *currentRegion = gAgent.getRegion();
|
||||
if (currentRegion != NULL)
|
||||
{
|
||||
llinfos << "STINSON DEBUG: currentRegion: '" << currentRegion->getName() << "' (" << currentRegion->getRegionID().asString() << ")" << llendl;
|
||||
std::vector<S32> availableRegions;
|
||||
currentRegion->getNeighboringRegionsStatus( availableRegions );
|
||||
std::vector<LLViewerRegion*> neighborRegionsPtrs;
|
||||
currentRegion->getNeighboringRegions( neighborRegionsPtrs );
|
||||
for (std::vector<S32>::const_iterator statusIter = availableRegions.begin();
|
||||
statusIter != availableRegions.end(); ++statusIter)
|
||||
{
|
||||
LLViewerRegion *region = neighborRegionsPtrs[statusIter - availableRegions.begin()];
|
||||
llinfos << "STINSON DEBUG: region #" << *statusIter << ": '" << region->getName() << "' (" << region->getRegionID().asString() << ")" << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
NavMeshLocationPtr centerNavMeshPtr(new NavMeshLocation(CENTER_REGION, boost::bind(&LLPathfindingNavMeshZone::handleNavMeshLocation, this)));
|
||||
mNavMeshLocationPtrs.push_back(centerNavMeshPtr);
|
||||
|
||||
U32 neighborRegionDir = gSavedSettings.getU32("RetrieveNeighboringRegion");
|
||||
if (neighborRegionDir != CENTER_REGION)
|
||||
{
|
||||
NavMeshLocationPtr neighborNavMeshPtr(new NavMeshLocation(neighborRegionDir, boost::bind(&LLPathfindingNavMeshZone::handleNavMeshLocation, this)));
|
||||
mNavMeshLocationPtrs.push_back(neighborNavMeshPtr);
|
||||
}
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::enable()
|
||||
{
|
||||
for (NavMeshLocationPtrs::iterator navMeshLocationPtrIter = mNavMeshLocationPtrs.begin();
|
||||
navMeshLocationPtrIter != mNavMeshLocationPtrs.end(); ++navMeshLocationPtrIter)
|
||||
{
|
||||
NavMeshLocationPtr navMeshLocationPtr = *navMeshLocationPtrIter;
|
||||
navMeshLocationPtr->enable();
|
||||
}
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::disable()
|
||||
{
|
||||
for (NavMeshLocationPtrs::iterator navMeshLocationPtrIter = mNavMeshLocationPtrs.begin();
|
||||
navMeshLocationPtrIter != mNavMeshLocationPtrs.end(); ++navMeshLocationPtrIter)
|
||||
{
|
||||
NavMeshLocationPtr navMeshLocationPtr = *navMeshLocationPtrIter;
|
||||
navMeshLocationPtr->disable();
|
||||
}
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::refresh()
|
||||
{
|
||||
llassert(LLPathingLib::getInstance() != NULL);
|
||||
if (LLPathingLib::getInstance() != NULL)
|
||||
{
|
||||
LLPathingLib::getInstance()->cleanupResidual();
|
||||
}
|
||||
|
||||
for (NavMeshLocationPtrs::iterator navMeshLocationPtrIter = mNavMeshLocationPtrs.begin();
|
||||
navMeshLocationPtrIter != mNavMeshLocationPtrs.end(); ++navMeshLocationPtrIter)
|
||||
{
|
||||
NavMeshLocationPtr navMeshLocationPtr = *navMeshLocationPtrIter;
|
||||
navMeshLocationPtr->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
LLPathfindingNavMeshZone::ENavMeshZoneStatus LLPathfindingNavMeshZone::getNavMeshZoneStatus() const
|
||||
{
|
||||
bool hasPending = false;
|
||||
bool hasBuilding = false;
|
||||
bool hasComplete = false;
|
||||
bool hasRepending = false;
|
||||
|
||||
for (NavMeshLocationPtrs::const_iterator navMeshLocationPtrIter = mNavMeshLocationPtrs.begin();
|
||||
navMeshLocationPtrIter != mNavMeshLocationPtrs.end(); ++navMeshLocationPtrIter)
|
||||
{
|
||||
const NavMeshLocationPtr navMeshLocationPtr = *navMeshLocationPtrIter;
|
||||
|
||||
switch (navMeshLocationPtr->getNavMeshStatus())
|
||||
{
|
||||
case LLPathfindingNavMeshStatus::kPending :
|
||||
hasPending = true;
|
||||
break;
|
||||
case LLPathfindingNavMeshStatus::kBuilding :
|
||||
hasBuilding = true;
|
||||
break;
|
||||
case LLPathfindingNavMeshStatus::kComplete :
|
||||
hasComplete = true;
|
||||
break;
|
||||
case LLPathfindingNavMeshStatus::kRepending :
|
||||
hasRepending = true;
|
||||
break;
|
||||
default :
|
||||
hasPending = true;
|
||||
llassert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ENavMeshZoneStatus zoneStatus = kNavMeshZoneComplete;
|
||||
if (hasRepending || (hasPending && hasBuilding))
|
||||
{
|
||||
zoneStatus = kNavMeshZonePendingAndBuilding;
|
||||
}
|
||||
else if (hasComplete)
|
||||
{
|
||||
if (hasPending)
|
||||
{
|
||||
zoneStatus = kNavMeshZoneSomePending;
|
||||
}
|
||||
else if (hasBuilding)
|
||||
{
|
||||
zoneStatus = kNavMeshZoneSomeBuilding;
|
||||
}
|
||||
else
|
||||
{
|
||||
zoneStatus = kNavMeshZoneComplete;
|
||||
}
|
||||
}
|
||||
else if (hasPending)
|
||||
{
|
||||
zoneStatus = kNavMeshZonePending;
|
||||
}
|
||||
else if (hasBuilding)
|
||||
{
|
||||
zoneStatus = kNavMeshZoneBuilding;
|
||||
}
|
||||
|
||||
return zoneStatus;
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::handleNavMeshLocation()
|
||||
{
|
||||
updateStatus();
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::updateStatus()
|
||||
{
|
||||
bool hasRequestUnknown = false;
|
||||
bool hasRequestChecking = false;
|
||||
bool hasRequestNeedsUpdate = false;
|
||||
bool hasRequestStarted = false;
|
||||
bool hasRequestCompleted = false;
|
||||
bool hasRequestNotEnabled = false;
|
||||
bool hasRequestError = false;
|
||||
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update BEGIN" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
for (NavMeshLocationPtrs::const_iterator navMeshLocationPtrIter = mNavMeshLocationPtrs.begin();
|
||||
navMeshLocationPtrIter != mNavMeshLocationPtrs.end(); ++navMeshLocationPtrIter)
|
||||
{
|
||||
const NavMeshLocationPtr navMeshLocationPtr = *navMeshLocationPtrIter;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: region #" << navMeshLocationPtr->getDirection() << ": region(" << navMeshLocationPtr->getRegionUUID().asString() << ") status:" << navMeshLocationPtr->getRequestStatus() << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
switch (navMeshLocationPtr->getRequestStatus())
|
||||
{
|
||||
case LLPathfindingNavMesh::kNavMeshRequestUnknown :
|
||||
hasRequestUnknown = true;
|
||||
break;
|
||||
case LLPathfindingNavMesh::kNavMeshRequestChecking :
|
||||
hasRequestChecking = true;
|
||||
break;
|
||||
case LLPathfindingNavMesh::kNavMeshRequestNeedsUpdate :
|
||||
hasRequestNeedsUpdate = true;
|
||||
break;
|
||||
case LLPathfindingNavMesh::kNavMeshRequestStarted :
|
||||
hasRequestStarted = true;
|
||||
break;
|
||||
case LLPathfindingNavMesh::kNavMeshRequestCompleted :
|
||||
hasRequestCompleted = true;
|
||||
break;
|
||||
case LLPathfindingNavMesh::kNavMeshRequestNotEnabled :
|
||||
hasRequestNotEnabled = true;
|
||||
break;
|
||||
case LLPathfindingNavMesh::kNavMeshRequestError :
|
||||
hasRequestError = true;
|
||||
break;
|
||||
default :
|
||||
hasRequestError = true;
|
||||
llassert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ENavMeshZoneRequestStatus zoneRequestStatus = kNavMeshZoneRequestUnknown;
|
||||
if (hasRequestNeedsUpdate)
|
||||
{
|
||||
zoneRequestStatus = kNavMeshZoneRequestNeedsUpdate;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is NEEDS UPDATE" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
}
|
||||
else if (hasRequestChecking)
|
||||
{
|
||||
zoneRequestStatus = kNavMeshZoneRequestChecking;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is CHECKING" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
}
|
||||
else if (hasRequestStarted)
|
||||
{
|
||||
zoneRequestStatus = kNavMeshZoneRequestStarted;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is STARTED" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
}
|
||||
else if (hasRequestError)
|
||||
{
|
||||
zoneRequestStatus = kNavMeshZoneRequestError;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is ERROR" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
}
|
||||
else if (hasRequestUnknown)
|
||||
{
|
||||
zoneRequestStatus = kNavMeshZoneRequestUnknown;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is UNKNOWN" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
}
|
||||
else if (hasRequestCompleted)
|
||||
{
|
||||
zoneRequestStatus = kNavMeshZoneRequestCompleted;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is COMPLETED" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
}
|
||||
else if (hasRequestNotEnabled)
|
||||
{
|
||||
zoneRequestStatus = kNavMeshZoneRequestNotEnabled;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is NOT ENABLED" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
}
|
||||
else
|
||||
{
|
||||
zoneRequestStatus = kNavMeshZoneRequestError;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is BAD ERROR" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llassert(0);
|
||||
}
|
||||
|
||||
if ((mNavMeshZoneRequestStatus != kNavMeshZoneRequestCompleted) &&
|
||||
(zoneRequestStatus == kNavMeshZoneRequestCompleted))
|
||||
{
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is stitching" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llassert(LLPathingLib::getInstance() != NULL);
|
||||
if (LLPathingLib::getInstance() != NULL)
|
||||
{
|
||||
LLPathingLib::getInstance()->stitchNavMeshes( gSavedSettings.getBOOL("EnableVBOForNavMeshVisualization") );
|
||||
}
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update stitching is done" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
}
|
||||
|
||||
mNavMeshZoneRequestStatus = zoneRequestStatus;
|
||||
mNavMeshZoneSignal(mNavMeshZoneRequestStatus);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// LLPathfindingNavMeshZone::NavMeshLocation
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
LLPathfindingNavMeshZone::NavMeshLocation::NavMeshLocation(S32 pDirection, navmesh_location_callback_t pLocationCallback)
|
||||
: mDirection(pDirection),
|
||||
mRegionUUID(),
|
||||
mHasNavMesh(false),
|
||||
mNavMeshVersion(0U),
|
||||
mNavMeshStatus(LLPathfindingNavMeshStatus::kComplete),
|
||||
mLocationCallback(pLocationCallback),
|
||||
mRequestStatus(LLPathfindingNavMesh::kNavMeshRequestUnknown),
|
||||
mNavMeshSlot()
|
||||
{
|
||||
}
|
||||
|
||||
LLPathfindingNavMeshZone::NavMeshLocation::~NavMeshLocation()
|
||||
{
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::NavMeshLocation::enable()
|
||||
{
|
||||
clear();
|
||||
|
||||
LLViewerRegion *region = getRegion();
|
||||
if (region == NULL)
|
||||
{
|
||||
mRegionUUID.setNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
mRegionUUID = region->getRegionID();
|
||||
mNavMeshSlot = LLPathfindingManager::getInstance()->registerNavMeshListenerForRegion(region, boost::bind(&LLPathfindingNavMeshZone::NavMeshLocation::handleNavMesh, this, _1, _2, _3));
|
||||
}
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::NavMeshLocation::refresh()
|
||||
{
|
||||
LLViewerRegion *region = getRegion();
|
||||
|
||||
if (region == NULL)
|
||||
{
|
||||
llassert(mRegionUUID.isNull());
|
||||
LLPathfindingNavMeshStatus newNavMeshStatus(mRegionUUID);
|
||||
LLSD::Binary nullData;
|
||||
handleNavMesh(LLPathfindingNavMesh::kNavMeshRequestNotEnabled, newNavMeshStatus, nullData);
|
||||
}
|
||||
else
|
||||
{
|
||||
llassert(mRegionUUID == region->getRegionID());
|
||||
LLPathfindingManager::getInstance()->requestGetNavMeshForRegion(region);
|
||||
}
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::NavMeshLocation::disable()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
LLPathfindingNavMesh::ENavMeshRequestStatus LLPathfindingNavMeshZone::NavMeshLocation::getRequestStatus() const
|
||||
{
|
||||
return mRequestStatus;
|
||||
}
|
||||
|
||||
LLPathfindingNavMeshStatus::ENavMeshStatus LLPathfindingNavMeshZone::NavMeshLocation::getNavMeshStatus() const
|
||||
{
|
||||
return mNavMeshStatus;
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::NavMeshLocation::handleNavMesh(LLPathfindingNavMesh::ENavMeshRequestStatus pNavMeshRequestStatus, const LLPathfindingNavMeshStatus &pNavMeshStatus, const LLSD::Binary &pNavMeshData)
|
||||
{
|
||||
llassert(mRegionUUID == pNavMeshStatus.getRegionUUID());
|
||||
|
||||
if ((pNavMeshRequestStatus == LLPathfindingNavMesh::kNavMeshRequestCompleted) &&
|
||||
(!mHasNavMesh || (mNavMeshVersion != pNavMeshStatus.getVersion())))
|
||||
{
|
||||
llassert(!pNavMeshData.empty());
|
||||
mHasNavMesh = true;
|
||||
mNavMeshVersion = pNavMeshStatus.getVersion();
|
||||
llassert(LLPathingLib::getInstance() != NULL);
|
||||
if (LLPathingLib::getInstance() != NULL)
|
||||
{
|
||||
LLPathingLib::getInstance()->extractNavMeshSrcFromLLSD(pNavMeshData, mDirection);
|
||||
}
|
||||
}
|
||||
|
||||
mRequestStatus = pNavMeshRequestStatus;
|
||||
mNavMeshStatus = pNavMeshStatus.getStatus();
|
||||
mLocationCallback();
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::NavMeshLocation::clear()
|
||||
{
|
||||
mHasNavMesh = false;
|
||||
mRequestStatus = LLPathfindingNavMesh::kNavMeshRequestUnknown;
|
||||
mNavMeshStatus = LLPathfindingNavMeshStatus::kComplete;
|
||||
if (mNavMeshSlot.connected())
|
||||
{
|
||||
mNavMeshSlot.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
LLViewerRegion *LLPathfindingNavMeshZone::NavMeshLocation::getRegion() const
|
||||
{
|
||||
LLViewerRegion *region = NULL;
|
||||
|
||||
LLViewerRegion *currentRegion = gAgent.getRegion();
|
||||
if (currentRegion != NULL)
|
||||
{
|
||||
if (mDirection == CENTER_REGION)
|
||||
{
|
||||
region = currentRegion;
|
||||
}
|
||||
else
|
||||
{
|
||||
//User wants to pull in a neighboring region
|
||||
std::vector<S32> availableRegions;
|
||||
currentRegion->getNeighboringRegionsStatus( availableRegions );
|
||||
//Is the desired region in the available list
|
||||
std::vector<S32>::iterator foundElem = std::find(availableRegions.begin(),availableRegions.end(),mDirection);
|
||||
if ( foundElem != availableRegions.end() )
|
||||
{
|
||||
std::vector<LLViewerRegion*> neighborRegionsPtrs;
|
||||
currentRegion->getNeighboringRegions( neighborRegionsPtrs );
|
||||
region = neighborRegionsPtrs[foundElem - availableRegions.begin()];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
/**
|
||||
* @file llpathfindingnavmeshzone.cpp
|
||||
* @author William Todd Stinson
|
||||
* @brief A class for representing the zone of navmeshes containing and possible surrounding the current region.
|
||||
*
|
||||
* $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 "llsd.h"
|
||||
#include "lluuid.h"
|
||||
#include "llagent.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llpathfindingnavmesh.h"
|
||||
#include "llpathfindingnavmeshzone.h"
|
||||
#include "llpathfindingmanager.h"
|
||||
#include "llviewercontrol.h"
|
||||
|
||||
#include "LLPathingLib.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#define CENTER_REGION 99
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// LLPathfindingNavMeshZone
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
LLPathfindingNavMeshZone::LLPathfindingNavMeshZone()
|
||||
: mNavMeshLocationPtrs(),
|
||||
mNavMeshZoneRequestStatus(kNavMeshZoneRequestUnknown),
|
||||
mNavMeshZoneSignal()
|
||||
{
|
||||
}
|
||||
|
||||
LLPathfindingNavMeshZone::~LLPathfindingNavMeshZone()
|
||||
{
|
||||
}
|
||||
|
||||
LLPathfindingNavMeshZone::navmesh_zone_slot_t LLPathfindingNavMeshZone::registerNavMeshZoneListener(navmesh_zone_callback_t pNavMeshZoneCallback)
|
||||
{
|
||||
return mNavMeshZoneSignal.connect(pNavMeshZoneCallback);
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::initialize()
|
||||
{
|
||||
mNavMeshLocationPtrs.clear();
|
||||
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
LLViewerRegion *currentRegion = gAgent.getRegion();
|
||||
if (currentRegion != NULL)
|
||||
{
|
||||
llinfos << "STINSON DEBUG: currentRegion: '" << currentRegion->getName() << "' (" << currentRegion->getRegionID().asString() << ")" << llendl;
|
||||
std::vector<S32> availableRegions;
|
||||
currentRegion->getNeighboringRegionsStatus( availableRegions );
|
||||
std::vector<LLViewerRegion*> neighborRegionsPtrs;
|
||||
currentRegion->getNeighboringRegions( neighborRegionsPtrs );
|
||||
for (std::vector<S32>::const_iterator statusIter = availableRegions.begin();
|
||||
statusIter != availableRegions.end(); ++statusIter)
|
||||
{
|
||||
LLViewerRegion *region = neighborRegionsPtrs[statusIter - availableRegions.begin()];
|
||||
llinfos << "STINSON DEBUG: region #" << *statusIter << ": '" << region->getName() << "' (" << region->getRegionID().asString() << ")" << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
NavMeshLocationPtr centerNavMeshPtr(new NavMeshLocation(CENTER_REGION, boost::bind(&LLPathfindingNavMeshZone::handleNavMeshLocation, this)));
|
||||
mNavMeshLocationPtrs.push_back(centerNavMeshPtr);
|
||||
|
||||
U32 neighborRegionDir = gSavedSettings.getU32("RetrieveNeighboringRegion");
|
||||
if (neighborRegionDir != CENTER_REGION)
|
||||
{
|
||||
NavMeshLocationPtr neighborNavMeshPtr(new NavMeshLocation(neighborRegionDir, boost::bind(&LLPathfindingNavMeshZone::handleNavMeshLocation, this)));
|
||||
mNavMeshLocationPtrs.push_back(neighborNavMeshPtr);
|
||||
}
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::enable()
|
||||
{
|
||||
for (NavMeshLocationPtrs::iterator navMeshLocationPtrIter = mNavMeshLocationPtrs.begin();
|
||||
navMeshLocationPtrIter != mNavMeshLocationPtrs.end(); ++navMeshLocationPtrIter)
|
||||
{
|
||||
NavMeshLocationPtr navMeshLocationPtr = *navMeshLocationPtrIter;
|
||||
navMeshLocationPtr->enable();
|
||||
}
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::disable()
|
||||
{
|
||||
for (NavMeshLocationPtrs::iterator navMeshLocationPtrIter = mNavMeshLocationPtrs.begin();
|
||||
navMeshLocationPtrIter != mNavMeshLocationPtrs.end(); ++navMeshLocationPtrIter)
|
||||
{
|
||||
NavMeshLocationPtr navMeshLocationPtr = *navMeshLocationPtrIter;
|
||||
navMeshLocationPtr->disable();
|
||||
}
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::refresh()
|
||||
{
|
||||
llassert(LLPathingLib::getInstance() != NULL);
|
||||
if (LLPathingLib::getInstance() != NULL)
|
||||
{
|
||||
LLPathingLib::getInstance()->cleanupResidual();
|
||||
}
|
||||
|
||||
for (NavMeshLocationPtrs::iterator navMeshLocationPtrIter = mNavMeshLocationPtrs.begin();
|
||||
navMeshLocationPtrIter != mNavMeshLocationPtrs.end(); ++navMeshLocationPtrIter)
|
||||
{
|
||||
NavMeshLocationPtr navMeshLocationPtr = *navMeshLocationPtrIter;
|
||||
navMeshLocationPtr->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
LLPathfindingNavMeshZone::ENavMeshZoneStatus LLPathfindingNavMeshZone::getNavMeshZoneStatus() const
|
||||
{
|
||||
bool hasPending = false;
|
||||
bool hasBuilding = false;
|
||||
bool hasComplete = false;
|
||||
bool hasRepending = false;
|
||||
|
||||
for (NavMeshLocationPtrs::const_iterator navMeshLocationPtrIter = mNavMeshLocationPtrs.begin();
|
||||
navMeshLocationPtrIter != mNavMeshLocationPtrs.end(); ++navMeshLocationPtrIter)
|
||||
{
|
||||
const NavMeshLocationPtr navMeshLocationPtr = *navMeshLocationPtrIter;
|
||||
|
||||
switch (navMeshLocationPtr->getNavMeshStatus())
|
||||
{
|
||||
case LLPathfindingNavMeshStatus::kPending :
|
||||
hasPending = true;
|
||||
break;
|
||||
case LLPathfindingNavMeshStatus::kBuilding :
|
||||
hasBuilding = true;
|
||||
break;
|
||||
case LLPathfindingNavMeshStatus::kComplete :
|
||||
hasComplete = true;
|
||||
break;
|
||||
case LLPathfindingNavMeshStatus::kRepending :
|
||||
hasRepending = true;
|
||||
break;
|
||||
default :
|
||||
hasPending = true;
|
||||
llassert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ENavMeshZoneStatus zoneStatus = kNavMeshZoneComplete;
|
||||
if (hasRepending || (hasPending && hasBuilding))
|
||||
{
|
||||
zoneStatus = kNavMeshZonePendingAndBuilding;
|
||||
}
|
||||
else if (hasComplete)
|
||||
{
|
||||
if (hasPending)
|
||||
{
|
||||
zoneStatus = kNavMeshZoneSomePending;
|
||||
}
|
||||
else if (hasBuilding)
|
||||
{
|
||||
zoneStatus = kNavMeshZoneSomeBuilding;
|
||||
}
|
||||
else
|
||||
{
|
||||
zoneStatus = kNavMeshZoneComplete;
|
||||
}
|
||||
}
|
||||
else if (hasPending)
|
||||
{
|
||||
zoneStatus = kNavMeshZonePending;
|
||||
}
|
||||
else if (hasBuilding)
|
||||
{
|
||||
zoneStatus = kNavMeshZoneBuilding;
|
||||
}
|
||||
|
||||
return zoneStatus;
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::handleNavMeshLocation()
|
||||
{
|
||||
updateStatus();
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::updateStatus()
|
||||
{
|
||||
bool hasRequestUnknown = false;
|
||||
bool hasRequestChecking = false;
|
||||
bool hasRequestNeedsUpdate = false;
|
||||
bool hasRequestStarted = false;
|
||||
bool hasRequestCompleted = false;
|
||||
bool hasRequestNotEnabled = false;
|
||||
bool hasRequestError = false;
|
||||
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update BEGIN" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
for (NavMeshLocationPtrs::const_iterator navMeshLocationPtrIter = mNavMeshLocationPtrs.begin();
|
||||
navMeshLocationPtrIter != mNavMeshLocationPtrs.end(); ++navMeshLocationPtrIter)
|
||||
{
|
||||
const NavMeshLocationPtr navMeshLocationPtr = *navMeshLocationPtrIter;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: region #" << navMeshLocationPtr->getDirection() << ": region(" << navMeshLocationPtr->getRegionUUID().asString() << ") status:" << navMeshLocationPtr->getRequestStatus() << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
switch (navMeshLocationPtr->getRequestStatus())
|
||||
{
|
||||
case LLPathfindingNavMesh::kNavMeshRequestUnknown :
|
||||
hasRequestUnknown = true;
|
||||
break;
|
||||
case LLPathfindingNavMesh::kNavMeshRequestChecking :
|
||||
hasRequestChecking = true;
|
||||
break;
|
||||
case LLPathfindingNavMesh::kNavMeshRequestNeedsUpdate :
|
||||
hasRequestNeedsUpdate = true;
|
||||
break;
|
||||
case LLPathfindingNavMesh::kNavMeshRequestStarted :
|
||||
hasRequestStarted = true;
|
||||
break;
|
||||
case LLPathfindingNavMesh::kNavMeshRequestCompleted :
|
||||
hasRequestCompleted = true;
|
||||
break;
|
||||
case LLPathfindingNavMesh::kNavMeshRequestNotEnabled :
|
||||
hasRequestNotEnabled = true;
|
||||
break;
|
||||
case LLPathfindingNavMesh::kNavMeshRequestError :
|
||||
hasRequestError = true;
|
||||
break;
|
||||
default :
|
||||
hasRequestError = true;
|
||||
llassert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ENavMeshZoneRequestStatus zoneRequestStatus = kNavMeshZoneRequestUnknown;
|
||||
if (hasRequestNeedsUpdate)
|
||||
{
|
||||
zoneRequestStatus = kNavMeshZoneRequestNeedsUpdate;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is NEEDS UPDATE" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
}
|
||||
else if (hasRequestChecking)
|
||||
{
|
||||
zoneRequestStatus = kNavMeshZoneRequestChecking;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is CHECKING" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
}
|
||||
else if (hasRequestStarted)
|
||||
{
|
||||
zoneRequestStatus = kNavMeshZoneRequestStarted;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is STARTED" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
}
|
||||
else if (hasRequestError)
|
||||
{
|
||||
zoneRequestStatus = kNavMeshZoneRequestError;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is ERROR" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
}
|
||||
else if (hasRequestUnknown)
|
||||
{
|
||||
zoneRequestStatus = kNavMeshZoneRequestUnknown;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is UNKNOWN" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
}
|
||||
else if (hasRequestCompleted)
|
||||
{
|
||||
zoneRequestStatus = kNavMeshZoneRequestCompleted;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is COMPLETED" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
}
|
||||
else if (hasRequestNotEnabled)
|
||||
{
|
||||
zoneRequestStatus = kNavMeshZoneRequestNotEnabled;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is NOT ENABLED" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
}
|
||||
else
|
||||
{
|
||||
zoneRequestStatus = kNavMeshZoneRequestError;
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is BAD ERROR" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llassert(0);
|
||||
}
|
||||
|
||||
if ((mNavMeshZoneRequestStatus != kNavMeshZoneRequestCompleted) &&
|
||||
(zoneRequestStatus == kNavMeshZoneRequestCompleted))
|
||||
{
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update is stitching" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llassert(LLPathingLib::getInstance() != NULL);
|
||||
if (LLPathingLib::getInstance() != NULL)
|
||||
{
|
||||
LLPathingLib::getInstance()->stitchNavMeshes();
|
||||
}
|
||||
#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
llinfos << "STINSON DEBUG: Navmesh zone update stitching is done" << llendl;
|
||||
#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
|
||||
}
|
||||
|
||||
mNavMeshZoneRequestStatus = zoneRequestStatus;
|
||||
mNavMeshZoneSignal(mNavMeshZoneRequestStatus);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// LLPathfindingNavMeshZone::NavMeshLocation
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
LLPathfindingNavMeshZone::NavMeshLocation::NavMeshLocation(S32 pDirection, navmesh_location_callback_t pLocationCallback)
|
||||
: mDirection(pDirection),
|
||||
mRegionUUID(),
|
||||
mHasNavMesh(false),
|
||||
mNavMeshVersion(0U),
|
||||
mNavMeshStatus(LLPathfindingNavMeshStatus::kComplete),
|
||||
mLocationCallback(pLocationCallback),
|
||||
mRequestStatus(LLPathfindingNavMesh::kNavMeshRequestUnknown),
|
||||
mNavMeshSlot()
|
||||
{
|
||||
}
|
||||
|
||||
LLPathfindingNavMeshZone::NavMeshLocation::~NavMeshLocation()
|
||||
{
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::NavMeshLocation::enable()
|
||||
{
|
||||
clear();
|
||||
|
||||
LLViewerRegion *region = getRegion();
|
||||
if (region == NULL)
|
||||
{
|
||||
mRegionUUID.setNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
mRegionUUID = region->getRegionID();
|
||||
mNavMeshSlot = LLPathfindingManager::getInstance()->registerNavMeshListenerForRegion(region, boost::bind(&LLPathfindingNavMeshZone::NavMeshLocation::handleNavMesh, this, _1, _2, _3));
|
||||
}
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::NavMeshLocation::refresh()
|
||||
{
|
||||
LLViewerRegion *region = getRegion();
|
||||
|
||||
if (region == NULL)
|
||||
{
|
||||
llassert(mRegionUUID.isNull());
|
||||
LLPathfindingNavMeshStatus newNavMeshStatus(mRegionUUID);
|
||||
LLSD::Binary nullData;
|
||||
handleNavMesh(LLPathfindingNavMesh::kNavMeshRequestNotEnabled, newNavMeshStatus, nullData);
|
||||
}
|
||||
else
|
||||
{
|
||||
llassert(mRegionUUID == region->getRegionID());
|
||||
LLPathfindingManager::getInstance()->requestGetNavMeshForRegion(region);
|
||||
}
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::NavMeshLocation::disable()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
LLPathfindingNavMesh::ENavMeshRequestStatus LLPathfindingNavMeshZone::NavMeshLocation::getRequestStatus() const
|
||||
{
|
||||
return mRequestStatus;
|
||||
}
|
||||
|
||||
LLPathfindingNavMeshStatus::ENavMeshStatus LLPathfindingNavMeshZone::NavMeshLocation::getNavMeshStatus() const
|
||||
{
|
||||
return mNavMeshStatus;
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::NavMeshLocation::handleNavMesh(LLPathfindingNavMesh::ENavMeshRequestStatus pNavMeshRequestStatus, const LLPathfindingNavMeshStatus &pNavMeshStatus, const LLSD::Binary &pNavMeshData)
|
||||
{
|
||||
llassert(mRegionUUID == pNavMeshStatus.getRegionUUID());
|
||||
|
||||
if ((pNavMeshRequestStatus == LLPathfindingNavMesh::kNavMeshRequestCompleted) &&
|
||||
(!mHasNavMesh || (mNavMeshVersion != pNavMeshStatus.getVersion())))
|
||||
{
|
||||
llassert(!pNavMeshData.empty());
|
||||
mHasNavMesh = true;
|
||||
mNavMeshVersion = pNavMeshStatus.getVersion();
|
||||
llassert(LLPathingLib::getInstance() != NULL);
|
||||
if (LLPathingLib::getInstance() != NULL)
|
||||
{
|
||||
LLPathingLib::getInstance()->extractNavMeshSrcFromLLSD(pNavMeshData, mDirection);
|
||||
}
|
||||
}
|
||||
|
||||
mRequestStatus = pNavMeshRequestStatus;
|
||||
mNavMeshStatus = pNavMeshStatus.getStatus();
|
||||
mLocationCallback();
|
||||
}
|
||||
|
||||
void LLPathfindingNavMeshZone::NavMeshLocation::clear()
|
||||
{
|
||||
mHasNavMesh = false;
|
||||
mRequestStatus = LLPathfindingNavMesh::kNavMeshRequestUnknown;
|
||||
mNavMeshStatus = LLPathfindingNavMeshStatus::kComplete;
|
||||
if (mNavMeshSlot.connected())
|
||||
{
|
||||
mNavMeshSlot.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
LLViewerRegion *LLPathfindingNavMeshZone::NavMeshLocation::getRegion() const
|
||||
{
|
||||
LLViewerRegion *region = NULL;
|
||||
|
||||
LLViewerRegion *currentRegion = gAgent.getRegion();
|
||||
if (currentRegion != NULL)
|
||||
{
|
||||
if (mDirection == CENTER_REGION)
|
||||
{
|
||||
region = currentRegion;
|
||||
}
|
||||
else
|
||||
{
|
||||
//User wants to pull in a neighboring region
|
||||
std::vector<S32> availableRegions;
|
||||
currentRegion->getNeighboringRegionsStatus( availableRegions );
|
||||
//Is the desired region in the available list
|
||||
std::vector<S32>::iterator foundElem = std::find(availableRegions.begin(),availableRegions.end(),mDirection);
|
||||
if ( foundElem != availableRegions.end() )
|
||||
{
|
||||
std::vector<LLViewerRegion*> neighborRegionsPtrs;
|
||||
currentRegion->getNeighboringRegions( neighborRegionsPtrs );
|
||||
region = neighborRegionsPtrs[foundElem - availableRegions.begin()];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue