add log view

This commit is contained in:
ikpil 2023-04-16 11:54:50 +09:00
parent c819ded81b
commit 52d7f63ebd
10 changed files with 287 additions and 87 deletions

View File

@ -19,12 +19,11 @@ freely, subject to the following restrictions:
*/
using System.Collections.Generic;
using System.Linq;
using DotRecast.Core;
using DotRecast.Detour;
using DotRecast.Recast.Demo.Builder;
using DotRecast.Recast.Demo.Geom;
using DotRecast.Recast.Demo.Settings;
using DotRecast.Recast.Demo.UI;
namespace DotRecast.Recast.Demo.Draw;

View File

@ -19,7 +19,7 @@ public static class Program
Directory.SetCurrentDirectory(workingDirectory);
}
var format = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj} [{MemberName}()] [{ThreadName}:{ThreadId}] at {FilePath}:{LineNumber} {NewLine}{Exception}";
var format = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj} [{ThreadName}:{ThreadId}]{NewLine}{Exception}";
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.Enrich.WithThreadId()

View File

@ -38,7 +38,7 @@ using DotRecast.Detour.Io;
using DotRecast.Recast.Demo.Builder;
using DotRecast.Recast.Demo.Draw;
using DotRecast.Recast.Demo.Geom;
using DotRecast.Recast.Demo.Settings;
using DotRecast.Recast.Demo.Tools;
using DotRecast.Recast.Demo.UI;
using static DotRecast.Core.RecastMath;
@ -50,7 +50,7 @@ public class RecastDemo
{
private static readonly ILogger Logger = Log.ForContext<RecastDemo>();
private RcViewSystem _viewSys;
private RcCanvas _canvas;
private IWindow window;
private IInputContext _input;
private ImGuiController _imgui;
@ -107,8 +107,11 @@ public class RecastDemo
private int[] viewport;
private bool markerPositionSet;
private Vector3f markerPosition = new Vector3f();
private ToolsView toolsUI;
private RcSettingsView settingsUI;
private RcLogView logUI;
private long prevFrameTime;
private RecastDebugDraw dd;
@ -252,9 +255,6 @@ public class RecastDemo
private IWindow CreateWindow()
{
var monitor = Window.Platforms.First().GetMainMonitor();
// // if (monitors.limit() > 1) {
// // monitor = monitors[1];
// // }
var resolution = monitor.VideoMode.Resolution.Value;
float aspect = 16.0f / 9.0f;
@ -358,7 +358,6 @@ public class RecastDemo
mice.MouseMove += OnMouseMoved;
}
_gl = window.CreateOpenGL();
dd = new RecastDebugDraw(_gl);
@ -367,28 +366,7 @@ public class RecastDemo
dd.init(camr);
_imgui = new ImGuiController(_gl, window, _input);
// // if (capabilities.OpenGL43) {
// // GL43.glDebugMessageControl(GL43.GL_DEBUG_SOURCE_API, GL43.GL_DEBUG_TYPE_OTHER,
// // GL43.GL_DEBUG_SEVERITY_NOTIFICATION,
// // (int[]) null, false);
// // } else if (capabilities.GL_ARB_debug_output) {
// // ARBDebugOutput.glDebugMessageControlARB(ARBDebugOutput.GL_DEBUG_SOURCE_API_ARB,
// // ARBDebugOutput.GL_DEBUG_TYPE_OTHER_ARB, ARBDebugOutput.GL_DEBUG_SEVERITY_LOW_ARB, (int[]) null, false);
// // }
var vendor = _gl.GetStringS(GLEnum.Vendor);
Logger.Debug(vendor);
var version = _gl.GetStringS(GLEnum.Version);
Logger.Debug(version);
var renderGl = _gl.GetStringS(GLEnum.Renderer);
Logger.Debug(renderGl);
var glslString = _gl.GetStringS(GLEnum.ShadingLanguageVersion);
Logger.Debug(glslString);
settingsUI = new RcSettingsView();
toolsUI = new ToolsView(
new TestNavmeshTool(),
@ -398,8 +376,20 @@ public class RecastDemo
new JumpLinkBuilderTool(),
new DynamicUpdateTool()
);
logUI = new RcLogView();
_canvas = new RcCanvas(window, settingsUI, toolsUI, logUI);
var vendor = _gl.GetStringS(GLEnum.Vendor);
var version = _gl.GetStringS(GLEnum.Version);
var renderGl = _gl.GetStringS(GLEnum.Renderer);
var glslString = _gl.GetStringS(GLEnum.ShadingLanguageVersion);
Logger.Debug(vendor);
Logger.Debug(version);
Logger.Debug(renderGl);
Logger.Debug(glslString);
_viewSys = new RcViewSystem(window, _input, settingsUI, toolsUI);
DemoInputGeomProvider geom = loadInputMesh(Loader.ToBytes("nav_test.obj"));
sample = new Sample(geom, ImmutableArray<RecastBuilderResult>.Empty, null, settingsUI, dd);
@ -537,6 +527,8 @@ public class RecastDemo
float m_detailSampleMaxError = settingsUI.getDetailSampleMaxError();
int m_tileSize = settingsUI.getTileSize();
long t = FrequencyWatch.Ticks;
Logger.Information($"build");
Tuple<IList<RecastBuilderResult>, NavMesh> buildResult;
if (settingsUI.isTiled())
@ -559,8 +551,22 @@ public class RecastDemo
sample.update(sample.getInputGeom(), buildResult.Item1, buildResult.Item2);
sample.setChanged(false);
settingsUI.setBuildTime((FrequencyWatch.Ticks - t) / TimeSpan.TicksPerMillisecond);
settingsUI.setBuildTelemetry(buildResult.Item1.Select(x => x.getTelemetry()).ToList());
//settingsUI.setBuildTelemetry(buildResult.Item1.Select(x => x.getTelemetry()).ToList());
toolsUI.setSample(sample);
Logger.Information($"build times");
Logger.Information($"-----------------------------------------");
var telemetries = buildResult.Item1
.Select(x => x.getTelemetry())
.SelectMany(x => x.ToList())
.GroupBy(x => x.Item1)
.ToImmutableSortedDictionary(x => x.Key, x => x.Sum(y => y.Item2));
foreach (var (key, millis) in telemetries)
{
Logger.Information($"{key}: {millis} ms");
}
}
}
else
@ -706,7 +712,7 @@ public class RecastDemo
io.DisplayFramebufferScale = Vector2.One;
io.DeltaTime = (float)dt;
//window.DoEvents();
_canvas.Update(dt);
_imgui.Update((float)dt);
}
@ -736,8 +742,8 @@ public class RecastDemo
dd.fog(false);
_viewSys.Draw();
_mouseOverMenu = _viewSys.IsMouseOverUI();
_canvas.Draw(dt);
_mouseOverMenu = _canvas.IsMouseOverUI();
_imgui.Render();
window.SwapBuffers();

