Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@
<PrivateAssets>all</PrivateAssets>
</PackageVersion>
<PackageVersion Include="Hexa.NET.ImGui" Version="2.2.8.4" />
<PackageVersion Include="Hexa.NET.ImGuizmo" Version="2.2.8.4" />
<PackageVersion Include="Hexa.NET.ImNodes" Version="2.2.8.4" />
<PackageVersion Include="Hexa.NET.ImPlot" Version="2.2.8.4" />
<PackageVersion Include="ktsu.Invoker" Version="1.1.0" />
<PackageVersion Include="ktsu.ScopedAction" Version="1.1.2" />
<PackageVersion Include="ktsu.StrongPaths" Version="1.3.2" />
<PackageVersion Include="ktsu.Extensions" Version="1.5.6" />
<PackageVersion Include="ktsu.Semantics" Version="1.0.19" />
<PackageVersion Include="Silk.NET" Version="2.22.0" />
<PackageVersion Include="Silk.NET.Assimp" Version="2.22.0" />
<PackageVersion Include="Silk.NET.Direct3D12" Version="2.22.0" />
Expand All @@ -21,7 +25,7 @@
<PackageVersion Include="Silk.NET.OpenGLES" Version="2.22.0" />
<PackageVersion Include="Silk.NET.OpenXR" Version="2.22.0" />
<PackageVersion Include="Silk.NET.Windowing.Sdl" Version="2.22.0" />
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.10" />
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.11" />
<PackageVersion Include="System.Text.Json" Version="9.0.7" />
<!-- Test Dependencies -->
<PackageVersion Include="Moq" Version="4.20.72" />
Expand All @@ -33,11 +37,11 @@
<PackageVersion Include="Microsoft.Testing.Extensions.HotReload" Version="1.7.3" />
<PackageVersion Include="Microsoft.Testing.Extensions.Retry" Version="1.7.3" />
<PackageVersion Include="Microsoft.Testing.Extensions.TrxReport" Version="1.7.3" />
<PackageVersion Include="MSTest.TestAdapter" Version="3.9.3" />
<PackageVersion Include="MSTest.TestFramework" Version="3.9.3" />
<PackageVersion Include="MSTest.TestAdapter" Version="3.10.0" />
<PackageVersion Include="MSTest.TestFramework" Version="3.10.0" />
<PackageVersion Include="coverlet.msbuild" Version="6.0.4" />
<!-- SDK Dependencies -->
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="Microsoft.SourceLink.AzureRepos.Git" Version="8.0.0" />
</ItemGroup>
</Project>
</Project>
5 changes: 3 additions & 2 deletions ImGuiApp.Test/AdvancedCoverageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace ktsu.ImGuiApp.Test;
using System;
using Hexa.NET.ImGui;
using ktsu.ImGuiApp.ImGuiController;
using ktsu.Semantics;
using Microsoft.VisualStudio.TestTools.UnitTesting;

