using DotRecast.Core; using DotRecast.Core.Numerics; using DotRecast.Detour.TileCache; using DotRecast.Detour.TileCache.Io.Compress; using DotRecast.Recast.Demo.Draw; using DotRecast.Recast.Toolset; using DotRecast.Recast.Toolset.Tools; using ImGuiNET; using Serilog; namespace DotRecast.Recast.Demo.Tools; public class ObstacleSampleTool : ISampleTool { private static readonly ILogger Logger = Log.ForContext(); private DemoSample _sample; private readonly RcObstacleTool _tool; public ObstacleSampleTool() { _tool = new(DtTileCacheCompressorFactory.Shared); } public void Layout() { if (ImGui.Button("Build Tile Cache")) { var geom = _sample.GetInputGeom(); var settings = _sample.GetSettings(); var buildResult = _tool.Build(geom, settings, RcByteOrder.LITTLE_ENDIAN, true); if (buildResult.Success) { _sample.Update(_sample.GetInputGeom(), buildResult.RecastBuilderResults, buildResult.NavMesh); _sample.SetChanged(false); } } if (ImGui.Button("Remove All Temp Obstacles")) { _tool.ClearAllTempObstacles(); } ImGui.Separator(); ImGui.Text("Click LMB to create an obstacle."); ImGui.Text("Shift+LMB to remove an obstacle."); } public void HandleRender(NavMeshRenderer renderer) { DrawObstacles(renderer.GetDebugDraw()); } private void DrawObstacles(RecastDebugDraw dd) { var tc = _tool.GetTileCache(); if (null == tc) return; // Draw obstacles for (int i = 0; i < tc.GetObstacleCount(); ++i) { var ob = tc.GetObstacle(i); if (ob.state == DtObstacleState.DT_OBSTACLE_EMPTY) continue; RcVec3f bmin = RcVec3f.Zero; RcVec3f bmax = RcVec3f.Zero; tc.GetObstacleBounds(ob, ref bmin, ref bmax); int col = 0; if (ob.state == DtObstacleState.DT_OBSTACLE_PROCESSING) col = DebugDraw.DuRGBA(255, 255, 0, 128); else if (ob.state == DtObstacleState.DT_OBSTACLE_PROCESSED) col = DebugDraw.DuRGBA(255, 192, 0, 192); else if (ob.state == DtObstacleState.DT_OBSTACLE_REMOVING) col = DebugDraw.DuRGBA(220, 0, 0, 128); dd.DebugDrawCylinder(bmin.X, bmin.Y, bmin.Z, bmax.X, bmax.Y, bmax.Z, col); dd.DebugDrawCylinderWire(bmin.X, bmin.Y, bmin.Z, bmax.X, bmax.Y, bmax.Z, DebugDraw.DuDarkenCol(col), 2); } } public IRcToolable GetTool() { return _tool; } public void SetSample(DemoSample sample) { _sample = sample; } public void OnSampleChanged() { } public void HandleClick(RcVec3f s, RcVec3f p, bool shift) { if (shift) { _tool.RemoveTempObstacle(s, p); } else { _tool.AddTempObstacle(p); } } public void HandleUpdate(float dt) { var tc = _tool.GetTileCache(); if (null != tc) tc.Update(); } public void HandleClickRay(RcVec3f start, RcVec3f direction, bool shift) { } }