View File

@ -22,7 +22,8 @@ using System.Collections.Generic;
using DotRecast.Detour;
using DotRecast.Recast.Demo.Draw;
using DotRecast.Recast.Demo.Geom;
using DotRecast.Recast.Demo.Settings;
using DotRecast.Recast.Demo.UI;
namespace DotRecast.Recast.Demo;

View File

@ -0,0 +1,22 @@
using System;
using System.IO;
using System.Text;
namespace DotRecast.Recast.Demo.Tools;
public class ConsoleTextWriterHook : TextWriter
{
public override Encoding Encoding => Encoding.UTF8;
private readonly Action<string> _event;
public ConsoleTextWriterHook(Action<string> relay)
{
_event = relay;
}
public override void Write(char[] buffer, int index, int count)
{
var s = new string(new Span<char>(buffer, index, count));
_event?.Invoke(s);
}
}

View File

@ -16,12 +16,12 @@ freely, subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
using Silk.NET.Windowing;
namespace DotRecast.Recast.Demo.UI;
public interface IRcView
{
void Bind(RcCanvas canvas);
bool IsMouseInside();
void Draw();
void Update(double dt);
void Draw(double dt);
}

View File

@ -16,29 +16,40 @@ freely, subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
using System.Numerics;
using ImGuiNET;
using Serilog;
using Serilog.Core;
using Silk.NET.Input;
using Silk.NET.Maths;
using Silk.NET.OpenGL;
using Silk.NET.Windowing;
namespace DotRecast.Recast.Demo.UI;
public class RcViewSystem
public class RcCanvas
{
private static readonly ILogger Logger = Log.ForContext<RecastDemo>();
private readonly IWindow _window;
private readonly IRcView[] _views;
private bool _mouseOverUI;
public bool IsMouseOverUI() => _mouseOverUI;
public RcViewSystem(IWindow window, IInputContext input, params IRcView[] views)
public Vector2D<int> Size => _window.Size;
public RcCanvas(IWindow window, params IRcView[] views)
{
_window = window;
_views = views;
foreach (var view in _views)
{
view.Bind(this);
}
// setupClipboard(window);
// glfwSetCharCallback(window, (w, codepoint) => nk_input_unicode(ctx, codepoint));
// glContext = new NuklearGL(this);
_views = views;
}
@ -86,13 +97,21 @@ public class RcViewSystem
// nk_input_end(ctx);
}
public void Draw()
public void Update(double dt)
{
foreach (var view in _views)
{
view.Update(dt);
}
}
public void Draw(double dt)
{
_mouseOverUI = false;
foreach (IRcView m in _views)
foreach (var view in _views)
{
m.Draw();
_mouseOverUI |= m.IsMouseInside();
view.Draw(dt);
_mouseOverUI |= view.IsMouseInside();
// if (_mouseOverUI)
// {
// Logger.Information("mouse hover!");

View File

@ -0,0 +1,130 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Numerics;
using System.Text;
using DotRecast.Recast.Demo.Tools;
using ImGuiNET;
namespace DotRecast.Recast.Demo.UI;
public class RcLogView : IRcView
{
private RcCanvas _canvas;
private bool _mouseInside;
private List<string> _lines = new();
private readonly ConcurrentQueue<string> _output = new();
private readonly StringBuilder _outputStringBuilder = new();
private readonly ConcurrentQueue<string> _error = new();
private readonly StringBuilder _errorStringBuilder = new();
public RcLogView()
{
Console.SetOut(new ConsoleTextWriterHook(OnOut));
Console.SetError(new ConsoleTextWriterHook(OnError));
}
private void OnOut(string log)
{
_output.Enqueue(log);
}
private void OnError(string log)
{
_error.Enqueue(log);
}
public void Clear()
{
_lines.Clear();
}
private void MergeLines(ConcurrentQueue<string> queue, StringBuilder builder)
{
while (queue.TryDequeue(out var s))
{
if (s != "\r\n")
{
builder.Append(s);
}
else
{
_lines.Add(builder.ToString());
builder.Clear();
}
}
}
public void Bind(RcCanvas canvas)
{
_canvas = canvas;
}
public void Update(double dt)
{
MergeLines(_output, _outputStringBuilder);
MergeLines(_error, _errorStringBuilder);
// buffer
if (10240 < _lines.Count)
{
_lines.RemoveRange(0, _lines.Count - 8196);
}
}
public bool IsMouseInside() => _mouseInside;
public void Draw(double dt)
{
int otherWidth = 310;
int height = 234;
var width = _canvas.Size.X - (otherWidth * 2);
//var posX = _canvas.Size.X - width;
ImGui.SetNextWindowPos(new Vector2(otherWidth, _canvas.Size.Y - height));
ImGui.SetNextWindowSize(new Vector2(width, height));
if (!ImGui.Begin("Log", ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoResize))
{
ImGui.End();
return;
}
if (ImGui.BeginChild("scrolling", Vector2.Zero, false, ImGuiWindowFlags.HorizontalScrollbar))
{
_mouseInside = ImGui.IsWindowHovered();
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, Vector2.Zero);
unsafe
{
var clipper = new ImGuiListClipperPtr(ImGuiNative.ImGuiListClipper_ImGuiListClipper());
clipper.Begin(_lines.Count);
while (clipper.Step())
{
for (int lineNo = clipper.DisplayStart; lineNo < clipper.DisplayEnd; lineNo++)
{
ImGui.TextUnformatted(_lines[lineNo]);
}
}
clipper.End();
clipper.Destroy();
}
ImGui.PopStyleVar();
if (ImGui.GetScrollY() >= ImGui.GetScrollMaxY())
{
ImGui.SetScrollHereY(1.0f);
}
}
ImGui.EndChild();
ImGui.End();
}
}

View File

@ -20,13 +20,14 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using DotRecast.Core;
using DotRecast.Recast.Demo.Draw;
using DotRecast.Recast.Demo.UI;
using ImGuiNET;
using Silk.NET.Windowing;
namespace DotRecast.Recast.Demo.Settings;
namespace DotRecast.Recast.Demo.UI;
public class RcSettingsView : IRcView
{
@ -63,7 +64,6 @@ public class RcSettingsView : IRcView
// public readonly NkColor transparent = NkColor.create();
private bool buildTriggered;
private long buildTime;
private Dictionary<string, long> telemetries = new();
private readonly int[] voxels = new int[2];
private readonly int[] tiles = new int[2];
private int maxTiles;
@ -77,14 +77,32 @@ public class RcSettingsView : IRcView
private bool _mouseInside;
public bool IsMouseInside() => _mouseInside;
public void Draw()
private RcCanvas _canvas;
public void Bind(RcCanvas canvas)
{
_canvas = canvas;
}
public void Update(double dt)
{
ImGui.Begin("Properties");
_mouseInside = ImGui.IsWindowHovered();
}
public void Draw(double dt)
{
int width = 310;
var posX = _canvas.Size.X - width;
ImGui.SetNextWindowPos(new Vector2(posX, 0));
ImGui.SetNextWindowSize(new Vector2(width, _canvas.Size.Y));
ImGui.Begin("Properties", ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoResize);
_mouseInside = ImGui.IsWindowHovered();
ImGui.Text("Input Mesh");
ImGui.Separator();
const string strLoadSourceGeom = "Load Source Geom...";
if (ImGui.Button(strLoadSourceGeom))
{
@ -101,13 +119,14 @@ public class RcSettingsView : IRcView
meshInputFilePath = picker.SelectedFile;
ImFilePicker.RemoveFilePicker(strLoadSourceGeom);
}
ImGui.EndPopup();
}
else
{
meshInputTrigerred = false;
}
ImGui.Text($"Verts: {voxels[0]} Tris: {voxels[1]}");
ImGui.NewLine();
@ -142,7 +161,7 @@ public class RcSettingsView : IRcView
ImGui.RadioButton(label, ref partitioningIdx, partition.Idx);
});
ImGui.NewLine();
ImGui.Text("Filtering");
ImGui.Separator();
ImGui.Checkbox("Low Hanging Obstacles", ref filterLowHangingObstacles);
@ -162,7 +181,7 @@ public class RcSettingsView : IRcView
ImGui.SliderFloat("Sample Distance", ref detailSampleDist, 0f, 16f, "%.1f");
ImGui.SliderFloat("Max Sample Error", ref detailSampleMaxError, 0f, 16f, "%.1f");
ImGui.NewLine();
ImGui.Text("Tiling");
ImGui.Separator();
ImGui.Checkbox("Enable", ref tiled);
@ -171,18 +190,16 @@ public class RcSettingsView : IRcView
if (0 < (tileSize % 16))
tileSize = tileSize + (16 - (tileSize % 16));
ImGui.SliderInt("Tile Size", ref tileSize, 16, 1024);
ImGui.Text($"Tiles {tiles[0]} x {tiles[1]}");
ImGui.Text($"Max Tiles {maxTiles}");
ImGui.Text($"Max Polys {maxPolys}");
}
ImGui.NewLine();
ImGui.Text($"Build Time: {buildTime} ms");
foreach (var (key, millis) in telemetries)
{
ImGui.Text($"{key}: {millis} ms");
}
ImGui.Separator();
buildTriggered = ImGui.Button("Build");
const string strLoadNavMesh = "Load Nav Mesh...";
@ -200,20 +217,18 @@ public class RcSettingsView : IRcView
Console.WriteLine(picker.SelectedFile);
ImFilePicker.RemoveFilePicker(strLoadNavMesh);
}
ImGui.EndPopup();
}
ImGui.NewLine();
ImGui.Text("Draw");
ImGui.Separator();
DrawMode.Values.forEach(dm =>
{
ImGui.RadioButton(dm.Text, ref drawMode, dm.Idx);
});
DrawMode.Values.forEach(dm => { ImGui.RadioButton(dm.Text, ref drawMode, dm.Idx); });
ImGui.NewLine();
ImGui.End();
}
@ -286,16 +301,7 @@ public class RcSettingsView : IRcView
{
this.buildTime = buildTime;
}
public void setBuildTelemetry(IList<Telemetry> telemetries)
{
this.telemetries = telemetries
.SelectMany(x => x.ToList())
.GroupBy(x => x.Item1)
.ToDictionary(x => x.Key, x => x.Sum(y => y.Item2));
}
public DrawMode getDrawMode()
{
return DrawMode.Values[drawMode];

View File

@ -17,12 +17,13 @@ freely, subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
using System.Numerics;
using DotRecast.Core;
using DotRecast.Recast.Demo.Tools;
using DotRecast.Recast.Demo.UI;
using ImGuiNET;
using Silk.NET.Windowing;
namespace DotRecast.Recast.Demo.Tools;
namespace DotRecast.Recast.Demo.UI;
public class ToolsView : IRcView
{
@ -36,22 +37,38 @@ public class ToolsView : IRcView
{
this.tools = tools;
}
private bool _mouseInside;
public bool IsMouseInside() => _mouseInside;
public void Draw()
private RcCanvas _canvas;
public void Bind(RcCanvas canvas)
{
_canvas = canvas;
}
public void Update(double dt)
{
ImGui.Begin("Tools");
_mouseInside = ImGui.IsWindowHovered();
}
public void Draw(double dt)
{
int width = 310;
ImGui.SetNextWindowPos(new Vector2(0, 0));
ImGui.SetNextWindowSize(new Vector2(width, _canvas.Size.Y));
ImGui.Begin("Tools", ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoResize);
_mouseInside = ImGui.IsWindowHovered();
for (int i = 0; i < tools.Length; ++i)
{
var tool = tools[i];
ImGui.RadioButton(tool.getName(), ref _currentToolIdx, i);
}
ImGui.NewLine();
if (0 > _currentToolIdx || _currentToolIdx >= tools.Length)
{
ImGui.End();