266 lines
7.9 KiB
C#
266 lines
7.9 KiB
C#
using Engine.Graphics;
|
|
using Engine.Input;
|
|
using Serilog;
|
|
using Serilog.Core;
|
|
using Serilog.Events;
|
|
using Serilog.Sinks.SystemConsole.Themes;
|
|
|
|
namespace Engine;
|
|
|
|
/// <summary>
|
|
/// Provides a builder for creating and configuring an instance of the <see cref="Engine"/> class.
|
|
/// </summary>
|
|
public sealed class EngineBuilder
|
|
{
|
|
/// <summary>
|
|
/// The title of the application window.
|
|
/// </summary>
|
|
private string _title = "";
|
|
|
|
/// <summary>
|
|
/// Indicates whether the engine should run in headless mode.
|
|
/// </summary>
|
|
private bool _headless;
|
|
|
|
/// <summary>
|
|
/// The width of the rendering window.
|
|
/// </summary>
|
|
private int _width = 1;
|
|
|
|
/// <summary>
|
|
/// The height of the rendering window.
|
|
/// </summary>
|
|
private int _height = 1;
|
|
|
|
/// <summary>
|
|
/// The path to the asset folder.
|
|
/// </summary>
|
|
private string _assetFolder = "./asset";
|
|
|
|
/// <summary>
|
|
/// The path to the data folder.
|
|
/// </summary>
|
|
private string _dataFolder = "./data";
|
|
|
|
/// <summary>
|
|
/// The input handler factory.
|
|
/// </summary>
|
|
private Func<Engine, IInputHandler>? _inputHandlerFunc;
|
|
|
|
/// <summary>
|
|
/// The presenter factory.
|
|
/// </summary>
|
|
private Func<Engine, IPresenter>? _presenterFunc;
|
|
|
|
// Logging
|
|
/// <summary>
|
|
/// Indicates whether to log to the console.
|
|
/// </summary>
|
|
private bool _logToConsole;
|
|
|
|
/// <summary>
|
|
/// Indicates whether to log to a file.
|
|
/// </summary>
|
|
private bool _logToFile;
|
|
|
|
/// <summary>
|
|
/// The path to the log file.
|
|
/// </summary>
|
|
private string? _logFilePath;
|
|
|
|
/// <summary>
|
|
/// The log level.
|
|
/// </summary>
|
|
private LogEventLevel _logLevel = LogEventLevel.Information;
|
|
|
|
/// <summary>
|
|
/// Sets the title of the engine window.
|
|
/// </summary>
|
|
/// <param name="parTitle">The title to use for the engine window.</param>
|
|
/// <returns>The current instance of <see cref="EngineBuilder"/> for chaining.</returns>
|
|
public EngineBuilder Title(string parTitle)
|
|
{
|
|
_title = parTitle;
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Configures the engine to run in headless mode.
|
|
/// </summary>
|
|
/// <param name="parHeadless">Indicates whether to enable headless mode. Defaults to <c>true</c>.</param>
|
|
/// <returns>The current instance of <see cref="EngineBuilder"/> for chaining.</returns>
|
|
public EngineBuilder Headless(bool parHeadless = true)
|
|
{
|
|
_headless = parHeadless;
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the width of the engine window.
|
|
/// </summary>
|
|
/// <param name="parWidth">The width in pixels. Must be greater than zero.</param>
|
|
/// <returns>The current instance of <see cref="EngineBuilder"/> for chaining.</returns>
|
|
public EngineBuilder Width(int parWidth)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parWidth);
|
|
|
|
_width = parWidth;
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the height of the engine window.
|
|
/// </summary>
|
|
/// <param name="parHeight">The height in pixels. Must be greater than zero.</param>
|
|
/// <returns>The current instance of <see cref="EngineBuilder"/> for chaining.</returns>
|
|
public EngineBuilder Height(int parHeight)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parHeight);
|
|
|
|
_height = parHeight;
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the folder path for assets used by the engine.
|
|
/// </summary>
|
|
/// <param name="parAssetFolder">The folder path containing asset files.</param>
|
|
/// <returns>The current instance of <see cref="EngineBuilder"/> for chaining.</returns>
|
|
public EngineBuilder AssetFolder(string parAssetFolder)
|
|
{
|
|
_assetFolder = parAssetFolder;
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the folder path for data files used by the engine.
|
|
/// </summary>
|
|
/// <param name="parDataFolder">The folder path containing data files.</param>
|
|
/// <returns>The current instance of <see cref="EngineBuilder"/> for chaining.</returns>
|
|
public EngineBuilder DataFolder(string parDataFolder)
|
|
{
|
|
_dataFolder = parDataFolder;
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Specifies the input handler to be used by the engine.
|
|
/// </summary>
|
|
/// <param name="parInputHandlerFunc">A function that creates an input handler for the engine.</param>
|
|
/// <returns>The current instance of <see cref="EngineBuilder"/> for chaining.</returns>
|
|
public EngineBuilder InputHandler(Func<Engine, IInputHandler> parInputHandlerFunc)
|
|
{
|
|
_inputHandlerFunc = parInputHandlerFunc;
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Specifies the presenter to be used by the engine.
|
|
/// </summary>
|
|
/// <param name="parPresenterFunc">A function that creates a presenter for the engine.</param>
|
|
/// <returns>The current instance of <see cref="EngineBuilder"/> for chaining.</returns>
|
|
public EngineBuilder Presenter(Func<Engine, IPresenter> parPresenterFunc)
|
|
{
|
|
_presenterFunc = parPresenterFunc;
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Configures logging to output to the console.
|
|
/// </summary>
|
|
/// <param name="parLogToConsole">Indicates whether to enable console logging. Defaults to <c>true</c>.</param>
|
|
/// <returns>The current instance of <see cref="EngineBuilder"/> for chaining.</returns>
|
|
public EngineBuilder LogToConsole(bool parLogToConsole = true)
|
|
{
|
|
_logToConsole = parLogToConsole;
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Configures logging to output to a file.
|
|
/// </summary>
|
|
/// <param name="parLogToFile">Indicates whether to enable file logging. Defaults to <c>true</c>.</param>
|
|
/// <param name="parLogFilePath">The path of the log file. Cannot be <c>null</c> if file logging is enabled.</param>
|
|
/// <returns>The current instance of <see cref="EngineBuilder"/> for chaining.</returns>
|
|
/// <exception cref="ArgumentNullException">Thrown if <paramref name="parLogFilePath"/> is <c>null</c> when <paramref name="parLogToFile"/> is <c>true</c>.</exception>
|
|
public EngineBuilder LogToFile(bool parLogToFile = true, string? parLogFilePath = null)
|
|
{
|
|
if (parLogToFile && parLogFilePath == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(parLogFilePath));
|
|
}
|
|
|
|
_logToFile = parLogToFile;
|
|
_logFilePath = parLogFilePath;
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the minimum log level for logging.
|
|
/// </summary>
|
|
/// <param name="parLogLevel">The minimum level of log events to capture.</param>
|
|
/// <returns>The current instance of <see cref="EngineBuilder"/> for chaining.</returns>
|
|
public EngineBuilder LogLevel(LogEventLevel parLogLevel)
|
|
{
|
|
_logLevel = parLogLevel;
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Builds and returns a new instance of the <see cref="Engine"/> class based on the configured settings.
|
|
/// </summary>
|
|
/// <returns>A fully configured instance of <see cref="Engine"/>.</returns>
|
|
public Engine Build()
|
|
{
|
|
var logger = BuildLogger();
|
|
var engine = new Engine(_width, _height, _headless, _title, _assetFolder, _dataFolder, logger);
|
|
|
|
var presenter = _presenterFunc?.Invoke(engine);
|
|
if (presenter != null)
|
|
{
|
|
engine.Presenter = presenter;
|
|
}
|
|
|
|
var inputHandler = _inputHandlerFunc?.Invoke(engine);
|
|
if (inputHandler != null)
|
|
{
|
|
engine.InputHandler = inputHandler;
|
|
}
|
|
|
|
return engine;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Configures and builds a logger based on the current logging settings.
|
|
/// </summary>
|
|
/// <returns>A configured instance of <see cref="Logger"/>.</returns>
|
|
private Logger BuildLogger()
|
|
{
|
|
const string template =
|
|
"[{Timestamp:yyyy-MM-dd HH:mm:ss.fff}] [{Level:u3}] [{ThreadName,-15:l}:{ThreadId,-4:d4}] [{SourceContext:l}] {Message:lj}{NewLine}{Exception}";
|
|
|
|
var loggerConfiguration = new LoggerConfiguration()
|
|
.MinimumLevel.Is(_logLevel)
|
|
.Enrich.WithThreadName()
|
|
.Enrich.WithThreadId()
|
|
.Enrich.FromLogContext();
|
|
|
|
if (_logToConsole)
|
|
{
|
|
loggerConfiguration.WriteTo.Console(
|
|
outputTemplate: template,
|
|
theme: AnsiConsoleTheme.Literate
|
|
);
|
|
}
|
|
|
|
if (_logToFile)
|
|
{
|
|
loggerConfiguration.WriteTo.File(
|
|
_logFilePath!,
|
|
outputTemplate: template
|
|
);
|
|
}
|
|
|
|
return loggerConfiguration.CreateLogger();
|
|
}
|
|
} |