Explorar o código

omg something works

flabbet hai 1 ano
pai
achega
0e08c3b051

+ 10 - 0
src/InjectedDrawingApiAvalonia/App.axaml

@@ -0,0 +1,10 @@
+<Application xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             x:Class="InjectedDrawingApiAvalonia.App"
+             RequestedThemeVariant="Default">
+             <!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
+
+    <Application.Styles>
+        <FluentTheme />
+    </Application.Styles>
+</Application>

+ 66 - 0
src/InjectedDrawingApiAvalonia/App.axaml.cs

@@ -0,0 +1,66 @@
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Markup.Xaml;
+using Avalonia.Media.Imaging;
+using Avalonia.OpenGL;
+using Avalonia.Platform;
+using Avalonia.Rendering.Composition;
+using PixiEditor.DrawingApi.Core.Bridge;
+using PixiEditor.DrawingApi.Skia;
+using PixiEditor.Numerics;
+using SkiaSharp;
+
+namespace InjectedDrawingApiAvalonia;
+
+public partial class App : Application
+{
+    public override void Initialize()
+    {
+        AvaloniaXamlLoader.Load(this);
+    }
+
+    public override void OnFrameworkInitializationCompleted()
+    {
+        if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+        {
+            var grContext = App.GetGrContext();
+            DrawingBackendApi.SetupBackend(new SkiaDrawingBackend(CreateGpuSurface));
+            
+            desktop.MainWindow = new MainWindow();
+        }
+
+        base.OnFrameworkInitializationCompleted();
+    }
+
+    private SKSurface CreateGpuSurface(VecI size)
+    {
+        WriteableBitmap bitmap = new WriteableBitmap(new PixelSize(size.X, size.Y), new Vector(96, 96), PixelFormat.Bgra8888);
+        using var fb = bitmap.Lock();
+        SKImageInfo info = new(size.X, size.Y, SKColorType.Bgra8888, SKAlphaType.Premul);
+        return SKSurface.Create(info, fb.Address, fb.RowBytes);
+    }
+
+    public static GRContext GetGrContext()
+    {
+        Compositor compositor = Compositor.TryGetDefaultCompositor();
+        var interop = compositor.TryGetCompositionGpuInterop();
+        var contextSharingFeature =
+            compositor.TryGetRenderInterfaceFeature(typeof(IOpenGlTextureSharingRenderInterfaceContextFeature)).Result
+                as IOpenGlTextureSharingRenderInterfaceContextFeature;
+
+        if (contextSharingFeature.CanCreateSharedContext)
+        {
+            IGlContext? glContext = contextSharingFeature.CreateSharedContext();
+            glContext.MakeCurrent();
+            return GRContext.CreateGl(GRGlInterface.Create(glContext.GlInterface.GetProcAddress));
+        }
+
+        return null;
+        /*var contextFactory = AvaloniaLocator.Current.GetRequiredService<IPlatformGraphicsOpenGlContextFactory>();
+        var ctx = contextFactory.CreateContext(null);
+        ctx.MakeCurrent();
+        var ctxInterface = GRGlInterface.Create(ctx.GlInterface.GetProcAddress);
+        var grContext = GRContext.CreateGl(ctxInterface);
+        return grContext;*/
+    }
+}

+ 23 - 0
src/InjectedDrawingApiAvalonia/InjectedDrawingApiAvalonia.csproj

@@ -0,0 +1,23 @@
+<Project Sdk="Microsoft.NET.Sdk">
+    <PropertyGroup>
+        <OutputType>WinExe</OutputType>
+        <TargetFramework>net8.0</TargetFramework>
+        <Nullable>enable</Nullable>
+        <BuiltInComInteropSupport>true</BuiltInComInteropSupport>
+        <ApplicationManifest>app.manifest</ApplicationManifest>
+        <AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
+    </PropertyGroup>
+
+    <ItemGroup>
+        <PackageReference Include="Avalonia" Version="11.0.10"/>
+        <PackageReference Include="Avalonia.Desktop" Version="11.0.10"/>
+        <PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.10"/>
+        <PackageReference Include="Avalonia.Fonts.Inter" Version="11.0.10"/>
+        <!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
+        <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.10"/>
+    </ItemGroup>
+
+    <ItemGroup>
+      <ProjectReference Include="..\PixiEditor.DrawingApi.Skia\PixiEditor.DrawingApi.Skia.csproj" />
+    </ItemGroup>
+</Project>

