From 6e97969d70ced27a30607a04a4af7b0bf3d6a59c Mon Sep 17 00:00:00 2001 From: Curtis Wensley Date: Thu, 21 Jan 2021 02:56:16 -0800 Subject: [PATCH 01/24] Update Eto and migrate to .NET 5 for test apps --- .vscode/launch.json | 6 +++--- .vscode/tasks.json | 2 +- src/Eto.Veldrid.Gtk/Eto.Veldrid.Gtk.csproj | 5 ++--- src/Eto.Veldrid.Mac/Eto.Veldrid.Mac64.csproj | 4 ++-- src/Eto.Veldrid.WinForms/Eto.Veldrid.WinForms.csproj | 2 +- src/Eto.Veldrid.Wpf/Eto.Veldrid.Wpf.csproj | 2 +- src/Eto.Veldrid/Eto.Veldrid.csproj | 2 +- test/TestEtoVeldrid.Gtk/TestEtoVeldrid.Gtk.csproj | 4 ++-- test/TestEtoVeldrid.Mac/TestEtoVeldrid.Mac64.csproj | 2 +- test/TestEtoVeldrid.WinForms/TestEtoVeldrid.WinForms.csproj | 2 +- test/TestEtoVeldrid.Wpf/TestEtoVeldrid.Wpf.csproj | 2 +- test/TestEtoVeldrid/MainForm.eto.cs | 6 +++--- test/TestEtoVeldrid/TestEtoVeldrid.csproj | 2 +- 13 files changed, 20 insertions(+), 21 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 5523677..d327e94 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,13 +11,13 @@ "preLaunchTask": "build", "program": "", "osx": { - "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Mac64/Debug/netcoreapp3.1/osx-x64/TestEtoVeldrid.Mac64.app/Contents/MacOS/TestEtoVeldrid.Mac64" + "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Mac64/Debug/net5.0/osx-x64/TestEtoVeldrid.Mac64.app/Contents/MacOS/TestEtoVeldrid.Mac64" }, "linux": { - "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Gtk/Debug/netcoreapp3.1/linux-x64/TestEtoVeldrid.Gtk.dll" + "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Gtk/Debug/net5.0/linux-x64/TestEtoVeldrid.Gtk.dll" }, "windows": { - "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Wpf/Debug/netcoreapp3.1/win-x64/TestEtoVeldrid.Wpf.dll" + "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Wpf/Debug/net5.0/win-x64/TestEtoVeldrid.Wpf.dll" }, "console": "internalConsole", "stopAtEntry": false diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 26f61cc..10d70b6 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -4,7 +4,7 @@ { "label": "build", "command": "dotnet", - "type": "process", + "type": "shell", "osx": { "args": [ "build", diff --git a/src/Eto.Veldrid.Gtk/Eto.Veldrid.Gtk.csproj b/src/Eto.Veldrid.Gtk/Eto.Veldrid.Gtk.csproj index e91b0b1..f093932 100644 --- a/src/Eto.Veldrid.Gtk/Eto.Veldrid.Gtk.csproj +++ b/src/Eto.Veldrid.Gtk/Eto.Veldrid.Gtk.csproj @@ -1,7 +1,7 @@  - net461;netcoreapp3.1 + netcoreapp3.1;net461 GTK3 Veldrid Gtk implementation for Eto.Forms This provides the Gtk implementation of Eto.Veldrid for Eto.Forms @@ -13,8 +13,7 @@ - - + diff --git a/src/Eto.Veldrid.Mac/Eto.Veldrid.Mac64.csproj b/src/Eto.Veldrid.Mac/Eto.Veldrid.Mac64.csproj index 9472807..88d0657 100644 --- a/src/Eto.Veldrid.Mac/Eto.Veldrid.Mac64.csproj +++ b/src/Eto.Veldrid.Mac/Eto.Veldrid.Mac64.csproj @@ -1,7 +1,7 @@  - net461;netcoreapp3.1 + netcoreapp3.1;net461 MONOMAC false Veldrid Mac implementation for Eto.Forms @@ -9,7 +9,7 @@ - + diff --git a/src/Eto.Veldrid.WinForms/Eto.Veldrid.WinForms.csproj b/src/Eto.Veldrid.WinForms/Eto.Veldrid.WinForms.csproj index a3ac4b5..dfa6860 100755 --- a/src/Eto.Veldrid.WinForms/Eto.Veldrid.WinForms.csproj +++ b/src/Eto.Veldrid.WinForms/Eto.Veldrid.WinForms.csproj @@ -25,7 +25,7 @@ - + diff --git a/src/Eto.Veldrid.Wpf/Eto.Veldrid.Wpf.csproj b/src/Eto.Veldrid.Wpf/Eto.Veldrid.Wpf.csproj index d68174e..92ebf5d 100755 --- a/src/Eto.Veldrid.Wpf/Eto.Veldrid.Wpf.csproj +++ b/src/Eto.Veldrid.Wpf/Eto.Veldrid.Wpf.csproj @@ -23,7 +23,7 @@ - + - + diff --git a/src/Eto.Veldrid/Eto.Veldrid.csproj b/src/Eto.Veldrid/Eto.Veldrid.csproj index 1100d1f..84520c3 100644 --- a/src/Eto.Veldrid/Eto.Veldrid.csproj +++ b/src/Eto.Veldrid/Eto.Veldrid.csproj @@ -1,22 +1,22 @@  - netstandard2.0 AnyCPU Veldrid Control for Eto.Forms This provides the control to use in your Eto.Forms application. Add the platform-specific package for each platform you wish to support. E.g. Eto.Veldrid.Gtk, Eto.Veldrid.Mac64, Eto.Veldrid.Wpf, etc. + net7.0 - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/test/TestEtoVeldrid.Gtk/TestEtoVeldrid.Gtk.csproj b/test/TestEtoVeldrid.Gtk/TestEtoVeldrid.Gtk.csproj index e2d5cf6..d29df91 100644 --- a/test/TestEtoVeldrid.Gtk/TestEtoVeldrid.Gtk.csproj +++ b/test/TestEtoVeldrid.Gtk/TestEtoVeldrid.Gtk.csproj @@ -2,8 +2,8 @@ WinExe - net5.0;net48 linux-x64 + net7.0 @@ -12,8 +12,8 @@ - - + + diff --git a/test/TestEtoVeldrid.Mac/TestEtoVeldrid.Mac64.csproj b/test/TestEtoVeldrid.Mac/TestEtoVeldrid.Mac64.csproj index 86f5b8a..348443b 100644 --- a/test/TestEtoVeldrid.Mac/TestEtoVeldrid.Mac64.csproj +++ b/test/TestEtoVeldrid.Mac/TestEtoVeldrid.Mac64.csproj @@ -2,14 +2,14 @@ WinExe - net48;net5.0 MONOMAC osx-x64 + net7.0 - - + + diff --git a/test/TestEtoVeldrid.WinForms/TestEtoVeldrid.WinForms.csproj b/test/TestEtoVeldrid.WinForms/TestEtoVeldrid.WinForms.csproj index 38f7c23..1886146 100644 --- a/test/TestEtoVeldrid.WinForms/TestEtoVeldrid.WinForms.csproj +++ b/test/TestEtoVeldrid.WinForms/TestEtoVeldrid.WinForms.csproj @@ -2,6 +2,7 @@ true + net7.0 @@ -9,7 +10,6 @@ WinExe - net48 $(TargetFrameworks);net5.0-windows true win-x64 @@ -21,7 +21,7 @@ - + diff --git a/test/TestEtoVeldrid.Wpf/TestEtoVeldrid.Wpf.csproj b/test/TestEtoVeldrid.Wpf/TestEtoVeldrid.Wpf.csproj index 13a18be..f72b470 100644 --- a/test/TestEtoVeldrid.Wpf/TestEtoVeldrid.Wpf.csproj +++ b/test/TestEtoVeldrid.Wpf/TestEtoVeldrid.Wpf.csproj @@ -2,6 +2,7 @@ true + net7.0 @@ -9,7 +10,6 @@ WinExe - net48 $(TargetFrameworks);net5.0-windows app1.manifest true @@ -31,7 +31,7 @@ https://github.com/picoe/Eto/issues/1544 https://github.com/xceedsoftware/wpftoolkit/issues/1557 --> - + diff --git a/test/TestEtoVeldrid/MainForm.cs b/test/TestEtoVeldrid/MainForm.cs index 0eb291b..e337f40 100644 --- a/test/TestEtoVeldrid/MainForm.cs +++ b/test/TestEtoVeldrid/MainForm.cs @@ -60,7 +60,6 @@ public MainForm(GraphicsBackend backend) Surface = new VeldridSurface(backend, options); Surface.Size = new Eto.Drawing.Size(200, 200); - Surface.VeldridInitialized += (sender, e) => VeldridReady = true; Content = Surface; @@ -69,6 +68,13 @@ public MainForm(GraphicsBackend backend) Surface = Surface }; + Surface.VeldridInitialized += (sender, e) => + { + Driver.SetUpVeldrid(); + + VeldridReady = true; + }; + // TODO: Make this binding actually work both ways. CmdAnimate.Bind("Checked", Driver, "Animate"); CmdClockwise.Bind("Checked", Driver, "Clockwise"); @@ -81,8 +87,6 @@ private void SetUpVeldrid() return; } - Driver.SetUpVeldrid(); - Title = $"Veldrid backend: {Surface.Backend.ToString()}"; Driver.Clock.Start(); diff --git a/test/TestEtoVeldrid/TestEtoVeldrid.csproj b/test/TestEtoVeldrid/TestEtoVeldrid.csproj index 04bf61a..326dc5c 100644 --- a/test/TestEtoVeldrid/TestEtoVeldrid.csproj +++ b/test/TestEtoVeldrid/TestEtoVeldrid.csproj @@ -1,10 +1,10 @@  - netstandard2.0 AnyCPU TestEtoVeldrid TestEtoVeldrid + net7.0 @@ -13,9 +13,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive From 842c7581e51afa456ce0896ba9412aa5ac05e360 Mon Sep 17 00:00:00 2001 From: philstopford Date: Sun, 11 Feb 2024 18:52:57 -0600 Subject: [PATCH 07/24] Shuffling some things around. --- Eto.Veldrid.sln | 11 ++++++++ .../Eto.VeldridSurface.csproj | 28 +++++++++++++++++++ .../Eto.VeldridSurface}/VeldridDriver.cs | 4 +-- .../shaders/VertexColor-fragment.450.glsl | 0 .../shaders/VertexColor-vertex.450.glsl | 0 test/TestEtoVeldrid/MainForm.cs | 2 +- test/TestEtoVeldrid/TestEtoVeldrid.csproj | 1 + 7 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 src/Eto.VeldridSurface/Eto.VeldridSurface.csproj rename {test/TestEtoVeldrid => src/Eto.VeldridSurface}/VeldridDriver.cs (99%) rename {test/TestEtoVeldrid => src/Eto.VeldridSurface}/shaders/VertexColor-fragment.450.glsl (100%) rename {test/TestEtoVeldrid => src/Eto.VeldridSurface}/shaders/VertexColor-vertex.450.glsl (100%) diff --git a/Eto.Veldrid.sln b/Eto.Veldrid.sln index 0a58c0f..8dbb54f 100644 --- a/Eto.Veldrid.sln +++ b/Eto.Veldrid.sln @@ -34,6 +34,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestEtoVeldrid.Wpf", "test\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestEtoVeldrid", "test\TestEtoVeldrid\TestEtoVeldrid.csproj", "{14AFF269-5C00-4E7A-8528-4DA704B7D2F4}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Eto.VeldridSurface", "src\Eto.VeldridSurface\Eto.VeldridSurface.csproj", "{AB712D06-69EA-4601-A9B3-774820B56633}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Mac = Debug|Mac @@ -114,6 +116,14 @@ Global {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Release|Mac.Build.0 = Release|Any CPU {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Release|Windows.ActiveCfg = Release|Any CPU {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Release|Windows.Build.0 = Release|Any CPU + {AB712D06-69EA-4601-A9B3-774820B56633}.Debug|Mac.ActiveCfg = Debug|Any CPU + {AB712D06-69EA-4601-A9B3-774820B56633}.Debug|Mac.Build.0 = Debug|Any CPU + {AB712D06-69EA-4601-A9B3-774820B56633}.Debug|Windows.ActiveCfg = Debug|Any CPU + {AB712D06-69EA-4601-A9B3-774820B56633}.Debug|Windows.Build.0 = Debug|Any CPU + {AB712D06-69EA-4601-A9B3-774820B56633}.Release|Mac.ActiveCfg = Release|Any CPU + {AB712D06-69EA-4601-A9B3-774820B56633}.Release|Mac.Build.0 = Release|Any CPU + {AB712D06-69EA-4601-A9B3-774820B56633}.Release|Windows.ActiveCfg = Release|Any CPU + {AB712D06-69EA-4601-A9B3-774820B56633}.Release|Windows.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -129,6 +139,7 @@ Global {3589BA37-A44E-49DB-A370-26D41EB3955F} = {48C6A621-D898-4932-A28F-DFC0C1B272B6} {51F518B4-5A7F-438D-A164-145D527DB1FF} = {48C6A621-D898-4932-A28F-DFC0C1B272B6} {14AFF269-5C00-4E7A-8528-4DA704B7D2F4} = {48C6A621-D898-4932-A28F-DFC0C1B272B6} + {AB712D06-69EA-4601-A9B3-774820B56633} = {6136B651-45C5-48C7-80E7-943FF2461732} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A0F9A175-218E-4414-B0EC-A227B0E5FA61} diff --git a/src/Eto.VeldridSurface/Eto.VeldridSurface.csproj b/src/Eto.VeldridSurface/Eto.VeldridSurface.csproj new file mode 100644 index 0000000..0ff9353 --- /dev/null +++ b/src/Eto.VeldridSurface/Eto.VeldridSurface.csproj @@ -0,0 +1,28 @@ + + + + net7.0 + enable + enable + + + + + + + + + + + + + + ..\..\..\..\..\home\phil\.nuget\packages\veldrid.spirv\1.0.15\lib\netstandard2.0\Veldrid.SPIRV.dll + + + + + + + + diff --git a/test/TestEtoVeldrid/VeldridDriver.cs b/src/Eto.VeldridSurface/VeldridDriver.cs similarity index 99% rename from test/TestEtoVeldrid/VeldridDriver.cs rename to src/Eto.VeldridSurface/VeldridDriver.cs index 20e4704..75f7829 100644 --- a/test/TestEtoVeldrid/VeldridDriver.cs +++ b/src/Eto.VeldridSurface/VeldridDriver.cs @@ -7,7 +7,7 @@ using Veldrid; using Veldrid.SPIRV; -namespace TestEtoVeldrid +namespace TestEtoVeldrid2 { public struct VertexPositionColor { @@ -285,7 +285,7 @@ private void CreateResources() private byte[] LoadSpirvBytes(ShaderStages stage) { string name = $"VertexColor-{stage.ToString().ToLowerInvariant()}.450.glsl"; - string full = $"TestEtoVeldrid.shaders.{name}"; + string full = $"Eto.VeldridSurface.shaders.{name}"; // Precompiled SPIR-V bytecode can speed up program start by saving // the need to load text files and compile them before converting diff --git a/test/TestEtoVeldrid/shaders/VertexColor-fragment.450.glsl b/src/Eto.VeldridSurface/shaders/VertexColor-fragment.450.glsl similarity index 100% rename from test/TestEtoVeldrid/shaders/VertexColor-fragment.450.glsl rename to src/Eto.VeldridSurface/shaders/VertexColor-fragment.450.glsl diff --git a/test/TestEtoVeldrid/shaders/VertexColor-vertex.450.glsl b/src/Eto.VeldridSurface/shaders/VertexColor-vertex.450.glsl similarity index 100% rename from test/TestEtoVeldrid/shaders/VertexColor-vertex.450.glsl rename to src/Eto.VeldridSurface/shaders/VertexColor-vertex.450.glsl diff --git a/test/TestEtoVeldrid/MainForm.cs b/test/TestEtoVeldrid/MainForm.cs index e337f40..898acaa 100644 --- a/test/TestEtoVeldrid/MainForm.cs +++ b/test/TestEtoVeldrid/MainForm.cs @@ -1,6 +1,6 @@ using Eto.Forms; using Eto.Veldrid; -using System; +using TestEtoVeldrid2; using Veldrid; namespace TestEtoVeldrid diff --git a/test/TestEtoVeldrid/TestEtoVeldrid.csproj b/test/TestEtoVeldrid/TestEtoVeldrid.csproj index 326dc5c..2c73e0c 100644 --- a/test/TestEtoVeldrid/TestEtoVeldrid.csproj +++ b/test/TestEtoVeldrid/TestEtoVeldrid.csproj @@ -22,6 +22,7 @@ + From e29a67b3cee6f9d13b124f3ab85e8893792eae00 Mon Sep 17 00:00:00 2001 From: philstopford Date: Thu, 15 Feb 2024 21:39:08 -0600 Subject: [PATCH 08/24] This draws a partial line... --- src/Eto.VeldridSurface/OVPSettings.cs | 596 ++++++++++++++++++++++++ src/Eto.VeldridSurface/VeldridDriver.cs | 257 +++++++--- src/Eto.VeldridSurface/ovp_Poly.cs | 24 + test/TestEtoVeldrid/MainForm.cs | 8 +- 4 files changed, 823 insertions(+), 62 deletions(-) create mode 100644 src/Eto.VeldridSurface/OVPSettings.cs create mode 100644 src/Eto.VeldridSurface/ovp_Poly.cs diff --git a/src/Eto.VeldridSurface/OVPSettings.cs b/src/Eto.VeldridSurface/OVPSettings.cs new file mode 100644 index 0000000..60c36f9 --- /dev/null +++ b/src/Eto.VeldridSurface/OVPSettings.cs @@ -0,0 +1,596 @@ +using Eto.Drawing; +using Eto.Forms; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace VeldridEto; + +public static class errorReporter +{ + public static void showMessage_OK(string stringToDisplay, string caption) + { + Application.Instance.Invoke(() => + { + MessageBox.Show(stringToDisplay, caption, MessageBoxButtons.OK); + }); + } +} + +public class OVPSettings +{ + // This is true if something changed in the settings (set internally for query). The viewport itself should set this false when the changes are handled. + public bool changed { get; set; } + + public int selectedIndex { get; set; } + + public float minX { get; set; } + public float maxX { get; set; } + public float minY { get; set; } + public float maxY { get; set; } + public Color minorGridColor { get; set; } + public Color majorGridColor { get; set; } + public Color axisColor { get; set; } + public Color backColor { get; set; } + public Color selectionColor { get; set; } + public Color inverSelectionColor { get; set; } + + public List polyList { get; set; } + public List polyListPtCount { get; set; } + public List polySourceIndex { get; set; } // will eventually track source of polygon, allowing for layer generating, etc. in output. + + public List polyMask { get; set; } // Masking boolean for overriding handling of polygons as-desired. + public List bgPolyList { get; set; } + public List bgPolyListPtCount { get; set; } + public List bgPolySourceIndex { get; set; } // will eventually track source of polygon, allowing for layer generating, etc. in output. + public List lineList { get; set; } // purely for lines. + public List lineListPtCount { get; set; } + public List lineSourceIndex { get; set; } // will eventually track source of polygon, allowing for layer generating, etc. in output. + public List lineMask { get; set; } // Masking boolean for overriding handling of polygons as-desired. + + public List tessPolyList { get; set; } // triangles, but also need to track color. This is decoupled to allow boundary extraction without triangles getting in the way. + public List drawnPoly { get; set; } // tracks whether the polygon corresponds to an enabled configuration or not. + + private bool enableFilledPolys; + private bool showPoints; + private float base_zoom; + private float zoomFactor; + private int zoomStep; + private bool allowZoomAndPan; + private bool dynamicGrid; + private bool panning; + private bool selecting; + private bool showGrid; + private bool showAxes; + private bool showDrawn; + private int grid_spacing; + private PointF cameraPosition; + private PointF default_cameraPosition; + private bool antiAlias; + private bool lockedViewport; + + public bool aA() + { + return antiAlias; + } + + public void aA(bool val) + { + if (antiAlias == val) + { + return; + } + antiAlias = val; + changed = true; + } + + public bool drawGrid() + { + return showGrid; + } + + public void drawGrid(bool val) + { + if (showGrid == val) + { + return; + } + showGrid = val; + changed = true; + } + + public bool drawPoints() + { + return showPoints; + } + + public void drawPoints (bool val) + { + if (showPoints == val) + { + return; + } + showPoints = val; + changed = true; + } + + public bool drawDrawn() + { + return showDrawn; + } + + public void drawDrawn(bool val) + { + if (showDrawn == val) + { + return; + } + showDrawn = val; + changed = true; + } + + public bool drawFilled() + { + return enableFilledPolys; + } + + public void drawFilled(bool val) + { + if (enableFilledPolys == val) + { + return; + } + enableFilledPolys = val; + changed = true; + } + + public bool drawAxes() + { + return showAxes; + } + + public void drawAxes(bool val) + { + if (showAxes == val) + { + return; + } + showAxes = val; + changed = true; + } + + public bool isGridDynamic() + { + return dynamicGrid; + } + + public void isGridDynamic(bool val) + { + if (dynamicGrid == val) + { + return; + } + dynamicGrid = val; + changed = true; + } + + public float gridSpacing() + { + return grid_spacing; + } + + public void resetCamera() + { + switch (lockedViewport) + { + case true: + return; + default: + setCameraPos(default_cameraPosition.X, default_cameraPosition.Y); + setZoomFactor(1.0f); + break; + } + } + + public void setCameraPos(float x, float y) + { + setCameraX(x); + setCameraY(y); + } + + public PointF getCameraPos() + { + return cameraPosition; + } + + public void setCameraX(float x) + { + switch (lockedViewport) + { + case true: + return; + default: + cameraPosition.X = x; + changed = true; + break; + } + } + + public void setCameraY(float y) + { + switch (lockedViewport) + { + case true: + return; + default: + cameraPosition.Y = y; + changed = true; + break; + } + } + + public float getCameraX() + { + return cameraPosition.X; + } + + public float getCameraY() + { + return cameraPosition.Y; + } + + public float getBaseZoom() + { + return base_zoom; + } + + public void setBaseZoom(float val) + { + base_zoom = val; + } + public void setZoomFactor(float val) + { + switch (lockedViewport) + { + case true: + return; + } + if (val < 0.0001) + { + val = 0.0001f; // avoid any chance of getting to zero. + } + zoomFactor = val; + changed = true; + } + + public float getZoomFactor() + { + return zoomFactor; + } + + public int getZoomStep() + { + return zoomStep; + } + + public void setZoomStep(int val) + { + zoomStep = val; + } + + public void lockVP(bool val) + { + if (val == lockedViewport) + { + return; + } + lockedViewport = val; + changed = true; + } + + public bool isLocked() + { + return lockedViewport; + } + + public float zoom() + { + return base_zoom * zoomFactor; + } + + public void updateColors(Color newColor) + { + pUpdateColors(newColor); + } + + private void pUpdateColors(Color newColor) + { + foreach (ovp_Poly t in polyList) + { + t.color = newColor; + } + foreach (ovp_Poly t in tessPolyList) + { + t.color = newColor; + } + changed = true; + } + + public void reset(bool clearBG = true) + { + pReset(clearBG); + } + + private void pReset(bool clearBG) + { + minX = 0; + maxX = 0; + minY = 0; + maxY = 0; + clear(clearBG); + drawnPoly.Clear(); + changed = true; + } + + public void clear(bool clearBG = true) + { + pClear(clearBG); + } + + private void pClear(bool clearBG) + { + polyList.Clear(); + polySourceIndex.Clear(); + polyMask.Clear(); + polyListPtCount.Clear(); + switch (clearBG) + { + case true: + bgPolyList.Clear(); + bgPolySourceIndex.Clear(); + bgPolyListPtCount.Clear(); + break; + } + lineList.Clear(); + lineSourceIndex.Clear(); + lineMask.Clear(); + lineListPtCount.Clear(); + tessPolyList.Clear(); + changed = true; + } + + public void addLine(PointF[] line, Color lineColor, float alpha, int layerIndex, bool mask = true) + { + pAddLine(line, lineColor, alpha, layerIndex, mask); + } + + private void pAddLine(PointF[] line, Color lineColor, float alpha, int layerIndex, bool mask) + { + lineList.Add(new ovp_Poly(line, lineColor, alpha)); + lineSourceIndex.Add(layerIndex); + lineListPtCount.Add((line.Length - 1) * 2); + lineMask.Add(true); + changed = true; + } + + public void addPolygon(PointF[] poly, Color polyColor, float alpha, bool drawn, int layerIndex, bool mask = true) + { + switch (drawn) + { + case true: + // Drawn polygons are to be treated as lines : they don't get filled. + addLine(poly, polyColor, alpha, layerIndex, mask); + break; + default: + pAddPolygon(poly, polyColor, alpha, drawn, layerIndex, mask); + break; + } + } + + private void pAddPolygon(PointF[] poly, Color polyColor, float alpha, bool drawn, int layerIndex, bool mask) + { + switch (drawn) + { + // avoid tessellation unless really necessary. + case false when enableFilledPolys: + try + { + //tessPoly(poly, polyColor, alpha); + } + catch (Exception) + { + + } + + break; + } + + PointF[] polys = closePoly(poly); + + polyList.Add(new ovp_Poly(poly, polyColor, alpha)); + polySourceIndex.Add(layerIndex); + polyListPtCount.Add(poly.Length); + polyMask.Add(mask); + drawnPoly.Add(drawn); + changed = true; + } + + public void addBGPolygon(PointF[] poly, Color polyColor, float alpha, int layerIndex) + { + pAddBGPolygon(poly, polyColor, alpha, layerIndex); + } + + private void pAddBGPolygon(PointF[] poly, Color polyColor, float alpha, int layerIndex) + { + bgPolyList.Add(new ovp_Poly(poly, polyColor, alpha)); + bgPolyListPtCount.Add(poly.Length); + bgPolySourceIndex.Add(layerIndex); + drawnPoly.Add(false); + changed = true; + } + + public OVPSettings(float defX = 0.0f, float defY = 0.0f) + { + init(defX, defY); + } + + private void init(float defX, float defY) + { + base_zoom = 1.0f; + minorGridColor = new Color(1.0f, 0.8f, 0.3f); + majorGridColor = new Color(0.2f, 0.8f, 0.3f); + axisColor = new Color(0.1f, 0.1f, 0.1f); + backColor = new Color(1.0f, 1.0f, 1.0f); + selectionColor = SystemColors.Highlight; + inverSelectionColor = SystemColors.Highlight; + allowZoomAndPan = true; + enableFilledPolys = false; + showPoints = true; + dynamicGrid = true; + panning = false; + selecting = false; + showGrid = true; + showAxes = true; + grid_spacing = 10; + antiAlias = true; + zoomStep = 1; + fullReset(defX, defY); + } + + public void fullReset(float defX = 0.0f, float defY = 0.0f) + { + pFullReset(defX, defY); + } + + private void pFullReset(float defX = 0.0f, float defY = 0.0f) + { + default_cameraPosition = new PointF(defX, defY); + bgPolyList = new List(); + bgPolySourceIndex = new List(); + bgPolyListPtCount = new List(); + polyList = new List(); + polySourceIndex = new List(); + polyMask = new List(); + polyListPtCount = new List(); + lineList = new List(); + lineSourceIndex = new List(); + lineMask = new List(); + lineListPtCount = new List(); + tessPolyList = new List(); + drawnPoly = new List(); + zoomFactor = 1.0f; + cameraPosition = new PointF(default_cameraPosition.X, default_cameraPosition.Y); + changed = true; + } + + private static PointF[] clockwiseOrder(PointF[] iPoints) + { + // Based on stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-clockwise-order + // Shoelace formula. + + double delta = 0; + + for (int pt = 0; pt < iPoints.Length; pt++) + { + double deltaX = 0; + double deltaY = 0; + if (pt == iPoints.Length - 1) + { + deltaX = iPoints[0].X - iPoints[pt].X; + deltaY = iPoints[0].Y + iPoints[pt].Y; + } + else + { + deltaX = iPoints[pt + 1].X - iPoints[pt].X; + deltaY = iPoints[pt + 1].Y + iPoints[pt].Y; + } + + delta += deltaX * deltaY; + } + + switch (delta) + { + case > 0: + // clockwise + break; + default: + // counter-clockwise. + Array.Reverse(iPoints); + break; + } + + return iPoints; + } + + /* + public static PointF[] convertToClosedPointF(PathD poly) + { + PointF[] tempPoly; + if (!(Math.Abs(poly[0].x - poly[^1].x) > double.Epsilon) || + !(Math.Abs(poly[0].y - poly[^1].y) > double.Epsilon)) + { + tempPoly = new PointF[poly.Count]; + for (int pt = 0; pt < poly.Count; pt++) + { + tempPoly[pt] = new PointF((float)poly[pt].x, (float)poly[pt].y); + } + } + else + { + tempPoly = new PointF[poly.Count + 1]; + for (int pt = 0; pt < poly.Count; pt++) + { + tempPoly[pt] = new PointF((float)poly[pt].x, (float)poly[pt].y); + } + tempPoly[^1] = new PointF(tempPoly[0].X, tempPoly[0].Y); + } + + return tempPoly; + } + */ + + public static PointF[] closePoly(PointF[] poly) + { + if (!(Math.Abs(poly[0].X - poly[^1].X) > double.Epsilon) || + !(Math.Abs(poly[0].Y - poly[^1].Y) > double.Epsilon)) + { + return poly; + } + + PointF[] tempPoly = new PointF[poly.Length + 1]; + for (int pt = 0; pt < poly.Length; pt++) + { + tempPoly[pt] = new PointF(poly[pt].X, poly[pt].Y); + } + tempPoly[^1] = new PointF(tempPoly[0].X, tempPoly[0].Y); + return tempPoly; + } + + /* + private void tessPoly(PointF[] source, Color polyColor, float alpha) + { + Tess tess = new(); + + ContourVertex[] contour = new ContourVertex[source.Length]; + for (int pt = 0; pt < contour.Length; pt++) + { + contour[pt].Position = new Vec3 { X = source[pt].X, Y = source[pt].Y, Z = 0 }; + } + tess.AddContour(contour, ContourOrientation.Clockwise); // keep our orientation to allow holes to be handled. + + // Triangulate. + tess.Tessellate(WindingRule.NonZero); // We don't have any hole polygons here. + + // Iterate triangles and create output geometry + for (int i = 0; i < tess.ElementCount; i++) + { + PointF[] tempPoly = new PointF[3]; // 3 points. + tempPoly[0] = new PointF((float)tess.Vertices[tess.Elements[i * 3]].Position.X, (float)tess.Vertices[tess.Elements[i * 3]].Position.Y); + tempPoly[1] = new PointF((float)tess.Vertices[tess.Elements[i * 3 + 1]].Position.X, (float)tess.Vertices[tess.Elements[i * 3 + 1]].Position.Y); + tempPoly[2] = new PointF((float)tess.Vertices[tess.Elements[i * 3 + 2]].Position.X, (float)tess.Vertices[tess.Elements[i * 3 + 2]].Position.Y); + + tessPolyList.Add(new ovp_Poly(clockwiseOrder(tempPoly).ToArray(), polyColor, alpha)); + } + } + */ +} diff --git a/src/Eto.VeldridSurface/VeldridDriver.cs b/src/Eto.VeldridSurface/VeldridDriver.cs index 75f7829..3b34eb2 100644 --- a/src/Eto.VeldridSurface/VeldridDriver.cs +++ b/src/Eto.VeldridSurface/VeldridDriver.cs @@ -6,6 +6,7 @@ using System.Runtime.InteropServices; using Veldrid; using Veldrid.SPIRV; +using VeldridEto; namespace TestEtoVeldrid2 { @@ -13,10 +14,10 @@ public struct VertexPositionColor { public static uint SizeInBytes = (uint)Marshal.SizeOf(typeof(VertexPositionColor)); - public Vector2 Position; + public Vector3 Position; public RgbaFloat Color; - public VertexPositionColor(Vector2 position, RgbaFloat color) + public VertexPositionColor(Vector3 position, RgbaFloat color) { Position = position; Color = color; @@ -33,6 +34,8 @@ public VertexPositionColor(Vector2 position, RgbaFloat color) /// public class VeldridDriver { + public OVPSettings ovpSettings; + private VeldridSurface _surface; public VeldridSurface Surface { @@ -41,41 +44,43 @@ public VeldridSurface Surface { _surface = value; - Surface.MouseDown += Surface_MouseDown; - Surface.KeyDown += Surface_KeyDown; - Surface.MouseWheel += Surface_MouseWheel; - Surface.Draw += (sender, e) => Draw(); } } - private void Surface_KeyDown(object sender, KeyEventArgs e) - { - if (e.Key == Keys.C) - { - Clockwise = !Clockwise; - e.Handled = true; - } - } - - private void Surface_MouseDown(object sender, MouseEventArgs e) - { - if (e.Buttons == MouseButtons.Primary) - { - Animate = !Animate; - e.Handled = true; - } - } - - private void Surface_MouseWheel(object sender, MouseEventArgs e) - { - Speed += (int)e.Delta.Height; - } + private uint[] polyFirst; + private uint[] polyVertexCount; + private uint[] tessFirst; + private uint[] tessVertexCount; + private uint[] lineFirst; + private uint[] lineVertexCount; + private uint[] pointsFirst; + private uint[] gridIndices; + private uint[] axesIndices; + + private float axisZ; + private float gridZ; + + private DeviceBuffer GridVertexBuffer; + private DeviceBuffer GridIndexBuffer; + private DeviceBuffer AxesVertexBuffer; + private DeviceBuffer AxesIndexBuffer; + + private DeviceBuffer LinesVertexBuffer; + private DeviceBuffer PointsVertexBuffer; + private DeviceBuffer PolysVertexBuffer; + private DeviceBuffer TessVertexBuffer; + + private Pipeline PointsPipeline; + private Pipeline LinePipeline; + private Pipeline LinesPipeline; + private Pipeline FilledPipeline; public UITimer Clock { get; } = new UITimer(); public CommandList CommandList { get; private set; } public DeviceBuffer VertexBuffer { get; private set; } + public DeviceBuffer IndexBuffer { get; private set; } public Shader VertexShader { get; private set; } public Shader FragmentShader { get; private set; } @@ -85,6 +90,10 @@ private void Surface_MouseWheel(object sender, MouseEventArgs e) public DeviceBuffer ModelBuffer { get; private set; } public ResourceSet ModelMatrixSet { get; private set; } + private Matrix4x4 ViewMatrix; + private DeviceBuffer ViewBuffer; + private ResourceSet ViewMatrixSet; + public bool Animate { get; set; } = true; private int _direction = 1; @@ -98,8 +107,10 @@ public bool Clockwise private bool Ready = false; - public VeldridDriver() + public VeldridDriver(ref OVPSettings settings, ref VeldridSurface surface) { + ovpSettings = settings; + Surface = surface; Clock.Interval = 1.0f / 60.0f; Clock.Elapsed += Clock_Elapsed; } @@ -109,6 +120,26 @@ public VeldridDriver() private DateTime CurrentTime; private DateTime PreviousTime = DateTime.Now; + private void drawAxes() + { + if (!ovpSettings.drawAxes()) + { + return; + } + + float zoom = ovpSettings.getBaseZoom() * ovpSettings.getZoomFactor(); + VertexPositionColor[] axesArray = new VertexPositionColor[4]; + axesArray[0] = new VertexPositionColor(new Vector3(0.0f, ovpSettings.getCameraY() + Surface.RenderHeight * zoom, axisZ), new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); + axesArray[1] = new VertexPositionColor(new Vector3(0.0f, ovpSettings.getCameraY() - Surface.RenderHeight * zoom, axisZ), new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); + axesArray[2] = new VertexPositionColor(new Vector3(ovpSettings.getCameraX() + Surface.RenderWidth * zoom, 0.0f, axisZ), new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); + axesArray[3] = new VertexPositionColor(new Vector3(ovpSettings.getCameraX() - Surface.RenderWidth * zoom, 0.0f, axisZ), new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); + + axesIndices = new uint[4] { 0, 1, 2, 3 }; + + updateBuffer(ref AxesVertexBuffer, axesArray, VertexPositionColor.SizeInBytes, BufferUsage.VertexBuffer); + updateBuffer(ref AxesIndexBuffer, axesIndices, sizeof(uint), BufferUsage.IndexBuffer); + } + public void Draw() { if (!Ready) @@ -118,20 +149,20 @@ public void Draw() CommandList.Begin(); - CurrentTime = DateTime.Now; - if (Animate) - { - double radians = Convert.ToDouble((CurrentTime - PreviousTime).TotalMilliseconds / 10.0); - float degrees = Convert.ToSingle(radians * (System.Math.PI / 180.0)); - degrees *= Speed; - - ModelMatrix *= Matrix4x4.CreateFromAxisAngle( - new Vector3(0, 0, _direction), - degrees); - } - PreviousTime = CurrentTime; + ModelMatrix *= Matrix4x4.CreateFromAxisAngle( + new Vector3(0, 0, 1), 0); CommandList.UpdateBuffer(ModelBuffer, 0, ModelMatrix); + float zoom = ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom(); + + float left = ovpSettings.getCameraX() - (float)Surface.RenderWidth / 2 * zoom; + float right = ovpSettings.getCameraX() + (float)Surface.RenderWidth / 2 * zoom; + float bottom = ovpSettings.getCameraY() + (float)Surface.RenderHeight / 2 * zoom; + float top = ovpSettings.getCameraY() - (float)Surface.RenderHeight / 2 * zoom; + + ViewMatrix = Matrix4x4.CreateOrthographicOffCenter(left, right, bottom, top, 0.0f, 1.0f); + CommandList.UpdateBuffer(ViewBuffer, 0, ViewMatrix); + CommandList.SetFramebuffer(Surface.Swapchain.Framebuffer); // These commands differ from the stock Veldrid "Getting Started" @@ -141,25 +172,81 @@ public void Draw() // said context. Second, this project creates its swapchain with a // depth buffer, and that buffer needs to be reset at the start of // each frame. - CommandList.ClearColorTarget(0, RgbaFloat.Pink); + + RgbaFloat bgColor = new(ovpSettings.backColor.R, ovpSettings.backColor.G, ovpSettings.backColor.B, 1.0f); + + CommandList.ClearColorTarget(0, bgColor); CommandList.ClearDepthStencil(1.0f); - CommandList.SetVertexBuffer(0, VertexBuffer); - CommandList.SetIndexBuffer(IndexBuffer, IndexFormat.UInt16); - CommandList.SetPipeline(Pipeline); - CommandList.SetGraphicsResourceSet(0, ModelMatrixSet); + if (GridVertexBuffer != null) + { + lock (GridVertexBuffer) + { + try + { + CommandList.SetVertexBuffer(0, GridVertexBuffer); + CommandList.SetIndexBuffer(GridIndexBuffer, IndexFormat.UInt32); + CommandList.SetPipeline(LinePipeline); + CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); + CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); + + CommandList.DrawIndexed( + indexCount: (uint)gridIndices.Length, + instanceCount: 1, + indexStart: 0, + vertexOffset: 0, + instanceStart: 0); + } + catch (Exception ex) + { + Console.WriteLine("Ex: " + ex); + } + } + } - CommandList.DrawIndexed( - indexCount: 4, - instanceCount: 1, - indexStart: 0, - vertexOffset: 0, - instanceStart: 0); + drawAxes(); + if (AxesVertexBuffer != null) + { + lock (AxesVertexBuffer) + { + try + { + CommandList.SetVertexBuffer(0, AxesVertexBuffer); + CommandList.SetIndexBuffer(AxesIndexBuffer, IndexFormat.UInt32); + CommandList.SetPipeline(LinePipeline); + CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); + CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); + + CommandList.DrawIndexed( + indexCount: (uint)axesIndices.Length, + instanceCount: 1, + indexStart: 0, + vertexOffset: 0, + instanceStart: 0); + } + catch (Exception ex) + { + Console.WriteLine("Ex: " + ex); + } + } + } CommandList.End(); - Surface.GraphicsDevice.SubmitCommands(CommandList); - Surface.GraphicsDevice.SwapBuffers(Surface.Swapchain); + try + { + lock (CommandList) + { + Surface.GraphicsDevice.SubmitCommands(CommandList); + } + + Surface.GraphicsDevice.SwapBuffers(Surface.Swapchain); + } + catch (Exception ex) + { + Console.WriteLine("Ex: " + ex); + } + } public void SetUpVeldrid() @@ -215,6 +302,19 @@ private void CreateResources() ResourceFactory factory = Surface.GraphicsDevice.ResourceFactory; + ResourceLayout viewMatrixLayout = factory.CreateResourceLayout( + new ResourceLayoutDescription( + new ResourceLayoutElementDescription( + "ViewMatrix", + ResourceKind.UniformBuffer, + ShaderStages.Vertex))); + + ViewBuffer = factory.CreateBuffer( + new BufferDescription(64, BufferUsage.UniformBuffer)); + + ViewMatrixSet = factory.CreateResourceSet(new ResourceSetDescription( + viewMatrixLayout, ViewBuffer)); + var vertex = new ShaderDescription(ShaderStages.Vertex, vertexShaderSpirvBytes, "main", true); var fragment = new ShaderDescription(ShaderStages.Fragment, fragmentShaderSpirvBytes, "main", true); Shader[] shaders = factory.CreateFromSpirv(vertex, fragment, options); @@ -234,10 +334,10 @@ private void CreateResources() VertexPositionColor[] quadVertices = { - new VertexPositionColor(new Vector2(-.75f, -.75f), RgbaFloat.Red), - new VertexPositionColor(new Vector2(.75f, -.75f), RgbaFloat.Green), - new VertexPositionColor(new Vector2(-.75f, .75f), RgbaFloat.Blue), - new VertexPositionColor(new Vector2(.75f, .75f), RgbaFloat.Yellow) + new VertexPositionColor(new Vector3(new Vector2(-.75f, -.75f), 0), RgbaFloat.Red), + new VertexPositionColor(new Vector3(new Vector2(.75f, -.75f), 0), RgbaFloat.Green), + new VertexPositionColor(new Vector3(new Vector2(-.75f, .75f), 0), RgbaFloat.Blue), + new VertexPositionColor(new Vector3(new Vector2(.75f, .75f), 0), RgbaFloat.Yellow) }; ushort[] quadIndices = { 0, 1, 2, 3 }; @@ -279,9 +379,50 @@ private void CreateResources() Outputs = Surface.Swapchain.Framebuffer.OutputDescription }); + + LinePipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription + { + BlendState = BlendStateDescription.SingleOverrideBlend, + DepthStencilState = new DepthStencilStateDescription( + depthTestEnabled: true, + depthWriteEnabled: true, + comparisonKind: ComparisonKind.LessEqual), + RasterizerState = new RasterizerStateDescription( + cullMode: FaceCullMode.Back, + fillMode: PolygonFillMode.Solid, + frontFace: FrontFace.Clockwise, + depthClipEnabled: true, + scissorTestEnabled: false), + PrimitiveTopology = PrimitiveTopology.LineList, + ResourceLayouts = new[] { viewMatrixLayout, modelMatrixLayout }, + ShaderSet = new ShaderSetDescription( + vertexLayouts: new[] { vertexLayout }, + shaders: shaders), + Outputs = Surface.Swapchain.Framebuffer.OutputDescription + }); + CommandList = factory.CreateCommandList(); } + public void updateBuffer(ref DeviceBuffer buffer, T[] data, uint elementSize, BufferUsage usage) + where T : unmanaged + { + switch (data.Length) + { + case > 0: + { + buffer?.Dispose(); + + ResourceFactory factory = Surface.GraphicsDevice.ResourceFactory; + + buffer = factory.CreateBuffer(new BufferDescription(elementSize * (uint)data.Length, usage)); + + Surface.GraphicsDevice.UpdateBuffer(buffer, 0, data); + break; + } + } + } + private byte[] LoadSpirvBytes(ShaderStages stage) { string name = $"VertexColor-{stage.ToString().ToLowerInvariant()}.450.glsl"; diff --git a/src/Eto.VeldridSurface/ovp_Poly.cs b/src/Eto.VeldridSurface/ovp_Poly.cs new file mode 100644 index 0000000..589e55f --- /dev/null +++ b/src/Eto.VeldridSurface/ovp_Poly.cs @@ -0,0 +1,24 @@ +using Eto.Drawing; + +namespace VeldridEto; + +public class ovp_Poly +{ + public PointF[] poly { get; set; } + public Color color { get; set; } + public float alpha { get; set; } + + public ovp_Poly(PointF[] geometry, Color geoColor) + { + poly = geometry; + color = geoColor; + alpha = 1.0f; + } + + public ovp_Poly(PointF[] geometry, Color geoColor, float alpha_) + { + poly = geometry; + color = geoColor; + alpha = alpha_; + } +} \ No newline at end of file diff --git a/test/TestEtoVeldrid/MainForm.cs b/test/TestEtoVeldrid/MainForm.cs index 898acaa..b5e5eb0 100644 --- a/test/TestEtoVeldrid/MainForm.cs +++ b/test/TestEtoVeldrid/MainForm.cs @@ -2,6 +2,7 @@ using Eto.Veldrid; using TestEtoVeldrid2; using Veldrid; +using VeldridEto; namespace TestEtoVeldrid { @@ -63,10 +64,9 @@ public MainForm(GraphicsBackend backend) Content = Surface; - Driver = new VeldridDriver - { - Surface = Surface - }; + OVPSettings settings = new OVPSettings(); + + Driver = new VeldridDriver(ref settings, ref Surface); Surface.VeldridInitialized += (sender, e) => { From fe52d813804ff453fc49c6ab3bb0b09fc72710a9 Mon Sep 17 00:00:00 2001 From: philstopford Date: Thu, 15 Feb 2024 21:55:17 -0600 Subject: [PATCH 09/24] weird.... --- src/Eto.VeldridSurface/VeldridDriver.cs | 204 +++++++++++++++++++++++- 1 file changed, 202 insertions(+), 2 deletions(-) diff --git a/src/Eto.VeldridSurface/VeldridDriver.cs b/src/Eto.VeldridSurface/VeldridDriver.cs index 3b34eb2..38d9638 100644 --- a/src/Eto.VeldridSurface/VeldridDriver.cs +++ b/src/Eto.VeldridSurface/VeldridDriver.cs @@ -1,4 +1,5 @@ -using Eto.Forms; +using Eto.Drawing; +using Eto.Forms; using Eto.Veldrid; using System; using System.IO; @@ -115,11 +116,209 @@ public VeldridDriver(ref OVPSettings settings, ref VeldridSurface surface) Clock.Elapsed += Clock_Elapsed; } - private void Clock_Elapsed(object sender, EventArgs e) => Surface.Invalidate(); + private void Clock_Elapsed(object sender, EventArgs e) + { + drawAxes(); + drawGrid(); + // Draw(); + Surface.Invalidate(); + } private DateTime CurrentTime; private DateTime PreviousTime = DateTime.Now; + private Point WorldToScreen(float x, float y) + { + // int oX = (int)((x - ovpSettings.getCameraX() / (ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom())) + Surface.RenderWidth / 2); + + double oX_2 = (double)Surface.RenderWidth / 2; + double oX_3 = ovpSettings.getCameraX() / (ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom()); + double oX_4 = x; + + int oXC = (int)(oX_4 - oX_3 + oX_2); + + // int oY = (int)((y - ovpSettings.getCameraY() / (ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom())) + Surface.RenderHeight / 2); + + double oY_2 = (double)Surface.RenderHeight / 2; + double oY_3 = ovpSettings.getCameraY() / (ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom()); + double oY_4 = y; + + int oYC = (int)(oY_4 - oY_3 + oY_2); + + return new Point(oXC, oYC); + } + + private Size WorldToScreen(SizeF pt) + { + Point pt1 = WorldToScreen(0, 0); + Point pt2 = WorldToScreen(pt.Width, pt.Height); + return new Size(pt2.X - pt1.X, pt2.Y - pt1.Y); + } + private void drawGrid() + { + if (!ovpSettings.drawGrid()) + { + return; + } + + float spacing = ovpSettings.gridSpacing(); + if (ovpSettings.isGridDynamic()) + { + while (WorldToScreen(new SizeF(spacing, 0.0f)).Width > 12.0f) + { + spacing /= 10.0f; + } + + while (WorldToScreen(new SizeF(spacing, 0.0f)).Width < 4.0f) + { + spacing *= 10.0f; + } + } + + float zoom = ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom(); + float x = ovpSettings.getCameraX(); + float y = ovpSettings.getCameraY(); + + List grid = new(); + + if (WorldToScreen(new SizeF(spacing, 0.0f)).Width >= 4.0f) + { + int k = 0; + for (float i = 0; i > -(Surface.RenderWidth * zoom) + x; i -= spacing) + { + float r = 0.0f; + float g = 0.0f; + float b = 0.0f; + switch (k) + { + case <= 9: + r = ovpSettings.minorGridColor.R; + g = ovpSettings.minorGridColor.G; + b = ovpSettings.minorGridColor.B; + break; + case 10: + r = ovpSettings.majorGridColor.R; + g = ovpSettings.majorGridColor.G; + b = ovpSettings.majorGridColor.B; + k = 0; + break; + } + + k++; + grid.Add(new VertexPositionColor(new Vector3(i, y + zoom * Surface.RenderHeight, gridZ), + new RgbaFloat(r, g, b, 1.0f))); + grid.Add(new VertexPositionColor(new Vector3(i, y + zoom * -Surface.RenderHeight, gridZ), + new RgbaFloat(r, g, b, 1.0f))); + } + + k = 0; + for (float i = 0; i < Surface.RenderWidth * zoom + x; i += spacing) + { + float r = 0.0f; + float g = 0.0f; + float b = 0.0f; + switch (k) + { + case <= 9: + r = ovpSettings.minorGridColor.R; + g = ovpSettings.minorGridColor.G; + b = ovpSettings.minorGridColor.B; + break; + case 10: + r = ovpSettings.majorGridColor.R; + g = ovpSettings.majorGridColor.G; + b = ovpSettings.majorGridColor.B; + k = 0; + break; + } + + k++; + grid.Add(new VertexPositionColor(new Vector3(i, y + zoom * Surface.RenderHeight, gridZ), + new RgbaFloat(r, g, b, 1.0f))); + grid.Add(new VertexPositionColor(new Vector3(i, y + zoom * -Surface.RenderHeight, gridZ), + new RgbaFloat(r, g, b, 1.0f))); + } + + k = 0; + for (float i = 0; i > -(Surface.RenderHeight * zoom) + y; i -= spacing) + { + float r = 0.0f; + float g = 0.0f; + float b = 0.0f; + switch (k) + { + case <= 9: + r = ovpSettings.minorGridColor.R; + g = ovpSettings.minorGridColor.G; + b = ovpSettings.minorGridColor.B; + break; + case 10: + r = ovpSettings.majorGridColor.R; + g = ovpSettings.majorGridColor.G; + b = ovpSettings.majorGridColor.B; + k = 0; + break; + } + + k++; + grid.Add(new VertexPositionColor(new Vector3(x + zoom * Surface.RenderWidth, i, gridZ), + new RgbaFloat(r, g, b, 1.0f))); + grid.Add(new VertexPositionColor(new Vector3(x + zoom * -Surface.RenderWidth, i, gridZ), + new RgbaFloat(r, g, b, 1.0f))); + } + + k = 0; + for (float i = 0; i < Surface.RenderHeight * zoom + y; i += spacing) + { + float r = 0.0f; + float g = 0.0f; + float b = 0.0f; + switch (k) + { + case <= 9: + r = ovpSettings.minorGridColor.R; + g = ovpSettings.minorGridColor.G; + b = ovpSettings.minorGridColor.B; + break; + case 10: + r = ovpSettings.majorGridColor.R; + g = ovpSettings.majorGridColor.G; + b = ovpSettings.majorGridColor.B; + k = 0; + break; + } + + k++; + grid.Add(new VertexPositionColor(new Vector3(x + zoom * Surface.RenderWidth, i, gridZ), + new RgbaFloat(r, g, b, 1.0f))); + grid.Add(new VertexPositionColor(new Vector3(x + zoom * -Surface.RenderWidth, i, gridZ), + new RgbaFloat(r, g, b, 1.0f))); + } + } + + uint gridCount = (uint)grid.Count; + + switch (gridCount) + { + case > 0: + { + gridIndices = new uint[gridCount]; + for (uint i = 0; i < gridIndices.Length; i++) + { + gridIndices[i] = i; + } + + updateBuffer(ref GridVertexBuffer, grid.ToArray(), VertexPositionColor.SizeInBytes, BufferUsage.VertexBuffer); + updateBuffer(ref GridIndexBuffer, gridIndices, sizeof(uint), BufferUsage.IndexBuffer); + break; + } + default: + GridVertexBuffer = null; + GridIndexBuffer = null; + break; + } + } + private void drawAxes() { if (!ovpSettings.drawAxes()) @@ -178,6 +377,7 @@ public void Draw() CommandList.ClearColorTarget(0, bgColor); CommandList.ClearDepthStencil(1.0f); + drawGrid(); if (GridVertexBuffer != null) { lock (GridVertexBuffer) From 226fb8204ae80b22b0863d6f5a520e28d1417e12 Mon Sep 17 00:00:00 2001 From: Phil Stopford Date: Fri, 16 Feb 2024 07:05:46 -0600 Subject: [PATCH 10/24] Another step, but in which direction? --- .../shaders/VertexColor-vertex.450.glsl | 11 ++++++++--- test/TestEtoVeldrid/MainForm.cs | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Eto.VeldridSurface/shaders/VertexColor-vertex.450.glsl b/src/Eto.VeldridSurface/shaders/VertexColor-vertex.450.glsl index 8362363..58a508c 100644 --- a/src/Eto.VeldridSurface/shaders/VertexColor-vertex.450.glsl +++ b/src/Eto.VeldridSurface/shaders/VertexColor-vertex.450.glsl @@ -1,18 +1,23 @@ #version 450 -layout (location = 0) in vec2 Position; +layout (location = 0) in vec3 Position; layout (location = 1) in vec4 Color; layout (location = 0) out vec4 fsin_Color; -layout (set = 0, binding = 0) uniform ModelMatrix +layout (set = 0, binding = 0) uniform ViewMatrix +{ + mat4 view; +}; + +layout (set = 1, binding = 0) uniform ModelMatrix { mat4 model; }; void main() { - gl_Position = model * vec4(Position, 0, 1); + gl_Position = model * view * vec4(Position, 1); fsin_Color = Color; } diff --git a/test/TestEtoVeldrid/MainForm.cs b/test/TestEtoVeldrid/MainForm.cs index b5e5eb0..88feb5e 100644 --- a/test/TestEtoVeldrid/MainForm.cs +++ b/test/TestEtoVeldrid/MainForm.cs @@ -76,8 +76,8 @@ public MainForm(GraphicsBackend backend) }; // TODO: Make this binding actually work both ways. - CmdAnimate.Bind("Checked", Driver, "Animate"); - CmdClockwise.Bind("Checked", Driver, "Clockwise"); + //CmdAnimate.Bind("Checked", Driver, "Animate"); + //CmdClockwise.Bind("Checked", Driver, "Clockwise"); } private void SetUpVeldrid() From 9c364d9ccce4a33393ebe581c2131f30c4595910 Mon Sep 17 00:00:00 2001 From: Phil Stopford Date: Fri, 16 Feb 2024 07:14:00 -0600 Subject: [PATCH 11/24] Update VeldridDriver.cs --- src/Eto.VeldridSurface/VeldridDriver.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Eto.VeldridSurface/VeldridDriver.cs b/src/Eto.VeldridSurface/VeldridDriver.cs index 38d9638..92088e0 100644 --- a/src/Eto.VeldridSurface/VeldridDriver.cs +++ b/src/Eto.VeldridSurface/VeldridDriver.cs @@ -532,22 +532,9 @@ private void CreateResources() ModelMatrixSet = factory.CreateResourceSet(new ResourceSetDescription( modelMatrixLayout, ModelBuffer)); - VertexPositionColor[] quadVertices = - { - new VertexPositionColor(new Vector3(new Vector2(-.75f, -.75f), 0), RgbaFloat.Red), - new VertexPositionColor(new Vector3(new Vector2(.75f, -.75f), 0), RgbaFloat.Green), - new VertexPositionColor(new Vector3(new Vector2(-.75f, .75f), 0), RgbaFloat.Blue), - new VertexPositionColor(new Vector3(new Vector2(.75f, .75f), 0), RgbaFloat.Yellow) - }; - - ushort[] quadIndices = { 0, 1, 2, 3 }; - VertexBuffer = factory.CreateBuffer(new BufferDescription(4 * VertexPositionColor.SizeInBytes, BufferUsage.VertexBuffer)); IndexBuffer = factory.CreateBuffer(new BufferDescription(4 * sizeof(ushort), BufferUsage.IndexBuffer)); - Surface.GraphicsDevice.UpdateBuffer(VertexBuffer, 0, quadVertices); - Surface.GraphicsDevice.UpdateBuffer(IndexBuffer, 0, quadIndices); - // Veldrid.SPIRV, when cross-compiling to HLSL, will always produce // TEXCOORD semantics; VertexElementSemantic.TextureCoordinate thus // becomes necessary to let D3D11 work alongside Vulkan and OpenGL. From 143eaccb2a6f36e6e657deb39f42e583a999ba6c Mon Sep 17 00:00:00 2001 From: Phil Stopford Date: Fri, 16 Feb 2024 07:26:03 -0600 Subject: [PATCH 12/24] Update VeldridDriver.cs --- src/Eto.VeldridSurface/VeldridDriver.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Eto.VeldridSurface/VeldridDriver.cs b/src/Eto.VeldridSurface/VeldridDriver.cs index 92088e0..73f043d 100644 --- a/src/Eto.VeldridSurface/VeldridDriver.cs +++ b/src/Eto.VeldridSurface/VeldridDriver.cs @@ -118,8 +118,8 @@ public VeldridDriver(ref OVPSettings settings, ref VeldridSurface surface) private void Clock_Elapsed(object sender, EventArgs e) { - drawAxes(); - drawGrid(); + // drawAxes(); + // drawGrid(); // Draw(); Surface.Invalidate(); } From f2f4ea25b0ab94d53c6301abecb5bbb4a97b8711 Mon Sep 17 00:00:00 2001 From: philstopford Date: Sat, 17 Feb 2024 15:48:45 -0600 Subject: [PATCH 13/24] Update VeldridDriver.cs --- src/Eto.VeldridSurface/VeldridDriver.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Eto.VeldridSurface/VeldridDriver.cs b/src/Eto.VeldridSurface/VeldridDriver.cs index 73f043d..d4486d9 100644 --- a/src/Eto.VeldridSurface/VeldridDriver.cs +++ b/src/Eto.VeldridSurface/VeldridDriver.cs @@ -542,7 +542,7 @@ private void CreateResources() // https://github.com/mellinoe/veldrid/issues/121 // var vertexLayout = new VertexLayoutDescription( - new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2), + new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3), new VertexElementDescription("Color", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float4)); Pipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription From 49dbbb4b2618002d102ef7e5a23d9260bfa601eb Mon Sep 17 00:00:00 2001 From: philstopford Date: Mon, 19 Feb 2024 09:58:00 -0600 Subject: [PATCH 14/24] Adding back demo functionality. Key handling seems to be MIA at the moment, and polygons are not yet drawn. WIP. --- src/Eto.VeldridSurface/VeldridDriver.cs | 1005 ++++++++++++++++++++++- test/TestEtoVeldrid/MainForm.cs | 287 ++++++- 2 files changed, 1257 insertions(+), 35 deletions(-) diff --git a/src/Eto.VeldridSurface/VeldridDriver.cs b/src/Eto.VeldridSurface/VeldridDriver.cs index d4486d9..df827b1 100644 --- a/src/Eto.VeldridSurface/VeldridDriver.cs +++ b/src/Eto.VeldridSurface/VeldridDriver.cs @@ -1,4 +1,5 @@ -using Eto.Drawing; +using Eto; +using Eto.Drawing; using Eto.Forms; using Eto.Veldrid; using System; @@ -38,6 +39,7 @@ public class VeldridDriver public OVPSettings ovpSettings; private VeldridSurface _surface; + public VeldridSurface Surface { get { return _surface; } @@ -49,6 +51,14 @@ public VeldridSurface Surface } } + public delegate void updateHost(); + + public updateHost updateHostFunc { get; set; } + + public delegate void updateHostSelection(int index); + + public updateHostSelection updateHostSelectionFunc { get; set; } + private uint[] polyFirst; private uint[] polyVertexCount; private uint[] tessFirst; @@ -67,57 +77,104 @@ public VeldridSurface Surface private DeviceBuffer AxesVertexBuffer; private DeviceBuffer AxesIndexBuffer; + public DeviceBuffer VertexBuffer { get; private set; } + public DeviceBuffer IndexBuffer { get; private set; } + public DeviceBuffer ModelBuffer { get; private set; } + + private DeviceBuffer ViewBuffer; + private DeviceBuffer LinesVertexBuffer; private DeviceBuffer PointsVertexBuffer; private DeviceBuffer PolysVertexBuffer; private DeviceBuffer TessVertexBuffer; + public Pipeline Pipeline { get; private set; } private Pipeline PointsPipeline; private Pipeline LinePipeline; private Pipeline LinesPipeline; private Pipeline FilledPipeline; - public UITimer Clock { get; } = new UITimer(); - - public CommandList CommandList { get; private set; } - public DeviceBuffer VertexBuffer { get; private set; } - - public DeviceBuffer IndexBuffer { get; private set; } - public Shader VertexShader { get; private set; } - public Shader FragmentShader { get; private set; } - public Pipeline Pipeline { get; private set; } - public Matrix4x4 ModelMatrix { get; private set; } = Matrix4x4.Identity; - public DeviceBuffer ModelBuffer { get; private set; } + private Matrix4x4 ViewMatrix; public ResourceSet ModelMatrixSet { get; private set; } - private Matrix4x4 ViewMatrix; - private DeviceBuffer ViewBuffer; private ResourceSet ViewMatrixSet; - public bool Animate { get; set; } = true; + public UITimer Clock { get; } = new UITimer(); - private int _direction = 1; - public bool Clockwise - { - get { return _direction == 1 ? true : false; } - set { _direction = value ? 1 : -1; } - } + public CommandList CommandList { get; private set; } - public int Speed { get; set; } = 1; + public Shader VertexShader { get; private set; } + public Shader FragmentShader { get; private set; } private bool Ready = false; + public bool savedLocation_valid { get; set; } + private PointF savedLocation; + + private const float pointWidth = 0.50f; + private bool hasFocus; + private bool keyHandlerApplied; + + // Use for drag handling. + public bool dragging { get; set; } + private float x_orig; + private float y_orig; public VeldridDriver(ref OVPSettings settings, ref VeldridSurface surface) { ovpSettings = settings; Surface = surface; + + try + { + Surface.MouseDown += downHandler; + Surface.MouseMove += dragHandler; + Surface.MouseUp += upHandler; + Surface.MouseWheel += zoomHandler; + Surface.GotFocus += addKeyHandler; + Surface.MouseEnter += setFocus; + Surface.LostFocus += removeKeyHandler; + } + catch (Exception ex) + { + int x = 2; + } + Clock.Interval = 1.0f / 60.0f; Clock.Elapsed += Clock_Elapsed; } + public void setFocus(object sender, EventArgs e) + { + switch (hasFocus) + { + case true: + return; + default: + Surface.Focus(); + hasFocus = true; + break; + } + } + + public void updateViewport() + { + if ((!ovpSettings.changed) || (Surface.GraphicsDevice == null) || + (!Surface.Visible) || (Surface.Width <= 0) || (Surface.Height <= 0)) + { + return; + } + + updateHostFunc?.Invoke(); + Surface.Invalidate(); + } + private void Clock_Elapsed(object sender, EventArgs e) { + if (!ovpSettings.changed) + { + return; + } // drawAxes(); // drawGrid(); // Draw(); @@ -127,6 +184,151 @@ private void Clock_Elapsed(object sender, EventArgs e) private DateTime CurrentTime; private DateTime PreviousTime = DateTime.Now; + private ContextMenu menu; + + public void setContextMenu(ref ContextMenu menu_) + { + menu = menu_; + } + + public void changeSettingsRef(ref OVPSettings newSettings) + { + ovpSettings = newSettings; + updateViewport(); + } + + private void downHandler(object sender, MouseEventArgs e) + { + switch (e.Buttons) + { + case MouseButtons.Primary: + setDown(e.Location.X, e.Location.Y); + break; + } + + if (e.Buttons == MouseButtons.Middle || e.Modifiers == Keys.Control && e.Buttons == MouseButtons.Primary) + { + selectByClick(e.Location.X, e.Location.Y); + } + + e.Handled = true; + } + + private void setDown(float x, float y) + { + switch (dragging) + { + // might not be needed, but seemed like a safe approach to avoid re-setting these in a drag event. + case false when !ovpSettings.isLocked(): + x_orig = x; + y_orig = y; + dragging = true; + break; + } + } + + public void saveLocation() + { + savedLocation = new PointF(ovpSettings.getCameraX(), ovpSettings.getCameraY()); + savedLocation_valid = true; + } + + public void zoomExtents(int index) + { + getExtents(index); + + if (ovpSettings.polyList.Count == 0 && ovpSettings.lineList.Count == 0 || + ovpSettings.minX == 0 && ovpSettings.maxX == 0 || + ovpSettings.minY == 0 && ovpSettings.maxY == 0) + { + reset(); + return; + } + + // Locate camera at center of the polygon field. + float dX = ovpSettings.maxX - ovpSettings.minX; + float dY = ovpSettings.maxY - ovpSettings.minY; + float cX = dX / 2.0f + ovpSettings.minX; + float cY = dY / 2.0f + ovpSettings.minY; + + // Now need to get the zoom level organized. + float zoomLevel_x = dX / Surface.Width; + float zoomLevel_y = dY / Surface.Height; + + if (zoomLevel_x > zoomLevel_y) + { + ovpSettings.setZoomFactor(zoomLevel_x / ovpSettings.getBaseZoom()); + } + else + { + ovpSettings.setZoomFactor(zoomLevel_y / ovpSettings.getBaseZoom()); + } + + goToLocation(cX, cY); + } + + public void loadLocation() + { + switch (savedLocation_valid) + { + case true: + ovpSettings.setCameraPos(savedLocation.X, savedLocation.Y); + updateViewport(); + break; + } + } + + public void goToLocation(float x, float y) + { + ovpSettings.setCameraPos(x, y); + updateViewport(); + } + + private void dragHandler(object sender, MouseEventArgs e) + { + if (!ovpSettings.isLocked()) + { + switch (e.Buttons) + { + case MouseButtons.Primary: + { + PointF scaledLocation = e.Location * Surface.ParentWindow.LogicalPixelSize; + + switch (dragging) + { + case false: + setDown(scaledLocation.X, scaledLocation.Y); + break; + } + + object locking = new(); + lock (locking) + { + float new_X = ovpSettings.getCameraX() - (scaledLocation.X - x_orig) * + ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom(); + float new_Y = ovpSettings.getCameraY() + (scaledLocation.Y - y_orig) * + ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom(); + ovpSettings.setCameraPos(new_X, new_Y); + x_orig = scaledLocation.X; + y_orig = scaledLocation.Y; + } + + break; + } + } + + updateViewport(); + } + + e.Handled = true; + } + + public void freeze_thaw() + { + ovpSettings.lockVP(!ovpSettings.isLocked()); + updateHostFunc?.Invoke(); + } + private Point WorldToScreen(float x, float y) { // int oX = (int)((x - ovpSettings.getCameraX() / (ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom())) + Surface.RenderWidth / 2); @@ -154,6 +356,631 @@ private Size WorldToScreen(SizeF pt) Point pt2 = WorldToScreen(pt.Width, pt.Height); return new Size(pt2.X - pt1.X, pt2.Y - pt1.Y); } + + private void selectByClick(float x, float y) + { + /* + // Where did we click? + PointF scaledLocation = new(x, y); + scaledLocation = ScreenToWorld(scaledLocation.X * Surface.ParentWindow.LogicalPixelSize, scaledLocation.Y * Surface.ParentWindow.LogicalPixelSize); + + PointF cPos = ovpSettings.getCameraPos(); + + // Populate our tree. + int polyCount = ovpSettings.polyList.Count; + switch (polyCount) + { + case > 0: + { + double[] distances = new double[polyCount]; + int[] indices = new int[polyCount]; + ParallelOptions po = new(); + //Parallel.For(0, polyCount, po, (poly, loopstate) => + for (int poly = 0; poly < ovpSettings.polyList.Count; poly++) + { + KDTree pTree = new(2, ovpSettings.polyListPtCount[poly] + 1); // add one for the midpoint. + foreach (PointF t1 in ovpSettings.polyList[poly].poly) + { + PointF t = new(t1.X, t1.Y); + pTree.AddPoint(new double[] { t.X, t.Y }, t); + } + + double maxX = ovpSettings.polyList[poly].poly.Max(p => p.X); + double minX = ovpSettings.polyList[poly].poly.Min(p => p.X); + double maxY = ovpSettings.polyList[poly].poly.Max(p => p.Y); + double minY = ovpSettings.polyList[poly].poly.Min(p => p.Y); + + double deltaX = (maxX - minX) * 0.5f; + double deltaY = (maxY - minY) * 0.5f; + + PointF midPoint = new((float)(minX + deltaX), (float)(minY + deltaY)); + pTree.AddPoint(new double[] { midPoint.X, midPoint.Y }, midPoint); + + // '1' forces a single nearest neighbor to be returned. + NearestNeighbour pIter = pTree.NearestNeighbors(new double[] { scaledLocation.X, scaledLocation.Y }, 1); + while (pIter.MoveNext()) + { + distances[poly] = Math.Abs(pIter.CurrentDistance); + indices[poly] = ovpSettings.polySourceIndex[poly]; + } + } + //); + + int selIndex = indices[Array.IndexOf(distances, distances.Min())]; + + updateHostSelectionFunc?.Invoke(selIndex); + break; + } + default: + { + // Populate our tree. + int lineCount = ovpSettings.lineList.Count; + switch (lineCount) + { + case > 0: + { + double[] distances = new double[lineCount]; + int[] indices = new int[lineCount]; + ParallelOptions po = new(); + //Parallel.For(0, lineCount, po, (line, loopstate) => + for (int line = 0; line < ovpSettings.lineList.Count; line++) + { + KDTree pTree = new(2, ovpSettings.lineListPtCount[line] + 1); // add one for the midpoint. + foreach (PointF t1 in ovpSettings.lineList[line].poly) + { + PointF t = new(t1.X, t1.Y); + pTree.AddPoint(new double[] { t.X, t.Y }, t); + } + + double maxX = ovpSettings.lineList[line].poly.Max(p => p.X); + double minX = ovpSettings.lineList[line].poly.Min(p => p.X); + double maxY = ovpSettings.lineList[line].poly.Max(p => p.Y); + double minY = ovpSettings.lineList[line].poly.Min(p => p.Y); + + double deltaX = (maxX - minX) * 0.5f; + double deltaY = (maxY - minY) * 0.5f; + + PointF midPoint = new((float)(minX + deltaX), (float)(minY + deltaY)); + pTree.AddPoint(new double[] { midPoint.X, midPoint.Y }, midPoint); + + // '1' forces a single nearest neighbor to be returned. + NearestNeighbour pIter = pTree.NearestNeighbors(new double[] { scaledLocation.X, scaledLocation.Y }, 1); + while (pIter.MoveNext()) + { + distances[line] = Math.Abs(pIter.CurrentDistance); + indices[line] = ovpSettings.lineSourceIndex[line]; + } + } + //); + + int selIndex = indices[Array.IndexOf(distances, distances.Min())]; + + updateHostSelectionFunc?.Invoke(selIndex); + break; + } + } + + break; + } + } + */ + } + + private void upHandler(object sender, MouseEventArgs e) + { + switch (e.Buttons) + { + case MouseButtons.Alternate: + { + menu?.Show(Surface); + + break; + } + } + + if (ovpSettings.isLocked()) + { + return; + } + + dragging = e.Buttons switch + { + MouseButtons.Primary => false, + _ => dragging + }; + e.Handled = true; + } + + public void zoomIn(float delta) + { + ovpSettings.setZoomFactor(ovpSettings.getZoomFactor() + ovpSettings.getZoomStep() * 0.01f * delta); + updateHostFunc?.Invoke(); + } + + public void zoomOut(float delta) + { + ovpSettings.setZoomFactor(ovpSettings.getZoomFactor() - ovpSettings.getZoomStep() * 0.01f * delta); + updateHostFunc?.Invoke(); + } + + public void fastZoomIn(float delta) + { + ovpSettings.setZoomFactor(ovpSettings.getZoomFactor() * calcZoom(delta)); + updateHostFunc?.Invoke(); + } + + public void fastZoomOut(float delta) + { + ovpSettings.setZoomFactor(ovpSettings.getZoomFactor() / calcZoom(delta)); + updateHostFunc?.Invoke(); + } + + private float calcZoom(float delta) + { + float f = Math.Abs(delta) * 0.1f; + f = delta switch + { + < 0 => 1.0f / f, + _ => f + }; + + return f; + } + + private void panVertical(float delta) + { + ovpSettings.setCameraY(ovpSettings.getCameraY() + delta / 10); + } + + private void panHorizontal(float delta) + { + ovpSettings.setCameraX(ovpSettings.getCameraX() + delta / 10); + } + + private void addKeyHandler(object sender, EventArgs e) + { + switch (keyHandlerApplied) + { + case true: + return; + default: + Surface.KeyDown += keyHandler; + keyHandlerApplied = true; + break; + } + } + + private void removeKeyHandler(object sender, EventArgs e) + { + switch (keyHandlerApplied) + { + case false: + return; + } + + hasFocus = false; + Surface.KeyDown -= keyHandler; + keyHandlerApplied = false; + } + + public void reset() + { + ovpSettings.resetCamera(); + } + + private void keyHandler(object sender, KeyEventArgs e) + { + //e.Handled = true; + + if (ovpSettings.isLocked()) + { + if (e.Key != Keys.F) + { + return; + } + } + + switch (e.Key) + { + case Keys.F: + ovpSettings.lockVP(!ovpSettings.isLocked()); + break; + case Keys.R: + reset(); + break; + } + + float stepping = 10.0f * ovpSettings.getZoomFactor(); + + bool doUpdate = true; + switch (e.Key) + { + case Keys.A: + panHorizontal(-stepping); + break; + case Keys.D: + panHorizontal(stepping); + break; + case Keys.W: + panVertical(stepping); + break; + case Keys.S: + panVertical(-stepping); + break; + case Keys.N: + zoomOut(-1); + break; + case Keys.M: + zoomIn(-1); + break; + case Keys.X: + zoomExtents(-1); + doUpdate = false; // update performed in extents + break; + case Keys.Z: + zoomExtents(ovpSettings.selectedIndex); + doUpdate = false; // update performed in extents + break; + } + + switch (doUpdate) + { + case true when Platform.Instance.IsGtk: + updateHostFunc?.Invoke(); + break; + case true: + updateViewport(); + break; + } + } + + private void zoomHandler(object sender, MouseEventArgs e) + { + if (!ovpSettings.isLocked()) + { + float wheelZoom = e.Delta.Height; // SystemInformation.MouseWheelScrollLines; + switch (wheelZoom) + { + case > 0: + zoomIn(wheelZoom); + break; + case < 0: + zoomOut(-wheelZoom); + break; + } + + updateViewport(); + } + + e.Handled = true; + } + + private void getExtents(int index) + { + float minX = 0; + float maxX = 0; + float minY = 0, maxY = 0; + + bool set = false; + + switch (ovpSettings.polyList.Count) + { + case 0 when ovpSettings.lineList.Count == 0: + ovpSettings.minX = 0; + ovpSettings.maxX = 0; + ovpSettings.minY = 0; + ovpSettings.maxY = 0; + return; + } + + if (ovpSettings.polyList.Count != 0) + { + for (int poly = 0; poly < ovpSettings.polyList.Count; poly++) + { + if (index != -1 && (ovpSettings.polySourceIndex[poly] != index || !ovpSettings.polyMask[poly])) + { + continue; + } + + switch (set) + { + case false: + minX = ovpSettings.polyList[poly].poly[0].X; + maxX = ovpSettings.polyList[poly].poly[0].X; + minY = ovpSettings.polyList[poly].poly[0].Y; + maxY = ovpSettings.polyList[poly].poly[0].Y; + set = true; + break; + } + + float tMinX = ovpSettings.polyList[poly].poly.Min(p => p.X); + float tMaxX = ovpSettings.polyList[poly].poly.Max(p => p.X); + float tMinY = ovpSettings.polyList[poly].poly.Min(p => p.Y); + float tMaxY = ovpSettings.polyList[poly].poly.Max(p => p.Y); + minX = Math.Min(minX, tMinX); + maxX = Math.Max(maxX, tMaxX); + minY = Math.Min(minY, tMinY); + maxY = Math.Max(maxY, tMaxY); + } + } + + if (ovpSettings.lineList.Count != 0) + { + for (int line = 0; line < ovpSettings.lineList.Count; line++) + { + if (index != -1 && (ovpSettings.lineSourceIndex[line] != index || !ovpSettings.lineMask[line])) + { + continue; + } + + switch (set) + { + case false: + minX = ovpSettings.lineList[line].poly[0].X; + maxX = ovpSettings.lineList[line].poly[0].X; + minY = ovpSettings.lineList[line].poly[0].Y; + maxY = ovpSettings.lineList[line].poly[0].Y; + set = true; + break; + } + + float tMinX = ovpSettings.lineList[line].poly.Min(p => p.X); + float tMaxX = ovpSettings.lineList[line].poly.Max(p => p.X); + float tMinY = ovpSettings.lineList[line].poly.Min(p => p.Y); + float tMaxY = ovpSettings.lineList[line].poly.Max(p => p.Y); + minX = Math.Min(minX, tMinX); + maxX = Math.Max(maxX, tMaxX); + minY = Math.Min(minY, tMinY); + maxY = Math.Max(maxY, tMaxY); + } + } + + ovpSettings.minX = minX; + ovpSettings.maxX = maxX; + ovpSettings.minY = minY; + ovpSettings.maxY = maxY; + + ovpSettings.changed = true; + } + + private void drawPolygons() + { + int polyListCount = ovpSettings.polyList.Count; + int bgPolyListCount = ovpSettings.bgPolyList.Count; + int tessPolyListCount = ovpSettings.tessPolyList.Count; + + List polyList = new(); + + List pointsList = new(); + + List tessPolyList = new(); + + try + { + + // Carve our Z-space up to stack polygons + int numPolys = 1; + + numPolys = polyListCount + bgPolyListCount; + // Create our first and count arrays for the vertex indices, to enable polygon separation when rendering. + polyFirst = new uint[numPolys]; + polyVertexCount = new uint[numPolys]; + + tessFirst = new uint[tessPolyListCount]; + tessVertexCount = new uint[tessPolyListCount]; + + List tFirst = new(); + + uint tCounter = 0; + + if (ovpSettings.drawFilled()) + { + numPolys += tessPolyListCount; + } + + float + polyZStep = 1.0f / Math.Max(1, + numPolys + + 1); // avoid a div by zero risk; pad the poly number also to reduce risk of adding a poly beyond the clipping range + + int counter = 0; // vertex count that will be used to define 'first' index for each polygon. + int previouscounter = 0; // will be used to derive the number of vertices in each polygon. + + float polyZ = 0; + + if (ovpSettings.drawFilled()) + { + for (int poly = 0; poly < tessPolyListCount; poly++) + { + tessFirst[poly] = (uint)(poly * 3); + float alpha = ovpSettings.tessPolyList[poly].alpha; + polyZ += polyZStep; + for (int pt = 0; pt < 3; pt++) + { + tessPolyList.Add(new VertexPositionColor( + new Vector3(ovpSettings.tessPolyList[poly].poly[pt].X, + ovpSettings.tessPolyList[poly].poly[pt].Y, polyZ), + new RgbaFloat(ovpSettings.tessPolyList[poly].color.R, + ovpSettings.tessPolyList[poly].color.G, ovpSettings.tessPolyList[poly].color.B, + alpha))); + } + + tessVertexCount[poly] = 3; + } + } + + // Pondering options here - this would make a nice border construct around the filled geometry, amongst other things. + for (int poly = 0; poly < polyListCount; poly++) + { + float alpha = ovpSettings.polyList[poly].alpha; + if (ovpSettings.drawFilled()) + { + alpha = 1.0f; + } + + polyZ += polyZStep; + polyFirst[poly] = (uint)counter; + previouscounter = counter; + int polyLength = ovpSettings.polyList[poly].poly.Length - 1; + for (int pt = 0; pt < polyLength; pt++) + { + polyList.Add(new VertexPositionColor( + new Vector3(ovpSettings.polyList[poly].poly[pt].X, ovpSettings.polyList[poly].poly[pt].Y, + polyZ), + new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, + ovpSettings.polyList[poly].color.B, alpha))); + counter++; + polyList.Add(new VertexPositionColor( + new Vector3(ovpSettings.polyList[poly].poly[pt + 1].X, + ovpSettings.polyList[poly].poly[pt + 1].Y, polyZ), + new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, + ovpSettings.polyList[poly].color.B, alpha))); + counter++; + + if (!ovpSettings.drawPoints()) + { + continue; + } + + tFirst.Add(tCounter); + pointsList.Add(new VertexPositionColor( + new Vector3(ovpSettings.polyList[poly].poly[pt].X - pointWidth / 2.0f, + ovpSettings.polyList[poly].poly[pt].Y - pointWidth / 2.0f, 1.0f), + new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, + ovpSettings.polyList[poly].color.B, alpha))); + tCounter++; + pointsList.Add(new VertexPositionColor( + new Vector3(ovpSettings.polyList[poly].poly[pt].X - pointWidth / 2.0f, + ovpSettings.polyList[poly].poly[pt].Y + pointWidth / 2.0f, 1.0f), + new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, + ovpSettings.polyList[poly].color.B, alpha))); + tCounter++; + pointsList.Add(new VertexPositionColor( + new Vector3(ovpSettings.polyList[poly].poly[pt].X + pointWidth / 2.0f, + ovpSettings.polyList[poly].poly[pt].Y - pointWidth / 2.0f, 1.0f), + new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, + ovpSettings.polyList[poly].color.B, alpha))); + tCounter++; + + tFirst.Add(tCounter); + pointsList.Add(new VertexPositionColor( + new Vector3(ovpSettings.polyList[poly].poly[pt].X + pointWidth / 2.0f, + ovpSettings.polyList[poly].poly[pt].Y - pointWidth / 2.0f, 1.0f), + new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, + ovpSettings.polyList[poly].color.B, alpha))); + tCounter++; + pointsList.Add(new VertexPositionColor( + new Vector3(ovpSettings.polyList[poly].poly[pt].X - pointWidth / 2.0f, + ovpSettings.polyList[poly].poly[pt].Y + pointWidth / 2.0f, 1.0f), + new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, + ovpSettings.polyList[poly].color.B, alpha))); + tCounter++; + pointsList.Add(new VertexPositionColor( + new Vector3(ovpSettings.polyList[poly].poly[pt].X + pointWidth / 2.0f, + ovpSettings.polyList[poly].poly[pt].Y + pointWidth / 2.0f, 1.0f), + new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, + ovpSettings.polyList[poly].color.B, alpha))); + tCounter++; + } + + polyVertexCount[poly] = (uint)(counter - previouscounter); // set our vertex count for the polygon. + } + + polyZ = 0; + for (int poly = 0; poly < bgPolyListCount; poly++) + { + float alpha = ovpSettings.bgPolyList[poly].alpha; + polyZ += polyZStep; + polyFirst[poly + polyListCount] = (uint)counter; + previouscounter = counter; + + int bgPolyLength = ovpSettings.bgPolyList[poly].poly.Length - 1; + for (int pt = 0; pt < bgPolyLength; pt++) + { + polyList.Add(new VertexPositionColor( + new Vector3(ovpSettings.bgPolyList[poly].poly[pt].X, + ovpSettings.bgPolyList[poly].poly[pt].Y, polyZ), + new RgbaFloat(ovpSettings.bgPolyList[poly].color.R, ovpSettings.bgPolyList[poly].color.G, + ovpSettings.bgPolyList[poly].color.B, alpha))); + counter++; + polyList.Add(new VertexPositionColor( + new Vector3(ovpSettings.bgPolyList[poly].poly[pt + 1].X, + ovpSettings.bgPolyList[poly].poly[pt + 1].Y, polyZ), + new RgbaFloat(ovpSettings.bgPolyList[poly].color.R, ovpSettings.bgPolyList[poly].color.G, + ovpSettings.bgPolyList[poly].color.B, alpha))); + counter++; + } + + polyVertexCount[poly + polyListCount] = + (uint)(counter - previouscounter); // set our vertex count for the polygon. + } + + pointsFirst = tFirst.ToArray(); + } + catch (Exception) + { + // Can ignore - not critical. + } + + if (polyListCount > 0 || bgPolyListCount > 0) + { + updateBuffer(ref PolysVertexBuffer, polyList.ToArray(), VertexPositionColor.SizeInBytes, + BufferUsage.VertexBuffer); + } + + if (ovpSettings.drawPoints() && polyListCount > 0) + { + updateBuffer(ref PointsVertexBuffer, pointsList.ToArray(), VertexPositionColor.SizeInBytes, + BufferUsage.VertexBuffer); + } + + if (ovpSettings.drawFilled() && tessPolyListCount > 0) + { + updateBuffer(ref TessVertexBuffer, tessPolyList.ToArray(), VertexPositionColor.SizeInBytes, + BufferUsage.VertexBuffer); + } + } + + private void drawLines() + { + int tmp = ovpSettings.lineList.Count; + + switch (tmp) + { + // Create our first and count arrays for the vertex indices, to enable polygon separation when rendering. + case > 0: + { + List lineList = new(); + + // Carve our Z-space up to stack polygons + float polyZStep = 1.0f / ovpSettings.lineList.Count; + + lineFirst = new uint[tmp]; + lineVertexCount = new uint[tmp]; + + for (int poly = 0; poly < tmp; poly++) + { + float alpha = ovpSettings.lineList[poly].alpha; + float polyZ = poly * polyZStep; + lineFirst[poly] = (uint)lineList.Count; + lineList.AddRange(ovpSettings.lineList[poly].poly.Select(t => + new VertexPositionColor(new Vector3(t.X, t.Y, polyZ), + new RgbaFloat(ovpSettings.lineList[poly].color.R, ovpSettings.lineList[poly].color.G, + ovpSettings.lineList[poly].color.B, alpha)))); + lineVertexCount[poly] = + (uint)ovpSettings.lineList[poly].poly.Length; // set our vertex count for the polygon. + } + + updateBuffer(ref LinesVertexBuffer, lineList.ToArray(), VertexPositionColor.SizeInBytes, + BufferUsage.VertexBuffer); + break; + } + default: + LinesVertexBuffer = null; + break; + } + } + private void drawGrid() { if (!ovpSettings.drawGrid()) @@ -308,7 +1135,8 @@ private void drawGrid() gridIndices[i] = i; } - updateBuffer(ref GridVertexBuffer, grid.ToArray(), VertexPositionColor.SizeInBytes, BufferUsage.VertexBuffer); + updateBuffer(ref GridVertexBuffer, grid.ToArray(), VertexPositionColor.SizeInBytes, + BufferUsage.VertexBuffer); updateBuffer(ref GridIndexBuffer, gridIndices, sizeof(uint), BufferUsage.IndexBuffer); break; } @@ -328,10 +1156,20 @@ private void drawAxes() float zoom = ovpSettings.getBaseZoom() * ovpSettings.getZoomFactor(); VertexPositionColor[] axesArray = new VertexPositionColor[4]; - axesArray[0] = new VertexPositionColor(new Vector3(0.0f, ovpSettings.getCameraY() + Surface.RenderHeight * zoom, axisZ), new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); - axesArray[1] = new VertexPositionColor(new Vector3(0.0f, ovpSettings.getCameraY() - Surface.RenderHeight * zoom, axisZ), new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); - axesArray[2] = new VertexPositionColor(new Vector3(ovpSettings.getCameraX() + Surface.RenderWidth * zoom, 0.0f, axisZ), new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); - axesArray[3] = new VertexPositionColor(new Vector3(ovpSettings.getCameraX() - Surface.RenderWidth * zoom, 0.0f, axisZ), new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); + axesArray[0] = + new VertexPositionColor( + new Vector3(0.0f, ovpSettings.getCameraY() + Surface.RenderHeight * zoom, axisZ), + new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); + axesArray[1] = + new VertexPositionColor( + new Vector3(0.0f, ovpSettings.getCameraY() - Surface.RenderHeight * zoom, axisZ), + new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); + axesArray[2] = + new VertexPositionColor(new Vector3(ovpSettings.getCameraX() + Surface.RenderWidth * zoom, 0.0f, axisZ), + new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); + axesArray[3] = + new VertexPositionColor(new Vector3(ovpSettings.getCameraX() - Surface.RenderWidth * zoom, 0.0f, axisZ), + new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); axesIndices = new uint[4] { 0, 1, 2, 3 }; @@ -378,6 +1216,10 @@ public void Draw() CommandList.ClearDepthStencil(1.0f); drawGrid(); + drawAxes(); + drawLines(); + drawPolygons(); + if (GridVertexBuffer != null) { lock (GridVertexBuffer) @@ -404,7 +1246,6 @@ public void Draw() } } - drawAxes(); if (AxesVertexBuffer != null) { lock (AxesVertexBuffer) @@ -431,6 +1272,104 @@ public void Draw() } } + if (ovpSettings.drawFilled()) + { + if (TessVertexBuffer != null) + { + lock (TessVertexBuffer) + { + try + { + CommandList.SetVertexBuffer(0, TessVertexBuffer); + CommandList.SetPipeline(FilledPipeline); + CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); + CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); + + for (int l = 0; l < tessVertexCount.Length; l++) + { + CommandList.Draw(tessVertexCount[l], 1, tessFirst[l], 0); + } + } + catch (Exception) + { + + } + } + } + } + + if (PolysVertexBuffer != null) + { + lock (PolysVertexBuffer) + { + try + { + CommandList.SetVertexBuffer(0, PolysVertexBuffer); + CommandList.SetPipeline(LinesPipeline); + CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); + CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); + + for (int l = 0; l < polyVertexCount.Length; l++) + { + CommandList.Draw(polyVertexCount[l], 1, polyFirst[l], 0); + } + } + catch (Exception) + { + + } + } + } + + if (LinesVertexBuffer != null && ovpSettings.drawDrawn()) + { + lock (LinesVertexBuffer) + { + try + { + CommandList.SetVertexBuffer(0, LinesVertexBuffer); + CommandList.SetPipeline(LinesPipeline); + CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); + CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); + + for (int l = 0; l < lineVertexCount.Length; l++) + { + CommandList.Draw(lineVertexCount[l], 1, lineFirst[l], 0); + } + } + catch (Exception) + { + + } + } + } + + if (ovpSettings.drawPoints()) + { + if (PointsVertexBuffer != null) + { + lock (PointsVertexBuffer) + { + try + { + CommandList.SetVertexBuffer(0, PointsVertexBuffer); + CommandList.SetPipeline(FilledPipeline); + CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); + CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); + + foreach (uint t in pointsFirst) + { + CommandList.Draw(3, 1, t, 0); + } + } + catch (Exception) + { + + } + } + } + } + CommandList.End(); try @@ -532,7 +1471,9 @@ private void CreateResources() ModelMatrixSet = factory.CreateResourceSet(new ResourceSetDescription( modelMatrixLayout, ModelBuffer)); - VertexBuffer = factory.CreateBuffer(new BufferDescription(4 * VertexPositionColor.SizeInBytes, BufferUsage.VertexBuffer)); + VertexBuffer = + factory.CreateBuffer(new BufferDescription(4 * VertexPositionColor.SizeInBytes, + BufferUsage.VertexBuffer)); IndexBuffer = factory.CreateBuffer(new BufferDescription(4 * sizeof(ushort), BufferUsage.IndexBuffer)); // Veldrid.SPIRV, when cross-compiling to HLSL, will always produce @@ -542,8 +1483,10 @@ private void CreateResources() // https://github.com/mellinoe/veldrid/issues/121 // var vertexLayout = new VertexLayoutDescription( - new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3), - new VertexElementDescription("Color", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float4)); + new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, + VertexElementFormat.Float3), + new VertexElementDescription("Color", VertexElementSemantic.TextureCoordinate, + VertexElementFormat.Float4)); Pipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription { diff --git a/test/TestEtoVeldrid/MainForm.cs b/test/TestEtoVeldrid/MainForm.cs index 88feb5e..70ca385 100644 --- a/test/TestEtoVeldrid/MainForm.cs +++ b/test/TestEtoVeldrid/MainForm.cs @@ -1,8 +1,12 @@ -using Eto.Forms; +using Eto.Drawing; +using Eto.Forms; using Eto.Veldrid; +using System; +using System.Threading; using TestEtoVeldrid2; using Veldrid; using VeldridEto; +using PixelFormat = Veldrid.PixelFormat; namespace TestEtoVeldrid { @@ -12,6 +16,8 @@ public partial class MainForm : Form VeldridDriver Driver; + private OVPSettings ovpSettings; + private bool _veldridReady = false; public bool VeldridReady { @@ -64,9 +70,10 @@ public MainForm(GraphicsBackend backend) Content = Surface; - OVPSettings settings = new OVPSettings(); + ovpSettings = new OVPSettings(); + addPolys(); - Driver = new VeldridDriver(ref settings, ref Surface); + Driver = new VeldridDriver(ref ovpSettings, ref Surface); Surface.VeldridInitialized += (sender, e) => { @@ -80,7 +87,277 @@ public MainForm(GraphicsBackend backend) //CmdClockwise.Bind("Checked", Driver, "Clockwise"); } - private void SetUpVeldrid() + private void addPolys() + { + ovpSettings.clear(); + + float r = 0.0f; + + PointF[] testPoly = new PointF[6]; + testPoly[0] = new PointF(2.0f + r, 2.0f + r); + testPoly[1] = new PointF(15.0f + r, 12.0f + r); + testPoly[2] = new PointF(8.0f + r, 24.0f + r); + testPoly[3] = new PointF(8.0f + r, 15.0f + r); + testPoly[4] = new PointF(3.0f + r, 2.0f + r); + testPoly[5] = new PointF(2.0f + r, 2.0f + r); + + + PointF[] testPoly2 = new PointF[6]; + testPoly2[0] = new PointF(12.0f + r, 2.0f + r); + testPoly2[1] = new PointF(25.0f + r, 12.0f + r); + testPoly2[2] = new PointF(18.0f + r, 24.0f + r); + testPoly2[3] = new PointF(18.0f + r, 15.0f + r); + testPoly2[4] = new PointF(13.0f + r, 2.0f + r); + testPoly2[5] = new PointF(12.0f + r, 2.0f + r); + + ovpSettings.addPolygon(testPoly2, Color.FromArgb(0, 255, 255), 1.0f, true, 1); + + ovpSettings.addPolygon(testPoly, Color.FromArgb(255, 0, 0), 1.0f, true, 2); + + r = -30.0f; + + PointF[] testPolyF1 = new PointF[6]; + testPolyF1[0] = new PointF(2.0f + r, 2.0f + r); + testPolyF1[1] = new PointF(15.0f + r, 12.0f + r); + testPolyF1[2] = new PointF(8.0f + r, 24.0f + r); + testPolyF1[3] = new PointF(8.0f + r, 15.0f + r); + testPolyF1[4] = new PointF(3.0f + r, 2.0f + r); + testPolyF1[5] = new PointF(2.0f + r, 2.0f + r); + + PointF[] testPolyF2 = new PointF[6]; + testPolyF2[0] = new PointF(12.0f + r, 2.0f + r); + testPolyF2[1] = new PointF(25.0f + r, 12.0f + r); + testPolyF2[2] = new PointF(18.0f + r, 24.0f + r); + testPolyF2[3] = new PointF(18.0f + r, 15.0f + r); + testPolyF2[4] = new PointF(13.0f + r, 2.0f + r); + testPolyF2[5] = new PointF(12.0f + r, 2.0f + r); + + + ovpSettings.addPolygon(testPolyF2, Color.FromArgb(0, 255, 255), 0.5f, false, 3); + + ovpSettings.addPolygon(testPolyF1, Color.FromArgb(255, 0, 0), 1.0f, false, 4); + + r = 30.0f; + + PointF[] testPolyBG1 = new PointF[6]; + testPolyBG1[0] = new PointF(2.0f + r, 2.0f + r); + testPolyBG1[1] = new PointF(15.0f + r, 12.0f + r); + testPolyBG1[2] = new PointF(8.0f + r, 24.0f + r); + testPolyBG1[3] = new PointF(8.0f + r, 15.0f + r); + testPolyBG1[4] = new PointF(3.0f + r, 2.0f + r); + testPolyBG1[5] = new PointF(2.0f + r, 2.0f + r); + + PointF[] testPolyBG2 = new PointF[6]; + testPolyBG2[0] = new PointF(12.0f + r, 2.0f + r); + testPolyBG2[1] = new PointF(25.0f + r, 12.0f + r); + testPolyBG2[2] = new PointF(18.0f + r, 24.0f + r); + testPolyBG2[3] = new PointF(18.0f + r, 15.0f + r); + testPolyBG2[4] = new PointF(13.0f + r, 2.0f + r); + testPolyBG2[5] = new PointF(12.0f + r, 2.0f + r); + + + ovpSettings.addBGPolygon(testPolyBG2, Color.FromArgb(0, 255, 255), 1.0f, 3); + + ovpSettings.addBGPolygon(testPolyBG1, Color.FromArgb(255, 0, 0), 1.0f, 4); + } + + + private ContextMenu vp_menu; + + private void createVPContextMenu() + { + // Single viewport now mandates regeneration of the context menu each time, to allow for entry screening. + vp_menu = new ContextMenu(); + + int itemIndex = 0; + vp_menu.Items.Add(new ButtonMenuItem { Text = "Reset" }); + vp_menu.Items[itemIndex].Click += delegate + { + Driver.reset(); + updateViewport(); + }; + itemIndex++; + + ButtonMenuItem VPMenuDisplayOptionsMenu = vp_menu.Items.GetSubmenu("Display Options"); + itemIndex++; + int displayOptionsSubItemIndex = 0; + VPMenuDisplayOptionsMenu.Items.Add(new ButtonMenuItem { Text = "Toggle AA" }); + VPMenuDisplayOptionsMenu.Items[displayOptionsSubItemIndex].Click += delegate + { + ovpSettings.aA(!ovpSettings.aA()); + updateViewport(); + }; + displayOptionsSubItemIndex++; + VPMenuDisplayOptionsMenu.Items.Add(new ButtonMenuItem { Text = "Toggle Fill" }); + VPMenuDisplayOptionsMenu.Items[displayOptionsSubItemIndex].Click += delegate + { + ovpSettings.drawFilled(!ovpSettings.drawFilled()); + updateViewport(); + }; + displayOptionsSubItemIndex++; + VPMenuDisplayOptionsMenu.Items.Add(new ButtonMenuItem { Text = "Toggle Points" }); + VPMenuDisplayOptionsMenu.Items[displayOptionsSubItemIndex].Click += delegate + { + ovpSettings.drawPoints(!ovpSettings.drawPoints()); + updateViewport(); + }; + displayOptionsSubItemIndex++; + + { + if (Driver.ovpSettings.isLocked()) + { + vp_menu.Items.Add(new ButtonMenuItem { Text = "Thaw" }); + } + else + { + vp_menu.Items.Add(new ButtonMenuItem { Text = "Freeze" }); + } + vp_menu.Items[itemIndex].Click += delegate + { + Driver.freeze_thaw(); + updateViewport(); + }; + itemIndex++; + vp_menu.Items.AddSeparator(); + itemIndex++; + vp_menu.Items.Add(new ButtonMenuItem { Text = "Save bookmark" }); + vp_menu.Items[itemIndex].Click += delegate + { + Driver.saveLocation(); + }; + itemIndex++; + vp_menu.Items.Add(new ButtonMenuItem { Text = "Load bookmark" }); + vp_menu.Items[itemIndex].Click += delegate + { + Driver.loadLocation(); + }; + vp_menu.Items[itemIndex].Enabled = Driver.savedLocation_valid switch + { + false => false, + _ => vp_menu.Items[itemIndex].Enabled + }; + itemIndex++; + } + vp_menu.Items.AddSeparator(); + itemIndex++; + vp_menu.Items.Add(new ButtonMenuItem { Text = "Zoom Extents" }); + vp_menu.Items[itemIndex].Click += delegate + { + Driver.zoomExtents(0); + }; + itemIndex++; + vp_menu.Items.AddSeparator(); + itemIndex++; + vp_menu.Items.Add(new ButtonMenuItem { Text = "Zoom In" }); + vp_menu.Items[itemIndex].Click += delegate + { + Driver.zoomIn(-1); + updateViewport(); + }; + itemIndex++; + + ButtonMenuItem VPMenuZoomInMenu = vp_menu.Items.GetSubmenu("Fast Zoom In"); + itemIndex++; + int zoomInSubItemIndex = 0; + VPMenuZoomInMenu.Items.Add(new ButtonMenuItem { Text = "Zoom In (x5)" }); + VPMenuZoomInMenu.Items[zoomInSubItemIndex].Click += delegate + { + Driver.zoomIn(-50); + updateViewport(); + }; + zoomInSubItemIndex++; + VPMenuZoomInMenu.Items.Add(new ButtonMenuItem { Text = "Zoom In (x10)" }); + VPMenuZoomInMenu.Items[zoomInSubItemIndex].Click += delegate + { + Driver.zoomIn(-100); + updateViewport(); + }; + zoomInSubItemIndex++; + VPMenuZoomInMenu.Items.Add(new ButtonMenuItem { Text = "Zoom In (x50)" }); + VPMenuZoomInMenu.Items[zoomInSubItemIndex].Click += delegate + { + Driver.zoomIn(-500); + updateViewport(); + }; + zoomInSubItemIndex++; + VPMenuZoomInMenu.Items.Add(new ButtonMenuItem { Text = "Zoom In (x100)" }); + VPMenuZoomInMenu.Items[zoomInSubItemIndex].Click += delegate + { + Driver.zoomIn(-1000); + updateViewport(); + }; + zoomInSubItemIndex++; + + vp_menu.Items.AddSeparator(); + itemIndex++; + + vp_menu.Items.Add(new ButtonMenuItem { Text = "Zoom Out" }); + vp_menu.Items[itemIndex].Click += delegate + { + Driver.zoomOut(-1); + updateViewport(); + }; + itemIndex++; + + ButtonMenuItem VPMenuZoomOutMenu = vp_menu.Items.GetSubmenu("Fast Zoom Out"); + itemIndex++; + int zoomOutSubItemIndex = 0; + VPMenuZoomOutMenu.Items.Add(new ButtonMenuItem { Text = "Zoom Out (x5)" }); + VPMenuZoomOutMenu.Items[zoomOutSubItemIndex].Click += delegate + { + Driver.zoomOut(-50); + updateViewport(); + }; + zoomOutSubItemIndex++; + VPMenuZoomOutMenu.Items.Add(new ButtonMenuItem { Text = "Zoom Out (x10)" }); + VPMenuZoomOutMenu.Items[zoomOutSubItemIndex].Click += delegate + { + Driver.zoomOut(-100); + updateViewport(); + }; + zoomOutSubItemIndex++; + VPMenuZoomOutMenu.Items.Add(new ButtonMenuItem { Text = "Zoom Out (x50)" }); + VPMenuZoomOutMenu.Items[zoomOutSubItemIndex].Click += delegate + { + Driver.zoomOut(-500); + updateViewport(); + }; + zoomOutSubItemIndex++; + VPMenuZoomOutMenu.Items.Add(new ButtonMenuItem { Text = "Zoom Out (x100)" }); + VPMenuZoomOutMenu.Items[zoomOutSubItemIndex].Click += delegate + { + Driver.zoomOut(-1000); + updateViewport(); + }; + zoomOutSubItemIndex++; + + Driver.setContextMenu(ref vp_menu); + } + + private void updateViewport() + { + Application.Instance.Invoke(() => + { + Monitor.Enter(ovpSettings); + // Force a geometry re-add here, just to test the fill system. Wouldn't be necessary in real world cases. + addPolys(); + + try + { + createVPContextMenu(); + Driver.updateViewport(); + } + catch (Exception) + { + } + finally + { + Monitor.Exit(ovpSettings); + } + }); + } + + private void SetUpVeldrid() { if (!(FormReady && VeldridReady)) { @@ -89,6 +366,8 @@ private void SetUpVeldrid() Title = $"Veldrid backend: {Surface.Backend.ToString()}"; + createVPContextMenu(); + Driver.Clock.Start(); } } From 94d182c9df24efda39025048c2253abc6d1e4160 Mon Sep 17 00:00:00 2001 From: philstopford Date: Mon, 19 Feb 2024 10:10:04 -0600 Subject: [PATCH 15/24] More WIP Polygon lines are now drawn, some clean-up as well. Filled polygons not yet available. --- src/Eto.VeldridSurface/VeldridDriver.cs | 64 +++++++++++++++++-------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/src/Eto.VeldridSurface/VeldridDriver.cs b/src/Eto.VeldridSurface/VeldridDriver.cs index df827b1..d2e1fc7 100644 --- a/src/Eto.VeldridSurface/VeldridDriver.cs +++ b/src/Eto.VeldridSurface/VeldridDriver.cs @@ -88,7 +88,6 @@ public VeldridSurface Surface private DeviceBuffer PolysVertexBuffer; private DeviceBuffer TessVertexBuffer; - public Pipeline Pipeline { get; private set; } private Pipeline PointsPipeline; private Pipeline LinePipeline; private Pipeline LinesPipeline; @@ -165,6 +164,11 @@ public void updateViewport() return; } + drawAxes(); + drawGrid(); + drawLines(); + drawPolygons(); + updateHostFunc?.Invoke(); Surface.Invalidate(); } @@ -1290,9 +1294,9 @@ public void Draw() CommandList.Draw(tessVertexCount[l], 1, tessFirst[l], 0); } } - catch (Exception) + catch (Exception ex) { - + int xx = 2; } } } @@ -1314,9 +1318,9 @@ public void Draw() CommandList.Draw(polyVertexCount[l], 1, polyFirst[l], 0); } } - catch (Exception) + catch (Exception ex) { - + int xx = 2; } } } @@ -1337,9 +1341,9 @@ public void Draw() CommandList.Draw(lineVertexCount[l], 1, lineFirst[l], 0); } } - catch (Exception) + catch (Exception ex) { - + int xx = 2; } } } @@ -1362,9 +1366,9 @@ public void Draw() CommandList.Draw(3, 1, t, 0); } } - catch (Exception) + catch (Exception ex) { - + int xx = 2; } } } @@ -1488,7 +1492,7 @@ private void CreateResources() new VertexElementDescription("Color", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float4)); - Pipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription + LinePipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription { BlendState = BlendStateDescription.SingleOverrideBlend, DepthStencilState = new DepthStencilStateDescription( @@ -1501,29 +1505,49 @@ private void CreateResources() frontFace: FrontFace.Clockwise, depthClipEnabled: true, scissorTestEnabled: false), - PrimitiveTopology = PrimitiveTopology.TriangleStrip, - ResourceLayouts = new[] { modelMatrixLayout }, + PrimitiveTopology = PrimitiveTopology.LineList, + ResourceLayouts = new[] { viewMatrixLayout, modelMatrixLayout }, ShaderSet = new ShaderSetDescription( - vertexLayouts: new VertexLayoutDescription[] { vertexLayout }, + vertexLayouts: new[] { vertexLayout }, shaders: shaders), Outputs = Surface.Swapchain.Framebuffer.OutputDescription }); - - LinePipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription + LinesPipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription { - BlendState = BlendStateDescription.SingleOverrideBlend, + BlendState = BlendStateDescription.SingleAlphaBlend, DepthStencilState = new DepthStencilStateDescription( - depthTestEnabled: true, - depthWriteEnabled: true, + depthTestEnabled: false, + depthWriteEnabled: false, comparisonKind: ComparisonKind.LessEqual), RasterizerState = new RasterizerStateDescription( cullMode: FaceCullMode.Back, fillMode: PolygonFillMode.Solid, frontFace: FrontFace.Clockwise, - depthClipEnabled: true, + depthClipEnabled: false, scissorTestEnabled: false), - PrimitiveTopology = PrimitiveTopology.LineList, + PrimitiveTopology = PrimitiveTopology.LineStrip, + ResourceLayouts = new[] { viewMatrixLayout, modelMatrixLayout }, + ShaderSet = new ShaderSetDescription( + vertexLayouts: new[] { vertexLayout }, + shaders: shaders), + Outputs = Surface.Swapchain.Framebuffer.OutputDescription + }); + + FilledPipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription + { + BlendState = BlendStateDescription.SingleAlphaBlend, + DepthStencilState = new DepthStencilStateDescription( + depthTestEnabled: false, + depthWriteEnabled: false, + comparisonKind: ComparisonKind.LessEqual), + RasterizerState = new RasterizerStateDescription( + cullMode: FaceCullMode.None, + fillMode: PolygonFillMode.Solid, + frontFace: FrontFace.CounterClockwise, + depthClipEnabled: false, + scissorTestEnabled: false), + PrimitiveTopology = PrimitiveTopology.TriangleStrip, ResourceLayouts = new[] { viewMatrixLayout, modelMatrixLayout }, ShaderSet = new ShaderSetDescription( vertexLayouts: new[] { vertexLayout }, From a64bd92649815fbf362d229c854253039b4a7086 Mon Sep 17 00:00:00 2001 From: philstopford Date: Mon, 19 Feb 2024 10:22:07 -0600 Subject: [PATCH 16/24] WIP --- src/Eto.VeldridSurface/VeldridDriver.cs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/Eto.VeldridSurface/VeldridDriver.cs b/src/Eto.VeldridSurface/VeldridDriver.cs index d2e1fc7..406d557 100644 --- a/src/Eto.VeldridSurface/VeldridDriver.cs +++ b/src/Eto.VeldridSurface/VeldridDriver.cs @@ -157,32 +157,29 @@ public void setFocus(object sender, EventArgs e) } public void updateViewport() + { + pUpdateViewport(); + } + + private void pUpdateViewport() { if ((!ovpSettings.changed) || (Surface.GraphicsDevice == null) || (!Surface.Visible) || (Surface.Width <= 0) || (Surface.Height <= 0)) { return; } - drawAxes(); drawGrid(); drawLines(); drawPolygons(); - updateHostFunc?.Invoke(); Surface.Invalidate(); + ovpSettings.changed = false; } private void Clock_Elapsed(object sender, EventArgs e) { - if (!ovpSettings.changed) - { - return; - } - // drawAxes(); - // drawGrid(); - // Draw(); - Surface.Invalidate(); + pUpdateViewport(); } private DateTime CurrentTime; @@ -1296,7 +1293,7 @@ public void Draw() } catch (Exception ex) { - int xx = 2; + Console.WriteLine("Ex: " + ex); } } } @@ -1320,7 +1317,7 @@ public void Draw() } catch (Exception ex) { - int xx = 2; + Console.WriteLine("Ex: " + ex); } } } @@ -1343,7 +1340,7 @@ public void Draw() } catch (Exception ex) { - int xx = 2; + Console.WriteLine("Ex: " + ex); } } } @@ -1368,7 +1365,7 @@ public void Draw() } catch (Exception ex) { - int xx = 2; + Console.WriteLine("Ex: " + ex); } } } From 13d0da9f9d411453ff233e9d753e3550d2b133a8 Mon Sep 17 00:00:00 2001 From: philstopford Date: Mon, 19 Feb 2024 10:32:21 -0600 Subject: [PATCH 17/24] Fudging this focus/handler thing for now Doesn't seem live the previous approach was reliable at least in current testing under Wayland. Temporary workaround to allow keyboard input testing. --- src/Eto.VeldridSurface/VeldridDriver.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Eto.VeldridSurface/VeldridDriver.cs b/src/Eto.VeldridSurface/VeldridDriver.cs index 406d557..65338ec 100644 --- a/src/Eto.VeldridSurface/VeldridDriver.cs +++ b/src/Eto.VeldridSurface/VeldridDriver.cs @@ -131,8 +131,9 @@ public VeldridDriver(ref OVPSettings settings, ref VeldridSurface surface) Surface.MouseUp += upHandler; Surface.MouseWheel += zoomHandler; Surface.GotFocus += addKeyHandler; - Surface.MouseEnter += setFocus; + Surface.MouseEnter += addKeyHandler;// setFocus; Surface.LostFocus += removeKeyHandler; + Surface.MouseLeave += removeKeyHandler; } catch (Exception ex) { From 522d49e7a947938bb5024fe2877bd66fc4c51a37 Mon Sep 17 00:00:00 2001 From: philstopford Date: Mon, 19 Feb 2024 12:03:49 -0600 Subject: [PATCH 18/24] Splitting out the contents The monolithic file was proving difficult to navigate and so break this out to improve matters. --- src/Eto.VeldridSurface/VeldridDriver.cs | 1374 +---------------- .../VeldridDriver_Conversions.cs | 34 + src/Eto.VeldridSurface/VeldridDriver_Draw.cs | 687 +++++++++ .../VeldridDriver_Handlers.cs | 471 ++++++ .../VeldridDriver_Public.cs | 134 ++ .../VeldridDriver_Variables.cs | 89 ++ 6 files changed, 1418 insertions(+), 1371 deletions(-) create mode 100644 src/Eto.VeldridSurface/VeldridDriver_Conversions.cs create mode 100644 src/Eto.VeldridSurface/VeldridDriver_Draw.cs create mode 100644 src/Eto.VeldridSurface/VeldridDriver_Handlers.cs create mode 100644 src/Eto.VeldridSurface/VeldridDriver_Public.cs create mode 100644 src/Eto.VeldridSurface/VeldridDriver_Variables.cs diff --git a/src/Eto.VeldridSurface/VeldridDriver.cs b/src/Eto.VeldridSurface/VeldridDriver.cs index 65338ec..b45372d 100644 --- a/src/Eto.VeldridSurface/VeldridDriver.cs +++ b/src/Eto.VeldridSurface/VeldridDriver.cs @@ -1,9 +1,4 @@ -using Eto; -using Eto.Drawing; -using Eto.Forms; -using Eto.Veldrid; -using System; -using System.IO; +using Eto.Veldrid; using System.Numerics; using System.Runtime.InteropServices; using Veldrid; @@ -34,1362 +29,18 @@ public VertexPositionColor(Vector3 position, RgbaFloat color) /// using Veldrid. How exactly to do that is up to you; this driver class is /// only one possible approach, and in all likelihood not the most efficient. /// - public class VeldridDriver + public partial class VeldridDriver { - public OVPSettings ovpSettings; - - private VeldridSurface _surface; - - public VeldridSurface Surface - { - get { return _surface; } - set - { - _surface = value; - - Surface.Draw += (sender, e) => Draw(); - } - } - - public delegate void updateHost(); - - public updateHost updateHostFunc { get; set; } - - public delegate void updateHostSelection(int index); - - public updateHostSelection updateHostSelectionFunc { get; set; } - - private uint[] polyFirst; - private uint[] polyVertexCount; - private uint[] tessFirst; - private uint[] tessVertexCount; - private uint[] lineFirst; - private uint[] lineVertexCount; - private uint[] pointsFirst; - private uint[] gridIndices; - private uint[] axesIndices; - - private float axisZ; - private float gridZ; - - private DeviceBuffer GridVertexBuffer; - private DeviceBuffer GridIndexBuffer; - private DeviceBuffer AxesVertexBuffer; - private DeviceBuffer AxesIndexBuffer; - - public DeviceBuffer VertexBuffer { get; private set; } - public DeviceBuffer IndexBuffer { get; private set; } - public DeviceBuffer ModelBuffer { get; private set; } - - private DeviceBuffer ViewBuffer; - - private DeviceBuffer LinesVertexBuffer; - private DeviceBuffer PointsVertexBuffer; - private DeviceBuffer PolysVertexBuffer; - private DeviceBuffer TessVertexBuffer; - - private Pipeline PointsPipeline; - private Pipeline LinePipeline; - private Pipeline LinesPipeline; - private Pipeline FilledPipeline; - - public Matrix4x4 ModelMatrix { get; private set; } = Matrix4x4.Identity; - private Matrix4x4 ViewMatrix; - public ResourceSet ModelMatrixSet { get; private set; } - - private ResourceSet ViewMatrixSet; - - public UITimer Clock { get; } = new UITimer(); - - public CommandList CommandList { get; private set; } - - public Shader VertexShader { get; private set; } - public Shader FragmentShader { get; private set; } - - private bool Ready = false; - public bool savedLocation_valid { get; set; } - private PointF savedLocation; - - private const float pointWidth = 0.50f; - private bool hasFocus; - private bool keyHandlerApplied; - - // Use for drag handling. - public bool dragging { get; set; } - private float x_orig; - private float y_orig; public VeldridDriver(ref OVPSettings settings, ref VeldridSurface surface) { ovpSettings = settings; Surface = surface; - - try - { - Surface.MouseDown += downHandler; - Surface.MouseMove += dragHandler; - Surface.MouseUp += upHandler; - Surface.MouseWheel += zoomHandler; - Surface.GotFocus += addKeyHandler; - Surface.MouseEnter += addKeyHandler;// setFocus; - Surface.LostFocus += removeKeyHandler; - Surface.MouseLeave += removeKeyHandler; - } - catch (Exception ex) - { - int x = 2; - } - + addKeyHandlers(); Clock.Interval = 1.0f / 60.0f; Clock.Elapsed += Clock_Elapsed; } - public void setFocus(object sender, EventArgs e) - { - switch (hasFocus) - { - case true: - return; - default: - Surface.Focus(); - hasFocus = true; - break; - } - } - - public void updateViewport() - { - pUpdateViewport(); - } - - private void pUpdateViewport() - { - if ((!ovpSettings.changed) || (Surface.GraphicsDevice == null) || - (!Surface.Visible) || (Surface.Width <= 0) || (Surface.Height <= 0)) - { - return; - } - drawAxes(); - drawGrid(); - drawLines(); - drawPolygons(); - updateHostFunc?.Invoke(); - Surface.Invalidate(); - ovpSettings.changed = false; - } - - private void Clock_Elapsed(object sender, EventArgs e) - { - pUpdateViewport(); - } - - private DateTime CurrentTime; - private DateTime PreviousTime = DateTime.Now; - - private ContextMenu menu; - - public void setContextMenu(ref ContextMenu menu_) - { - menu = menu_; - } - - public void changeSettingsRef(ref OVPSettings newSettings) - { - ovpSettings = newSettings; - updateViewport(); - } - - private void downHandler(object sender, MouseEventArgs e) - { - switch (e.Buttons) - { - case MouseButtons.Primary: - setDown(e.Location.X, e.Location.Y); - break; - } - - if (e.Buttons == MouseButtons.Middle || e.Modifiers == Keys.Control && e.Buttons == MouseButtons.Primary) - { - selectByClick(e.Location.X, e.Location.Y); - } - - e.Handled = true; - } - - private void setDown(float x, float y) - { - switch (dragging) - { - // might not be needed, but seemed like a safe approach to avoid re-setting these in a drag event. - case false when !ovpSettings.isLocked(): - x_orig = x; - y_orig = y; - dragging = true; - break; - } - } - - public void saveLocation() - { - savedLocation = new PointF(ovpSettings.getCameraX(), ovpSettings.getCameraY()); - savedLocation_valid = true; - } - - public void zoomExtents(int index) - { - getExtents(index); - - if (ovpSettings.polyList.Count == 0 && ovpSettings.lineList.Count == 0 || - ovpSettings.minX == 0 && ovpSettings.maxX == 0 || - ovpSettings.minY == 0 && ovpSettings.maxY == 0) - { - reset(); - return; - } - - // Locate camera at center of the polygon field. - float dX = ovpSettings.maxX - ovpSettings.minX; - float dY = ovpSettings.maxY - ovpSettings.minY; - float cX = dX / 2.0f + ovpSettings.minX; - float cY = dY / 2.0f + ovpSettings.minY; - - // Now need to get the zoom level organized. - float zoomLevel_x = dX / Surface.Width; - float zoomLevel_y = dY / Surface.Height; - - if (zoomLevel_x > zoomLevel_y) - { - ovpSettings.setZoomFactor(zoomLevel_x / ovpSettings.getBaseZoom()); - } - else - { - ovpSettings.setZoomFactor(zoomLevel_y / ovpSettings.getBaseZoom()); - } - - goToLocation(cX, cY); - } - - public void loadLocation() - { - switch (savedLocation_valid) - { - case true: - ovpSettings.setCameraPos(savedLocation.X, savedLocation.Y); - updateViewport(); - break; - } - } - - public void goToLocation(float x, float y) - { - ovpSettings.setCameraPos(x, y); - updateViewport(); - } - - private void dragHandler(object sender, MouseEventArgs e) - { - if (!ovpSettings.isLocked()) - { - switch (e.Buttons) - { - case MouseButtons.Primary: - { - PointF scaledLocation = e.Location * Surface.ParentWindow.LogicalPixelSize; - - switch (dragging) - { - case false: - setDown(scaledLocation.X, scaledLocation.Y); - break; - } - - object locking = new(); - lock (locking) - { - float new_X = ovpSettings.getCameraX() - (scaledLocation.X - x_orig) * - ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom(); - float new_Y = ovpSettings.getCameraY() + (scaledLocation.Y - y_orig) * - ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom(); - ovpSettings.setCameraPos(new_X, new_Y); - x_orig = scaledLocation.X; - y_orig = scaledLocation.Y; - } - - break; - } - } - - updateViewport(); - } - - e.Handled = true; - } - - public void freeze_thaw() - { - ovpSettings.lockVP(!ovpSettings.isLocked()); - updateHostFunc?.Invoke(); - } - - private Point WorldToScreen(float x, float y) - { - // int oX = (int)((x - ovpSettings.getCameraX() / (ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom())) + Surface.RenderWidth / 2); - - double oX_2 = (double)Surface.RenderWidth / 2; - double oX_3 = ovpSettings.getCameraX() / (ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom()); - double oX_4 = x; - - int oXC = (int)(oX_4 - oX_3 + oX_2); - - // int oY = (int)((y - ovpSettings.getCameraY() / (ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom())) + Surface.RenderHeight / 2); - - double oY_2 = (double)Surface.RenderHeight / 2; - double oY_3 = ovpSettings.getCameraY() / (ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom()); - double oY_4 = y; - - int oYC = (int)(oY_4 - oY_3 + oY_2); - - return new Point(oXC, oYC); - } - - private Size WorldToScreen(SizeF pt) - { - Point pt1 = WorldToScreen(0, 0); - Point pt2 = WorldToScreen(pt.Width, pt.Height); - return new Size(pt2.X - pt1.X, pt2.Y - pt1.Y); - } - - private void selectByClick(float x, float y) - { - /* - // Where did we click? - PointF scaledLocation = new(x, y); - scaledLocation = ScreenToWorld(scaledLocation.X * Surface.ParentWindow.LogicalPixelSize, scaledLocation.Y * Surface.ParentWindow.LogicalPixelSize); - - PointF cPos = ovpSettings.getCameraPos(); - - // Populate our tree. - int polyCount = ovpSettings.polyList.Count; - switch (polyCount) - { - case > 0: - { - double[] distances = new double[polyCount]; - int[] indices = new int[polyCount]; - ParallelOptions po = new(); - //Parallel.For(0, polyCount, po, (poly, loopstate) => - for (int poly = 0; poly < ovpSettings.polyList.Count; poly++) - { - KDTree pTree = new(2, ovpSettings.polyListPtCount[poly] + 1); // add one for the midpoint. - foreach (PointF t1 in ovpSettings.polyList[poly].poly) - { - PointF t = new(t1.X, t1.Y); - pTree.AddPoint(new double[] { t.X, t.Y }, t); - } - - double maxX = ovpSettings.polyList[poly].poly.Max(p => p.X); - double minX = ovpSettings.polyList[poly].poly.Min(p => p.X); - double maxY = ovpSettings.polyList[poly].poly.Max(p => p.Y); - double minY = ovpSettings.polyList[poly].poly.Min(p => p.Y); - - double deltaX = (maxX - minX) * 0.5f; - double deltaY = (maxY - minY) * 0.5f; - - PointF midPoint = new((float)(minX + deltaX), (float)(minY + deltaY)); - pTree.AddPoint(new double[] { midPoint.X, midPoint.Y }, midPoint); - - // '1' forces a single nearest neighbor to be returned. - NearestNeighbour pIter = pTree.NearestNeighbors(new double[] { scaledLocation.X, scaledLocation.Y }, 1); - while (pIter.MoveNext()) - { - distances[poly] = Math.Abs(pIter.CurrentDistance); - indices[poly] = ovpSettings.polySourceIndex[poly]; - } - } - //); - - int selIndex = indices[Array.IndexOf(distances, distances.Min())]; - - updateHostSelectionFunc?.Invoke(selIndex); - break; - } - default: - { - // Populate our tree. - int lineCount = ovpSettings.lineList.Count; - switch (lineCount) - { - case > 0: - { - double[] distances = new double[lineCount]; - int[] indices = new int[lineCount]; - ParallelOptions po = new(); - //Parallel.For(0, lineCount, po, (line, loopstate) => - for (int line = 0; line < ovpSettings.lineList.Count; line++) - { - KDTree pTree = new(2, ovpSettings.lineListPtCount[line] + 1); // add one for the midpoint. - foreach (PointF t1 in ovpSettings.lineList[line].poly) - { - PointF t = new(t1.X, t1.Y); - pTree.AddPoint(new double[] { t.X, t.Y }, t); - } - - double maxX = ovpSettings.lineList[line].poly.Max(p => p.X); - double minX = ovpSettings.lineList[line].poly.Min(p => p.X); - double maxY = ovpSettings.lineList[line].poly.Max(p => p.Y); - double minY = ovpSettings.lineList[line].poly.Min(p => p.Y); - - double deltaX = (maxX - minX) * 0.5f; - double deltaY = (maxY - minY) * 0.5f; - - PointF midPoint = new((float)(minX + deltaX), (float)(minY + deltaY)); - pTree.AddPoint(new double[] { midPoint.X, midPoint.Y }, midPoint); - - // '1' forces a single nearest neighbor to be returned. - NearestNeighbour pIter = pTree.NearestNeighbors(new double[] { scaledLocation.X, scaledLocation.Y }, 1); - while (pIter.MoveNext()) - { - distances[line] = Math.Abs(pIter.CurrentDistance); - indices[line] = ovpSettings.lineSourceIndex[line]; - } - } - //); - - int selIndex = indices[Array.IndexOf(distances, distances.Min())]; - - updateHostSelectionFunc?.Invoke(selIndex); - break; - } - } - - break; - } - } - */ - } - - private void upHandler(object sender, MouseEventArgs e) - { - switch (e.Buttons) - { - case MouseButtons.Alternate: - { - menu?.Show(Surface); - - break; - } - } - - if (ovpSettings.isLocked()) - { - return; - } - - dragging = e.Buttons switch - { - MouseButtons.Primary => false, - _ => dragging - }; - e.Handled = true; - } - - public void zoomIn(float delta) - { - ovpSettings.setZoomFactor(ovpSettings.getZoomFactor() + ovpSettings.getZoomStep() * 0.01f * delta); - updateHostFunc?.Invoke(); - } - - public void zoomOut(float delta) - { - ovpSettings.setZoomFactor(ovpSettings.getZoomFactor() - ovpSettings.getZoomStep() * 0.01f * delta); - updateHostFunc?.Invoke(); - } - - public void fastZoomIn(float delta) - { - ovpSettings.setZoomFactor(ovpSettings.getZoomFactor() * calcZoom(delta)); - updateHostFunc?.Invoke(); - } - - public void fastZoomOut(float delta) - { - ovpSettings.setZoomFactor(ovpSettings.getZoomFactor() / calcZoom(delta)); - updateHostFunc?.Invoke(); - } - - private float calcZoom(float delta) - { - float f = Math.Abs(delta) * 0.1f; - f = delta switch - { - < 0 => 1.0f / f, - _ => f - }; - - return f; - } - - private void panVertical(float delta) - { - ovpSettings.setCameraY(ovpSettings.getCameraY() + delta / 10); - } - - private void panHorizontal(float delta) - { - ovpSettings.setCameraX(ovpSettings.getCameraX() + delta / 10); - } - - private void addKeyHandler(object sender, EventArgs e) - { - switch (keyHandlerApplied) - { - case true: - return; - default: - Surface.KeyDown += keyHandler; - keyHandlerApplied = true; - break; - } - } - - private void removeKeyHandler(object sender, EventArgs e) - { - switch (keyHandlerApplied) - { - case false: - return; - } - - hasFocus = false; - Surface.KeyDown -= keyHandler; - keyHandlerApplied = false; - } - - public void reset() - { - ovpSettings.resetCamera(); - } - - private void keyHandler(object sender, KeyEventArgs e) - { - //e.Handled = true; - - if (ovpSettings.isLocked()) - { - if (e.Key != Keys.F) - { - return; - } - } - - switch (e.Key) - { - case Keys.F: - ovpSettings.lockVP(!ovpSettings.isLocked()); - break; - case Keys.R: - reset(); - break; - } - - float stepping = 10.0f * ovpSettings.getZoomFactor(); - - bool doUpdate = true; - switch (e.Key) - { - case Keys.A: - panHorizontal(-stepping); - break; - case Keys.D: - panHorizontal(stepping); - break; - case Keys.W: - panVertical(stepping); - break; - case Keys.S: - panVertical(-stepping); - break; - case Keys.N: - zoomOut(-1); - break; - case Keys.M: - zoomIn(-1); - break; - case Keys.X: - zoomExtents(-1); - doUpdate = false; // update performed in extents - break; - case Keys.Z: - zoomExtents(ovpSettings.selectedIndex); - doUpdate = false; // update performed in extents - break; - } - - switch (doUpdate) - { - case true when Platform.Instance.IsGtk: - updateHostFunc?.Invoke(); - break; - case true: - updateViewport(); - break; - } - } - - private void zoomHandler(object sender, MouseEventArgs e) - { - if (!ovpSettings.isLocked()) - { - float wheelZoom = e.Delta.Height; // SystemInformation.MouseWheelScrollLines; - switch (wheelZoom) - { - case > 0: - zoomIn(wheelZoom); - break; - case < 0: - zoomOut(-wheelZoom); - break; - } - - updateViewport(); - } - - e.Handled = true; - } - - private void getExtents(int index) - { - float minX = 0; - float maxX = 0; - float minY = 0, maxY = 0; - - bool set = false; - - switch (ovpSettings.polyList.Count) - { - case 0 when ovpSettings.lineList.Count == 0: - ovpSettings.minX = 0; - ovpSettings.maxX = 0; - ovpSettings.minY = 0; - ovpSettings.maxY = 0; - return; - } - - if (ovpSettings.polyList.Count != 0) - { - for (int poly = 0; poly < ovpSettings.polyList.Count; poly++) - { - if (index != -1 && (ovpSettings.polySourceIndex[poly] != index || !ovpSettings.polyMask[poly])) - { - continue; - } - - switch (set) - { - case false: - minX = ovpSettings.polyList[poly].poly[0].X; - maxX = ovpSettings.polyList[poly].poly[0].X; - minY = ovpSettings.polyList[poly].poly[0].Y; - maxY = ovpSettings.polyList[poly].poly[0].Y; - set = true; - break; - } - - float tMinX = ovpSettings.polyList[poly].poly.Min(p => p.X); - float tMaxX = ovpSettings.polyList[poly].poly.Max(p => p.X); - float tMinY = ovpSettings.polyList[poly].poly.Min(p => p.Y); - float tMaxY = ovpSettings.polyList[poly].poly.Max(p => p.Y); - minX = Math.Min(minX, tMinX); - maxX = Math.Max(maxX, tMaxX); - minY = Math.Min(minY, tMinY); - maxY = Math.Max(maxY, tMaxY); - } - } - - if (ovpSettings.lineList.Count != 0) - { - for (int line = 0; line < ovpSettings.lineList.Count; line++) - { - if (index != -1 && (ovpSettings.lineSourceIndex[line] != index || !ovpSettings.lineMask[line])) - { - continue; - } - - switch (set) - { - case false: - minX = ovpSettings.lineList[line].poly[0].X; - maxX = ovpSettings.lineList[line].poly[0].X; - minY = ovpSettings.lineList[line].poly[0].Y; - maxY = ovpSettings.lineList[line].poly[0].Y; - set = true; - break; - } - - float tMinX = ovpSettings.lineList[line].poly.Min(p => p.X); - float tMaxX = ovpSettings.lineList[line].poly.Max(p => p.X); - float tMinY = ovpSettings.lineList[line].poly.Min(p => p.Y); - float tMaxY = ovpSettings.lineList[line].poly.Max(p => p.Y); - minX = Math.Min(minX, tMinX); - maxX = Math.Max(maxX, tMaxX); - minY = Math.Min(minY, tMinY); - maxY = Math.Max(maxY, tMaxY); - } - } - - ovpSettings.minX = minX; - ovpSettings.maxX = maxX; - ovpSettings.minY = minY; - ovpSettings.maxY = maxY; - - ovpSettings.changed = true; - } - - private void drawPolygons() - { - int polyListCount = ovpSettings.polyList.Count; - int bgPolyListCount = ovpSettings.bgPolyList.Count; - int tessPolyListCount = ovpSettings.tessPolyList.Count; - - List polyList = new(); - - List pointsList = new(); - - List tessPolyList = new(); - - try - { - - // Carve our Z-space up to stack polygons - int numPolys = 1; - - numPolys = polyListCount + bgPolyListCount; - // Create our first and count arrays for the vertex indices, to enable polygon separation when rendering. - polyFirst = new uint[numPolys]; - polyVertexCount = new uint[numPolys]; - - tessFirst = new uint[tessPolyListCount]; - tessVertexCount = new uint[tessPolyListCount]; - - List tFirst = new(); - - uint tCounter = 0; - - if (ovpSettings.drawFilled()) - { - numPolys += tessPolyListCount; - } - - float - polyZStep = 1.0f / Math.Max(1, - numPolys + - 1); // avoid a div by zero risk; pad the poly number also to reduce risk of adding a poly beyond the clipping range - - int counter = 0; // vertex count that will be used to define 'first' index for each polygon. - int previouscounter = 0; // will be used to derive the number of vertices in each polygon. - - float polyZ = 0; - - if (ovpSettings.drawFilled()) - { - for (int poly = 0; poly < tessPolyListCount; poly++) - { - tessFirst[poly] = (uint)(poly * 3); - float alpha = ovpSettings.tessPolyList[poly].alpha; - polyZ += polyZStep; - for (int pt = 0; pt < 3; pt++) - { - tessPolyList.Add(new VertexPositionColor( - new Vector3(ovpSettings.tessPolyList[poly].poly[pt].X, - ovpSettings.tessPolyList[poly].poly[pt].Y, polyZ), - new RgbaFloat(ovpSettings.tessPolyList[poly].color.R, - ovpSettings.tessPolyList[poly].color.G, ovpSettings.tessPolyList[poly].color.B, - alpha))); - } - - tessVertexCount[poly] = 3; - } - } - - // Pondering options here - this would make a nice border construct around the filled geometry, amongst other things. - for (int poly = 0; poly < polyListCount; poly++) - { - float alpha = ovpSettings.polyList[poly].alpha; - if (ovpSettings.drawFilled()) - { - alpha = 1.0f; - } - - polyZ += polyZStep; - polyFirst[poly] = (uint)counter; - previouscounter = counter; - int polyLength = ovpSettings.polyList[poly].poly.Length - 1; - for (int pt = 0; pt < polyLength; pt++) - { - polyList.Add(new VertexPositionColor( - new Vector3(ovpSettings.polyList[poly].poly[pt].X, ovpSettings.polyList[poly].poly[pt].Y, - polyZ), - new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, - ovpSettings.polyList[poly].color.B, alpha))); - counter++; - polyList.Add(new VertexPositionColor( - new Vector3(ovpSettings.polyList[poly].poly[pt + 1].X, - ovpSettings.polyList[poly].poly[pt + 1].Y, polyZ), - new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, - ovpSettings.polyList[poly].color.B, alpha))); - counter++; - - if (!ovpSettings.drawPoints()) - { - continue; - } - - tFirst.Add(tCounter); - pointsList.Add(new VertexPositionColor( - new Vector3(ovpSettings.polyList[poly].poly[pt].X - pointWidth / 2.0f, - ovpSettings.polyList[poly].poly[pt].Y - pointWidth / 2.0f, 1.0f), - new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, - ovpSettings.polyList[poly].color.B, alpha))); - tCounter++; - pointsList.Add(new VertexPositionColor( - new Vector3(ovpSettings.polyList[poly].poly[pt].X - pointWidth / 2.0f, - ovpSettings.polyList[poly].poly[pt].Y + pointWidth / 2.0f, 1.0f), - new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, - ovpSettings.polyList[poly].color.B, alpha))); - tCounter++; - pointsList.Add(new VertexPositionColor( - new Vector3(ovpSettings.polyList[poly].poly[pt].X + pointWidth / 2.0f, - ovpSettings.polyList[poly].poly[pt].Y - pointWidth / 2.0f, 1.0f), - new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, - ovpSettings.polyList[poly].color.B, alpha))); - tCounter++; - - tFirst.Add(tCounter); - pointsList.Add(new VertexPositionColor( - new Vector3(ovpSettings.polyList[poly].poly[pt].X + pointWidth / 2.0f, - ovpSettings.polyList[poly].poly[pt].Y - pointWidth / 2.0f, 1.0f), - new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, - ovpSettings.polyList[poly].color.B, alpha))); - tCounter++; - pointsList.Add(new VertexPositionColor( - new Vector3(ovpSettings.polyList[poly].poly[pt].X - pointWidth / 2.0f, - ovpSettings.polyList[poly].poly[pt].Y + pointWidth / 2.0f, 1.0f), - new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, - ovpSettings.polyList[poly].color.B, alpha))); - tCounter++; - pointsList.Add(new VertexPositionColor( - new Vector3(ovpSettings.polyList[poly].poly[pt].X + pointWidth / 2.0f, - ovpSettings.polyList[poly].poly[pt].Y + pointWidth / 2.0f, 1.0f), - new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, - ovpSettings.polyList[poly].color.B, alpha))); - tCounter++; - } - - polyVertexCount[poly] = (uint)(counter - previouscounter); // set our vertex count for the polygon. - } - - polyZ = 0; - for (int poly = 0; poly < bgPolyListCount; poly++) - { - float alpha = ovpSettings.bgPolyList[poly].alpha; - polyZ += polyZStep; - polyFirst[poly + polyListCount] = (uint)counter; - previouscounter = counter; - - int bgPolyLength = ovpSettings.bgPolyList[poly].poly.Length - 1; - for (int pt = 0; pt < bgPolyLength; pt++) - { - polyList.Add(new VertexPositionColor( - new Vector3(ovpSettings.bgPolyList[poly].poly[pt].X, - ovpSettings.bgPolyList[poly].poly[pt].Y, polyZ), - new RgbaFloat(ovpSettings.bgPolyList[poly].color.R, ovpSettings.bgPolyList[poly].color.G, - ovpSettings.bgPolyList[poly].color.B, alpha))); - counter++; - polyList.Add(new VertexPositionColor( - new Vector3(ovpSettings.bgPolyList[poly].poly[pt + 1].X, - ovpSettings.bgPolyList[poly].poly[pt + 1].Y, polyZ), - new RgbaFloat(ovpSettings.bgPolyList[poly].color.R, ovpSettings.bgPolyList[poly].color.G, - ovpSettings.bgPolyList[poly].color.B, alpha))); - counter++; - } - - polyVertexCount[poly + polyListCount] = - (uint)(counter - previouscounter); // set our vertex count for the polygon. - } - - pointsFirst = tFirst.ToArray(); - } - catch (Exception) - { - // Can ignore - not critical. - } - - if (polyListCount > 0 || bgPolyListCount > 0) - { - updateBuffer(ref PolysVertexBuffer, polyList.ToArray(), VertexPositionColor.SizeInBytes, - BufferUsage.VertexBuffer); - } - - if (ovpSettings.drawPoints() && polyListCount > 0) - { - updateBuffer(ref PointsVertexBuffer, pointsList.ToArray(), VertexPositionColor.SizeInBytes, - BufferUsage.VertexBuffer); - } - - if (ovpSettings.drawFilled() && tessPolyListCount > 0) - { - updateBuffer(ref TessVertexBuffer, tessPolyList.ToArray(), VertexPositionColor.SizeInBytes, - BufferUsage.VertexBuffer); - } - } - - private void drawLines() - { - int tmp = ovpSettings.lineList.Count; - - switch (tmp) - { - // Create our first and count arrays for the vertex indices, to enable polygon separation when rendering. - case > 0: - { - List lineList = new(); - - // Carve our Z-space up to stack polygons - float polyZStep = 1.0f / ovpSettings.lineList.Count; - - lineFirst = new uint[tmp]; - lineVertexCount = new uint[tmp]; - - for (int poly = 0; poly < tmp; poly++) - { - float alpha = ovpSettings.lineList[poly].alpha; - float polyZ = poly * polyZStep; - lineFirst[poly] = (uint)lineList.Count; - lineList.AddRange(ovpSettings.lineList[poly].poly.Select(t => - new VertexPositionColor(new Vector3(t.X, t.Y, polyZ), - new RgbaFloat(ovpSettings.lineList[poly].color.R, ovpSettings.lineList[poly].color.G, - ovpSettings.lineList[poly].color.B, alpha)))); - lineVertexCount[poly] = - (uint)ovpSettings.lineList[poly].poly.Length; // set our vertex count for the polygon. - } - - updateBuffer(ref LinesVertexBuffer, lineList.ToArray(), VertexPositionColor.SizeInBytes, - BufferUsage.VertexBuffer); - break; - } - default: - LinesVertexBuffer = null; - break; - } - } - - private void drawGrid() - { - if (!ovpSettings.drawGrid()) - { - return; - } - - float spacing = ovpSettings.gridSpacing(); - if (ovpSettings.isGridDynamic()) - { - while (WorldToScreen(new SizeF(spacing, 0.0f)).Width > 12.0f) - { - spacing /= 10.0f; - } - - while (WorldToScreen(new SizeF(spacing, 0.0f)).Width < 4.0f) - { - spacing *= 10.0f; - } - } - - float zoom = ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom(); - float x = ovpSettings.getCameraX(); - float y = ovpSettings.getCameraY(); - - List grid = new(); - - if (WorldToScreen(new SizeF(spacing, 0.0f)).Width >= 4.0f) - { - int k = 0; - for (float i = 0; i > -(Surface.RenderWidth * zoom) + x; i -= spacing) - { - float r = 0.0f; - float g = 0.0f; - float b = 0.0f; - switch (k) - { - case <= 9: - r = ovpSettings.minorGridColor.R; - g = ovpSettings.minorGridColor.G; - b = ovpSettings.minorGridColor.B; - break; - case 10: - r = ovpSettings.majorGridColor.R; - g = ovpSettings.majorGridColor.G; - b = ovpSettings.majorGridColor.B; - k = 0; - break; - } - - k++; - grid.Add(new VertexPositionColor(new Vector3(i, y + zoom * Surface.RenderHeight, gridZ), - new RgbaFloat(r, g, b, 1.0f))); - grid.Add(new VertexPositionColor(new Vector3(i, y + zoom * -Surface.RenderHeight, gridZ), - new RgbaFloat(r, g, b, 1.0f))); - } - - k = 0; - for (float i = 0; i < Surface.RenderWidth * zoom + x; i += spacing) - { - float r = 0.0f; - float g = 0.0f; - float b = 0.0f; - switch (k) - { - case <= 9: - r = ovpSettings.minorGridColor.R; - g = ovpSettings.minorGridColor.G; - b = ovpSettings.minorGridColor.B; - break; - case 10: - r = ovpSettings.majorGridColor.R; - g = ovpSettings.majorGridColor.G; - b = ovpSettings.majorGridColor.B; - k = 0; - break; - } - - k++; - grid.Add(new VertexPositionColor(new Vector3(i, y + zoom * Surface.RenderHeight, gridZ), - new RgbaFloat(r, g, b, 1.0f))); - grid.Add(new VertexPositionColor(new Vector3(i, y + zoom * -Surface.RenderHeight, gridZ), - new RgbaFloat(r, g, b, 1.0f))); - } - - k = 0; - for (float i = 0; i > -(Surface.RenderHeight * zoom) + y; i -= spacing) - { - float r = 0.0f; - float g = 0.0f; - float b = 0.0f; - switch (k) - { - case <= 9: - r = ovpSettings.minorGridColor.R; - g = ovpSettings.minorGridColor.G; - b = ovpSettings.minorGridColor.B; - break; - case 10: - r = ovpSettings.majorGridColor.R; - g = ovpSettings.majorGridColor.G; - b = ovpSettings.majorGridColor.B; - k = 0; - break; - } - - k++; - grid.Add(new VertexPositionColor(new Vector3(x + zoom * Surface.RenderWidth, i, gridZ), - new RgbaFloat(r, g, b, 1.0f))); - grid.Add(new VertexPositionColor(new Vector3(x + zoom * -Surface.RenderWidth, i, gridZ), - new RgbaFloat(r, g, b, 1.0f))); - } - - k = 0; - for (float i = 0; i < Surface.RenderHeight * zoom + y; i += spacing) - { - float r = 0.0f; - float g = 0.0f; - float b = 0.0f; - switch (k) - { - case <= 9: - r = ovpSettings.minorGridColor.R; - g = ovpSettings.minorGridColor.G; - b = ovpSettings.minorGridColor.B; - break; - case 10: - r = ovpSettings.majorGridColor.R; - g = ovpSettings.majorGridColor.G; - b = ovpSettings.majorGridColor.B; - k = 0; - break; - } - - k++; - grid.Add(new VertexPositionColor(new Vector3(x + zoom * Surface.RenderWidth, i, gridZ), - new RgbaFloat(r, g, b, 1.0f))); - grid.Add(new VertexPositionColor(new Vector3(x + zoom * -Surface.RenderWidth, i, gridZ), - new RgbaFloat(r, g, b, 1.0f))); - } - } - - uint gridCount = (uint)grid.Count; - - switch (gridCount) - { - case > 0: - { - gridIndices = new uint[gridCount]; - for (uint i = 0; i < gridIndices.Length; i++) - { - gridIndices[i] = i; - } - - updateBuffer(ref GridVertexBuffer, grid.ToArray(), VertexPositionColor.SizeInBytes, - BufferUsage.VertexBuffer); - updateBuffer(ref GridIndexBuffer, gridIndices, sizeof(uint), BufferUsage.IndexBuffer); - break; - } - default: - GridVertexBuffer = null; - GridIndexBuffer = null; - break; - } - } - - private void drawAxes() - { - if (!ovpSettings.drawAxes()) - { - return; - } - - float zoom = ovpSettings.getBaseZoom() * ovpSettings.getZoomFactor(); - VertexPositionColor[] axesArray = new VertexPositionColor[4]; - axesArray[0] = - new VertexPositionColor( - new Vector3(0.0f, ovpSettings.getCameraY() + Surface.RenderHeight * zoom, axisZ), - new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); - axesArray[1] = - new VertexPositionColor( - new Vector3(0.0f, ovpSettings.getCameraY() - Surface.RenderHeight * zoom, axisZ), - new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); - axesArray[2] = - new VertexPositionColor(new Vector3(ovpSettings.getCameraX() + Surface.RenderWidth * zoom, 0.0f, axisZ), - new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); - axesArray[3] = - new VertexPositionColor(new Vector3(ovpSettings.getCameraX() - Surface.RenderWidth * zoom, 0.0f, axisZ), - new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); - - axesIndices = new uint[4] { 0, 1, 2, 3 }; - - updateBuffer(ref AxesVertexBuffer, axesArray, VertexPositionColor.SizeInBytes, BufferUsage.VertexBuffer); - updateBuffer(ref AxesIndexBuffer, axesIndices, sizeof(uint), BufferUsage.IndexBuffer); - } - - public void Draw() - { - if (!Ready) - { - return; - } - - CommandList.Begin(); - - ModelMatrix *= Matrix4x4.CreateFromAxisAngle( - new Vector3(0, 0, 1), 0); - CommandList.UpdateBuffer(ModelBuffer, 0, ModelMatrix); - - float zoom = ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom(); - - float left = ovpSettings.getCameraX() - (float)Surface.RenderWidth / 2 * zoom; - float right = ovpSettings.getCameraX() + (float)Surface.RenderWidth / 2 * zoom; - float bottom = ovpSettings.getCameraY() + (float)Surface.RenderHeight / 2 * zoom; - float top = ovpSettings.getCameraY() - (float)Surface.RenderHeight / 2 * zoom; - - ViewMatrix = Matrix4x4.CreateOrthographicOffCenter(left, right, bottom, top, 0.0f, 1.0f); - CommandList.UpdateBuffer(ViewBuffer, 0, ViewMatrix); - - CommandList.SetFramebuffer(Surface.Swapchain.Framebuffer); - - // These commands differ from the stock Veldrid "Getting Started" - // tutorial in two ways. First, the viewport is cleared to pink - // instead of black so as to more easily distinguish between errors - // in creating a graphics context and errors drawing vertices within - // said context. Second, this project creates its swapchain with a - // depth buffer, and that buffer needs to be reset at the start of - // each frame. - - RgbaFloat bgColor = new(ovpSettings.backColor.R, ovpSettings.backColor.G, ovpSettings.backColor.B, 1.0f); - - CommandList.ClearColorTarget(0, bgColor); - CommandList.ClearDepthStencil(1.0f); - - drawGrid(); - drawAxes(); - drawLines(); - drawPolygons(); - - if (GridVertexBuffer != null) - { - lock (GridVertexBuffer) - { - try - { - CommandList.SetVertexBuffer(0, GridVertexBuffer); - CommandList.SetIndexBuffer(GridIndexBuffer, IndexFormat.UInt32); - CommandList.SetPipeline(LinePipeline); - CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); - CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); - - CommandList.DrawIndexed( - indexCount: (uint)gridIndices.Length, - instanceCount: 1, - indexStart: 0, - vertexOffset: 0, - instanceStart: 0); - } - catch (Exception ex) - { - Console.WriteLine("Ex: " + ex); - } - } - } - - if (AxesVertexBuffer != null) - { - lock (AxesVertexBuffer) - { - try - { - CommandList.SetVertexBuffer(0, AxesVertexBuffer); - CommandList.SetIndexBuffer(AxesIndexBuffer, IndexFormat.UInt32); - CommandList.SetPipeline(LinePipeline); - CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); - CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); - - CommandList.DrawIndexed( - indexCount: (uint)axesIndices.Length, - instanceCount: 1, - indexStart: 0, - vertexOffset: 0, - instanceStart: 0); - } - catch (Exception ex) - { - Console.WriteLine("Ex: " + ex); - } - } - } - - if (ovpSettings.drawFilled()) - { - if (TessVertexBuffer != null) - { - lock (TessVertexBuffer) - { - try - { - CommandList.SetVertexBuffer(0, TessVertexBuffer); - CommandList.SetPipeline(FilledPipeline); - CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); - CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); - - for (int l = 0; l < tessVertexCount.Length; l++) - { - CommandList.Draw(tessVertexCount[l], 1, tessFirst[l], 0); - } - } - catch (Exception ex) - { - Console.WriteLine("Ex: " + ex); - } - } - } - } - - if (PolysVertexBuffer != null) - { - lock (PolysVertexBuffer) - { - try - { - CommandList.SetVertexBuffer(0, PolysVertexBuffer); - CommandList.SetPipeline(LinesPipeline); - CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); - CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); - - for (int l = 0; l < polyVertexCount.Length; l++) - { - CommandList.Draw(polyVertexCount[l], 1, polyFirst[l], 0); - } - } - catch (Exception ex) - { - Console.WriteLine("Ex: " + ex); - } - } - } - - if (LinesVertexBuffer != null && ovpSettings.drawDrawn()) - { - lock (LinesVertexBuffer) - { - try - { - CommandList.SetVertexBuffer(0, LinesVertexBuffer); - CommandList.SetPipeline(LinesPipeline); - CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); - CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); - - for (int l = 0; l < lineVertexCount.Length; l++) - { - CommandList.Draw(lineVertexCount[l], 1, lineFirst[l], 0); - } - } - catch (Exception ex) - { - Console.WriteLine("Ex: " + ex); - } - } - } - - if (ovpSettings.drawPoints()) - { - if (PointsVertexBuffer != null) - { - lock (PointsVertexBuffer) - { - try - { - CommandList.SetVertexBuffer(0, PointsVertexBuffer); - CommandList.SetPipeline(FilledPipeline); - CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); - CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); - - foreach (uint t in pointsFirst) - { - CommandList.Draw(3, 1, t, 0); - } - } - catch (Exception ex) - { - Console.WriteLine("Ex: " + ex); - } - } - } - } - - CommandList.End(); - - try - { - lock (CommandList) - { - Surface.GraphicsDevice.SubmitCommands(CommandList); - } - - Surface.GraphicsDevice.SwapBuffers(Surface.Swapchain); - } - catch (Exception ex) - { - Console.WriteLine("Ex: " + ex); - } - - } - public void SetUpVeldrid() { CreateResources(); @@ -1556,25 +207,6 @@ private void CreateResources() CommandList = factory.CreateCommandList(); } - public void updateBuffer(ref DeviceBuffer buffer, T[] data, uint elementSize, BufferUsage usage) - where T : unmanaged - { - switch (data.Length) - { - case > 0: - { - buffer?.Dispose(); - - ResourceFactory factory = Surface.GraphicsDevice.ResourceFactory; - - buffer = factory.CreateBuffer(new BufferDescription(elementSize * (uint)data.Length, usage)); - - Surface.GraphicsDevice.UpdateBuffer(buffer, 0, data); - break; - } - } - } - private byte[] LoadSpirvBytes(ShaderStages stage) { string name = $"VertexColor-{stage.ToString().ToLowerInvariant()}.450.glsl"; diff --git a/src/Eto.VeldridSurface/VeldridDriver_Conversions.cs b/src/Eto.VeldridSurface/VeldridDriver_Conversions.cs new file mode 100644 index 0000000..f2b77de --- /dev/null +++ b/src/Eto.VeldridSurface/VeldridDriver_Conversions.cs @@ -0,0 +1,34 @@ +using Eto.Drawing; + +namespace TestEtoVeldrid2; + +public partial class VeldridDriver +{ + private Point WorldToScreen(float x, float y) + { + // int oX = (int)((x - ovpSettings.getCameraX() / (ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom())) + Surface.RenderWidth / 2); + + double oX_2 = (double)Surface.RenderWidth / 2; + double oX_3 = ovpSettings.getCameraX() / (ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom()); + double oX_4 = x; + + int oXC = (int)(oX_4 - oX_3 + oX_2); + + // int oY = (int)((y - ovpSettings.getCameraY() / (ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom())) + Surface.RenderHeight / 2); + + double oY_2 = (double)Surface.RenderHeight / 2; + double oY_3 = ovpSettings.getCameraY() / (ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom()); + double oY_4 = y; + + int oYC = (int)(oY_4 - oY_3 + oY_2); + + return new Point(oXC, oYC); + } + + private Size WorldToScreen(SizeF pt) + { + Point pt1 = WorldToScreen(0, 0); + Point pt2 = WorldToScreen(pt.Width, pt.Height); + return new Size(pt2.X - pt1.X, pt2.Y - pt1.Y); + } +} diff --git a/src/Eto.VeldridSurface/VeldridDriver_Draw.cs b/src/Eto.VeldridSurface/VeldridDriver_Draw.cs new file mode 100644 index 0000000..1ca8beb --- /dev/null +++ b/src/Eto.VeldridSurface/VeldridDriver_Draw.cs @@ -0,0 +1,687 @@ +using Eto.Drawing; +using System.Numerics; +using Veldrid; + +namespace TestEtoVeldrid2; + +public partial class VeldridDriver +{ + private void pUpdateViewport() + { + if ((!ovpSettings.changed) || (Surface.GraphicsDevice == null) || + (!Surface.Visible) || (Surface.Width <= 0) || (Surface.Height <= 0)) + { + return; + } + drawAxes(); + drawGrid(); + drawLines(); + drawPolygons(); + updateHostFunc?.Invoke(); + Surface.Invalidate(); + ovpSettings.changed = false; + } + private void drawPolygons() + { + int polyListCount = ovpSettings.polyList.Count; + int bgPolyListCount = ovpSettings.bgPolyList.Count; + int tessPolyListCount = ovpSettings.tessPolyList.Count; + + List polyList = new(); + + List pointsList = new(); + + List tessPolyList = new(); + + try + { + + // Carve our Z-space up to stack polygons + int numPolys = 1; + + numPolys = polyListCount + bgPolyListCount; + // Create our first and count arrays for the vertex indices, to enable polygon separation when rendering. + polyFirst = new uint[numPolys]; + polyVertexCount = new uint[numPolys]; + + tessFirst = new uint[tessPolyListCount]; + tessVertexCount = new uint[tessPolyListCount]; + + List tFirst = new(); + + uint tCounter = 0; + + if (ovpSettings.drawFilled()) + { + numPolys += tessPolyListCount; + } + + float + polyZStep = 1.0f / Math.Max(1, + numPolys + + 1); // avoid a div by zero risk; pad the poly number also to reduce risk of adding a poly beyond the clipping range + + int counter = 0; // vertex count that will be used to define 'first' index for each polygon. + int previouscounter = 0; // will be used to derive the number of vertices in each polygon. + + float polyZ = 0; + + if (ovpSettings.drawFilled()) + { + for (int poly = 0; poly < tessPolyListCount; poly++) + { + tessFirst[poly] = (uint)(poly * 3); + float alpha = ovpSettings.tessPolyList[poly].alpha; + polyZ += polyZStep; + for (int pt = 0; pt < 3; pt++) + { + tessPolyList.Add(new VertexPositionColor( + new Vector3(ovpSettings.tessPolyList[poly].poly[pt].X, + ovpSettings.tessPolyList[poly].poly[pt].Y, polyZ), + new RgbaFloat(ovpSettings.tessPolyList[poly].color.R, + ovpSettings.tessPolyList[poly].color.G, ovpSettings.tessPolyList[poly].color.B, + alpha))); + } + + tessVertexCount[poly] = 3; + } + } + + // Pondering options here - this would make a nice border construct around the filled geometry, amongst other things. + for (int poly = 0; poly < polyListCount; poly++) + { + float alpha = ovpSettings.polyList[poly].alpha; + if (ovpSettings.drawFilled()) + { + alpha = 1.0f; + } + + polyZ += polyZStep; + polyFirst[poly] = (uint)counter; + previouscounter = counter; + int polyLength = ovpSettings.polyList[poly].poly.Length - 1; + for (int pt = 0; pt < polyLength; pt++) + { + polyList.Add(new VertexPositionColor( + new Vector3(ovpSettings.polyList[poly].poly[pt].X, ovpSettings.polyList[poly].poly[pt].Y, + polyZ), + new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, + ovpSettings.polyList[poly].color.B, alpha))); + counter++; + polyList.Add(new VertexPositionColor( + new Vector3(ovpSettings.polyList[poly].poly[pt + 1].X, + ovpSettings.polyList[poly].poly[pt + 1].Y, polyZ), + new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, + ovpSettings.polyList[poly].color.B, alpha))); + counter++; + + if (!ovpSettings.drawPoints()) + { + continue; + } + + tFirst.Add(tCounter); + pointsList.Add(new VertexPositionColor( + new Vector3(ovpSettings.polyList[poly].poly[pt].X - pointWidth / 2.0f, + ovpSettings.polyList[poly].poly[pt].Y - pointWidth / 2.0f, 1.0f), + new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, + ovpSettings.polyList[poly].color.B, alpha))); + tCounter++; + pointsList.Add(new VertexPositionColor( + new Vector3(ovpSettings.polyList[poly].poly[pt].X - pointWidth / 2.0f, + ovpSettings.polyList[poly].poly[pt].Y + pointWidth / 2.0f, 1.0f), + new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, + ovpSettings.polyList[poly].color.B, alpha))); + tCounter++; + pointsList.Add(new VertexPositionColor( + new Vector3(ovpSettings.polyList[poly].poly[pt].X + pointWidth / 2.0f, + ovpSettings.polyList[poly].poly[pt].Y - pointWidth / 2.0f, 1.0f), + new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, + ovpSettings.polyList[poly].color.B, alpha))); + tCounter++; + + tFirst.Add(tCounter); + pointsList.Add(new VertexPositionColor( + new Vector3(ovpSettings.polyList[poly].poly[pt].X + pointWidth / 2.0f, + ovpSettings.polyList[poly].poly[pt].Y - pointWidth / 2.0f, 1.0f), + new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, + ovpSettings.polyList[poly].color.B, alpha))); + tCounter++; + pointsList.Add(new VertexPositionColor( + new Vector3(ovpSettings.polyList[poly].poly[pt].X - pointWidth / 2.0f, + ovpSettings.polyList[poly].poly[pt].Y + pointWidth / 2.0f, 1.0f), + new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, + ovpSettings.polyList[poly].color.B, alpha))); + tCounter++; + pointsList.Add(new VertexPositionColor( + new Vector3(ovpSettings.polyList[poly].poly[pt].X + pointWidth / 2.0f, + ovpSettings.polyList[poly].poly[pt].Y + pointWidth / 2.0f, 1.0f), + new RgbaFloat(ovpSettings.polyList[poly].color.R, ovpSettings.polyList[poly].color.G, + ovpSettings.polyList[poly].color.B, alpha))); + tCounter++; + } + + polyVertexCount[poly] = (uint)(counter - previouscounter); // set our vertex count for the polygon. + } + + polyZ = 0; + for (int poly = 0; poly < bgPolyListCount; poly++) + { + float alpha = ovpSettings.bgPolyList[poly].alpha; + polyZ += polyZStep; + polyFirst[poly + polyListCount] = (uint)counter; + previouscounter = counter; + + int bgPolyLength = ovpSettings.bgPolyList[poly].poly.Length - 1; + for (int pt = 0; pt < bgPolyLength; pt++) + { + polyList.Add(new VertexPositionColor( + new Vector3(ovpSettings.bgPolyList[poly].poly[pt].X, + ovpSettings.bgPolyList[poly].poly[pt].Y, polyZ), + new RgbaFloat(ovpSettings.bgPolyList[poly].color.R, ovpSettings.bgPolyList[poly].color.G, + ovpSettings.bgPolyList[poly].color.B, alpha))); + counter++; + polyList.Add(new VertexPositionColor( + new Vector3(ovpSettings.bgPolyList[poly].poly[pt + 1].X, + ovpSettings.bgPolyList[poly].poly[pt + 1].Y, polyZ), + new RgbaFloat(ovpSettings.bgPolyList[poly].color.R, ovpSettings.bgPolyList[poly].color.G, + ovpSettings.bgPolyList[poly].color.B, alpha))); + counter++; + } + + polyVertexCount[poly + polyListCount] = + (uint)(counter - previouscounter); // set our vertex count for the polygon. + } + + pointsFirst = tFirst.ToArray(); + } + catch (Exception) + { + // Can ignore - not critical. + } + + if (polyListCount > 0 || bgPolyListCount > 0) + { + updateBuffer(ref PolysVertexBuffer, polyList.ToArray(), VertexPositionColor.SizeInBytes, + BufferUsage.VertexBuffer); + } + + if (ovpSettings.drawPoints() && polyListCount > 0) + { + updateBuffer(ref PointsVertexBuffer, pointsList.ToArray(), VertexPositionColor.SizeInBytes, + BufferUsage.VertexBuffer); + } + + if (ovpSettings.drawFilled() && tessPolyListCount > 0) + { + updateBuffer(ref TessVertexBuffer, tessPolyList.ToArray(), VertexPositionColor.SizeInBytes, + BufferUsage.VertexBuffer); + } + } + + private void drawLines() + { + int tmp = ovpSettings.lineList.Count; + + switch (tmp) + { + // Create our first and count arrays for the vertex indices, to enable polygon separation when rendering. + case > 0: + { + List lineList = new(); + + // Carve our Z-space up to stack polygons + float polyZStep = 1.0f / ovpSettings.lineList.Count; + + lineFirst = new uint[tmp]; + lineVertexCount = new uint[tmp]; + + for (int poly = 0; poly < tmp; poly++) + { + float alpha = ovpSettings.lineList[poly].alpha; + float polyZ = poly * polyZStep; + lineFirst[poly] = (uint)lineList.Count; + lineList.AddRange(ovpSettings.lineList[poly].poly.Select(t => + new VertexPositionColor(new Vector3(t.X, t.Y, polyZ), + new RgbaFloat(ovpSettings.lineList[poly].color.R, ovpSettings.lineList[poly].color.G, + ovpSettings.lineList[poly].color.B, alpha)))); + lineVertexCount[poly] = + (uint)ovpSettings.lineList[poly].poly.Length; // set our vertex count for the polygon. + } + + updateBuffer(ref LinesVertexBuffer, lineList.ToArray(), VertexPositionColor.SizeInBytes, + BufferUsage.VertexBuffer); + break; + } + default: + LinesVertexBuffer = null; + break; + } + } + + private void drawGrid() + { + if (!ovpSettings.drawGrid()) + { + return; + } + + float spacing = ovpSettings.gridSpacing(); + if (ovpSettings.isGridDynamic()) + { + while (WorldToScreen(new SizeF(spacing, 0.0f)).Width > 12.0f) + { + spacing /= 10.0f; + } + + while (WorldToScreen(new SizeF(spacing, 0.0f)).Width < 4.0f) + { + spacing *= 10.0f; + } + } + + float zoom = ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom(); + float x = ovpSettings.getCameraX(); + float y = ovpSettings.getCameraY(); + + List grid = new(); + + if (WorldToScreen(new SizeF(spacing, 0.0f)).Width >= 4.0f) + { + int k = 0; + for (float i = 0; i > -(Surface.RenderWidth * zoom) + x; i -= spacing) + { + float r = 0.0f; + float g = 0.0f; + float b = 0.0f; + switch (k) + { + case <= 9: + r = ovpSettings.minorGridColor.R; + g = ovpSettings.minorGridColor.G; + b = ovpSettings.minorGridColor.B; + break; + case 10: + r = ovpSettings.majorGridColor.R; + g = ovpSettings.majorGridColor.G; + b = ovpSettings.majorGridColor.B; + k = 0; + break; + } + + k++; + grid.Add(new VertexPositionColor(new Vector3(i, y + zoom * Surface.RenderHeight, gridZ), + new RgbaFloat(r, g, b, 1.0f))); + grid.Add(new VertexPositionColor(new Vector3(i, y + zoom * -Surface.RenderHeight, gridZ), + new RgbaFloat(r, g, b, 1.0f))); + } + + k = 0; + for (float i = 0; i < Surface.RenderWidth * zoom + x; i += spacing) + { + float r = 0.0f; + float g = 0.0f; + float b = 0.0f; + switch (k) + { + case <= 9: + r = ovpSettings.minorGridColor.R; + g = ovpSettings.minorGridColor.G; + b = ovpSettings.minorGridColor.B; + break; + case 10: + r = ovpSettings.majorGridColor.R; + g = ovpSettings.majorGridColor.G; + b = ovpSettings.majorGridColor.B; + k = 0; + break; + } + + k++; + grid.Add(new VertexPositionColor(new Vector3(i, y + zoom * Surface.RenderHeight, gridZ), + new RgbaFloat(r, g, b, 1.0f))); + grid.Add(new VertexPositionColor(new Vector3(i, y + zoom * -Surface.RenderHeight, gridZ), + new RgbaFloat(r, g, b, 1.0f))); + } + + k = 0; + for (float i = 0; i > -(Surface.RenderHeight * zoom) + y; i -= spacing) + { + float r = 0.0f; + float g = 0.0f; + float b = 0.0f; + switch (k) + { + case <= 9: + r = ovpSettings.minorGridColor.R; + g = ovpSettings.minorGridColor.G; + b = ovpSettings.minorGridColor.B; + break; + case 10: + r = ovpSettings.majorGridColor.R; + g = ovpSettings.majorGridColor.G; + b = ovpSettings.majorGridColor.B; + k = 0; + break; + } + + k++; + grid.Add(new VertexPositionColor(new Vector3(x + zoom * Surface.RenderWidth, i, gridZ), + new RgbaFloat(r, g, b, 1.0f))); + grid.Add(new VertexPositionColor(new Vector3(x + zoom * -Surface.RenderWidth, i, gridZ), + new RgbaFloat(r, g, b, 1.0f))); + } + + k = 0; + for (float i = 0; i < Surface.RenderHeight * zoom + y; i += spacing) + { + float r = 0.0f; + float g = 0.0f; + float b = 0.0f; + switch (k) + { + case <= 9: + r = ovpSettings.minorGridColor.R; + g = ovpSettings.minorGridColor.G; + b = ovpSettings.minorGridColor.B; + break; + case 10: + r = ovpSettings.majorGridColor.R; + g = ovpSettings.majorGridColor.G; + b = ovpSettings.majorGridColor.B; + k = 0; + break; + } + + k++; + grid.Add(new VertexPositionColor(new Vector3(x + zoom * Surface.RenderWidth, i, gridZ), + new RgbaFloat(r, g, b, 1.0f))); + grid.Add(new VertexPositionColor(new Vector3(x + zoom * -Surface.RenderWidth, i, gridZ), + new RgbaFloat(r, g, b, 1.0f))); + } + } + + uint gridCount = (uint)grid.Count; + + switch (gridCount) + { + case > 0: + { + gridIndices = new uint[gridCount]; + for (uint i = 0; i < gridIndices.Length; i++) + { + gridIndices[i] = i; + } + + updateBuffer(ref GridVertexBuffer, grid.ToArray(), VertexPositionColor.SizeInBytes, + BufferUsage.VertexBuffer); + updateBuffer(ref GridIndexBuffer, gridIndices, sizeof(uint), BufferUsage.IndexBuffer); + break; + } + default: + GridVertexBuffer = null; + GridIndexBuffer = null; + break; + } + } + + private void drawAxes() + { + if (!ovpSettings.drawAxes()) + { + return; + } + + float zoom = ovpSettings.getBaseZoom() * ovpSettings.getZoomFactor(); + VertexPositionColor[] axesArray = new VertexPositionColor[4]; + axesArray[0] = + new VertexPositionColor( + new Vector3(0.0f, ovpSettings.getCameraY() + Surface.RenderHeight * zoom, axisZ), + new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); + axesArray[1] = + new VertexPositionColor( + new Vector3(0.0f, ovpSettings.getCameraY() - Surface.RenderHeight * zoom, axisZ), + new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); + axesArray[2] = + new VertexPositionColor(new Vector3(ovpSettings.getCameraX() + Surface.RenderWidth * zoom, 0.0f, axisZ), + new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); + axesArray[3] = + new VertexPositionColor(new Vector3(ovpSettings.getCameraX() - Surface.RenderWidth * zoom, 0.0f, axisZ), + new RgbaFloat(ovpSettings.axisColor.R, ovpSettings.axisColor.G, ovpSettings.axisColor.B, 1.0f)); + + axesIndices = new uint[4] { 0, 1, 2, 3 }; + + updateBuffer(ref AxesVertexBuffer, axesArray, VertexPositionColor.SizeInBytes, BufferUsage.VertexBuffer); + updateBuffer(ref AxesIndexBuffer, axesIndices, sizeof(uint), BufferUsage.IndexBuffer); + } + + public void Draw() + { + if (!Ready) + { + return; + } + + CommandList.Begin(); + + ModelMatrix *= Matrix4x4.CreateFromAxisAngle( + new Vector3(0, 0, 1), 0); + CommandList.UpdateBuffer(ModelBuffer, 0, ModelMatrix); + + float zoom = ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom(); + + float left = ovpSettings.getCameraX() - (float)Surface.RenderWidth / 2 * zoom; + float right = ovpSettings.getCameraX() + (float)Surface.RenderWidth / 2 * zoom; + float bottom = ovpSettings.getCameraY() + (float)Surface.RenderHeight / 2 * zoom; + float top = ovpSettings.getCameraY() - (float)Surface.RenderHeight / 2 * zoom; + + ViewMatrix = Matrix4x4.CreateOrthographicOffCenter(left, right, bottom, top, 0.0f, 1.0f); + CommandList.UpdateBuffer(ViewBuffer, 0, ViewMatrix); + + CommandList.SetFramebuffer(Surface.Swapchain.Framebuffer); + + // These commands differ from the stock Veldrid "Getting Started" + // tutorial in two ways. First, the viewport is cleared to pink + // instead of black so as to more easily distinguish between errors + // in creating a graphics context and errors drawing vertices within + // said context. Second, this project creates its swapchain with a + // depth buffer, and that buffer needs to be reset at the start of + // each frame. + + RgbaFloat bgColor = new(ovpSettings.backColor.R, ovpSettings.backColor.G, ovpSettings.backColor.B, 1.0f); + + CommandList.ClearColorTarget(0, bgColor); + CommandList.ClearDepthStencil(1.0f); + + drawGrid(); + drawAxes(); + drawLines(); + drawPolygons(); + + if (GridVertexBuffer != null) + { + lock (GridVertexBuffer) + { + try + { + CommandList.SetVertexBuffer(0, GridVertexBuffer); + CommandList.SetIndexBuffer(GridIndexBuffer, IndexFormat.UInt32); + CommandList.SetPipeline(LinePipeline); + CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); + CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); + + CommandList.DrawIndexed( + indexCount: (uint)gridIndices.Length, + instanceCount: 1, + indexStart: 0, + vertexOffset: 0, + instanceStart: 0); + } + catch (Exception ex) + { + Console.WriteLine("Ex: " + ex); + } + } + } + + if (AxesVertexBuffer != null) + { + lock (AxesVertexBuffer) + { + try + { + CommandList.SetVertexBuffer(0, AxesVertexBuffer); + CommandList.SetIndexBuffer(AxesIndexBuffer, IndexFormat.UInt32); + CommandList.SetPipeline(LinePipeline); + CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); + CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); + + CommandList.DrawIndexed( + indexCount: (uint)axesIndices.Length, + instanceCount: 1, + indexStart: 0, + vertexOffset: 0, + instanceStart: 0); + } + catch (Exception ex) + { + Console.WriteLine("Ex: " + ex); + } + } + } + + if (ovpSettings.drawFilled()) + { + if (TessVertexBuffer != null) + { + lock (TessVertexBuffer) + { + try + { + CommandList.SetVertexBuffer(0, TessVertexBuffer); + CommandList.SetPipeline(FilledPipeline); + CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); + CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); + + for (int l = 0; l < tessVertexCount.Length; l++) + { + CommandList.Draw(tessVertexCount[l], 1, tessFirst[l], 0); + } + } + catch (Exception ex) + { + Console.WriteLine("Ex: " + ex); + } + } + } + } + + if (PolysVertexBuffer != null) + { + lock (PolysVertexBuffer) + { + try + { + CommandList.SetVertexBuffer(0, PolysVertexBuffer); + CommandList.SetPipeline(LinesPipeline); + CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); + CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); + + for (int l = 0; l < polyVertexCount.Length; l++) + { + CommandList.Draw(polyVertexCount[l], 1, polyFirst[l], 0); + } + } + catch (Exception ex) + { + Console.WriteLine("Ex: " + ex); + } + } + } + + if (LinesVertexBuffer != null && ovpSettings.drawDrawn()) + { + lock (LinesVertexBuffer) + { + try + { + CommandList.SetVertexBuffer(0, LinesVertexBuffer); + CommandList.SetPipeline(LinesPipeline); + CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); + CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); + + for (int l = 0; l < lineVertexCount.Length; l++) + { + CommandList.Draw(lineVertexCount[l], 1, lineFirst[l], 0); + } + } + catch (Exception ex) + { + Console.WriteLine("Ex: " + ex); + } + } + } + + if (ovpSettings.drawPoints()) + { + if (PointsVertexBuffer != null) + { + lock (PointsVertexBuffer) + { + try + { + CommandList.SetVertexBuffer(0, PointsVertexBuffer); + CommandList.SetPipeline(FilledPipeline); + CommandList.SetGraphicsResourceSet(0, ViewMatrixSet); + CommandList.SetGraphicsResourceSet(1, ModelMatrixSet); + + foreach (uint t in pointsFirst) + { + CommandList.Draw(3, 1, t, 0); + } + } + catch (Exception ex) + { + Console.WriteLine("Ex: " + ex); + } + } + } + } + + CommandList.End(); + + try + { + lock (CommandList) + { + Surface.GraphicsDevice.SubmitCommands(CommandList); + } + + Surface.GraphicsDevice.SwapBuffers(Surface.Swapchain); + } + catch (Exception ex) + { + Console.WriteLine("Ex: " + ex); + } + + } + + private void updateBuffer(ref DeviceBuffer buffer, T[] data, uint elementSize, BufferUsage usage) + where T : unmanaged + { + switch (data.Length) + { + case > 0: + { + buffer?.Dispose(); + + ResourceFactory factory = Surface.GraphicsDevice.ResourceFactory; + + buffer = factory.CreateBuffer(new BufferDescription(elementSize * (uint)data.Length, usage)); + + Surface.GraphicsDevice.UpdateBuffer(buffer, 0, data); + break; + } + } + } +} diff --git a/src/Eto.VeldridSurface/VeldridDriver_Handlers.cs b/src/Eto.VeldridSurface/VeldridDriver_Handlers.cs new file mode 100644 index 0000000..11833d5 --- /dev/null +++ b/src/Eto.VeldridSurface/VeldridDriver_Handlers.cs @@ -0,0 +1,471 @@ +using Eto; +using Eto.Drawing; +using Eto.Forms; + +namespace TestEtoVeldrid2; + +public partial class VeldridDriver +{ + private void addKeyHandler(object sender, EventArgs e) + { + switch (keyHandlerApplied) + { + case true: + return; + default: + Surface.KeyDown += keyHandler; + keyHandlerApplied = true; + break; + } + } + + private void removeKeyHandler(object sender, EventArgs e) + { + switch (keyHandlerApplied) + { + case false: + return; + } + + hasFocus = false; + Surface.KeyDown -= keyHandler; + keyHandlerApplied = false; + } + + private void keyHandler(object sender, KeyEventArgs e) + { + //e.Handled = true; + + if (ovpSettings.isLocked()) + { + if (e.Key != Keys.F) + { + return; + } + } + + switch (e.Key) + { + case Keys.F: + ovpSettings.lockVP(!ovpSettings.isLocked()); + break; + case Keys.R: + reset(); + break; + } + + float stepping = 10.0f * ovpSettings.getZoomFactor(); + + bool doUpdate = true; + switch (e.Key) + { + case Keys.A: + panHorizontal(-stepping); + break; + case Keys.D: + panHorizontal(stepping); + break; + case Keys.W: + panVertical(stepping); + break; + case Keys.S: + panVertical(-stepping); + break; + case Keys.N: + zoomOut(-1); + break; + case Keys.M: + zoomIn(-1); + break; + case Keys.X: + zoomExtents(-1); + doUpdate = false; // update performed in extents + break; + case Keys.Z: + zoomExtents(ovpSettings.selectedIndex); + doUpdate = false; // update performed in extents + break; + } + + switch (doUpdate) + { + case true when Platform.Instance.IsGtk: + updateHostFunc?.Invoke(); + break; + case true: + updateViewport(); + break; + } + } + + private void zoomHandler(object sender, MouseEventArgs e) + { + if (!ovpSettings.isLocked()) + { + float wheelZoom = e.Delta.Height; // SystemInformation.MouseWheelScrollLines; + switch (wheelZoom) + { + case > 0: + zoomIn(wheelZoom); + break; + case < 0: + zoomOut(-wheelZoom); + break; + } + + updateViewport(); + } + + e.Handled = true; + } + + private void dragHandler(object sender, MouseEventArgs e) + { + if (!ovpSettings.isLocked()) + { + switch (e.Buttons) + { + case MouseButtons.Primary: + { + PointF scaledLocation = e.Location * Surface.ParentWindow.LogicalPixelSize; + + switch (dragging) + { + case false: + setDown(scaledLocation.X, scaledLocation.Y); + break; + } + + object locking = new(); + lock (locking) + { + float new_X = ovpSettings.getCameraX() - (scaledLocation.X - x_orig) * + ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom(); + float new_Y = ovpSettings.getCameraY() + (scaledLocation.Y - y_orig) * + ovpSettings.getZoomFactor() * ovpSettings.getBaseZoom(); + ovpSettings.setCameraPos(new_X, new_Y); + x_orig = scaledLocation.X; + y_orig = scaledLocation.Y; + } + + break; + } + } + + updateViewport(); + } + + e.Handled = true; + } + + private void upHandler(object sender, MouseEventArgs e) + { + switch (e.Buttons) + { + case MouseButtons.Alternate: + { + menu?.Show(Surface); + + break; + } + } + + if (ovpSettings.isLocked()) + { + return; + } + + dragging = e.Buttons switch + { + MouseButtons.Primary => false, + _ => dragging + }; + e.Handled = true; + } + + private void downHandler(object sender, MouseEventArgs e) + { + switch (e.Buttons) + { + case MouseButtons.Primary: + setDown(e.Location.X, e.Location.Y); + break; + } + + if (e.Buttons == MouseButtons.Middle || e.Modifiers == Keys.Control && e.Buttons == MouseButtons.Primary) + { + selectByClick(e.Location.X, e.Location.Y); + } + + e.Handled = true; + } + + private void setFocus(object sender, EventArgs e) + { + switch (hasFocus) + { + case true: + return; + default: + Surface.Focus(); + hasFocus = true; + break; + } + } + + private void Clock_Elapsed(object sender, EventArgs e) + { + pUpdateViewport(); + } + + private void addKeyHandlers() + { + try + { + Surface.MouseDown += downHandler; + Surface.MouseMove += dragHandler; + Surface.MouseUp += upHandler; + Surface.MouseWheel += zoomHandler; + Surface.GotFocus += addKeyHandler; + Surface.MouseEnter += addKeyHandler; // setFocus; + Surface.LostFocus += removeKeyHandler; + Surface.MouseLeave += removeKeyHandler; + } + catch (Exception ex) + { + Console.WriteLine("Ex: " + ex); + } + } + + private void setDown(float x, float y) + { + switch (dragging) + { + // might not be needed, but seemed like a safe approach to avoid re-setting these in a drag event. + case false when !ovpSettings.isLocked(): + x_orig = x; + y_orig = y; + dragging = true; + break; + } + } + + private void selectByClick(float x, float y) + { + /* + // Where did we click? + PointF scaledLocation = new(x, y); + scaledLocation = ScreenToWorld(scaledLocation.X * Surface.ParentWindow.LogicalPixelSize, scaledLocation.Y * Surface.ParentWindow.LogicalPixelSize); + + PointF cPos = ovpSettings.getCameraPos(); + + // Populate our tree. + int polyCount = ovpSettings.polyList.Count; + switch (polyCount) + { + case > 0: + { + double[] distances = new double[polyCount]; + int[] indices = new int[polyCount]; + ParallelOptions po = new(); + //Parallel.For(0, polyCount, po, (poly, loopstate) => + for (int poly = 0; poly < ovpSettings.polyList.Count; poly++) + { + KDTree pTree = new(2, ovpSettings.polyListPtCount[poly] + 1); // add one for the midpoint. + foreach (PointF t1 in ovpSettings.polyList[poly].poly) + { + PointF t = new(t1.X, t1.Y); + pTree.AddPoint(new double[] { t.X, t.Y }, t); + } + + double maxX = ovpSettings.polyList[poly].poly.Max(p => p.X); + double minX = ovpSettings.polyList[poly].poly.Min(p => p.X); + double maxY = ovpSettings.polyList[poly].poly.Max(p => p.Y); + double minY = ovpSettings.polyList[poly].poly.Min(p => p.Y); + + double deltaX = (maxX - minX) * 0.5f; + double deltaY = (maxY - minY) * 0.5f; + + PointF midPoint = new((float)(minX + deltaX), (float)(minY + deltaY)); + pTree.AddPoint(new double[] { midPoint.X, midPoint.Y }, midPoint); + + // '1' forces a single nearest neighbor to be returned. + NearestNeighbour pIter = pTree.NearestNeighbors(new double[] { scaledLocation.X, scaledLocation.Y }, 1); + while (pIter.MoveNext()) + { + distances[poly] = Math.Abs(pIter.CurrentDistance); + indices[poly] = ovpSettings.polySourceIndex[poly]; + } + } + //); + + int selIndex = indices[Array.IndexOf(distances, distances.Min())]; + + updateHostSelectionFunc?.Invoke(selIndex); + break; + } + default: + { + // Populate our tree. + int lineCount = ovpSettings.lineList.Count; + switch (lineCount) + { + case > 0: + { + double[] distances = new double[lineCount]; + int[] indices = new int[lineCount]; + ParallelOptions po = new(); + //Parallel.For(0, lineCount, po, (line, loopstate) => + for (int line = 0; line < ovpSettings.lineList.Count; line++) + { + KDTree pTree = new(2, ovpSettings.lineListPtCount[line] + 1); // add one for the midpoint. + foreach (PointF t1 in ovpSettings.lineList[line].poly) + { + PointF t = new(t1.X, t1.Y); + pTree.AddPoint(new double[] { t.X, t.Y }, t); + } + + double maxX = ovpSettings.lineList[line].poly.Max(p => p.X); + double minX = ovpSettings.lineList[line].poly.Min(p => p.X); + double maxY = ovpSettings.lineList[line].poly.Max(p => p.Y); + double minY = ovpSettings.lineList[line].poly.Min(p => p.Y); + + double deltaX = (maxX - minX) * 0.5f; + double deltaY = (maxY - minY) * 0.5f; + + PointF midPoint = new((float)(minX + deltaX), (float)(minY + deltaY)); + pTree.AddPoint(new double[] { midPoint.X, midPoint.Y }, midPoint); + + // '1' forces a single nearest neighbor to be returned. + NearestNeighbour pIter = pTree.NearestNeighbors(new double[] { scaledLocation.X, scaledLocation.Y }, 1); + while (pIter.MoveNext()) + { + distances[line] = Math.Abs(pIter.CurrentDistance); + indices[line] = ovpSettings.lineSourceIndex[line]; + } + } + //); + + int selIndex = indices[Array.IndexOf(distances, distances.Min())]; + + updateHostSelectionFunc?.Invoke(selIndex); + break; + } + } + + break; + } + } + */ + } + + private float calcZoom(float delta) + { + float f = Math.Abs(delta) * 0.1f; + f = delta switch + { + < 0 => 1.0f / f, + _ => f + }; + + return f; + } + + private void panVertical(float delta) + { + ovpSettings.setCameraY(ovpSettings.getCameraY() + delta / 10); + } + + private void panHorizontal(float delta) + { + ovpSettings.setCameraX(ovpSettings.getCameraX() + delta / 10); + } + + private void getExtents(int index) + { + float minX = 0; + float maxX = 0; + float minY = 0, maxY = 0; + + bool set = false; + + switch (ovpSettings.polyList.Count) + { + case 0 when ovpSettings.lineList.Count == 0: + ovpSettings.minX = 0; + ovpSettings.maxX = 0; + ovpSettings.minY = 0; + ovpSettings.maxY = 0; + return; + } + + if (ovpSettings.polyList.Count != 0) + { + for (int poly = 0; poly < ovpSettings.polyList.Count; poly++) + { + if (index != -1 && (ovpSettings.polySourceIndex[poly] != index || !ovpSettings.polyMask[poly])) + { + continue; + } + + switch (set) + { + case false: + minX = ovpSettings.polyList[poly].poly[0].X; + maxX = ovpSettings.polyList[poly].poly[0].X; + minY = ovpSettings.polyList[poly].poly[0].Y; + maxY = ovpSettings.polyList[poly].poly[0].Y; + set = true; + break; + } + + float tMinX = ovpSettings.polyList[poly].poly.Min(p => p.X); + float tMaxX = ovpSettings.polyList[poly].poly.Max(p => p.X); + float tMinY = ovpSettings.polyList[poly].poly.Min(p => p.Y); + float tMaxY = ovpSettings.polyList[poly].poly.Max(p => p.Y); + minX = Math.Min(minX, tMinX); + maxX = Math.Max(maxX, tMaxX); + minY = Math.Min(minY, tMinY); + maxY = Math.Max(maxY, tMaxY); + } + } + + if (ovpSettings.lineList.Count != 0) + { + for (int line = 0; line < ovpSettings.lineList.Count; line++) + { + if (index != -1 && (ovpSettings.lineSourceIndex[line] != index || !ovpSettings.lineMask[line])) + { + continue; + } + + switch (set) + { + case false: + minX = ovpSettings.lineList[line].poly[0].X; + maxX = ovpSettings.lineList[line].poly[0].X; + minY = ovpSettings.lineList[line].poly[0].Y; + maxY = ovpSettings.lineList[line].poly[0].Y; + set = true; + break; + } + + float tMinX = ovpSettings.lineList[line].poly.Min(p => p.X); + float tMaxX = ovpSettings.lineList[line].poly.Max(p => p.X); + float tMinY = ovpSettings.lineList[line].poly.Min(p => p.Y); + float tMaxY = ovpSettings.lineList[line].poly.Max(p => p.Y); + minX = Math.Min(minX, tMinX); + maxX = Math.Max(maxX, tMaxX); + minY = Math.Min(minY, tMinY); + maxY = Math.Max(maxY, tMaxY); + } + } + + ovpSettings.minX = minX; + ovpSettings.maxX = maxX; + ovpSettings.minY = minY; + ovpSettings.maxY = maxY; + + ovpSettings.changed = true; + } +} diff --git a/src/Eto.VeldridSurface/VeldridDriver_Public.cs b/src/Eto.VeldridSurface/VeldridDriver_Public.cs new file mode 100644 index 0000000..8fb64a7 --- /dev/null +++ b/src/Eto.VeldridSurface/VeldridDriver_Public.cs @@ -0,0 +1,134 @@ +using Eto.Drawing; +using Eto.Forms; +using VeldridEto; + +namespace TestEtoVeldrid2; + +public partial class VeldridDriver +{ + // This gets connected to the reference passed in, to allow easier updates from the client. + public OVPSettings ovpSettings; + + // Delegates to allow client to work with updates/selections. + public delegate void updateHost(); + + public updateHost updateHostFunc { get; set; } + + public delegate void updateHostSelection(int index); + + public updateHostSelection updateHostSelectionFunc { get; set; } + + // Clock is exposed to allow client side to enable automatic time-based updates + public UITimer Clock { get; } = new UITimer(); + + // Is saved location valid? + public bool savedLocation_valid { get; private set; } + + public void updateViewport() + { + pUpdateViewport(); + } + + public void setContextMenu(ref ContextMenu menu_) + { + menu = menu_; + } + + public void changeSettingsRef(ref OVPSettings newSettings) + { + ovpSettings = newSettings; + updateViewport(); + } + + public void saveLocation() + { + savedLocation = new PointF(ovpSettings.getCameraX(), ovpSettings.getCameraY()); + savedLocation_valid = true; + } + + public void zoomExtents(int index) + { + getExtents(index); + + if (ovpSettings.polyList.Count == 0 && ovpSettings.lineList.Count == 0 || + ovpSettings.minX == 0 && ovpSettings.maxX == 0 || + ovpSettings.minY == 0 && ovpSettings.maxY == 0) + { + reset(); + return; + } + + // Locate camera at center of the polygon field. + float dX = ovpSettings.maxX - ovpSettings.minX; + float dY = ovpSettings.maxY - ovpSettings.minY; + float cX = dX / 2.0f + ovpSettings.minX; + float cY = dY / 2.0f + ovpSettings.minY; + + // Now need to get the zoom level organized. + float zoomLevel_x = dX / Surface.Width; + float zoomLevel_y = dY / Surface.Height; + + if (zoomLevel_x > zoomLevel_y) + { + ovpSettings.setZoomFactor(zoomLevel_x / ovpSettings.getBaseZoom()); + } + else + { + ovpSettings.setZoomFactor(zoomLevel_y / ovpSettings.getBaseZoom()); + } + + goToLocation(cX, cY); + } + + public void loadLocation() + { + switch (savedLocation_valid) + { + case true: + ovpSettings.setCameraPos(savedLocation.X, savedLocation.Y); + updateViewport(); + break; + } + } + + public void goToLocation(float x, float y) + { + ovpSettings.setCameraPos(x, y); + updateViewport(); + } + + public void freeze_thaw() + { + ovpSettings.lockVP(!ovpSettings.isLocked()); + updateHostFunc?.Invoke(); + } + + public void zoomIn(float delta) + { + ovpSettings.setZoomFactor(ovpSettings.getZoomFactor() + ovpSettings.getZoomStep() * 0.01f * delta); + updateHostFunc?.Invoke(); + } + + public void zoomOut(float delta) + { + ovpSettings.setZoomFactor(ovpSettings.getZoomFactor() - ovpSettings.getZoomStep() * 0.01f * delta); + updateHostFunc?.Invoke(); + } + + public void fastZoomIn(float delta) + { + ovpSettings.setZoomFactor(ovpSettings.getZoomFactor() * calcZoom(delta)); + updateHostFunc?.Invoke(); + } + + public void fastZoomOut(float delta) + { + ovpSettings.setZoomFactor(ovpSettings.getZoomFactor() / calcZoom(delta)); + updateHostFunc?.Invoke(); + } + + public void reset() + { + ovpSettings.resetCamera(); + } +} diff --git a/src/Eto.VeldridSurface/VeldridDriver_Variables.cs b/src/Eto.VeldridSurface/VeldridDriver_Variables.cs new file mode 100644 index 0000000..af9592f --- /dev/null +++ b/src/Eto.VeldridSurface/VeldridDriver_Variables.cs @@ -0,0 +1,89 @@ +using Eto.Drawing; +using Eto.Forms; +using Eto.Veldrid; +using System.Numerics; +using Veldrid; + +namespace TestEtoVeldrid2; + +public partial class VeldridDriver +{ + // Core Veldrid stuff. This shouldn't need to be messed with + private VeldridSurface _surface; + + public VeldridSurface Surface + { + get + { + return _surface; + } + private set + { + _surface = value; + + Surface.Draw += (sender, e) => Draw(); + } + } + + private uint[] polyFirst; + private uint[] polyVertexCount; + private uint[] tessFirst; + private uint[] tessVertexCount; + private uint[] lineFirst; + private uint[] lineVertexCount; + private uint[] pointsFirst; + private uint[] gridIndices; + private uint[] axesIndices; + + private float axisZ; + private float gridZ; + + private DeviceBuffer GridVertexBuffer; + private DeviceBuffer GridIndexBuffer; + private DeviceBuffer AxesVertexBuffer; + private DeviceBuffer AxesIndexBuffer; + + private DeviceBuffer VertexBuffer { get; set; } + private DeviceBuffer IndexBuffer { get; set; } + private DeviceBuffer ModelBuffer { get; set; } + + private DeviceBuffer ViewBuffer; + + private DeviceBuffer LinesVertexBuffer; + private DeviceBuffer PointsVertexBuffer; + private DeviceBuffer PolysVertexBuffer; + private DeviceBuffer TessVertexBuffer; + + private Pipeline PointsPipeline; + private Pipeline LinePipeline; + private Pipeline LinesPipeline; + private Pipeline FilledPipeline; + + private Matrix4x4 ModelMatrix { get; set; } = Matrix4x4.Identity; + private Matrix4x4 ViewMatrix; + private ResourceSet ModelMatrixSet { get; set; } + + private ResourceSet ViewMatrixSet; + + private CommandList CommandList { get; set; } + + private Shader VertexShader { get; set; } + private Shader FragmentShader { get; set; } + + private bool Ready = false; + private PointF savedLocation; + + private const float pointWidth = 0.50f; + private bool hasFocus; + private bool keyHandlerApplied; + + // Use for drag handling. + private bool dragging { get; set; } + private float x_orig; + private float y_orig; + + private DateTime CurrentTime; + private DateTime PreviousTime = DateTime.Now; + + private ContextMenu menu; +} From 1985257dd5c24fe5a560eb0a0bffe2de6cfeb887 Mon Sep 17 00:00:00 2001 From: philstopford Date: Mon, 19 Feb 2024 13:21:25 -0600 Subject: [PATCH 19/24] More reorganization --- src/Eto.VeldridSurface/VeldridDriver.cs | 10 ++- src/Eto.VeldridSurface/VeldridDriver_Draw.cs | 71 +++++++++++++++----- 2 files changed, 62 insertions(+), 19 deletions(-) diff --git a/src/Eto.VeldridSurface/VeldridDriver.cs b/src/Eto.VeldridSurface/VeldridDriver.cs index b45372d..f94b20a 100644 --- a/src/Eto.VeldridSurface/VeldridDriver.cs +++ b/src/Eto.VeldridSurface/VeldridDriver.cs @@ -141,6 +141,14 @@ private void CreateResources() new VertexElementDescription("Color", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float4)); + create_pipelines(ref factory, ref viewMatrixLayout, ref modelMatrixLayout, ref shaders, ref vertexLayout); + + CommandList = factory.CreateCommandList(); + } + + private void create_pipelines(ref ResourceFactory factory, ref ResourceLayout viewMatrixLayout, + ref ResourceLayout modelMatrixLayout, ref Shader[] shaders, ref VertexLayoutDescription vertexLayout) + { LinePipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription { BlendState = BlendStateDescription.SingleOverrideBlend, @@ -203,8 +211,6 @@ private void CreateResources() shaders: shaders), Outputs = Surface.Swapchain.Framebuffer.OutputDescription }); - - CommandList = factory.CreateCommandList(); } private byte[] LoadSpirvBytes(ShaderStages stage) diff --git a/src/Eto.VeldridSurface/VeldridDriver_Draw.cs b/src/Eto.VeldridSurface/VeldridDriver_Draw.cs index 1ca8beb..731be1b 100644 --- a/src/Eto.VeldridSurface/VeldridDriver_Draw.cs +++ b/src/Eto.VeldridSurface/VeldridDriver_Draw.cs @@ -13,6 +13,7 @@ private void pUpdateViewport() { return; } + drawAxes(); drawGrid(); drawLines(); @@ -21,6 +22,7 @@ private void pUpdateViewport() Surface.Invalidate(); ovpSettings.changed = false; } + private void drawPolygons() { int polyListCount = ovpSettings.polyList.Count; @@ -493,6 +495,28 @@ public void Draw() CommandList.ClearColorTarget(0, bgColor); CommandList.ClearDepthStencil(1.0f); + populate_command_list(); + + CommandList.End(); + + try + { + lock (CommandList) + { + Surface.GraphicsDevice.SubmitCommands(CommandList); + } + + Surface.GraphicsDevice.SwapBuffers(Surface.Swapchain); + } + catch (Exception ex) + { + Console.WriteLine("Ex: " + ex); + } + + } + + private void populate_command_list() + { drawGrid(); drawAxes(); drawLines(); @@ -500,6 +524,11 @@ public void Draw() if (GridVertexBuffer != null) { + if (LinePipeline == null) + { + throw new("populate_command_list : LinePipeline not initialized!"); + } + lock (GridVertexBuffer) { try @@ -526,6 +555,11 @@ public void Draw() if (AxesVertexBuffer != null) { + if (LinePipeline == null) + { + throw new("populate_command_list : LinePipeline not initialized!"); + } + lock (AxesVertexBuffer) { try @@ -554,6 +588,11 @@ public void Draw() { if (TessVertexBuffer != null) { + if (LinePipeline == null) + { + throw new("populate_command_list : FilledPipeline not initialized!"); + } + lock (TessVertexBuffer) { try @@ -578,6 +617,11 @@ public void Draw() if (PolysVertexBuffer != null) { + if (LinePipeline == null) + { + throw new("populate_command_list : LinesPipeline not initialized!"); + } + lock (PolysVertexBuffer) { try @@ -601,6 +645,11 @@ public void Draw() if (LinesVertexBuffer != null && ovpSettings.drawDrawn()) { + if (LinePipeline == null) + { + throw new("populate_command_list : LinesPipeline not initialized!"); + } + lock (LinesVertexBuffer) { try @@ -626,6 +675,11 @@ public void Draw() { if (PointsVertexBuffer != null) { + if (LinePipeline == null) + { + throw new("populate_command_list : FilledPipeline not initialized!"); + } + lock (PointsVertexBuffer) { try @@ -647,23 +701,6 @@ public void Draw() } } } - - CommandList.End(); - - try - { - lock (CommandList) - { - Surface.GraphicsDevice.SubmitCommands(CommandList); - } - - Surface.GraphicsDevice.SwapBuffers(Surface.Swapchain); - } - catch (Exception ex) - { - Console.WriteLine("Ex: " + ex); - } - } private void updateBuffer(ref DeviceBuffer buffer, T[] data, uint elementSize, BufferUsage usage) From 62bdae1643e0b8f03680c17dc9840fec617a31e7 Mon Sep 17 00:00:00 2001 From: philstopford Date: Mon, 19 Feb 2024 13:41:16 -0600 Subject: [PATCH 20/24] Update MainForm.cs --- test/TestEtoVeldrid/MainForm.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/TestEtoVeldrid/MainForm.cs b/test/TestEtoVeldrid/MainForm.cs index 70ca385..a8983fa 100644 --- a/test/TestEtoVeldrid/MainForm.cs +++ b/test/TestEtoVeldrid/MainForm.cs @@ -81,10 +81,6 @@ public MainForm(GraphicsBackend backend) VeldridReady = true; }; - - // TODO: Make this binding actually work both ways. - //CmdAnimate.Bind("Checked", Driver, "Animate"); - //CmdClockwise.Bind("Checked", Driver, "Clockwise"); } private void addPolys() From b4f3bfc8e968718e898976b8016e6b2e29370e28 Mon Sep 17 00:00:00 2001 From: philstopford Date: Thu, 22 Feb 2024 09:41:35 -0600 Subject: [PATCH 21/24] Trying to find a workable keyboard handling approach --- .../VeldridDriver_Handlers.cs | 63 ++++++++----------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/src/Eto.VeldridSurface/VeldridDriver_Handlers.cs b/src/Eto.VeldridSurface/VeldridDriver_Handlers.cs index 11833d5..5871de8 100644 --- a/src/Eto.VeldridSurface/VeldridDriver_Handlers.cs +++ b/src/Eto.VeldridSurface/VeldridDriver_Handlers.cs @@ -6,34 +6,12 @@ namespace TestEtoVeldrid2; public partial class VeldridDriver { - private void addKeyHandler(object sender, EventArgs e) - { - switch (keyHandlerApplied) - { - case true: - return; - default: - Surface.KeyDown += keyHandler; - keyHandlerApplied = true; - break; - } - } - - private void removeKeyHandler(object sender, EventArgs e) + private void keyHandler(object sender, KeyEventArgs e) { - switch (keyHandlerApplied) + if (!hasFocus) { - case false: - return; + return; } - - hasFocus = false; - Surface.KeyDown -= keyHandler; - keyHandlerApplied = false; - } - - private void keyHandler(object sender, KeyEventArgs e) - { //e.Handled = true; if (ovpSettings.isLocked()) @@ -185,6 +163,10 @@ private void upHandler(object sender, MouseEventArgs e) private void downHandler(object sender, MouseEventArgs e) { + if (!hasFocus) + { + return; + } switch (e.Buttons) { case MouseButtons.Primary: @@ -202,15 +184,23 @@ private void downHandler(object sender, MouseEventArgs e) private void setFocus(object sender, EventArgs e) { - switch (hasFocus) + if (hasFocus) { - case true: - return; - default: - Surface.Focus(); - hasFocus = true; - break; + return; } + + Surface.Focus(); + hasFocus = true; + } + + private void removeFocus(object sender, EventArgs e) + { + if (!hasFocus) + { + return; + } + + hasFocus = false; } private void Clock_Elapsed(object sender, EventArgs e) @@ -226,10 +216,11 @@ private void addKeyHandlers() Surface.MouseMove += dragHandler; Surface.MouseUp += upHandler; Surface.MouseWheel += zoomHandler; - Surface.GotFocus += addKeyHandler; - Surface.MouseEnter += addKeyHandler; // setFocus; - Surface.LostFocus += removeKeyHandler; - Surface.MouseLeave += removeKeyHandler; + Surface.MouseEnter += setFocus; + Surface.MouseLeave += removeFocus; + Surface.KeyDown += keyHandler; + keyHandlerApplied = true; + // Surface.MouseLeave += removeKeyHandler; } catch (Exception ex) { From 4e8999592327854fed11a30d7fcea75f6726f164 Mon Sep 17 00:00:00 2001 From: philstopford Date: Mon, 26 Feb 2024 13:17:32 -0600 Subject: [PATCH 22/24] For some reason, the Surface can't grab focus Keyboard input therefore always goes to the textbox instead of the viewport. --- test/TestEtoVeldrid/MainForm.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/TestEtoVeldrid/MainForm.cs b/test/TestEtoVeldrid/MainForm.cs index a8983fa..f51afc3 100644 --- a/test/TestEtoVeldrid/MainForm.cs +++ b/test/TestEtoVeldrid/MainForm.cs @@ -68,7 +68,15 @@ public MainForm(GraphicsBackend backend) Surface = new VeldridSurface(backend, options); Surface.Size = new Eto.Drawing.Size(200, 200); - Content = Surface; + TableLayout tl = new(); + tl.Rows.Add(new()); + TextBox tb = new(); + tl.Rows[^1].Cells.Add(new() {Control = tb}); + + tl.Rows.Add(new() {ScaleHeight = true}); + tl.Rows[^1].Cells.Add(new() {Control = Surface}); + + Content = tl; ovpSettings = new OVPSettings(); addPolys(); From 0d48d9016ba2332ec244e097509da13faf329f3b Mon Sep 17 00:00:00 2001 From: Curtis Wensley Date: Wed, 3 Apr 2024 10:44:08 -0700 Subject: [PATCH 23/24] Get focus and events working on Gtk --- .vscode/launch.json | 2 +- .../GtkVeldridSurfaceHandler.cs | 21 +++++++++---------- .../Eto.VeldridSurface.csproj | 6 +----- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 9a5d503..3b85bb1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -14,7 +14,7 @@ "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Mac64/Debug/net5.0/osx-x64/TestEtoVeldrid.Mac64.app/Contents/MacOS/TestEtoVeldrid.Mac64" }, "linux": { - "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Gtk/Debug/net5.0/linux-x64/TestEtoVeldrid.Gtk.dll" + "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Gtk/Debug/net7.0/linux-x64/TestEtoVeldrid.Gtk.dll" }, "windows": { "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Wpf/Debug/net5.0-windows/win-x64/TestEtoVeldrid.Wpf.dll" diff --git a/src/Eto.Veldrid.Gtk/GtkVeldridSurfaceHandler.cs b/src/Eto.Veldrid.Gtk/GtkVeldridSurfaceHandler.cs index b9012b7..14e8134 100755 --- a/src/Eto.Veldrid.Gtk/GtkVeldridSurfaceHandler.cs +++ b/src/Eto.Veldrid.Gtk/GtkVeldridSurfaceHandler.cs @@ -10,7 +10,7 @@ namespace Eto.Veldrid.Gtk { - public class GtkVeldridSurfaceHandler : GtkControl, VeldridSurface.IHandler, VeldridSurface.IOpenGL + public class GtkVeldridSurfaceHandler : GtkControl, VeldridSurface.IHandler, VeldridSurface.IOpenGL { GLArea glArea; System.Action _makeCurrent; @@ -23,8 +23,6 @@ public class GtkVeldridSurfaceHandler : GtkControl + - - - ..\..\..\..\..\home\phil\.nuget\packages\veldrid.spirv\1.0.15\lib\netstandard2.0\Veldrid.SPIRV.dll - - From a88ba3dcd20f74a492a1d1a14b8270ca6a2bd013 Mon Sep 17 00:00:00 2001 From: Curtis Wensley Date: Mon, 17 Jun 2024 21:07:38 -0700 Subject: [PATCH 24/24] Updates to clean things up --- .github/workflows/build.yml | 38 +-- .vscode/launch.json | 23 +- .vscode/tasks.json | 84 ++----- Directory.Build.props | 7 +- Eto.Veldrid.sln | 123 ++++++++- src/Directory.Build.props | 9 + src/Eto.Veldrid.Gtk/Eto.Veldrid.Gtk.csproj | 11 +- .../GtkVeldridSurfaceHandler.cs | 20 +- src/Eto.Veldrid.Mac/Eto.Veldrid.Mac64.csproj | 3 +- src/Eto.Veldrid.Mac/Eto.Veldrid.macOS.csproj | 17 ++ .../MacVeldridSurfaceHandler.cs | 19 +- src/Eto.Veldrid.Mac/MacVeldridView.cs | 6 +- .../Eto.Veldrid.WinForms.csproj | 23 +- .../WinFormsVeldridSurfaceHandler.cs | 14 +- src/Eto.Veldrid.Wpf/Eto.Veldrid.Wpf.csproj | 25 +- .../ManualBubbleWindowsFormsHostHandler.cs | 28 +-- .../WpfVeldridSurfaceHandler.cs | 10 +- src/Eto.Veldrid/Eto.Veldrid.csproj | 21 +- src/Eto.Veldrid/VeldridSurface.cs | 6 +- .../Eto.VeldridSurface.csproj | 24 -- src/Eto.VeldridSurface/VeldridDriver.cs | 234 ------------------ .../TestEtoVeldrid.Gtk.csproj | 9 +- test/TestEtoVeldrid.Mac/Info.plist | 2 +- .../TestEtoVeldrid.Mac64.csproj | 11 +- .../TestEtoVeldrid.macOS.csproj | 24 ++ test/TestEtoVeldrid.WinForms/Program.cs | 2 +- .../TestEtoVeldrid.WinForms.csproj | 15 +- .../TestEtoVeldrid.Wpf.csproj | 20 +- test/TestEtoVeldrid/MainForm.cs | 4 - .../TestEtoVeldrid}/OVPSettings.cs | 8 +- test/TestEtoVeldrid/TestEtoVeldrid.csproj | 9 +- test/TestEtoVeldrid/VeldridDriver.cs | 232 +++++++++++++++++ .../VeldridDriver_Conversions.cs | 2 +- .../TestEtoVeldrid}/VeldridDriver_Draw.cs | 2 +- .../TestEtoVeldrid}/VeldridDriver_Handlers.cs | 3 +- .../TestEtoVeldrid}/VeldridDriver_Public.cs | 3 +- .../VeldridDriver_Variables.cs | 10 +- .../TestEtoVeldrid}/ovp_Poly.cs | 4 +- .../shaders/VertexColor-fragment.450.glsl | 0 .../shaders/VertexColor-vertex.450.glsl | 0 40 files changed, 555 insertions(+), 550 deletions(-) create mode 100755 src/Directory.Build.props create mode 100755 src/Eto.Veldrid.Mac/Eto.Veldrid.macOS.csproj mode change 100644 => 100755 src/Eto.Veldrid.Mac/MacVeldridView.cs mode change 100644 => 100755 src/Eto.Veldrid.Wpf/ManualBubbleWindowsFormsHostHandler.cs delete mode 100644 src/Eto.VeldridSurface/Eto.VeldridSurface.csproj delete mode 100644 src/Eto.VeldridSurface/VeldridDriver.cs create mode 100644 test/TestEtoVeldrid.Mac/TestEtoVeldrid.macOS.csproj mode change 100644 => 100755 test/TestEtoVeldrid.WinForms/Program.cs mode change 100644 => 100755 test/TestEtoVeldrid.WinForms/TestEtoVeldrid.WinForms.csproj mode change 100644 => 100755 test/TestEtoVeldrid.Wpf/TestEtoVeldrid.Wpf.csproj mode change 100644 => 100755 test/TestEtoVeldrid/MainForm.cs rename {src/Eto.VeldridSurface => test/TestEtoVeldrid}/OVPSettings.cs (98%) mode change 100644 => 100755 mode change 100644 => 100755 test/TestEtoVeldrid/TestEtoVeldrid.csproj create mode 100755 test/TestEtoVeldrid/VeldridDriver.cs rename {src/Eto.VeldridSurface => test/TestEtoVeldrid}/VeldridDriver_Conversions.cs (97%) mode change 100644 => 100755 rename {src/Eto.VeldridSurface => test/TestEtoVeldrid}/VeldridDriver_Draw.cs (99%) mode change 100644 => 100755 rename {src/Eto.VeldridSurface => test/TestEtoVeldrid}/VeldridDriver_Handlers.cs (99%) mode change 100644 => 100755 rename {src/Eto.VeldridSurface => test/TestEtoVeldrid}/VeldridDriver_Public.cs (98%) mode change 100644 => 100755 rename {src/Eto.VeldridSurface => test/TestEtoVeldrid}/VeldridDriver_Variables.cs (89%) mode change 100644 => 100755 rename {src/Eto.VeldridSurface => test/TestEtoVeldrid}/ovp_Poly.cs (93%) mode change 100644 => 100755 rename {src/Eto.VeldridSurface => test/TestEtoVeldrid}/shaders/VertexColor-fragment.450.glsl (100%) mode change 100644 => 100755 rename {src/Eto.VeldridSurface => test/TestEtoVeldrid}/shaders/VertexColor-vertex.450.glsl (100%) mode change 100644 => 100755 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9d823ad..5dde800 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,20 +22,23 @@ jobs: PlatformBuildParameters: /p:Platform=Windows steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET Core - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v4 with: - dotnet-version: '5.0.x' + dotnet-version: '8.0.x' - - uses: actions/cache@v1 + - uses: actions/cache@v4 with: path: ~/.nuget/packages key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} restore-keys: | ${{ runner.os }}-nuget- + - name: Install macos workload + run: dotnet workload install macos + - name: Build run: dotnet build ${{ env.PlatformBuildParameters }} ${{ env.BuildParameters }} @@ -43,7 +46,7 @@ jobs: run: dotnet pack ${{ env.PlatformBuildParameters }} ${{ env.BuildParameters }} - name: Upload artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: nuget path: artifacts/nuget/**/*.nupkg @@ -56,27 +59,28 @@ jobs: PlatformBuildParameters: /p:Platform=Mac steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup .NET Core - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v4 with: - dotnet-version: '5.0.x' + dotnet-version: '8.0.x' - - name: setup-xamarin - uses: maxim-lobanov/setup-xamarin@v1 + - name: Setup XCode + uses: maxim-lobanov/setup-xcode@v1 with: - mono-version: latest - xamarin-mac-version: latest - xcode-version: latest + xcode-version: latest-stable - - uses: actions/cache@v1 + - uses: actions/cache@v4 with: path: ~/.nuget/packages key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} restore-keys: | ${{ runner.os }}-nuget- + - name: Install macos workload + run: dotnet workload install macos + - name: Build run: dotnet build ${{ env.PlatformBuildParameters }} ${{ env.BuildParameters }} @@ -84,7 +88,7 @@ jobs: run: dotnet pack ${{ env.PlatformBuildParameters }} ${{ env.BuildParameters }} # - name: Upload artifacts -# uses: actions/upload-artifact@v2 +# uses: actions/upload-artifact@v4 # with: # name: nuget # path: artifacts/nuget/**/Eto.Veldrid.XamMac2.nupkg @@ -95,10 +99,10 @@ jobs: if: github.event_name == 'release' && github.event.action == 'published' steps: - name: Setup .NET Core - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v4 - name: Download NuGet Packages - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v4 with: name: nuget diff --git a/.vscode/launch.json b/.vscode/launch.json index 3b85bb1..ef810ad 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,34 +11,31 @@ "preLaunchTask": "build", "program": "", "osx": { - "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Mac64/Debug/net5.0/osx-x64/TestEtoVeldrid.Mac64.app/Contents/MacOS/TestEtoVeldrid.Mac64" + "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Mac64/Debug/net8.0/TestEtoVeldrid.Mac64.app/Contents/MacOS/TestEtoVeldrid.Mac64" }, "linux": { - "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Gtk/Debug/net7.0/linux-x64/TestEtoVeldrid.Gtk.dll" + "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Gtk/Debug/net8.0/linux-x64/TestEtoVeldrid.Gtk.dll" }, "windows": { - "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Wpf/Debug/net5.0-windows/win-x64/TestEtoVeldrid.Wpf.dll" + "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Wpf/Debug/net8.0-windows/win-x64/TestEtoVeldrid.Wpf.dll" }, "console": "internalConsole", "stopAtEntry": false }, { - "name": "Launch Mono", - "type": "mono", + "name": "Launch macOS", + "type": "coreclr", "request": "launch", "preLaunchTask": "build", "program": "", "osx": { - "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Mac64/Debug/net48/osx-x64/TestEtoVeldrid.Mac64.app/Contents/MacOS/TestEtoVeldrid.Mac64", - "useRuntime": false - }, - "linux": { - "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.Gtk/Debug/net48/linux-x64/TestEtoVeldrid.Gtk.exe" + "program": "${workspaceFolder}/artifacts/bin/TestEtoVeldrid.macOS/Debug/net8.0-macos/TestEtoVeldrid.macOS.app/Contents/MacOS/TestEtoVeldrid.macOS" }, - "console": "internalConsole" + "console": "internalConsole", + "stopAtEntry": false }, { - "name": "Launch .NET (WPF)", + "name": "Launch WPF - net48", "type": "clr", "request": "launch", "preLaunchTask": "build", @@ -49,7 +46,7 @@ "console": "internalConsole" }, { - "name": "Launch .NET (WinForms)", + "name": "Launch WinForms - net48", "type": "clr", "request": "launch", "preLaunchTask": "build", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 10d70b6..3159249 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -5,73 +5,35 @@ "label": "build", "command": "dotnet", "type": "shell", - "osx": { - "args": [ - "build", - "${workspaceFolder}/Eto.Veldrid.sln", - "/p:Platform=Mac", - "/p:Configuration=${input:configuration}", - "/p:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], + "args": [ + "build", + "${workspaceFolder}/Eto.Veldrid.sln", + "/p:Configuration=${input:configuration}", + "/p:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile", + "presentation": { + "reveal": "always", + "clear": true }, - "linux": { - "args": [ - "build", - "${workspaceFolder}/Eto.Veldrid.sln", - "/p:Platform=Mac", - "/p:Configuration=${input:configuration}", - "/p:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - }, - "windows": { - "args": [ - "build", - "${workspaceFolder}/Eto.Veldrid.sln", - "/p:Platform=Windows", - "/p:Configuration=${input:configuration}", - "/p:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - }, - "problemMatcher": "$msCompile" }, { "label": "Pack", "command": "dotnet", "type": "process", - "osx": { - "args": [ - "pack", - "${workspaceFolder}/Eto.Veldrid.sln", - "/p:Platform=Mac", - "/p:Configuration=${input:configuration}", - "/p:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ] - }, - "linux": { - "args": [ - "pack", - "${workspaceFolder}/Eto.Veldrid.sln", - "/p:Platform=Mac", - "/p:Configuration=${input:configuration}", - "/p:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ] - }, - "windows": { - "args": [ - "pack", - "${workspaceFolder}/Eto.Veldrid.sln", - "/p:Platform=Windows", - "/p:Configuration=${input:configuration}", - "/p:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ] + "args": [ + "pack", + "${workspaceFolder}/Eto.Veldrid.sln", + "/p:Configuration=${input:configuration}", + "/p:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile", + "presentation": { + "reveal": "always", + "clear": true }, - "problemMatcher": "$msCompile" } ], "inputs": [ @@ -86,4 +48,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/Directory.Build.props b/Directory.Build.props index 47abf29..bc4c695 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -8,6 +8,11 @@ + enable + 10.0 + + true + https://www.myget.org/F/eto/ $(MSBuildThisFileDirectory) @@ -28,7 +33,7 @@ - 0.1.0 + 0.2.0 $(BuildBranch.Substring(10)) diff --git a/Eto.Veldrid.sln b/Eto.Veldrid.sln index 8dbb54f..5f30d4f 100644 --- a/Eto.Veldrid.sln +++ b/Eto.Veldrid.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.28803.156 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.35004.147 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Eto.Veldrid", "src\Eto.Veldrid\Eto.Veldrid.csproj", "{72B9021E-5D60-4494-8C19-96EA28F1154E}" EndProject @@ -34,96 +34,194 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestEtoVeldrid.Wpf", "test\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestEtoVeldrid", "test\TestEtoVeldrid\TestEtoVeldrid.csproj", "{14AFF269-5C00-4E7A-8528-4DA704B7D2F4}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Eto.VeldridSurface", "src\Eto.VeldridSurface\Eto.VeldridSurface.csproj", "{AB712D06-69EA-4601-A9B3-774820B56633}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Eto.Veldrid.macOS", "src\Eto.Veldrid.Mac\Eto.Veldrid.macOS.csproj", "{B5532B13-B15D-4987-81E5-7AEBC18CDED0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestEtoVeldrid.macOS", "test\TestEtoVeldrid.Mac\TestEtoVeldrid.macOS.csproj", "{63B74346-2B72-429F-AA2C-BD4CA09CD0E5}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Linux = Debug|Linux Debug|Mac = Debug|Mac Debug|Windows = Debug|Windows + Release|Any CPU = Release|Any CPU + Release|Linux = Release|Linux Release|Mac = Release|Mac Release|Windows = Release|Windows EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {72B9021E-5D60-4494-8C19-96EA28F1154E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72B9021E-5D60-4494-8C19-96EA28F1154E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72B9021E-5D60-4494-8C19-96EA28F1154E}.Debug|Linux.ActiveCfg = Debug|Any CPU + {72B9021E-5D60-4494-8C19-96EA28F1154E}.Debug|Linux.Build.0 = Debug|Any CPU {72B9021E-5D60-4494-8C19-96EA28F1154E}.Debug|Mac.ActiveCfg = Debug|Any CPU {72B9021E-5D60-4494-8C19-96EA28F1154E}.Debug|Mac.Build.0 = Debug|Any CPU {72B9021E-5D60-4494-8C19-96EA28F1154E}.Debug|Windows.ActiveCfg = Debug|Any CPU {72B9021E-5D60-4494-8C19-96EA28F1154E}.Debug|Windows.Build.0 = Debug|Any CPU + {72B9021E-5D60-4494-8C19-96EA28F1154E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72B9021E-5D60-4494-8C19-96EA28F1154E}.Release|Any CPU.Build.0 = Release|Any CPU + {72B9021E-5D60-4494-8C19-96EA28F1154E}.Release|Linux.ActiveCfg = Release|Any CPU + {72B9021E-5D60-4494-8C19-96EA28F1154E}.Release|Linux.Build.0 = Release|Any CPU {72B9021E-5D60-4494-8C19-96EA28F1154E}.Release|Mac.ActiveCfg = Release|Any CPU {72B9021E-5D60-4494-8C19-96EA28F1154E}.Release|Mac.Build.0 = Release|Any CPU {72B9021E-5D60-4494-8C19-96EA28F1154E}.Release|Windows.ActiveCfg = Release|Any CPU {72B9021E-5D60-4494-8C19-96EA28F1154E}.Release|Windows.Build.0 = Release|Any CPU + {280A06EE-3A6C-422F-B303-040F90EA4B3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {280A06EE-3A6C-422F-B303-040F90EA4B3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {280A06EE-3A6C-422F-B303-040F90EA4B3B}.Debug|Linux.ActiveCfg = Debug|Any CPU + {280A06EE-3A6C-422F-B303-040F90EA4B3B}.Debug|Linux.Build.0 = Debug|Any CPU {280A06EE-3A6C-422F-B303-040F90EA4B3B}.Debug|Mac.ActiveCfg = Debug|Any CPU {280A06EE-3A6C-422F-B303-040F90EA4B3B}.Debug|Mac.Build.0 = Debug|Any CPU {280A06EE-3A6C-422F-B303-040F90EA4B3B}.Debug|Windows.ActiveCfg = Debug|Any CPU {280A06EE-3A6C-422F-B303-040F90EA4B3B}.Debug|Windows.Build.0 = Debug|Any CPU + {280A06EE-3A6C-422F-B303-040F90EA4B3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {280A06EE-3A6C-422F-B303-040F90EA4B3B}.Release|Any CPU.Build.0 = Release|Any CPU + {280A06EE-3A6C-422F-B303-040F90EA4B3B}.Release|Linux.ActiveCfg = Release|Any CPU + {280A06EE-3A6C-422F-B303-040F90EA4B3B}.Release|Linux.Build.0 = Release|Any CPU {280A06EE-3A6C-422F-B303-040F90EA4B3B}.Release|Mac.ActiveCfg = Release|Any CPU {280A06EE-3A6C-422F-B303-040F90EA4B3B}.Release|Mac.Build.0 = Release|Any CPU {280A06EE-3A6C-422F-B303-040F90EA4B3B}.Release|Windows.ActiveCfg = Release|Any CPU {280A06EE-3A6C-422F-B303-040F90EA4B3B}.Release|Windows.Build.0 = Release|Any CPU + {E8C6995B-791B-449A-A9B9-AEA2047FAA1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E8C6995B-791B-449A-A9B9-AEA2047FAA1E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E8C6995B-791B-449A-A9B9-AEA2047FAA1E}.Debug|Linux.ActiveCfg = Debug|Any CPU + {E8C6995B-791B-449A-A9B9-AEA2047FAA1E}.Debug|Linux.Build.0 = Debug|Any CPU {E8C6995B-791B-449A-A9B9-AEA2047FAA1E}.Debug|Mac.ActiveCfg = Debug|Any CPU {E8C6995B-791B-449A-A9B9-AEA2047FAA1E}.Debug|Mac.Build.0 = Debug|Any CPU {E8C6995B-791B-449A-A9B9-AEA2047FAA1E}.Debug|Windows.ActiveCfg = Debug|Any CPU {E8C6995B-791B-449A-A9B9-AEA2047FAA1E}.Debug|Windows.Build.0 = Debug|Any CPU + {E8C6995B-791B-449A-A9B9-AEA2047FAA1E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E8C6995B-791B-449A-A9B9-AEA2047FAA1E}.Release|Any CPU.Build.0 = Release|Any CPU + {E8C6995B-791B-449A-A9B9-AEA2047FAA1E}.Release|Linux.ActiveCfg = Release|Any CPU + {E8C6995B-791B-449A-A9B9-AEA2047FAA1E}.Release|Linux.Build.0 = Release|Any CPU {E8C6995B-791B-449A-A9B9-AEA2047FAA1E}.Release|Mac.ActiveCfg = Release|Any CPU {E8C6995B-791B-449A-A9B9-AEA2047FAA1E}.Release|Mac.Build.0 = Release|Any CPU {E8C6995B-791B-449A-A9B9-AEA2047FAA1E}.Release|Windows.ActiveCfg = Release|Any CPU {E8C6995B-791B-449A-A9B9-AEA2047FAA1E}.Release|Windows.Build.0 = Release|Any CPU + {748ABF6C-F3E3-4872-8746-627ABFA7D322}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {748ABF6C-F3E3-4872-8746-627ABFA7D322}.Debug|Any CPU.Build.0 = Debug|Any CPU + {748ABF6C-F3E3-4872-8746-627ABFA7D322}.Debug|Linux.ActiveCfg = Debug|Any CPU {748ABF6C-F3E3-4872-8746-627ABFA7D322}.Debug|Mac.ActiveCfg = Debug|Any CPU {748ABF6C-F3E3-4872-8746-627ABFA7D322}.Debug|Windows.ActiveCfg = Debug|Any CPU {748ABF6C-F3E3-4872-8746-627ABFA7D322}.Debug|Windows.Build.0 = Debug|Any CPU + {748ABF6C-F3E3-4872-8746-627ABFA7D322}.Release|Any CPU.ActiveCfg = Release|Any CPU + {748ABF6C-F3E3-4872-8746-627ABFA7D322}.Release|Any CPU.Build.0 = Release|Any CPU + {748ABF6C-F3E3-4872-8746-627ABFA7D322}.Release|Linux.ActiveCfg = Release|Any CPU {748ABF6C-F3E3-4872-8746-627ABFA7D322}.Release|Mac.ActiveCfg = Release|Any CPU {748ABF6C-F3E3-4872-8746-627ABFA7D322}.Release|Windows.ActiveCfg = Release|Any CPU {748ABF6C-F3E3-4872-8746-627ABFA7D322}.Release|Windows.Build.0 = Release|Any CPU + {2B8EAE29-7D66-4C15-918E-A7C2ED97F040}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2B8EAE29-7D66-4C15-918E-A7C2ED97F040}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2B8EAE29-7D66-4C15-918E-A7C2ED97F040}.Debug|Linux.ActiveCfg = Debug|Any CPU {2B8EAE29-7D66-4C15-918E-A7C2ED97F040}.Debug|Mac.ActiveCfg = Debug|Any CPU {2B8EAE29-7D66-4C15-918E-A7C2ED97F040}.Debug|Windows.ActiveCfg = Debug|Any CPU {2B8EAE29-7D66-4C15-918E-A7C2ED97F040}.Debug|Windows.Build.0 = Debug|Any CPU + {2B8EAE29-7D66-4C15-918E-A7C2ED97F040}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2B8EAE29-7D66-4C15-918E-A7C2ED97F040}.Release|Any CPU.Build.0 = Release|Any CPU + {2B8EAE29-7D66-4C15-918E-A7C2ED97F040}.Release|Linux.ActiveCfg = Release|Any CPU {2B8EAE29-7D66-4C15-918E-A7C2ED97F040}.Release|Mac.ActiveCfg = Release|Any CPU {2B8EAE29-7D66-4C15-918E-A7C2ED97F040}.Release|Windows.ActiveCfg = Release|Any CPU {2B8EAE29-7D66-4C15-918E-A7C2ED97F040}.Release|Windows.Build.0 = Release|Any CPU + {AB71CC3A-A9A4-4EA0-96FB-16036E92BBC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB71CC3A-A9A4-4EA0-96FB-16036E92BBC9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB71CC3A-A9A4-4EA0-96FB-16036E92BBC9}.Debug|Linux.ActiveCfg = Debug|Any CPU + {AB71CC3A-A9A4-4EA0-96FB-16036E92BBC9}.Debug|Linux.Build.0 = Debug|Any CPU {AB71CC3A-A9A4-4EA0-96FB-16036E92BBC9}.Debug|Mac.ActiveCfg = Debug|Any CPU {AB71CC3A-A9A4-4EA0-96FB-16036E92BBC9}.Debug|Mac.Build.0 = Debug|Any CPU {AB71CC3A-A9A4-4EA0-96FB-16036E92BBC9}.Debug|Windows.ActiveCfg = Debug|Any CPU {AB71CC3A-A9A4-4EA0-96FB-16036E92BBC9}.Debug|Windows.Build.0 = Debug|Any CPU + {AB71CC3A-A9A4-4EA0-96FB-16036E92BBC9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB71CC3A-A9A4-4EA0-96FB-16036E92BBC9}.Release|Any CPU.Build.0 = Release|Any CPU + {AB71CC3A-A9A4-4EA0-96FB-16036E92BBC9}.Release|Linux.ActiveCfg = Release|Any CPU + {AB71CC3A-A9A4-4EA0-96FB-16036E92BBC9}.Release|Linux.Build.0 = Release|Any CPU {AB71CC3A-A9A4-4EA0-96FB-16036E92BBC9}.Release|Mac.ActiveCfg = Release|Any CPU {AB71CC3A-A9A4-4EA0-96FB-16036E92BBC9}.Release|Mac.Build.0 = Release|Any CPU {AB71CC3A-A9A4-4EA0-96FB-16036E92BBC9}.Release|Windows.ActiveCfg = Release|Any CPU {AB71CC3A-A9A4-4EA0-96FB-16036E92BBC9}.Release|Windows.Build.0 = Release|Any CPU + {6AF05698-3D64-4FA5-B9DE-CCA2C2DD9CA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6AF05698-3D64-4FA5-B9DE-CCA2C2DD9CA1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6AF05698-3D64-4FA5-B9DE-CCA2C2DD9CA1}.Debug|Linux.ActiveCfg = Debug|Any CPU + {6AF05698-3D64-4FA5-B9DE-CCA2C2DD9CA1}.Debug|Linux.Build.0 = Debug|Any CPU {6AF05698-3D64-4FA5-B9DE-CCA2C2DD9CA1}.Debug|Mac.ActiveCfg = Debug|Any CPU {6AF05698-3D64-4FA5-B9DE-CCA2C2DD9CA1}.Debug|Mac.Build.0 = Debug|Any CPU {6AF05698-3D64-4FA5-B9DE-CCA2C2DD9CA1}.Debug|Windows.ActiveCfg = Debug|Any CPU {6AF05698-3D64-4FA5-B9DE-CCA2C2DD9CA1}.Debug|Windows.Build.0 = Debug|Any CPU + {6AF05698-3D64-4FA5-B9DE-CCA2C2DD9CA1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6AF05698-3D64-4FA5-B9DE-CCA2C2DD9CA1}.Release|Any CPU.Build.0 = Release|Any CPU + {6AF05698-3D64-4FA5-B9DE-CCA2C2DD9CA1}.Release|Linux.ActiveCfg = Release|Any CPU + {6AF05698-3D64-4FA5-B9DE-CCA2C2DD9CA1}.Release|Linux.Build.0 = Release|Any CPU {6AF05698-3D64-4FA5-B9DE-CCA2C2DD9CA1}.Release|Mac.ActiveCfg = Release|Any CPU {6AF05698-3D64-4FA5-B9DE-CCA2C2DD9CA1}.Release|Mac.Build.0 = Release|Any CPU {6AF05698-3D64-4FA5-B9DE-CCA2C2DD9CA1}.Release|Windows.ActiveCfg = Release|Any CPU {6AF05698-3D64-4FA5-B9DE-CCA2C2DD9CA1}.Release|Windows.Build.0 = Release|Any CPU + {3589BA37-A44E-49DB-A370-26D41EB3955F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3589BA37-A44E-49DB-A370-26D41EB3955F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3589BA37-A44E-49DB-A370-26D41EB3955F}.Debug|Linux.ActiveCfg = Debug|Any CPU {3589BA37-A44E-49DB-A370-26D41EB3955F}.Debug|Mac.ActiveCfg = Debug|Any CPU {3589BA37-A44E-49DB-A370-26D41EB3955F}.Debug|Windows.ActiveCfg = Debug|Any CPU {3589BA37-A44E-49DB-A370-26D41EB3955F}.Debug|Windows.Build.0 = Debug|Any CPU + {3589BA37-A44E-49DB-A370-26D41EB3955F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3589BA37-A44E-49DB-A370-26D41EB3955F}.Release|Any CPU.Build.0 = Release|Any CPU + {3589BA37-A44E-49DB-A370-26D41EB3955F}.Release|Linux.ActiveCfg = Release|Any CPU {3589BA37-A44E-49DB-A370-26D41EB3955F}.Release|Mac.ActiveCfg = Release|Any CPU {3589BA37-A44E-49DB-A370-26D41EB3955F}.Release|Windows.ActiveCfg = Release|Any CPU {3589BA37-A44E-49DB-A370-26D41EB3955F}.Release|Windows.Build.0 = Release|Any CPU + {51F518B4-5A7F-438D-A164-145D527DB1FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {51F518B4-5A7F-438D-A164-145D527DB1FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {51F518B4-5A7F-438D-A164-145D527DB1FF}.Debug|Linux.ActiveCfg = Debug|Any CPU {51F518B4-5A7F-438D-A164-145D527DB1FF}.Debug|Mac.ActiveCfg = Debug|Any CPU {51F518B4-5A7F-438D-A164-145D527DB1FF}.Debug|Windows.ActiveCfg = Debug|Any CPU {51F518B4-5A7F-438D-A164-145D527DB1FF}.Debug|Windows.Build.0 = Debug|Any CPU + {51F518B4-5A7F-438D-A164-145D527DB1FF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {51F518B4-5A7F-438D-A164-145D527DB1FF}.Release|Any CPU.Build.0 = Release|Any CPU + {51F518B4-5A7F-438D-A164-145D527DB1FF}.Release|Linux.ActiveCfg = Release|Any CPU {51F518B4-5A7F-438D-A164-145D527DB1FF}.Release|Mac.ActiveCfg = Release|Any CPU {51F518B4-5A7F-438D-A164-145D527DB1FF}.Release|Windows.ActiveCfg = Release|Any CPU {51F518B4-5A7F-438D-A164-145D527DB1FF}.Release|Windows.Build.0 = Release|Any CPU + {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Debug|Linux.ActiveCfg = Debug|Any CPU + {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Debug|Linux.Build.0 = Debug|Any CPU {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Debug|Mac.ActiveCfg = Debug|Any CPU {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Debug|Mac.Build.0 = Debug|Any CPU {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Debug|Windows.ActiveCfg = Debug|Any CPU {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Debug|Windows.Build.0 = Debug|Any CPU + {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Release|Any CPU.Build.0 = Release|Any CPU + {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Release|Linux.ActiveCfg = Release|Any CPU + {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Release|Linux.Build.0 = Release|Any CPU {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Release|Mac.ActiveCfg = Release|Any CPU {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Release|Mac.Build.0 = Release|Any CPU {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Release|Windows.ActiveCfg = Release|Any CPU {14AFF269-5C00-4E7A-8528-4DA704B7D2F4}.Release|Windows.Build.0 = Release|Any CPU - {AB712D06-69EA-4601-A9B3-774820B56633}.Debug|Mac.ActiveCfg = Debug|Any CPU - {AB712D06-69EA-4601-A9B3-774820B56633}.Debug|Mac.Build.0 = Debug|Any CPU - {AB712D06-69EA-4601-A9B3-774820B56633}.Debug|Windows.ActiveCfg = Debug|Any CPU - {AB712D06-69EA-4601-A9B3-774820B56633}.Debug|Windows.Build.0 = Debug|Any CPU - {AB712D06-69EA-4601-A9B3-774820B56633}.Release|Mac.ActiveCfg = Release|Any CPU - {AB712D06-69EA-4601-A9B3-774820B56633}.Release|Mac.Build.0 = Release|Any CPU - {AB712D06-69EA-4601-A9B3-774820B56633}.Release|Windows.ActiveCfg = Release|Any CPU - {AB712D06-69EA-4601-A9B3-774820B56633}.Release|Windows.Build.0 = Release|Any CPU + {B5532B13-B15D-4987-81E5-7AEBC18CDED0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B5532B13-B15D-4987-81E5-7AEBC18CDED0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B5532B13-B15D-4987-81E5-7AEBC18CDED0}.Debug|Linux.ActiveCfg = Debug|Any CPU + {B5532B13-B15D-4987-81E5-7AEBC18CDED0}.Debug|Mac.ActiveCfg = Debug|Any CPU + {B5532B13-B15D-4987-81E5-7AEBC18CDED0}.Debug|Mac.Build.0 = Debug|Any CPU + {B5532B13-B15D-4987-81E5-7AEBC18CDED0}.Debug|Windows.ActiveCfg = Debug|Any CPU + {B5532B13-B15D-4987-81E5-7AEBC18CDED0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B5532B13-B15D-4987-81E5-7AEBC18CDED0}.Release|Any CPU.Build.0 = Release|Any CPU + {B5532B13-B15D-4987-81E5-7AEBC18CDED0}.Release|Linux.ActiveCfg = Release|Any CPU + {B5532B13-B15D-4987-81E5-7AEBC18CDED0}.Release|Linux.Build.0 = Release|Any CPU + {B5532B13-B15D-4987-81E5-7AEBC18CDED0}.Release|Mac.ActiveCfg = Release|Any CPU + {B5532B13-B15D-4987-81E5-7AEBC18CDED0}.Release|Mac.Build.0 = Release|Any CPU + {B5532B13-B15D-4987-81E5-7AEBC18CDED0}.Release|Windows.ActiveCfg = Release|Any CPU + {B5532B13-B15D-4987-81E5-7AEBC18CDED0}.Release|Windows.Build.0 = Release|Any CPU + {63B74346-2B72-429F-AA2C-BD4CA09CD0E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {63B74346-2B72-429F-AA2C-BD4CA09CD0E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {63B74346-2B72-429F-AA2C-BD4CA09CD0E5}.Debug|Linux.ActiveCfg = Debug|Any CPU + {63B74346-2B72-429F-AA2C-BD4CA09CD0E5}.Debug|Mac.ActiveCfg = Debug|Any CPU + {63B74346-2B72-429F-AA2C-BD4CA09CD0E5}.Debug|Mac.Build.0 = Debug|Any CPU + {63B74346-2B72-429F-AA2C-BD4CA09CD0E5}.Debug|Windows.ActiveCfg = Debug|Any CPU + {63B74346-2B72-429F-AA2C-BD4CA09CD0E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {63B74346-2B72-429F-AA2C-BD4CA09CD0E5}.Release|Any CPU.Build.0 = Release|Any CPU + {63B74346-2B72-429F-AA2C-BD4CA09CD0E5}.Release|Linux.ActiveCfg = Release|Any CPU + {63B74346-2B72-429F-AA2C-BD4CA09CD0E5}.Release|Linux.Build.0 = Release|Any CPU + {63B74346-2B72-429F-AA2C-BD4CA09CD0E5}.Release|Mac.ActiveCfg = Release|Any CPU + {63B74346-2B72-429F-AA2C-BD4CA09CD0E5}.Release|Mac.Build.0 = Release|Any CPU + {63B74346-2B72-429F-AA2C-BD4CA09CD0E5}.Release|Windows.ActiveCfg = Release|Any CPU + {63B74346-2B72-429F-AA2C-BD4CA09CD0E5}.Release|Windows.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -139,7 +237,8 @@ Global {3589BA37-A44E-49DB-A370-26D41EB3955F} = {48C6A621-D898-4932-A28F-DFC0C1B272B6} {51F518B4-5A7F-438D-A164-145D527DB1FF} = {48C6A621-D898-4932-A28F-DFC0C1B272B6} {14AFF269-5C00-4E7A-8528-4DA704B7D2F4} = {48C6A621-D898-4932-A28F-DFC0C1B272B6} - {AB712D06-69EA-4601-A9B3-774820B56633} = {6136B651-45C5-48C7-80E7-943FF2461732} + {B5532B13-B15D-4987-81E5-7AEBC18CDED0} = {6136B651-45C5-48C7-80E7-943FF2461732} + {63B74346-2B72-429F-AA2C-BD4CA09CD0E5} = {48C6A621-D898-4932-A28F-DFC0C1B272B6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A0F9A175-218E-4414-B0EC-A227B0E5FA61} diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100755 index 0000000..1d4bd7f --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,9 @@ + + + + + + enable + + + diff --git a/src/Eto.Veldrid.Gtk/Eto.Veldrid.Gtk.csproj b/src/Eto.Veldrid.Gtk/Eto.Veldrid.Gtk.csproj index ffc44b0..75990ec 100644 --- a/src/Eto.Veldrid.Gtk/Eto.Veldrid.Gtk.csproj +++ b/src/Eto.Veldrid.Gtk/Eto.Veldrid.Gtk.csproj @@ -1,15 +1,10 @@  - + + netstandard2.0;net6.0 GTK3 Veldrid Gtk implementation for Eto.Forms This provides the Gtk implementation of Eto.Veldrid for Eto.Forms - net7.0 - - - - Project - false @@ -19,5 +14,5 @@ - + diff --git a/src/Eto.Veldrid.Gtk/GtkVeldridSurfaceHandler.cs b/src/Eto.Veldrid.Gtk/GtkVeldridSurfaceHandler.cs index 14e8134..8291a7e 100755 --- a/src/Eto.Veldrid.Gtk/GtkVeldridSurfaceHandler.cs +++ b/src/Eto.Veldrid.Gtk/GtkVeldridSurfaceHandler.cs @@ -12,7 +12,7 @@ namespace Eto.Veldrid.Gtk { public class GtkVeldridSurfaceHandler : GtkControl, VeldridSurface.IHandler, VeldridSurface.IOpenGL { - GLArea glArea; + GLArea? glArea; System.Action _makeCurrent; System.Action _clearCurrent; public Size RenderSize => Size.Round((SizeF)Widget.Size * Scale); @@ -27,13 +27,13 @@ public GtkVeldridSurfaceHandler() _clearCurrent = ClearCurrent; } - public Swapchain CreateSwapchain() + public Swapchain? CreateSwapchain() { - Swapchain swapchain; + Swapchain? swapchain; if (Widget.Backend == GraphicsBackend.OpenGL) { - swapchain = Widget.GraphicsDevice.MainSwapchain; + swapchain = Widget.GraphicsDevice?.MainSwapchain; } else { @@ -47,7 +47,7 @@ public Swapchain CreateSwapchain() X11Interop.gdk_x11_window_get_xid(Control.Window.Handle)); var renderSize = RenderSize; - swapchain = Widget.GraphicsDevice.ResourceFactory.CreateSwapchain( + swapchain = Widget.GraphicsDevice?.ResourceFactory.CreateSwapchain( new SwapchainDescription( source, (uint)renderSize.Width, @@ -60,15 +60,17 @@ public Swapchain CreateSwapchain() return swapchain; } - void glArea_InitializeGraphicsBackend(object sender, EventArgs e) + void glArea_InitializeGraphicsBackend(object? sender, EventArgs e) { + if (glArea == null) + return; // Make context current to manually initialize a Veldrid GraphicsDevice. glArea.Context.MakeCurrent(); Callback.OnInitializeBackend(Widget, new InitializeEventArgs(RenderSize)); // Veldrid clears the context at the end of initialization and sets it current in the worker thread. // Clear context in the worker thread for now to make Mesa happy. - if (Widget.GraphicsDevice.GetOpenGLInfo(out BackendInfoOpenGL glInfo)) + if (Widget.GraphicsDevice?.GetOpenGLInfo(out BackendInfoOpenGL glInfo) == true) { // This action has to wait so GTK can manage the context after this method. glInfo.ExecuteOnGLThread(_clearCurrent);//, wait: true); @@ -78,7 +80,7 @@ void glArea_InitializeGraphicsBackend(object sender, EventArgs e) glArea.Resize += glArea_Resize; } - void Control_InitializeGraphicsBackend(object sender, EventArgs e) + void Control_InitializeGraphicsBackend(object? sender, EventArgs e) { Callback.OnInitializeBackend(Widget, new InitializeEventArgs(RenderSize)); } @@ -99,6 +101,8 @@ void glArea_Render(object o, RenderArgs args) // GTK makes the context current for us, so we need to clear it to hand it over to the Veldrid worker. Gdk.GLContext.ClearCurrent(); + if (Widget.GraphicsDevice == null) + return; // Make context current on the Veldrid worker. if (Widget.GraphicsDevice.GetOpenGLInfo(out BackendInfoOpenGL glInfo)) diff --git a/src/Eto.Veldrid.Mac/Eto.Veldrid.Mac64.csproj b/src/Eto.Veldrid.Mac/Eto.Veldrid.Mac64.csproj index 4883845..2587c03 100644 --- a/src/Eto.Veldrid.Mac/Eto.Veldrid.Mac64.csproj +++ b/src/Eto.Veldrid.Mac/Eto.Veldrid.Mac64.csproj @@ -1,16 +1,15 @@  + net6.0;net462 MONOMAC false Veldrid Mac implementation for Eto.Forms This provides the Mac64 implementation of Eto.Veldrid for Eto.Forms - net7.0 - diff --git a/src/Eto.Veldrid.Mac/Eto.Veldrid.macOS.csproj b/src/Eto.Veldrid.Mac/Eto.Veldrid.macOS.csproj new file mode 100755 index 0000000..8532713 --- /dev/null +++ b/src/Eto.Veldrid.Mac/Eto.Veldrid.macOS.csproj @@ -0,0 +1,17 @@ + + + + net7.0-macos10.15 + Veldrid Mac implementation for Eto.Forms + This provides the Mac64 implementation of Eto.Veldrid for Eto.Forms + + + + + + + + + + + diff --git a/src/Eto.Veldrid.Mac/MacVeldridSurfaceHandler.cs b/src/Eto.Veldrid.Mac/MacVeldridSurfaceHandler.cs index 2944fc6..1f78055 100755 --- a/src/Eto.Veldrid.Mac/MacVeldridSurfaceHandler.cs +++ b/src/Eto.Veldrid.Mac/MacVeldridSurfaceHandler.cs @@ -3,12 +3,13 @@ using Eto.Veldrid.Mac; using System; using Veldrid; -using MonoMac.CoreVideo; using Eto.Drawing; #if MONOMAC +using MonoMac.CoreVideo; using MonoMac.AppKit; -#elif XAMMAC2 +#else +using CoreVideo; using AppKit; #endif @@ -18,7 +19,7 @@ namespace Eto.Veldrid.Mac { public class MacVeldridSurfaceHandler : MacView, VeldridSurface.IHandler { - CVDisplayLink _displayLink; + CVDisplayLink? _displayLink; Size? _newRenderSize; public Size RenderSize => Size.Round((SizeF)Widget.Size * Scale); @@ -36,13 +37,13 @@ public MacVeldridSurfaceHandler() Control.Draw += Control_Draw; } - public Swapchain CreateSwapchain() + public Swapchain? CreateSwapchain() { - Swapchain swapchain; + Swapchain? swapchain; if (Widget.Backend == GraphicsBackend.OpenGL) { - swapchain = Widget.GraphicsDevice.MainSwapchain; + swapchain = Widget.GraphicsDevice?.MainSwapchain; } else { @@ -54,7 +55,7 @@ public Swapchain CreateSwapchain() var source = SwapchainSource.CreateNSView(Control.Handle); var renderSize = RenderSize; - swapchain = Widget.GraphicsDevice.ResourceFactory.CreateSwapchain( + swapchain = Widget.GraphicsDevice?.ResourceFactory.CreateSwapchain( new SwapchainDescription( source, (uint)renderSize.Width, @@ -67,7 +68,7 @@ public Swapchain CreateSwapchain() return swapchain; } - private void Control_Draw(object sender, EventArgs e) + private void Control_Draw(object? sender, EventArgs e) { Callback.OnInitializeBackend(Widget, new InitializeEventArgs(RenderSize)); @@ -82,7 +83,7 @@ private void Control_Draw(object sender, EventArgs e) Widget.SizeChanged += Widget_SizeChanged; } - private void Widget_SizeChanged(object sender, EventArgs e) + private void Widget_SizeChanged(object? sender, EventArgs e) { if (Widget.Backend == GraphicsBackend.OpenGL) { diff --git a/src/Eto.Veldrid.Mac/MacVeldridView.cs b/src/Eto.Veldrid.Mac/MacVeldridView.cs old mode 100644 new mode 100755 index b5e70a0..566fd84 --- a/src/Eto.Veldrid.Mac/MacVeldridView.cs +++ b/src/Eto.Veldrid.Mac/MacVeldridView.cs @@ -4,7 +4,7 @@ #if MONOMAC using MonoMac.AppKit; using MonoMac.CoreGraphics; -#elif XAMMAC2 +#else using AppKit; using CoreGraphics; #endif @@ -19,9 +19,9 @@ public class MacVeldridView : NSView, IMacControl public bool CanFocus { get; set; } = true; - public WeakReference WeakHandler { get; set; } + public WeakReference? WeakHandler { get; set; } - public event EventHandler Draw; + public event EventHandler? Draw; public override void DrawRect(CGRect dirtyRect) { diff --git a/src/Eto.Veldrid.WinForms/Eto.Veldrid.WinForms.csproj b/src/Eto.Veldrid.WinForms/Eto.Veldrid.WinForms.csproj index d078b62..3e7324a 100755 --- a/src/Eto.Veldrid.WinForms/Eto.Veldrid.WinForms.csproj +++ b/src/Eto.Veldrid.WinForms/Eto.Veldrid.WinForms.csproj @@ -1,16 +1,8 @@ - + - true - net7.0 - - - - - - - $(TargetFrameworks);netcoreapp3.1 - true + net6.0-windows;net462 + true Veldrid Windows Forms implementation for Eto.Forms This provides the Windows Forms implementation of Eto.Veldrid for Eto.Forms @@ -19,17 +11,8 @@ - - - - - - - - - diff --git a/src/Eto.Veldrid.WinForms/WinFormsVeldridSurfaceHandler.cs b/src/Eto.Veldrid.WinForms/WinFormsVeldridSurfaceHandler.cs index 43ab475..8d40884 100755 --- a/src/Eto.Veldrid.WinForms/WinFormsVeldridSurfaceHandler.cs +++ b/src/Eto.Veldrid.WinForms/WinFormsVeldridSurfaceHandler.cs @@ -12,7 +12,7 @@ namespace Eto.Veldrid.WinForms { public class WinFormsVeldridSurfaceHandler : WindowsControl, VeldridSurface.IHandler { - public Size RenderSize => Size.Round((SizeF)Widget.Size * Scale); + public Eto.Drawing.Size RenderSize => Eto.Drawing.Size.Round((Eto.Drawing.SizeF)Widget.Size * Scale); float Scale => Widget.ParentWindow?.LogicalPixelSize ?? 1; @@ -24,13 +24,13 @@ public WinFormsVeldridSurfaceHandler() Control.HandleCreated += Control_HandleCreated; } - public Swapchain CreateSwapchain() + public Swapchain? CreateSwapchain() { - Swapchain swapchain; + Swapchain? swapchain; if (Widget.Backend == GraphicsBackend.OpenGL) { - swapchain = Widget.GraphicsDevice.MainSwapchain; + swapchain = Widget.GraphicsDevice?.MainSwapchain; } else { @@ -44,7 +44,7 @@ public Swapchain CreateSwapchain() Marshal.GetHINSTANCE(typeof(VeldridSurface).Module)); var renderSize = RenderSize; - swapchain = Widget.GraphicsDevice.ResourceFactory.CreateSwapchain( + swapchain = Widget.GraphicsDevice?.ResourceFactory.CreateSwapchain( new SwapchainDescription( source, (uint)renderSize.Width, @@ -57,7 +57,7 @@ public Swapchain CreateSwapchain() return swapchain; } - private void Control_HandleCreated(object sender, EventArgs e) + private void Control_HandleCreated(object? sender, EventArgs e) { if (RenderSize.IsEmpty) return; @@ -67,7 +67,7 @@ private void Control_HandleCreated(object sender, EventArgs e) Widget.SizeChanged += Widget_SizeChanged; } - private void Widget_SizeChanged(object sender, EventArgs e) + private void Widget_SizeChanged(object? sender, EventArgs e) { Callback.OnResize(Widget, new ResizeEventArgs(RenderSize)); } diff --git a/src/Eto.Veldrid.Wpf/Eto.Veldrid.Wpf.csproj b/src/Eto.Veldrid.Wpf/Eto.Veldrid.Wpf.csproj index ab46151..4921562 100755 --- a/src/Eto.Veldrid.Wpf/Eto.Veldrid.Wpf.csproj +++ b/src/Eto.Veldrid.Wpf/Eto.Veldrid.Wpf.csproj @@ -1,17 +1,9 @@ - + - true - net7.0 - - - - - - - $(TargetFrameworks);netcoreapp3.1 - true - true + net6.0-windows;net462 + true + true NU1701 Veldrid WPF implementation for Eto.Forms @@ -23,17 +15,16 @@ - + - - + @@ -43,8 +34,4 @@ - - - - diff --git a/src/Eto.Veldrid.Wpf/ManualBubbleWindowsFormsHostHandler.cs b/src/Eto.Veldrid.Wpf/ManualBubbleWindowsFormsHostHandler.cs old mode 100644 new mode 100755 index 81af132..7238221 --- a/src/Eto.Veldrid.Wpf/ManualBubbleWindowsFormsHostHandler.cs +++ b/src/Eto.Veldrid.Wpf/ManualBubbleWindowsFormsHostHandler.cs @@ -121,7 +121,7 @@ private void Control_MouseWheel(object sender, swi.MouseWheelEventArgs e) bool charPressed; public Keys? LastKeyDown { get; set; } - void WinFormsControl_KeyDown(object sender, swf.KeyEventArgs e) + void WinFormsControl_KeyDown(object? sender, swf.KeyEventArgs e) { charPressed = false; handled = true; @@ -149,7 +149,7 @@ void WinFormsControl_KeyDown(object sender, swf.KeyEventArgs e) LastKeyDown = null; } - void WinFormsControl_KeyPress(object sender, swf.KeyPressEventArgs e) + void WinFormsControl_KeyPress(object? sender, swf.KeyPressEventArgs e) { charPressed = true; keyChar = e.KeyChar; @@ -173,7 +173,7 @@ void WinFormsControl_KeyPress(object sender, swf.KeyPressEventArgs e) e.Handled = true; } - void WinFormsControl_KeyUp(object sender, swf.KeyEventArgs e) + void WinFormsControl_KeyUp(object? sender, swf.KeyEventArgs e) { key = e.KeyData.ToEto(); @@ -182,7 +182,7 @@ void WinFormsControl_KeyUp(object sender, swf.KeyEventArgs e) e.Handled = kpea.Handled; } - void WinFormsControl_TextChanged(object sender, EventArgs e) + void WinFormsControl_TextChanged(object? sender, EventArgs e) { var widget = Widget as TextControl; if (widget != null) @@ -192,7 +192,7 @@ void WinFormsControl_TextChanged(object sender, EventArgs e) } } - void WinFormsControl_MouseWheel(object sender, swf.MouseEventArgs e) + void WinFormsControl_MouseWheel(object? sender, swf.MouseEventArgs e) { var args = new swi.MouseWheelEventArgs(swi.InputManager.Current.PrimaryMouseDevice, Environment.TickCount, e.Delta) { @@ -203,13 +203,13 @@ void WinFormsControl_MouseWheel(object sender, swf.MouseEventArgs e) Control.RaiseEvent(args); } - void WinFormsControl_MouseLeave(object sender, EventArgs e) => Callback.OnMouseLeave(Widget, new MouseEventArgs(Mouse.Buttons, Keyboard.Modifiers, PointFromScreen(Mouse.Position))); + void WinFormsControl_MouseLeave(object? sender, EventArgs e) => Callback.OnMouseLeave(Widget, new MouseEventArgs(Mouse.Buttons, Keyboard.Modifiers, PointFromScreen(Mouse.Position))); - void WinFormsControl_MouseEnter(object sender, EventArgs e) => Callback.OnMouseEnter(Widget, new MouseEventArgs(Mouse.Buttons, Keyboard.Modifiers, PointFromScreen(Mouse.Position))); + void WinFormsControl_MouseEnter(object? sender, EventArgs e) => Callback.OnMouseEnter(Widget, new MouseEventArgs(Mouse.Buttons, Keyboard.Modifiers, PointFromScreen(Mouse.Position))); - void WinFormsControl_MouseDoubleClick(object sender, swf.MouseEventArgs e) => Callback.OnMouseDoubleClick(Widget, e.ToEto(WinFormsControl)); + void WinFormsControl_MouseDoubleClick(object? sender, swf.MouseEventArgs e) => Callback.OnMouseDoubleClick(Widget, e.ToEto(WinFormsControl)); - void WinFormsControl_MouseDown(object sender, swf.MouseEventArgs e) + void WinFormsControl_MouseDown(object? sender, swf.MouseEventArgs e) { // Contrary to most WPF controls, the WindowsFormsHost class seems // to prevent correct mouse event data from being obtained (e.g. @@ -233,7 +233,7 @@ void WinFormsControl_MouseDown(object sender, swf.MouseEventArgs e) Control.RaiseEvent(args); } - void WinFormsControl_MouseUp(object sender, swf.MouseEventArgs e) + void WinFormsControl_MouseUp(object? sender, swf.MouseEventArgs e) { Control.CaptureMouse(); @@ -251,7 +251,7 @@ void WinFormsControl_MouseUp(object sender, swf.MouseEventArgs e) Control.RaiseEvent(args); } - void WinFormsControl_MouseMove(object sender, swf.MouseEventArgs e) + void WinFormsControl_MouseMove(object? sender, swf.MouseEventArgs e) { var args = new swi.MouseEventArgs(swi.InputManager.Current.PrimaryMouseDevice, Environment.TickCount) { @@ -262,9 +262,9 @@ void WinFormsControl_MouseMove(object sender, swf.MouseEventArgs e) Control.RaiseEvent(args); } - void WinFormsControl_LostFocus(object sender, EventArgs e) => Callback.OnLostFocus(Widget, EventArgs.Empty); + void WinFormsControl_LostFocus(object? sender, EventArgs e) => Callback.OnLostFocus(Widget, EventArgs.Empty); - void WinFormsControl_GotFocus(object sender, EventArgs e) => Callback.OnGotFocus(Widget, EventArgs.Empty); + void WinFormsControl_GotFocus(object? sender, EventArgs e) => Callback.OnGotFocus(Widget, EventArgs.Empty); public override void Focus() { @@ -274,7 +274,7 @@ public override void Focus() Widget.LoadComplete += Widget_LoadComplete; } - void Widget_LoadComplete(object sender, EventArgs e) + void Widget_LoadComplete(object? sender, EventArgs e) { Widget.LoadComplete -= Widget_LoadComplete; WinFormsControl.Focus(); diff --git a/src/Eto.Veldrid.Wpf/WpfVeldridSurfaceHandler.cs b/src/Eto.Veldrid.Wpf/WpfVeldridSurfaceHandler.cs index 17cffe9..293e4b4 100755 --- a/src/Eto.Veldrid.Wpf/WpfVeldridSurfaceHandler.cs +++ b/src/Eto.Veldrid.Wpf/WpfVeldridSurfaceHandler.cs @@ -20,13 +20,13 @@ public WpfVeldridSurfaceHandler() : base(new WinFormsVeldridUserControl()) Control.Loaded += Control_Loaded; } - public Swapchain CreateSwapchain() + public Swapchain? CreateSwapchain() { - Swapchain swapchain; + Swapchain? swapchain; if (Widget.Backend == GraphicsBackend.OpenGL) { - swapchain = Widget.GraphicsDevice.MainSwapchain; + swapchain = Widget.GraphicsDevice?.MainSwapchain; } else { @@ -40,7 +40,7 @@ public Swapchain CreateSwapchain() Marshal.GetHINSTANCE(typeof(VeldridSurface).Module)); var renderSize = RenderSize; - swapchain = Widget.GraphicsDevice.ResourceFactory.CreateSwapchain( + swapchain = Widget.GraphicsDevice?.ResourceFactory.CreateSwapchain( new SwapchainDescription( source, (uint)renderSize.Width, @@ -61,7 +61,7 @@ private void Control_Loaded(object sender, System.Windows.RoutedEventArgs e) Widget.SizeChanged += Widget_SizeChanged; } - private void Widget_SizeChanged(object sender, EventArgs e) + private void Widget_SizeChanged(object? sender, EventArgs e) { Callback.OnResize(Widget, new ResizeEventArgs(RenderSize)); } diff --git a/src/Eto.Veldrid/Eto.Veldrid.csproj b/src/Eto.Veldrid/Eto.Veldrid.csproj index 84520c3..e00df32 100644 --- a/src/Eto.Veldrid/Eto.Veldrid.csproj +++ b/src/Eto.Veldrid/Eto.Veldrid.csproj @@ -1,33 +1,28 @@  - AnyCPU + netstandard2.0;net6.0 Veldrid Control for Eto.Forms This provides the control to use in your Eto.Forms application. Add the platform-specific package for each platform you wish to support. E.g. Eto.Veldrid.Gtk, Eto.Veldrid.Mac64, Eto.Veldrid.Wpf, etc. - net7.0 - + - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - Eto.Veldrid-LICENSE + + Eto.Veldrid-LICENSE.txt PreserveNewest - - - Eto.Veldrid-AUTHORS + + + Eto.Veldrid-AUTHORS.txt PreserveNewest - + diff --git a/src/Eto.Veldrid/VeldridSurface.cs b/src/Eto.Veldrid/VeldridSurface.cs index ba37d74..84abbbe 100755 --- a/src/Eto.Veldrid/VeldridSurface.cs +++ b/src/Eto.Veldrid/VeldridSurface.cs @@ -16,7 +16,7 @@ public class VeldridSurface : Control public new interface IHandler : Control.IHandler { Size RenderSize { get; } - Swapchain CreateSwapchain(); + Swapchain? CreateSwapchain(); } new IHandler Handler => (IHandler)base.Handler; @@ -72,9 +72,9 @@ public interface IOpenGL public int RenderHeight => RenderSize.Height; public GraphicsBackend Backend { get; private set; } - public GraphicsDevice GraphicsDevice { get; private set; } + public GraphicsDevice? GraphicsDevice { get; private set; } public GraphicsDeviceOptions GraphicsDeviceOptions { get; private set; } - public Swapchain Swapchain { get; private set; } + public Swapchain? Swapchain { get; private set; } public const string VeldridInitializedEvent = "VeldridSurface.VeldridInitialized"; public const string DrawEvent = "VeldridSurface.Draw"; diff --git a/src/Eto.VeldridSurface/Eto.VeldridSurface.csproj b/src/Eto.VeldridSurface/Eto.VeldridSurface.csproj deleted file mode 100644 index c34cb80..0000000 --- a/src/Eto.VeldridSurface/Eto.VeldridSurface.csproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - net7.0 - enable - enable - - - - - - - - - - - - - - - - - - diff --git a/src/Eto.VeldridSurface/VeldridDriver.cs b/src/Eto.VeldridSurface/VeldridDriver.cs deleted file mode 100644 index f94b20a..0000000 --- a/src/Eto.VeldridSurface/VeldridDriver.cs +++ /dev/null @@ -1,234 +0,0 @@ -using Eto.Veldrid; -using System.Numerics; -using System.Runtime.InteropServices; -using Veldrid; -using Veldrid.SPIRV; -using VeldridEto; - -namespace TestEtoVeldrid2 -{ - public struct VertexPositionColor - { - public static uint SizeInBytes = (uint)Marshal.SizeOf(typeof(VertexPositionColor)); - - public Vector3 Position; - public RgbaFloat Color; - - public VertexPositionColor(Vector3 position, RgbaFloat color) - { - Position = position; - Color = color; - } - } - - /// - /// A class that controls rendering to a VeldridSurface. - /// - /// - /// VeldridSurface is only a basic control that lets you render to the screen - /// using Veldrid. How exactly to do that is up to you; this driver class is - /// only one possible approach, and in all likelihood not the most efficient. - /// - public partial class VeldridDriver - { - - public VeldridDriver(ref OVPSettings settings, ref VeldridSurface surface) - { - ovpSettings = settings; - Surface = surface; - addKeyHandlers(); - Clock.Interval = 1.0f / 60.0f; - Clock.Elapsed += Clock_Elapsed; - } - - public void SetUpVeldrid() - { - CreateResources(); - - Ready = true; - } - - private void CreateResources() - { - // Veldrid.SPIRV is an additional library that complements Veldrid - // by simplifying the development of cross-backend shaders, and is - // currently the recommended approach to doing so: - // - // https://veldrid.dev/articles/portable-shaders.html - // - // If you decide against using it, you can try out Veldrid developer - // mellinoe's other project, ShaderGen, or drive yourself crazy by - // writing and maintaining custom shader code for each platform. - byte[] vertexShaderSpirvBytes = LoadSpirvBytes(ShaderStages.Vertex); - byte[] fragmentShaderSpirvBytes = LoadSpirvBytes(ShaderStages.Fragment); - - var options = new CrossCompileOptions(); - switch (Surface.GraphicsDevice.BackendType) - { - // InvertVertexOutputY and FixClipSpaceZ address two major - // differences between Veldrid's various graphics APIs, as - // discussed here: - // - // https://veldrid.dev/articles/backend-differences.html - // - // Note that the only reason those options are useful in this - // example project is that the vertices being drawn are stored - // the way Vulkan stores vertex data. The options will therefore - // properly convert from the Vulkan style to whatever's used by - // the destination backend. If you store vertices in a different - // coordinate system, these may not do anything for you, and - // you'll need to handle the difference in your shader code. - case GraphicsBackend.Metal: - options.InvertVertexOutputY = true; - break; - case GraphicsBackend.Direct3D11: - options.InvertVertexOutputY = true; - break; - case GraphicsBackend.OpenGL: - options.FixClipSpaceZ = true; - options.InvertVertexOutputY = true; - break; - default: - break; - } - - ResourceFactory factory = Surface.GraphicsDevice.ResourceFactory; - - ResourceLayout viewMatrixLayout = factory.CreateResourceLayout( - new ResourceLayoutDescription( - new ResourceLayoutElementDescription( - "ViewMatrix", - ResourceKind.UniformBuffer, - ShaderStages.Vertex))); - - ViewBuffer = factory.CreateBuffer( - new BufferDescription(64, BufferUsage.UniformBuffer)); - - ViewMatrixSet = factory.CreateResourceSet(new ResourceSetDescription( - viewMatrixLayout, ViewBuffer)); - - var vertex = new ShaderDescription(ShaderStages.Vertex, vertexShaderSpirvBytes, "main", true); - var fragment = new ShaderDescription(ShaderStages.Fragment, fragmentShaderSpirvBytes, "main", true); - Shader[] shaders = factory.CreateFromSpirv(vertex, fragment, options); - - ResourceLayout modelMatrixLayout = factory.CreateResourceLayout( - new ResourceLayoutDescription( - new ResourceLayoutElementDescription( - "ModelMatrix", - ResourceKind.UniformBuffer, - ShaderStages.Vertex))); - - ModelBuffer = factory.CreateBuffer( - new BufferDescription(64, BufferUsage.UniformBuffer)); - - ModelMatrixSet = factory.CreateResourceSet(new ResourceSetDescription( - modelMatrixLayout, ModelBuffer)); - - VertexBuffer = - factory.CreateBuffer(new BufferDescription(4 * VertexPositionColor.SizeInBytes, - BufferUsage.VertexBuffer)); - IndexBuffer = factory.CreateBuffer(new BufferDescription(4 * sizeof(ushort), BufferUsage.IndexBuffer)); - - // Veldrid.SPIRV, when cross-compiling to HLSL, will always produce - // TEXCOORD semantics; VertexElementSemantic.TextureCoordinate thus - // becomes necessary to let D3D11 work alongside Vulkan and OpenGL. - // - // https://github.com/mellinoe/veldrid/issues/121 - // - var vertexLayout = new VertexLayoutDescription( - new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, - VertexElementFormat.Float3), - new VertexElementDescription("Color", VertexElementSemantic.TextureCoordinate, - VertexElementFormat.Float4)); - - create_pipelines(ref factory, ref viewMatrixLayout, ref modelMatrixLayout, ref shaders, ref vertexLayout); - - CommandList = factory.CreateCommandList(); - } - - private void create_pipelines(ref ResourceFactory factory, ref ResourceLayout viewMatrixLayout, - ref ResourceLayout modelMatrixLayout, ref Shader[] shaders, ref VertexLayoutDescription vertexLayout) - { - LinePipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription - { - BlendState = BlendStateDescription.SingleOverrideBlend, - DepthStencilState = new DepthStencilStateDescription( - depthTestEnabled: true, - depthWriteEnabled: true, - comparisonKind: ComparisonKind.LessEqual), - RasterizerState = new RasterizerStateDescription( - cullMode: FaceCullMode.Back, - fillMode: PolygonFillMode.Solid, - frontFace: FrontFace.Clockwise, - depthClipEnabled: true, - scissorTestEnabled: false), - PrimitiveTopology = PrimitiveTopology.LineList, - ResourceLayouts = new[] { viewMatrixLayout, modelMatrixLayout }, - ShaderSet = new ShaderSetDescription( - vertexLayouts: new[] { vertexLayout }, - shaders: shaders), - Outputs = Surface.Swapchain.Framebuffer.OutputDescription - }); - - LinesPipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription - { - BlendState = BlendStateDescription.SingleAlphaBlend, - DepthStencilState = new DepthStencilStateDescription( - depthTestEnabled: false, - depthWriteEnabled: false, - comparisonKind: ComparisonKind.LessEqual), - RasterizerState = new RasterizerStateDescription( - cullMode: FaceCullMode.Back, - fillMode: PolygonFillMode.Solid, - frontFace: FrontFace.Clockwise, - depthClipEnabled: false, - scissorTestEnabled: false), - PrimitiveTopology = PrimitiveTopology.LineStrip, - ResourceLayouts = new[] { viewMatrixLayout, modelMatrixLayout }, - ShaderSet = new ShaderSetDescription( - vertexLayouts: new[] { vertexLayout }, - shaders: shaders), - Outputs = Surface.Swapchain.Framebuffer.OutputDescription - }); - - FilledPipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription - { - BlendState = BlendStateDescription.SingleAlphaBlend, - DepthStencilState = new DepthStencilStateDescription( - depthTestEnabled: false, - depthWriteEnabled: false, - comparisonKind: ComparisonKind.LessEqual), - RasterizerState = new RasterizerStateDescription( - cullMode: FaceCullMode.None, - fillMode: PolygonFillMode.Solid, - frontFace: FrontFace.CounterClockwise, - depthClipEnabled: false, - scissorTestEnabled: false), - PrimitiveTopology = PrimitiveTopology.TriangleStrip, - ResourceLayouts = new[] { viewMatrixLayout, modelMatrixLayout }, - ShaderSet = new ShaderSetDescription( - vertexLayouts: new[] { vertexLayout }, - shaders: shaders), - Outputs = Surface.Swapchain.Framebuffer.OutputDescription - }); - } - - private byte[] LoadSpirvBytes(ShaderStages stage) - { - string name = $"VertexColor-{stage.ToString().ToLowerInvariant()}.450.glsl"; - string full = $"Eto.VeldridSurface.shaders.{name}"; - - // Precompiled SPIR-V bytecode can speed up program start by saving - // the need to load text files and compile them before converting - // the result to the final backend shader format. If they're not - // available, though, the plain .glsl files will do just fine. Look - // up glslangValidator to learn how to compile SPIR-V binary files. - - using (var stream = GetType().Assembly.GetManifestResourceStream(full)) - using (var reader = new BinaryReader(stream)) - { - return reader.ReadBytes((int)stream.Length); - } - } - } -} diff --git a/test/TestEtoVeldrid.Gtk/TestEtoVeldrid.Gtk.csproj b/test/TestEtoVeldrid.Gtk/TestEtoVeldrid.Gtk.csproj index d29df91..eb91039 100644 --- a/test/TestEtoVeldrid.Gtk/TestEtoVeldrid.Gtk.csproj +++ b/test/TestEtoVeldrid.Gtk/TestEtoVeldrid.Gtk.csproj @@ -2,18 +2,11 @@ WinExe - linux-x64 - net7.0 - - - - Project - false + net8.0 - diff --git a/test/TestEtoVeldrid.Mac/Info.plist b/test/TestEtoVeldrid.Mac/Info.plist index 7a937cb..784a35f 100644 --- a/test/TestEtoVeldrid.Mac/Info.plist +++ b/test/TestEtoVeldrid.Mac/Info.plist @@ -9,7 +9,7 @@ CFBundleShortVersionString 1.0 LSMinimumSystemVersion - 10.7 + 10.15 CFBundleDevelopmentRegion en NSHumanReadableCopyright diff --git a/test/TestEtoVeldrid.Mac/TestEtoVeldrid.Mac64.csproj b/test/TestEtoVeldrid.Mac/TestEtoVeldrid.Mac64.csproj index 348443b..ae24336 100644 --- a/test/TestEtoVeldrid.Mac/TestEtoVeldrid.Mac64.csproj +++ b/test/TestEtoVeldrid.Mac/TestEtoVeldrid.Mac64.csproj @@ -1,15 +1,18 @@  - WinExe + Exe + osx-x64;osx-arm64 + net8.0 MONOMAC - osx-x64 - net7.0 + + + + - diff --git a/test/TestEtoVeldrid.Mac/TestEtoVeldrid.macOS.csproj b/test/TestEtoVeldrid.Mac/TestEtoVeldrid.macOS.csproj new file mode 100644 index 0000000..c915c8c --- /dev/null +++ b/test/TestEtoVeldrid.Mac/TestEtoVeldrid.macOS.csproj @@ -0,0 +1,24 @@ + + + + Exe + osx-x64;osx-arm64 + net8.0-macos + 10.15 + + + + + + + + + + + + + + + + + diff --git a/test/TestEtoVeldrid.WinForms/Program.cs b/test/TestEtoVeldrid.WinForms/Program.cs old mode 100644 new mode 100755 index 7464426..15d2734 --- a/test/TestEtoVeldrid.WinForms/Program.cs +++ b/test/TestEtoVeldrid.WinForms/Program.cs @@ -10,7 +10,7 @@ public static void Main(string[] args) { var platform = new Eto.WinForms.Platform(); - new Application(platform).Run(new MainForm()); + new Eto.Forms.Application(platform).Run(new MainForm()); } } } diff --git a/test/TestEtoVeldrid.WinForms/TestEtoVeldrid.WinForms.csproj b/test/TestEtoVeldrid.WinForms/TestEtoVeldrid.WinForms.csproj old mode 100644 new mode 100755 index 1886146..ae0365f --- a/test/TestEtoVeldrid.WinForms/TestEtoVeldrid.WinForms.csproj +++ b/test/TestEtoVeldrid.WinForms/TestEtoVeldrid.WinForms.csproj @@ -1,16 +1,8 @@ - - - - true - net7.0 - - - - + WinExe - $(TargetFrameworks);net5.0-windows + net48;net8.0-windows true win-x64 @@ -24,7 +16,4 @@ - - - diff --git a/test/TestEtoVeldrid.Wpf/TestEtoVeldrid.Wpf.csproj b/test/TestEtoVeldrid.Wpf/TestEtoVeldrid.Wpf.csproj old mode 100644 new mode 100755 index f72b470..277463a --- a/test/TestEtoVeldrid.Wpf/TestEtoVeldrid.Wpf.csproj +++ b/test/TestEtoVeldrid.Wpf/TestEtoVeldrid.Wpf.csproj @@ -1,19 +1,11 @@ - - - - true - net7.0 - - - - + WinExe - $(TargetFrameworks);net5.0-windows + net48;net8.0-windows app1.manifest - true win-x64 + true NU1701 @@ -24,17 +16,13 @@ - + - - - - diff --git a/test/TestEtoVeldrid/MainForm.cs b/test/TestEtoVeldrid/MainForm.cs old mode 100644 new mode 100755 index f51afc3..baa95e5 --- a/test/TestEtoVeldrid/MainForm.cs +++ b/test/TestEtoVeldrid/MainForm.cs @@ -1,11 +1,7 @@ using Eto.Drawing; using Eto.Forms; using Eto.Veldrid; -using System; -using System.Threading; -using TestEtoVeldrid2; using Veldrid; -using VeldridEto; using PixelFormat = Veldrid.PixelFormat; namespace TestEtoVeldrid diff --git a/src/Eto.VeldridSurface/OVPSettings.cs b/test/TestEtoVeldrid/OVPSettings.cs old mode 100644 new mode 100755 similarity index 98% rename from src/Eto.VeldridSurface/OVPSettings.cs rename to test/TestEtoVeldrid/OVPSettings.cs index 60c36f9..970e88f --- a/src/Eto.VeldridSurface/OVPSettings.cs +++ b/test/TestEtoVeldrid/OVPSettings.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq; -namespace VeldridEto; +namespace TestEtoVeldrid; public static class errorReporter { @@ -56,10 +56,7 @@ public class OVPSettings private float base_zoom; private float zoomFactor; private int zoomStep; - private bool allowZoomAndPan; private bool dynamicGrid; - private bool panning; - private bool selecting; private bool showGrid; private bool showAxes; private bool showDrawn; @@ -443,12 +440,9 @@ private void init(float defX, float defY) backColor = new Color(1.0f, 1.0f, 1.0f); selectionColor = SystemColors.Highlight; inverSelectionColor = SystemColors.Highlight; - allowZoomAndPan = true; enableFilledPolys = false; showPoints = true; dynamicGrid = true; - panning = false; - selecting = false; showGrid = true; showAxes = true; grid_spacing = 10; diff --git a/test/TestEtoVeldrid/TestEtoVeldrid.csproj b/test/TestEtoVeldrid/TestEtoVeldrid.csproj old mode 100644 new mode 100755 index 2c73e0c..dedac6e --- a/test/TestEtoVeldrid/TestEtoVeldrid.csproj +++ b/test/TestEtoVeldrid/TestEtoVeldrid.csproj @@ -1,28 +1,21 @@  - AnyCPU + netstandard2.0 TestEtoVeldrid TestEtoVeldrid - net7.0 - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - diff --git a/test/TestEtoVeldrid/VeldridDriver.cs b/test/TestEtoVeldrid/VeldridDriver.cs new file mode 100755 index 0000000..cae5c25 --- /dev/null +++ b/test/TestEtoVeldrid/VeldridDriver.cs @@ -0,0 +1,232 @@ +using Eto.Veldrid; +using System.Numerics; +using System.Runtime.InteropServices; +using Veldrid; +using Veldrid.SPIRV; + +namespace TestEtoVeldrid; + +public struct VertexPositionColor +{ + public static uint SizeInBytes = (uint)Marshal.SizeOf(typeof(VertexPositionColor)); + + public Vector3 Position; + public RgbaFloat Color; + + public VertexPositionColor(Vector3 position, RgbaFloat color) + { + Position = position; + Color = color; + } +} + +/// +/// A class that controls rendering to a VeldridSurface. +/// +/// +/// VeldridSurface is only a basic control that lets you render to the screen +/// using Veldrid. How exactly to do that is up to you; this driver class is +/// only one possible approach, and in all likelihood not the most efficient. +/// +public partial class VeldridDriver +{ + + public VeldridDriver(ref OVPSettings settings, ref VeldridSurface surface) + { + ovpSettings = settings; + Surface = surface; + addKeyHandlers(); + Clock.Interval = 1.0f / 60.0f; + Clock.Elapsed += Clock_Elapsed; + } + + public void SetUpVeldrid() + { + CreateResources(); + + Ready = true; + } + + private void CreateResources() + { + // Veldrid.SPIRV is an additional library that complements Veldrid + // by simplifying the development of cross-backend shaders, and is + // currently the recommended approach to doing so: + // + // https://veldrid.dev/articles/portable-shaders.html + // + // If you decide against using it, you can try out Veldrid developer + // mellinoe's other project, ShaderGen, or drive yourself crazy by + // writing and maintaining custom shader code for each platform. + byte[] vertexShaderSpirvBytes = LoadSpirvBytes(ShaderStages.Vertex); + byte[] fragmentShaderSpirvBytes = LoadSpirvBytes(ShaderStages.Fragment); + + var options = new CrossCompileOptions(); + switch (Surface.GraphicsDevice.BackendType) + { + // InvertVertexOutputY and FixClipSpaceZ address two major + // differences between Veldrid's various graphics APIs, as + // discussed here: + // + // https://veldrid.dev/articles/backend-differences.html + // + // Note that the only reason those options are useful in this + // example project is that the vertices being drawn are stored + // the way Vulkan stores vertex data. The options will therefore + // properly convert from the Vulkan style to whatever's used by + // the destination backend. If you store vertices in a different + // coordinate system, these may not do anything for you, and + // you'll need to handle the difference in your shader code. + case GraphicsBackend.Metal: + options.InvertVertexOutputY = true; + break; + case GraphicsBackend.Direct3D11: + options.InvertVertexOutputY = true; + break; + case GraphicsBackend.OpenGL: + options.FixClipSpaceZ = true; + options.InvertVertexOutputY = true; + break; + default: + break; + } + + ResourceFactory factory = Surface.GraphicsDevice.ResourceFactory; + + ResourceLayout viewMatrixLayout = factory.CreateResourceLayout( + new ResourceLayoutDescription( + new ResourceLayoutElementDescription( + "ViewMatrix", + ResourceKind.UniformBuffer, + ShaderStages.Vertex))); + + ViewBuffer = factory.CreateBuffer( + new BufferDescription(64, BufferUsage.UniformBuffer)); + + ViewMatrixSet = factory.CreateResourceSet(new ResourceSetDescription( + viewMatrixLayout, ViewBuffer)); + + var vertex = new ShaderDescription(ShaderStages.Vertex, vertexShaderSpirvBytes, "main", true); + var fragment = new ShaderDescription(ShaderStages.Fragment, fragmentShaderSpirvBytes, "main", true); + Shader[] shaders = factory.CreateFromSpirv(vertex, fragment, options); + + ResourceLayout modelMatrixLayout = factory.CreateResourceLayout( + new ResourceLayoutDescription( + new ResourceLayoutElementDescription( + "ModelMatrix", + ResourceKind.UniformBuffer, + ShaderStages.Vertex))); + + ModelBuffer = factory.CreateBuffer( + new BufferDescription(64, BufferUsage.UniformBuffer)); + + ModelMatrixSet = factory.CreateResourceSet(new ResourceSetDescription( + modelMatrixLayout, ModelBuffer)); + + VertexBuffer = + factory.CreateBuffer(new BufferDescription(4 * VertexPositionColor.SizeInBytes, + BufferUsage.VertexBuffer)); + IndexBuffer = factory.CreateBuffer(new BufferDescription(4 * sizeof(ushort), BufferUsage.IndexBuffer)); + + // Veldrid.SPIRV, when cross-compiling to HLSL, will always produce + // TEXCOORD semantics; VertexElementSemantic.TextureCoordinate thus + // becomes necessary to let D3D11 work alongside Vulkan and OpenGL. + // + // https://github.com/mellinoe/veldrid/issues/121 + // + var vertexLayout = new VertexLayoutDescription( + new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, + VertexElementFormat.Float3), + new VertexElementDescription("Color", VertexElementSemantic.TextureCoordinate, + VertexElementFormat.Float4)); + + create_pipelines(ref factory, ref viewMatrixLayout, ref modelMatrixLayout, ref shaders, ref vertexLayout); + + CommandList = factory.CreateCommandList(); + } + + private void create_pipelines(ref ResourceFactory factory, ref ResourceLayout viewMatrixLayout, + ref ResourceLayout modelMatrixLayout, ref Shader[] shaders, ref VertexLayoutDescription vertexLayout) + { + LinePipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription + { + BlendState = BlendStateDescription.SingleOverrideBlend, + DepthStencilState = new DepthStencilStateDescription( + depthTestEnabled: true, + depthWriteEnabled: true, + comparisonKind: ComparisonKind.LessEqual), + RasterizerState = new RasterizerStateDescription( + cullMode: FaceCullMode.Back, + fillMode: PolygonFillMode.Solid, + frontFace: FrontFace.Clockwise, + depthClipEnabled: true, + scissorTestEnabled: false), + PrimitiveTopology = PrimitiveTopology.LineList, + ResourceLayouts = new[] { viewMatrixLayout, modelMatrixLayout }, + ShaderSet = new ShaderSetDescription( + vertexLayouts: new[] { vertexLayout }, + shaders: shaders), + Outputs = Surface.Swapchain.Framebuffer.OutputDescription + }); + + LinesPipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription + { + BlendState = BlendStateDescription.SingleAlphaBlend, + DepthStencilState = new DepthStencilStateDescription( + depthTestEnabled: false, + depthWriteEnabled: false, + comparisonKind: ComparisonKind.LessEqual), + RasterizerState = new RasterizerStateDescription( + cullMode: FaceCullMode.Back, + fillMode: PolygonFillMode.Solid, + frontFace: FrontFace.Clockwise, + depthClipEnabled: false, + scissorTestEnabled: false), + PrimitiveTopology = PrimitiveTopology.LineStrip, + ResourceLayouts = new[] { viewMatrixLayout, modelMatrixLayout }, + ShaderSet = new ShaderSetDescription( + vertexLayouts: new[] { vertexLayout }, + shaders: shaders), + Outputs = Surface.Swapchain.Framebuffer.OutputDescription + }); + + FilledPipeline = factory.CreateGraphicsPipeline(new GraphicsPipelineDescription + { + BlendState = BlendStateDescription.SingleAlphaBlend, + DepthStencilState = new DepthStencilStateDescription( + depthTestEnabled: false, + depthWriteEnabled: false, + comparisonKind: ComparisonKind.LessEqual), + RasterizerState = new RasterizerStateDescription( + cullMode: FaceCullMode.None, + fillMode: PolygonFillMode.Solid, + frontFace: FrontFace.CounterClockwise, + depthClipEnabled: false, + scissorTestEnabled: false), + PrimitiveTopology = PrimitiveTopology.TriangleStrip, + ResourceLayouts = new[] { viewMatrixLayout, modelMatrixLayout }, + ShaderSet = new ShaderSetDescription( + vertexLayouts: new[] { vertexLayout }, + shaders: shaders), + Outputs = Surface.Swapchain.Framebuffer.OutputDescription + }); + } + + private byte[] LoadSpirvBytes(ShaderStages stage) + { + string name = $"VertexColor-{stage.ToString().ToLowerInvariant()}.450.glsl"; + string full = $"TestEtoVeldrid.shaders.{name}"; + + // Precompiled SPIR-V bytecode can speed up program start by saving + // the need to load text files and compile them before converting + // the result to the final backend shader format. If they're not + // available, though, the plain .glsl files will do just fine. Look + // up glslangValidator to learn how to compile SPIR-V binary files. + + using (var stream = GetType().Assembly.GetManifestResourceStream(full)) + using (var reader = new BinaryReader(stream)) + { + return reader.ReadBytes((int)stream.Length); + } + } +} diff --git a/src/Eto.VeldridSurface/VeldridDriver_Conversions.cs b/test/TestEtoVeldrid/VeldridDriver_Conversions.cs old mode 100644 new mode 100755 similarity index 97% rename from src/Eto.VeldridSurface/VeldridDriver_Conversions.cs rename to test/TestEtoVeldrid/VeldridDriver_Conversions.cs index f2b77de..5f35efc --- a/src/Eto.VeldridSurface/VeldridDriver_Conversions.cs +++ b/test/TestEtoVeldrid/VeldridDriver_Conversions.cs @@ -1,6 +1,6 @@ using Eto.Drawing; -namespace TestEtoVeldrid2; +namespace TestEtoVeldrid; public partial class VeldridDriver { diff --git a/src/Eto.VeldridSurface/VeldridDriver_Draw.cs b/test/TestEtoVeldrid/VeldridDriver_Draw.cs old mode 100644 new mode 100755 similarity index 99% rename from src/Eto.VeldridSurface/VeldridDriver_Draw.cs rename to test/TestEtoVeldrid/VeldridDriver_Draw.cs index 731be1b..b1a6266 --- a/src/Eto.VeldridSurface/VeldridDriver_Draw.cs +++ b/test/TestEtoVeldrid/VeldridDriver_Draw.cs @@ -2,7 +2,7 @@ using System.Numerics; using Veldrid; -namespace TestEtoVeldrid2; +namespace TestEtoVeldrid; public partial class VeldridDriver { diff --git a/src/Eto.VeldridSurface/VeldridDriver_Handlers.cs b/test/TestEtoVeldrid/VeldridDriver_Handlers.cs old mode 100644 new mode 100755 similarity index 99% rename from src/Eto.VeldridSurface/VeldridDriver_Handlers.cs rename to test/TestEtoVeldrid/VeldridDriver_Handlers.cs index 5871de8..a066015 --- a/src/Eto.VeldridSurface/VeldridDriver_Handlers.cs +++ b/test/TestEtoVeldrid/VeldridDriver_Handlers.cs @@ -2,7 +2,7 @@ using Eto.Drawing; using Eto.Forms; -namespace TestEtoVeldrid2; +namespace TestEtoVeldrid; public partial class VeldridDriver { @@ -219,7 +219,6 @@ private void addKeyHandlers() Surface.MouseEnter += setFocus; Surface.MouseLeave += removeFocus; Surface.KeyDown += keyHandler; - keyHandlerApplied = true; // Surface.MouseLeave += removeKeyHandler; } catch (Exception ex) diff --git a/src/Eto.VeldridSurface/VeldridDriver_Public.cs b/test/TestEtoVeldrid/VeldridDriver_Public.cs old mode 100644 new mode 100755 similarity index 98% rename from src/Eto.VeldridSurface/VeldridDriver_Public.cs rename to test/TestEtoVeldrid/VeldridDriver_Public.cs index 8fb64a7..d15cc26 --- a/src/Eto.VeldridSurface/VeldridDriver_Public.cs +++ b/test/TestEtoVeldrid/VeldridDriver_Public.cs @@ -1,8 +1,7 @@ using Eto.Drawing; using Eto.Forms; -using VeldridEto; -namespace TestEtoVeldrid2; +namespace TestEtoVeldrid; public partial class VeldridDriver { diff --git a/src/Eto.VeldridSurface/VeldridDriver_Variables.cs b/test/TestEtoVeldrid/VeldridDriver_Variables.cs old mode 100644 new mode 100755 similarity index 89% rename from src/Eto.VeldridSurface/VeldridDriver_Variables.cs rename to test/TestEtoVeldrid/VeldridDriver_Variables.cs index af9592f..fe68e7c --- a/src/Eto.VeldridSurface/VeldridDriver_Variables.cs +++ b/test/TestEtoVeldrid/VeldridDriver_Variables.cs @@ -4,7 +4,7 @@ using System.Numerics; using Veldrid; -namespace TestEtoVeldrid2; +namespace TestEtoVeldrid; public partial class VeldridDriver { @@ -35,8 +35,8 @@ private set private uint[] gridIndices; private uint[] axesIndices; - private float axisZ; - private float gridZ; + private float axisZ = 0; + private float gridZ = 0; private DeviceBuffer GridVertexBuffer; private DeviceBuffer GridIndexBuffer; @@ -54,7 +54,6 @@ private set private DeviceBuffer PolysVertexBuffer; private DeviceBuffer TessVertexBuffer; - private Pipeline PointsPipeline; private Pipeline LinePipeline; private Pipeline LinesPipeline; private Pipeline FilledPipeline; @@ -75,15 +74,12 @@ private set private const float pointWidth = 0.50f; private bool hasFocus; - private bool keyHandlerApplied; // Use for drag handling. private bool dragging { get; set; } private float x_orig; private float y_orig; - private DateTime CurrentTime; - private DateTime PreviousTime = DateTime.Now; private ContextMenu menu; } diff --git a/src/Eto.VeldridSurface/ovp_Poly.cs b/test/TestEtoVeldrid/ovp_Poly.cs old mode 100644 new mode 100755 similarity index 93% rename from src/Eto.VeldridSurface/ovp_Poly.cs rename to test/TestEtoVeldrid/ovp_Poly.cs index 589e55f..2d9943b --- a/src/Eto.VeldridSurface/ovp_Poly.cs +++ b/test/TestEtoVeldrid/ovp_Poly.cs @@ -1,6 +1,6 @@ using Eto.Drawing; -namespace VeldridEto; +namespace TestEtoVeldrid; public class ovp_Poly { @@ -21,4 +21,4 @@ public ovp_Poly(PointF[] geometry, Color geoColor, float alpha_) color = geoColor; alpha = alpha_; } -} \ No newline at end of file +} diff --git a/src/Eto.VeldridSurface/shaders/VertexColor-fragment.450.glsl b/test/TestEtoVeldrid/shaders/VertexColor-fragment.450.glsl old mode 100644 new mode 100755 similarity index 100% rename from src/Eto.VeldridSurface/shaders/VertexColor-fragment.450.glsl rename to test/TestEtoVeldrid/shaders/VertexColor-fragment.450.glsl diff --git a/src/Eto.VeldridSurface/shaders/VertexColor-vertex.450.glsl b/test/TestEtoVeldrid/shaders/VertexColor-vertex.450.glsl old mode 100644 new mode 100755 similarity index 100% rename from src/Eto.VeldridSurface/shaders/VertexColor-vertex.450.glsl rename to test/TestEtoVeldrid/shaders/VertexColor-vertex.450.glsl