diff --git a/Hypercube.Client/Graphics/Rendering/Renderer.Render.cs b/Hypercube.Client/Graphics/Rendering/Renderer.Render.cs index edc2dc1..1dda4c0 100644 --- a/Hypercube.Client/Graphics/Rendering/Renderer.Render.cs +++ b/Hypercube.Client/Graphics/Rendering/Renderer.Render.cs @@ -33,7 +33,7 @@ public sealed partial class Renderer private void OnLoad() { _baseShader = new Shader("Resources/Shaders/base"); - _baseTexture = _textureManager.CreateHandler("Resources/Textures/opengl_logo.png"); + _baseTexture = _textureManager.CreateHandler("Resources/Textures/icon.png"); _baseTexture.Bind(); _cameraManager.SetMainCamera(_cameraManager.CreateCamera2D(MainWindow.Size)); diff --git a/Hypercube.Client/Graphics/Rendering/Renderer.cs b/Hypercube.Client/Graphics/Rendering/Renderer.cs index ad81e4e..6c356c4 100644 --- a/Hypercube.Client/Graphics/Rendering/Renderer.cs +++ b/Hypercube.Client/Graphics/Rendering/Renderer.cs @@ -94,6 +94,10 @@ private void OnStartup(RuntimeStartupEvent args) break; } + var windowIcons = _windowManager.LoadWindowIcon(_textureManager, "Resources/Icons").ToList(); + _windowManager.SetWindowIcons(MainWindow, windowIcons); + + InitOpenGL(); OnLoad(); diff --git a/Hypercube.Client/Graphics/Texturing/ITextureManager.cs b/Hypercube.Client/Graphics/Texturing/ITextureManager.cs index b6b7f9e..75cc0ce 100644 --- a/Hypercube.Client/Graphics/Texturing/ITextureManager.cs +++ b/Hypercube.Client/Graphics/Texturing/ITextureManager.cs @@ -3,6 +3,13 @@ public interface ITextureManager { ITexture Create(string path); + /// + /// Creates ITexture, allows to set flipping mode + /// + /// Path to image + /// DO FLIP + /// ITexture + ITexture Create(string path, bool doFlip); ITextureHandle CreateHandler(string path); ITextureHandle CreateHandler(ITexture texture); diff --git a/Hypercube.Client/Graphics/Texturing/TextureManager.cs b/Hypercube.Client/Graphics/Texturing/TextureManager.cs index 7420b4e..b241759 100644 --- a/Hypercube.Client/Graphics/Texturing/TextureManager.cs +++ b/Hypercube.Client/Graphics/Texturing/TextureManager.cs @@ -15,6 +15,16 @@ public ITexture Create(string path) return Create(ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha)); } + public ITexture Create(string path, bool doFlip) + { + if (doFlip) + StbImage.stbi_set_flip_vertically_on_load(0); + var texture = Create(path); + + StbImage.stbi_set_flip_vertically_on_load(1); + return texture; + } + public ITextureHandle CreateHandler(ITexture texture) { return new TextureHandle(texture); diff --git a/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.Window.cs b/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.Window.cs index 5a77a5c..4a92ee6 100644 --- a/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.Window.cs +++ b/Hypercube.Client/Graphics/Windows/Manager/GlfwWindowManager.Window.cs @@ -1,9 +1,12 @@ using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; using Hypercube.Client.Graphics.OpenGL; +using Hypercube.Client.Graphics.Texturing; using Hypercube.Client.Graphics.Windows.Manager.Registrations; using Hypercube.Client.Utilities; using OpenTK.Windowing.Common; using OpenTK.Windowing.GraphicsLibraryFramework; +using GlfwImage = OpenTK.Windowing.GraphicsLibraryFramework.Image; using Monitor = OpenTK.Windowing.GraphicsLibraryFramework.Monitor; namespace Hypercube.Client.Graphics.Windows.Manager; @@ -102,10 +105,10 @@ public WindowCreateResult WindowCreate(ContextInfo? context, WindowCreateSetting return new WindowCreateResult(null, GLFWHelper.GetError()); } - return new WindowCreateResult(WindowSetup(window), null); + return new WindowCreateResult(WindowSetup(window, settings), null); } - private GlfwWindowRegistration WindowSetup(Window* window) + private GlfwWindowRegistration WindowSetup(Window* window, WindowCreateSettings settings) { GLFWHelper.GetFramebufferSize(window, out var framebufferSize); GLFWHelper.GetWindowSize(window, out var size); @@ -121,14 +124,17 @@ private GlfwWindowRegistration WindowSetup(Window* window) }; registration.Handle = new WindowHandle(_renderer, registration); - + + // Setting icons + if (settings.WindowImages != null) + SetWindowIcons(registration, settings.WindowImages.ToList()); + // Setting callbacks GLFW.SetKeyCallback(window, OnWindowKeyHandled); GLFW.SetWindowCloseCallback(window, OnWindowClosed); GLFW.SetWindowSizeCallback(window, OnWindowResized); GLFW.SetWindowFocusCallback(window, OnWindowFocusChanged); - return registration; } @@ -178,5 +184,36 @@ private bool TryGetWindow(Window* window, [NotNullWhen(true)] out GlfwWindowRegi return null; } - + + public IEnumerable LoadWindowIcon(ITextureManager textureMan, string resPath) + { + var files = Directory.EnumerateFiles(resPath, "*.png"); + + foreach (var file in files) + { + yield return textureMan.Create(file, true); + } + } + + public void SetWindowIcons(WindowRegistration window, List images) + { + if (window is not GlfwWindowRegistration glfwWindow) + return; + + var count = images.Count; + + // ReSharper disable once SuggestVarOrType_Elsewhere + Span handles = stackalloc GCHandle[count]; + Span glfwImages = stackalloc GlfwImage[count]; + + for (var i = 0; i < count; i++) + { + var image = images[i]; + handles[i] = GCHandle.Alloc(image.Data, GCHandleType.Pinned); + var addrOfPinnedObject = (byte*) handles[i].AddrOfPinnedObject(); + glfwImages[i] = new GlfwImage(image.Width, image.Height, addrOfPinnedObject); + } + + GLFW.SetWindowIcon(glfwWindow.Pointer, glfwImages); + } } \ No newline at end of file diff --git a/Hypercube.Client/Graphics/Windows/Manager/IWindowManager.cs b/Hypercube.Client/Graphics/Windows/Manager/IWindowManager.cs index 52b9992..b9a4b3d 100644 --- a/Hypercube.Client/Graphics/Windows/Manager/IWindowManager.cs +++ b/Hypercube.Client/Graphics/Windows/Manager/IWindowManager.cs @@ -1,5 +1,6 @@ using Hypercube.Client.Graphics.Monitors; using Hypercube.Client.Graphics.OpenGL; +using Hypercube.Client.Graphics.Texturing; using Hypercube.Shared.Math.Vector; namespace Hypercube.Client.Graphics.Windows.Manager; @@ -29,6 +30,8 @@ public interface IWindowManager : IDisposable void WindowSetVisible(WindowRegistration registration, bool visible); void WindowSetSize(WindowRegistration registration, Vector2Int size); void WindowSwapBuffers(WindowRegistration window); + IEnumerable LoadWindowIcon(ITextureManager textureMan, string resPath); + void SetWindowIcons(WindowRegistration window, List images); nint GetProcAddress(string procName); } \ No newline at end of file diff --git a/Hypercube.Client/Graphics/Windows/WindowCreateSettings.cs b/Hypercube.Client/Graphics/Windows/WindowCreateSettings.cs index 50a996a..1e3d9b8 100644 --- a/Hypercube.Client/Graphics/Windows/WindowCreateSettings.cs +++ b/Hypercube.Client/Graphics/Windows/WindowCreateSettings.cs @@ -1,4 +1,5 @@ using Hypercube.Client.Graphics.Monitors; +using Hypercube.Client.Graphics.Texturing; using Hypercube.Shared.Math.Vector; namespace Hypercube.Client.Graphics.Windows; @@ -10,7 +11,8 @@ public class WindowCreateSettings public string Title = "Hypercube Window"; public Vector2Int Size = new(1280, 720); - + public ITexture[]? WindowImages = null; + public IMonitorHandle? Monitor; public bool Resizable = true; diff --git a/Resources/Icons/image.png b/Resources/Icons/image.png new file mode 100644 index 0000000..f3df425 Binary files /dev/null and b/Resources/Icons/image.png differ diff --git a/Resources/Textures/icon.png b/Resources/Textures/icon.png new file mode 100644 index 0000000..99ed4b5 Binary files /dev/null and b/Resources/Textures/icon.png differ