+ 14 - 0
src/InjectedDrawingApiAvalonia/MainWindow.axaml

@@ -0,0 +1,14 @@
+<Window xmlns="https://github.com/avaloniaui"
+        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:visuals="clr-namespace:InjectedDrawingApiAvalonia.Visuals"
+        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+        x:Class="InjectedDrawingApiAvalonia.MainWindow"
+        Name="window" Background="CornflowerBlue"
+        Title="InjectedDrawingApiAvalonia">
+    
+    <visuals:SurfaceControl Width="128" Height="128" Name="SurfaceControl" VerticalAlignment="Top" HorizontalAlignment="Left"
+        Surface="{Binding Surface, ElementName=window}"/>
+    
+</Window>

+ 40 - 0
src/InjectedDrawingApiAvalonia/MainWindow.axaml.cs

@@ -0,0 +1,40 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using PixiEditor.DrawingApi.Core.Bridge;
+using PixiEditor.DrawingApi.Core.ColorsImpl;
+using PixiEditor.DrawingApi.Core.Surface;
+using PixiEditor.DrawingApi.Core.Surface.ImageData;
+using PixiEditor.DrawingApi.Core.Surface.PaintImpl;
+using PixiEditor.DrawingApi.Skia;
+
+namespace InjectedDrawingApiAvalonia;
+
+public partial class MainWindow : Window
+{
+    public static readonly StyledProperty<DrawingSurface> SurfaceProperty = AvaloniaProperty.Register<MainWindow, DrawingSurface>(
+        "Surface");
+
+    public DrawingSurface Surface
+    {
+        get => GetValue(SurfaceProperty);
+        set => SetValue(SurfaceProperty, value);
+    }
+    
+    public MainWindow()
+    {
+        InitializeComponent();
+    }
+
+    protected override void OnLoaded(RoutedEventArgs e)
+    {
+        base.OnLoaded(e);
+        
+        Surface = DrawingSurface.Create(new ImageInfo(128, 128));
+        
+        Surface.Canvas.Clear(Colors.Brown);
+        Surface.Canvas.DrawRect(0, 0, 128, 128, new Paint(){ Color = Colors.Green });
+        Surface.Canvas.Flush();
+        SurfaceControl.InvalidateVisual();
+    }
+}

+ 28 - 0
src/InjectedDrawingApiAvalonia/Program.cs

@@ -0,0 +1,28 @@
+using Avalonia;
+using System;
+
+namespace InjectedDrawingApiAvalonia;
+
+class Program
+{
+    // Initialization code. Don't use any Avalonia, third-party APIs or any
+    // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
+    // yet and stuff might break.
+    [STAThread]
+    public static void Main(string[] args)
+    {
+        BuildAvaloniaApp()
+            .StartWithClassicDesktopLifetime(args);
+    }
+
+    // Avalonia configuration, don't remove; also used by visual designer.
+    public static AppBuilder BuildAvaloniaApp()
+        => AppBuilder.Configure<App>()
+            .UsePlatformDetect()
+            .WithInterFont()
+            .With(new Win32PlatformOptions()
+            {
+                RenderingMode = new [] { Win32RenderingMode.Wgl },
+            })
+            .LogToTrace();
+}

+ 47 - 0
src/InjectedDrawingApiAvalonia/Visuals/SkiaDrawOperation.cs

@@ -0,0 +1,47 @@
+using System;
+using Avalonia;
+using Avalonia.Media;
+using Avalonia.Platform;
+using Avalonia.Rendering.SceneGraph;
+using Avalonia.Skia;
+
+namespace InjectedDrawingApiAvalonia.Visuals;
+
+internal abstract class SkiaDrawOperation : ICustomDrawOperation
+{
+    public Rect Bounds { get; }
+
+
+    public SkiaDrawOperation(Rect dirtyBounds)
+    {
+        Bounds = dirtyBounds;
+    }
+
+    public abstract bool Equals(ICustomDrawOperation? other);
+
+    public virtual void Dispose()
+    {
+
+    }
+
+    void IDisposable.Dispose()
+    {
+        Dispose();
+    }
+
+    public virtual bool HitTest(Point p) => false;
+
+    public void Render(ImmediateDrawingContext context)
+    {
+        if (!context.TryGetFeature(out ISkiaSharpApiLeaseFeature leaseFeature))
+        {
+            throw new InvalidOperationException("SkiaSharp API lease feature is not available.");
+        }
+
+        using var lease = leaseFeature.Lease();
+
+        Render(lease);
+    }
+
+    public abstract void Render(ISkiaSharpApiLease lease);
+}

