Gondwana Game Engine Development (master) - 2.6.1
Gondwana is a cross-platform 2.5D game and rendering engine written in C#/.NET 8. It provides fine-grained control over rendering, timing, and scene composition, with built-in support for parallax, z-ordering, pixel overhang, collision detection, and particle effects. Gondwana targets desktop and web platforms using SkiaSharp for graphics and pluggable audio backends for desktop and browser targets.
Loading...
Searching...
No Matches
EngineConfiguration.cs
5using Newtonsoft.Json;
6
8
12[JsonObject]
13public partial class EngineConfiguration
14{
15 private float _renderScale = 1f;
16
22 public float RenderScale
23 {
24 get => _renderScale;
25 set
26 {
27 if (!float.IsFinite(value) || value <= 0)
28 throw new ArgumentOutOfRangeException(nameof(value), "RenderScale must be finite and positive.");
29 if (_renderScale == value) return;
30 var surfaces = RenderSurfaceHostRegistry.Snapshot();
31 // Validate every dimension before publishing intent or queuing any changes.
32 foreach (var surface in surfaces)
33 {
34 if (surface.RenderSurfaceAdapter is { } adapter)
35 {
36 PresentationTransform.ScaleDimension(adapter.Width, value);
37 PresentationTransform.ScaleDimension(adapter.Height, value);
38 }
39 }
40 _renderScale = value;
41 foreach (var surface in surfaces)
42 surface.RequestRenderScale(value);
43 }
44 }
45
46 private RenderScalingFilter _renderScalingFilter = RenderScalingFilter.Linear;
47
50 {
51 get => _renderScalingFilter;
52 set
53 {
54 if (!Enum.IsDefined(value)) throw new ArgumentOutOfRangeException(nameof(value));
55 _renderScalingFilter = value;
56 foreach (var surface in RenderSurfaceHostRegistry.Snapshot())
57 surface.InvalidatePresentation();
58 }
59 }
60
61 private int _targetFPS = 60;
62
75 public int TargetFPS
76 {
77 get => _targetFPS;
78 set
79 {
80 _targetFPS = value < 0 ? 0 : value;
81
82 // Propagate to all active GPU backbuffers so their TargetFps stays in sync.
83 foreach (var surface in RenderSurfaceHostRegistry.Snapshot())
84 {
85 if (surface.Backbuffer is GpuBackbuffer gpuBb)
86 gpuBb.TargetFps = _targetFPS;
87 }
88 }
89 }
90
91 private int _timerDrivenSimulationRate = 120;
92
99 {
100 get => _timerDrivenSimulationRate;
101 set => _timerDrivenSimulationRate = Math.Max(1, value);
102 }
103
104 private int _maxTimerDrivenSimulationSteps = 8;
105
113 {
114 get => _maxTimerDrivenSimulationSteps;
115 set => _maxTimerDrivenSimulationSteps = Math.Max(1, value);
116 }
117
118 private float _startInitializationWaitTimeout = 30f;
119
129 {
130 get => _startInitializationWaitTimeout;
131 set => _startInitializationWaitTimeout =
132 !float.IsFinite(value) || value <= 0f
133 ? 0.001f
134 : Math.Min(value, (float)TimeSpan.MaxValue.TotalSeconds);
135 }
136
137 private bool _vSync = true;
138
162 public bool VSync
163 {
164 get => _vSync;
165 set
166 {
167 _vSync = value;
168
169 // Propagate to all active GPU backbuffers so their VSync stays in sync.
170 foreach (var surface in RenderSurfaceHostRegistry.Snapshot())
171 {
172 if (surface.Backbuffer is GpuBackbuffer gpuBb)
173 gpuBb.VSync = _vSync;
174 }
175 }
176 }
177
178 private int _msaaSampleCount = 1;
179
208 {
209 get => _msaaSampleCount;
210 set
211 {
212 _msaaSampleCount = value < 1 ? 1 : value;
213
214 // Propagate to all active GPU backbuffers so their MsaaSampleCount stays in sync.
215 foreach (var surface in RenderSurfaceHostRegistry.Snapshot())
216 {
217 if (surface.Backbuffer is GpuBackbuffer gpuBb)
218 gpuBb.MsaaSampleCount = _msaaSampleCount;
219 }
220 }
221 }
222
223 private double _samplingTimeForCPS = 1.5;
224
233 [Obsolete(
234 "Legacy CPS/FPS sampling is deprecated. Use Engine.Profiler.Configure(...) for runtime telemetry.",
235 DiagnosticId = "GOND0001")]
236 public double SamplingTimeForCPS
237 {
238 get => _samplingTimeForCPS;
239 set => _samplingTimeForCPS = value < 0 ? 0 : value;
240 }
241
248 [JsonIgnore]
249 [Obsolete(
250 "Legacy CPS/FPS sampling is deprecated. Use Engine.Profiler.Configure(...) for runtime telemetry.",
251 DiagnosticId = "GOND0001")]
252 public long SamplingTimeForCPSTicks => LegacyCpsSamplingTicks;
253
257 internal double LegacyCpsSamplingTime
258 {
259 get => _samplingTimeForCPS;
260 set => _samplingTimeForCPS = value < 0 ? 0 : value;
261 }
262
266 internal long LegacyCpsSamplingTicks =>
267 (long)(_samplingTimeForCPS * HighResTimer.TicksPerSecond);
268
274 public double TimeBetweenKeyboardEvents { get; set; } = 0.03;
275
276 private double _gamepadConnectionUpdateFrequencyHz = 0.2;
277
287 {
288 get => _gamepadConnectionUpdateFrequencyHz;
289 set => _gamepadConnectionUpdateFrequencyHz =
290 double.IsFinite(value) && value > 0d ? value : 0d;
291 }
292
293 private double _gamepadPollFrequencyHz = 60d;
294
303 {
304 get => _gamepadPollFrequencyHz;
305 set => _gamepadPollFrequencyHz =
306 double.IsFinite(value) && value > 0d ? value : 0d;
307 }
308
315 public double TimeBetweenGamepadEvents { get; set; } = 0.03;
316
322 public double TimeBetweenMouseEvents { get; set; } = 0.03;
323
329 public double TimeBetweenTouchEvents { get; set; } = 0.03;
330
346 public EngineLoggingMode LoggingMode { get; set; } = EngineLoggingMode.Asynchronous;
347
348 private int _loggingQueueCapacity = 8192;
349
360 {
361 get => _loggingQueueCapacity;
362 set
363 {
364 if (value <= 0)
365 throw new ArgumentOutOfRangeException(nameof(value), "Capacity must be > 0.");
366 _loggingQueueCapacity = value;
367 }
368 }
369
374 public bool FlushAsyncLogsOnShutdown { get; set; } = true;
375
379 public List<StateFileMount>? StateFiles { get; set; }
380
381 #region ConfigurationSections
382
417 [JsonProperty]
418 public Dictionary<string, Dictionary<string, string>> ConfigurationSections { get; set; } = new();
419
427 public bool HasConfigurationSection(string section)
428 {
429 return ConfigurationSections.ContainsKey(section);
430 }
431
439 public Dictionary<string, string> CreateConfigurationSection(string section)
440 {
441 ArgumentException.ThrowIfNullOrWhiteSpace(section);
442
443 if (!ConfigurationSections.TryGetValue(section, out var values))
444 {
445 values = new Dictionary<string, string>();
446 ConfigurationSections[section] = values;
447 }
448
449 return values;
450 }
451
459 public bool RemoveConfigurationSection(string section)
460 {
461 ArgumentException.ThrowIfNullOrWhiteSpace(section);
462
463 return ConfigurationSections.Remove(section);
464 }
465
473 public IReadOnlyDictionary<string, string>? GetConfigurationSection(string section)
474 {
475 ArgumentException.ThrowIfNullOrWhiteSpace(section);
476
477 return ConfigurationSections.TryGetValue(section, out var values)
478 ? values
479 : null;
480 }
481
490 public bool HasConfigurationValue(string section, string key)
491 {
492 ArgumentException.ThrowIfNullOrWhiteSpace(section);
493 ArgumentException.ThrowIfNullOrWhiteSpace(key);
494
495 return ConfigurationSections.TryGetValue(section, out var values)
496 && values.ContainsKey(key);
497 }
498
508 public string? GetConfigurationValue(string section, string key, string? defaultValue = null)
509 {
510 ArgumentException.ThrowIfNullOrWhiteSpace(section);
511 ArgumentException.ThrowIfNullOrWhiteSpace(key);
512
513 return ConfigurationSections.TryGetValue(section, out var values)
514 && values.TryGetValue(key, out var value)
515 ? value
516 : defaultValue;
517 }
518
525 public void SetConfigurationValue(string section, string key, string value)
526 {
527 ArgumentException.ThrowIfNullOrWhiteSpace(section);
528 ArgumentException.ThrowIfNullOrWhiteSpace(key);
529 ArgumentNullException.ThrowIfNull(value);
530
531 var values = CreateConfigurationSection(section);
532 values[key] = value;
533 }
534
543 public bool RemoveConfigurationValue(string section, string key)
544 {
545 ArgumentException.ThrowIfNullOrWhiteSpace(section);
546 ArgumentException.ThrowIfNullOrWhiteSpace(key);
547
548 return ConfigurationSections.TryGetValue(section, out var values)
549 && values.Remove(key);
550 }
551
559 public bool ClearConfigurationSection(string section)
560 {
561 ArgumentException.ThrowIfNullOrWhiteSpace(section);
562
563 if (!ConfigurationSections.TryGetValue(section, out var values))
564 return false;
565
566 values.Clear();
567 return true;
568 }
569
574 {
575 ConfigurationSections.Clear();
576 }
577
589 public Dictionary<string, string>? this[string section]
590 {
591 get
592 {
593 ArgumentException.ThrowIfNullOrWhiteSpace(section);
594
595 return ConfigurationSections.TryGetValue(section, out var values)
596 ? values
597 : null;
598 }
599 set
600 {
601 ArgumentException.ThrowIfNullOrWhiteSpace(section);
602
603 if (value == null)
604 {
605 ConfigurationSections.Remove(section);
606 }
607 else
608 {
609 ConfigurationSections[section] = value;
610 }
611 }
612 }
613
626 public string? this[string section, string key]
627 {
628 get
629 {
630 ArgumentException.ThrowIfNullOrWhiteSpace(section);
631 ArgumentException.ThrowIfNullOrWhiteSpace(key);
632
633 return ConfigurationSections.TryGetValue(section, out var values)
634 && values.TryGetValue(key, out var value)
635 ? value
636 : null;
637 }
638 set
639 {
640 ArgumentException.ThrowIfNullOrWhiteSpace(section);
641 ArgumentException.ThrowIfNullOrWhiteSpace(key);
642
643 if (value == null)
644 {
645 if (ConfigurationSections.TryGetValue(section, out var values))
646 {
647 values.Remove(key);
648 }
649 return;
650 }
651
652 if (!ConfigurationSections.TryGetValue(section, out var sectionValues))
653 {
654 sectionValues = new Dictionary<string, string>();
655 ConfigurationSections[section] = sectionValues;
656 }
657
658 sectionValues[key] = value;
659 }
660 }
661
662 #endregion ConfigurationSections
663}
Settings used by the engine when cycling.
int LoggingQueueCapacity
Maximum number of queued log events when LoggingMode is EngineLoggingMode.Asynchronous....
bool RemoveConfigurationValue(string section, string key)
Removes a configuration value from the specified section.
RenderScalingFilter RenderScalingFilter
Filtering for the finished Backbuffer image; independent of View.Zoom and tile filtering.
long SamplingTimeForCPSTicks
Total number of system ticks between each legacy CPS sampling.
int TimerDrivenSimulationRate
Gets or sets the number of fixed simulation updates performed per second in timer-driven mode....
bool RemoveConfigurationSection(string section)
Removes the specified configuration section and all key/value pairs contained within it.
double TimeBetweenMouseEvents
Minimum time (in seconds) allowed between Mouse events. Use this to prevent flooding the system with ...
void ClearConfigurationSections()
Removes all configuration sections and all contained key/value pairs.
double TimeBetweenGamepadEvents
Minimum time (in seconds) allowed between Gamepad events. Use this to prevent flooding the system wit...
IReadOnlyDictionary< string, string >? GetConfigurationSection(string section)
Gets a read-only view of all key/value pairs in the specified configuration section.
double GamepadPollFrequencyHz
Gets or sets how often the engine refreshes the state of already-connected gamepads.
float RenderScale
Establishes logical Backbuffer dimensions from current adapter dimensions. Default is one; values abo...
string? GetConfigurationValue(string section, string key, string? defaultValue=null)
Gets a configuration value from the specified section.
float StartInitializationWaitTimeout
Gets or sets how long Engine.Start(SynchronizationContext) waits when another thread is already runni...
List< StateFileMount >? StateFiles
Optional collection of serialized EngineStates to mount at initialization.
void SetConfigurationValue(string section, string key, string value)
Sets a configuration value in the specified section, creating the section if necessary.
Dictionary< string, string > CreateConfigurationSection(string section)
Creates a configuration section if it does not already exist.
EngineLoggingMode LoggingMode
Controls whether engine logging operations are performed synchronously or asynchronously.
double GamepadConnectionUpdateFrequencyHz
Gets or sets how often the engine checks for gamepad connection and disconnection changes.
int MsaaSampleCount
Gets or sets the number of MSAA (multisample anti-aliasing) samples used when creating GPU render-tar...
bool VSync
Gets or sets a value indicating whether vertical synchronisation (vsync) is enabled.
double TimeBetweenKeyboardEvents
Minimum time (in seconds) allowed between Keyboard events. Use this to prevent flooding the system wi...
double SamplingTimeForCPS
Total number of seconds between legacy Cycles Per Second (CPS) calculations. Default is 1....
bool ClearConfigurationSection(string section)
Clears all key/value pairs from the specified configuration section without removing the section itse...
bool FlushAsyncLogsOnShutdown
If true, the engine will attempt to flush queued async log events during shutdown....
bool HasConfigurationSection(string section)
Determines whether the specified configuration section exists.
int TargetFPS
Target screen refresh rate for the Engine. Setting the number lower allows more time for the processo...
int MaxTimerDrivenSimulationSteps
Gets or sets the maximum number of fixed simulation updates that one externally driven Tick() call ma...
Dictionary< string, Dictionary< string, string > > ConfigurationSections
Gets or sets a collection of structured configuration values organized into named sections.
bool HasConfigurationValue(string section, string key)
Determines whether a configuration value exists in the specified section.
double TimeBetweenTouchEvents
Minimum time (in seconds) allowed between Touch events. Use this to prevent flooding the system with ...
Provides a fully GPU-rendered backbuffer implementation using SkiaSharp and OpenGL.
EngineLoggingMode
Specifies the logging mode for the engine.
readonly record struct PresentationTransform(float Scale, SKRect DestinationRect)
Aspect-preserving mapping between logical Backbuffer ScreenPx and adapter pixels.
RenderScalingFilter
Filtering used only when presenting the finished Backbuffer.