11/*
2- Copyright (c) 2025 , Lars Brubaker
2+ Copyright (c) 2026 , Lars Brubaker
33All rights reserved.
44
55Redistribution 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
3030using System ;
31+ using System . Collections . Generic ;
3132using System . Drawing ;
3233using System . Windows . Forms ;
3334using 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