+ 183 - 0
src/InjectedDrawingApiAvalonia/Visuals/SurfaceControl.cs

@@ -0,0 +1,183 @@
+using System;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Media;
+using Avalonia.Media.Imaging;
+using Avalonia.Rendering.SceneGraph;
+using Avalonia.Skia;
+using Avalonia.Threading;
+using PixiEditor.DrawingApi.Core.Surface;
+using PixiEditor.Numerics;
+using SkiaSharp;
+
+namespace InjectedDrawingApiAvalonia.Visuals;
+
+internal class SurfaceControl : Control
+{
+    public static readonly StyledProperty<DrawingSurface> SurfaceProperty =
+        AvaloniaProperty.Register<SurfaceControl, DrawingSurface>(
+            nameof(Surface));
+
+    public static readonly StyledProperty<Stretch> StretchProperty = AvaloniaProperty.Register<SurfaceControl, Stretch>(
+        nameof(Stretch), Stretch.Uniform);
+
+    public static readonly StyledProperty<IBrush> BackgroundProperty =
+        AvaloniaProperty.Register<SurfaceControl, IBrush>(
+            nameof(Background));
+
+    public IBrush Background
+    {
+        get => GetValue(BackgroundProperty);
+        set => SetValue(BackgroundProperty, value);
+    }
+
+    public Stretch Stretch
+    {
+        get => GetValue(StretchProperty);
+        set => SetValue(StretchProperty, value);
+    }
+
+    public DrawingSurface Surface
+    {
+        get => GetValue(SurfaceProperty);
+        set => SetValue(SurfaceProperty, value);
+    }
+
+    private RectI? nextDirtyRect;
+
+    static SurfaceControl()
+    {
+        AffectsMeasure<SurfaceControl>(StretchProperty, SurfaceProperty);
+        BoundsProperty.Changed.AddClassHandler<SurfaceControl>(BoundsChanged);
+        SurfaceProperty.Changed.AddClassHandler<SurfaceControl>(Rerender);
+        StretchProperty.Changed.AddClassHandler<SurfaceControl>(Rerender);
+    }
+
+    public SurfaceControl()
+    {
+        ClipToBounds = true;
+    }
+
+    /// <summary>
+    /// Measures the control.
+    /// </summary>
+    /// <param name="availableSize">The available size.</param>
+    /// <returns>The desired size of the control.</returns>
+    protected override Size MeasureOverride(Size availableSize)
+    {
+        var source = Surface;
+        var result = new Size();
+
+        result = new Size(Width, Height); 
+
+        return result;
+    }
+
+    /// <inheritdoc/>
+    protected override Size ArrangeOverride(Size finalSize)
+    {
+        var source = Surface;
+        return finalSize;
+    }
+
+    public override void Render(DrawingContext context)
+    {
+        if (Background != null)
+        {
+            context.FillRectangle(Background, new Rect(0, 0, Bounds.Width, Bounds.Height));
+        }
+
+        if (Surface == null || Surface.IsDisposed)
+        {
+            return;
+        }
+
+        var bounds = new Rect(Bounds.Size);
+        var operation = new DrawSurfaceOperation(bounds, Surface, Stretch, Opacity);
+        context.Custom(operation);
+        
+        Dispatcher.UIThread.InvokeAsync(InvalidateVisual, DispatcherPriority.Background);
+    }
+
+    private void SurfaceChanged(RectD? changedRect)
+    {
+        if (changedRect.HasValue)
+        {
+            var rect = changedRect.Value;
+            var rectI = new RectI((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height);
+            nextDirtyRect = nextDirtyRect?.Union(rectI) ?? rectI;
+        }
+        else
+        {
+            nextDirtyRect = null;
+        }
+
+        Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Render);
+    }
+
+    private static void BoundsChanged(SurfaceControl sender, AvaloniaPropertyChangedEventArgs e)
+    {
+        Dispatcher.UIThread.Post(sender.InvalidateVisual, DispatcherPriority.Render);
+    }
+
+    private static void Rerender(SurfaceControl sender, AvaloniaPropertyChangedEventArgs e)
+    {
+        if (e.OldValue is DrawingSurface oldSurface)
+        {
+            oldSurface.Changed -= sender.SurfaceChanged;
+        }
+
+        if (e.NewValue is DrawingSurface newSurface)
+        {
+            newSurface.Changed += sender.SurfaceChanged;
+        }
+
+        Dispatcher.UIThread.Post(sender.InvalidateVisual, DispatcherPriority.Render);
+    }
+}
+
+internal class DrawSurfaceOperation : SkiaDrawOperation
+{
+    public DrawingSurface Surface { get; }
+    public Stretch Stretch { get; }
+
+    public double Opacity { get; set; } = 1.0;
+
+    private SKPaint _paint = new SKPaint();
+    
+    private WriteableBitmap targetBitmap;
+
+    public DrawSurfaceOperation(Rect dirtyBounds, DrawingSurface surface, Stretch stretch, double opacity = 1) :
+        base(dirtyBounds)
+    {
+        Surface = surface;
+        Stretch = stretch;
+        Opacity = opacity;
+    }
+
+    public override void Render(ISkiaSharpApiLease lease)
+    {
+        SKCanvas canvas = lease.SkCanvas;
+
+        if (Surface == null || Surface.IsDisposed)
+        {
+            return;
+        }
+            
+        canvas.Save();
+        _paint.Color = _paint.Color.WithAlpha((byte)(Opacity * 255));
+        canvas.DrawSurface((SKSurface)Surface.Native, new SKPoint(0, 0), _paint);
+        canvas.Restore();
+    }
+
+
+    public override bool Equals(ICustomDrawOperation? other)
+    {
+        return other is DrawSurfaceOperation otherOp && otherOp.Surface == Surface && otherOp.Stretch == Stretch;
+    }
+
+    public override void Dispose()
+    {
+        _paint.Dispose();
+    }
+}

