using System; using System.Diagnostics.CodeAnalysis; using System.IO; using ADOFAIRenderer.Core; using ADOFAIRenderer.Data; using ADOFAIRenderer.Util; namespace ADOFAIRenderer.API; /// /// Fluent builder for configuring and starting a render session. /// [SuppressMessage("ReSharper", "UnusedType.Global")] public class RenderSession { private bool _auto = true; /// /// Specifies the types of patches that can be configured for a render session. /// public enum PatchType { /// /// Time-related patch controlling frame timing and clock synchronization. /// Time, /// /// Screen-related patch controlling screen resolution. /// Screen } private bool _timePatch = true; private bool _screenPatch = true; private string? _outputPath; private bool _notification = true; private Func? _endCondition; private Action? _onComplete; private Action? _onLastUpdate; /// /// Sets whether auto mode is enabled. /// /// true to enable auto mode; otherwise, false. Default is true. /// The current instance for method chaining. public RenderSession WithAuto(bool enabled = true) { _auto = enabled; return this; } /// /// Sets whether a specific patch type is enabled for the render session. /// /// The to configure. /// true to enable the specified patch; otherwise, false. Default is true. /// The current instance for method chaining. /// Thrown when an unsupported is provided. public RenderSession WithPatch(PatchType patchType, bool enabled = true) { switch (patchType) { case PatchType.Time: _timePatch = enabled; break; case PatchType.Screen: _screenPatch = enabled; break; default: throw new ArgumentOutOfRangeException(nameof(patchType), patchType, null); } return this; } /// /// Sets the custom condition function that determines when the render session should end. /// /// A delegate returning true when the session end condition is met. /// The current instance for method chaining. public RenderSession WithEndCondition(Func endCondition) { _endCondition = endCondition; return this; } /// /// Sets the custom output path for the rendered file. /// /// The file path where the output will be saved, or null to use the default capture directory. /// The current instance for method chaining. public RenderSession WithOutputPath(string? outputPath) { _outputPath = outputPath; return this; } /// /// Sets whether desktop notifications should be displayed when rendering completes. /// /// true to enable desktop notifications; otherwise, false. /// The current instance for method chaining. public RenderSession WithNotification(bool enabled) { _notification = enabled; return this; } /// /// Adds a callback action to be invoked when the render session completes or fails. /// /// The callback action that receives the resulting . /// The current instance for method chaining. public RenderSession OnComplete(Action callback) { _onComplete += callback; return this; } /// /// Adds a callback action to be invoked on the last update of each frame in the render session. /// /// The callback action to execute. /// The current instance for method chaining. public RenderSession OnLastUpdate(Action callback) { _onLastUpdate += callback; return this; } /// /// Applies the configured flags and initiates the render session. /// /// The configuration settings for the render session. /// The file path of the level to render. /// Thrown when the output directory cannot be determined from the output path. public void Start(RenderConfig renderConfig, string levelPath) { RenderContext.Auto = _auto; RenderContext.TimePatch = _timePatch; RenderContext.ScreenPatch = _screenPatch; RenderContext.OutputPath = _outputPath; RenderContext.Notification = _notification; if (_endCondition is not null) RenderContext.EndCondition = _endCondition; if (_onComplete is not null) RenderContext.OnComplete = _onComplete; if (_onLastUpdate is not null) RenderContext.OnLastUpdate = _onLastUpdate; RenderManager.Instance.levelPath = levelPath; RenderManager.Instance.Configuration = renderConfig; RenderManager.Instance.StartLoadingOverride(); if (_outputPath is null) RenderManager.Instance.SetupCaptureDirectory(); else FileUtil.CreateDirectory(Path.GetDirectoryName(_outputPath) ?? throw new InvalidOperationException()); RenderManager.Instance.SetupGameScene(); } }