.
This commit is contained in:
31
PresenterWpf/PresenterWpf.csproj
Normal file
31
PresenterWpf/PresenterWpf.csproj
Normal file
@@ -0,0 +1,31 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UseWPF>true</UseWPF>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Engine\Engine.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="src\App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<XamlRuntime>Wpf</XamlRuntime>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="src\MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<XamlRuntime>Wpf</XamlRuntime>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
5
PresenterWpf/src/App.xaml
Normal file
5
PresenterWpf/src/App.xaml
Normal file
@@ -0,0 +1,5 @@
|
||||
<Application x:Class="PresenterWpf.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:PresenterWpf">
|
||||
</Application>
|
||||
83
PresenterWpf/src/App.xaml.cs
Normal file
83
PresenterWpf/src/App.xaml.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Windows;
|
||||
using Engine.Graphics;
|
||||
using Engine.Graphics.Texture;
|
||||
using OpenTK.Windowing.Common;
|
||||
|
||||
namespace PresenterWpf;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
// Hijack the default startup event to start the engine
|
||||
protected override void OnStartup(StartupEventArgs e)
|
||||
{
|
||||
var presenter = new PresenterWrapper();
|
||||
var engine = new Engine.Engine(1, 1, _ => presenter);
|
||||
|
||||
// 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(engine);
|
||||
presenter.Presenter = window;
|
||||
window.Show();
|
||||
System.Windows.Threading.Dispatcher.Run();
|
||||
});
|
||||
|
||||
thread.SetApartmentState(ApartmentState.STA);
|
||||
thread.IsBackground = true;
|
||||
thread.Start();
|
||||
|
||||
engine.Run();
|
||||
|
||||
// Shutdown WPF
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
private class PresenterWrapper : IPresenter
|
||||
{
|
||||
private IPresenter? _presenter;
|
||||
|
||||
public IPresenter? Presenter
|
||||
{
|
||||
get => _presenter;
|
||||
set
|
||||
{
|
||||
if (_presenter != null)
|
||||
{
|
||||
_presenter.Resize -= PresenterResize;
|
||||
}
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
value.Resize += PresenterResize;
|
||||
}
|
||||
|
||||
_presenter = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsExiting => Presenter?.IsExiting ?? false;
|
||||
public int Width => Presenter?.Width ?? 0;
|
||||
public int Height => Presenter?.Height ?? 0;
|
||||
public event Action<ResizeEventArgs>? Resize;
|
||||
|
||||
public void Present(IConstTexture parTexture)
|
||||
{
|
||||
Presenter?.Present(parTexture);
|
||||
}
|
||||
|
||||
public void Update(double parDeltaTime)
|
||||
{
|
||||
Presenter?.Update(parDeltaTime);
|
||||
}
|
||||
|
||||
private void PresenterResize(ResizeEventArgs e)
|
||||
{
|
||||
Resize?.Invoke(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
10
PresenterWpf/src/AssemblyInfo.cs
Normal file
10
PresenterWpf/src/AssemblyInfo.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.Windows;
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
13
PresenterWpf/src/MainWindow.xaml
Normal file
13
PresenterWpf/src/MainWindow.xaml
Normal file
@@ -0,0 +1,13 @@
|
||||
<Window x:Class="PresenterWpf.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:PresenterWpf"
|
||||
mc:Ignorable="d"
|
||||
Title="MainWindow" Height="450" Width="800" Closing="MainWindow_OnClosing">
|
||||
<Grid>
|
||||
<Image x:Name="Image" Width="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=ActualWidth}"
|
||||
Height="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=ActualHeight}" />
|
||||
</Grid>
|
||||
</Window>
|
||||
101
PresenterWpf/src/MainWindow.xaml.cs
Normal file
101
PresenterWpf/src/MainWindow.xaml.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using System.Windows.Threading;
|
||||
using Engine.Asset;
|
||||
using Engine.Graphics;
|
||||
using Engine.Graphics.Pixel;
|
||||
using Engine.Graphics.Texture;
|
||||
using OpenTK.Windowing.Common;
|
||||
|
||||
namespace PresenterWpf;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window, IPresenter
|
||||
{
|
||||
public bool IsExiting { get; set; }
|
||||
public int Width => (int)_cachedWidth;
|
||||
public int Height => (int)_cachedHeight;
|
||||
public event Action<ResizeEventArgs>? Resize;
|
||||
|
||||
|
||||
private Engine.Engine _engine;
|
||||
private Image<Rgb8>? _image;
|
||||
private WriteableBitmap? _bitmap;
|
||||
|
||||
private int _cachedWidth;
|
||||
private int _cachedHeight;
|
||||
|
||||
public MainWindow(Engine.Engine parEngine)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_engine = parEngine;
|
||||
}
|
||||
|
||||
public void Update(double parDeltaTime)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
if ((int)Image.Width != _cachedWidth || (int)Image.Height != _cachedHeight)
|
||||
{
|
||||
_cachedWidth = (int)Image.Width;
|
||||
_cachedHeight = (int)Image.Height;
|
||||
}
|
||||
});
|
||||
|
||||
// Resizes are lazy so resizing only happens when the window's size actually changes
|
||||
if (Width != 0 && Height != 0)
|
||||
_engine.Renderer.Resize(Width, Height);
|
||||
}
|
||||
|
||||
public void Present(IConstTexture parTexture)
|
||||
{
|
||||
if (_image == null || parTexture.Width != _image.Width || parTexture.Height != _image.Height)
|
||||
{
|
||||
_image = new Image<Rgb8>(parTexture.Width, parTexture.Height);
|
||||
}
|
||||
|
||||
parTexture.ReadPixels(_image);
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
if (_bitmap == null || _bitmap.PixelWidth != _image.Width || _bitmap.PixelHeight != _image.Height)
|
||||
{
|
||||
_bitmap = new WriteableBitmap(_image.Width, _image.Height, 96, 96, PixelFormats.Rgb24, null);
|
||||
}
|
||||
|
||||
DrawImage(_image);
|
||||
Image.Source = _bitmap;
|
||||
});
|
||||
}
|
||||
|
||||
private void DrawImage(Image<Rgb8> parImage)
|
||||
{
|
||||
try
|
||||
{
|
||||
_bitmap!.Lock();
|
||||
_bitmap.WritePixels(new Int32Rect(0, 0, parImage.Width, parImage.Height), parImage.Pixels, parImage.Width * 3, 0,
|
||||
0);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_bitmap!.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void MainWindow_OnClosing(object? parSender, CancelEventArgs parE)
|
||||
{
|
||||
IsExiting = true;
|
||||
}
|
||||
}
|
||||
5
PresenterWpf/src/Program.cs
Normal file
5
PresenterWpf/src/Program.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
namespace PresenterWpf;
|
||||
|
||||
internal class Program
|
||||
{
|
||||
}
|
||||
Reference in New Issue
Block a user