+ 18 - 0
src/InjectedDrawingApiAvalonia/app.manifest

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+  <!-- This manifest is used on Windows only.
+       Don't remove it as it might cause problems with window transparency and embedded controls.
+       For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
+  <assemblyIdentity version="1.0.0.0" name="InjectedDrawingApiAvalonia.Desktop"/>
+
+  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+    <application>
+      <!-- A list of the Windows versions that this application has been tested on
+           and is designed to work with. Uncomment the appropriate elements
+           and Windows will automatically select the most compatible environment. -->
+
+      <!-- Windows 10 -->
+      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
+    </application>
+  </compatibility>
+</assembly>

+ 4 - 4
src/PixiEditor.DrawingApi.Skia/Implementations/SkiaSurfaceImplementation.cs

@@ -15,14 +15,14 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
         private readonly SkiaCanvasImplementation _canvasImplementation;
         private readonly SkiaCanvasImplementation _canvasImplementation;
         private readonly SkiaPaintImplementation _paintImplementation;
         private readonly SkiaPaintImplementation _paintImplementation;
 
 
-        public GRContext GraphicsContext { get; set; }
+        public Func<VecI, SKSurface> CreateGpuSurface { get; set; }
 
 
-        public SkiaSurfaceImplementation(GRContext context, SkiaPixmapImplementation pixmapImplementation, SkiaCanvasImplementation canvasImplementation, SkiaPaintImplementation paintImplementation)
+        public SkiaSurfaceImplementation(Func<VecI, SKSurface> context, SkiaPixmapImplementation pixmapImplementation, SkiaCanvasImplementation canvasImplementation, SkiaPaintImplementation paintImplementation)
         {
         {
             _pixmapImplementation = pixmapImplementation;
             _pixmapImplementation = pixmapImplementation;
             _canvasImplementation = canvasImplementation;
             _canvasImplementation = canvasImplementation;
             _paintImplementation = paintImplementation;
             _paintImplementation = paintImplementation;
-            GraphicsContext = context;
+            CreateGpuSurface = context;
         }
         }
         
         
         public Pixmap PeekPixels(DrawingSurface drawingSurface)
         public Pixmap PeekPixels(DrawingSurface drawingSurface)
