From 7776971c8508d2a987b9bf09f2d2104e859f1d06 Mon Sep 17 00:00:00 2001 From: ikpil Date: Fri, 14 Aug 2026 01:00:14 +0900 Subject: [PATCH 1/2] [upstream] clean up UI code (erincatto/box2d#1062) organized UI functions better retina display uses vector font Ported erincatto/box2d@f2086ed638be65eca10830719566a95d94e1bde3 to C#. --- src/Box2D.NET.Samples/SampleApp.cs | 120 ++--- src/Box2D.NET.Samples/SampleContext.cs | 4 +- .../Samples/Benchmarks/BenchmarkBarrel.cs | 4 +- .../Samples/Benchmarks/BenchmarkCast.cs | 12 +- .../Benchmarks/BenchmarkManyTumblers.cs | 6 +- .../Benchmarks/BenchmarkShapeDistance.cs | 10 +- .../Samples/Benchmarks/BenchmarkSleep.cs | 8 +- .../Samples/Benchmarks/BenchmarkSmash.cs | 6 +- .../Samples/Benchmarks/BenchmarkSpinner.cs | 4 +- .../Samples/Benchmarks/BenchmarkWasher.cs | 4 +- .../Samples/Bodies/BodyType.cs | 6 +- .../Samples/Bodies/SetVelocity.cs | 4 +- src/Box2D.NET.Samples/Samples/Bodies/Sleep.cs | 8 +- .../Samples/Bodies/WakeTouching.cs | 6 +- .../Samples/Bodies/Weeble.cs | 6 +- .../Samples/Characters/Mover.cs | 10 +- .../Samples/Collisions/CastWorld.cs | 4 +- .../Samples/Collisions/DynamicTree.cs | 10 +- .../Samples/Collisions/Manifold.cs | 6 +- .../Samples/Collisions/OverlapWorld.cs | 4 +- .../Samples/Collisions/RayCast.cs | 4 +- .../Samples/Collisions/ShapeCast.cs | 4 +- .../Samples/Collisions/ShapeDistance.cs | 8 +- .../Samples/Collisions/SmoothManifold.cs | 4 +- .../Samples/Collisions/TimeOfImpact.cs | 6 +- .../Samples/Continuous/BounceHouse.cs | 4 +- .../Samples/Continuous/ChainDrop.cs | 4 +- .../Samples/Continuous/GhostBumps.cs | 6 +- .../Samples/Continuous/SkinnyBox.cs | 6 +- .../Samples/Events/BodyMove.cs | 6 +- .../Samples/Events/ContactEvent.cs | 4 +- .../Samples/Events/FootSensor.cs | 6 +- .../Samples/Events/Platform.cs | 6 +- .../Samples/Events/SensorBookend.cs | 12 +- .../Samples/Events/SensorFunnel.cs | 6 +- .../Samples/Events/SensorHits.cs | 10 +- .../Samples/Geometries/ConvexHull.cs | 4 +- .../Samples/Issues/Crash01.cs | 6 +- .../Samples/Issues/DisableCrash.cs | 6 +- .../Samples/Joints/BallAndChain.cs | 4 +- .../Samples/Joints/BreakableJoint.cs | 4 +- .../Samples/Joints/Bridge.cs | 6 +- .../Samples/Joints/Cantilever.cs | 6 +- .../Samples/Joints/DistanceJoint.cs | 6 +- src/Box2D.NET.Samples/Samples/Joints/Door.cs | 6 +- .../Samples/Joints/Driving.cs | 6 +- .../Samples/Joints/GearLift.cs | 4 +- .../Samples/Joints/JointSeparation.cs | 4 +- .../Samples/Joints/MotionLocks.cs | 6 +- .../Samples/Joints/MotorJoint.cs | 4 +- .../Samples/Joints/PrismaticJoint.cs | 10 +- .../Samples/Joints/Ragdoll.cs | 4 +- .../Samples/Joints/RevoluteJoint.cs | 10 +- .../Samples/Joints/ScaleRagdoll.cs | 4 +- .../Samples/Joints/ScissorLift.cs | 4 +- .../Samples/Joints/TopDownFriction.cs | 6 +- .../Samples/Joints/UserConstraint.cs | 6 +- .../Samples/Joints/WheelJoint.cs | 6 +- .../Samples/Robustness/Cart.cs | 6 +- .../Samples/Robustness/OverlapRecovery.cs | 6 +- .../Samples/Robustness/TinyPyramid.cs | 4 +- src/Box2D.NET.Samples/Samples/Sample.cs | 494 +++++++++--------- .../Samples/Shapes/ChainSegmentShape.cs | 4 +- .../Samples/Shapes/ChainShape.cs | 4 +- .../Samples/Shapes/CompoundShapes.cs | 6 +- .../Samples/Shapes/Explosion.cs | 6 +- .../Samples/Shapes/ModifyGeometry.cs | 4 +- .../Samples/Shapes/Restitution.cs | 4 +- .../Samples/Shapes/ShapeFilter.cs | 8 +- .../Samples/Shapes/TangentSpeed.cs | 4 +- src/Box2D.NET.Samples/Samples/Shapes/Wind.cs | 6 +- .../Samples/Stackings/CircleImpulse.cs | 4 +- .../Samples/Stackings/CircleStack.cs | 6 +- .../Samples/Stackings/Cliff.cs | 6 +- .../Samples/Stackings/SingleBox.cs | 6 +- .../Samples/Stackings/VerticalStack.cs | 6 +- .../Samples/Worlds/LargeWorld.cs | 4 +- src/Box2D.NET.Samples/Settings.cs | 2 +- 78 files changed, 549 insertions(+), 501 deletions(-) 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/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..79445a9f 100644 --- a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkCast.cs +++ b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkCast.cs @@ -321,7 +321,7 @@ public override void Step() } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -387,25 +387,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 = {m_buildTime:g}"); DrawScreenTextLine($"hit count = {hitCount}, node visits = {nodeVisits}, leaf visits = {leafVisits}"); - DrawTextLine($"total ms = {ms:F3}"); + DrawScreenTextLine($"total ms = {ms:F3}"); - DrawTextLine($"min total ms = {m_minTime:F3}"); + DrawScreenTextLine($"min total ms = {m_minTime:F3}"); float aveRayCost = 1000.0f * m_minTime / (float)sampleCount; - DrawTextLine($"average us = {aveRayCost:F2}"); + DrawScreenTextLine($"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..0e006d65 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 = {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 = {output.distance}"); } } diff --git a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSleep.cs b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSleep.cs index f09e2e8a..86ff93ef 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 @@ -127,7 +127,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 = {m_wakeTotal / count:g} ms"); + DrawScreenTextLine($"sleep ave = {m_sleepTotal / count:g} 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..09be7821 100644 --- a/src/Box2D.NET.Samples/Samples/Bodies/SetVelocity.cs +++ b/src/Box2D.NET.Samples/Samples/Bodies/SetVelocity.cs @@ -61,6 +61,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) = {position.X:G}, {position.Y:G})"); } -} \ 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..ba76f24c 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]}"); } } -} \ 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..023d1e28 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($"position {p.X:F2} {p.Y:F2}"); + DrawScreenTextLine($"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..bdcbeaad 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($"incremental : {_ms:F3} ms"); } break; case UpdateType.Update_FullRebuild: { - DrawTextLine($"full build {_boxCount} : {_ms:F3} ms"); + DrawScreenTextLine($"full build {_boxCount} : {_ms:F3} ms"); } break; case UpdateType.Update_PartialRebuild: { - DrawTextLine($"partial rebuild {_boxCount} : {_ms:F3} ms"); + DrawScreenTextLine($"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..6922f73e 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 @@ -73,7 +73,7 @@ public override void Draw() { base.Draw(); - DrawTextLine($"toi = {_output.fraction:g}"); + DrawScreenTextLine($"toi = {_output.fraction:g}"); B2Vec2[] vertices = new B2Vec2[B2_MAX_POLYGON_VERTICES]; @@ -126,7 +126,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 = {distanceOutput.distance}:g"); } 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..74b0b2eb 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}"); } } diff --git a/src/Box2D.NET.Samples/Samples/Events/SensorBookend.cs b/src/Box2D.NET.Samples/Samples/Events/SensorBookend.cs index c3816d27..79036ffc 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}"); + DrawScreenTextLine($"visiting 2 == {m_isVisiting2}"); + 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..a29b6b6b 100644 --- a/src/Box2D.NET.Samples/Samples/Geometries/ConvexHull.cs +++ b/src/Box2D.NET.Samples/Samples/Geometries/ConvexHull.cs @@ -196,7 +196,7 @@ public override void Draw() if (m_valid == false) { - DrawTextLine($"generation = {m_generation}, FAILED"); + DrawScreenTextLine($"generation = {m_generation}, FAILED"); } else @@ -207,7 +207,7 @@ public override void Draw() if (m_milliseconds > 0.0f) { - DrawTextLine($"milliseconds = {m_milliseconds:G}"); + DrawScreenTextLine($"milliseconds = {m_milliseconds:G}"); } 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..46783c7a 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($"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..73ad4063 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/Door.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/Door.cs @@ -91,7 +91,7 @@ public Door(SampleContext context) : base(context) } } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -122,6 +122,8 @@ public override void BuildSamplePanel() { b2RevoluteJoint_EnableLimit(m_jointId, m_enableLimit); } + + return true; } public override void Draw() @@ -134,6 +136,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 = {m_translationError}"); } } diff --git a/src/Box2D.NET.Samples/Samples/Joints/Driving.cs b/src/Box2D.NET.Samples/Samples/Joints/Driving.cs index a83cc801..72efa261 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/Driving.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/Driving.cs @@ -211,7 +211,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 +239,8 @@ public override void BuildSamplePanel() ImGui.PopItemWidth(); + + return true; } public override void Step() @@ -273,7 +275,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: {kph:G2}"); 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..c2afd757 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($"Motor Force = {force:4,F1}"); float translation = b2PrismaticJoint_GetTranslation(m_jointId); - DrawTextLine($"Translation = {translation:4,F1}"); + DrawScreenTextLine($"Translation = {translation:4,F1}"); float speed = b2PrismaticJoint_GetSpeed(m_jointId); - DrawTextLine($"Speed = {speed:4,F8}"); + DrawScreenTextLine($"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..95328590 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($"Angle (Deg) 1 = {angle1:F1}"); float torque1 = b2RevoluteJoint_GetMotorTorque(m_jointId1); - DrawTextLine($"Motor Torque 1 = {torque1:F1}"); + DrawScreenTextLine($"Motor Torque 1 = {torque1:F1}"); float torque2 = b2RevoluteJoint_GetMotorTorque(m_jointId2); - DrawTextLine($"Motor Torque 2 = {torque2:F1}"); + DrawScreenTextLine($"Motor Torque 2 = {torque2: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..d4f62b2d 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 @@ -135,6 +135,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 = {m_impulses[0] * invTimeStep:g}, {m_impulses[1] * invTimeStep:g}"); } -} \ 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..fb40777b 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($"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..ef5982b6 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($"{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..7bf1bf00 100644 --- a/src/Box2D.NET.Samples/Samples/Shapes/Explosion.cs +++ b/src/Box2D.NET.Samples/Samples/Shapes/Explosion.cs @@ -80,7 +80,7 @@ public Explosion(SampleContext context) : base(context) m_impulse = 10.0f; } - public override void BuildSamplePanel() + public override bool DrawControls() { @@ -99,6 +99,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 +126,7 @@ public override void Draw() { base.Draw(); - DrawTextLine($"reference angle = {m_referenceAngle:g}"); + DrawScreenTextLine($"reference angle = {m_referenceAngle:g}"); 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..7b18603a 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 @@ -56,6 +56,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) = ({position.X:G2}, {position.Y:G2})"); } -} \ 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; } From 6940320d6a7bfb57b0695430850456d83cf3b105 Mon Sep 17 00:00:00 2001 From: ikpil Date: Fri, 14 Aug 2026 01:14:09 +0900 Subject: [PATCH 2/2] [upstream] Fix sample UI text fidelity (erincatto/box2d#1062) Follow up the C# port of erincatto/box2d@f2086ed638be65eca10830719566a95d94e1bde3 by matching the printf output used by the samples after HUD text moved to ImGui. Extend FormatFloat with printf-style precision, preserve invariant decimal formatting and lowercase boolean text, and correct malformed interpolation in the TOI, prismatic joint, velocity, benchmark, and diagnostic displays. This keeps the visible labels, precision, alignment, and punctuation consistent with the original samples. Add regression coverage for general-format precision. Verified with Debug and Release solution builds and the full net8.0, net9.0, and net10.0 test matrix. --- src/Box2D.NET.Samples/SampleText.cs | 4 ++-- .../Samples/Benchmarks/BenchmarkCast.cs | 9 +++++---- .../Samples/Benchmarks/BenchmarkShapeDistance.cs | 4 ++-- .../Samples/Benchmarks/BenchmarkSleep.cs | 5 +++-- src/Box2D.NET.Samples/Samples/Bodies/SetVelocity.cs | 3 ++- src/Box2D.NET.Samples/Samples/Bodies/Sleep.cs | 2 +- src/Box2D.NET.Samples/Samples/Characters/Mover.cs | 4 ++-- src/Box2D.NET.Samples/Samples/Collisions/DynamicTree.cs | 6 +++--- src/Box2D.NET.Samples/Samples/Collisions/TimeOfImpact.cs | 5 +++-- src/Box2D.NET.Samples/Samples/Events/Platform.cs | 2 +- src/Box2D.NET.Samples/Samples/Events/SensorBookend.cs | 4 ++-- src/Box2D.NET.Samples/Samples/Geometries/ConvexHull.cs | 3 ++- src/Box2D.NET.Samples/Samples/Joints/Cantilever.cs | 2 +- src/Box2D.NET.Samples/Samples/Joints/Door.cs | 3 ++- src/Box2D.NET.Samples/Samples/Joints/Driving.cs | 3 ++- src/Box2D.NET.Samples/Samples/Joints/PrismaticJoint.cs | 6 +++--- src/Box2D.NET.Samples/Samples/Joints/RevoluteJoint.cs | 6 +++--- src/Box2D.NET.Samples/Samples/Joints/UserConstraint.cs | 3 ++- src/Box2D.NET.Samples/Samples/Joints/WheelJoint.cs | 2 +- src/Box2D.NET.Samples/Samples/Robustness/TinyPyramid.cs | 2 +- src/Box2D.NET.Samples/Samples/Shapes/Explosion.cs | 3 ++- src/Box2D.NET.Samples/Samples/Stackings/SingleBox.cs | 3 ++- test/Box2D.NET.Test/SampleTextTests.cs | 8 ++++++++ 23 files changed, 55 insertions(+), 37 deletions(-) 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/BenchmarkCast.cs b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkCast.cs index 79445a9f..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; @@ -395,19 +396,19 @@ public override void Draw() { base.Draw(); - DrawScreenTextLine($"build time ms = {m_buildTime:g}"); + DrawScreenTextLine($"build time ms = {FormatFloat(m_buildTime)}"); DrawScreenTextLine($"hit count = {hitCount}, node visits = {nodeVisits}, leaf visits = {leafVisits}"); - DrawScreenTextLine($"total ms = {ms:F3}"); + DrawScreenTextLine(System.FormattableString.Invariant($"total ms = {ms:F3}")); - DrawScreenTextLine($"min total ms = {m_minTime:F3}"); + DrawScreenTextLine(System.FormattableString.Invariant($"min total ms = {m_minTime:F3}")); float aveRayCost = 1000.0f * m_minTime / (float)sampleCount; - DrawScreenTextLine($"average us = {aveRayCost:F2}"); + DrawScreenTextLine(System.FormattableString.Invariant($"average us = {aveRayCost:F2}")); } } diff --git a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkShapeDistance.cs b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkShapeDistance.cs index 0e006d65..cd9ac75c 100644 --- a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkShapeDistance.cs +++ b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkShapeDistance.cs @@ -143,7 +143,7 @@ public override void Draw() { DrawScreenTextLine($"count = {m_count}"); DrawScreenTextLine($"min ms = {FormatFloat(m_minMilliseconds)}, ave us = {FormatFloat(1000.0f * m_minMilliseconds / (float)m_count)}"); - DrawScreenTextLine($"average iterations = {totalIterations / (float)m_count}"); + DrawScreenTextLine($"average iterations = {FormatFloat(totalIterations / (float)m_count)}"); } B2Transform xfA = m_transformAs[m_drawIndex]; @@ -155,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); - DrawScreenTextLine($"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 86ff93ef..196e06e9 100644 --- a/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSleep.cs +++ b/src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSleep.cs @@ -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; - DrawScreenTextLine($"wake ave = {m_wakeTotal / count:g} ms"); - DrawScreenTextLine($"sleep ave = {m_sleepTotal / count:g} ms"); + DrawScreenTextLine($"wake ave = {FormatFloat(m_wakeTotal / count)} ms"); + DrawScreenTextLine($"sleep ave = {FormatFloat(m_sleepTotal / count)} ms"); } } diff --git a/src/Box2D.NET.Samples/Samples/Bodies/SetVelocity.cs b/src/Box2D.NET.Samples/Samples/Bodies/SetVelocity.cs index 09be7821..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); - DrawScreenTextLine($"(x, y) = {position.X:G}, {position.Y:G})"); + DrawScreenTextLine($"(x, y) = ({FormatFloat(position.X, 2)}, {FormatFloat(position.Y, 2)})"); } } diff --git a/src/Box2D.NET.Samples/Samples/Bodies/Sleep.cs b/src/Box2D.NET.Samples/Samples/Bodies/Sleep.cs index ba76f24c..acc34e6a 100644 --- a/src/Box2D.NET.Samples/Samples/Bodies/Sleep.cs +++ b/src/Box2D.NET.Samples/Samples/Bodies/Sleep.cs @@ -262,7 +262,7 @@ public override void Draw() for (int i = 0; i < 2; ++i) { - DrawScreenTextLine($"sensor touch {i} = {m_sensorTouching[i]}"); + DrawScreenTextLine($"sensor touch {i} = {(m_sensorTouching[i] ? "true" : "false")}"); } } } diff --git a/src/Box2D.NET.Samples/Samples/Characters/Mover.cs b/src/Box2D.NET.Samples/Samples/Characters/Mover.cs index 023d1e28..4a11c7fe 100644 --- a/src/Box2D.NET.Samples/Samples/Characters/Mover.cs +++ b/src/Box2D.NET.Samples/Samples/Characters/Mover.cs @@ -635,8 +635,8 @@ public override void Draw() } B2Vec2 p = m_transform.p; - DrawScreenTextLine($"position {p.X:F2} {p.Y:F2}"); - DrawScreenTextLine($"velocity {m_velocity.X:F2}, {m_velocity.Y:F2}"); + 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/DynamicTree.cs b/src/Box2D.NET.Samples/Samples/Collisions/DynamicTree.cs index bdcbeaad..2beca3d6 100644 --- a/src/Box2D.NET.Samples/Samples/Collisions/DynamicTree.cs +++ b/src/Box2D.NET.Samples/Samples/Collisions/DynamicTree.cs @@ -450,19 +450,19 @@ public override void Draw() { case UpdateType.Update_Incremental: { - DrawScreenTextLine($"incremental : {_ms:F3} ms"); + DrawScreenTextLine(System.FormattableString.Invariant($"incremental : {_ms:F3} ms")); } break; case UpdateType.Update_FullRebuild: { - DrawScreenTextLine($"full build {_boxCount} : {_ms:F3} ms"); + DrawScreenTextLine(System.FormattableString.Invariant($"full build {_boxCount} : {_ms:F3} ms")); } break; case UpdateType.Update_PartialRebuild: { - DrawScreenTextLine($"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/TimeOfImpact.cs b/src/Box2D.NET.Samples/Samples/Collisions/TimeOfImpact.cs index 6922f73e..5dbb39c4 100644 --- a/src/Box2D.NET.Samples/Samples/Collisions/TimeOfImpact.cs +++ b/src/Box2D.NET.Samples/Samples/Collisions/TimeOfImpact.cs @@ -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(); - DrawScreenTextLine($"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); - DrawScreenTextLine($"distance = {distanceOutput.distance}:g"); + DrawScreenTextLine($"distance = {FormatFloat(distanceOutput.distance)}"); } diff --git a/src/Box2D.NET.Samples/Samples/Events/Platform.cs b/src/Box2D.NET.Samples/Samples/Events/Platform.cs index 74b0b2eb..dba0bc5d 100644 --- a/src/Box2D.NET.Samples/Samples/Events/Platform.cs +++ b/src/Box2D.NET.Samples/Samples/Events/Platform.cs @@ -256,6 +256,6 @@ public override void Draw() DrawScreenTextLine("Movement: A/D/Space"); - DrawScreenTextLine($"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 79036ffc..006f32bf 100644 --- a/src/Box2D.NET.Samples/Samples/Events/SensorBookend.cs +++ b/src/Box2D.NET.Samples/Samples/Events/SensorBookend.cs @@ -345,8 +345,8 @@ public override void Draw() { base.Draw(); - DrawScreenTextLine($"visiting 1 == {m_isVisiting1}"); - DrawScreenTextLine($"visiting 2 == {m_isVisiting2}"); + DrawScreenTextLine($"visiting 1 == {(m_isVisiting1 ? "true" : "false")}"); + DrawScreenTextLine($"visiting 2 == {(m_isVisiting2 ? "true" : "false")}"); DrawScreenTextLine($"sensors overlap count == {m_sensorsOverlapCount}"); } } diff --git a/src/Box2D.NET.Samples/Samples/Geometries/ConvexHull.cs b/src/Box2D.NET.Samples/Samples/Geometries/ConvexHull.cs index a29b6b6b..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; @@ -207,7 +208,7 @@ public override void Draw() if (m_milliseconds > 0.0f) { - DrawScreenTextLine($"milliseconds = {m_milliseconds:G}"); + DrawScreenTextLine($"milliseconds = {FormatFloat(m_milliseconds)}"); } diff --git a/src/Box2D.NET.Samples/Samples/Joints/Cantilever.cs b/src/Box2D.NET.Samples/Samples/Joints/Cantilever.cs index 46783c7a..4aee5c1e 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/Cantilever.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/Cantilever.cs @@ -164,6 +164,6 @@ public override void Draw() base.Draw(); B2Vec2 tipPosition = b2Body_GetPosition(m_tipId); - DrawScreenTextLine($"tip-y = {tipPosition.Y:F2}"); + DrawScreenTextLine(System.FormattableString.Invariant($"tip-y = {tipPosition.Y:F2}")); } } diff --git a/src/Box2D.NET.Samples/Samples/Joints/Door.cs b/src/Box2D.NET.Samples/Samples/Joints/Door.cs index 73ad4063..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; @@ -136,6 +137,6 @@ public override void Draw() float translationError = b2Joint_GetLinearSeparation(m_jointId); m_translationError = b2MaxFloat(m_translationError, translationError); - DrawScreenTextLine($"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 72efa261..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; @@ -275,7 +276,7 @@ public override void Draw() B2Vec2 linearVelocity = b2Body_GetLinearVelocity(m_car.m_chassisId); float kph = linearVelocity.X * 3.6f; - DrawScreenTextLine($"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/PrismaticJoint.cs b/src/Box2D.NET.Samples/Samples/Joints/PrismaticJoint.cs index c2afd757..237d5cac 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/PrismaticJoint.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/PrismaticJoint.cs @@ -161,14 +161,14 @@ public override void Draw() base.Draw(); float force = b2PrismaticJoint_GetMotorForce(m_jointId); - DrawScreenTextLine($"Motor Force = {force:4,F1}"); + DrawScreenTextLine(System.FormattableString.Invariant($"Motor Force = {force,4:F1}")); float translation = b2PrismaticJoint_GetTranslation(m_jointId); - DrawScreenTextLine($"Translation = {translation:4,F1}"); + DrawScreenTextLine(System.FormattableString.Invariant($"Translation = {translation,4:F1}")); float speed = b2PrismaticJoint_GetSpeed(m_jointId); - DrawScreenTextLine($"Speed = {speed:4,F8}"); + DrawScreenTextLine(System.FormattableString.Invariant($"Speed = {speed,4:F8}")); } } diff --git a/src/Box2D.NET.Samples/Samples/Joints/RevoluteJoint.cs b/src/Box2D.NET.Samples/Samples/Joints/RevoluteJoint.cs index 95328590..9e921017 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/RevoluteJoint.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/RevoluteJoint.cs @@ -214,13 +214,13 @@ public override void Draw() base.Draw(); float angle1 = b2RevoluteJoint_GetAngle(m_jointId1); - DrawScreenTextLine($"Angle (Deg) 1 = {angle1:F1}"); + DrawScreenTextLine(System.FormattableString.Invariant($"Angle (Deg) 1 = {angle1,2:F1}")); float torque1 = b2RevoluteJoint_GetMotorTorque(m_jointId1); - DrawScreenTextLine($"Motor Torque 1 = {torque1:F1}"); + DrawScreenTextLine(System.FormattableString.Invariant($"Motor Torque 1 = {torque1,4:F1}")); float torque2 = b2RevoluteJoint_GetMotorTorque(m_jointId2); - DrawScreenTextLine($"Motor Torque 2 = {torque2:F1}"); + DrawScreenTextLine(System.FormattableString.Invariant($"Motor Torque 2 = {torque2,4:F1}")); } } diff --git a/src/Box2D.NET.Samples/Samples/Joints/UserConstraint.cs b/src/Box2D.NET.Samples/Samples/Joints/UserConstraint.cs index d4f62b2d..b411fcc3 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/UserConstraint.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/UserConstraint.cs @@ -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; - DrawScreenTextLine($"forces = {m_impulses[0] * invTimeStep:g}, {m_impulses[1] * invTimeStep:g}"); + DrawScreenTextLine($"forces = {FormatFloat(m_impulses[0] * invTimeStep)}, {FormatFloat(m_impulses[1] * invTimeStep)}"); } } diff --git a/src/Box2D.NET.Samples/Samples/Joints/WheelJoint.cs b/src/Box2D.NET.Samples/Samples/Joints/WheelJoint.cs index fb40777b..be18c4ab 100644 --- a/src/Box2D.NET.Samples/Samples/Joints/WheelJoint.cs +++ b/src/Box2D.NET.Samples/Samples/Joints/WheelJoint.cs @@ -142,6 +142,6 @@ public override void Draw() base.Draw(); float torque = b2WheelJoint_GetMotorTorque(m_jointId); - DrawScreenTextLine($"Motor Torque = {torque,4:F1}"); + DrawScreenTextLine(System.FormattableString.Invariant($"Motor Torque = {torque,4:F1}")); } } diff --git a/src/Box2D.NET.Samples/Samples/Robustness/TinyPyramid.cs b/src/Box2D.NET.Samples/Samples/Robustness/TinyPyramid.cs index ef5982b6..f377788b 100644 --- a/src/Box2D.NET.Samples/Samples/Robustness/TinyPyramid.cs +++ b/src/Box2D.NET.Samples/Samples/Robustness/TinyPyramid.cs @@ -71,6 +71,6 @@ public override void Draw() { base.Draw(); - DrawScreenTextLine($"{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/Shapes/Explosion.cs b/src/Box2D.NET.Samples/Samples/Shapes/Explosion.cs index 7bf1bf00..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; @@ -126,7 +127,7 @@ public override void Draw() { base.Draw(); - DrawScreenTextLine($"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/Stackings/SingleBox.cs b/src/Box2D.NET.Samples/Samples/Stackings/SingleBox.cs index 7b18603a..4364a539 100644 --- a/src/Box2D.NET.Samples/Samples/Stackings/SingleBox.cs +++ b/src/Box2D.NET.Samples/Samples/Stackings/SingleBox.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.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); - DrawScreenTextLine($"(x, y) = ({position.X:G2}, {position.Y:G2})"); + DrawScreenTextLine($"(x, y) = ({FormatFloat(position.X, 2)}, {FormatFloat(position.Y, 2)})"); } } 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)); + } }