/// <summary>
Expand Down Expand Up @@ -179,8 +180,8 @@ public void ImGuiApp_WindowState_MultipleAccess_ReturnsConsistentValues()
[TestMethod]
public void ImGuiApp_Textures_MultipleAccess_ReturnsSameInstance()
{
System.Collections.Concurrent.ConcurrentDictionary<StrongPaths.AbsoluteFilePath, ImGuiAppTextureInfo> textures1 = ImGuiApp.Textures;
System.Collections.Concurrent.ConcurrentDictionary<StrongPaths.AbsoluteFilePath, ImGuiAppTextureInfo> textures2 = ImGuiApp.Textures;
System.Collections.Concurrent.ConcurrentDictionary<AbsoluteFilePath, ImGuiAppTextureInfo> textures1 = ImGuiApp.Textures;
System.Collections.Concurrent.ConcurrentDictionary<AbsoluteFilePath, ImGuiAppTextureInfo> textures2 = ImGuiApp.Textures;

// Should return the same collection instance
Assert.AreSame(textures1, textures2);
Expand Down
2 changes: 1 addition & 1 deletion ImGuiApp.Test/ImGuiAppCoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace ktsu.ImGuiApp.Test;

using System.Collections.Concurrent;
using ktsu.Extensions;
using ktsu.StrongPaths;
using ktsu.Semantics;
using Microsoft.VisualStudio.TestTools.UnitTesting;

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion ImGuiApp.Test/ImGuiAppDataStructureTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace ktsu.ImGuiApp.Test;

using System.Numerics;
using ktsu.Extensions;
using ktsu.StrongPaths;
using ktsu.Semantics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Silk.NET.Windowing;

Expand Down
4 changes: 1 addition & 3 deletions ImGuiApp.Test/ImGuiAppTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@
// All rights reserved.
// Licensed under the MIT license.

using Microsoft.VisualStudio.TestTools.UnitTesting;

[assembly: DoNotParallelize]

namespace ktsu.ImGuiApp.Test;

using System.Numerics;
using ktsu.Extensions;
using ktsu.StrongPaths;
using ktsu.Semantics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Silk.NET.Core.Contexts;
Expand Down
3 changes: 1 addition & 2 deletions ImGuiApp.Test/ImGuiAppWindowManagementTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
namespace ktsu.ImGuiApp.Test;

using System.Numerics;

using ktsu.StrongPaths;
using ktsu.Semantics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Silk.NET.Windowing;
Expand Down
2 changes: 1 addition & 1 deletion ImGuiApp/DebugLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace ktsu.ImGuiApp;

using ktsu.Extensions;
using ktsu.StrongPaths;
using ktsu.Semantics;

/// <summary>
/// Simple file logger for debugging crashes
Expand Down
193 changes: 173 additions & 20 deletions ImGuiApp/ImGuiApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
using ktsu.ImGuiApp.ImGuiController;
using ktsu.Invoker;
using ktsu.ScopedAction;
using ktsu.StrongPaths;
using ktsu.Semantics;
using Silk.NET.Input;
using Silk.NET.OpenGL;
using Silk.NET.Windowing;
Expand All @@ -31,12 +31,12 @@
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "This class is the main entry point for the ImGui application and requires many dependencies. Consider refactoring in the future.")]
public static partial class ImGuiApp
{
internal static IWindow? window;

Check warning on line 34 in ImGuiApp/ImGuiApp.cs

View workflow job for this annotation

GitHub Actions / Build, Test & Release

Change the visibility of 'window' or make it 'const' or 'readonly'. (https://rules.sonarsource.com/csharp/RSPEC-2223)
internal static GL? gl;

Check warning on line 35 in ImGuiApp/ImGuiApp.cs

View workflow job for this annotation

GitHub Actions / Build, Test & Release

Change the visibility of 'gl' or make it 'const' or 'readonly'. (https://rules.sonarsource.com/csharp/RSPEC-2223)
internal static ImGuiController.ImGuiController? controller;

Check warning on line 36 in ImGuiApp/ImGuiApp.cs

View workflow job for this annotation

GitHub Actions / Build, Test & Release

Change the visibility of 'controller' or make it 'const' or 'readonly'. (https://rules.sonarsource.com/csharp/RSPEC-2223)
internal static IInputContext? inputContext;

Check warning on line 37 in ImGuiApp/ImGuiApp.cs

View workflow job for this annotation

GitHub Actions / Build, Test & Release

Change the visibility of 'inputContext' or make it 'const' or 'readonly'. (https://rules.sonarsource.com/csharp/RSPEC-2223)
internal static OpenGLProvider? glProvider;

Check warning on line 38 in ImGuiApp/ImGuiApp.cs

View workflow job for this annotation

GitHub Actions / Build, Test & Release

Change the visibility of 'glProvider' or make it 'const' or 'readonly'. (https://rules.sonarsource.com/csharp/RSPEC-2223)
internal static IntPtr currentGLContextHandle; // Track the current GL context handle

Check warning on line 39 in ImGuiApp/ImGuiApp.cs

View workflow job for this annotation

GitHub Actions / Build, Test & Release

Change the visibility of 'currentGLContextHandle' or make it 'const' or 'readonly'. (https://rules.sonarsource.com/csharp/RSPEC-2223)

internal static ImGuiAppWindowState LastNormalWindowState { get; set; } = new();

Expand All @@ -58,7 +58,7 @@
}

internal static ConcurrentDictionary<string, int> FontIndices { get; } = [];
internal static float lastFontScaleFactor;

Check warning on line 61 in ImGuiApp/ImGuiApp.cs

View workflow job for this annotation

GitHub Actions / Build, Test & Release

Change the visibility of 'lastFontScaleFactor' or make it 'const' or 'readonly'. (https://rules.sonarsource.com/csharp/RSPEC-2223)
internal static readonly List<GCHandle> currentPinnedFontData = [];

/// <summary>
Expand Down Expand Up @@ -91,8 +91,8 @@
/// </summary>
public static bool IsIdle { get; private set; }

internal static DateTime lastInputTime = DateTime.UtcNow;

Check warning on line 94 in ImGuiApp/ImGuiApp.cs

View workflow job for this annotation

GitHub Actions / Build, Test & Release

Change the visibility of 'lastInputTime' or make it 'const' or 'readonly'. (https://rules.sonarsource.com/csharp/RSPEC-2223)
internal static double targetFrameTimeMs = 1000.0 / 30.0; // Default to 30 FPS (33.33ms per frame)

Check warning on line 95 in ImGuiApp/ImGuiApp.cs

View workflow job for this annotation

GitHub Actions / Build, Test & Release

Change the visibility of 'targetFrameTimeMs' or make it 'const' or 'readonly'. (https://rules.sonarsource.com/csharp/RSPEC-2223)
internal static readonly PidFrameLimiter frameLimiter = new();
internal static double previousTargetFrameTimeMs = 1000.0 / 30.0;

Expand All @@ -101,9 +101,16 @@
/// </summary>
internal static void OnUserInput() => lastInputTime = DateTime.UtcNow;

internal static bool showImGuiMetrics;
internal static bool showImGuiDemo;
internal static bool showPerformanceMonitor;
internal static bool isImGuiMetricsVisible;
internal static bool isImGuiDemoVisible;
internal static bool isImGuiStyleEditorVisible;
internal static bool isPerformanceMonitorVisible;

// Track whether we need to focus windows on their first frame
internal static bool shouldFocusImGuiDemo;
internal static bool shouldFocusImGuiMetrics;
internal static bool shouldFocusImGuiStyleEditor;
internal static bool shouldFocusPerformanceMonitor;

// Performance monitoring data structures
internal static readonly Queue<float> performanceFrameTimes = new();
Expand Down Expand Up @@ -133,6 +140,54 @@
window.Close();
}

/// <summary>
/// Opens the ImGui Demo window.
/// </summary>
public static void ShowImGuiDemo()
{
if (!isImGuiDemoVisible)
{
shouldFocusImGuiDemo = true;
}
isImGuiDemoVisible = true;
}

/// <summary>
/// Opens the ImGui Metrics window.
/// </summary>
public static void ShowImGuiMetrics()
{
if (!isImGuiMetricsVisible)
{
shouldFocusImGuiMetrics = true;
}
isImGuiMetricsVisible = true;
}

/// <summary>
/// Opens the ImGui Style Editor window.
/// </summary>
public static void ShowImGuiStyleEditor()
{
if (!isImGuiStyleEditorVisible)
{
shouldFocusImGuiStyleEditor = true;
}
isImGuiStyleEditorVisible = true;
}

/// <summary>
/// Opens the Performance Monitor window.
/// </summary>
public static void ShowPerformanceMonitor()
{
if (!isPerformanceMonitorVisible)
{
shouldFocusPerformanceMonitor = true;
}
isPerformanceMonitorVisible = true;
}

internal static ImGuiAppConfig Config { get; set; } = new();

internal static void InitializeWindow(ImGuiAppConfig config)
Expand Down Expand Up @@ -337,6 +392,8 @@
UpdateWindowPerformance();
UpdatePerformanceMonitoring((float)delta);

// SetupContext prepares ImGui context for this frame
controller?.SetupContext();
controller?.Update((float)delta);
config.OnUpdate?.Invoke((float)delta);
Invoker.DoInvokes();
Expand Down Expand Up @@ -510,7 +567,7 @@
{
// Temporarily keep console window visible for debugging
// if (OperatingSystem.IsWindows())
// {

Check warning on line 570 in ImGuiApp/ImGuiApp.cs

View workflow job for this annotation

GitHub Actions / Build, Test & Release

Remove this commented out code. (https://rules.sonarsource.com/csharp/RSPEC-125)
// DebugLogger.Log("ImGuiApp.Start: Hiding console window");
// nint handle = NativeMethods.GetConsoleWindow();
// NativeMethods.ShowWindow(handle, SW_HIDE);
Expand Down Expand Up @@ -688,19 +745,54 @@

if (ImGui.BeginMenu("Debug"))
{
if (ImGui.MenuItem("Show ImGui Demo", "", showImGuiDemo))
if (ImGui.MenuItem("Show ImGui Demo", "", isImGuiDemoVisible))
{
showImGuiDemo = !showImGuiDemo;
if (!isImGuiDemoVisible)
{
ShowImGuiDemo();
}
else
{
isImGuiDemoVisible = false;
}
}

if (ImGui.MenuItem("Show ImGui Metrics", "", showImGuiMetrics))
if (ImGui.MenuItem("Show ImGui Metrics", "", isImGuiMetricsVisible))
{
showImGuiMetrics = !showImGuiMetrics;
if (!isImGuiMetricsVisible)
{
ShowImGuiMetrics();
}
else
{
isImGuiMetricsVisible = false;
}
}

if (ImGui.MenuItem("Show Performance Monitor", "", showPerformanceMonitor))
if (ImGui.MenuItem("Show Style Editor", "", isImGuiStyleEditorVisible))
{
showPerformanceMonitor = !showPerformanceMonitor;
if (!isImGuiStyleEditorVisible)
{
ShowImGuiStyleEditor();
}
else
{
isImGuiStyleEditorVisible = false;
}
}

ImGui.Separator();

if (ImGui.MenuItem("Show Performance Monitor", "", isPerformanceMonitorVisible))
{
if (!isPerformanceMonitorVisible)
{
ShowPerformanceMonitor();
}
else
{
isPerformanceMonitorVisible = false;
}
}

ImGui.EndMenu();
Expand All @@ -723,22 +815,65 @@
ImGui.SetNextWindowPos(ImGui.GetMainViewport().WorkPos);
ImGuiStylePtr style = ImGui.GetStyle();
System.Numerics.Vector4 borderColor = style.Colors[(int)ImGuiCol.Border];
if (ImGui.Begin("##mainWindow", ref b, ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoSavedSettings))
if (ImGui.Begin("##mainWindow", ref b, ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoBringToFrontOnFocus))
{
style.Colors[(int)ImGuiCol.Border] = borderColor;
tickDelegate?.Invoke(dt);
}

ImGui.End();

if (showImGuiDemo)
if (isImGuiDemoVisible)
{
// Position the demo window to ensure it's visible and accessible
ImGui.SetNextWindowPos(new System.Numerics.Vector2(50, 50), ImGuiCond.FirstUseEver);
ImGui.SetNextWindowSize(new System.Numerics.Vector2(800, 600), ImGuiCond.FirstUseEver);

// Focus on first frame after opening for good UX
if (shouldFocusImGuiDemo)
{
ImGui.SetNextWindowFocus();
shouldFocusImGuiDemo = false;
}

ImGui.ShowDemoWindow(ref isImGuiDemoVisible);
}

if (isImGuiMetricsVisible)
{
ImGui.ShowDemoWindow(ref showImGuiDemo);
// Position the metrics window to ensure it's visible and accessible
ImGui.SetNextWindowPos(new System.Numerics.Vector2(100, 100), ImGuiCond.FirstUseEver);
ImGui.SetNextWindowSize(new System.Numerics.Vector2(600, 500), ImGuiCond.FirstUseEver);

// Focus on first frame after opening for good UX
if (shouldFocusImGuiMetrics)
{
ImGui.SetNextWindowFocus();
shouldFocusImGuiMetrics = false;
}

ImGui.ShowMetricsWindow(ref isImGuiMetricsVisible);
}

if (showImGuiMetrics)
if (isImGuiStyleEditorVisible)
{
ImGui.ShowMetricsWindow(ref showImGuiMetrics);
// Position and configure the style editor window for better accessibility
ImGui.SetNextWindowPos(new System.Numerics.Vector2(150, 150), ImGuiCond.FirstUseEver);
ImGui.SetNextWindowSize(new System.Numerics.Vector2(500, 400), ImGuiCond.FirstUseEver);

// Focus on first frame after opening for good UX
if (shouldFocusImGuiStyleEditor)
{
ImGui.SetNextWindowFocus();
shouldFocusImGuiStyleEditor = false;
}

if (ImGui.Begin("Style Editor", ref isImGuiStyleEditorVisible))
{
ImGui.ShowStyleEditor();
}

ImGui.End();
}
}

Expand Down Expand Up @@ -1198,9 +1333,16 @@
IsIdle = false;
lastInputTime = DateTime.UtcNow;
targetFrameTimeMs = 1000.0 / 30.0;
showImGuiMetrics = false;
showImGuiDemo = false;
showPerformanceMonitor = false;
isImGuiMetricsVisible = false;
isImGuiDemoVisible = false;
isImGuiStyleEditorVisible = false;
isPerformanceMonitorVisible = false;

shouldFocusImGuiDemo = false;
shouldFocusImGuiMetrics = false;
shouldFocusImGuiStyleEditor = false;
shouldFocusPerformanceMonitor = false;

performanceFrameTimes.Clear();
performanceFrameTimeSum = 0;
performanceFpsHistory.Clear();
Expand Down Expand Up @@ -1319,12 +1461,23 @@
/// </summary>
internal static void RenderPerformanceMonitor()
{
if (!showPerformanceMonitor)
if (!isPerformanceMonitorVisible)
{
return;
}

if (ImGui.Begin("Performance Monitor", ref showPerformanceMonitor))
// Position the performance monitor window to ensure it's visible and accessible
ImGui.SetNextWindowPos(new System.Numerics.Vector2(200, 200), ImGuiCond.FirstUseEver);
ImGui.SetNextWindowSize(new System.Numerics.Vector2(500, 350), ImGuiCond.FirstUseEver);

// Focus on first frame after opening for good UX
if (shouldFocusPerformanceMonitor)
{
ImGui.SetNextWindowFocus();
shouldFocusPerformanceMonitor = false;
}

if (ImGui.Begin("Performance Monitor", ref isPerformanceMonitorVisible))
{
ImGui.TextWrapped("This window shows the current performance state and throttling behavior.");
ImGui.Separator();
Expand Down
3 changes: 2 additions & 1 deletion ImGuiApp/ImGuiApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@

<ItemGroup>
<PackageReference Include="Hexa.NET.ImGui" />
<PackageReference Include="ktsu.Extensions" />
<PackageReference Include="ktsu.Invoker" />
<PackageReference Include="ktsu.ScopedAction" />
<PackageReference Include="ktsu.StrongPaths" />
<PackageReference Include="ktsu.Semantics" />
<PackageReference Include="Silk.NET" />
<PackageReference Include="Silk.NET.Assimp" />
<PackageReference Include="Silk.NET.Direct3D12" />
Expand Down
Loading
Loading