@@ -91,7 +91,7 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
 
 
         private SKSurface CreateSkiaSurface(VecI size)
         private SKSurface CreateSkiaSurface(VecI size)
         {
         {
-            return SKSurface.Create(GraphicsContext, false, new SKImageInfo(size.X, size.Y));
+            return CreateGpuSurface(size);
         }
         }
 
 
         public void Dispose(DrawingSurface drawingSurface)
         public void Dispose(DrawingSurface drawingSurface)

+ 7 - 5
src/PixiEditor.DrawingApi.Skia/SkiaDrawingBackend.cs

@@ -1,8 +1,10 @@
-using PixiEditor.DrawingApi.Core.Bridge;
+using System;
+using PixiEditor.DrawingApi.Core.Bridge;
 using PixiEditor.DrawingApi.Core.Bridge.NativeObjectsImpl;
 using PixiEditor.DrawingApi.Core.Bridge.NativeObjectsImpl;
 using PixiEditor.DrawingApi.Core.Bridge.Operations;
 using PixiEditor.DrawingApi.Core.Bridge.Operations;
 using PixiEditor.DrawingApi.Skia.Exceptions;
 using PixiEditor.DrawingApi.Skia.Exceptions;
 using PixiEditor.DrawingApi.Skia.Implementations;
 using PixiEditor.DrawingApi.Skia.Implementations;
+using PixiEditor.Numerics;
 using SkiaSharp;
 using SkiaSharp;
 
 
 namespace PixiEditor.DrawingApi.Skia
 namespace PixiEditor.DrawingApi.Skia
@@ -38,11 +40,11 @@ namespace PixiEditor.DrawingApi.Skia
         public IBitmapImplementation BitmapImplementation { get; }
         public IBitmapImplementation BitmapImplementation { get; }
         public IColorFilterImplementation ColorFilterImplementation { get; set; }
         public IColorFilterImplementation ColorFilterImplementation { get; set; }
         public IShaderImplementation ShaderImplementation { get; set; }
         public IShaderImplementation ShaderImplementation { get; set; }
-        
+
         private SkiaSurfaceImplementation _surfaceImplementation;
         private SkiaSurfaceImplementation _surfaceImplementation;
         private GRContext _grContext;
         private GRContext _grContext;
 
 
-        public SkiaDrawingBackend()
+        public SkiaDrawingBackend(Func<VecI, SKSurface> createSurface)
         {
         {
             ColorImplementation = new SkiaColorImplementation();
             ColorImplementation = new SkiaColorImplementation();
             
             
@@ -77,7 +79,7 @@ namespace PixiEditor.DrawingApi.Skia
             
             
             SkiaCanvasImplementation canvasImpl = new SkiaCanvasImplementation(paintImpl, imgImpl, bitmapImpl, pathImpl);
             SkiaCanvasImplementation canvasImpl = new SkiaCanvasImplementation(paintImpl, imgImpl, bitmapImpl, pathImpl);
             
             
-            _surfaceImplementation = new SkiaSurfaceImplementation(GraphicsContext, pixmapImpl, canvasImpl, paintImpl);
+            _surfaceImplementation = new SkiaSurfaceImplementation(createSurface, pixmapImpl, canvasImpl, paintImpl);
 
 
             canvasImpl.SetSurfaceImplementation(_surfaceImplementation);
             canvasImpl.SetSurfaceImplementation(_surfaceImplementation);
             imgImpl.SetSurfaceImplementation(_surfaceImplementation);
             imgImpl.SetSurfaceImplementation(_surfaceImplementation);
@@ -87,7 +89,7 @@ namespace PixiEditor.DrawingApi.Skia
         
         
         public void Setup()
         public void Setup()
         {
         {
-            _surfaceImplementation.GraphicsContext = GraphicsContext;
+            
         }
         }
     }
     }
 }
 }

+ 31 - 0
src/PixiEditor.sln

