This commit is contained in:
Chris Bell 2025-01-14 23:11:13 -06:00
commit 1a8baa2ff4
15 changed files with 347 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.idea/
AvaloniaOpenTK/bin/
AvaloniaOpenTK/obj/

16
AvaloniaOpenTK.sln Normal file
View File

@ -0,0 +1,16 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AvaloniaOpenTK", "AvaloniaOpenTK\AvaloniaOpenTK.csproj", "{9DF7318A-20CB-4172-B798-D1619F9615F8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9DF7318A-20CB-4172-B798-D1619F9615F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9DF7318A-20CB-4172-B798-D1619F9615F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9DF7318A-20CB-4172-B798-D1619F9615F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9DF7318A-20CB-4172-B798-D1619F9615F8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

15
AvaloniaOpenTK/App.axaml Normal file
View File

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

View File

@ -0,0 +1,47 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core;
using Avalonia.Data.Core.Plugins;
using System.Linq;
using Avalonia.Markup.Xaml;
using AvaloniaOpenTK.ViewModels;
using AvaloniaOpenTK.Views;
namespace AvaloniaOpenTK;
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
// Avoid duplicate validations from both Avalonia and the CommunityToolkit.
// More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins
DisableAvaloniaDataAnnotationValidation();
desktop.MainWindow = new MainWindow
{
DataContext = new MainWindowViewModel(),
};
}
base.OnFrameworkInitializationCompleted();
}
private void DisableAvaloniaDataAnnotationValidation()
{
// Get an array of plugins to remove
var dataValidationPluginsToRemove =
BindingPlugins.DataValidators.OfType<DataAnnotationsValidationPlugin>().ToArray();
// remove each entry found
foreach (var plugin in dataValidationPluginsToRemove)
{
BindingPlugins.DataValidators.Remove(plugin);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

View File

@ -0,0 +1,29 @@
<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>
<Folder Include="Models\"/>
<AvaloniaResource Include="Assets\**"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.2.1"/>
<PackageReference Include="Avalonia.Desktop" Version="11.2.1"/>
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.2.1"/>
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.1"/>
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Include="Avalonia.Diagnostics" Version="11.2.1">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1"/>
<PackageReference Include="OpenTK" Version="5.0.0-pre.13" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,7 @@
<UserControl 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"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="AvaloniaOpenTK.Controls.BaseOpenTKControl">
</UserControl>

View File

@ -0,0 +1,86 @@
// BaseOpenTKControl.axaml.cs
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.OpenGL;
using Avalonia.OpenGL.Controls;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
namespace AvaloniaOpenTK.Controls;
public partial class BaseOpenTKControl : OpenGlControlBase
{
private int _vao;
private int _vbo;
private readonly float[] _verts =
{
0.0f, 0.5f,
-0.5f, -0.5f,
0.5f, -0.5f
};
public BaseOpenTKControl()
{
InitializeComponent();
}
protected override void OnOpenGlInit(GlInterface gl)
{
GLLoader.LoadBindings(new AvaloniaBindingsContext(gl));
GL.ClearColor(new(0.2f, 0.4f, 0.8f, 1.0f));
_vao = GL.GenVertexArray();
GL.BindVertexArray(_vao);
_vbo = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo);
GL.BufferData(BufferTarget.ArrayBuffer, _verts.Length * sizeof(float), _verts, BufferUsage.StaticDraw);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 2 * sizeof(float), 0);
GL.BindVertexArray(0);
}
protected override void OnOpenGlRender(GlInterface gl, int fb)
{
var width = (int)Bounds.Width;
var height = (int)Bounds.Height;
GL.Viewport(0, 0, width, height);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.BindVertexArray(_vao);
GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
GL.BindVertexArray(0);
}
protected override void OnOpenGlDeinit(GlInterface gl)
{
GL.DeleteBuffer(_vbo);
GL.DeleteVertexArray(_vao);
}
private class AvaloniaBindingsContext : IBindingsContext
{
private readonly GlInterface _gl;
public AvaloniaBindingsContext(GlInterface gl)
{
_gl = gl;
}
public IntPtr GetProcAddress(string procName)
{
return _gl.GetProcAddress(procName);
}
}
}

43
AvaloniaOpenTK/Program.cs Normal file
View File

@ -0,0 +1,43 @@
using Avalonia;
using System;
using System.Collections.ObjectModel;
namespace AvaloniaOpenTK;
sealed class Program
{
// Platform-specific options to be passed to AppBuilder.Configure.
private static Win32PlatformOptions _win32PlatformOptions = new()
{
RenderingMode = new Collection<Win32RenderingMode>() { Win32RenderingMode.Wgl }
};
private static X11PlatformOptions _x11PlatformOptions = new()
{
RenderingMode = new Collection<X11RenderingMode>() { X11RenderingMode.Egl },
WmClass = "AvaloniaOpenTKApp"
};
private static MacOSPlatformOptions _macOSPlatformOptions = new()
{
ShowInDock = true
};
// 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()
.UseSkia()
.With(_win32PlatformOptions)
.With(_x11PlatformOptions)
.With(_macOSPlatformOptions)
.LogToTrace();
}

View File

@ -0,0 +1,30 @@
using System;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using AvaloniaOpenTK.ViewModels;
namespace AvaloniaOpenTK;
public class ViewLocator : IDataTemplate
{
public Control? Build(object? param)
{
if (param is null)
return null;
var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
var type = Type.GetType(name);
if (type != null)
{
return (Control)Activator.CreateInstance(type)!;
}
return new TextBlock { Text = "Not Found: " + name };
}
public bool Match(object? data)
{
return data is ViewModelBase;
}
}

View File

@ -0,0 +1,11 @@
using OpenTK.Mathematics;
namespace AvaloniaOpenTK.ViewModels;
public partial class MainWindowViewModel : ViewModelBase
{
public string Greeting { get; } = "Avalonia OpenTK!";
public int OpenTKViewportSizeX { get; } = 800;
public int OpenTKViewportSizeY { get; } = 800;
}

View File

@ -0,0 +1,7 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace AvaloniaOpenTK.ViewModels;
public class ViewModelBase : ObservableObject
{
}

View File

@ -0,0 +1,24 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:AvaloniaOpenTK.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="clr-namespace:AvaloniaOpenTK.Controls"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="AvaloniaOpenTK.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
Icon="/Assets/avalonia-logo.ico"
Title="AvaloniaOpenTK">
<Design.DataContext>
<!-- This only sets the DataContext for the previewer in an IDE,
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
<vm:MainWindowViewModel/>
</Design.DataContext>
<StackPanel x:Name="MainPanel" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="{Binding Greeting}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<controls:BaseOpenTKControl Width="{Binding OpenTKViewportSizeX}" Height="{Binding OpenTKViewportSizeY}"/>
</StackPanel>
</Window>

View File

@ -0,0 +1,11 @@
using Avalonia.Controls;
namespace AvaloniaOpenTK.Views;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}

View File

@ -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="AvaloniaOpenTK.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>