From 7ce474d92a855f9d67b5f42d6dda390921c7d445 Mon Sep 17 00:00:00 2001 From: "H. Utku Maden" Date: Thu, 11 Apr 2024 19:09:00 +0300 Subject: [PATCH] Changes to platform abstraction layer. --- Quik.OpenTK/OpenTKPlatform.cs | 31 +++++++++++- Quik.OpenTK/OpenTKPort.cs | 4 +- Quik/PAL/IQuikHost.cs | 38 --------------- Quik/PAL/IQuikPlatform.cs | 59 ++++++++++++++++++++++ Quik/PAL/IQuikPort.cs | 49 ------------------- Quik/PAL/QuikPort.cs | 92 +++++++++++++++++++++++++++++++++++ Quik/QuikApplication.cs | 52 ++++++++++++++++---- 7 files changed, 225 insertions(+), 100 deletions(-) delete mode 100644 Quik/PAL/IQuikHost.cs create mode 100644 Quik/PAL/IQuikPlatform.cs delete mode 100644 Quik/PAL/IQuikPort.cs create mode 100644 Quik/PAL/QuikPort.cs diff --git a/Quik.OpenTK/OpenTKPlatform.cs b/Quik.OpenTK/OpenTKPlatform.cs index 669429c..30180e6 100644 --- a/Quik.OpenTK/OpenTKPlatform.cs +++ b/Quik.OpenTK/OpenTKPlatform.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using OpenTK.Windowing.Desktop; using OpenTK.Windowing.GraphicsLibraryFramework; +using Quik.CommandMachine; using Quik.Media; using Quik.OpenGL; using Quik.PAL; @@ -24,7 +25,7 @@ namespace Quik.OpenTK private bool IsGLInitialized = false; - public IQuikPort CreatePort() + public IQuikPortHandle CreatePort() { NativeWindow window = new NativeWindow(DefaultSettings); OpenTKPort port = new OpenTKPort(window); @@ -33,7 +34,7 @@ namespace Quik.OpenTK if (!IsGLInitialized) { window.Context.MakeCurrent(); - GL.LoadBindings((string proc) => GLFW.GetProcAddress(proc)); + GL.LoadBindings(GLFW.GetProcAddress); IsGLInitialized = true; } @@ -60,5 +61,31 @@ namespace Quik.OpenTK { NativeWindow.ProcessWindowEvents(block); } + + public void DestroyPort(IQuikPortHandle port) => ((OpenTKPort)port).Dispose(); + + public string PortGetTitle(IQuikPortHandle port) => ((OpenTKPort)port).Title; + + public void PortSetTitle(IQuikPortHandle port, string title) => ((OpenTKPort)port).Title = title; + + public QVec2 PortGetSize(IQuikPortHandle port) => ((OpenTKPort)port).Size; + + public void PortSetSize(IQuikPortHandle port, QVec2 size) => ((OpenTKPort)port).Size = size; + + public QVec2 PortGetPosition(IQuikPortHandle port) => ((OpenTKPort)port).Position; + + public void PortSetPosition(IQuikPortHandle port, QVec2 position) => ((OpenTKPort)port).Position = position; + + public bool PortIsValid(IQuikPortHandle port) => ((OpenTKPort)port).IsValid; + + public void PortSubscribeEvent(IQuikPortHandle port, EventHandler handler) => ((OpenTKPort)port).EventRaised += handler; + + public void PortUnsubscribeEvent(IQuikPortHandle port, EventHandler handler) => ((OpenTKPort)port).EventRaised -= handler; + + public void PortFocus(IQuikPortHandle port) => ((OpenTKPort)port).Focus(); + + public void PortShow(IQuikPortHandle port, bool shown = true) => ((OpenTKPort)port).Show(shown); + + public void PortPaint(IQuikPortHandle port, CommandList commands) => ((OpenTKPort)port).Paint(commands); } } \ No newline at end of file diff --git a/Quik.OpenTK/OpenTKPort.cs b/Quik.OpenTK/OpenTKPort.cs index ae529a7..df6dcea 100644 --- a/Quik.OpenTK/OpenTKPort.cs +++ b/Quik.OpenTK/OpenTKPort.cs @@ -8,7 +8,7 @@ using Quik.VertexGenerator; namespace Quik.OpenTK { - public class OpenTKPort : IQuikPort + public class OpenTKPort : IQuikPortHandle { private readonly NativeWindow _window; private readonly GL21Driver _glDriver; @@ -70,7 +70,7 @@ namespace Quik.OpenTK QRectangle view = new QRectangle(Size, new QVec2(0, 0)); _vertexEngine.Reset(); - _vertexEngine.ProcessCommands(new QRectangle(), queue); + _vertexEngine.ProcessCommands(view, queue); if (!_window.Context.IsCurrent) _window.Context.MakeCurrent(); diff --git a/Quik/PAL/IQuikHost.cs b/Quik/PAL/IQuikHost.cs deleted file mode 100644 index 571fb1f..0000000 --- a/Quik/PAL/IQuikHost.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using Quik.Media; - -namespace Quik.PAL -{ - /// - /// The primary primary platform abstraction interface for Quik hosts. - /// - public interface IQuikPlatform : IDisposable - { - /// - /// The title of the application. - /// - string Title { get; set; } - - /// - /// The default icon for the application. - /// - QImage Icon { get; set; } - - /// - /// The event raised when an event is received. - /// - event EventHandler EventRaised; - - /// - /// Create a window. - /// - /// The window instance. - IQuikPort CreatePort(); - - /// - /// Raise the events that have been enqueued. - /// - /// True to block until a new event arrives. - void ProcessEvents(bool block); - } -} \ No newline at end of file diff --git a/Quik/PAL/IQuikPlatform.cs b/Quik/PAL/IQuikPlatform.cs new file mode 100644 index 0000000..d481fd5 --- /dev/null +++ b/Quik/PAL/IQuikPlatform.cs @@ -0,0 +1,59 @@ +using System; +using Quik.CommandMachine; +using Quik.Media; + +namespace Quik.PAL +{ + /// + /// An empty interface to statically type Quik port handles. + /// + public interface IQuikPortHandle + { + } + + /// + /// The primary primary platform abstraction interface for Quik hosts. + /// + public interface IQuikPlatform : IDisposable + { + /// + /// The title of the application. + /// + string Title { get; set; } + + /// + /// The default icon for the application. + /// + QImage Icon { get; set; } + + /// + /// The event raised when an event is received. + /// + event EventHandler EventRaised; + + /// + /// Raise the events that have been enqueued. + /// + /// True to block until a new event arrives. + void ProcessEvents(bool block); + + /// + /// Create a window. + /// + /// The window instance. + IQuikPortHandle CreatePort(); + void DestroyPort(IQuikPortHandle port); + string PortGetTitle(IQuikPortHandle port); + void PortSetTitle(IQuikPortHandle port, string title); + QVec2 PortGetSize(IQuikPortHandle port); + void PortSetSize(IQuikPortHandle port, QVec2 size); + QVec2 PortGetPosition(IQuikPortHandle port); + void PortSetPosition(IQuikPortHandle port, QVec2 position); + bool PortIsValid(IQuikPortHandle port); + void PortSubscribeEvent(IQuikPortHandle port, EventHandler handler); + void PortUnsubscribeEvent(IQuikPortHandle port, EventHandler handler); + void PortFocus(IQuikPortHandle port); + void PortShow(IQuikPortHandle port, bool shown = true); + void PortPaint(IQuikPortHandle port, CommandList commands); + } +} \ No newline at end of file diff --git a/Quik/PAL/IQuikPort.cs b/Quik/PAL/IQuikPort.cs deleted file mode 100644 index a8c65fe..0000000 --- a/Quik/PAL/IQuikPort.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using Quik.CommandMachine; - -namespace Quik.PAL -{ - /// - /// An abstraction over the a window or a rendering context. - /// - public interface IQuikPort : IDisposable - { - /// - /// Title of the window, if applicable. - /// - string Title { get; set; } - - /// - /// Size of the window. - /// - QVec2 Size { get; set; } - - /// - /// Position of the window in the coordinate system. - /// - QVec2 Position { get; set; } - bool IsValid { get; } - - /// - /// Called when an event for this port is raised. - /// - event EventHandler EventRaised; - - /// - /// Focus the window, bringing it to the front. - /// - void Focus(); - - /// - /// Show or hide the window. - /// - /// True to show the window, false to hide. - void Show(bool shown = true); - - /// - /// Paint the given command queue onto the port. - /// - /// The command queue to paint. - void Paint(CommandList queue); - } -} \ No newline at end of file diff --git a/Quik/PAL/QuikPort.cs b/Quik/PAL/QuikPort.cs new file mode 100644 index 0000000..f7d27c5 --- /dev/null +++ b/Quik/PAL/QuikPort.cs @@ -0,0 +1,92 @@ +using Quik.CommandMachine; +using Quik.Controls; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Quik.PAL +{ + /// + /// An abstraction layer over the UI input and output. + /// + public class QuikPort + { + private readonly IQuikPortHandle handle; + private readonly IQuikPlatform platform; + + public string Title + { + get => platform.PortGetTitle(handle); + set => platform.PortSetTitle(handle, value); + } + + public QVec2 Size + { + get => platform.PortGetSize(handle); + set => platform.PortSetSize(handle, value); + } + + public QVec2 Position + { + get => platform.PortGetPosition(handle); + set => platform.PortSetPosition(handle, value); + } + + public UIBase UIElement { get; set; } + + public bool IsValid => platform.PortIsValid(handle); + + public event EventHandler EventRaised + { + add + { + platform.PortSubscribeEvent(handle, value); + } + remove + { + platform.PortUnsubscribeEvent(handle, value); + } + } + + public QuikPort(IQuikPlatform platform) + { + this.platform = platform; + handle = platform.CreatePort(); + } + + bool isDisposed = false; + public void Dispose() + { + if (isDisposed) return; + + platform.DestroyPort(handle); + isDisposed = true; + } + + public void Focus() + { + platform.PortFocus(handle); + } + + public void Paint(CommandList list = null) + { + if (UIElement == null) + return; + + if(list == null) + list = new CommandList(); + + list.Clear(); + UIElement.Bounds = new QRectangle(Size, new QVec2(0,0)); + UIElement.Paint(list); + platform.PortPaint(handle, list); + } + + public void Show(bool shown = true) + { + platform.PortShow(handle, shown); + } + } +} diff --git a/Quik/QuikApplication.cs b/Quik/QuikApplication.cs index 734d581..af3b74e 100644 --- a/Quik/QuikApplication.cs +++ b/Quik/QuikApplication.cs @@ -4,6 +4,7 @@ using Quik.CommandMachine; using Quik.Controls; using Quik.Media; using Quik.PAL; +using Quik.Typography; namespace Quik { @@ -35,7 +36,9 @@ namespace Quik set => Platform.Icon = value; } - public View MainView { get; private set; } = null; + public QuikPort MainPort { get; private set; } = null; + + public FontProvider FontProvider { get; } /// /// List of media loaders, drivers that load media such as images and fonts. @@ -45,25 +48,56 @@ namespace Quik public QuikApplication(IQuikPlatform platform) { Platform = platform; + FontProvider = new FontProvider(this); + } + + public IDisposable GetMedia(object key, MediaHint hint) + { + IDisposable disposable = null; + + foreach (MediaLoader loader in MediaLoaders) + { + disposable = loader.GetMedia(key, hint); + + if (disposable != null) + break; + } + + return disposable; + } + + public IDisposable GetMedia(T key, MediaHint hint) + { + IDisposable disposable = null; + + foreach (MediaLoader loader in MediaLoaders) + { + if (loader is MediaLoader typedLoader) + { + disposable = typedLoader.GetMedia(key, hint); + + if (disposable != null) + break; + } + } + + return disposable; } public void Run(View mainView) { - IQuikPort port = Platform.CreatePort(); + MainPort = new QuikPort(Platform) { UIElement = mainView }; CommandList cmd = new CommandList(); - MainView = mainView; + MainPort.EventRaised += (sender, ea) => mainView.NotifyEvent(sender, ea); - port.EventRaised += (sender, ea) => mainView.NotifyEvent(sender, ea); - - while (port.IsValid) + while (MainPort.IsValid) { Platform.ProcessEvents(false); - if (port.IsValid) + if (MainPort.IsValid) { cmd.Clear(); - MainView.Paint(cmd); - port.Paint(cmd); + MainPort.Paint(cmd); } } }