@@ -112,6 +112,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PixiEngineSampleApp", "Pixi
 EndProject
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PixiEngineAvaloniaApp", "PixiEngineAvaloniaApp\PixiEngineAvaloniaApp.csproj", "{D63AC04D-075B-4A8B-8FDC-C46975AFEFF3}"
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PixiEngineAvaloniaApp", "PixiEngineAvaloniaApp\PixiEngineAvaloniaApp.csproj", "{D63AC04D-075B-4A8B-8FDC-C46975AFEFF3}"
 EndProject
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InjectedDrawingApiAvalonia", "InjectedDrawingApiAvalonia\InjectedDrawingApiAvalonia.csproj", "{7B741B75-130D-48F6-B37D-55CD142F1FF8}"
+EndProject
 Global
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|x64 = Debug|x64
 		Debug|x64 = Debug|x64
@@ -1622,6 +1624,34 @@ Global
 		{D63AC04D-075B-4A8B-8FDC-C46975AFEFF3}.Steam|x64.Build.0 = Debug|Any CPU
 		{D63AC04D-075B-4A8B-8FDC-C46975AFEFF3}.Steam|x64.Build.0 = Debug|Any CPU
 		{D63AC04D-075B-4A8B-8FDC-C46975AFEFF3}.Steam|ARM64.ActiveCfg = Debug|Any CPU
 		{D63AC04D-075B-4A8B-8FDC-C46975AFEFF3}.Steam|ARM64.ActiveCfg = Debug|Any CPU
 		{D63AC04D-075B-4A8B-8FDC-C46975AFEFF3}.Steam|ARM64.Build.0 = Debug|Any CPU
 		{D63AC04D-075B-4A8B-8FDC-C46975AFEFF3}.Steam|ARM64.Build.0 = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.Debug|x64.Build.0 = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.Debug|ARM64.Build.0 = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.DevRelease|x64.ActiveCfg = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.DevRelease|x64.Build.0 = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.DevRelease|ARM64.ActiveCfg = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.DevRelease|ARM64.Build.0 = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.DevSteam|x64.ActiveCfg = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.DevSteam|x64.Build.0 = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.DevSteam|ARM64.ActiveCfg = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.DevSteam|ARM64.Build.0 = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.MSIX Debug|x64.ActiveCfg = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.MSIX Debug|x64.Build.0 = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.MSIX Debug|ARM64.ActiveCfg = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.MSIX Debug|ARM64.Build.0 = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.MSIX|x64.ActiveCfg = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.MSIX|x64.Build.0 = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.MSIX|ARM64.ActiveCfg = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.MSIX|ARM64.Build.0 = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.Release|x64.ActiveCfg = Release|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.Release|x64.Build.0 = Release|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.Release|ARM64.ActiveCfg = Release|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.Release|ARM64.Build.0 = Release|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.Steam|x64.ActiveCfg = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.Steam|x64.Build.0 = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.Steam|ARM64.ActiveCfg = Debug|Any CPU
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8}.Steam|ARM64.Build.0 = Debug|Any CPU
 	EndGlobalSection
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 		HideSolutionNode = FALSE
@@ -1672,6 +1702,7 @@ Global
 		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C} = {55A3BEC1-C848-4BA9-BB16-028467CC46C8}
 		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C} = {55A3BEC1-C848-4BA9-BB16-028467CC46C8}
 		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80} = {5AFBF881-C054-4CE4-8159-8D4017FFD27A}
 		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80} = {5AFBF881-C054-4CE4-8159-8D4017FFD27A}
 		{D63AC04D-075B-4A8B-8FDC-C46975AFEFF3} = {5AFBF881-C054-4CE4-8159-8D4017FFD27A}
 		{D63AC04D-075B-4A8B-8FDC-C46975AFEFF3} = {5AFBF881-C054-4CE4-8159-8D4017FFD27A}
+		{7B741B75-130D-48F6-B37D-55CD142F1FF8} = {5AFBF881-C054-4CE4-8159-8D4017FFD27A}
 	EndGlobalSection
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {D04B4AB0-CA33-42FD-A909-79966F9255C5}
 		SolutionGuid = {D04B4AB0-CA33-42FD-A909-79966F9255C5}