mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
added navmesh tester tool
Added ground work for tester tool tester tool works but needs to fill out list of acceptable datablocks and spawnclasses navpaths now share 1 navmeshquery AIControllerData now has a vector of area costs for different polyareas General cleanup
This commit is contained in:
parent
edf4d47be0
commit
6d36e17d91
|
|
@ -535,6 +535,10 @@ AIControllerData::AIControllerData()
|
|||
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
mLinkTypes = LinkData(AllFlags);
|
||||
mFilter.setIncludeFlags(mLinkTypes.getFlags());
|
||||
mFilter.setExcludeFlags(0);
|
||||
mAreaCosts.setSize(PolyAreas::NumAreas);
|
||||
mAreaCosts.fill(1.0f);
|
||||
mNavSize = AINavigation::Regular;
|
||||
mFlocking.mChance = 90;
|
||||
mFlocking.mMin = 1.0f;
|
||||
|
|
@ -560,6 +564,8 @@ AIControllerData::AIControllerData(const AIControllerData& other, bool temp_clon
|
|||
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
mLinkTypes = other.mLinkTypes;
|
||||
mFilter = other.mFilter;
|
||||
mAreaCosts = other.mAreaCosts;
|
||||
mNavSize = other.mNavSize;
|
||||
mFlocking.mChance = other.mFlocking.mChance;
|
||||
mFlocking.mMin = other.mFlocking.mMin;
|
||||
|
|
@ -629,6 +635,8 @@ void AIControllerData::initPersistFields()
|
|||
addFieldV("FlockSideStep", TypeRangedF32, Offset(mFlocking.mSideStep, AIControllerData), &CommonValidators::PositiveFloat,
|
||||
"@brief Distance from destination before we stop moving out of the way.");
|
||||
|
||||
addField("areaCosts", TypeF32Vector, Offset(mAreaCosts, AIControllerData),
|
||||
"Vector of costs for each PolyArea.");
|
||||
addField("allowWalk", TypeBool, Offset(mLinkTypes.walk, AIControllerData),
|
||||
"Allow the character to walk on dry land.");
|
||||
addField("allowJump", TypeBool, Offset(mLinkTypes.jump, AIControllerData),
|
||||
|
|
@ -662,6 +670,10 @@ void AIControllerData::packData(BitStream* stream)
|
|||
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
//enums
|
||||
stream->write(mAreaCosts.size());
|
||||
for (U32 i = 0; i < mAreaCosts.size(); i++) {
|
||||
stream->write(mAreaCosts[i]);
|
||||
}
|
||||
stream->write(mLinkTypes.getFlags());
|
||||
stream->write((U32)mNavSize);
|
||||
// end enums
|
||||
|
|
@ -684,10 +696,23 @@ void AIControllerData::unpackData(BitStream* stream)
|
|||
stream->read(&mFollowTolerance);
|
||||
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
U32 num;
|
||||
stream->read(&num);
|
||||
mAreaCosts.setSize(num);
|
||||
for (U32 i = 0; i < num; i++)
|
||||
{
|
||||
stream->read(&mAreaCosts[i]);
|
||||
}
|
||||
//enums
|
||||
U16 linkFlags;
|
||||
stream->read(&linkFlags);
|
||||
mLinkTypes = LinkData(linkFlags);
|
||||
mFilter.setIncludeFlags(mLinkTypes.getFlags());
|
||||
mFilter.setExcludeFlags(mLinkTypes.getExcludeFlags());
|
||||
for (U32 i = 0; i < PolyAreas::NumAreas; i++)
|
||||
{
|
||||
mFilter.setAreaCost((PolyAreas)i, mAreaCosts[i]);
|
||||
}
|
||||
U32 navSize;
|
||||
stream->read(&navSize);
|
||||
mNavSize = (AINavigation::NavSize)(navSize);
|
||||
|
|
|
|||
|
|
@ -168,6 +168,8 @@ public:
|
|||
|
||||
/// Types of link we can use.
|
||||
LinkData mLinkTypes;
|
||||
dtQueryFilter mFilter;
|
||||
Vector<F32> mAreaCosts;
|
||||
AINavigation::NavSize mNavSize;
|
||||
#endif
|
||||
Delegate<void(AIController* obj, Point3F location, Move* movePtr)> resolveYawPtr;
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ bool AINavigation::setPathDestination(const Point3F& pos, bool replace)
|
|||
path->mAlwaysRender = true;
|
||||
path->mLinkTypes = getCtrl()->mControllerData->mLinkTypes;
|
||||
path->mXray = true;
|
||||
path->mFilter = getCtrl()->mControllerData->mFilter;
|
||||
// Paths plan automatically upon being registered.
|
||||
if (!path->registerObject())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -114,6 +114,10 @@ AIPlayer::AIPlayer()
|
|||
mJump = None;
|
||||
mNavSize = Regular;
|
||||
mLinkTypes = LinkData(AllFlags);
|
||||
mFilter.setIncludeFlags(mLinkTypes.getFlags());
|
||||
mFilter.setExcludeFlags(0);
|
||||
mAreaCosts.setSize(PolyAreas::NumAreas);
|
||||
mAreaCosts.fill(1.0f);
|
||||
#endif
|
||||
|
||||
mIsAiControlled = true;
|
||||
|
|
@ -163,7 +167,8 @@ void AIPlayer::initPersistFields()
|
|||
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
addGroup("Pathfinding");
|
||||
|
||||
addField("areaCosts", TypeF32Vector, Offset(mAreaCosts, AIPlayer),
|
||||
"Vector of costs for each PolyArea.");
|
||||
addField("allowWalk", TypeBool, Offset(mLinkTypes.walk, AIPlayer),
|
||||
"Allow the character to walk on dry land.");
|
||||
addField("allowJump", TypeBool, Offset(mLinkTypes.jump, AIPlayer),
|
||||
|
|
@ -785,6 +790,7 @@ void AIPlayer::moveToNode(S32 node)
|
|||
|
||||
bool AIPlayer::setPathDestination(const Point3F &pos)
|
||||
{
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
// Pathfinding only happens on the server.
|
||||
if(!isServerObject())
|
||||
return false;
|
||||
|
|
@ -799,6 +805,13 @@ bool AIPlayer::setPathDestination(const Point3F &pos)
|
|||
return false;
|
||||
}
|
||||
|
||||
mFilter.setIncludeFlags(mLinkTypes.getFlags());
|
||||
mFilter.setExcludeFlags(mLinkTypes.getExcludeFlags());
|
||||
for (U32 i = 0; i < PolyAreas::NumAreas; i++)
|
||||
{
|
||||
mFilter.setAreaCost((PolyAreas)i, mAreaCosts[i]);
|
||||
}
|
||||
|
||||
// Create a new path.
|
||||
NavPath *path = new NavPath();
|
||||
|
||||
|
|
@ -808,6 +821,7 @@ bool AIPlayer::setPathDestination(const Point3F &pos)
|
|||
path->mFromSet = path->mToSet = true;
|
||||
path->mAlwaysRender = true;
|
||||
path->mLinkTypes = mLinkTypes;
|
||||
path->mFilter = mFilter;
|
||||
path->mXray = true;
|
||||
// Paths plan automatically upon being registered.
|
||||
if(!path->registerObject())
|
||||
|
|
@ -839,6 +853,9 @@ bool AIPlayer::setPathDestination(const Point3F &pos)
|
|||
path->deleteObject();
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
setMoveDestination(pos, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
DefineEngineMethod(AIPlayer, setPathDestination, bool, (Point3F goal),,
|
||||
|
|
|
|||
|
|
@ -59,8 +59,6 @@ GuiNavEditorCtrl::GuiNavEditorCtrl()
|
|||
mIsDirty = false;
|
||||
mStartDragMousePoint = InvalidMousePoint;
|
||||
mMesh = NULL;
|
||||
mPlayer = mCurPlayer = NULL;
|
||||
mSpawnClass = mSpawnDatablock = "";
|
||||
}
|
||||
|
||||
GuiNavEditorCtrl::~GuiNavEditorCtrl()
|
||||
|
|
@ -97,11 +95,6 @@ void GuiNavEditorCtrl::initPersistFields()
|
|||
docsURL;
|
||||
addField("isDirty", TypeBool, Offset(mIsDirty, GuiNavEditorCtrl));
|
||||
|
||||
addField("spawnClass", TypeRealString, Offset(mSpawnClass, GuiNavEditorCtrl),
|
||||
"Class of object to spawn in test mode.");
|
||||
addField("spawnDatablock", TypeRealString, Offset(mSpawnDatablock, GuiNavEditorCtrl),
|
||||
"Datablock to give new objects in test mode.");
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
|
|
@ -140,79 +133,6 @@ DefineEngineMethod(GuiNavEditorCtrl, getMesh, S32, (),,
|
|||
return object->getMeshId();
|
||||
}
|
||||
|
||||
S32 GuiNavEditorCtrl::getPlayerId()
|
||||
{
|
||||
return mPlayer.isNull() ? 0 : mPlayer->getId();
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiNavEditorCtrl, getPlayer, S32, (),,
|
||||
"@brief Select a NavMesh object.")
|
||||
{
|
||||
return object->getPlayerId();
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::deselect()
|
||||
{
|
||||
if(!mMesh.isNull())
|
||||
mMesh->setSelected(false);
|
||||
mMesh = NULL;
|
||||
mPlayer = mCurPlayer = NULL;
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiNavEditorCtrl, deselect, void, (),,
|
||||
"@brief Deselect whatever is currently selected in the editor.")
|
||||
{
|
||||
object->deselect();
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::spawnPlayer(const Point3F &pos)
|
||||
{
|
||||
SceneObject *obj = (SceneObject*)Sim::spawnObject(mSpawnClass, mSpawnDatablock);
|
||||
if(obj)
|
||||
{
|
||||
MatrixF mat(true);
|
||||
mat.setPosition(pos);
|
||||
obj->setTransform(mat);
|
||||
SimObject* cleanup = Sim::findObject("MissionCleanup");
|
||||
if(cleanup)
|
||||
{
|
||||
SimGroup* missionCleanup = dynamic_cast<SimGroup*>(cleanup);
|
||||
missionCleanup->addObject(obj);
|
||||
}
|
||||
mPlayer = obj;
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
AIPlayer* asAIPlayer = dynamic_cast<AIPlayer*>(obj);
|
||||
if (asAIPlayer) //try direct
|
||||
{
|
||||
Con::executef(this, "onPlayerSelected", Con::getIntArg(asAIPlayer->mLinkTypes.getFlags()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ShapeBase* sbo = dynamic_cast<ShapeBase*>(obj);
|
||||
if (sbo->getAIController())
|
||||
{
|
||||
if (sbo->getAIController()->mControllerData)
|
||||
Con::executef(this, "onPlayerSelected", Con::getIntArg(sbo->getAIController()->mControllerData->mLinkTypes.getFlags()));
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
Con::executef(this, "onPlayerSelected");
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
DefineEngineMethod(GuiNavEditorCtrl, spawnPlayer, void, (),,
|
||||
"@brief Spawn an AIPlayer at the centre of the screen.")
|
||||
{
|
||||
Point3F c;
|
||||
if(object->get3DCentre(c))
|
||||
object->spawnPlayer(c);
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::get3DCursor(GuiCursor *&cursor,
|
||||
bool &visible,
|
||||
const Gui3DMouseEvent &event_)
|
||||
|
|
@ -277,89 +197,6 @@ void GuiNavEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event)
|
|||
mouseLock();
|
||||
|
||||
return;
|
||||
|
||||
// Construct a LineSegment from the camera position to 1000 meters away in
|
||||
// the direction clicked.
|
||||
// If that segment hits the terrain, truncate the ray to only be that length.
|
||||
|
||||
Point3F startPnt = event.pos;
|
||||
Point3F endPnt = event.pos + event.vec * 1000.0f;
|
||||
|
||||
RayInfo ri;
|
||||
|
||||
U8 keys = Input::getModifierKeys();
|
||||
bool shift = keys & SI_LSHIFT;
|
||||
bool ctrl = keys & SI_LCTRL;
|
||||
|
||||
if(mMode == mTestMode)
|
||||
{
|
||||
// Spawn new character
|
||||
if(ctrl)
|
||||
{
|
||||
if(gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
||||
spawnPlayer(ri.point);
|
||||
}
|
||||
// Deselect character
|
||||
else if(shift)
|
||||
{
|
||||
mPlayer = NULL;
|
||||
Con::executef(this, "onPlayerDeselected");
|
||||
}
|
||||
// Select/move character
|
||||
else
|
||||
{
|
||||
if(gServerContainer.castRay(startPnt, endPnt, PlayerObjectType | VehicleObjectType, &ri))
|
||||
{
|
||||
if(ri.object)
|
||||
{
|
||||
mPlayer = ri.object;
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
AIPlayer* asAIPlayer = dynamic_cast<AIPlayer*>(mPlayer.getPointer());
|
||||
if (asAIPlayer) //try direct
|
||||
{
|
||||
Con::executef(this, "onPlayerSelected", Con::getIntArg(asAIPlayer->mLinkTypes.getFlags()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ShapeBase* sbo = dynamic_cast<ShapeBase*>(mPlayer.getPointer());
|
||||
if (sbo->getAIController())
|
||||
{
|
||||
if (sbo->getAIController()->mControllerData)
|
||||
Con::executef(this, "onPlayerSelected", Con::getIntArg(sbo->getAIController()->mControllerData->mLinkTypes.getFlags()));
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
Con::executef(this, "onPlayerSelected");
|
||||
}
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (!mPlayer.isNull() && gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
||||
{
|
||||
AIPlayer* asAIPlayer = dynamic_cast<AIPlayer*>(mPlayer.getPointer());
|
||||
if (asAIPlayer) //try direct
|
||||
{
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
asAIPlayer->setPathDestination(ri.point);
|
||||
#else
|
||||
asAIPlayer->setMoveDestination(ri.point,false);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ShapeBase* sbo = dynamic_cast<ShapeBase*>(mPlayer.getPointer());
|
||||
if (sbo->getAIController())
|
||||
{
|
||||
if (sbo->getAIController()->mControllerData)
|
||||
sbo->getAIController()->getNav()->setPathDestination(ri.point, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::on3DMouseUp(const Gui3DMouseEvent & event)
|
||||
|
|
@ -385,22 +222,6 @@ void GuiNavEditorCtrl::on3DMouseMove(const Gui3DMouseEvent & event)
|
|||
mTool->on3DMouseMove(event);
|
||||
|
||||
return;
|
||||
|
||||
//if(mSelRiver != NULL && mSelNode != -1)
|
||||
//mGizmo->on3DMouseMove(event);
|
||||
|
||||
Point3F startPnt = event.pos;
|
||||
Point3F endPnt = event.pos + event.vec * 1000.0f;
|
||||
|
||||
RayInfo ri;
|
||||
|
||||
if(mMode == mTestMode)
|
||||
{
|
||||
if(gServerContainer.castRay(startPnt, endPnt, PlayerObjectType | VehicleObjectType, &ri))
|
||||
mCurPlayer = ri.object;
|
||||
else
|
||||
mCurPlayer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::on3DMouseDragged(const Gui3DMouseEvent & event)
|
||||
|
|
@ -443,22 +264,6 @@ void GuiNavEditorCtrl::onRender(Point2I offset, const RectI &updateRect)
|
|||
return;
|
||||
}
|
||||
|
||||
static void renderBoxOutline(const Box3F &box, const ColorI &col)
|
||||
{
|
||||
if(box != Box3F::Invalid)
|
||||
{
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setCullMode(GFXCullNone);
|
||||
desc.setFillModeSolid();
|
||||
desc.setZReadWrite(true, false);
|
||||
desc.setBlend(true);
|
||||
GFX->getDrawUtil()->drawCube(desc, box, ColorI(col, 20));
|
||||
desc.setFillModeWireframe();
|
||||
desc.setBlend(false);
|
||||
GFX->getDrawUtil()->drawCube(desc, box, ColorI(col, 255));
|
||||
}
|
||||
}
|
||||
|
||||
void GuiNavEditorCtrl::renderScene(const RectI & updateRect)
|
||||
{
|
||||
GFX->setStateBlock(mZDisableSB);
|
||||
|
|
@ -479,14 +284,6 @@ void GuiNavEditorCtrl::renderScene(const RectI & updateRect)
|
|||
if (mTool)
|
||||
mTool->onRender3D();
|
||||
|
||||
if(mMode == mTestMode)
|
||||
{
|
||||
if(!mCurPlayer.isNull())
|
||||
renderBoxOutline(mCurPlayer->getWorldBox(), ColorI::BLUE);
|
||||
if(!mPlayer.isNull())
|
||||
renderBoxOutline(mPlayer->getWorldBox(), ColorI::GREEN);
|
||||
}
|
||||
|
||||
duDebugDrawTorque d;
|
||||
if(!mMesh.isNull())
|
||||
mMesh->renderLinks(d);
|
||||
|
|
|
|||
|
|
@ -103,17 +103,8 @@ public:
|
|||
String getMode() { return mMode; }
|
||||
|
||||
void selectMesh(NavMesh *mesh);
|
||||
void deselect();
|
||||
|
||||
S32 getMeshId();
|
||||
S32 getPlayerId();
|
||||
|
||||
String mSpawnClass;
|
||||
String mSpawnDatablock;
|
||||
|
||||
void deleteLink();
|
||||
void setLinkFlags(const LinkData &d);
|
||||
void spawnPlayer(const Point3F &pos);
|
||||
|
||||
/// @}
|
||||
void setActiveTool(NavMeshTool* tool);
|
||||
|
|
@ -148,14 +139,6 @@ protected:
|
|||
|
||||
/// @}
|
||||
|
||||
/// @name Test mode
|
||||
/// @{
|
||||
|
||||
SimObjectPtr<SceneObject> mPlayer;
|
||||
SimObjectPtr<SceneObject> mCurPlayer;
|
||||
|
||||
/// @}
|
||||
|
||||
Gui3DMouseEvent mLastMouseEvent;
|
||||
|
||||
#define InvalidMousePoint Point2I(-100,-100)
|
||||
|
|
|
|||
|
|
@ -225,10 +225,13 @@ NavMesh::NavMesh()
|
|||
|
||||
mWaterVertStart = 0;
|
||||
mWaterTriStart = 0;
|
||||
|
||||
mQuery = NULL;
|
||||
}
|
||||
|
||||
NavMesh::~NavMesh()
|
||||
{
|
||||
dtFreeNavMeshQuery(mQuery);
|
||||
dtFreeNavMesh(nm);
|
||||
nm = NULL;
|
||||
delete ctx;
|
||||
|
|
@ -677,32 +680,6 @@ bool NavMesh::build(bool background, bool saveIntermediates)
|
|||
return false;
|
||||
}
|
||||
|
||||
Box3F worldBox = getWorldBox();
|
||||
SceneContainer::CallbackInfo info;
|
||||
info.context = PLC_Navigation;
|
||||
info.boundingBox = worldBox;
|
||||
m_geo = new RecastPolyList;
|
||||
info.polyList = m_geo;
|
||||
info.key = this;
|
||||
getContainer()->findObjects(worldBox, StaticObjectType | DynamicShapeObjectType, buildCallback, &info);
|
||||
|
||||
// Parse water objects into the same list, but remember how much geometry was /not/ water.
|
||||
mWaterVertStart = m_geo->getVertCount();
|
||||
mWaterTriStart = m_geo->getTriCount();
|
||||
if (mWaterMethod != Ignore)
|
||||
{
|
||||
getContainer()->findObjects(worldBox, WaterObjectType, buildCallback, &info);
|
||||
}
|
||||
|
||||
// Check for no geometry.
|
||||
if (!m_geo->getVertCount())
|
||||
{
|
||||
m_geo->clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_geo->getChunkyMesh();
|
||||
|
||||
// Needed for the recast config and generation params.
|
||||
Box3F rc_box = DTStoRC(getWorldBox());
|
||||
S32 gw = 0, gh = 0;
|
||||
|
|
@ -803,33 +780,6 @@ void NavMesh::createNewFile()
|
|||
mFileName = StringTable->insert(fileName.c_str());
|
||||
}
|
||||
|
||||
void NavMesh::updateConfig()
|
||||
{
|
||||
//// Build rcConfig object from our console members.
|
||||
//dMemset(&cfg, 0, sizeof(cfg));
|
||||
//cfg.cs = mCellSize;
|
||||
//cfg.ch = mCellHeight;
|
||||
//Box3F box = DTStoRC(getWorldBox());
|
||||
//rcVcopy(cfg.bmin, box.minExtents);
|
||||
//rcVcopy(cfg.bmax, box.maxExtents);
|
||||
//rcCalcGridSize(cfg.bmin, cfg.bmax, cfg.cs, &cfg.width, &cfg.height);
|
||||
|
||||
//cfg.walkableHeight = mCeil(mWalkableHeight / mCellHeight);
|
||||
//cfg.walkableClimb = mCeil(mWalkableClimb / mCellHeight);
|
||||
//cfg.walkableRadius = mCeil(mWalkableRadius / mCellSize);
|
||||
//cfg.walkableSlopeAngle = mWalkableSlope;
|
||||
//cfg.borderSize = cfg.walkableRadius + 3;
|
||||
|
||||
//cfg.detailSampleDist = mDetailSampleDist;
|
||||
//cfg.detailSampleMaxError = mDetailSampleMaxError;
|
||||
//cfg.maxEdgeLen = mMaxEdgeLen;
|
||||
//cfg.maxSimplificationError = mMaxSimplificationError;
|
||||
//cfg.maxVertsPerPoly = mMaxVertsPerPoly;
|
||||
//cfg.minRegionArea = mMinRegionArea;
|
||||
//cfg.mergeRegionArea = mMergeRegionArea;
|
||||
//cfg.tileSize = mTileSize / cfg.cs;
|
||||
}
|
||||
|
||||
S32 NavMesh::getTile(const Point3F& pos)
|
||||
{
|
||||
if(mBuilding)
|
||||
|
|
@ -938,6 +888,8 @@ void NavMesh::buildNextTile()
|
|||
|
||||
if(!mDirtyTiles.empty())
|
||||
{
|
||||
dtFreeNavMeshQuery(mQuery);
|
||||
mQuery = NULL;
|
||||
// Pop a single dirty tile and process it.
|
||||
U32 i = mDirtyTiles.front();
|
||||
mDirtyTiles.pop_front();
|
||||
|
|
@ -1002,6 +954,12 @@ void NavMesh::buildNextTile()
|
|||
// Did we just build the last tile?
|
||||
if(mDirtyTiles.empty())
|
||||
{
|
||||
mQuery = dtAllocNavMeshQuery();
|
||||
if (dtStatusFailed(mQuery->init(nm, 2048)))
|
||||
{
|
||||
Con::errorf("NavMesh - Failed to create navmesh query");
|
||||
}
|
||||
|
||||
ctx->stopTimer(RC_TIMER_TOTAL);
|
||||
if(getEventManager())
|
||||
{
|
||||
|
|
@ -1012,6 +970,15 @@ void NavMesh::buildNextTile()
|
|||
mBuilding = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mQuery == NULL)
|
||||
{
|
||||
mQuery = dtAllocNavMeshQuery();
|
||||
if (dtStatusFailed(mQuery->init(nm, 2048)))
|
||||
{
|
||||
Con::errorf("NavMesh - Failed to create navmesh query");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char *NavMesh::buildTileData(const Tile &tile, U32 &dataSize)
|
||||
|
|
@ -1614,11 +1581,13 @@ void NavMesh::renderToDrawer()
|
|||
m_drawMode == DRAWMODE_NAVMESH_INVIS))
|
||||
{
|
||||
if (m_drawMode != DRAWMODE_NAVMESH_INVIS)
|
||||
duDebugDrawNavMesh(&mDbgDraw, *n->nm, 0);
|
||||
duDebugDrawNavMeshWithClosedList(&mDbgDraw, *n->nm, *n->mQuery, 0);
|
||||
if(m_drawMode == DRAWMODE_NAVMESH_BVTREE)
|
||||
duDebugDrawNavMeshBVTree(&mDbgDraw, *n->nm);
|
||||
if(m_drawMode == DRAWMODE_NAVMESH_PORTALS)
|
||||
duDebugDrawNavMeshPortals(&mDbgDraw, *n->nm);
|
||||
if (m_drawMode == DRAWMODE_NAVMESH_NODES)
|
||||
duDebugDrawNavMeshNodes(&mDbgDraw, *n->mQuery);
|
||||
}
|
||||
|
||||
mDbgDraw.depthMask(true, false);
|
||||
|
|
|
|||
|
|
@ -187,6 +187,8 @@ public:
|
|||
/// Delete the selected link.
|
||||
void deleteLink(U32 idx);
|
||||
|
||||
dtNavMeshQuery* getNavMeshQuery() { return mQuery; }
|
||||
|
||||
/// @}
|
||||
|
||||
/// Should small characters use this mesh?
|
||||
|
|
@ -381,16 +383,9 @@ private:
|
|||
|
||||
/// @}
|
||||
|
||||
/// @name Intermediate data
|
||||
/// @{
|
||||
|
||||
/// Updates our config from console members.
|
||||
void updateConfig();
|
||||
|
||||
dtNavMesh *nm;
|
||||
rcContext *ctx;
|
||||
|
||||
/// @}
|
||||
dtNavMeshQuery* mQuery;
|
||||
|
||||
/// @name Cover
|
||||
/// @{
|
||||
|
|
|
|||
302
Engine/source/navigation/navMeshTools/navMeshTestTool.cpp
Normal file
302
Engine/source/navigation/navMeshTools/navMeshTestTool.cpp
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
#include "navMeshTestTool.h"
|
||||
#include "navigation/guiNavEditorCtrl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "gfx/gfxDrawUtil.h"
|
||||
#include "scene/sceneManager.h"
|
||||
#include "math/mathUtils.h"
|
||||
#include "T3D/gameBase/gameConnection.h"
|
||||
#include "T3D/AI/AIController.h"
|
||||
|
||||
IMPLEMENT_CONOBJECT(NavMeshTestTool);
|
||||
|
||||
//// take control
|
||||
// GameConnection* conn = GameConnection::getConnectionToServer();
|
||||
// if (conn)
|
||||
// conn->setControlObject(static_cast<GameBase*>(obj));
|
||||
//}
|
||||
|
||||
static void renderBoxOutline(const Box3F& box, const ColorI& col)
|
||||
{
|
||||
if (box != Box3F::Invalid)
|
||||
{
|
||||
GFXStateBlockDesc desc;
|
||||
desc.setCullMode(GFXCullNone);
|
||||
desc.setFillModeSolid();
|
||||
desc.setZReadWrite(true, false);
|
||||
desc.setBlend(true);
|
||||
GFX->getDrawUtil()->drawCube(desc, box, ColorI(col, 20));
|
||||
desc.setFillModeWireframe();
|
||||
desc.setBlend(false);
|
||||
GFX->getDrawUtil()->drawCube(desc, box, ColorI(col, 255));
|
||||
}
|
||||
}
|
||||
|
||||
void NavMeshTestTool::spawnPlayer(const Point3F& position)
|
||||
{
|
||||
if (mSpawnClass.isEmpty() || mSpawnDatablock.isEmpty())
|
||||
{
|
||||
Con::warnf("NavMeshTestTool::spawnPlayer - spawn class/datablock not set!");
|
||||
return;
|
||||
}
|
||||
|
||||
SimObject* spawned = Sim::spawnObject(mSpawnClass, mSpawnDatablock);
|
||||
SceneObject* obj = dynamic_cast<SceneObject*>(spawned);
|
||||
|
||||
if (!obj)
|
||||
{
|
||||
Con::warnf("NavMeshTestTool::spawnPlayer - spawn failed or not a SceneObject");
|
||||
if (spawned)
|
||||
spawned->deleteObject();
|
||||
return;
|
||||
}
|
||||
|
||||
obj->setPosition(position);
|
||||
obj->registerObject();
|
||||
SimObject* cleanup = Sim::findObject("MissionCleanup");
|
||||
if (cleanup)
|
||||
{
|
||||
SimGroup* missionCleanup = dynamic_cast<SimGroup*>(cleanup);
|
||||
missionCleanup->addObject(obj);
|
||||
}
|
||||
mPlayer = obj;
|
||||
|
||||
Con::executef(this, "onPlayerSpawned", obj->getIdString());
|
||||
}
|
||||
|
||||
void NavMeshTestTool::drawAgent(duDebugDrawTorque& dd, const F32* pos, F32 r, F32 h, F32 c, const U32 col)
|
||||
{
|
||||
dd.depthMask(false);
|
||||
|
||||
// Agent dimensions.
|
||||
duDebugDrawCylinderWire(&dd, pos[0] - r, pos[1] + 0.02f, pos[2] - r, pos[0] + r, pos[1] + h, pos[2] + r, col, 2.0f);
|
||||
|
||||
duDebugDrawCircle(&dd, pos[0], pos[1] + c, pos[2], r, duRGBA(0, 0, 0, 64), 1.0f);
|
||||
|
||||
U32 colb = duRGBA(0, 0, 0, 196);
|
||||
dd.begin(DU_DRAW_LINES);
|
||||
dd.vertex(pos[0], pos[1] - c, pos[2], colb);
|
||||
dd.vertex(pos[0], pos[1] + c, pos[2], colb);
|
||||
dd.vertex(pos[0] - r / 2, pos[1] + 0.02f, pos[2], colb);
|
||||
dd.vertex(pos[0] + r / 2, pos[1] + 0.02f, pos[2], colb);
|
||||
dd.vertex(pos[0], pos[1] + 0.02f, pos[2] - r / 2, colb);
|
||||
dd.vertex(pos[0], pos[1] + 0.02f, pos[2] + r / 2, colb);
|
||||
dd.end();
|
||||
|
||||
dd.depthMask(true);
|
||||
}
|
||||
|
||||
NavMeshTestTool::NavMeshTestTool()
|
||||
{
|
||||
mSpawnClass = String::EmptyString;
|
||||
mSpawnDatablock = String::EmptyString;
|
||||
mPlayer = NULL;
|
||||
mCurPlayer = NULL;
|
||||
|
||||
mPathStart = Point3F::Max;
|
||||
mPathEnd = Point3F::Max;
|
||||
}
|
||||
|
||||
void NavMeshTestTool::onActivated(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
Con::executef(this, "onActivated");
|
||||
}
|
||||
|
||||
void NavMeshTestTool::onDeactivated()
|
||||
{
|
||||
Con::executef(this, "onDeactivated");
|
||||
}
|
||||
|
||||
void NavMeshTestTool::on3DMouseDown(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
if (mNavMesh.isNull())
|
||||
return;
|
||||
|
||||
Point3F startPnt = evt.pos;
|
||||
Point3F endPnt = evt.pos + evt.vec * 1000.0f;
|
||||
|
||||
RayInfo ri;
|
||||
bool shift = evt.modifier & SI_LSHIFT;
|
||||
bool ctrl = evt.modifier & SI_LCTRL;
|
||||
|
||||
if (ctrl)
|
||||
{
|
||||
if (gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
||||
{
|
||||
spawnPlayer(ri.point);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (shift)
|
||||
{
|
||||
mPlayer = NULL;
|
||||
Con::executef(this, "onPlayerDeselected");
|
||||
return;
|
||||
}
|
||||
|
||||
if (gServerContainer.castRay(startPnt, endPnt, PlayerObjectType | VehicleObjectType, &ri))
|
||||
{
|
||||
if (!ri.object)
|
||||
return;
|
||||
|
||||
mPlayer = ri.object;
|
||||
|
||||
#ifdef TORQUE_NAVIGATION_ENABLED
|
||||
AIPlayer* asAIPlayer = dynamic_cast<AIPlayer*>(mPlayer.getPointer());
|
||||
if (asAIPlayer)
|
||||
{
|
||||
Con::executef(this, "onPlayerSelected", Con::getIntArg(asAIPlayer->mLinkTypes.getFlags()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ShapeBase* sbo = dynamic_cast<ShapeBase*>(mPlayer.getPointer());
|
||||
if (sbo && sbo->getAIController() && sbo->getAIController()->mControllerData)
|
||||
{
|
||||
Con::executef(this, "onPlayerSelected", Con::getIntArg(sbo->getAIController()->mControllerData->mLinkTypes.getFlags()));
|
||||
}
|
||||
else
|
||||
{
|
||||
Con::executef(this, "onPlayerSelected");
|
||||
}
|
||||
}
|
||||
#else
|
||||
Con::executef(this, "onPlayerSelected");
|
||||
#endif
|
||||
}
|
||||
else if (gServerContainer.castRay(startPnt, endPnt, StaticObjectType, &ri))
|
||||
{
|
||||
if (mPlayer.isNull())
|
||||
{
|
||||
if (mPathStart != Point3F::Max && mPathEnd != Point3F::Max) // start a new path.
|
||||
{
|
||||
mPathStart = Point3F::Max;
|
||||
mPathEnd = Point3F::Max;
|
||||
}
|
||||
|
||||
if (mPathStart != Point3F::Max)
|
||||
{
|
||||
mPathEnd = ri.point;
|
||||
}
|
||||
else
|
||||
{
|
||||
mPathStart = ri.point;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AIPlayer* asAIPlayer = dynamic_cast<AIPlayer*>(mPlayer.getPointer());
|
||||
if (asAIPlayer) //try direct
|
||||
{
|
||||
asAIPlayer->setPathDestination(ri.point);
|
||||
mPathStart = mPlayer->getPosition();
|
||||
mPathEnd = ri.point;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShapeBase* sbo = dynamic_cast<ShapeBase*>(mPlayer.getPointer());
|
||||
if (sbo->getAIController())
|
||||
{
|
||||
if (sbo->getAIController()->mControllerData)
|
||||
{
|
||||
sbo->getAIController()->getNav()->setPathDestination(ri.point, true);
|
||||
mPathStart = mPlayer->getPosition();
|
||||
mPathEnd = ri.point;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void NavMeshTestTool::on3DMouseMove(const Gui3DMouseEvent& evt)
|
||||
{
|
||||
if (mNavMesh.isNull())
|
||||
return;
|
||||
|
||||
Point3F startPnt = evt.pos;
|
||||
Point3F endPnt = evt.pos + evt.vec * 1000.0f;
|
||||
|
||||
RayInfo ri;
|
||||
|
||||
if (gServerContainer.castRay(startPnt, endPnt, PlayerObjectType | VehicleObjectType, &ri))
|
||||
mCurPlayer = ri.object;
|
||||
else
|
||||
mCurPlayer = NULL;
|
||||
|
||||
}
|
||||
|
||||
void NavMeshTestTool::onRender3D()
|
||||
{
|
||||
if (mNavMesh.isNull())
|
||||
return;
|
||||
|
||||
static const U32 startCol = duRGBA(128, 25, 0, 192);
|
||||
static const U32 endCol = duRGBA(51, 102, 0, 129);
|
||||
|
||||
const F32 agentRadius = mNavMesh->mWalkableRadius;
|
||||
const F32 agentHeight = mNavMesh->mWalkableHeight;
|
||||
const F32 agentClimb = mNavMesh->mWalkableClimb;
|
||||
|
||||
duDebugDrawTorque dd;
|
||||
dd.depthMask(false);
|
||||
if (mPathStart != Point3F::Max)
|
||||
{
|
||||
drawAgent(dd, DTStoRC(mPathStart), agentRadius, agentHeight, agentClimb, startCol);
|
||||
}
|
||||
|
||||
if (mPathEnd != Point3F::Max)
|
||||
{
|
||||
drawAgent(dd, DTStoRC(mPathEnd), agentRadius, agentHeight, agentClimb, endCol);
|
||||
}
|
||||
dd.depthMask(true);
|
||||
|
||||
dd.immediateRender();
|
||||
|
||||
if (!mCurPlayer.isNull())
|
||||
renderBoxOutline(mCurPlayer->getWorldBox(), ColorI::BLUE);
|
||||
if (!mPlayer.isNull())
|
||||
renderBoxOutline(mPlayer->getWorldBox(), ColorI::GREEN);
|
||||
}
|
||||
|
||||
bool NavMeshTestTool::updateGuiInfo()
|
||||
{
|
||||
SimObject* statusbar;
|
||||
Sim::findObject("EditorGuiStatusBar", statusbar);
|
||||
|
||||
GuiTextCtrl* selectionBar;
|
||||
Sim::findObject("EWorldEditorStatusBarSelection", selectionBar);
|
||||
|
||||
String text;
|
||||
|
||||
if (statusbar)
|
||||
Con::executef(statusbar, "setInfo", text.c_str());
|
||||
|
||||
text = "";
|
||||
|
||||
if (selectionBar)
|
||||
selectionBar->setText(text);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
S32 NavMeshTestTool::getPlayerId()
|
||||
{
|
||||
return mPlayer.isNull() ? 0 : mPlayer->getId();
|
||||
}
|
||||
|
||||
DefineEngineMethod(NavMeshTestTool, getPlayer, S32, (), ,
|
||||
"@brief Return the current player id.")
|
||||
{
|
||||
return object->getPlayerId();
|
||||
}
|
||||
|
||||
DefineEngineMethod(NavMeshTestTool, setSpawnClass, void, (String className), , "")
|
||||
{
|
||||
object->setSpawnClass(className);
|
||||
}
|
||||
|
||||
DefineEngineMethod(NavMeshTestTool, setSpawnDatablock, void, (String dbName), , "")
|
||||
{
|
||||
object->setSpawnDatablock(dbName);
|
||||
}
|
||||
47
Engine/source/navigation/navMeshTools/navMeshTestTool.h
Normal file
47
Engine/source/navigation/navMeshTools/navMeshTestTool.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef _NAVMESHTESTTOOL_H_
|
||||
#define _NAVMESHTESTTOOL_H_
|
||||
|
||||
|
||||
#ifndef _NAVMESH_TOOL_H_
|
||||
#include "navigation/navMeshTool.h"
|
||||
#endif
|
||||
|
||||
class NavMeshTestTool : public NavMeshTool
|
||||
{
|
||||
typedef NavMeshTool Parent;
|
||||
protected:
|
||||
String mSpawnClass;
|
||||
String mSpawnDatablock;
|
||||
SimObjectPtr<SceneObject> mPlayer;
|
||||
SimObjectPtr<SceneObject> mCurPlayer;
|
||||
Point3F mPathStart;
|
||||
Point3F mPathEnd;
|
||||
public:
|
||||
DECLARE_CONOBJECT(NavMeshTestTool);
|
||||
|
||||
void spawnPlayer(const Point3F& position);
|
||||
|
||||
void drawAgent(duDebugDrawTorque& dd, const F32* pos, F32 r, F32 h, F32 c, const U32 col);
|
||||
|
||||
NavMeshTestTool();
|
||||
|
||||
virtual ~NavMeshTestTool() {}
|
||||
|
||||
void onActivated(const Gui3DMouseEvent& evt) override;
|
||||
void onDeactivated() override;
|
||||
|
||||
void on3DMouseDown(const Gui3DMouseEvent& evt) override;
|
||||
void on3DMouseMove(const Gui3DMouseEvent& evt) override;
|
||||
void onRender3D() override;
|
||||
|
||||
bool updateGuiInfo() override;
|
||||
|
||||
S32 getPlayerId();
|
||||
|
||||
void setSpawnClass(String className) { mSpawnClass = className; }
|
||||
void setSpawnDatablock(String dbName) { mSpawnDatablock = dbName; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // !_NAVMESHTESTTOOL_H_
|
||||
|
|
@ -69,14 +69,11 @@ NavPath::NavPath() :
|
|||
mXray = false;
|
||||
mRenderSearch = false;
|
||||
|
||||
mQuery = NULL;
|
||||
mStatus = DT_FAILURE;
|
||||
}
|
||||
|
||||
NavPath::~NavPath()
|
||||
{
|
||||
dtFreeNavMeshQuery(mQuery);
|
||||
mQuery = NULL;
|
||||
}
|
||||
|
||||
void NavPath::checkAutoUpdate()
|
||||
|
|
@ -264,9 +261,6 @@ bool NavPath::onAdd()
|
|||
|
||||
if(isServerObject())
|
||||
{
|
||||
mQuery = dtAllocNavMeshQuery();
|
||||
if(!mQuery)
|
||||
return false;
|
||||
checkAutoUpdate();
|
||||
if(!plan())
|
||||
setProcessTick(true);
|
||||
|
|
@ -293,7 +287,8 @@ bool NavPath::init()
|
|||
return false;
|
||||
|
||||
// Initialise our query.
|
||||
if(dtStatusFailed(mQuery->init(mMesh->getNavMesh(), MaxPathLen)))
|
||||
mQuery = mMesh->getNavMeshQuery();
|
||||
if(!mQuery)
|
||||
return false;
|
||||
|
||||
mPoints.clear();
|
||||
|
|
@ -372,9 +367,6 @@ void NavPath::resize()
|
|||
bool NavPath::plan()
|
||||
{
|
||||
PROFILE_SCOPE(NavPath_plan);
|
||||
// Initialise filter.
|
||||
mFilter.setIncludeFlags(mLinkTypes.getFlags());
|
||||
|
||||
// Initialise query and visit locations.
|
||||
if(!init())
|
||||
return false;
|
||||
|
|
@ -641,6 +633,7 @@ void NavPath::renderSimple(ObjectRenderInst *ri, SceneRenderState *state, BaseMa
|
|||
{
|
||||
duDebugDrawTorque dd;
|
||||
duDebugDrawNavMeshNodes(&dd, *np->mQuery);
|
||||
dd.immediateRender();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ public:
|
|||
|
||||
/// What sort of link types are we allowed to move on?
|
||||
LinkData mLinkTypes;
|
||||
|
||||
dtQueryFilter mFilter;
|
||||
/// Plan the path.
|
||||
bool plan();
|
||||
|
||||
|
|
@ -152,7 +152,6 @@ private:
|
|||
|
||||
dtNavMeshQuery *mQuery;
|
||||
dtStatus mStatus;
|
||||
dtQueryFilter mFilter;
|
||||
S32 mCurIndex;
|
||||
Vector<Point3F> mPoints;
|
||||
Vector<U16> mFlags;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,8 @@ inline void rcCol(unsigned int col, U8 &r, U8 &g, U8 &b, U8 &a)
|
|||
}
|
||||
|
||||
enum PolyAreas {
|
||||
GroundArea = 1,
|
||||
NullArea = 0,
|
||||
GroundArea,
|
||||
WaterArea,
|
||||
OffMeshArea,
|
||||
NumAreas
|
||||
|
|
@ -99,6 +100,10 @@ struct LinkData {
|
|||
(climb ? ClimbFlag : 0) |
|
||||
(teleport ? TeleportFlag : 0);
|
||||
}
|
||||
U16 getExcludeFlags() const
|
||||
{
|
||||
return AllFlags & ~getFlags();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -857,7 +857,27 @@ $guiContent = new GuiNavEditorCtrl(NavEditorGui, EditorGuiGroup) {
|
|||
visible = "1";
|
||||
active = "0";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
toolTip = "Can this character walk on ground?";
|
||||
toolTip = "Can this character walk on ground?";
|
||||
hovertime = "1000";
|
||||
isContainer = "0";
|
||||
canSave = "1";
|
||||
canSaveDynamicFields = "0";
|
||||
};
|
||||
new GuiCheckBoxCtrl() {
|
||||
internalName = "LinkSwimFlag";
|
||||
class = "NavMeshTestFlagButton";
|
||||
text = " Swim";
|
||||
buttonType = "ToggleButton";
|
||||
useMouseEvents = "0";
|
||||
extent = "159 15";
|
||||
minExtent = "8 2";
|
||||
horizSizing = "right";
|
||||
vertSizing = "bottom";
|
||||
profile = "ToolsGuiCheckBoxProfile";
|
||||
visible = "1";
|
||||
active = "0";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
toolTip = "Can this character swim?";
|
||||
hovertime = "1000";
|
||||
isContainer = "0";
|
||||
canSave = "1";
|
||||
|
|
|
|||
|
|
@ -77,68 +77,5 @@ $guiContent = new GuiControl(NavEditorToolbar,EditorGuiGroup) {
|
|||
canSave = "1";
|
||||
canSaveDynamicFields = "0";
|
||||
};
|
||||
new GuiCheckBoxCtrl() {
|
||||
text = "Mesh";
|
||||
groupNum = "-1";
|
||||
buttonType = "ToggleButton";
|
||||
useMouseEvents = "0";
|
||||
position = "167 1";
|
||||
extent = "50 30";
|
||||
minExtent = "8 2";
|
||||
horizSizing = "right";
|
||||
vertSizing = "bottom";
|
||||
profile = "ToolsGuiCheckBoxProfile";
|
||||
visible = "1";
|
||||
active = "1";
|
||||
variable = "$Nav::Editor::renderMesh";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
hovertime = "1000";
|
||||
isContainer = "0";
|
||||
internalName = "MeshButton";
|
||||
canSave = "1";
|
||||
canSaveDynamicFields = "0";
|
||||
};
|
||||
new GuiCheckBoxCtrl() {
|
||||
text = "Portals";
|
||||
groupNum = "-1";
|
||||
buttonType = "ToggleButton";
|
||||
useMouseEvents = "0";
|
||||
position = "224 1";
|
||||
extent = "54 30";
|
||||
minExtent = "8 2";
|
||||
horizSizing = "right";
|
||||
vertSizing = "bottom";
|
||||
profile = "ToolsGuiCheckBoxProfile";
|
||||
visible = "1";
|
||||
active = "1";
|
||||
variable = "$Nav::Editor::renderPortals";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
hovertime = "1000";
|
||||
isContainer = "0";
|
||||
internalName = "PortalButton";
|
||||
canSave = "1";
|
||||
canSaveDynamicFields = "0";
|
||||
};
|
||||
new GuiCheckBoxCtrl() {
|
||||
text = "BV tree";
|
||||
groupNum = "-1";
|
||||
buttonType = "ToggleButton";
|
||||
useMouseEvents = "0";
|
||||
position = "286 1";
|
||||
extent = "140 30";
|
||||
minExtent = "8 2";
|
||||
horizSizing = "right";
|
||||
vertSizing = "bottom";
|
||||
profile = "ToolsGuiCheckBoxProfile";
|
||||
visible = "1";
|
||||
active = "1";
|
||||
variable = "$Nav::Editor::renderBVTree";
|
||||
tooltipProfile = "GuiToolTipProfile";
|
||||
hovertime = "1000";
|
||||
isContainer = "0";
|
||||
internalName = "BVTreeButton";
|
||||
canSave = "1";
|
||||
canSaveDynamicFields = "0";
|
||||
};
|
||||
};
|
||||
//--- OBJECT WRITE END ---
|
||||
|
|
|
|||
|
|
@ -66,6 +66,13 @@ function initializeNavEditor()
|
|||
buttonImage = "ToolsModule:nav_link_n_image";
|
||||
};
|
||||
|
||||
new NavMeshTestTool()
|
||||
{
|
||||
internalName = "TestTool";
|
||||
toolTip = "PathFinding Test tool";
|
||||
buttonImage = "ToolsModule:3rd_person_camera_n_image";
|
||||
};
|
||||
|
||||
new TileTool()
|
||||
{
|
||||
internalName = "TileTool";
|
||||
|
|
@ -140,7 +147,7 @@ function EditorGui::SetNavPalletBar()
|
|||
EWToolsPaletteWindow.addButton("LinkMode", "ToolsModule:nav_link_n_image", "NavEditorGui.setActiveTool(NavMeshTools->LinkTool);", "", "Create off-mesh links", "2");
|
||||
// EWToolsPaletteWindow.addButton("CoverMode", "ToolsModule:nav_cover_n_image", "NavEditorGui.setMode(\"CoverMode\");", "","Edit cover", "3");
|
||||
// EWToolsPaletteWindow.addButton("TileMode", "ToolsModule:select_bounds_n_image", "NavEditorGui.setMode(\"TileMode\");", "", "View tiles", "4");
|
||||
// EWToolsPaletteWindow.addButton("TestMode", "ToolsModule:3rd_person_camera_n_image", "NavEditorGui.setMode(\"TestMode\");", "", "Test pathfinding", "5");
|
||||
EWToolsPaletteWindow.addButton("TestMode", "ToolsModule:3rd_person_camera_n_image", "NavEditorGui.setActiveTool(NavMeshTools->TestTool);", "", "Test pathfinding", "5");
|
||||
EWToolsPaletteWindow.addButton("TileMode", "ToolsModule:select_bounds_n_image", "NavEditorGui.setActiveTool(NavMeshTools->TileTool);" , "", "View and Edit Tiles", "4");
|
||||
EWToolsPaletteWindow.refresh();
|
||||
}
|
||||
|
|
@ -263,7 +270,7 @@ function NavEditorPlugin::initSettings(%this)
|
|||
EditorSettings.beginGroup("NavEditor", true);
|
||||
|
||||
EditorSettings.setDefaultValue("SpawnClass", "AIPlayer");
|
||||
EditorSettings.setDefaultValue("SpawnDatablock", "DefaultPlayerData");
|
||||
EditorSettings.setDefaultValue("SpawnDatablock", "ProtoPlayer");
|
||||
|
||||
EditorSettings.endGroup();
|
||||
}
|
||||
|
|
@ -273,9 +280,6 @@ function NavEditorPlugin::readSettings(%this)
|
|||
EditorSettings.beginGroup("NavEditor", true);
|
||||
|
||||
// Currently these are globals because of the way they are accessed in navMesh.cpp.
|
||||
$Nav::Editor::renderMesh = EditorSettings.value("RenderMesh");
|
||||
$Nav::Editor::renderPortals = EditorSettings.value("RenderPortals");
|
||||
$Nav::Editor::renderBVTree = EditorSettings.value("RenderBVTree");
|
||||
NavEditorGui.spawnClass = EditorSettings.value("SpawnClass");
|
||||
NavEditorGui.spawnDatablock = EditorSettings.value("SpawnDatablock");
|
||||
NavEditorGui.backgroundBuild = EditorSettings.value("BackgroundBuild");
|
||||
|
|
@ -295,9 +299,6 @@ function NavEditorPlugin::writeSettings(%this)
|
|||
{
|
||||
EditorSettings.beginGroup("NavEditor", true);
|
||||
|
||||
EditorSettings.setValue("RenderMesh", $Nav::Editor::renderMesh);
|
||||
EditorSettings.setValue("RenderPortals", $Nav::Editor::renderPortals);
|
||||
EditorSettings.setValue("RenderBVTree", $Nav::Editor::renderBVTree);
|
||||
EditorSettings.setValue("SpawnClass", NavEditorGui.spawnClass);
|
||||
EditorSettings.setValue("SpawnDatablock", NavEditorGui.spawnDatablock);
|
||||
EditorSettings.setValue("BackgroundBuild", NavEditorGui.backgroundBuild);
|
||||
|
|
|
|||
|
|
@ -411,6 +411,142 @@ function NavMeshLinkBiDirection::onClick(%this)
|
|||
|
||||
//------------------------------------------------------
|
||||
|
||||
function NavMeshTestTool::onActivated(%this)
|
||||
{
|
||||
NavInspector.setVisible(false);
|
||||
|
||||
%actions = NavEditorOptionsWindow->ActionsBox;
|
||||
%actions->SelectActions.setVisible(false);
|
||||
%actions->LinkActions.setVisible(false);
|
||||
%actions->CoverActions.setVisible(false);
|
||||
%actions->TileActions.setVisible(false);
|
||||
%actions->TestActions.setVisible(false);
|
||||
|
||||
%properties = NavEditorOptionsWindow->PropertiesBox;
|
||||
%properties->LinkProperties.setVisible(false);
|
||||
%properties->TileProperties.setVisible(false);
|
||||
%properties->TestProperties.setVisible(false);
|
||||
|
||||
%actions->TestActions.setVisible(true);
|
||||
%properties->TestProperties.setVisible(true);
|
||||
}
|
||||
|
||||
function NavMeshTestTool::onDeactivated(%this)
|
||||
{
|
||||
NavInspector.setVisible(false);
|
||||
|
||||
%actions = NavEditorOptionsWindow->ActionsBox;
|
||||
%actions->SelectActions.setVisible(false);
|
||||
%actions->LinkActions.setVisible(false);
|
||||
%actions->CoverActions.setVisible(false);
|
||||
%actions->TileActions.setVisible(false);
|
||||
%actions->TestActions.setVisible(false);
|
||||
|
||||
%properties = NavEditorOptionsWindow->PropertiesBox;
|
||||
%properties->LinkProperties.setVisible(false);
|
||||
%properties->TileProperties.setVisible(false);
|
||||
%properties->TestProperties.setVisible(false);
|
||||
}
|
||||
|
||||
function updateTestData(%control, %flags)
|
||||
{
|
||||
%control->LinkWalkFlag.setActive(true);
|
||||
%control->LinkSwimFlag.setActive(true);
|
||||
%control->LinkJumpFlag.setActive(true);
|
||||
%control->LinkDropFlag.setActive(true);
|
||||
%control->LinkLedgeFlag.setActive(true);
|
||||
%control->LinkClimbFlag.setActive(true);
|
||||
%control->LinkTeleportFlag.setActive(true);
|
||||
|
||||
%control->LinkWalkFlag.setStateOn(%flags & $Nav::WalkFlag);
|
||||
%control->LinkSwimFlag.setStateOn(%flags & $Nav::SwimFlag);
|
||||
%control->LinkJumpFlag.setStateOn(%flags & $Nav::JumpFlag);
|
||||
%control->LinkDropFlag.setStateOn(%flags & $Nav::DropFlag);
|
||||
%control->LinkLedgeFlag.setStateOn(%flags & $Nav::LedgeFlag);
|
||||
%control->LinkClimbFlag.setStateOn(%flags & $Nav::ClimbFlag);
|
||||
%control->LinkTeleportFlag.setStateOn(%flags & $Nav::TeleportFlag);
|
||||
}
|
||||
|
||||
function getTestFlags(%control)
|
||||
{
|
||||
return (%control->LinkWalkFlag.isStateOn() ? $Nav::WalkFlag : 0) |
|
||||
(%control->LinkSwimFlag.isStateOn() ? $Nav::SwimFlag : 0) |
|
||||
(%control->LinkJumpFlag.isStateOn() ? $Nav::JumpFlag : 0) |
|
||||
(%control->LinkDropFlag.isStateOn() ? $Nav::DropFlag : 0) |
|
||||
(%control->LinkLedgeFlag.isStateOn() ? $Nav::LedgeFlag : 0) |
|
||||
(%control->LinkClimbFlag.isStateOn() ? $Nav::ClimbFlag : 0) |
|
||||
(%control->LinkTeleportFlag.isStateOn() ? $Nav::TeleportFlag : 0);
|
||||
}
|
||||
|
||||
function disableTestData(%control)
|
||||
{
|
||||
%control->LinkWalkFlag.setActive(false);
|
||||
%control->LinkSwimFlag.setActive(false);
|
||||
%control->LinkJumpFlag.setActive(false);
|
||||
%control->LinkDropFlag.setActive(false);
|
||||
%control->LinkLedgeFlag.setActive(false);
|
||||
%control->LinkClimbFlag.setActive(false);
|
||||
%control->LinkTeleportFlag.setActive(false);
|
||||
}
|
||||
|
||||
function getControllerDataFlags(%controllerData)
|
||||
{
|
||||
return (%controllerData.allowWalk ? $Nav::WalkFlag : 0 ) |
|
||||
(%controllerData.allowSwim ? $Nav::SwimFlag : 0 ) |
|
||||
(%controllerData.allowJump ? $Nav::JumpFlag : 0 ) |
|
||||
(%controllerData.allowDrop ? $Nav::DropFlag : 0 ) |
|
||||
(%controllerData.allowLedge ? $Nav::LedgeFlag : 0) |
|
||||
(%controllerData.allowClimb ? $Nav::ClimbFlag : 0) |
|
||||
(%controllerData.allowTeleport ? $Nav::TeleportFlag : 0 );
|
||||
}
|
||||
|
||||
function NavMeshTestTool::updateTestFlags(%this)
|
||||
{
|
||||
if(isObject(%this.getPlayer()))
|
||||
{
|
||||
%properties = NavEditorOptionsWindow-->TestProperties;
|
||||
%player = %this.getPlayer();
|
||||
%controllerData = %player.getDatablock().aiControllerData;
|
||||
|
||||
%controllerData.allowWalk = %properties->LinkWalkFlag.isStateOn();
|
||||
%controllerData.allowSwim = %properties->LinkSwimFlag.isStateOn();
|
||||
%controllerData.allowJump = %properties->LinkJumpFlag.isStateOn();
|
||||
%controllerData.allowDrop = %properties->LinkDropFlag.isStateOn();
|
||||
%controllerData.allowLedge = %properties->LinkLedgeFlag.isStateOn();
|
||||
%controllerData.allowClimb = %properties->LinkClimbFlag.isStateOn();
|
||||
%controllerData.allowTeleport = %properties->LinkTeleportFlag.isStateOn();
|
||||
|
||||
%player.aiController = new AIController(){ ControllerData = %controllerData; };
|
||||
%player.setAIController(%player.aiController);
|
||||
}
|
||||
}
|
||||
|
||||
function NavMeshTestTool::onPlayerSelected(%this, %flags)
|
||||
{
|
||||
if (!isObject(%this.getPlayer().aiController) || (isObject(%this.getPlayer().aiController) && !(%this.getPlayer().isMemberOfClass("AIPlayer"))))
|
||||
{
|
||||
%this.getPlayer().aiController = new AIController(){ ControllerData = %this.getPlayer().getDatablock().aiControllerData; };
|
||||
%this.getPlayer().setAIController(%this.getPlayer().aiController);
|
||||
%flags = getControllerDataFlags(%this.getPlayer().getDatablock().aiControllerData);
|
||||
}
|
||||
NavMeshIgnore(%this.getPlayer(), true);
|
||||
%this.getPlayer().setDamageState("Enabled");
|
||||
|
||||
updateTestData(NavEditorOptionsWindow-->TestProperties, %flags);
|
||||
}
|
||||
|
||||
function NavMeshTestTool::onPlayerDeselected(%this)
|
||||
{
|
||||
disableTestData(NavEditorOptionsWindow-->TestProperties);
|
||||
}
|
||||
|
||||
function NavMeshTestFlagButton::onClick(%this)
|
||||
{
|
||||
NavMeshTools->TestTool.updateTestFlags();
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
function TileTool::onActivated(%this)
|
||||
{
|
||||
NavInspector.setVisible(false);
|
||||
|
|
@ -540,13 +676,13 @@ function NavEditorGui::deleteSelected(%this)
|
|||
toolsMessageBoxYesNo("Warning",
|
||||
"Are you sure you want to delete" SPC NavEditorGui.selectedObject.getName(),
|
||||
"NavEditorGui.deleteMesh();");
|
||||
case "TestMode":
|
||||
%this.getPlayer().delete();
|
||||
%this.onPlayerDeselected();
|
||||
case "LinkMode":
|
||||
%this.deleteLink();
|
||||
%this.isDirty = true;
|
||||
}
|
||||
// case "TestMode":
|
||||
// %this.getPlayer().delete();
|
||||
// %this.onPlayerDeselected();
|
||||
// case "LinkMode":
|
||||
// %this.deleteLink();
|
||||
// %this.isDirty = true;
|
||||
// }
|
||||
}
|
||||
|
||||
function NavEditorGui::buildSelectedMeshes(%this)
|
||||
|
|
@ -567,47 +703,6 @@ function NavEditorGui::buildLinks(%this)
|
|||
}
|
||||
}
|
||||
|
||||
function NavEditorGui::onLinkSelected(%this, %flags)
|
||||
{
|
||||
updateLinkData(NavEditorOptionsWindow-->LinkProperties, %flags);
|
||||
}
|
||||
|
||||
function NavEditorGui::onPlayerSelected(%this, %flags)
|
||||
{
|
||||
if (!isObject(%this.getPlayer().aiController) || (isObject(%this.getPlayer().aiController) && !(%this.getPlayer().isMemberOfClass("AIPlayer"))))
|
||||
{
|
||||
%this.getPlayer().aiController = new AIController(){ ControllerData = %this.getPlayer().getDatablock().aiControllerData; };
|
||||
%this.getPlayer().setAIController(%this.getPlayer().aiController);
|
||||
}
|
||||
NavMeshIgnore(%this.getPlayer(), true);
|
||||
%this.getPlayer().setDamageState("Enabled");
|
||||
|
||||
updateLinkData(NavEditorOptionsWindow-->TestProperties, %flags);
|
||||
}
|
||||
|
||||
function NavEditorGui::updateTestFlags(%this)
|
||||
{
|
||||
if(isObject(%this.getPlayer()))
|
||||
{
|
||||
%properties = NavEditorOptionsWindow-->TestProperties;
|
||||
%player = %this.getPlayer();
|
||||
|
||||
%player.allowWwalk = %properties->LinkWalkFlag.isStateOn();
|
||||
%player.allowJump = %properties->LinkJumpFlag.isStateOn();
|
||||
%player.allowDrop = %properties->LinkDropFlag.isStateOn();
|
||||
%player.allowLedge = %properties->LinkLedgeFlag.isStateOn();
|
||||
%player.allowClimb = %properties->LinkClimbFlag.isStateOn();
|
||||
%player.allowTeleport = %properties->LinkTeleportFlag.isStateOn();
|
||||
|
||||
%this.isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
function NavEditorGui::onPlayerDeselected(%this)
|
||||
{
|
||||
disableLinkData(NavEditorOptionsWindow-->TestProperties);
|
||||
}
|
||||
|
||||
function NavEditorGui::createCoverPoints(%this)
|
||||
{
|
||||
if(isObject(%this.getMesh()))
|
||||
|
|
@ -718,11 +813,6 @@ function ENavEditorPaletteButton::onClick(%this)
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function NavMeshTestFlagButton::onClick(%this)
|
||||
{
|
||||
NavEditorGui.updateTestFlags();
|
||||
}
|
||||
|
||||
singleton GuiControlProfile(NavEditorProfile)
|
||||
{
|
||||
canKeyFocus = true;
|
||||
|
|
|
|||
Loading…
Reference in a new issue