From dc09674362aaac2c447fe8ab30d8baa1e434edcf Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 21 Jul 2018 13:37:02 +0300 Subject: [PATCH] Add command and settings option to enable actors paths render --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwbase/world.hpp | 4 + apps/openmw/mwmechanics/aipackage.cpp | 7 ++ apps/openmw/mwrender/actorspaths.cpp | 99 +++++++++++++++++++++++ apps/openmw/mwrender/actorspaths.hpp | 51 ++++++++++++ apps/openmw/mwrender/renderingmanager.cpp | 20 ++++- apps/openmw/mwrender/renderingmanager.hpp | 10 +++ apps/openmw/mwrender/rendermode.hpp | 1 + apps/openmw/mwscript/docs/vmformat.txt | 3 +- apps/openmw/mwscript/miscextensions.cpp | 15 ++++ apps/openmw/mwworld/scene.cpp | 3 + apps/openmw/mwworld/worldimp.cpp | 6 ++ apps/openmw/mwworld/worldimp.hpp | 3 + components/CMakeLists.txt | 2 +- components/compiler/extensions0.cpp | 2 +- components/compiler/opcodes.hpp | 1 + components/sceneutil/agentpath.cpp | 71 ++++++++++++++++ components/sceneutil/agentpath.hpp | 26 ++++++ components/sceneutil/detourdebugdraw.cpp | 9 ++- components/sceneutil/detourdebugdraw.hpp | 2 + files/settings-default.cfg | 5 +- 21 files changed, 334 insertions(+), 8 deletions(-) create mode 100644 apps/openmw/mwrender/actorspaths.cpp create mode 100644 apps/openmw/mwrender/actorspaths.hpp create mode 100644 components/sceneutil/agentpath.cpp create mode 100644 components/sceneutil/agentpath.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index bac9634db..ad8853753 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -21,7 +21,7 @@ add_openmw_dir (mwrender actors objects renderingmanager animation rotatecontroller sky npcanimation vismask creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation - renderbin actoranimation landmanager navmesh + renderbin actoranimation landmanager navmesh actorspaths ) add_openmw_dir (mwinput diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 18f997324..db6bda141 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -597,6 +598,9 @@ namespace MWBase virtual void preloadEffects(const ESM::EffectList* effectList) = 0; virtual DetourNavigator::Navigator* getNavigator() const = 0; + + virtual void updateActorPath(const MWWorld::ConstPtr& actor, const std::deque& path, + const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end) const = 0; }; } diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index 0b06d8c1d..16af9c8e7 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" @@ -102,6 +103,12 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const osg::Vec3f& const ESM::Position pos = actor.getRefData().getPosition(); //position of the actor + { + const auto halfExtents = MWBase::Environment::get().getWorld()->getHalfExtents(actor); + MWBase::Environment::get().getWorld()->updateActorPath(actor, mPathFinder.getPath(), halfExtents, + pos.asVec3(), dest); + } + /// Stops the actor when it gets too close to a unloaded cell //... At current time, this test is unnecessary. AI shuts down when actor is more than 7168 //... units from player, and exterior cells are 8192 units long and wide. diff --git a/apps/openmw/mwrender/actorspaths.cpp b/apps/openmw/mwrender/actorspaths.cpp new file mode 100644 index 000000000..35b255355 --- /dev/null +++ b/apps/openmw/mwrender/actorspaths.cpp @@ -0,0 +1,99 @@ +#include "actorspaths.hpp" +#include "vismask.hpp" + +#include + +#include + +namespace MWRender +{ + ActorsPaths::ActorsPaths(const osg::ref_ptr& root, bool enabled) + : mRootNode(root) + , mEnabled(enabled) + { + } + + ActorsPaths::~ActorsPaths() + { + if (mEnabled) + disable(); + } + + bool ActorsPaths::toggle() + { + if (mEnabled) + disable(); + else + enable(); + + return mEnabled; + } + + void ActorsPaths::update(const MWWorld::ConstPtr& actor, const std::deque& path, + const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end, + const DetourNavigator::Settings& settings) + { + if (!mEnabled) + return; + + const auto group = mGroups.find(actor); + if (group != mGroups.end()) + mRootNode->removeChild(group->second); + + const auto newGroup = SceneUtil::createAgentPathGroup(path, halfExtents, start, end, settings); + if (newGroup) + { + newGroup->setNodeMask(Mask_Debug); + mRootNode->addChild(newGroup); + mGroups[actor] = newGroup; + } + } + + void ActorsPaths::remove(const MWWorld::ConstPtr& actor) + { + const auto group = mGroups.find(actor); + if (group != mGroups.end()) + { + mRootNode->removeChild(group->second); + mGroups.erase(group); + } + } + + void ActorsPaths::removeCell(const MWWorld::CellStore* const store) + { + for (auto it = mGroups.begin(); it != mGroups.end(); ) + { + if (it->first.getCell() == store) + { + mRootNode->removeChild(it->second); + it = mGroups.erase(it); + } + else + ++it; + } + } + + void ActorsPaths::updatePtr(const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated) + { + const auto it = mGroups.find(old); + if (it == mGroups.end()) + return; + auto group = std::move(it->second); + mGroups.erase(it); + mGroups.insert(std::make_pair(updated, std::move(group))); + } + + void ActorsPaths::enable() + { + std::for_each(mGroups.begin(), mGroups.end(), + [&] (const Groups::value_type& v) { mRootNode->addChild(v.second); }); + mEnabled = true; + } + + void ActorsPaths::disable() + { + std::for_each(mGroups.begin(), mGroups.end(), + [&] (const Groups::value_type& v) { mRootNode->removeChild(v.second); }); + mEnabled = false; + } +} diff --git a/apps/openmw/mwrender/actorspaths.hpp b/apps/openmw/mwrender/actorspaths.hpp new file mode 100644 index 000000000..1f61834d4 --- /dev/null +++ b/apps/openmw/mwrender/actorspaths.hpp @@ -0,0 +1,51 @@ +#ifndef OPENMW_MWRENDER_AGENTSPATHS_H +#define OPENMW_MWRENDER_AGENTSPATHS_H + +#include + +#include + +#include + +#include +#include + +namespace osg +{ + class Group; +} + +namespace MWRender +{ + class ActorsPaths + { + public: + ActorsPaths(const osg::ref_ptr& root, bool enabled); + ~ActorsPaths(); + + bool toggle(); + + void update(const MWWorld::ConstPtr& actor, const std::deque& path, + const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end, + const DetourNavigator::Settings& settings); + + void remove(const MWWorld::ConstPtr& actor); + + void removeCell(const MWWorld::CellStore* const store); + + void updatePtr(const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated); + + void enable(); + + void disable(); + + private: + using Groups = std::map>; + + osg::ref_ptr mRootNode; + Groups mGroups; + bool mEnabled; + }; +} + +#endif diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index fbe8ba345..5c0a3347c 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -66,6 +66,7 @@ #include "terrainstorage.hpp" #include "util.hpp" #include "navmesh.hpp" +#include "actorspaths.hpp" namespace { @@ -234,7 +235,8 @@ namespace MWRender mRootNode->addChild(mSceneRoot); - mNavMesh.reset(new NavMesh(mRootNode, Settings::Manager::getBool("enable render", "Navigator"))); + mNavMesh.reset(new NavMesh(mRootNode, Settings::Manager::getBool("enable nav mesh render", "Navigator"))); + mActorsPaths.reset(new ActorsPaths(mRootNode, Settings::Manager::getBool("enable agents paths render", "Navigator"))); mPathgrid.reset(new Pathgrid(mRootNode)); mObjects.reset(new Objects(mResourceSystem, sceneRoot, mUnrefQueue.get())); @@ -472,6 +474,7 @@ namespace MWRender void RenderingManager::removeCell(const MWWorld::CellStore *store) { mPathgrid->removeCell(store); + mActorsPaths->removeCell(store); mObjects->removeCell(store); if (store->getCell()->isExterior()) @@ -527,6 +530,10 @@ namespace MWRender { return mNavMesh->toggle(); } + else if (mode == Render_ActorsPaths) + { + return mActorsPaths->toggle(); + } return false; } @@ -666,6 +673,7 @@ namespace MWRender void RenderingManager::removeObject(const MWWorld::Ptr &ptr) { + mActorsPaths->remove(ptr); mObjects->removeObject(ptr); mWater->removeEmitter(ptr); } @@ -1049,6 +1057,7 @@ namespace MWRender void RenderingManager::updatePtr(const MWWorld::Ptr &old, const MWWorld::Ptr &updated) { mObjects->updatePtr(old, updated); + mActorsPaths->updatePtr(old, updated); } void RenderingManager::spawnEffect(const std::string &model, const std::string &texture, const osg::Vec3f &worldPosition, float scale, bool isMagicVFX) @@ -1369,5 +1378,14 @@ namespace MWRender return mTerrainStorage->getLandManager(); } + void RenderingManager::updateActorPath(const MWWorld::ConstPtr& actor, const std::deque& path, + const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end) const + { + mActorsPaths->update(actor, path, halfExtents, start, end, mNavigator.getSettings()); + } + void RenderingManager::removeActorPath(const MWWorld::ConstPtr& actor) const + { + mActorsPaths->remove(actor); + } } diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index a8eae5286..76ec67445 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -12,6 +12,8 @@ #include "renderinginterface.hpp" #include "rendermode.hpp" +#include + namespace osg { class Group; @@ -58,6 +60,7 @@ namespace SceneUtil namespace DetourNavigator { class Navigator; + struct Settings; } namespace MWRender @@ -74,6 +77,7 @@ namespace MWRender class TerrainStorage; class LandManager; class NavMesh; + class ActorsPaths; class RenderingManager : public MWRender::RenderingInterface { @@ -219,6 +223,11 @@ namespace MWRender bool toggleBorders(); + void updateActorPath(const MWWorld::ConstPtr& actor, const std::deque& path, + const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end) const; + + void removeActorPath(const MWWorld::ConstPtr& actor) const; + private: void updateProjectionMatrix(); void updateTextureFiltering(); @@ -245,6 +254,7 @@ namespace MWRender DetourNavigator::Navigator& mNavigator; std::unique_ptr mNavMesh; + std::unique_ptr mActorsPaths; std::unique_ptr mPathgrid; std::unique_ptr mObjects; std::unique_ptr mWater; diff --git a/apps/openmw/mwrender/rendermode.hpp b/apps/openmw/mwrender/rendermode.hpp index 9f0c5a7cd..077710f4f 100644 --- a/apps/openmw/mwrender/rendermode.hpp +++ b/apps/openmw/mwrender/rendermode.hpp @@ -12,6 +12,7 @@ namespace MWRender Render_Water, Render_Scene, Render_NavMesh, + Render_ActorsPaths, }; } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 2ce22633c..bc7d93a13 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -456,5 +456,6 @@ op 0x2000305: Show, explicit op 0x2000306: OnActivate, explicit op 0x2000307: ToggleBorders, tb op 0x2000308: ToggleNavMesh +op 0x2000309: ToggleActorsPaths -opcodes 0x2000309-0x3ffffff unused +opcodes 0x200030a-0x3ffffff unused diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 8ccb619d0..8507b7628 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -1331,6 +1331,20 @@ namespace MWScript } }; + class OpToggleActorsPaths : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + bool enabled = + MWBase::Environment::get().getWorld()->toggleRenderMode (MWRender::Render_ActorsPaths); + + runtime.getContext().report (enabled ? + "Agents Paths Rendering -> On" : "Agents Paths Rendering -> Off"); + } + }; + void installOpcodes (Interpreter::Interpreter& interpreter) { interpreter.installSegment5 (Compiler::Misc::opcodeXBox, new OpXBox); @@ -1432,6 +1446,7 @@ namespace MWScript interpreter.installSegment3 (Compiler::Misc::opcodeShowSceneGraphExplicit, new OpShowSceneGraph); interpreter.installSegment5 (Compiler::Misc::opcodeToggleBorders, new OpToggleBorders); interpreter.installSegment5 (Compiler::Misc::opcodeToggleNavMesh, new OpToggleNavMesh); + interpreter.installSegment5 (Compiler::Misc::opcodeToggleActorsPaths, new OpToggleActorsPaths); } } } diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index ca19383d1..2f6c0330f 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -278,7 +278,10 @@ namespace MWWorld if (const auto object = mPhysics->getObject(ptr)) navigator->removeObject(reinterpret_cast(object)); else if (const auto actor = mPhysics->getActor(ptr)) + { navigator->removeAgent(playerHalfExtents); + mRendering.removeActorPath(ptr); + } mPhysics->remove(ptr); } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index bb8bd9615..2929a4974 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -3745,4 +3745,10 @@ namespace MWWorld return mNavigator.get(); } + void World::updateActorPath(const MWWorld::ConstPtr& actor, const std::deque& path, + const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end) const + { + mRendering->updateActorPath(actor, path, halfExtents, start, end); + } + } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 4e3deffbe..b49267962 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -691,6 +691,9 @@ namespace MWWorld void preloadEffects(const ESM::EffectList* effectList) override; DetourNavigator::Navigator* getNavigator() const override; + + void updateActorPath(const MWWorld::ConstPtr& actor, const std::deque& path, + const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end) const override; }; } diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 7ca7ce673..cf45d3212 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -51,7 +51,7 @@ add_component_dir (shader add_component_dir (sceneutil clone attach visitor util statesetupdater controller skeleton riggeometry morphgeometry lightcontroller lightmanager lightutil positionattitudetransform workqueue unrefqueue pathgridutil waterutil writescene serialize optimizer - actorutil detourdebugdraw navmesh + actorutil detourdebugdraw navmesh agentpath ) add_component_dir (nif diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index e39b97e3f..241abfaa4 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -321,7 +321,7 @@ namespace Compiler extensions.registerInstruction ("tb", "", opcodeToggleBorders); extensions.registerInstruction ("toggleborders", "", opcodeToggleBorders); extensions.registerInstruction ("togglenavmesh", "", opcodeToggleNavMesh); - extensions.registerInstruction ("tnm", "", opcodeToggleNavMesh); + extensions.registerInstruction ("toggleactorspaths", "", opcodeToggleActorsPaths); } } diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index 75ef73837..c591115ec 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -297,6 +297,7 @@ namespace Compiler const int opcodeShowSceneGraphExplicit = 0x20030; const int opcodeToggleBorders = 0x2000307; const int opcodeToggleNavMesh = 0x2000308; + const int opcodeToggleActorsPaths = 0x2000309; } namespace Sky diff --git a/components/sceneutil/agentpath.cpp b/components/sceneutil/agentpath.cpp new file mode 100644 index 000000000..aaee4dd1e --- /dev/null +++ b/components/sceneutil/agentpath.cpp @@ -0,0 +1,71 @@ +#include "agentpath.hpp" +#include "detourdebugdraw.hpp" + +#include +#include + +#include + +namespace +{ + void drawAgent(duDebugDraw& debugDraw, const osg::Vec3f& pos, const float radius, const float height, + const float climb, const unsigned color) + { + debugDraw.depthMask(false); + + duDebugDrawCylinderWire(&debugDraw, pos.x() - radius, pos.z() + 0.02f, pos.y() - radius, pos.x() + radius, + pos.z() + height, pos.y() + radius, color, radius * 0.2f); + + duDebugDrawCircle(&debugDraw, pos.x(), pos.z() + climb, pos.y(), radius, duRGBA(0, 0 , 0, 64), radius * 0.1f); + + const auto colb = duRGBA(0, 0, 0, 196); + debugDraw.begin(DU_DRAW_LINES); + debugDraw.vertex(pos.x(), pos.z() - climb, pos.y(), colb); + debugDraw.vertex(pos.x(), pos.z() + climb, pos.y(), colb); + debugDraw.vertex(pos.x() - radius / 2, pos.z() + 0.02f, pos.y(), colb); + debugDraw.vertex(pos.x() + radius / 2, pos.z() + 0.02f, pos.y(), colb); + debugDraw.vertex(pos.x(), pos.z() + 0.02f, pos.y() - radius / 2, colb); + debugDraw.vertex(pos.x(), pos.z() + 0.02f, pos.y() + radius / 2, colb); + debugDraw.end(); + + debugDraw.depthMask(true); + } +} + +namespace SceneUtil +{ + osg::ref_ptr createAgentPathGroup(const std::deque& path, + const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end, + const DetourNavigator::Settings& settings) + { + using namespace DetourNavigator; + + const osg::ref_ptr group(new osg::Group); + + DebugDraw debugDraw(*group, osg::Vec3f(0, 0, 0), 1); + + const auto agentRadius = halfExtents.x(); + const auto agentHeight = 2.0f * halfExtents.z(); + const auto agentClimb = settings.mMaxClimb; + const auto startColor = duRGBA(128, 25, 0, 192); + const auto endColor = duRGBA(51, 102, 0, 129); + + drawAgent(debugDraw, start, agentRadius, agentHeight, agentClimb, startColor); + drawAgent(debugDraw, end, agentRadius, agentHeight, agentClimb, endColor); + + const auto pathColor = duRGBA(0, 0, 0, 220); + + debugDraw.depthMask(false); + + debugDraw.begin(osg::PrimitiveSet::LINE_STRIP, agentRadius * 0.5f); + debugDraw.vertex(osg::Vec3f(start.x(), start.z() + agentClimb, start.y()).ptr(), startColor); + std::for_each(path.begin(), path.end(), + [&] (const osg::Vec3f& v) { debugDraw.vertex(osg::Vec3f(v.x(), v.z() + agentClimb, v.y()).ptr(), pathColor); }); + debugDraw.vertex(osg::Vec3f(end.x(), end.z() + agentClimb, end.y()).ptr(), endColor); + debugDraw.end(); + + debugDraw.depthMask(true); + + return group; + } +} diff --git a/components/sceneutil/agentpath.hpp b/components/sceneutil/agentpath.hpp new file mode 100644 index 000000000..a8965d852 --- /dev/null +++ b/components/sceneutil/agentpath.hpp @@ -0,0 +1,26 @@ +#ifndef OPENMW_COMPONENTS_SCENEUTIL_AGENTPATH_H +#define OPENMW_COMPONENTS_SCENEUTIL_AGENTPATH_H + +#include + +#include + +namespace osg +{ + class Group; + class Vec3f; +} + +namespace DetourNavigator +{ + struct Settings; +} + +namespace SceneUtil +{ + osg::ref_ptr createAgentPathGroup(const std::deque& path, + const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end, + const DetourNavigator::Settings& settings); +} + +#endif diff --git a/components/sceneutil/detourdebugdraw.cpp b/components/sceneutil/detourdebugdraw.cpp index f6c438e79..a0ae67dc2 100644 --- a/components/sceneutil/detourdebugdraw.cpp +++ b/components/sceneutil/detourdebugdraw.cpp @@ -56,14 +56,19 @@ namespace SceneUtil throw std::logic_error("DebugDraw does not support textures (at " __FILE__ ":" OPENMW_LINE_STRING ")"); } - void DebugDraw::begin(duDebugDrawPrimitives prim, float size) + void DebugDraw::begin(osg::PrimitiveSet::Mode mode, float size) { - mMode = toOsgPrimitiveSetMode(prim); + mMode = mode; mVertices = new osg::Vec3Array; mColors = new osg::Vec4Array; mSize = size * mRecastInvertedScaleFactor; } + void DebugDraw::begin(duDebugDrawPrimitives prim, float size) + { + begin(toOsgPrimitiveSetMode(prim), size); + } + void DebugDraw::vertex(const float* pos, unsigned color) { vertex(pos[0], pos[1], pos[2], color); diff --git a/components/sceneutil/detourdebugdraw.hpp b/components/sceneutil/detourdebugdraw.hpp index 87f501e2b..bb170e7ba 100644 --- a/components/sceneutil/detourdebugdraw.hpp +++ b/components/sceneutil/detourdebugdraw.hpp @@ -18,6 +18,8 @@ namespace SceneUtil void texture(bool state) override; + void begin(osg::PrimitiveSet::Mode mode, float size); + void begin(duDebugDrawPrimitives prim, float size) override; void vertex(const float* pos, unsigned int color) override; diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 1b346dad6..c046a19b3 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -619,4 +619,7 @@ recast mesh path prefix = nav mesh path prefix = # Render nav mesh (true, false) -enable render = false +enable nav mesh render = false + +# Render agents paths (true, false) +enable agents paths render = false