Skip to content

Commit 18eac65

Browse files
committed
Update D3D11SystemWindow with auto-exit and screenshot functionality
- Updated copyright year to 2026. - Added properties for automatic window closure after a specified time and for capturing screenshots at designated frame numbers. - Refactored screenshot and auto-exit logic into dedicated methods for improved clarity and maintainability. - Enhanced screenshot saving to a dedicated directory on the desktop. Refactored depth stencil state management in VorticeD3D to use a caching mechanism for improved performance and reduced resource allocation overhead.
1 parent f473c78 commit 18eac65

2 files changed

Lines changed: 230 additions & 122 deletions

File tree

PlatformWin32/win32/D3D11SystemWindow.cs

Lines changed: 41 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2025, Lars Brubaker
2+
Copyright (c) 2026, Lars Brubaker
33
All rights reserved.
44
55
Redistribution and use in source and binary forms, with or without
@@ -28,6 +28,7 @@ The views and conclusions contained in the software and documentation are those
2828
*/
2929

3030
using System;
31+
using System.Collections.Generic;
3132
using System.Drawing;
3233
using System.Windows.Forms;
3334
using MatterHackers.RenderOpenGl;
@@ -37,6 +38,17 @@ namespace MatterHackers.Agg.UI
3738
{
3839
public class D3D11SystemWindow : WinformsSystemWindow
3940
{
41+
/// <summary>
42+
/// When set to a value greater than 0, the window will automatically close after the specified number of seconds.
43+
/// </summary>
44+
public static double ExitAfterXSeconds { get; set; } = 0.0;
45+
46+
/// <summary>
47+
/// Frame numbers at which to capture a screenshot to the desktop (e.g. { 2, 10, 50 }).
48+
/// Empty by default (no screenshots captured).
49+
/// </summary>
50+
public static List<int> ScreenshotAtFrames { get; set; } = new List<int>();
51+
4052
private D3D11Control d3dControl;
4153
private bool doneLoading = false;
4254
private bool viewPortHasBeenSet = false;
@@ -54,46 +66,17 @@ public D3D11SystemWindow()
5466
this.Controls.Add(d3dControl);
5567
}
5668

57-
private Timer screenshotTimer;
58-
5969
protected override void OnLoad(EventArgs e)
6070
{
6171
base.OnLoad(e);
6272

63-
DebugLog("OnLoad: Initializing D3D11...");
6473
d3dControl.InitializeD3D();
6574
GL.Instance = d3dControl.GlBackend;
66-
DebugLog($"OnLoad: D3D11 initialized. Device={d3dControl.Device != null}, GL.Instance={GL.Instance?.GetType().Name}");
67-
68-
screenshotTimer = new Timer { Interval = 8000 };
69-
screenshotTimer.Tick += (s, ev) =>
70-
{
71-
screenshotTimer.Stop();
72-
screenshotTimer.Dispose();
73-
screenshotTimer = null;
74-
Invalidate();
75-
Application.DoEvents();
76-
try
77-
{
78-
var path = System.IO.Path.Combine(
79-
Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
80-
"mattercad_d3d11_timed.png");
81-
d3dControl.CaptureScreenshot(path);
82-
DebugLog($"Timed screenshot saved: {path}");
83-
}
84-
catch (Exception ex) { DebugLog($"Timed screenshot error: {ex.Message}"); }
85-
};
86-
screenshotTimer.Start();
8775

88-
var autoExitTimer = new Timer { Interval = 15000 };
89-
autoExitTimer.Tick += (s, ev) =>
76+
if (ExitAfterXSeconds > 0)
9077
{
91-
autoExitTimer.Stop();
92-
autoExitTimer.Dispose();
93-
DebugLog("Auto-exit timer fired, closing application.");
94-
Close();
95-
};
96-
autoExitTimer.Start();
78+
SetupAutoExit();
79+
}
9780

9881
doneLoading = true;
9982

@@ -112,6 +95,18 @@ protected override void OnLoad(EventArgs e)
11295
initHasBeenCalled = true;
11396
}
11497

98+
private void SetupAutoExit()
99+
{
100+
var autoExitTimer = new Timer { Interval = (int)(ExitAfterXSeconds * 1000) };
101+
autoExitTimer.Tick += (s, ev) =>
102+
{
103+
autoExitTimer.Stop();
104+
autoExitTimer.Dispose();
105+
Close();
106+
};
107+
autoExitTimer.Start();
108+
}
109+
115110
protected override void OnClosed(EventArgs e)
116111
{
117112
try
@@ -188,54 +183,36 @@ protected override void OnResize(EventArgs e)
188183
{
189184
Invalidate();
190185
d3dControl.Bounds = bounds;
191-
192-
if (initHasBeenCalled)
193-
{
194-
SetAndClearViewPort();
195-
base.OnResize(e);
196-
}
197-
else
198-
{
199-
base.OnResize(e);
200-
}
186+
SetAndClearViewPort();
187+
base.OnResize(e);
201188
}
202189
}
203190

204191
private int frameCount;
205-
private static readonly string debugLogPath = System.IO.Path.Combine(
206-
Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "d3d11_debug.log");
207-
208-
private void DebugLog(string msg)
209-
{
210-
try { System.IO.File.AppendAllText(debugLogPath, $"{DateTime.Now:HH:mm:ss.fff} {msg}\n"); } catch { }
211-
}
212192

213193
public override void CopyBackBufferToScreen(Graphics displayGraphics)
214194
{
215195
if (d3dControl != null && !d3dControl.IsDisposed)
216196
{
217-
frameCount++;
197+
d3dControl.Present();
198+
viewPortHasBeenSet = false;
218199

219-
if (frameCount <= 3 || frameCount % 100 == 0)
220-
{
221-
DebugLog($"Frame {frameCount}, ClientSize={ClientSize}");
222-
}
200+
frameCount++;
223201

224-
if (frameCount == 2 || frameCount == 10 || frameCount == 50)
202+
if (ScreenshotAtFrames.Count > 0 && ScreenshotAtFrames.Contains(frameCount))
225203
{
226204
try
227205
{
228-
var path = System.IO.Path.Combine(
206+
var dir = System.IO.Path.Combine(
229207
Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
230-
$"mattercad_d3d11_frame{frameCount}.png");
231-
d3dControl.CaptureScreenshot(path);
232-
DebugLog($"Screenshot saved: {path}");
208+
"D3D11_Screen_Shots");
209+
System.IO.Directory.CreateDirectory(dir);
210+
d3dControl.CaptureScreenshot(System.IO.Path.Combine(dir, $"frame{frameCount}.png"));
211+
}
212+
catch
213+
{
233214
}
234-
catch (Exception ex) { DebugLog($"Screenshot error: {ex.Message}"); }
235215
}
236-
237-
d3dControl.Present();
238-
viewPortHasBeenSet = false;
239216
}
240217
}
241218

0 commit comments

Comments
 (0)