using System.Globalization; using System.IO; using System.Windows; using System.Windows.Threading; using Engine; using Engine.Graphics; using Engine.Graphics.Texture; using Engine.Input; using OpenTK.Mathematics; using OpenTK.Windowing.Common; using Serilog.Events; namespace PresenterWpf; /// /// Interaction logic for App.xaml /// public partial class App : Application { // Hijack the default startup event to start the engine protected override void OnStartup(StartupEventArgs parEventArgs) { var presenter = new PresenterWrapper(); var inputHandler = new InputHandlerWrapper(); var engine = new EngineBuilder() .Headless() .Presenter(_ => presenter) .InputHandler(_ => inputHandler) .LogToConsole() .LogToFile(true, "log.txt") .LogLevel(LogEventLevel.Debug) .AssetFolder(Path.GetFullPath("./asset")) .DataFolder(Path.GetFullPath("./data")) .Build(); // Since engine claims current thread for rendering, we need to create a new thread to run WPF var thread = new Thread(() => { var window = new MainWindow(); presenter.Presenter = window; inputHandler.InputHandler = new WpfInputHandler(window); window.Show(); Dispatcher.Run(); }); thread.SetApartmentState(ApartmentState.STA); thread.IsBackground = true; thread.Start(); DoomDeathmatch.DoomDeathmatch.Initialize(engine); engine.Run(); // Shutdown WPF Shutdown(); } private class InputHandlerWrapper : IInputHandler { public IInputHandler? InputHandler { get; set; } public CultureInfo CurrentInputLanguage => InputHandler?.CurrentInputLanguage ?? new CultureInfo(1033); public Vector2 MousePosition => InputHandler?.MousePosition ?? Vector2.Zero; public bool IsKeyPressed(KeyboardButtonCode parKeyboardButtonCode) { return InputHandler?.IsKeyPressed(parKeyboardButtonCode) ?? false; } public bool IsKeyJustPressed(KeyboardButtonCode parKeyboardButtonCode) { return InputHandler?.IsKeyJustPressed(parKeyboardButtonCode) ?? false; } public bool IsMouseButtonPressed(MouseButtonCode parButtonCode) { return InputHandler?.IsMouseButtonPressed(parButtonCode) ?? false; } public bool IsMouseButtonJustPressed(MouseButtonCode parButtonCode) { return InputHandler?.IsMouseButtonJustPressed(parButtonCode) ?? false; } public void Update(double parDeltaTime) { InputHandler?.Update(parDeltaTime); } } private class PresenterWrapper : IPresenter { public event Action? OnResize; public IPresenter? Presenter { get => _presenter; set { if (_presenter != null) { _presenter.OnResize -= PresenterResize; } if (value != null) { value.OnResize += PresenterResize; } _presenter = value; } } public int Width => Presenter?.Width ?? 0; public int Height => Presenter?.Height ?? 0; public bool IsExiting => Presenter?.IsExiting ?? false; private IPresenter? _presenter; public void Present(IConstTexture parTexture) { Presenter?.Present(parTexture); } public void Update(double parDeltaTime) { Presenter?.Update(parDeltaTime); } public void Render() { Presenter?.Render(); } public void Exit() { Presenter?.Exit(); } private void PresenterResize(ResizeEventArgs e) { OnResize?.Invoke(e); } } }