diff --git a/src/Box2D.NET.Samples/SampleApp.cs b/src/Box2D.NET.Samples/SampleApp.cs index b14a2178..0a93eac5 100644 --- a/src/Box2D.NET.Samples/SampleApp.cs +++ b/src/Box2D.NET.Samples/SampleApp.cs @@ -114,15 +114,18 @@ public int Run(string[] args) Monitor* primaryMonitor = _context.glfw.GetPrimaryMonitor(); if (null != primaryMonitor) { + float contentScale = 1.0f; + _context.glfw.GetMonitorContentScale(primaryMonitor, out contentScale, out contentScale); + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { - _context.glfw.GetMonitorContentScale(primaryMonitor, out s_framebufferScale, out s_framebufferScale); + _context.uiScale = 1.0f; + s_framebufferScale = contentScale; } else { - float uiScale = 1.0f; - _context.glfw.GetMonitorContentScale(primaryMonitor, out uiScale, out uiScale); - _context.uiScale = uiScale; + _context.uiScale = contentScale; + s_framebufferScale = 1.0f; } } } @@ -288,26 +291,27 @@ private void OnWindowUpdate(double dt) int bufferWidth = 0; int bufferHeight = 0; - double cursorPosX = 0.0d; - double cursorPosY = 0.0d; unsafe { _context.glfw.GetFramebufferSize(_context.window, out bufferWidth, out bufferHeight); // _ctx.draw.DrawBackground(); - - _context.glfw.GetCursorPos(_context.window, out cursorPosX, out cursorPosY); } - // ImGui_ImplGlfw_CursorPosCallback(_ctx.g_mainWindow, cursorPosX / s_windowScale, cursorPosY / s_windowScale); - // ImGui_ImplOpenGL3_NewFrame(); - // ImGui_ImplGlfw_NewFrame(); - // ImGui_ImplGlfw_CursorPosCallback(_ctx.g_mainWindow, cursorPosX / s_windowScale, cursorPosY / s_windowScale); if (null != _imgui) { var io = ImGui.GetIO(); io.DisplaySize = new Vector2(_context.camera.width, _context.camera.height); - io.DisplayFramebufferScale = new Vector2(bufferWidth / (float)_context.camera.width, bufferHeight / (float)_context.camera.height); + + // These can be zero if the window is minimized + if (_context.camera.width > 0.0f && _context.camera.height > 0.0f) + { + // Framebuffer/window ratio: 1 on Windows/Linux, 2 on a Retina display. Drives + // both UI magnification and font rasterizer density. + io.DisplayFramebufferScale = new Vector2(bufferWidth / (float)_context.camera.width, + bufferHeight / (float)_context.camera.height); + } + io.DeltaTime = (float)dt; _imgui.Update((float)dt); } @@ -319,20 +323,6 @@ private void OnWindowUpdate(double dt) } _context.sample.ResetText(); - - if (_context.showUI) - { - _context.sample.DrawColoredTextLine(B2HexColor.b2_colorGoldenRod, SampleFactory.Shared.GetName(_context.sampleIndex)); - _context.sample.DrawColoredTextLine(B2HexColor.b2_colorLightGray, SampleFactory.Shared.GetCategory(_context.sampleIndex)); - _context.sample.DrawTextLine(""); - _context.sample.DrawColoredTextLine(B2HexColor.b2_colorSeaGreen, $"{1000.0f * _frameTime:0.0} ms"); - _context.sample.DrawColoredTextLine(B2HexColor.b2_colorSeaGreen, $"step {_context.sample.m_stepCount}"); - _context.sample.DrawTextLine(""); - _context.sample.DrawColoredTextLine(B2HexColor.b2_colorSeaGreen, - $"cam ({_context.camera.center.X:0.0}, {_context.camera.center.Y:0.0})"); - _context.sample.DrawColoredTextLine(B2HexColor.b2_colorSeaGreen, $"zoom {_context.camera.zoom:0.00}"); - } - _context.sample.Step(); _context.sample.Draw(); } @@ -353,18 +343,9 @@ private void OnWindowRender(double dt) { _context.gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); - if (_context.showUI == false) - { - float fontSize = ImGui.GetFontSize(); - DrawScreenString(_context.draw, 5.0f, 1.5f * fontSize, B2HexColor.b2_colorYellow, - $"{SampleFactory.Shared.GetCategory(_context.sampleIndex)} : {SampleFactory.Shared.GetName(_context.sampleIndex)}"); - DrawScreenString(_context.draw, 5.0f, _context.camera.height - 0.5f * fontSize, B2HexColor.b2_colorSeaGreen, - $"{1000.0f * _frameTime:0.0} ms step {_context.sample.m_stepCount}"); - } - FlushDraw(_context.draw, _context.camera); - UpdateSampleUI(_context); + DrawUI(_context, _frameTime); //ImGui.ShowDemoWindow(); @@ -541,7 +522,7 @@ private void CreateUI(string glslVersion) // } // - if (_context.uiScale != 1.0f) + if (_context.uiScale != 1.0f || s_framebufferScale != 1.0f) { // ImGui.NET 1.90 does not expose AddFontDefaultVector, so use the existing font as an embedded resource. using Stream stream = typeof(SampleApp).Assembly.GetManifestResourceStream("Box2D.NET.Samples.Fonts.droid_sans.ttf")!; @@ -556,8 +537,11 @@ private void CreateUI(string glslVersion) { ApplyUIStyle(); + ImGuiStylePtr style = ImGui.GetStyle(); + style.ScaleAllSizes(_context.uiScale); + ImGuiIOPtr io = ImGui.GetIO(); - if (_context.uiScale == 1.0f) + if (_context.uiScale == 1.0f && s_framebufferScale == 1.0f) { io.Fonts.AddFontDefault(); } @@ -566,21 +550,15 @@ private void CreateUI(string glslVersion) unsafe { ImFontConfigPtr fontConfig = new ImFontConfigPtr(ImGuiNative.ImFontConfig_ImFontConfig()); - // This brightens the font, improving readability when it is small. - fontConfig.RasterizerMultiply = _context.uiScale * s_framebufferScale; fontConfig.FontDataOwnedByAtlas = false; - float regularSize = MathF.Floor(13.0f * _context.uiScale); + float regularSize = MathF.Floor(13.0f * _context.uiScale * s_framebufferScale); io.Fonts.AddFontFromMemoryTTF(_fontDataHandle.AddrOfPinnedObject(), _fontData.Length, regularSize, fontConfig); + io.FontGlobalScale = 1.0f / s_framebufferScale; ImGuiNative.ImFontConfig_destroy(fontConfig.NativePtr); } } }); - - if (_context.uiScale != 1.0f) - { - ImGui.GetStyle().ScaleAllSizes(_context.uiScale); - } } public void DestroyUI() @@ -619,58 +597,20 @@ private unsafe void KeyCallback(WindowHandle* window, Keys key, int scancode, In case Keys.Left: // Pan left - if (0 != ((uint)mods & (uint)KeyModifiers.Control)) - { - B2Vec2 newOrigin = new B2Vec2(2.0f, 0.0f); - _context.sample.ShiftOrigin(newOrigin); - } - else - { - _context.camera.center.X -= 0.5f; - } - + _context.camera.center.X -= 0.5f; break; case Keys.Right: // Pan right - if (0 != ((uint)mods & (uint)KeyModifiers.Control)) - { - B2Vec2 newOrigin = new B2Vec2(-2.0f, 0.0f); - _context.sample.ShiftOrigin(newOrigin); - } - else - { - _context.camera.center.X += 0.5f; - } - + _context.camera.center.X += 0.5f; break; case Keys.Down: - // Pan down - if (0 != ((uint)mods & (uint)KeyModifiers.Control)) - { - B2Vec2 newOrigin = new B2Vec2(0.0f, 2.0f); - _context.sample.ShiftOrigin(newOrigin); - } - else - { - _context.camera.center.Y -= 0.5f; - } - + _context.camera.center.Y -= 0.5f; break; case Keys.Up: - // Pan up - if (0 != ((uint)mods & (uint)KeyModifiers.Control)) - { - B2Vec2 newOrigin = new B2Vec2(0.0f, -2.0f); - _context.sample.ShiftOrigin(newOrigin); - } - else - { - _context.camera.center.Y += 0.5f; - } - + _context.camera.center.Y += 0.5f; break; case Keys.Home: @@ -730,7 +670,7 @@ private unsafe void KeyCallback(WindowHandle* window, Keys key, int scancode, In break; case Keys.M: - _context.showDiagnostics = !_context.showDiagnostics; + _context.showMetrics = !_context.showMetrics; break; default: diff --git a/src/Box2D.NET.Samples/SampleContext.cs b/src/Box2D.NET.Samples/SampleContext.cs index dfd32457..1de0fd2d 100644 --- a/src/Box2D.NET.Samples/SampleContext.cs +++ b/src/Box2D.NET.Samples/SampleContext.cs @@ -44,7 +44,7 @@ public class SampleContext public bool showUI = true; // Diagnostics drawer visibility. D toggles. - public bool showDiagnostics = false; + public bool showMetrics = false; // Set by Ctrl+O; consumed by UpdateSampleUI to open the fuzzy sample picker. public bool openSamplePicker = false; @@ -95,7 +95,7 @@ public void Load() sampleIndex = settings.sampleIndex; debugDraw.drawShapes = settings.drawShapes; debugDraw.drawJoints = settings.drawJoints; - showDiagnostics = settings.showDiagnostics; + showMetrics = settings.showDiagnostics; } diff --git a/src/Box2D.NET.Samples/SampleText.cs b/src/Box2D.NET.Samples/SampleText.cs index 0a360d41..c12250fc 100644 --- a/src/Box2D.NET.Samples/SampleText.cs +++ b/src/Box2D.NET.Samples/SampleText.cs @@ -7,7 +7,7 @@ namespace Box2D.NET.Samples; public static class SampleText { - public static string FormatFloat(float value) + public static string FormatFloat(float value, int precision = 6) { if (float.IsNaN(value)) { @@ -25,6 +25,6 @@ public static string FormatFloat(float value) } // C printf("%g") defaults to six significant digits and is not affected by the current .NET culture. - return value.ToString("g6", CultureInfo.InvariantCulture); + return value.ToString($"g{precision}", CultureInfo.InvariantCulture); } } diff --git a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkBarrel.cs b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkBarrel.cs index 864f761e..7b23154f 100644 --- a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkBarrel.cs +++ b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkBarrel.cs @@ -302,7 +302,7 @@ void CreateScene() } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -327,5 +327,7 @@ public override void BuildSamplePanel() } + + return true; } } diff --git a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkCast.cs b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkCast.cs index b6f094e5..de4dbfc1 100644 --- a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkCast.cs +++ b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkCast.cs @@ -17,6 +17,7 @@ using static Box2D.NET.B2Timers; using static Box2D.NET.B2Distances; using static Box2D.NET.Samples.Graphics.Draws; +using static Box2D.NET.Samples.SampleText; namespace Box2D.NET.Samples.Samples.Benchmarks; @@ -321,7 +322,7 @@ public override void Step() } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -387,25 +388,27 @@ public override void BuildSamplePanel() { BuildScene(); } + + return true; } public override void Draw() { base.Draw(); - DrawTextLine($"build time ms = {m_buildTime:g}"); + DrawScreenTextLine($"build time ms = {FormatFloat(m_buildTime)}"); DrawScreenTextLine($"hit count = {hitCount}, node visits = {nodeVisits}, leaf visits = {leafVisits}"); - DrawTextLine($"total ms = {ms:F3}"); + DrawScreenTextLine(System.FormattableString.Invariant($"total ms = {ms:F3}")); - DrawTextLine($"min total ms = {m_minTime:F3}"); + DrawScreenTextLine(System.FormattableString.Invariant($"min total ms = {m_minTime:F3}")); float aveRayCost = 1000.0f * m_minTime / (float)sampleCount; - DrawTextLine($"average us = {aveRayCost:F2}"); + DrawScreenTextLine(System.FormattableString.Invariant($"average us = {aveRayCost:F2}")); } } diff --git a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkManyTumblers.cs b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkManyTumblers.cs index 9cf6433d..52d08c8b 100644 --- a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkManyTumblers.cs +++ b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkManyTumblers.cs @@ -138,7 +138,7 @@ void CreateScene() m_bodyIndex = 0; } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); @@ -163,6 +163,8 @@ public override void BuildSamplePanel() ImGui.PopItemWidth(); + + return true; } public override void Step() @@ -189,4 +191,4 @@ public override void Step() } } } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkShapeDistance.cs b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkShapeDistance.cs index bd297931..cd9ac75c 100644 --- a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkShapeDistance.cs +++ b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkShapeDistance.cs @@ -98,11 +98,13 @@ public override void Dispose() m_outputs = null; } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); ImGui.SliderInt("draw index", ref m_drawIndex, 0, m_count - 1); ImGui.PopItemWidth(); + + return true; } public override void Step() @@ -139,9 +141,9 @@ public override void Draw() if (m_context.pause == false || m_context.singleStep == true) { - DrawTextLine($"count = {m_count}"); + DrawScreenTextLine($"count = {m_count}"); DrawScreenTextLine($"min ms = {FormatFloat(m_minMilliseconds)}, ave us = {FormatFloat(1000.0f * m_minMilliseconds / (float)m_count)}"); - DrawTextLine($"average iterations = {totalIterations / (float)m_count}"); + DrawScreenTextLine($"average iterations = {FormatFloat(totalIterations / (float)m_count)}"); } B2Transform xfA = m_transformAs[m_drawIndex]; @@ -153,6 +155,6 @@ public override void Draw() DrawPoint(m_draw, output.pointA, 10.0f, B2HexColor.b2_colorWhite); DrawPoint(m_draw, output.pointB, 10.0f, B2HexColor.b2_colorWhite); DrawLine(m_draw, output.pointA, output.pointA + 0.5f * output.normal, B2HexColor.b2_colorYellow); - DrawTextLine($"distance = {output.distance}"); + DrawScreenTextLine($"distance = {FormatFloat(output.distance)}"); } } diff --git a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSleep.cs b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSleep.cs index f09e2e8a..196e06e9 100644 --- a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSleep.cs +++ b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSleep.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2025 Erin Catto +// SPDX-FileCopyrightText: 2025 Erin Catto // SPDX-FileCopyrightText: 2025 Ikpil Choi(ikpil@naver.com) // SPDX-License-Identifier: MIT @@ -9,6 +9,7 @@ using static Box2D.NET.B2Timers; using static Box2D.NET.B2Diagnostics; using static Box2D.NET.B2Joints; +using static Box2D.NET.Samples.SampleText; namespace Box2D.NET.Samples.Samples.Benchmarks; @@ -127,7 +128,7 @@ public override void Draw() base.Draw(); int count = m_stepCount - 20; - DrawTextLine($"wake ave = {m_wakeTotal / count:g} ms"); - DrawTextLine($"sleep ave = {m_sleepTotal / count:g} ms"); + DrawScreenTextLine($"wake ave = {FormatFloat(m_wakeTotal / count)} ms"); + DrawScreenTextLine($"sleep ave = {FormatFloat(m_sleepTotal / count)} ms"); } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSmash.cs b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSmash.cs index d7fc6ef5..bbd8f567 100644 --- a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSmash.cs +++ b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSmash.cs @@ -54,7 +54,7 @@ private void CreateScene() } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -80,5 +80,7 @@ public override void BuildSamplePanel() } + + return true; } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSpinner.cs b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSpinner.cs index 5d3f96ac..419d3402 100644 --- a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSpinner.cs +++ b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSpinner.cs @@ -46,6 +46,6 @@ public override void Draw() { base.Draw(); - //DrawTextLine($"toi calls, hits = {b2_toiCalls}, {b2_toiHitCount}"); + // DrawScreenTextLine($"toi calls, hits = {b2_toiCalls}, {b2_toiHitCount}"); } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkWasher.cs b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkWasher.cs index fd70ee88..531c0a1c 100644 --- a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkWasher.cs +++ b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkWasher.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2025 Erin Catto +// SPDX-FileCopyrightText: 2025 Erin Catto // SPDX-FileCopyrightText: 2025 Ikpil Choi(ikpil@naver.com) // SPDX-License-Identifier: MIT @@ -32,6 +32,6 @@ public override void Step() base.Step(); B2ContactEvents events = b2World_GetContactEvents(m_worldId); - DrawTextLine($"hits = {events.hitCount}"); + DrawScreenTextLine($"hits = {events.hitCount}"); } } diff --git a/src/Box2D.NET.Samples/Samples/Bodies/BodyType.cs b/src/Box2D.NET.Samples/Samples/Bodies/BodyType.cs index a23475ba..b4edc889 100644 --- a/src/Box2D.NET.Samples/Samples/Bodies/BodyType.cs +++ b/src/Box2D.NET.Samples/Samples/Bodies/BodyType.cs @@ -220,7 +220,7 @@ public BodyType(SampleContext context) : base(context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -276,6 +276,8 @@ public override void BuildSamplePanel() } + + return true; } public override void Step() @@ -295,4 +297,4 @@ public override void Step() base.Step(); } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Bodies/SetVelocity.cs b/src/Box2D.NET.Samples/Samples/Bodies/SetVelocity.cs index f896c8f2..9785d4af 100644 --- a/src/Box2D.NET.Samples/Samples/Bodies/SetVelocity.cs +++ b/src/Box2D.NET.Samples/Samples/Bodies/SetVelocity.cs @@ -6,6 +6,7 @@ using static Box2D.NET.B2Types; using static Box2D.NET.B2Bodies; using static Box2D.NET.B2Shapes; +using static Box2D.NET.Samples.SampleText; namespace Box2D.NET.Samples.Samples.Bodies; @@ -61,6 +62,6 @@ public override void Draw() { base.Draw(); B2Vec2 position = b2Body_GetPosition(m_bodyId); - DrawTextLine($"(x, y) = {position.X:G}, {position.Y:G})"); + DrawScreenTextLine($"(x, y) = ({FormatFloat(position.X, 2)}, {FormatFloat(position.Y, 2)})"); } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Bodies/Sleep.cs b/src/Box2D.NET.Samples/Samples/Bodies/Sleep.cs index a259c261..acc34e6a 100644 --- a/src/Box2D.NET.Samples/Samples/Bodies/Sleep.cs +++ b/src/Box2D.NET.Samples/Samples/Bodies/Sleep.cs @@ -171,7 +171,7 @@ void ToggleInvoker() } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -212,6 +212,8 @@ public override void BuildSamplePanel() } + + return true; } public override void Step() @@ -260,7 +262,7 @@ public override void Draw() for (int i = 0; i < 2; ++i) { - DrawTextLine($"sensor touch {i} = {m_sensorTouching[i]}"); + DrawScreenTextLine($"sensor touch {i} = {(m_sensorTouching[i] ? "true" : "false")}"); } } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Bodies/WakeTouching.cs b/src/Box2D.NET.Samples/Samples/Bodies/WakeTouching.cs index 7f0170d1..ad277b75 100644 --- a/src/Box2D.NET.Samples/Samples/Bodies/WakeTouching.cs +++ b/src/Box2D.NET.Samples/Samples/Bodies/WakeTouching.cs @@ -64,7 +64,7 @@ public WakeTouching(SampleContext context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -74,5 +74,7 @@ public override void BuildSamplePanel() } + + return true; } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Bodies/Weeble.cs b/src/Box2D.NET.Samples/Samples/Bodies/Weeble.cs index 2116f325..0d20ba25 100644 --- a/src/Box2D.NET.Samples/Samples/Bodies/Weeble.cs +++ b/src/Box2D.NET.Samples/Samples/Bodies/Weeble.cs @@ -91,7 +91,7 @@ static float RestitutionCallback(float restitutionA, ulong materialA, float rest } - public override void BuildSamplePanel() + public override bool DrawControls() { if (ImGui.Button("Teleport")) @@ -115,6 +115,8 @@ public override void BuildSamplePanel() ImGui.PopItemWidth(); + + return true; } public override void Draw() @@ -134,4 +136,4 @@ public override void Draw() DrawLine(m_draw, worldPoint, worldPoint + v1, B2HexColor.b2_colorRed); DrawLine(m_draw, worldPoint + offset, worldPoint + v2 + offset, B2HexColor.b2_colorGreen); } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Characters/Mover.cs b/src/Box2D.NET.Samples/Samples/Characters/Mover.cs index 39f0e56c..4a11c7fe 100644 --- a/src/Box2D.NET.Samples/Samples/Characters/Mover.cs +++ b/src/Box2D.NET.Samples/Samples/Characters/Mover.cs @@ -459,7 +459,7 @@ void SolveMove(float timeStep, float throttle) m_velocity = b2ClipVector(m_velocity, m_planes, m_planeCount); } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.TextUnformatted("Mover"); ImGui.Spacing(); @@ -489,6 +489,8 @@ public override void BuildSamplePanel() ImGui.RadioButton("Segment", ref m_pogoShape, (int)PogoShape.PogoSegment); ImGui.Checkbox("Lock Camera", ref m_lockCamera); + + return true; } static bool PlaneResultFcn(B2ShapeId shapeId, ref B2PlaneResult planeResult, object context) @@ -633,9 +635,9 @@ public override void Draw() } B2Vec2 p = m_transform.p; - DrawTextLine($"position {p.X:F2} {p.Y:F2}"); - DrawTextLine($"velocity {m_velocity.X:F2}, {m_velocity.Y:F2}"); - DrawTextLine($"iterations {m_totalIterations}"); + DrawScreenTextLine(FormattableString.Invariant($"position {p.X:F2} {p.Y:F2}")); + DrawScreenTextLine(FormattableString.Invariant($"velocity {m_velocity.X:F2} {m_velocity.Y:F2}")); + DrawScreenTextLine($"iterations {m_totalIterations}"); if (m_lockCamera) { diff --git a/src/Box2D.NET.Samples/Samples/Collisions/CastWorld.cs b/src/Box2D.NET.Samples/Samples/Collisions/CastWorld.cs index 3d243cf1..37a31088 100644 --- a/src/Box2D.NET.Samples/Samples/Collisions/CastWorld.cs +++ b/src/Box2D.NET.Samples/Samples/Collisions/CastWorld.cs @@ -297,7 +297,7 @@ public override void MouseMove(B2Vec2 p) } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -368,6 +368,8 @@ public override void BuildSamplePanel() { DestroyBody(); } + + return true; } public override void Step() diff --git a/src/Box2D.NET.Samples/Samples/Collisions/DynamicTree.cs b/src/Box2D.NET.Samples/Samples/Collisions/DynamicTree.cs index 14dc28ef..2beca3d6 100644 --- a/src/Box2D.NET.Samples/Samples/Collisions/DynamicTree.cs +++ b/src/Box2D.NET.Samples/Samples/Collisions/DynamicTree.cs @@ -188,7 +188,7 @@ void BuildTree() } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -257,6 +257,8 @@ public override void BuildSamplePanel() { BuildTree(); } + + return true; } public override void MouseDown(B2Vec2 p, MouseButton button, KeyModifiers mods) @@ -448,19 +450,19 @@ public override void Draw() { case UpdateType.Update_Incremental: { - DrawTextLine($"incremental : {_ms:F3} ms"); + DrawScreenTextLine(System.FormattableString.Invariant($"incremental : {_ms:F3} ms")); } break; case UpdateType.Update_FullRebuild: { - DrawTextLine($"full build {_boxCount} : {_ms:F3} ms"); + DrawScreenTextLine(System.FormattableString.Invariant($"full build {_boxCount} : {_ms:F3} ms")); } break; case UpdateType.Update_PartialRebuild: { - DrawTextLine($"partial rebuild {_boxCount} : {_ms:F3} ms"); + DrawScreenTextLine(System.FormattableString.Invariant($"partial rebuild {_boxCount} : {_ms:F3} ms")); } break; diff --git a/src/Box2D.NET.Samples/Samples/Collisions/Manifold.cs b/src/Box2D.NET.Samples/Samples/Collisions/Manifold.cs index d790d7f2..9ccdb025 100644 --- a/src/Box2D.NET.Samples/Samples/Collisions/Manifold.cs +++ b/src/Box2D.NET.Samples/Samples/Collisions/Manifold.cs @@ -86,7 +86,7 @@ public Manifold(SampleContext context) : base(context) m_wedge = b2ComputeHull(points, 3); } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -125,6 +125,8 @@ public override void BuildSamplePanel() ImGui.Text("mouse button 1 + shift: rotate"); + + return true; } public override void MouseDown(B2Vec2 p, MouseButton button, KeyModifiers mods) @@ -699,4 +701,4 @@ public override void Step() } #endif } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Collisions/OverlapWorld.cs b/src/Box2D.NET.Samples/Samples/Collisions/OverlapWorld.cs index fb7d6e45..b516dbad 100644 --- a/src/Box2D.NET.Samples/Samples/Collisions/OverlapWorld.cs +++ b/src/Box2D.NET.Samples/Samples/Collisions/OverlapWorld.cs @@ -266,7 +266,7 @@ public override void MouseMove(B2Vec2 p) } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -324,6 +324,8 @@ public override void BuildSamplePanel() ImGui.RadioButton("Box##Overlap", ref m_shapeType, e_boxShape); + + return true; } public override void Step() diff --git a/src/Box2D.NET.Samples/Samples/Collisions/RayCast.cs b/src/Box2D.NET.Samples/Samples/Collisions/RayCast.cs index 5527b5cb..4325d288 100644 --- a/src/Box2D.NET.Samples/Samples/Collisions/RayCast.cs +++ b/src/Box2D.NET.Samples/Samples/Collisions/RayCast.cs @@ -80,7 +80,7 @@ public RayCast(SampleContext context) : base(context) m_showFraction = false; } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -114,6 +114,8 @@ public override void BuildSamplePanel() ImGui.Text("mouse btn 1 + shft: translate"); ImGui.Text("mouse btn 1 + ctrl: rotate"); + + return true; } public override void MouseDown(B2Vec2 p, MouseButton button, KeyModifiers mods) diff --git a/src/Box2D.NET.Samples/Samples/Collisions/ShapeCast.cs b/src/Box2D.NET.Samples/Samples/Collisions/ShapeCast.cs index 00234fa7..35a5c71b 100644 --- a/src/Box2D.NET.Samples/Samples/Collisions/ShapeCast.cs +++ b/src/Box2D.NET.Samples/Samples/Collisions/ShapeCast.cs @@ -298,7 +298,7 @@ public override void MouseMove(B2Vec2 p) } } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); string[] shapeTypes = { "point", "segment", "triangle", "box" }; @@ -342,6 +342,8 @@ public override void BuildSamplePanel() ImGui.Checkbox("show indices", ref m_showIndices); ImGui.Checkbox("encroach", ref m_encroach); + + return true; } public override void Step() diff --git a/src/Box2D.NET.Samples/Samples/Collisions/ShapeDistance.cs b/src/Box2D.NET.Samples/Samples/Collisions/ShapeDistance.cs index 55b4d0f0..f839b39d 100644 --- a/src/Box2D.NET.Samples/Samples/Collisions/ShapeDistance.cs +++ b/src/Box2D.NET.Samples/Samples/Collisions/ShapeDistance.cs @@ -212,7 +212,7 @@ void DrawShape(ShapeType type, in B2Transform transform, float radius, B2HexColo } } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); string[] shapeTypes = ["point", "segment", "triangle", "box"]; @@ -271,6 +271,8 @@ public override void BuildSamplePanel() m_simplexIndex = b2ClampInt(m_simplexIndex, 0, m_simplexCount - 1); ImGui.PopItemWidth(); } + + return true; } public override void MouseDown(B2Vec2 p, MouseButton button, KeyModifiers mods) @@ -445,11 +447,11 @@ public override void Draw() if (m_cache.count == 1) { - DrawTextLine($"cache = {{{m_cache.indexA[0]}}}, {{{m_cache.indexB[0]}}}"); + DrawScreenTextLine($"cache = {{{m_cache.indexA[0]}}}, {{{m_cache.indexB[0]}}}"); } else if (m_cache.count == 2) { - DrawTextLine($"cache = {{{m_cache.indexA[0]}, {m_cache.indexA[1]}}}, {{{m_cache.indexB[0]}, {m_cache.indexB[1]}}}"); + DrawScreenTextLine($"cache = {{{m_cache.indexA[0]}, {m_cache.indexA[1]}}}, {{{m_cache.indexB[0]}, {m_cache.indexB[1]}}}"); } else if (m_cache.count == 3) { diff --git a/src/Box2D.NET.Samples/Samples/Collisions/SmoothManifold.cs b/src/Box2D.NET.Samples/Samples/Collisions/SmoothManifold.cs index 482d6c5b..d7fc7149 100644 --- a/src/Box2D.NET.Samples/Samples/Collisions/SmoothManifold.cs +++ b/src/Box2D.NET.Samples/Samples/Collisions/SmoothManifold.cs @@ -133,7 +133,7 @@ public SmoothManifold(SampleContext context) : base(context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); @@ -172,6 +172,8 @@ public override void BuildSamplePanel() ImGui.Text("mouse button 1: drag"); ImGui.Text("mouse button 1 + shift: rotate"); + + return true; } public override void MouseDown(B2Vec2 p, MouseButton button, KeyModifiers mods) diff --git a/src/Box2D.NET.Samples/Samples/Collisions/TimeOfImpact.cs b/src/Box2D.NET.Samples/Samples/Collisions/TimeOfImpact.cs index 6eeb8042..5dbb39c4 100644 --- a/src/Box2D.NET.Samples/Samples/Collisions/TimeOfImpact.cs +++ b/src/Box2D.NET.Samples/Samples/Collisions/TimeOfImpact.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2025 Erin Catto +// SPDX-FileCopyrightText: 2025 Erin Catto // SPDX-FileCopyrightText: 2025 Ikpil Choi(ikpil@naver.com) // SPDX-License-Identifier: MIT @@ -6,6 +6,7 @@ using static Box2D.NET.B2Distances; using static Box2D.NET.B2Constants; using static Box2D.NET.Samples.Graphics.Draws; +using static Box2D.NET.Samples.SampleText; namespace Box2D.NET.Samples.Samples.Collisions; @@ -73,7 +74,7 @@ public override void Draw() { base.Draw(); - DrawTextLine($"toi = {_output.fraction:g}"); + DrawScreenTextLine($"toi = {FormatFloat(_output.fraction)}"); B2Vec2[] vertices = new B2Vec2[B2_MAX_POLYGON_VERTICES]; @@ -126,7 +127,7 @@ public override void Draw() distanceInput.useRadii = false; B2SimplexCache cache = new B2SimplexCache(); B2DistanceOutput distanceOutput = b2ShapeDistance(ref distanceInput, ref cache, null, 0); - DrawTextLine($"distance = {distanceOutput.distance}:g"); + DrawScreenTextLine($"distance = {FormatFloat(distanceOutput.distance)}"); } diff --git a/src/Box2D.NET.Samples/Samples/Continuous/BounceHouse.cs b/src/Box2D.NET.Samples/Samples/Continuous/BounceHouse.cs index 87caffa2..5aeaa504 100644 --- a/src/Box2D.NET.Samples/Samples/Continuous/BounceHouse.cs +++ b/src/Box2D.NET.Samples/Samples/Continuous/BounceHouse.cs @@ -125,7 +125,7 @@ void Launch() } } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); string[] shapeTypes = { "Circle", "Capsule", "Box" }; @@ -143,6 +143,8 @@ public override void BuildSamplePanel() } + + return true; } public override void Step() diff --git a/src/Box2D.NET.Samples/Samples/Continuous/ChainDrop.cs b/src/Box2D.NET.Samples/Samples/Continuous/ChainDrop.cs index 2535acee..5926ef31 100644 --- a/src/Box2D.NET.Samples/Samples/Continuous/ChainDrop.cs +++ b/src/Box2D.NET.Samples/Samples/Continuous/ChainDrop.cs @@ -85,7 +85,7 @@ void Launch() //m_shapeId = b2CreatePolygonShape( m_bodyId, &shapeDef, &box ); } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); ImGui.SliderFloat("Speed", ref m_speed, -100.0f, 0.0f, "%.0f"); @@ -98,5 +98,7 @@ public override void BuildSamplePanel() } + + return true; } } diff --git a/src/Box2D.NET.Samples/Samples/Continuous/GhostBumps.cs b/src/Box2D.NET.Samples/Samples/Continuous/GhostBumps.cs index 31511ecf..fc7a44f6 100644 --- a/src/Box2D.NET.Samples/Samples/Continuous/GhostBumps.cs +++ b/src/Box2D.NET.Samples/Samples/Continuous/GhostBumps.cs @@ -267,7 +267,7 @@ void Launch() } } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); @@ -314,5 +314,7 @@ public override void BuildSamplePanel() ImGui.PopItemWidth(); + + return true; } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Continuous/SkinnyBox.cs b/src/Box2D.NET.Samples/Samples/Continuous/SkinnyBox.cs index 374c0def..51cf89a9 100644 --- a/src/Box2D.NET.Samples/Samples/Continuous/SkinnyBox.cs +++ b/src/Box2D.NET.Samples/Samples/Continuous/SkinnyBox.cs @@ -111,7 +111,7 @@ void Launch() } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -125,6 +125,8 @@ public override void BuildSamplePanel() ImGui.Checkbox("Auto Test", ref m_autoTest); + + return true; } public override void Step() @@ -136,4 +138,4 @@ public override void Step() Launch(); } } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Events/BodyMove.cs b/src/Box2D.NET.Samples/Samples/Events/BodyMove.cs index 29036e15..6f99259b 100644 --- a/src/Box2D.NET.Samples/Samples/Events/BodyMove.cs +++ b/src/Box2D.NET.Samples/Samples/Events/BodyMove.cs @@ -177,7 +177,7 @@ public override void Step() } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -194,6 +194,8 @@ public override void BuildSamplePanel() ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); ImGui.SliderFloat("Magnitude", ref m_explosionMagnitude, -20.0f, 20.0f, "%.1f"); ImGui.PopItemWidth(); + + return true; } public override void Draw() @@ -202,6 +204,6 @@ public override void Draw() DrawCircle(m_draw, m_explosionPosition, m_explosionRadius, B2HexColor.b2_colorAzure); - DrawTextLine($"sleep count: {m_sleepCount}"); + DrawScreenTextLine($"sleep count: {m_sleepCount}"); } } diff --git a/src/Box2D.NET.Samples/Samples/Events/ContactEvent.cs b/src/Box2D.NET.Samples/Samples/Events/ContactEvent.cs index 218a255c..38fe4569 100644 --- a/src/Box2D.NET.Samples/Samples/Events/ContactEvent.cs +++ b/src/Box2D.NET.Samples/Samples/Events/ContactEvent.cs @@ -144,11 +144,13 @@ void SpawnDebris() } } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); ImGui.SliderFloat("force", ref m_force, 100.0f, 500.0f, "%.1f"); ImGui.PopItemWidth(); + + return true; } public override void Step() diff --git a/src/Box2D.NET.Samples/Samples/Events/FootSensor.cs b/src/Box2D.NET.Samples/Samples/Events/FootSensor.cs index e08a2d45..a813d98a 100644 --- a/src/Box2D.NET.Samples/Samples/Events/FootSensor.cs +++ b/src/Box2D.NET.Samples/Samples/Events/FootSensor.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2025 Erin Catto +// SPDX-FileCopyrightText: 2025 Erin Catto // SPDX-FileCopyrightText: 2025 Ikpil Choi(ikpil@naver.com) // SPDX-License-Identifier: MIT @@ -151,7 +151,7 @@ public override void Draw() DrawPoint(m_draw, point, 10.0f, B2HexColor.b2_colorWhite); } - DrawTextLine($"count == {m_overlapCount}"); + DrawScreenTextLine($"count == {m_overlapCount}"); } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Events/Platform.cs b/src/Box2D.NET.Samples/Samples/Events/Platform.cs index 988db39f..dba0bc5d 100644 --- a/src/Box2D.NET.Samples/Samples/Events/Platform.cs +++ b/src/Box2D.NET.Samples/Samples/Events/Platform.cs @@ -154,12 +154,14 @@ public bool PreSolve(B2ShapeId shapeIdA, B2ShapeId shapeIdB, B2Vec2 point, B2Vec return false; } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); ImGui.SliderFloat("force", ref m_force, 0.0f, 50.0f, "%.1f"); ImGui.SliderFloat("impulse", ref m_impulse, 0.0f, 50.0f, "%.1f"); ImGui.PopItemWidth(); + + return true; } public override void Step() @@ -254,6 +256,6 @@ public override void Draw() DrawScreenTextLine("Movement: A/D/Space"); - DrawTextLine($"Can jump = {m_canJump}"); + DrawScreenTextLine($"Can jump = {(m_canJump ? "true" : "false")}"); } } diff --git a/src/Box2D.NET.Samples/Samples/Events/SensorBookend.cs b/src/Box2D.NET.Samples/Samples/Events/SensorBookend.cs index c3816d27..006f32bf 100644 --- a/src/Box2D.NET.Samples/Samples/Events/SensorBookend.cs +++ b/src/Box2D.NET.Samples/Samples/Events/SensorBookend.cs @@ -120,7 +120,7 @@ void CreateVisitor() m_visitorShapeId = b2CreateCircleShape(m_visitorBodyId, shapeDef, circle); } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -243,6 +243,8 @@ public override void BuildSamplePanel() } + + return true; } public override void Step() @@ -343,8 +345,8 @@ public override void Draw() { base.Draw(); - DrawTextLine($"visiting 1 == {m_isVisiting1}"); - DrawTextLine($"visiting 2 == {m_isVisiting2}"); - DrawTextLine($"sensors overlap count == {m_sensorsOverlapCount}"); + DrawScreenTextLine($"visiting 1 == {(m_isVisiting1 ? "true" : "false")}"); + DrawScreenTextLine($"visiting 2 == {(m_isVisiting2 ? "true" : "false")}"); + DrawScreenTextLine($"sensors overlap count == {m_sensorsOverlapCount}"); } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Events/SensorFunnel.cs b/src/Box2D.NET.Samples/Samples/Events/SensorFunnel.cs index abccd2ec..5991e9bd 100644 --- a/src/Box2D.NET.Samples/Samples/Events/SensorFunnel.cs +++ b/src/Box2D.NET.Samples/Samples/Events/SensorFunnel.cs @@ -261,7 +261,7 @@ void Clear() } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -278,6 +278,8 @@ public override void BuildSamplePanel() } + + return true; } public override void Step() @@ -345,4 +347,4 @@ public override void Step() } } } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Events/SensorHits.cs b/src/Box2D.NET.Samples/Samples/Events/SensorHits.cs index 90877243..5a50275a 100644 --- a/src/Box2D.NET.Samples/Samples/Events/SensorHits.cs +++ b/src/Box2D.NET.Samples/Samples/Events/SensorHits.cs @@ -170,7 +170,7 @@ void Launch() m_shapeId = b2CreateCircleShape(m_bodyId, shapeDef, circle); } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -182,6 +182,8 @@ public override void BuildSamplePanel() } + + return true; } void CollectTransforms(B2ShapeId sensorShapeId) @@ -246,7 +248,7 @@ public override void Draw() DrawTransform(m_draw, m_transforms[i], 1.0f); } - DrawTextLine($"begin touch count = {m_beginCount}"); - DrawTextLine($"end touch count = {m_endCount}"); + DrawScreenTextLine($"begin touch count = {m_beginCount}"); + DrawScreenTextLine($"end touch count = {m_endCount}"); } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Geometries/ConvexHull.cs b/src/Box2D.NET.Samples/Samples/Geometries/ConvexHull.cs index a2611882..b08dd5af 100644 --- a/src/Box2D.NET.Samples/Samples/Geometries/ConvexHull.cs +++ b/src/Box2D.NET.Samples/Samples/Geometries/ConvexHull.cs @@ -8,6 +8,7 @@ using static Box2D.NET.B2Constants; using static Box2D.NET.Shared.RandomSupports; using static Box2D.NET.Samples.Graphics.Draws; +using static Box2D.NET.Samples.SampleText; namespace Box2D.NET.Samples.Samples.Geometries; @@ -196,7 +197,7 @@ public override void Draw() if (m_valid == false) { - DrawTextLine($"generation = {m_generation}, FAILED"); + DrawScreenTextLine($"generation = {m_generation}, FAILED"); } else @@ -207,7 +208,7 @@ public override void Draw() if (m_milliseconds > 0.0f) { - DrawTextLine($"milliseconds = {m_milliseconds:G}"); + DrawScreenTextLine($"milliseconds = {FormatFloat(m_milliseconds)}"); } diff --git a/src/Box2D.NET.Samples/Samples/Issues/Crash01.cs b/src/Box2D.NET.Samples/Samples/Issues/Crash01.cs index f114285e..fd1f35f9 100644 --- a/src/Box2D.NET.Samples/Samples/Issues/Crash01.cs +++ b/src/Box2D.NET.Samples/Samples/Issues/Crash01.cs @@ -106,7 +106,7 @@ public Crash01(SampleContext context) : base(context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -142,5 +142,7 @@ public override void BuildSamplePanel() } + + return true; } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Issues/DisableCrash.cs b/src/Box2D.NET.Samples/Samples/Issues/DisableCrash.cs index dc8c2501..520862ea 100644 --- a/src/Box2D.NET.Samples/Samples/Issues/DisableCrash.cs +++ b/src/Box2D.NET.Samples/Samples/Issues/DisableCrash.cs @@ -73,7 +73,7 @@ public DisableCrash(SampleContext context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -90,5 +90,7 @@ public override void BuildSamplePanel() } + + return true; } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Joints/BallAndChain.cs b/src/Box2D.NET.Samples/Samples/Joints/BallAndChain.cs index 37f556b0..4379bc4e 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/BallAndChain.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/BallAndChain.cs @@ -107,7 +107,7 @@ public BallAndChain(SampleContext context) : base(context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); bool updateFriction = ImGui.SliderFloat("Joint Friction", ref m_frictionTorque, 0.0f, 1000.0f, "%2.f"); @@ -119,5 +119,7 @@ public override void BuildSamplePanel() b2RevoluteJoint_SetMaxMotorTorque(m_jointIds[i], m_frictionTorque); } } + + return true; } } diff --git a/src/Box2D.NET.Samples/Samples/Joints/BreakableJoint.cs b/src/Box2D.NET.Samples/Samples/Joints/BreakableJoint.cs index eed01365..4dbdca01 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/BreakableJoint.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/BreakableJoint.cs @@ -200,7 +200,7 @@ public BreakableJoint(SampleContext context) : base(context) m_breakForce = 1000.0f; } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); ImGui.SliderFloat("break force", ref m_breakForce, 0.0f, 10000.0f, "%.1f"); @@ -211,6 +211,8 @@ public override void BuildSamplePanel() b2World_SetGravity(m_worldId, gravity); } ImGui.PopItemWidth(); + + return true; } diff --git a/src/Box2D.NET.Samples/Samples/Joints/Bridge.cs b/src/Box2D.NET.Samples/Samples/Joints/Bridge.cs index 7ab21d29..c59dd7c5 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/Bridge.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/Bridge.cs @@ -138,7 +138,7 @@ public Bridge(SampleContext context) : base(context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -187,5 +187,7 @@ public override void BuildSamplePanel() ImGui.PopItemWidth(); + + return true; } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Joints/Cantilever.cs b/src/Box2D.NET.Samples/Samples/Joints/Cantilever.cs index f7bb3fac..4aee5c1e 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/Cantilever.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/Cantilever.cs @@ -100,7 +100,7 @@ public Cantilever(SampleContext context) : base(context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); @@ -154,6 +154,8 @@ public override void BuildSamplePanel() b2Joint_SetCollideConnected(m_jointIds[i], m_collideConnected); } } + + return true; } @@ -162,6 +164,6 @@ public override void Draw() base.Draw(); B2Vec2 tipPosition = b2Body_GetPosition(m_tipId); - DrawTextLine($"tip-y = {tipPosition.Y:F2}"); + DrawScreenTextLine(System.FormattableString.Invariant($"tip-y = {tipPosition.Y:F2}")); } } diff --git a/src/Box2D.NET.Samples/Samples/Joints/DistanceJoint.cs b/src/Box2D.NET.Samples/Samples/Joints/DistanceJoint.cs index 0a870b2b..1ebe6d18 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/DistanceJoint.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/DistanceJoint.cs @@ -129,7 +129,7 @@ void CreateScene(int newCount) } } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); @@ -230,5 +230,7 @@ public override void BuildSamplePanel() ImGui.PopItemWidth(); + + return true; } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Joints/Door.cs b/src/Box2D.NET.Samples/Samples/Joints/Door.cs index 1b246d49..e51ce5a6 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/Door.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/Door.cs @@ -13,6 +13,7 @@ using static Box2D.NET.B2Ids; using static Box2D.NET.B2RevoluteJoints; using static Box2D.NET.Samples.Graphics.Draws; +using static Box2D.NET.Samples.SampleText; namespace Box2D.NET.Samples.Samples.Joints; @@ -91,7 +92,7 @@ public Door(SampleContext context) : base(context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -122,6 +123,8 @@ public override void BuildSamplePanel() { b2RevoluteJoint_EnableLimit(m_jointId, m_enableLimit); } + + return true; } public override void Draw() @@ -134,6 +137,6 @@ public override void Draw() float translationError = b2Joint_GetLinearSeparation(m_jointId); m_translationError = b2MaxFloat(m_translationError, translationError); - DrawTextLine($"translation error = {m_translationError}"); + DrawScreenTextLine($"translation error = {FormatFloat(m_translationError)}"); } } diff --git a/src/Box2D.NET.Samples/Samples/Joints/Driving.cs b/src/Box2D.NET.Samples/Samples/Joints/Driving.cs index a83cc801..febe2998 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/Driving.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/Driving.cs @@ -12,6 +12,7 @@ using static Box2D.NET.B2Bodies; using static Box2D.NET.B2Shapes; using static Box2D.NET.B2Diagnostics; +using static Box2D.NET.Samples.SampleText; namespace Box2D.NET.Samples.Samples.Joints; @@ -211,7 +212,7 @@ public Driving(SampleContext context) : base(context) m_car.Spawn(m_worldId, new B2Vec2(0.0f, 0.0f), 1.0f, m_hertz, m_dampingRatio, m_torque, B2UserData.Empty); } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -239,6 +240,8 @@ public override void BuildSamplePanel() ImGui.PopItemWidth(); + + return true; } public override void Step() @@ -273,7 +276,7 @@ public override void Draw() B2Vec2 linearVelocity = b2Body_GetLinearVelocity(m_car.m_chassisId); float kph = linearVelocity.X * 3.6f; - DrawTextLine($"speed in kph: {kph:G2}"); + DrawScreenTextLine($"speed in kph: {FormatFloat(kph, 2)}"); B2Vec2 carPosition = b2Body_GetPosition(m_car.m_chassisId); diff --git a/src/Box2D.NET.Samples/Samples/Joints/GearLift.cs b/src/Box2D.NET.Samples/Samples/Joints/GearLift.cs index 5bdbe5a7..49b1a59f 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/GearLift.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/GearLift.cs @@ -294,7 +294,7 @@ public GearLift(SampleContext context) : base(context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -318,6 +318,8 @@ public override void BuildSamplePanel() b2Joint_WakeBodies(m_driverId); } ImGui.PopItemWidth(); + + return true; } public override void Step() diff --git a/src/Box2D.NET.Samples/Samples/Joints/JointSeparation.cs b/src/Box2D.NET.Samples/Samples/Joints/JointSeparation.cs index 05254203..be691ffd 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/JointSeparation.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/JointSeparation.cs @@ -176,7 +176,7 @@ public JointSeparation(SampleContext context) : base(context) m_jointDampingRatio = 2.0f; } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); B2Vec2 gravity = b2World_GetGravity(m_worldId); @@ -213,6 +213,8 @@ public override void BuildSamplePanel() b2Body_ApplyLinearImpulse(m_bodyIds[i], new B2Vec2(m_impulse, -m_impulse), p, true); } } + + return true; } public override void Draw() diff --git a/src/Box2D.NET.Samples/Samples/Joints/MotionLocks.cs b/src/Box2D.NET.Samples/Samples/Joints/MotionLocks.cs index cb53e20f..a9f561a1 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/MotionLocks.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/MotionLocks.cs @@ -198,7 +198,7 @@ public MotionLocks(SampleContext context) : base(context) ++index; } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -230,6 +230,8 @@ public override void BuildSamplePanel() } + + return true; } public override void Step() @@ -243,4 +245,4 @@ public override void Step() ), true); } } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Joints/MotorJoint.cs b/src/Box2D.NET.Samples/Samples/Joints/MotorJoint.cs index eb93eaa0..905d6f56 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/MotorJoint.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/MotorJoint.cs @@ -123,7 +123,7 @@ public MotorJoint(SampleContext context) : base(context) m_time = 0.0f; } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); if (ImGui.SliderFloat("Speed", ref m_speed, -5.0f, 5.0f, "%.0f")) @@ -146,6 +146,8 @@ public override void BuildSamplePanel() { b2Body_ApplyLinearImpulseToCenter(m_bodyId, new B2Vec2(100.0f, 0.0f), true); } + + return true; } diff --git a/src/Box2D.NET.Samples/Samples/Joints/PrismaticJoint.cs b/src/Box2D.NET.Samples/Samples/Joints/PrismaticJoint.cs index 6958d2da..237d5cac 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/PrismaticJoint.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/PrismaticJoint.cs @@ -91,7 +91,7 @@ public PrismaticJoint(SampleContext context) : base(context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -152,6 +152,8 @@ public override void BuildSamplePanel() } ImGui.PopItemWidth(); } + + return true; } public override void Draw() @@ -159,14 +161,14 @@ public override void Draw() base.Draw(); float force = b2PrismaticJoint_GetMotorForce(m_jointId); - DrawTextLine($"Motor Force = {force:4,F1}"); + DrawScreenTextLine(System.FormattableString.Invariant($"Motor Force = {force,4:F1}")); float translation = b2PrismaticJoint_GetTranslation(m_jointId); - DrawTextLine($"Translation = {translation:4,F1}"); + DrawScreenTextLine(System.FormattableString.Invariant($"Translation = {translation,4:F1}")); float speed = b2PrismaticJoint_GetSpeed(m_jointId); - DrawTextLine($"Speed = {speed:4,F8}"); + DrawScreenTextLine(System.FormattableString.Invariant($"Speed = {speed,4:F8}")); } } diff --git a/src/Box2D.NET.Samples/Samples/Joints/Ragdoll.cs b/src/Box2D.NET.Samples/Samples/Joints/Ragdoll.cs index ccd479b6..7b6067bf 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/Ragdoll.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/Ragdoll.cs @@ -61,7 +61,7 @@ void Spawn() //Human_ApplyRandomAngularImpulse(ref m_human, 10.0f); } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); @@ -89,5 +89,7 @@ public override void BuildSamplePanel() Spawn(); } + + return true; } } diff --git a/src/Box2D.NET.Samples/Samples/Joints/RevoluteJoint.cs b/src/Box2D.NET.Samples/Samples/Joints/RevoluteJoint.cs index 17a059c4..9e921017 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/RevoluteJoint.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/RevoluteJoint.cs @@ -143,7 +143,7 @@ public RevoluteJoint(SampleContext context) : base(context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -205,6 +205,8 @@ public override void BuildSamplePanel() } ImGui.PopItemWidth(); } + + return true; } public override void Draw() @@ -212,13 +214,13 @@ public override void Draw() base.Draw(); float angle1 = b2RevoluteJoint_GetAngle(m_jointId1); - DrawTextLine($"Angle (Deg) 1 = {angle1:F1}"); + DrawScreenTextLine(System.FormattableString.Invariant($"Angle (Deg) 1 = {angle1,2:F1}")); float torque1 = b2RevoluteJoint_GetMotorTorque(m_jointId1); - DrawTextLine($"Motor Torque 1 = {torque1:F1}"); + DrawScreenTextLine(System.FormattableString.Invariant($"Motor Torque 1 = {torque1,4:F1}")); float torque2 = b2RevoluteJoint_GetMotorTorque(m_jointId2); - DrawTextLine($"Motor Torque 2 = {torque2:F1}"); + DrawScreenTextLine(System.FormattableString.Invariant($"Motor Torque 2 = {torque2,4:F1}")); } } diff --git a/src/Box2D.NET.Samples/Samples/Joints/ScaleRagdoll.cs b/src/Box2D.NET.Samples/Samples/Joints/ScaleRagdoll.cs index 7f52f5bb..387ff6fa 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/ScaleRagdoll.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/ScaleRagdoll.cs @@ -59,7 +59,7 @@ void Spawn() Human_ApplyRandomAngularImpulse(ref m_human, 0.1f); } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); @@ -71,5 +71,7 @@ public override void BuildSamplePanel() ImGui.PopItemWidth(); + + return true; } } diff --git a/src/Box2D.NET.Samples/Samples/Joints/ScissorLift.cs b/src/Box2D.NET.Samples/Samples/Joints/ScissorLift.cs index 9ca95117..064c66d9 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/ScissorLift.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/ScissorLift.cs @@ -204,7 +204,7 @@ public ScissorLift(SampleContext context) : base(context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -228,5 +228,7 @@ public override void BuildSamplePanel() b2Joint_WakeBodies(m_liftJointId); } ImGui.PopItemWidth(); + + return true; } } diff --git a/src/Box2D.NET.Samples/Samples/Joints/TopDownFriction.cs b/src/Box2D.NET.Samples/Samples/Joints/TopDownFriction.cs index c319750c..786a0f19 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/TopDownFriction.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/TopDownFriction.cs @@ -109,7 +109,7 @@ private TopDownFriction(SampleContext context) : base(context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -126,5 +126,7 @@ public override void BuildSamplePanel() } + + return true; } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Joints/UserConstraint.cs b/src/Box2D.NET.Samples/Samples/Joints/UserConstraint.cs index 09a767d4..b411fcc3 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/UserConstraint.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/UserConstraint.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2025 Erin Catto +// SPDX-FileCopyrightText: 2025 Erin Catto // SPDX-FileCopyrightText: 2025 Ikpil Choi(ikpil@naver.com) // SPDX-License-Identifier: MIT @@ -8,6 +8,7 @@ using static Box2D.NET.B2Bodies; using static Box2D.NET.B2Shapes; using static Box2D.NET.Samples.Graphics.Draws; +using static Box2D.NET.Samples.SampleText; namespace Box2D.NET.Samples.Samples.Joints; @@ -135,6 +136,6 @@ public override void Draw() base.Draw(); float invTimeStep = m_context.hertz; - DrawTextLine($"forces = {m_impulses[0] * invTimeStep:g}, {m_impulses[1] * invTimeStep:g}"); + DrawScreenTextLine($"forces = {FormatFloat(m_impulses[0] * invTimeStep)}, {FormatFloat(m_impulses[1] * invTimeStep)}"); } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Joints/WheelJoint.cs b/src/Box2D.NET.Samples/Samples/Joints/WheelJoint.cs index 4dc6e519..be18c4ab 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/WheelJoint.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/WheelJoint.cs @@ -85,7 +85,7 @@ public WheelJoint(SampleContext context) : base(context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -133,6 +133,8 @@ public override void BuildSamplePanel() } ImGui.PopItemWidth(); } + + return true; } public override void Draw() @@ -140,6 +142,6 @@ public override void Draw() base.Draw(); float torque = b2WheelJoint_GetMotorTorque(m_jointId); - DrawTextLine($"Motor Torque = {torque,4:F1}"); + DrawScreenTextLine(System.FormattableString.Invariant($"Motor Torque = {torque,4:F1}")); } } diff --git a/src/Box2D.NET.Samples/Samples/Robustness/Cart.cs b/src/Box2D.NET.Samples/Samples/Robustness/Cart.cs index 05433688..83b7d9bc 100644 --- a/src/Box2D.NET.Samples/Samples/Robustness/Cart.cs +++ b/src/Box2D.NET.Samples/Samples/Robustness/Cart.cs @@ -141,7 +141,7 @@ void CreateScene() b2Joint_SetConstraintTuning(m_jointId2, m_constraintHertz, m_constraintDampingRatio); } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); @@ -178,5 +178,7 @@ public override void BuildSamplePanel() ImGui.PopItemWidth(); + + return true; } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Robustness/OverlapRecovery.cs b/src/Box2D.NET.Samples/Samples/Robustness/OverlapRecovery.cs index 7af4c2a7..bea3a34d 100644 --- a/src/Box2D.NET.Samples/Samples/Robustness/OverlapRecovery.cs +++ b/src/Box2D.NET.Samples/Samples/Robustness/OverlapRecovery.cs @@ -101,7 +101,7 @@ void CreateScene() B2_ASSERT(bodyIndex == m_bodyCount); } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); @@ -122,5 +122,7 @@ public override void BuildSamplePanel() ImGui.PopItemWidth(); + + return true; } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Robustness/TinyPyramid.cs b/src/Box2D.NET.Samples/Samples/Robustness/TinyPyramid.cs index 14464caf..f377788b 100644 --- a/src/Box2D.NET.Samples/Samples/Robustness/TinyPyramid.cs +++ b/src/Box2D.NET.Samples/Samples/Robustness/TinyPyramid.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2025 Erin Catto +// SPDX-FileCopyrightText: 2025 Erin Catto // SPDX-FileCopyrightText: 2025 Ikpil Choi(ikpil@naver.com) // SPDX-License-Identifier: MIT @@ -71,6 +71,6 @@ public override void Draw() { base.Draw(); - DrawTextLine($"{200.0f * m_extent:F1}cm squares"); + DrawScreenTextLine(System.FormattableString.Invariant($"{200.0f * m_extent:F1}cm squares")); } } diff --git a/src/Box2D.NET.Samples/Samples/Sample.cs b/src/Box2D.NET.Samples/Samples/Sample.cs index bb9ec5a3..6112f99c 100644 --- a/src/Box2D.NET.Samples/Samples/Sample.cs +++ b/src/Box2D.NET.Samples/Samples/Sample.cs @@ -33,35 +33,8 @@ public class Sample : IDisposable public const int m_maxTasks = 512; public const int m_maxThreads = 64; public const int m_profileCapacity = 512; - public const int m_maxHudLines = 64; private const int MAX_SAMPLES = 256; - public struct HudLine - { - public B2HexColor color; - public string text; - } - - private readonly struct ProfileRowDef - { - public readonly string name; - public readonly int indent; - public readonly Vector4 color; - - public ProfileRowDef(string name, int indent, Vector4 color) - { - this.name = name; - this.indent = indent; - this.color = color; - } - } - - private struct ScoredSample - { - public int index; - public int score; - } - #if DEBUG public const bool m_isDebug = true; #else @@ -81,8 +54,6 @@ private struct ScoredSample protected float m_mouseForceScale; public int m_stepCount; - public readonly HudLine[] m_hudLines; - public int m_hudLineCount; private float m_screenTextY; // @@ -101,7 +72,7 @@ private struct ScoredSample private static int s_pickerHighlight; private static int s_previousPickerHighlight; private static readonly int[] s_filteredSamples = new int[MAX_SAMPLES]; - private static readonly ScoredSample[] s_scoredSamples = new ScoredSample[MAX_SAMPLES]; + private static readonly Scored[] s_scored = new Scored[MAX_SAMPLES]; private static int s_filteredCount; private static bool s_pickerJustOpened; private static bool s_forcePickerScroll; @@ -124,8 +95,6 @@ public Sample(SampleContext context) m_stepCount = 0; m_didStep = false; - m_hudLines = new HudLine[m_maxHudLines]; - m_hudLineCount = 0; m_screenTextY = 0.0f; m_mouseBodyId = b2_nullBodyId; @@ -198,15 +167,42 @@ public void TestMathCpp() c += c; } - public virtual void UpdateGui() + private readonly struct RowDef { - float fontSize = ImGui.GetFontSize(); + public readonly string name; + public readonly int indent; + public readonly Vector4 color; + + public RowDef(string name, int indent, Vector4 color) + { + this.name = name; + this.indent = indent; + this.color = color; + } + } + + private static float AddSegment(ImDrawListPtr dl, float availWidth, float t, float stepNow, Vector4 col, float x, + Vector2 cursor, float barHeight) + { + float w = availWidth * (t / stepNow); + if (w > 0.0f) + { + dl.AddRectFilled(new Vector2(x, cursor.Y), new Vector2(x + w, cursor.Y + barHeight), + ImGui.ColorConvertFloat4ToU32(col)); + x += w; + } + + return x; + } - if (m_context.showDiagnostics == false) + public void DrawMetrics() + { + if (m_context.showMetrics == false) { return; } + float fontSize = ImGui.GetFontSize(); float menuWidth = 14.0f * fontSize; float drawerHeight = 16.0f * fontSize; float drawerWidth = m_camera.width - menuWidth - 1.5f * fontSize; @@ -214,11 +210,11 @@ public virtual void UpdateGui() ImGui.SetNextWindowPos(new Vector2(0.5f * fontSize, m_camera.height - drawerHeight - 0.5f * fontSize)); ImGui.SetNextWindowSize(new Vector2(drawerWidth, drawerHeight)); - ImGui.Begin("Diagnostics", + ImGui.Begin("Metrics", ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoTitleBar); - if (ImGui.BeginTabBar("DiagnosticsTabs", ImGuiTabBarFlags.None)) + if (ImGui.BeginTabBar("MetricsTabs", ImGuiTabBarFlags.None)) { if (ImGui.BeginTabItem("Profile")) { @@ -314,7 +310,7 @@ public virtual void UpdateGui() Vector4 colorOther = new Vector4(90.0f / 255.0f, 90.0f / 255.0f, 90.0f / 255.0f, 1.0f); Vector4 colorDefault = new Vector4(220.0f / 255.0f, 220.0f / 255.0f, 220.0f / 255.0f, 1.0f); - ProfileRowDef[] rows = + RowDef[] rows = [ new("step", 0, colorStep), new("pairs", 0, colorPairs), new("collide", 0, colorCollide), new("solve", 0, colorSolve), new("setup", 1, colorDefault), new("constraints", 1, colorDefault), @@ -371,21 +367,11 @@ public virtual void UpdateGui() Vector2 cursor = ImGui.GetCursorScreenPos(); float x = cursor.X; - void AddSegment(float t, Vector4 color) - { - float width = availWidth * (t / stepNow); - if (width > 0.0f) - { - drawList.AddRectFilled(new Vector2(x, cursor.Y), new Vector2(x + width, cursor.Y + barHeight), ImGui.ColorConvertFloat4ToU32(color)); - x += width; - } - } - - AddSegment(pairsT, colorPairs); - AddSegment(collideT, colorCollide); - AddSegment(solveT, colorSolve); - AddSegment(sensorsT, colorSensors); - AddSegment(otherT, colorOther); + x = AddSegment(drawList, availWidth, pairsT, stepNow, colorPairs, x, cursor, barHeight); + x = AddSegment(drawList, availWidth, collideT, stepNow, colorCollide, x, cursor, barHeight); + x = AddSegment(drawList, availWidth, solveT, stepNow, colorSolve, x, cursor, barHeight); + x = AddSegment(drawList, availWidth, sensorsT, stepNow, colorSensors, x, cursor, barHeight); + x = AddSegment(drawList, availWidth, otherT, stepNow, colorOther, x, cursor, barHeight); ImGui.Dummy(new Vector2(availWidth, barHeight)); } @@ -432,7 +418,7 @@ void AddSegment(float t, Vector4 color) continue; } - ProfileRowDef row = rows[r]; + RowDef row = rows[r]; float[] history = histories[r]; ImGui.TableNextRow(); @@ -579,7 +565,7 @@ void AddSegment(float t, Vector4 color) continue; } float segmentWidth = availableWidth * itemCount * invTotal; - uint color = ImGui.ColorConvertFloat4ToU32(HexToColor(b2GetGraphColor(i))); + uint color = ImGui.ColorConvertFloat4ToU32(MakeColor(b2GetGraphColor(i))); drawList.AddRectFilled(new Vector2(x, cursor.Y), new Vector2(x + segmentWidth, cursor.Y + barHeight), color); x += segmentWidth; } @@ -604,12 +590,6 @@ void AddSegment(float t, Vector4 color) ImGui.End(); } - private static Vector4 HexToColor(B2HexColor color) - { - uint hex = (uint)color; - return new Vector4(((hex >> 16) & 0xFF) / 255.0f, ((hex >> 8) & 0xFF) / 255.0f, (hex & 0xFF) / 255.0f, 1.0f); - } - private void DrawProfilePlot(string label, int count, float maxValue, float maxTime, Vector2 size) { Vector2 canvasPos = ImGui.GetCursorScreenPos(); @@ -703,7 +683,6 @@ private void DrawProfileSeries(ImDrawListPtr drawList, Vector2 origin, Vector2 s public void ResetText() { - m_hudLineCount = 0; float fontSize = ImGui.GetFontSize(); if (m_context.showUI) { @@ -818,43 +797,12 @@ public virtual void MouseMove(B2Vec2 p) m_mousePoint = p; } - public void DrawColoredTextLine(B2HexColor color, string text) - { - if (m_context.showUI == false || m_hudLineCount >= m_maxHudLines) - { - return; - } - - m_hudLines[m_hudLineCount].color = color; - m_hudLines[m_hudLineCount].text = TruncateText(text); - m_hudLineCount += 1; - } - - - public void DrawTextLine(string text) - { - if (m_context.showUI == false || m_hudLineCount >= m_maxHudLines) - { - return; - } - - m_hudLines[m_hudLineCount].color = B2HexColor.b2_colorWhite; - m_hudLines[m_hudLineCount].text = TruncateText(text); - m_hudLineCount += 1; - } - public void DrawScreenTextLine(string text) { DrawScreenString(m_draw, 5.0f, m_screenTextY, B2HexColor.b2_colorWhite, TruncateText(text)); m_screenTextY += 1.5f * ImGui.GetFontSize(); } - public void DrawColoredScreenTextLine(B2HexColor color, string text) - { - DrawScreenString(m_draw, 5.0f, m_screenTextY, color, TruncateText(text)); - m_screenTextY += 1.5f * ImGui.GetFontSize(); - } - private static string TruncateText(string text) { return text.Length > 255 ? text[..255] : text; @@ -884,8 +832,8 @@ public virtual void Step() if (m_context.showUI) { - DrawTextLine("****PAUSED****"); - DrawTextLine(""); + DrawScreenTextLine("****PAUSED****"); + DrawScreenTextLine(""); } } @@ -941,13 +889,9 @@ public virtual void Draw() } - public virtual void BuildSamplePanel() - { - } - - public void ShiftOrigin(B2Vec2 newOrigin) + public virtual bool DrawControls() { - // m_world.ShiftOrigin(newOrigin); + return false; } @@ -1020,53 +964,7 @@ private static int FuzzyScore(string needle, string haystack) return score; } - private static void RebuildSampleFilter(string query) - { - int sampleCount = Math.Min(SampleFactory.Shared.SampleCount, MAX_SAMPLES); - int count = 0; - for (int i = 0; i < sampleCount; ++i) - { - int nameScore = FuzzyScore(query, SampleFactory.Shared.GetName(i)); - int categoryScore = FuzzyScore(query, SampleFactory.Shared.GetCategory(i)); - int best = -1; - if (nameScore >= 0) - { - best = nameScore * 2; // name matches outweigh category-only matches - } - if (categoryScore >= 0 && categoryScore > best) - { - best = categoryScore; - } - if (best < 0) - { - continue; - } - s_scoredSamples[count].index = i; - s_scoredSamples[count].score = best; - ++count; - } - - // Stable insertion sort by score desc; equal scores keep registry order - // (which main.cpp sorts by category then name). - for (int i = 1; i < count; ++i) - { - ScoredSample temporary = s_scoredSamples[i]; - int j = i - 1; - while (j >= 0 && s_scoredSamples[j].score < temporary.score) - { - s_scoredSamples[j + 1] = s_scoredSamples[j]; - --j; - } - s_scoredSamples[j + 1] = temporary; - } - for (int i = 0; i < count; ++i) - { - s_filteredSamples[i] = s_scoredSamples[i].index; - } - s_filteredCount = count; - } - - private static void AddHelpRow(string key, string description) + private static void DrawRow(string key, string description) { ImGui.TableNextRow(); ImGui.TableSetColumnIndex(0); @@ -1097,17 +995,9 @@ private static void TextLinkOpenURL(string label, string url) } } - public static void UpdateSampleUI(SampleContext context) + private static void DrawMenuBar(SampleContext context) { - int maxWorkers = B2_MAX_WORKERS; - float fontSize = ImGui.GetFontSize(); - float menuWidth = 14.0f * fontSize; - - if (context.showUI == false) - { - return; - } if (ImGui.BeginMainMenuBar()) { @@ -1200,7 +1090,7 @@ public static void UpdateSampleUI(SampleContext context) ImGui.EndMenu(); } ImGui.Separator(); - ImGui.MenuItem("Diagnostics", "M", ref context.showDiagnostics); + ImGui.MenuItem("Diagnostics", "M", ref context.showMetrics); ImGui.Separator(); if (ImGui.BeginMenu("Scale")) { @@ -1252,6 +1142,7 @@ public static void UpdateSampleUI(SampleContext context) ImGui.EndMainMenuBar(); + // Draw a dark border along the bottom of the menu { float menuBarBottom = ImGui.GetFrameHeight(); uint borderColor = ImGui.GetColorU32(ImGuiCol.Border); @@ -1272,27 +1163,27 @@ public static void UpdateSampleUI(SampleContext context) ImGui.SeparatorText("Keyboard"); if (ImGui.BeginTable("keys", 2, ImGuiTableFlags.SizingFixedFit)) { - AddHelpRow("Tab", "Show / hide UI"); - AddHelpRow("M", "Show / hide diagnostics"); - AddHelpRow("P", "Pause / resume"); - AddHelpRow("O", "Single step"); - AddHelpRow("R", "Restart sample"); - AddHelpRow("[ ]", "Previous / next sample"); - AddHelpRow("Ctrl+O", "Open sample picker"); - AddHelpRow("Arrows", "Pan camera"); - AddHelpRow("Ctrl+Arrows", "Shift origin"); - AddHelpRow("Z X", "Zoom out / in"); - AddHelpRow("Home", "Reset camera"); - AddHelpRow("Esc", "Quit"); + DrawRow("Tab", "Show / hide UI"); + DrawRow("M", "Show / hide diagnostics"); + DrawRow("P", "Pause / resume"); + DrawRow("O", "Single step"); + DrawRow("R", "Restart sample"); + DrawRow("[ ]", "Previous / next sample"); + DrawRow("Ctrl+O", "Open sample picker"); + DrawRow("Arrows", "Pan camera"); + DrawRow("Ctrl+Arrows", "Shift origin"); + DrawRow("Z X", "Zoom out / in"); + DrawRow("Home", "Reset camera"); + DrawRow("Esc", "Quit"); ImGui.EndTable(); } ImGui.SeparatorText("Mouse"); if (ImGui.BeginTable("mouse", 2, ImGuiTableFlags.SizingFixedFit)) { - AddHelpRow("Left drag", "Move bodies (mouse joint)"); - AddHelpRow("Right drag", "Pan camera"); - AddHelpRow("Scroll wheel", "Zoom"); + DrawRow("Left drag", "Move bodies (mouse joint)"); + DrawRow("Right drag", "Pan camera"); + DrawRow("Scroll wheel", "Zoom"); ImGui.EndTable(); } } @@ -1317,90 +1208,172 @@ public static void UpdateSampleUI(SampleContext context) ImGui.End(); } } + } + + private struct Scored + { + public int idx; + public int score; + } + + private static void Rebuild(string query) + { + int sampleCount = Math.Min(SampleFactory.Shared.SampleCount, MAX_SAMPLES); + int count = 0; + for (int i = 0; i < sampleCount; ++i) + { + int nameScore = FuzzyScore(query, SampleFactory.Shared.GetName(i)); + int categoryScore = FuzzyScore(query, SampleFactory.Shared.GetCategory(i)); + int best = -1; + if (nameScore >= 0) + { + best = nameScore * 2; // name matches outweigh category-only matches + } + if (categoryScore >= 0 && categoryScore > best) + { + best = categoryScore; + } + if (best < 0) + { + continue; + } + s_scored[count].idx = i; + s_scored[count].score = best; + count += 1; + } + + // Stable insertion sort by score desc. Equal scores keep registry order + // (which main.cpp sorts by category then name). + for (int i = 1; i < count; ++i) + { + Scored temporary = s_scored[i]; + int j = i - 1; + while (j >= 0 && s_scored[j].score < temporary.score) + { + s_scored[j + 1] = s_scored[j]; + --j; + } + s_scored[j + 1] = temporary; + } + + for (int i = 0; i < count; ++i) + { + s_filteredSamples[i] = s_scored[i].idx; + } + s_filteredCount = count; + } + + private static void DrawSamplePicker(SampleContext context) + { + float fontSize = ImGui.GetFontSize(); // Fuzzy sample picker (Ctrl+O). Opens a transient popup; type to filter by // name or category, Up/Down to navigate, Enter to select, Esc / click-outside to dismiss. + if (context.openSamplePicker) + { + ImGui.OpenPopup("##sample_picker"); + context.openSamplePicker = false; + s_pickerQuery = string.Empty; + s_previousPickerQuery = string.Empty; + s_pickerHighlight = 0; + s_previousPickerHighlight = 0; + Rebuild(s_pickerQuery); + s_pickerJustOpened = true; + s_forcePickerScroll = true; + } + + ImGui.SetNextWindowPos(new Vector2(context.camera.width * 0.5f, context.camera.height * 0.35f), + ImGuiCond.Appearing, new Vector2(0.5f, 0.5f)); + ImGui.SetNextWindowSize(new Vector2(32.0f * fontSize, 0.0f), ImGuiCond.Appearing); + + if (ImGui.BeginPopup("##sample_picker", + ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoSavedSettings)) { - if (context.openSamplePicker) + if (s_pickerJustOpened) { - ImGui.OpenPopup("##sample_picker"); - context.openSamplePicker = false; - s_pickerQuery = string.Empty; - s_previousPickerQuery = string.Empty; - s_pickerHighlight = 0; - s_previousPickerHighlight = 0; - RebuildSampleFilter(s_pickerQuery); - s_pickerJustOpened = true; - s_forcePickerScroll = true; + ImGui.SetKeyboardFocusHere(); + s_pickerJustOpened = false; } - ImGui.SetNextWindowPos(new Vector2(context.camera.width * 0.5f, context.camera.height * 0.35f), - ImGuiCond.Appearing, new Vector2(0.5f, 0.5f)); - ImGui.SetNextWindowSize(new Vector2(32.0f * fontSize, 0.0f), ImGuiCond.Appearing); + ImGui.PushItemWidth(-1.0f); + ImGui.InputTextWithHint("##q", "Search by name or category...", ref s_pickerQuery, 64); + ImGui.PopItemWidth(); - if (ImGui.BeginPopup("##sample_picker", - ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoSavedSettings)) + if (s_pickerQuery != s_previousPickerQuery) { - if (s_pickerJustOpened) - { - ImGui.SetKeyboardFocusHere(); - s_pickerJustOpened = false; - } - - ImGui.PushItemWidth(-1.0f); - ImGui.InputTextWithHint("##q", "Search by name or category...", ref s_pickerQuery, 64); - ImGui.PopItemWidth(); + Rebuild(s_pickerQuery); + s_previousPickerQuery = s_pickerQuery; + s_pickerHighlight = 0; + s_forcePickerScroll = true; + } - if (s_pickerQuery != s_previousPickerQuery) + if (s_filteredCount > 0) + { + if (ImGui.IsKeyPressed(ImGuiKey.DownArrow, true)) { - RebuildSampleFilter(s_pickerQuery); - s_previousPickerQuery = s_pickerQuery; - s_pickerHighlight = 0; - s_forcePickerScroll = true; + s_pickerHighlight = (s_pickerHighlight + 1) % s_filteredCount; } - - if (s_filteredCount > 0) + if (ImGui.IsKeyPressed(ImGuiKey.UpArrow, true)) { - if (ImGui.IsKeyPressed(ImGuiKey.DownArrow, true)) - { - s_pickerHighlight = (s_pickerHighlight + 1) % s_filteredCount; - } - if (ImGui.IsKeyPressed(ImGuiKey.UpArrow, true)) - { - s_pickerHighlight = (s_pickerHighlight + s_filteredCount - 1) % s_filteredCount; - } + s_pickerHighlight = (s_pickerHighlight + s_filteredCount - 1) % s_filteredCount; } - bool commit = ImGui.IsKeyPressed(ImGuiKey.Enter, false) || ImGui.IsKeyPressed(ImGuiKey.KeypadEnter, false); + } + bool commit = ImGui.IsKeyPressed(ImGuiKey.Enter, false) || ImGui.IsKeyPressed(ImGuiKey.KeypadEnter, false); - ImGui.BeginChild("##results", new Vector2(0.0f, 14.0f * fontSize), ImGuiChildFlags.Border); - for (int row = 0; row < s_filteredCount; ++row) + ImGui.BeginChild("##results", new Vector2(0.0f, 14.0f * fontSize), ImGuiChildFlags.Border); + for (int row = 0; row < s_filteredCount; ++row) + { + int i = s_filteredSamples[row]; + string label = $"{SampleFactory.Shared.GetCategory(i)} > {SampleFactory.Shared.GetName(i)}"; + bool selected = row == s_pickerHighlight; + if (ImGui.Selectable(label, selected)) { - int i = s_filteredSamples[row]; - string label = $"{SampleFactory.Shared.GetCategory(i)} > {SampleFactory.Shared.GetName(i)}"; - bool selected = row == s_pickerHighlight; - if (ImGui.Selectable(label, selected)) - { - s_pickerHighlight = row; - commit = true; - } - if (selected && (s_forcePickerScroll || s_pickerHighlight != s_previousPickerHighlight)) - { - ImGui.SetScrollHereY(); - } + s_pickerHighlight = row; + commit = true; } - ImGui.EndChild(); - s_previousPickerHighlight = s_pickerHighlight; - s_forcePickerScroll = false; - - if (commit && s_filteredCount > 0) + if (selected && (s_forcePickerScroll || s_pickerHighlight != s_previousPickerHighlight)) { - SelectSample(context, s_filteredSamples[s_pickerHighlight], false); - ImGui.CloseCurrentPopup(); + ImGui.SetScrollHereY(); } + } + ImGui.EndChild(); + s_previousPickerHighlight = s_pickerHighlight; + s_forcePickerScroll = false; - ImGui.EndPopup(); + if (commit && s_filteredCount > 0) + { + SelectSample(context, s_filteredSamples[s_pickerHighlight], false); + ImGui.CloseCurrentPopup(); } + + ImGui.EndPopup(); } + } + + // When UI is hidden draw a minimal in world hud + private static void DrawHud(SampleContext context, float frameTime) + { + string category = SampleFactory.Shared.GetCategory(context.sampleIndex); + string name = SampleFactory.Shared.GetName(context.sampleIndex); + float fontSize = ImGui.GetFontSize(); + + DrawScreenString(context.draw, 5.0f, 1.5f * fontSize, B2HexColor.b2_colorYellow, $"{category} : {name}"); + DrawScreenString(context.draw, 5.0f, context.camera.height - 0.5f * fontSize, B2HexColor.b2_colorSeaGreen, + FormattableString.Invariant($"{1000.0f * frameTime:0.0} ms step {context.sample.m_stepCount}")); + } + + private static Vector4 MakeColor(B2HexColor color) + { + uint hex = (uint)color; + return new Vector4(((hex >> 16) & 0xFF) / 255.0f, ((hex >> 8) & 0xFF) / 255.0f, (hex & 0xFF) / 255.0f, 1.0f); + } + + private static void DrawRightPanel(SampleContext context, float frameTime) + { + string name = SampleFactory.Shared.GetName(context.sampleIndex); + string category = SampleFactory.Shared.GetCategory(context.sampleIndex); + float fontSize = ImGui.GetFontSize(); + float menuWidth = 14.0f * fontSize; float menuBarHeight = ImGui.GetFrameHeight(); @@ -1412,37 +1385,33 @@ public static void UpdateSampleUI(SampleContext context) ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoTitleBar); - for (int i = 0; i < context.sample.m_hudLineCount; ++i) - { - HudLine line = context.sample.m_hudLines[i]; - if (string.IsNullOrEmpty(line.text)) - { - ImGui.Separator(); - continue; - } - ImGui.PushStyleColor(ImGuiCol.Text, HexToColor(line.color)); - ImGui.TextUnformatted(line.text); - ImGui.PopStyleColor(); - } + ImGui.TextColored(MakeColor(B2HexColor.b2_colorGoldenRod), name); + ImGui.TextColored(MakeColor(B2HexColor.b2_colorLightGray), category); + ImGui.Separator(); + ImGui.TextColored(MakeColor(B2HexColor.b2_colorSeaGreen), FormattableString.Invariant($"{1000.0f * frameTime:0.0} ms")); + ImGui.TextColored(MakeColor(B2HexColor.b2_colorSeaGreen), $"step {context.sample.m_stepCount}"); + ImGui.Separator(); + ImGui.TextColored(MakeColor(B2HexColor.b2_colorSeaGreen), + FormattableString.Invariant($"cam ({context.camera.center.X:0.0}, {context.camera.center.Y:0.0})")); + ImGui.TextColored(MakeColor(B2HexColor.b2_colorSeaGreen), + FormattableString.Invariant($"zoom {context.camera.zoom:0.00}")); + + ImGui.Separator(); - if (context.sample.m_hudLineCount > 0) + if (context.sample.DrawControls()) { ImGui.Separator(); } - context.sample.BuildSamplePanel(); - - ImGui.Separator(); - if (ImGui.CollapsingHeader("Solver", ImGuiTreeNodeFlags.DefaultOpen)) { ImGui.PushItemWidth(6.0f * fontSize); ImGui.SliderInt("Sub-steps", ref context.subStepCount, 1, 32); ImGui.SliderFloat("Hertz", ref context.hertz, 5.0f, 240.0f, "%.0f hz"); - if (ImGui.SliderInt("Workers", ref context.workerCount, 1, maxWorkers)) + if (ImGui.SliderInt("Workers", ref context.workerCount, 1, B2_MAX_WORKERS)) { - context.workerCount = b2ClampInt(context.workerCount, 1, maxWorkers); + context.workerCount = b2ClampInt(context.workerCount, 1, B2_MAX_WORKERS); SelectSample(context, context.sampleIndex, true); } @@ -1460,8 +1429,23 @@ public static void UpdateSampleUI(SampleContext context) } ImGui.End(); + } + + // Entry point for all UI drawing. This should not be a member of Sample because + // this can delete the current sample. + public static void DrawUI(SampleContext context, float frameTime) + { + if (context.showUI == false) + { + // Minimal hud + DrawHud(context, frameTime); + return; + } - context.sample.UpdateGui(); + DrawMenuBar(context); + DrawSamplePicker(context); + DrawRightPanel(context, frameTime); + context.sample.DrawMetrics(); } diff --git a/src/Box2D.NET.Samples/Samples/Shapes/ChainSegmentShape.cs b/src/Box2D.NET.Samples/Samples/Shapes/ChainSegmentShape.cs index 0eadbb1e..e42a7127 100644 --- a/src/Box2D.NET.Samples/Samples/Shapes/ChainSegmentShape.cs +++ b/src/Box2D.NET.Samples/Samples/Shapes/ChainSegmentShape.cs @@ -162,7 +162,7 @@ public void Mutate() } } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); string[] shapeTypes = { "Circle", "Capsule", "Box" }; @@ -184,6 +184,8 @@ public override void BuildSamplePanel() { Mutate(); } + + return true; } public override void Step() diff --git a/src/Box2D.NET.Samples/Samples/Shapes/ChainShape.cs b/src/Box2D.NET.Samples/Samples/Shapes/ChainShape.cs index 3ebb102e..20769687 100644 --- a/src/Box2D.NET.Samples/Samples/Shapes/ChainShape.cs +++ b/src/Box2D.NET.Samples/Samples/Shapes/ChainShape.cs @@ -185,7 +185,7 @@ public override void Draw() // DrawTextLine($"toi calls, hits = {b2_toiCalls}, {b2_toiHitCount}"); } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); string[] shapeTypes = { "Circle", "Capsule", "Box" }; @@ -213,5 +213,7 @@ public override void BuildSamplePanel() { Launch(); } + + return true; } } diff --git a/src/Box2D.NET.Samples/Samples/Shapes/CompoundShapes.cs b/src/Box2D.NET.Samples/Samples/Shapes/CompoundShapes.cs index c0b1b951..e8de1c22 100644 --- a/src/Box2D.NET.Samples/Samples/Shapes/CompoundShapes.cs +++ b/src/Box2D.NET.Samples/Samples/Shapes/CompoundShapes.cs @@ -194,7 +194,7 @@ void Spawn() } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -206,6 +206,8 @@ public override void BuildSamplePanel() ImGui.Checkbox("Body AABBs", ref m_drawBodyAABBs); + + return true; } public override void Draw() @@ -227,4 +229,4 @@ public override void Draw() DrawBounds(m_draw, aabb, B2HexColor.b2_colorYellow); } } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Shapes/Explosion.cs b/src/Box2D.NET.Samples/Samples/Shapes/Explosion.cs index ef2c6afd..c3c9418e 100644 --- a/src/Box2D.NET.Samples/Samples/Shapes/Explosion.cs +++ b/src/Box2D.NET.Samples/Samples/Shapes/Explosion.cs @@ -13,6 +13,7 @@ using static Box2D.NET.B2Shapes; using static Box2D.NET.B2Worlds; using static Box2D.NET.Samples.Graphics.Draws; +using static Box2D.NET.Samples.SampleText; namespace Box2D.NET.Samples.Samples.Shapes; @@ -80,7 +81,7 @@ public Explosion(SampleContext context) : base(context) m_impulse = 10.0f; } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -99,6 +100,8 @@ public override void BuildSamplePanel() ImGui.SliderFloat("falloff", ref m_falloff, 0.0f, 20.0f, "%.1f"); ImGui.SliderFloat("impulse", ref m_impulse, -20.0f, 20.0f, "%.1f"); ImGui.PopItemWidth(); + + return true; } public override void Step() @@ -124,7 +127,7 @@ public override void Draw() { base.Draw(); - DrawTextLine($"reference angle = {m_referenceAngle:g}"); + DrawScreenTextLine($"reference angle = {FormatFloat(m_referenceAngle)}"); DrawCircle(m_draw, b2Vec2_zero, m_radius + m_falloff, B2HexColor.b2_colorBox2DBlue); DrawCircle(m_draw, b2Vec2_zero, m_radius, B2HexColor.b2_colorBox2DYellow); diff --git a/src/Box2D.NET.Samples/Samples/Shapes/ModifyGeometry.cs b/src/Box2D.NET.Samples/Samples/Shapes/ModifyGeometry.cs index 87472e9c..2c8e15e5 100644 --- a/src/Box2D.NET.Samples/Samples/Shapes/ModifyGeometry.cs +++ b/src/Box2D.NET.Samples/Samples/Shapes/ModifyGeometry.cs @@ -108,7 +108,7 @@ void UpdateShape() b2Body_ApplyMassFromShapes(bodyId); } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -160,5 +160,7 @@ public override void BuildSamplePanel() { b2Body_SetType(bodyId, B2BodyType.b2_dynamicBody); } + + return true; } } diff --git a/src/Box2D.NET.Samples/Samples/Shapes/Restitution.cs b/src/Box2D.NET.Samples/Samples/Shapes/Restitution.cs index 853cca59..58d2824a 100644 --- a/src/Box2D.NET.Samples/Samples/Shapes/Restitution.cs +++ b/src/Box2D.NET.Samples/Samples/Shapes/Restitution.cs @@ -104,7 +104,7 @@ void CreateBodies() } } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); bool changed = false; @@ -122,5 +122,7 @@ public override void BuildSamplePanel() { CreateBodies(); } + + return true; } } diff --git a/src/Box2D.NET.Samples/Samples/Shapes/ShapeFilter.cs b/src/Box2D.NET.Samples/Samples/Shapes/ShapeFilter.cs index e788f101..aae53467 100644 --- a/src/Box2D.NET.Samples/Samples/Shapes/ShapeFilter.cs +++ b/src/Box2D.NET.Samples/Samples/Shapes/ShapeFilter.cs @@ -88,7 +88,7 @@ public ShapeFilter(SampleContext context) : base(context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -124,6 +124,8 @@ public override void BuildSamplePanel() b2Shape_SetFilter(m_shape1Id, filter1); } + + return true; } ImGui.Separator(); @@ -197,8 +199,6 @@ public override void BuildSamplePanel() b2Shape_SetFilter(m_shape3Id, filter3); } } - - } public override void Draw() @@ -214,4 +214,4 @@ public override void Draw() B2Vec2 p3 = b2Body_GetPosition(m_player3Id); DrawWorldString(m_draw, m_camera, new B2Vec2(p3.X - 0.5f, p3.Y), B2HexColor.b2_colorWhite, "player 3"); } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Shapes/TangentSpeed.cs b/src/Box2D.NET.Samples/Samples/Shapes/TangentSpeed.cs index 8db394b8..3a7791aa 100644 --- a/src/Box2D.NET.Samples/Samples/Shapes/TangentSpeed.cs +++ b/src/Box2D.NET.Samples/Samples/Shapes/TangentSpeed.cs @@ -114,7 +114,7 @@ void Reset() m_bodyIds.Clear(); } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); @@ -129,6 +129,8 @@ public override void BuildSamplePanel() Reset(); } ImGui.PopItemWidth(); + + return true; } public override void Step() diff --git a/src/Box2D.NET.Samples/Samples/Shapes/Wind.cs b/src/Box2D.NET.Samples/Samples/Shapes/Wind.cs index dd485261..358bb6b7 100644 --- a/src/Box2D.NET.Samples/Samples/Shapes/Wind.cs +++ b/src/Box2D.NET.Samples/Samples/Shapes/Wind.cs @@ -128,7 +128,7 @@ private void CreateScene() } } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); @@ -153,6 +153,8 @@ public override void BuildSamplePanel() ImGui.PopItemWidth(); + + return true; } public override void Step() @@ -189,4 +191,4 @@ public override void Draw() base.Draw(); DrawLine(m_draw, b2Vec2_zero, b2MulSV(0.2f, m_current_wind), B2HexColor.b2_colorFuchsia); } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Stackings/CircleImpulse.cs b/src/Box2D.NET.Samples/Samples/Stackings/CircleImpulse.cs index 04afd85c..82c265e3 100644 --- a/src/Box2D.NET.Samples/Samples/Stackings/CircleImpulse.cs +++ b/src/Box2D.NET.Samples/Samples/Stackings/CircleImpulse.cs @@ -105,7 +105,7 @@ void Spawn() b2Body_SetMassData(m_bodyId, massData); } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -120,6 +120,8 @@ public override void BuildSamplePanel() } + + return true; } public override void Step() diff --git a/src/Box2D.NET.Samples/Samples/Stackings/CircleStack.cs b/src/Box2D.NET.Samples/Samples/Stackings/CircleStack.cs index 2ff68b8d..3f97f074 100644 --- a/src/Box2D.NET.Samples/Samples/Stackings/CircleStack.cs +++ b/src/Box2D.NET.Samples/Samples/Stackings/CircleStack.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2025 Erin Catto +// SPDX-FileCopyrightText: 2025 Erin Catto // SPDX-FileCopyrightText: 2025 Ikpil Choi(ikpil@naver.com) // SPDX-License-Identifier: MIT @@ -111,7 +111,7 @@ public override void Draw() int eventCount = m_events.Count; for (int i = 0; i < eventCount; ++i) { - DrawTextLine($"{m_events[i].indexA}, {m_events[i].indexB}"); + DrawScreenTextLine($"{m_events[i].indexA}, {m_events[i].indexB}"); } } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Stackings/Cliff.cs b/src/Box2D.NET.Samples/Samples/Stackings/Cliff.cs index c6432e3b..965623ae 100644 --- a/src/Box2D.NET.Samples/Samples/Stackings/Cliff.cs +++ b/src/Box2D.NET.Samples/Samples/Stackings/Cliff.cs @@ -142,7 +142,7 @@ void CreateBodies() } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -153,5 +153,7 @@ public override void BuildSamplePanel() } + + return true; } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Stackings/SingleBox.cs b/src/Box2D.NET.Samples/Samples/Stackings/SingleBox.cs index 26bd62aa..4364a539 100644 --- a/src/Box2D.NET.Samples/Samples/Stackings/SingleBox.cs +++ b/src/Box2D.NET.Samples/Samples/Stackings/SingleBox.cs @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2025 Erin Catto +// SPDX-FileCopyrightText: 2025 Erin Catto // SPDX-FileCopyrightText: 2025 Ikpil Choi(ikpil@naver.com) // SPDX-License-Identifier: MIT @@ -6,6 +6,7 @@ using static Box2D.NET.B2Types; using static Box2D.NET.B2Bodies; using static Box2D.NET.B2Shapes; +using static Box2D.NET.Samples.SampleText; namespace Box2D.NET.Samples.Samples.Stackings; @@ -56,6 +57,6 @@ public override void Draw() // m_context.g_draw.DrawCircle({0.0f, 2.0f}, 1.0f, b2HexColor.b2_colorWhite); B2Vec2 position = b2Body_GetPosition(m_bodyId); - DrawTextLine($"(x, y) = ({position.X:G2}, {position.Y:G2})"); + DrawScreenTextLine($"(x, y) = ({FormatFloat(position.X, 2)}, {FormatFloat(position.Y, 2)})"); } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Stackings/VerticalStack.cs b/src/Box2D.NET.Samples/Samples/Stackings/VerticalStack.cs index e80d7b24..8c340a77 100644 --- a/src/Box2D.NET.Samples/Samples/Stackings/VerticalStack.cs +++ b/src/Box2D.NET.Samples/Samples/Stackings/VerticalStack.cs @@ -242,7 +242,7 @@ public override void Keyboard(Keys key) } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -286,5 +286,7 @@ public override void BuildSamplePanel() } + + return true; } -} \ No newline at end of file +} diff --git a/src/Box2D.NET.Samples/Samples/Worlds/LargeWorld.cs b/src/Box2D.NET.Samples/Samples/Worlds/LargeWorld.cs index fc3f2178..4b569225 100644 --- a/src/Box2D.NET.Samples/Samples/Worlds/LargeWorld.cs +++ b/src/Box2D.NET.Samples/Samples/Worlds/LargeWorld.cs @@ -167,7 +167,7 @@ public LargeWorld(SampleContext context) : base(context) m_followCar = false; } - public override void BuildSamplePanel() + public override bool DrawControls() { ImGui.PushItemWidth(6.0f * ImGui.GetFontSize()); ImGui.SliderFloat("speed", ref m_speed, -400.0f, 400.0f, "%.0f"); @@ -182,6 +182,8 @@ public override void BuildSamplePanel() ImGui.Text($"world size = {m_gridSize * m_gridCount / 1000.0f} kilometers"); + + return true; } public override void Step() diff --git a/src/Box2D.NET.Samples/Settings.cs b/src/Box2D.NET.Samples/Settings.cs index 3d172a7e..80a82393 100644 --- a/src/Box2D.NET.Samples/Settings.cs +++ b/src/Box2D.NET.Samples/Settings.cs @@ -45,7 +45,7 @@ public static Settings CopyFrom(SampleContext context) setting.sampleIndex = context.sampleIndex; setting.drawShapes = context.debugDraw.drawShapes; setting.drawJoints = context.debugDraw.drawJoints; - setting.showDiagnostics = context.showDiagnostics; + setting.showDiagnostics = context.showMetrics; return setting; } diff --git a/test/Box2D.NET.Test/SampleTextTests.cs b/test/Box2D.NET.Test/SampleTextTests.cs index 329aedb3..310a1302 100644 --- a/test/Box2D.NET.Test/SampleTextTests.cs +++ b/test/Box2D.NET.Test/SampleTextTests.cs @@ -33,4 +33,12 @@ public void FormatFloatDoesNotUseCurrentCulture() CultureInfo.CurrentCulture = previousCulture; } } + + [TestCase(1.26f, 2, "1.3")] + [TestCase(123.456f, 2, "1.2e+02")] + [TestCase(0.001234f, 2, "0.0012")] + public void FormatFloatSupportsPrintfGeneralFormatPrecision(float value, int precision, string expected) + { + Assert.That(SampleText.FormatFloat(value, precision), Is.EqualTo(expected)); + } }