Work on creating a simple message box dialog.
@ -4,7 +4,7 @@ using BindingFlags = System.Reflection.BindingFlags;
|
||||
|
||||
namespace Dashboard.Pal
|
||||
{
|
||||
public abstract class AppContext : IContextBase<AppContext, IAppContextExtension>
|
||||
public abstract class Application : IContextBase<Application, IApplicationExtension>
|
||||
{
|
||||
public abstract string DriverName { get; }
|
||||
public abstract string DriverVendor { get; }
|
||||
@ -16,12 +16,17 @@ namespace Dashboard.Pal
|
||||
public bool IsDisposed { get; private set; } = false;
|
||||
public IContextDebugger? Debugger { get; set; }
|
||||
|
||||
private readonly TypeDictionary<IAppContextExtension> _extensions =
|
||||
new TypeDictionary<IAppContextExtension>(true);
|
||||
private readonly TypeDictionary<IAppContextExtension, Func<IAppContextExtension>> _preloadedExtensions =
|
||||
new TypeDictionary<IAppContextExtension, Func<IAppContextExtension>>(true);
|
||||
private readonly TypeDictionary<IApplicationExtension> _extensions =
|
||||
new TypeDictionary<IApplicationExtension>(true);
|
||||
private readonly TypeDictionary<IApplicationExtension, Func<IApplicationExtension>> _preloadedExtensions =
|
||||
new TypeDictionary<IApplicationExtension, Func<IApplicationExtension>>(true);
|
||||
|
||||
~AppContext()
|
||||
public Application()
|
||||
{
|
||||
Current = this;
|
||||
}
|
||||
|
||||
~Application()
|
||||
{
|
||||
InvokeDispose(false);
|
||||
}
|
||||
@ -83,19 +88,32 @@ namespace Dashboard.Pal
|
||||
window.WindowManager = wm;
|
||||
return window;
|
||||
}
|
||||
|
||||
public IWindow CreateDialogWindow(IWindow? parent = null)
|
||||
{
|
||||
if (parent is IVirtualWindow virtualWindow)
|
||||
{
|
||||
IWindow? window = virtualWindow.WindowManager?.CreateWindow();
|
||||
|
||||
if (window != null)
|
||||
return window;
|
||||
}
|
||||
|
||||
return CreatePhysicalWindow();
|
||||
}
|
||||
#endregion
|
||||
|
||||
public bool IsExtensionAvailable<T>() where T : IAppContextExtension
|
||||
public bool IsExtensionAvailable<T>() where T : IApplicationExtension
|
||||
{
|
||||
return _extensions.Contains<T>() || _preloadedExtensions.Contains<T>();
|
||||
}
|
||||
|
||||
public bool ExtensionPreload<T>() where T : IAppContextExtension, new()
|
||||
public bool ExtensionPreload<T>() where T : IApplicationExtension, new()
|
||||
{
|
||||
return _preloadedExtensions.Add<T>(() => new T());
|
||||
}
|
||||
|
||||
public T ExtensionRequire<T>() where T : IAppContextExtension
|
||||
public T ExtensionRequire<T>() where T : IApplicationExtension
|
||||
{
|
||||
T? extension = default;
|
||||
|
||||
@ -107,7 +125,7 @@ namespace Dashboard.Pal
|
||||
if (_extensions.TryGet(out extension))
|
||||
return extension;
|
||||
|
||||
if (_preloadedExtensions.Remove<T>(out Func<IAppContextExtension>? loader))
|
||||
if (_preloadedExtensions.Remove<T>(out Func<IApplicationExtension>? loader))
|
||||
{
|
||||
extension = (T)loader!();
|
||||
}
|
||||
@ -128,7 +146,7 @@ namespace Dashboard.Pal
|
||||
{
|
||||
if (!isDisposing) return;
|
||||
|
||||
foreach (IAppContextExtension extension in _extensions)
|
||||
foreach (IApplicationExtension extension in _extensions)
|
||||
{
|
||||
extension.Dispose();
|
||||
}
|
||||
@ -145,5 +163,12 @@ namespace Dashboard.Pal
|
||||
}
|
||||
|
||||
public void Dispose() => InvokeDispose(true);
|
||||
|
||||
[ThreadStatic] private static Application _current;
|
||||
public static Application Current
|
||||
{
|
||||
get => _current ?? throw new InvalidOperationException("There is currently no current application.");
|
||||
set => _current = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10,6 +10,9 @@ namespace Dashboard.Pal
|
||||
private readonly TypeDictionary<IDeviceContextExtension, Func<IDeviceContextExtension>> _preloadedExtensions =
|
||||
new TypeDictionary<IDeviceContextExtension, Func<IDeviceContextExtension>>(true);
|
||||
|
||||
private Dictionary<string, object> _attributes = new Dictionary<string, object>();
|
||||
|
||||
|
||||
public abstract string DriverName { get; }
|
||||
public abstract string DriverVendor { get; }
|
||||
public abstract Version DriverVersion { get; }
|
||||
@ -72,6 +75,29 @@ namespace Dashboard.Pal
|
||||
return extension;
|
||||
}
|
||||
|
||||
public void SetAttribute(string name, object? v)
|
||||
{
|
||||
if (v != null)
|
||||
_attributes[name] = v;
|
||||
else
|
||||
_attributes.Remove(name);
|
||||
}
|
||||
|
||||
public void SetAttribute<T>(string name, T v) => SetAttribute(name, (object?)v);
|
||||
|
||||
public object? GetAttribute(string name)
|
||||
{
|
||||
return _attributes.GetValueOrDefault(name);
|
||||
}
|
||||
|
||||
public T? GetAttribute<T>(string name)
|
||||
{
|
||||
object? o = GetAttribute(name);
|
||||
if (o != null)
|
||||
return (T?)o;
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implement your dispose in this function.
|
||||
/// </summary>
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
namespace Dashboard.Pal
|
||||
{
|
||||
public interface IAppContextExtension : IContextExtensionBase<AppContext>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
7
Dashboard.Common/Pal/IApplicationExtension.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Dashboard.Pal
|
||||
{
|
||||
public interface IApplicationExtension : IContextExtensionBase<Application>
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@ -50,6 +50,7 @@ namespace Dashboard.Windowing
|
||||
/// </summary>
|
||||
public interface IVirtualWindow : IWindow, IEventListener
|
||||
{
|
||||
IWindowManager? WindowManager { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -98,6 +98,11 @@ namespace Dashboard.Drawing.OpenGL.Pal
|
||||
return;
|
||||
}
|
||||
|
||||
if (levels == 0)
|
||||
{
|
||||
levels = Math.Max(Math.ILogB(width), Math.ILogB(height));
|
||||
}
|
||||
|
||||
Bind();
|
||||
SizedInternalFormat glFormat = GetFormat(format);
|
||||
if (Extension.SupportsArbTextureStorage)
|
||||
@ -122,18 +127,23 @@ namespace Dashboard.Drawing.OpenGL.Pal
|
||||
switch (Type)
|
||||
{
|
||||
case TextureType.Texture1D:
|
||||
GL.TexImage1D(Target, 0, (InternalFormat)glFormat, width, 0, (OGL.PixelFormat)glFormat, PixelType.Byte, IntPtr.Zero);
|
||||
GL.TexImage1D(Target, 0, (InternalFormat)glFormat, width, 0, (OGL.PixelFormat)glFormat, PixelType.UnsignedByte, IntPtr.Zero);
|
||||
break;
|
||||
case TextureType.Texture2D:
|
||||
GL.TexImage2D(Target, 0, (InternalFormat)glFormat, width, height, 0, (OGL.PixelFormat)glFormat, PixelType.Byte, IntPtr.Zero);
|
||||
GL.TexImage2D(Target, 0, (InternalFormat)glFormat, width, height, 0, (OGL.PixelFormat)glFormat, PixelType.UnsignedByte, IntPtr.Zero);
|
||||
break;
|
||||
case TextureType.Texture3D:
|
||||
case TextureType.Texture2DArray:
|
||||
case TextureType.Texture2DCube:
|
||||
GL.TexImage3D(Target, 0, (InternalFormat)glFormat, width, height, depth, 0, (OGL.PixelFormat)glFormat, PixelType.Byte, IntPtr.Zero);
|
||||
GL.TexImage3D(Target, 0, (InternalFormat)glFormat, width, height, depth, 0, (OGL.PixelFormat)glFormat, PixelType.UnsignedByte, IntPtr.Zero);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Width = width;
|
||||
Height = height;
|
||||
Depth = depth;
|
||||
Levels = levels;
|
||||
}
|
||||
|
||||
public void Read<T>(Span<T> buffer, int level = 0, int align = 0) where T : unmanaged
|
||||
@ -160,7 +170,7 @@ namespace Dashboard.Drawing.OpenGL.Pal
|
||||
|
||||
PixelType glType = format switch
|
||||
{
|
||||
PixelFormat.R8I or PixelFormat.Rg8I or PixelFormat.Rgb8I or PixelFormat.Rgba8I => PixelType.Byte,
|
||||
PixelFormat.R8I or PixelFormat.Rg8I or PixelFormat.Rgb8I or PixelFormat.Rgba8I => PixelType.UnsignedByte,
|
||||
PixelFormat.R16F or PixelFormat.Rg16F or PixelFormat.Rgb16F or PixelFormat.Rgba16F => PixelType.HalfFloat,
|
||||
_ => throw new NotSupportedException()
|
||||
};
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
using Dashboard.Drawing.OpenGL.Pal;
|
||||
using Dashboard.Pal;
|
||||
using Dashboard.Windowing;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Platform;
|
||||
using AppContext = Dashboard.Pal.AppContext;
|
||||
using TK = OpenTK.Platform.Toolkit;
|
||||
|
||||
namespace Dashboard.OpenTK.PAL2
|
||||
{
|
||||
public class Pal2AppContext : AppContext
|
||||
public class Pal2Application : Application
|
||||
{
|
||||
public override string DriverName => "Dashboard OpenTK PAL2.0 Driver";
|
||||
public override string DriverVendor => "Dashboard";
|
||||
@ -6,17 +6,30 @@ namespace Dashboard.Controls
|
||||
{
|
||||
public class Control : IEventListener, IDisposable
|
||||
{
|
||||
private Form? _owner = null;
|
||||
|
||||
public string? Id { get; set; }
|
||||
public ClassSet Classes { get; }
|
||||
public Form? Owner { get; protected set; } = null;
|
||||
public Form Owner
|
||||
{
|
||||
get => _owner ?? throw NoOwnerException;
|
||||
protected set
|
||||
{
|
||||
_owner = value;
|
||||
OnOwnerChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
public Control? Parent { get; private set; } = null;
|
||||
public bool Disposed { get; private set; }
|
||||
public virtual DrawQueue DrawQueue => Owner?.DrawQueue ?? throw NoOwnerException;
|
||||
public virtual Box2d ClientArea { get; set; }
|
||||
public bool IsFocused => _owner?.FocusedControl == this;
|
||||
|
||||
public event EventHandler? Painting;
|
||||
public event EventHandler? OwnerChanged;
|
||||
public event EventHandler? ParentChanged;
|
||||
public event EventHandler? FocusGained;
|
||||
public event EventHandler? FocusLost;
|
||||
public event EventHandler? Disposing;
|
||||
public event EventHandler? Resized;
|
||||
|
||||
@ -49,6 +62,7 @@ namespace Dashboard.Controls
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing) Disposing?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public void Dispose() => InvokeDispose(true);
|
||||
@ -61,6 +75,42 @@ namespace Dashboard.Controls
|
||||
internal static void SetParent(Control parent, Control child)
|
||||
{
|
||||
child.Parent = parent;
|
||||
child.ParentChanged?.Invoke(child, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public virtual void Focus()
|
||||
{
|
||||
(Owner ?? throw NoOwnerException).Focus(this);
|
||||
}
|
||||
|
||||
protected virtual void OnFocusGained(object sender)
|
||||
{
|
||||
FocusGained?.Invoke(sender, EventArgs.Empty);
|
||||
}
|
||||
|
||||
protected virtual void OnFocusLost(object sender)
|
||||
{
|
||||
FocusLost?.Invoke(sender, EventArgs.Empty);
|
||||
}
|
||||
|
||||
internal static void InvokeFocusGained(Form form, Control control)
|
||||
{
|
||||
control.OnFocusGained(form);
|
||||
}
|
||||
|
||||
internal static void InvokeFocusLost(Form form, Control control)
|
||||
{
|
||||
control.OnFocusLost(form);
|
||||
}
|
||||
|
||||
protected virtual void OnResize()
|
||||
{
|
||||
Resized?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void OnOwnerChanged(Form value)
|
||||
{
|
||||
OwnerChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
protected static Exception NoOwnerException => new Exception("No form owns this control");
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using Dashboard.Drawing;
|
||||
using Dashboard.Resources;
|
||||
using Dashboard.Windowing;
|
||||
|
||||
namespace Dashboard.Controls
|
||||
@ -7,6 +9,10 @@ namespace Dashboard.Controls
|
||||
{
|
||||
public IWindow Window { get; }
|
||||
|
||||
public Image? WindowIcon { get; set; }
|
||||
public string? Title { get; set; } = "Untitled Form";
|
||||
public Control? FocusedControl { get; private set; } = null;
|
||||
|
||||
public override Box2d ClientArea
|
||||
{
|
||||
get => new Box2d(0, 0, Window.ClientSize.Width, Window.ClientSize.Height);
|
||||
@ -17,5 +23,15 @@ namespace Dashboard.Controls
|
||||
{
|
||||
Window = window;
|
||||
}
|
||||
|
||||
|
||||
public void Focus(Control control)
|
||||
{
|
||||
if (FocusedControl != null)
|
||||
InvokeFocusLost(this, FocusedControl);
|
||||
|
||||
FocusedControl = control;
|
||||
InvokeFocusGained(this, control);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ namespace Dashboard.Controls
|
||||
public override void OnPaint()
|
||||
{
|
||||
base.OnPaint();
|
||||
DrawQueue.Text(new Vector3(ClientArea.Min, 0), TextBrush, Text, Font);
|
||||
// DrawQueue.Text(new Vector3(ClientArea.Min, 0), TextBrush, Text, Font);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
138
Dashboard/Controls/MessageBox.cs
Normal file
@ -0,0 +1,138 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Dashboard.Resources;
|
||||
using Dashboard.Windowing;
|
||||
|
||||
namespace Dashboard.Controls
|
||||
{
|
||||
public enum MessageBoxIcon
|
||||
{
|
||||
Info,
|
||||
Question,
|
||||
Warning,
|
||||
Error,
|
||||
Custom,
|
||||
}
|
||||
|
||||
public enum MessageBoxButtons
|
||||
{
|
||||
AbortRetryIgnore,
|
||||
CancelRetryContinue,
|
||||
Ok,
|
||||
OkCancel,
|
||||
RetryCancel,
|
||||
YesNo,
|
||||
YesNoCancel,
|
||||
Custom,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A simple message box dialog.
|
||||
/// </summary>
|
||||
public class MessageBox : Form
|
||||
{
|
||||
private Image? _icon;
|
||||
private Label _label = new Label();
|
||||
private readonly List<Label> _buttons = new List<Label>();
|
||||
|
||||
public MessageBoxIcon Icon { get; set; }
|
||||
public Image? CustomImage { get; set; }
|
||||
public string? Message { get; set; }
|
||||
public MessageBoxButtons Buttons { get; set; }
|
||||
public ObservableCollection<string> CustomButtons { get; } = new ObservableCollection<string>();
|
||||
public int Result { get; private set; }
|
||||
|
||||
public MessageBox(IWindow window) : base(window)
|
||||
{
|
||||
SetParent(this, _label);
|
||||
}
|
||||
|
||||
public static readonly Image s_questionIcon;
|
||||
public static readonly Image s_infoIcon;
|
||||
public static readonly Image s_warningIcon;
|
||||
public static readonly Image s_errorIcon;
|
||||
|
||||
private static readonly ImmutableList<string> s_abortRetryContinue = ["Abort", "Retry", "Continue"];
|
||||
private static readonly ImmutableList<string> s_cancelRetryContinue = ["Cancel", "Retry", "Continue"];
|
||||
private static readonly ImmutableList<string> s_ok = ["OK"];
|
||||
private static readonly ImmutableList<string> s_okCancel = ["OK", "Cancel"];
|
||||
private static readonly ImmutableList<string> s_retryCancel = ["Retry", "Cancel"];
|
||||
private static readonly ImmutableList<string> s_yesNo = ["Yes", "No"];
|
||||
private static readonly ImmutableList<string> s_yesNoCancel = ["Yes", "No", "Cancel"];
|
||||
|
||||
static MessageBox()
|
||||
{
|
||||
Assembly asm = typeof(MessageBox).Assembly;
|
||||
using (Stream str = asm.GetManifestResourceStream("Dashboard.Resources.question.png")!)
|
||||
s_questionIcon = Image.Load(str);
|
||||
using (Stream str = asm.GetManifestResourceStream("Dashboard.Resources.info.png")!)
|
||||
s_infoIcon = Image.Load(str);
|
||||
using (Stream str = asm.GetManifestResourceStream("Dashboard.Resources.warning.png")!)
|
||||
s_warningIcon = Image.Load(str);
|
||||
using (Stream str = asm.GetManifestResourceStream("Dashboard.Resources.error.png")!)
|
||||
s_errorIcon = Image.Load(str);
|
||||
}
|
||||
|
||||
public override void OnPaint()
|
||||
{
|
||||
base.OnPaint();
|
||||
}
|
||||
|
||||
public static MessageBox Create(IWindow window, string message, string title, MessageBoxIcon icon, MessageBoxButtons buttons)
|
||||
{
|
||||
return new MessageBox(window)
|
||||
{
|
||||
Message = message,
|
||||
Title = title,
|
||||
Icon = icon,
|
||||
Buttons = buttons,
|
||||
};
|
||||
}
|
||||
|
||||
// public static MessageBox Create(IWindow window, string message, string title, Image icon, IEnumerable<string> buttons)
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
|
||||
private static string GetDefaultTitle(MessageBoxIcon icon)
|
||||
{
|
||||
return icon switch
|
||||
{
|
||||
MessageBoxIcon.Error => "Error",
|
||||
MessageBoxIcon.Info => "Info",
|
||||
MessageBoxIcon.Question => "Question",
|
||||
MessageBoxIcon.Warning => "Warning",
|
||||
_ => "Message Box",
|
||||
};
|
||||
}
|
||||
|
||||
private static Image GetDefaultIcon(MessageBoxIcon icon)
|
||||
{
|
||||
return icon switch
|
||||
{
|
||||
MessageBoxIcon.Error => s_errorIcon,
|
||||
MessageBoxIcon.Question => s_questionIcon,
|
||||
MessageBoxIcon.Warning => s_warningIcon,
|
||||
_ => s_infoIcon,
|
||||
};
|
||||
}
|
||||
|
||||
private static ImmutableList<string> GetDefaultButtons(MessageBoxButtons buttons)
|
||||
{
|
||||
return buttons switch
|
||||
{
|
||||
MessageBoxButtons.AbortRetryIgnore => s_abortRetryContinue,
|
||||
MessageBoxButtons.CancelRetryContinue => s_cancelRetryContinue,
|
||||
MessageBoxButtons.OkCancel => s_okCancel,
|
||||
MessageBoxButtons.RetryCancel => s_retryCancel,
|
||||
MessageBoxButtons.YesNo => s_yesNo,
|
||||
MessageBoxButtons.YesNoCancel => s_yesNoCancel,
|
||||
_ => s_ok,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9,6 +9,11 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Dashboard.Common\Dashboard.Common.csproj" />
|
||||
<ProjectReference Include="..\Dashboard.Drawing\Dashboard.Drawing.csproj" />
|
||||
<EmbeddedResource Include="Resources\**\*.png"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ReFuel.StbImage" Version="2.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
81
Dashboard/Resources/Image.cs
Normal file
@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Dashboard.Drawing;
|
||||
using Dashboard.Pal;
|
||||
using ReFuel.Stb;
|
||||
using ReFuel.Stb.Native;
|
||||
|
||||
namespace Dashboard.Resources
|
||||
{
|
||||
public class Image(PixelFormat format, int width, int height, byte[] data, bool premultiplied = false) : IDisposable
|
||||
{
|
||||
protected readonly ConditionalWeakTable<DeviceContext, ITexture> Textures =
|
||||
new ConditionalWeakTable<DeviceContext, ITexture>();
|
||||
|
||||
protected virtual TextureType TextureType => TextureType.Texture2D;
|
||||
public PixelFormat Format { get; } = format;
|
||||
public int Width { get; } = width;
|
||||
public int Height { get; } = height;
|
||||
public bool Premultiplied { get; } = premultiplied;
|
||||
|
||||
public bool IsDisposed { get; private set; } = false;
|
||||
|
||||
~Image()
|
||||
{
|
||||
InvokeDispose(false);
|
||||
}
|
||||
|
||||
public virtual ITexture InternTexture(DeviceContext dc)
|
||||
{
|
||||
if (Textures.TryGetValue(dc, out ITexture? texture))
|
||||
return texture;
|
||||
|
||||
ITextureExtension ext = dc.ExtensionRequire<ITextureExtension>();
|
||||
texture = ext.CreateTexture(TextureType.Texture2D);
|
||||
texture.SetStorage(Format, Width, Height, 1, 0);
|
||||
texture.Write<byte>(Format, data);
|
||||
texture.Premultiplied = Premultiplied;
|
||||
texture.GenerateMipmaps();
|
||||
Textures.Add(dc, texture);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
private void InvokeDispose(bool disposing)
|
||||
{
|
||||
if (IsDisposed)
|
||||
return;
|
||||
IsDisposed = true;
|
||||
|
||||
Dispose(disposing);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
foreach ((DeviceContext dc, ITexture texture) in Textures)
|
||||
{
|
||||
texture.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() => InvokeDispose(true);
|
||||
|
||||
public static Image Load(Stream stream)
|
||||
{
|
||||
using StbImage image = StbImage.Load(stream, StbiImageFormat.Rgba);
|
||||
ReadOnlySpan<byte> data = image.AsSpan<byte>();
|
||||
return new Image(
|
||||
image.Format switch
|
||||
{
|
||||
StbiImageFormat.Grey => PixelFormat.R8I,
|
||||
StbiImageFormat.Rgb => PixelFormat.Rgb8I,
|
||||
StbiImageFormat.Rgba => PixelFormat.Rgba8I,
|
||||
// StbiImageFormat.GreyAlpha) => PixelFormat.Rg8I,
|
||||
_ => throw new Exception("Unrecognized pixel format"),
|
||||
},
|
||||
image.Width, image.Height,
|
||||
data.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
Dashboard/Resources/error.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
85
Dashboard/Resources/error.svg
Normal file
@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 12.7 12.7"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
sodipodi:docname="error.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
inkscape:zoom="6.0664802"
|
||||
inkscape:cx="-5.7694081"
|
||||
inkscape:cy="25.962336"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1364"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
showguides="true">
|
||||
<sodipodi:guide
|
||||
position="6.3500001,12.7"
|
||||
orientation="-1,0"
|
||||
id="guide1"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
inkscape:color="rgb(0,134,229)" />
|
||||
<sodipodi:guide
|
||||
position="3.705891,12.686148"
|
||||
orientation="-1,0"
|
||||
id="guide2"
|
||||
inkscape:label=""
|
||||
inkscape:locked="false"
|
||||
inkscape:color="rgb(0,134,229)" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#ff0000;stroke:#d60000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path1"
|
||||
inkscape:flatsided="true"
|
||||
sodipodi:sides="8"
|
||||
sodipodi:cx="6.3499999"
|
||||
sodipodi:cy="6.3499999"
|
||||
sodipodi:r1="6.8657174"
|
||||
sodipodi:r2="8.2966747"
|
||||
sodipodi:arg1="1.9608592"
|
||||
sodipodi:arg2="2.3535583"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="M 3.7393344,12.7 0.01385251,8.9941088 -2.0290497e-7,3.7393344 3.705891,0.01385251 8.9606654,-2.0290497e-7 12.686147,3.705891 12.7,8.9606654 8.9941088,12.686147 Z"
|
||||
transform="matrix(0.92700733,0,0,0.92700733,0.46350342,0.46350342)" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:9.87777px;line-height:normal;font-family:'Rec Mono Linear';-inkscape-font-specification:'Rec Mono Linear Bold';text-align:center;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;direction:ltr;text-orientation:upright;text-anchor:middle;fill:#ffffff;stroke:none;stroke-width:0.600001"
|
||||
x="6.3154373"
|
||||
y="9.0071211"
|
||||
id="text1"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan1"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:'Rec Mono Linear';-inkscape-font-specification:'Rec Mono Linear Bold';fill:#ffffff;stroke-width:0.6"
|
||||
x="6.3154373"
|
||||
y="9.0071211">x</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
BIN
Dashboard/Resources/info.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
62
Dashboard/Resources/info.svg
Normal file
@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 12.7 12.7"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
sodipodi:docname="info.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
inkscape:zoom="15.987983"
|
||||
inkscape:cx="14.823634"
|
||||
inkscape:cy="21.234699"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1364"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:#00b200;fill-opacity:1;stroke:#009900;stroke-width:0.573001;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect1"
|
||||
width="12.127"
|
||||
height="12.127"
|
||||
x="0.28650019"
|
||||
y="0.28650019"
|
||||
rx="1.0105833"
|
||||
ry="1.0105834" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:italic;font-size:9.87777px;line-height:normal;font-family:'Rec Mono Linear';-inkscape-font-specification:'Rec Mono Linear Italic';text-align:center;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;direction:ltr;text-orientation:upright;text-anchor:middle;fill:#f9f9f9;stroke:none;stroke-width:0.600001"
|
||||
x="6.3351822"
|
||||
y="10.172698"
|
||||
id="text1"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan1"
|
||||
style="font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:'Rec Mono Linear';-inkscape-font-specification:'Rec Mono Linear Bold Italic';fill:#f9f9f9;stroke-width:0.6"
|
||||
x="6.3351822"
|
||||
y="10.172698">i</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
BIN
Dashboard/Resources/question.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
66
Dashboard/Resources/question.svg
Normal file
@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 12.7 12.7"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
sodipodi:docname="question.svg"
|
||||
xml:space="preserve"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
inkscape:zoom="6.4560796"
|
||||
inkscape:cx="12.701206"
|
||||
inkscape:cy="14.172688"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1364"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
showguides="true"><sodipodi:guide
|
||||
position="6.3500001,12.7"
|
||||
orientation="-1,0"
|
||||
id="guide1"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
inkscape:color="rgb(0,134,229)" /><sodipodi:guide
|
||||
position="3.705891,12.686148"
|
||||
orientation="-1,0"
|
||||
id="guide2"
|
||||
inkscape:label=""
|
||||
inkscape:locked="false"
|
||||
inkscape:color="rgb(0,134,229)" /></sodipodi:namedview><defs
|
||||
id="defs1" /><g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"><circle
|
||||
style="fill:#0000ff;stroke:#0000cc;stroke-width:0.9271;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path2"
|
||||
cx="6.3500004"
|
||||
cy="6.3500004"
|
||||
r="5.8864961" /><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:9.87777px;line-height:normal;font-family:'Rec Mono Linear';-inkscape-font-specification:'Rec Mono Linear Bold';text-align:center;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;direction:ltr;text-orientation:upright;text-anchor:middle;fill:#ffffff;stroke:none;stroke-width:0.600001"
|
||||
x="6.2907381"
|
||||
y="9.8615408"
|
||||
id="text1"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan1"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:'Rec Mono Linear';-inkscape-font-specification:'Rec Mono Linear Bold';fill:#ffffff;stroke-width:0.6"
|
||||
x="6.2907381"
|
||||
y="9.8615408">?</tspan></text></g></svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
BIN
Dashboard/Resources/warning.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
67
Dashboard/Resources/warning.svg
Normal file
@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 12.7 12.7"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
sodipodi:docname="warning.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="23"
|
||||
inkscape:cy="24.5"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1364"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
showguides="true">
|
||||
<sodipodi:guide
|
||||
position="6.3500001,12.7"
|
||||
orientation="-1,0"
|
||||
id="guide1"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
inkscape:color="rgb(0,134,229)" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:#ffcc00;stroke:#ffbb00;stroke-width:0.9271;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 0.46350557,12.236497 6.3500001,0.46350801 12.236494,12.236497 Z"
|
||||
id="path1"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:9.87777px;line-height:normal;font-family:'Rec Mono Linear';-inkscape-font-specification:'Rec Mono Linear Bold';text-align:center;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;direction:ltr;text-orientation:upright;text-anchor:middle;fill:#ffcc00;stroke:none;stroke-width:0.600001"
|
||||
x="6.2858014"
|
||||
y="10.821102"
|
||||
id="text1"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan1"
|
||||
style="fill:#000000;stroke-width:0.6;-inkscape-font-specification:'Rec Mono Linear Bold';font-family:'Rec Mono Linear';font-weight:bold;font-style:normal;font-stretch:normal;font-variant:normal"
|
||||
x="6.2858014"
|
||||
y="10.821102">!</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
@ -10,10 +10,13 @@ using OpenTK.Mathematics;
|
||||
using Box2d = Dashboard.Box2d;
|
||||
using TK = OpenTK.Platform.Toolkit;
|
||||
using Dashboard;
|
||||
using Dashboard.Controls;
|
||||
using Dashboard.Drawing.OpenGL.Pal;
|
||||
using Dashboard.Pal;
|
||||
using Dashboard.Windowing;
|
||||
using OpenTK.Windowing.GraphicsLibraryFramework;
|
||||
using AppContext = Dashboard.Pal.AppContext;
|
||||
using ReFuel.Stb;
|
||||
using Image = Dashboard.Resources.Image;
|
||||
using Vector4 = System.Numerics.Vector4;
|
||||
|
||||
TK.Init(new ToolkitOptions()
|
||||
@ -27,7 +30,7 @@ TK.Init(new ToolkitOptions()
|
||||
FeatureFlags = ToolkitFlags.EnableOpenGL,
|
||||
});
|
||||
|
||||
AppContext app = new Pal2AppContext()
|
||||
Application app = new Pal2Application()
|
||||
{
|
||||
GraphicsApiHints = new OpenGLGraphicsApiHints()
|
||||
{
|
||||
@ -106,6 +109,8 @@ EventQueue.EventRaised += (handle, type, eventArgs) =>
|
||||
TK.Window.SetMode(window.WindowHandle, WindowMode.Normal);
|
||||
// font = Typesetter.LoadFont("Nimbus Mono", 12f);
|
||||
|
||||
foreach (string str in typeof(Image).Assembly.GetManifestResourceNames()) Console.WriteLine(str);
|
||||
|
||||
window.Painting += (sender, ea) => {
|
||||
TK.Window.GetSize(window.WindowHandle, out Vector2i size);
|
||||
// executor.BeginFrame();
|
||||
@ -173,6 +178,8 @@ window.Painting += (sender, ea) => {
|
||||
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
||||
GL.ColorMask(true, true, true, true);
|
||||
|
||||
ITexture texture = MessageBox.s_questionIcon.InternTexture(context);
|
||||
|
||||
// executor.Draw(window.DrawQueue, new RectangleF(0, 0, size.X, size.Y), 1.5f /*(window as IDpiAwareWindow)?.Scale ?? 1*/);
|
||||
// executor.EndFrame();
|
||||
|
||||
|
||||