diff --git a/ImGui.Forms/Controls/ImageButton.cs b/ImGui.Forms/Controls/ImageButton.cs
index a8a74af..c8c3b84 100644
--- a/ImGui.Forms/Controls/ImageButton.cs
+++ b/ImGui.Forms/Controls/ImageButton.cs
@@ -50,7 +50,7 @@ protected override void UpdateInternal(Rectangle contentRect)
if ((IntPtr)Image != IntPtr.Zero)
{
- if ((ImGuiNET.ImGui.ImageButton((IntPtr)Image, GetImageSize()) || IsKeyDown(KeyAction)) && Enabled)
+ if ((ImGuiNET.ImGui.ImageButton($"##{Id}", (IntPtr)Image, GetImageSize()) || IsKeyDown(KeyAction)) && Enabled)
OnClicked();
}
else
diff --git a/ImGui.Forms/Controls/Layouts/TableLayout.cs b/ImGui.Forms/Controls/Layouts/TableLayout.cs
index b9272b9..ef02fb3 100644
--- a/ImGui.Forms/Controls/Layouts/TableLayout.cs
+++ b/ImGui.Forms/Controls/Layouts/TableLayout.cs
@@ -86,13 +86,13 @@ protected override void UpdateInternal(Rectangle contentRect)
if (contentRect.Height < totalHeight)
childFlags |= ImGuiWindowFlags.AlwaysVerticalScrollbar;
- if (ImGuiNET.ImGui.BeginChild($"{Id}", contentRect.Size, false, childFlags))
+ if (ImGuiNET.ImGui.BeginChild($"{Id}", contentRect.Size, ImGuiChildFlags.None, childFlags))
{
var (x, y) = GetInitPoint(localWidths, localHeights, contentRect);
ImGuiNET.ImGui.SetCursorPosX(x);
ImGuiNET.ImGui.SetCursorPosY(y);
- if (ImGuiNET.ImGui.BeginChild($"{Id}-in", new Vector2(totalWidth, totalHeight), false, ImGuiWindowFlags.NoScrollbar))
+ if (ImGuiNET.ImGui.BeginChild($"{Id}-in", new Vector2(totalWidth, totalHeight), ImGuiChildFlags.None, ImGuiWindowFlags.NoScrollbar))
{
(x, y) = (0, 0);
var origX = x;
@@ -155,13 +155,13 @@ protected override void UpdateInternal(Rectangle contentRect)
ImGuiNET.ImGui.SetCursorPosX(x);
ImGuiNET.ImGui.SetCursorPosY(y);
- if (ImGuiNET.ImGui.BeginChild($"{Id}-{r}-{c}", new Vector2(cellWidth, cellHeight), false, ImGuiWindowFlags.NoScrollbar))
+ if (ImGuiNET.ImGui.BeginChild($"{Id}-{r}-{c}", new Vector2(cellWidth, cellHeight), ImGuiChildFlags.None, ImGuiWindowFlags.NoScrollbar))
{
// Draw cell content container
ImGuiNET.ImGui.SetCursorPosX(xAdjust);
ImGuiNET.ImGui.SetCursorPosY(yAdjust);
- if (ImGuiNET.ImGui.BeginChild($"{Id}-{r}-{c}-content", new Vector2(cellInternalWidth, cellInternalHeight), false, ImGuiWindowFlags.NoScrollbar))
+ if (ImGuiNET.ImGui.BeginChild($"{Id}-{r}-{c}-content", new Vector2(cellInternalWidth, cellInternalHeight), ImGuiChildFlags.None, ImGuiWindowFlags.NoScrollbar))
{
// Draw component
cell.Content?.Update(new Rectangle((int)(contentRect.X + x + xAdjust - sx), (int)(contentRect.Y + y + yAdjust - sy), cellInternalWidth, cellInternalHeight));
diff --git a/ImGui.Forms/Controls/Lists/BaseList.cs b/ImGui.Forms/Controls/Lists/BaseList.cs
index 70984dd..fe8e20b 100644
--- a/ImGui.Forms/Controls/Lists/BaseList.cs
+++ b/ImGui.Forms/Controls/Lists/BaseList.cs
@@ -4,6 +4,7 @@
using System.Numerics;
using ImGui.Forms.Controls.Base;
using ImGui.Forms.Controls.Layouts;
+using ImGuiNET;
using Veldrid;
using Size = ImGui.Forms.Models.Size;
@@ -63,7 +64,7 @@ protected override void UpdateInternal(Rectangle contentRect)
var listDimension = localItems.Sum(i => GetDimension(i, contentRect)) + Math.Max(0, localItems.Length - 1) * ItemSpacing + (int)(GetPadding() * 2);
var scrollableDimension = GetScrollableDimension(contentRect);
- if (ImGuiNET.ImGui.BeginChild($"{Id}", contentRect.Size, false))
+ if (ImGuiNET.ImGui.BeginChild($"{Id}", contentRect.Size, ImGuiChildFlags.None))
{
if (_scrollToLast)
{
@@ -136,7 +137,7 @@ private void SetScroll(float scroll)
{
scroll = Math.Max(0, scroll);
- if(Alignment == Alignment.Vertical)
+ if (Alignment == Alignment.Vertical)
ImGuiNET.ImGui.SetScrollY(scroll);
else
ImGuiNET.ImGui.SetScrollX(scroll);
diff --git a/ImGui.Forms/Controls/Lists/ImageList.cs b/ImGui.Forms/Controls/Lists/ImageList.cs
index 31343f0..99a155d 100644
--- a/ImGui.Forms/Controls/Lists/ImageList.cs
+++ b/ImGui.Forms/Controls/Lists/ImageList.cs
@@ -55,7 +55,7 @@ protected override void UpdateInternal(Rectangle contentRect)
{
ImageListItem selectedItem = null;
- if (ImGuiNET.ImGui.BeginChild($"##{Id}_out", new Vector2(contentRect.Width, contentRect.Height), false))
+ if (ImGuiNET.ImGui.BeginChild($"##{Id}_out", new Vector2(contentRect.Width, contentRect.Height), ImGuiChildFlags.None))
{
var textHeight = FontResource.GetCurrentLineHeight(Font);
@@ -66,7 +66,7 @@ protected override void UpdateInternal(Rectangle contentRect)
var localItems = Items.ToArray();
- if (ImGuiNET.ImGui.BeginChild($"##{Id}_in", new Vector2(contentRect.Width, Padding.Y * 2 + localItems.Length * (itemHeight + ItemPadding)), false, ImGuiWindowFlags.NoScrollbar))
+ if (ImGuiNET.ImGui.BeginChild($"##{Id}_in", new Vector2(contentRect.Width, Padding.Y * 2 + localItems.Length * (itemHeight + ItemPadding)), ImGuiChildFlags.None, ImGuiWindowFlags.NoScrollbar))
{
for (var i = 0; i < localItems.Length; i++)
{
diff --git a/ImGui.Forms/Controls/MultiLineTextBox.cs b/ImGui.Forms/Controls/MultiLineTextBox.cs
index a92da2d..1a60c60 100644
--- a/ImGui.Forms/Controls/MultiLineTextBox.cs
+++ b/ImGui.Forms/Controls/MultiLineTextBox.cs
@@ -1,6 +1,7 @@
using System;
using ImGui.Forms.Controls.Base;
using ImGui.Forms.Models;
+using ImGuiNET;
using Veldrid;
namespace ImGui.Forms.Controls
@@ -24,6 +25,11 @@ public string Text
}
}
+ ///
+ /// Marks the input as read-only.
+ ///
+ public bool IsReadOnly { get; set; }
+
///
/// Get or set the max count of characters allowed in the text box.
///
@@ -41,8 +47,24 @@ public string Text
protected override void UpdateInternal(Rectangle contentRect)
{
- if (ImGuiNET.ImGui.InputTextMultiline($"##{Id}", ref _text, MaxCharacters, contentRect.Size))
+ var enabled = Enabled;
+ var isReadonly = IsReadOnly;
+
+ var flags = ImGuiInputTextFlags.None;
+ if (isReadonly || !enabled) flags |= ImGuiInputTextFlags.ReadOnly;
+
+ if (isReadonly || !enabled)
+ {
+ ImGuiNET.ImGui.PushStyleColor(ImGuiCol.FrameBg, 0xFF666666);
+ ImGuiNET.ImGui.PushStyleColor(ImGuiCol.FrameBgActive, 0xFF666666);
+ ImGuiNET.ImGui.PushStyleColor(ImGuiCol.FrameBgHovered, 0xFF666666);
+ }
+
+ if (ImGuiNET.ImGui.InputTextMultiline($"##{Id}", ref _text, MaxCharacters, contentRect.Size, flags))
OnTextChanged();
+
+ if (isReadonly || !enabled)
+ ImGuiNET.ImGui.PopStyleColor(3);
}
private void OnTextChanged()
diff --git a/ImGui.Forms/Controls/Tree/TreeView.cs b/ImGui.Forms/Controls/Tree/TreeView.cs
index 35cc0c1..ae390fa 100644
--- a/ImGui.Forms/Controls/Tree/TreeView.cs
+++ b/ImGui.Forms/Controls/Tree/TreeView.cs
@@ -59,7 +59,7 @@ protected override void UpdateInternal(Rectangle contentRect)
return;
var anyNodeHovered = false;
- if (ImGuiNET.ImGui.BeginChild($"{Id}", new Vector2(contentRect.Width, contentRect.Height), false, ImGuiWindowFlags.HorizontalScrollbar))
+ if (ImGuiNET.ImGui.BeginChild($"{Id}", new Vector2(contentRect.Width, contentRect.Height), ImGuiChildFlags.None, ImGuiWindowFlags.HorizontalScrollbar))
{
UpdateNodes(Nodes, ref anyNodeHovered);
}
diff --git a/ImGui.Forms/Factories/FontFactory.cs b/ImGui.Forms/Factories/FontFactory.cs
index 2829b36..be41016 100644
--- a/ImGui.Forms/Factories/FontFactory.cs
+++ b/ImGui.Forms/Factories/FontFactory.cs
@@ -1,7 +1,10 @@
using System;
using System.Collections.Generic;
+using System.Drawing;
using System.IO;
+using System.Linq;
using System.Reflection;
+using ImGui.Forms.Models;
using ImGui.Forms.Resources;
using ImGui.Forms.Support.Veldrid.ImGui;
using ImGuiNET;
@@ -26,17 +29,17 @@ internal FontFactory()
#region Registration
- public void RegisterFromFile(string ttfPath, int size)
+ public void RegisterFromFile(string ttfPath, int size, FontGlyphRange glyphRanges = FontGlyphRange.All)
{
if (IsInitialized)
throw new InvalidOperationException("Can not register new fonts after application started.");
// If font not tracked, add it
if (!_discCache.ContainsKey((ttfPath, size)))
- _discCache[(ttfPath, size)] = new FontResource(ttfPath, size);
+ _discCache[(ttfPath, size)] = new FontResource(ttfPath, size, glyphRanges);
}
- public void RegisterFromResource(Assembly assembly, string resourceName, int size)
+ public void RegisterFromResource(Assembly assembly, string resourceName, int size, FontGlyphRange glyphRanges = FontGlyphRange.All)
{
if (IsInitialized)
throw new InvalidOperationException("Can not register new fonts after application started.");
@@ -62,7 +65,7 @@ public void RegisterFromResource(Assembly assembly, string resourceName, int siz
return;
// Otherwise add it to cache
- _discCache[(fontPath, size)] = new FontResource(fontPath, size, true);
+ _discCache[(fontPath, size)] = new FontResource(fontPath, size, glyphRanges, true);
}
#endregion
@@ -93,18 +96,82 @@ public FontResource Get(Assembly assembly, string resourceName, int size)
#region Initialization
- internal void Initialize(ImGuiIOPtr io, ImGuiRenderer controller)
+ internal unsafe void Initialize(ImGuiIOPtr io, ImGuiRenderer controller)
{
_io = io;
_controller = controller;
+ // Initialize default font
+ var defaultFont = InitializeDefaultFont();
+
// Initialize fonts
+ var config = ImGuiNative.ImFontConfig_ImFontConfig();
+ config->MergeMode = 1;
+
foreach (var discFont in _discCache)
- discFont.Value.Initialize(_io.Fonts.AddFontFromFileTTF(discFont.Key.Item1, discFont.Key.Item2));
+ {
+ if (discFont.Value == defaultFont)
+ continue;
+
+ var ranges = GetGlyphRanges(discFont.Value.GlyphRanges);
+
+ var loadedFont = _io.Fonts.AddFontFromFileTTF(discFont.Key.Item1, discFont.Key.Item2, config, ranges.Data);
+ discFont.Value.Initialize(loadedFont);
+ }
_controller.RecreateFontDeviceTexture();
}
+ private unsafe FontResource InitializeDefaultFont()
+ {
+ _io.Fonts.Clear();
+
+ ImFontPtr defaultFontPtr;
+
+ var defaultFont = _discCache.Values.FirstOrDefault(f => f.GlyphRanges.HasFlag(FontGlyphRange.Default));
+ if (defaultFont == null)
+ {
+ defaultFontPtr = _io.Fonts.AddFontDefault().NativePtr;
+ }
+ else
+ {
+ defaultFontPtr = _io.Fonts.AddFontFromFileTTF(defaultFont.Path, defaultFont.Size, null, GetGlyphRanges(defaultFont.GlyphRanges).Data);
+ defaultFont.Initialize(defaultFontPtr);
+ }
+
+ var config = ImGuiNative.ImFontConfig_ImFontConfig();
+ config->DstFont = defaultFontPtr;
+
+ return defaultFont;
+ }
+
+ private unsafe ImVector GetGlyphRanges(FontGlyphRange rangeFlags)
+ {
+ var builder = new ImFontGlyphRangesBuilderPtr(ImGuiNative.ImFontGlyphRangesBuilder_ImFontGlyphRangesBuilder());
+ builder.Clear();
+
+ if (rangeFlags.HasFlag(FontGlyphRange.Default))
+ builder.AddRanges(_io.Fonts.GetGlyphRangesDefault());
+ if (rangeFlags.HasFlag(FontGlyphRange.Cyrillic))
+ builder.AddRanges(_io.Fonts.GetGlyphRangesCyrillic());
+ if (rangeFlags.HasFlag(FontGlyphRange.Chinese))
+ builder.AddRanges(_io.Fonts.GetGlyphRangesChineseFull());
+ if (rangeFlags.HasFlag(FontGlyphRange.Japanese))
+ builder.AddRanges(_io.Fonts.GetGlyphRangesJapanese());
+ if (rangeFlags.HasFlag(FontGlyphRange.Greek))
+ builder.AddRanges(_io.Fonts.GetGlyphRangesGreek());
+ if (rangeFlags.HasFlag(FontGlyphRange.Korean))
+ builder.AddRanges(_io.Fonts.GetGlyphRangesKorean());
+ if (rangeFlags.HasFlag(FontGlyphRange.Thai))
+ builder.AddRanges(_io.Fonts.GetGlyphRangesThai());
+ if (rangeFlags.HasFlag(FontGlyphRange.Vietnamese))
+ builder.AddRanges(_io.Fonts.GetGlyphRangesVietnamese());
+
+ builder.BuildRanges(out var ranges);
+
+ return ranges;
+ }
+
#endregion
public void Dispose()
diff --git a/ImGui.Forms/ImGui.Forms.csproj b/ImGui.Forms/ImGui.Forms.csproj
index f058ede..61d41f5 100644
--- a/ImGui.Forms/ImGui.Forms.csproj
+++ b/ImGui.Forms/ImGui.Forms.csproj
@@ -18,18 +18,10 @@
-
-
-
- arial.ttf
-
-
- roboto.ttf
-
error.png
@@ -78,7 +70,7 @@
-
+
diff --git a/ImGui.Forms/ImGui.Forms.nuspec b/ImGui.Forms/ImGui.Forms.nuspec
index 16f4a86..dfc46cc 100644
--- a/ImGui.Forms/ImGui.Forms.nuspec
+++ b/ImGui.Forms/ImGui.Forms.nuspec
@@ -2,7 +2,7 @@
Imgui.Forms
- 1.0.45
+ 1.0.46
A WinForms-inspired object-oriented framework around Dear ImGui (https://github.com/ocornut/imgui)
onepiecefreak
@@ -19,7 +19,7 @@
-
+
diff --git a/ImGui.Forms/Models/FontGlyphRange.cs b/ImGui.Forms/Models/FontGlyphRange.cs
new file mode 100644
index 0000000..c0fd800
--- /dev/null
+++ b/ImGui.Forms/Models/FontGlyphRange.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace ImGui.Forms.Models
+{
+ [Flags]
+ public enum FontGlyphRange
+ {
+ Default = 1 << 0,
+ Cyrillic = 1 << 1,
+ Chinese = 1 << 2,
+ Japanese = 1 << 3,
+ Greek = 1 << 4,
+ Korean = 1 << 5,
+ Thai = 1 << 6,
+ Vietnamese = 1 << 7,
+
+ All = 255,
+ }
+}
diff --git a/ImGui.Forms/Resources/FontResource.cs b/ImGui.Forms/Resources/FontResource.cs
index b49204e..4021d1d 100644
--- a/ImGui.Forms/Resources/FontResource.cs
+++ b/ImGui.Forms/Resources/FontResource.cs
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Numerics;
+using ImGui.Forms.Models;
using ImGuiNET;
namespace ImGui.Forms.Resources
@@ -12,20 +13,29 @@ namespace ImGui.Forms.Resources
public class FontResource : IDisposable
{
private ImFontPtr _ptr;
-
- private readonly string _path;
+
private readonly bool _temporary;
+ ///
+ /// Supported glyphs.
+ ///
+ public FontGlyphRange GlyphRanges { get; }
+
+ ///
+ /// The physical path to the font.
+ ///
+ public string Path { get; }
///
/// The size of the font.
///
public int Size { get; }
- internal FontResource(string path, int size, bool temporary = false)
+ internal FontResource(string path, int size, FontGlyphRange glyphRanges, bool temporary = false)
{
- _path = path;
+ Path = path;
Size = size;
_temporary = temporary;
+ GlyphRanges = glyphRanges;
}
internal void Initialize(ImFontPtr ptr)
@@ -42,8 +52,8 @@ protected virtual void Dispose(bool disposing)
if (!_temporary)
return;
- if (File.Exists(_path))
- File.Delete(_path);
+ if (File.Exists(Path))
+ File.Delete(Path);
}
///
diff --git a/ImGui.Forms/Resources/FontResources.cs b/ImGui.Forms/Resources/FontResources.cs
deleted file mode 100644
index 485567d..0000000
--- a/ImGui.Forms/Resources/FontResources.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-namespace ImGui.Forms.Resources
-{
- ///
- /// Allows access to built-in fonts.
- ///
- /// To load and use your own fonts, see and .
- public static class FontResources
- {
- private const string ArialPath_ = "arial.ttf";
- private const string RobotoPath_ = "roboto.ttf";
-
- ///
- /// Registers the font "Arial" with into the application. Has to be called before the application was started.
- ///
- /// The size to display the font in.
- public static void RegisterArial(int size)
- {
- Application.FontFactory.RegisterFromResource(typeof(FontResources).Assembly, ArialPath_, size);
- }
-
- ///
- /// Registers the font "Roboto" with into the application. Has to be called before the application was started.
- ///
- /// The size to display the font in.
- public static void RegisterRoboto(int size)
- {
- Application.FontFactory.RegisterFromResource(typeof(FontResources).Assembly, RobotoPath_, size);
- }
-
- ///
- /// Gets a representing "Arial" with . Has to be registered with before the application was started.
- ///
- /// The size to display the font in.
- /// A representing "Arial" in the given .
- public static FontResource Arial(int size)
- {
- return Application.FontFactory.Get(typeof(FontResources).Assembly, ArialPath_, size);
- }
-
- ///
- /// Gets a representing "Roboto" with . Has to be registered with before the application was started.
- ///
- ///
- /// A representing "Roboto" in the given .
- public static FontResource Roboto(int size)
- {
- return Application.FontFactory.Get(typeof(FontResources).Assembly, RobotoPath_, size);
- }
- }
-}
diff --git a/ImGui.Forms/Resources/Fonts/arial.ttf b/ImGui.Forms/Resources/Fonts/arial.ttf
deleted file mode 100644
index ff0815c..0000000
Binary files a/ImGui.Forms/Resources/Fonts/arial.ttf and /dev/null differ
diff --git a/ImGui.Forms/Resources/Fonts/roboto.ttf b/ImGui.Forms/Resources/Fonts/roboto.ttf
deleted file mode 100644
index 39c63d7..0000000
Binary files a/ImGui.Forms/Resources/Fonts/roboto.ttf and /dev/null differ
diff --git a/ImGui.Forms/Support/Veldrid.ImGui/ImGuiRenderer.cs b/ImGui.Forms/Support/Veldrid.ImGui/ImGuiRenderer.cs
index fa91e49..98b2892 100644
--- a/ImGui.Forms/Support/Veldrid.ImGui/ImGuiRenderer.cs
+++ b/ImGui.Forms/Support/Veldrid.ImGui/ImGuiRenderer.cs
@@ -32,9 +32,6 @@ public class ImGuiRenderer : IDisposable
private ResourceSet _mainResourceSet;
private ResourceSet _fontTextureResourceSet;
private IntPtr _fontAtlasID = (IntPtr)1;
- private bool _controlDown;
- private bool _shiftDown;
- private bool _altDown;
private int _windowWidth;
private int _windowHeight;
@@ -43,8 +40,10 @@ public class ImGuiRenderer : IDisposable
// Image trackers
private readonly Dictionary _setsByView
= new Dictionary();
+
private readonly Dictionary _autoViewsByTexture
= new Dictionary();
+
private readonly Dictionary _viewsById = new Dictionary();
private readonly List _ownedResources = new List();
private int _lastAssignedID = 100;
@@ -58,7 +57,9 @@ private readonly Dictionary _autoViewsByTexture
/// The initial width of the rendering target. Can be resized.
/// The initial height of the rendering target. Can be resized.
public ImGuiRenderer(GraphicsDevice gd, OutputDescription outputDescription, int width, int height)
- : this(gd, outputDescription, width, height, ColorSpaceHandling.Legacy) { }
+ : this(gd, outputDescription, width, height, ColorSpaceHandling.Legacy)
+ {
+ }
///
/// Constructs a new ImGuiRenderer.
@@ -68,7 +69,8 @@ public ImGuiRenderer(GraphicsDevice gd, OutputDescription outputDescription, int
/// The initial width of the rendering target. Can be resized.
/// The initial height of the rendering target. Can be resized.
/// Identifies how the renderer should treat vertex colors.
- public ImGuiRenderer(GraphicsDevice gd, OutputDescription outputDescription, int width, int height, ColorSpaceHandling colorSpaceHandling)
+ public ImGuiRenderer(GraphicsDevice gd, OutputDescription outputDescription, int width, int height,
+ ColorSpaceHandling colorSpaceHandling)
{
_gd = gd;
_assembly = typeof(ImGuiRenderer).GetTypeInfo().Assembly;
@@ -79,10 +81,10 @@ public ImGuiRenderer(GraphicsDevice gd, OutputDescription outputDescription, int
IntPtr context = ImGuiNET.ImGui.CreateContext();
ImGuiNET.ImGui.SetCurrentContext(context);
- ImGuiNET.ImGui.GetIO().Fonts.AddFontDefault();
+ //ImGuiNET.ImGui.GetIO().Fonts.AddFontDefault();
+ //ImGuiNET.ImGui.GetIO().Fonts.Flags |= ImFontAtlasFlags.NoBakedLines;
CreateDeviceResources(gd, outputDescription);
- SetOpenTKKeyMappings();
SetPerFrameImGuiData(1f / 60f);
@@ -103,42 +105,61 @@ public void DestroyDeviceObjects()
public void CreateDeviceResources(GraphicsDevice gd, OutputDescription outputDescription)
=> CreateDeviceResources(gd, outputDescription, _colorSpaceHandling);
- public void CreateDeviceResources(GraphicsDevice gd, OutputDescription outputDescription, ColorSpaceHandling colorSpaceHandling)
+
+ public void CreateDeviceResources(GraphicsDevice gd, OutputDescription outputDescription,
+ ColorSpaceHandling colorSpaceHandling)
{
_gd = gd;
_colorSpaceHandling = colorSpaceHandling;
ResourceFactory factory = gd.ResourceFactory;
- _vertexBuffer = factory.CreateBuffer(new BufferDescription(10000, BufferUsage.VertexBuffer | BufferUsage.Dynamic));
+ _vertexBuffer =
+ factory.CreateBuffer(new BufferDescription(10000, BufferUsage.VertexBuffer | BufferUsage.Dynamic));
_vertexBuffer.Name = "ImGui.NET Vertex Buffer";
- _indexBuffer = factory.CreateBuffer(new BufferDescription(2000, BufferUsage.IndexBuffer | BufferUsage.Dynamic));
+ _indexBuffer =
+ factory.CreateBuffer(new BufferDescription(2000, BufferUsage.IndexBuffer | BufferUsage.Dynamic));
_indexBuffer.Name = "ImGui.NET Index Buffer";
- _projMatrixBuffer = factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
+ _projMatrixBuffer =
+ factory.CreateBuffer(new BufferDescription(64, BufferUsage.UniformBuffer | BufferUsage.Dynamic));
_projMatrixBuffer.Name = "ImGui.NET Projection Buffer";
- byte[] vertexShaderBytes = LoadEmbeddedShaderCode(gd.ResourceFactory, "imgui-vertex", ShaderStages.Vertex, _colorSpaceHandling);
- byte[] fragmentShaderBytes = LoadEmbeddedShaderCode(gd.ResourceFactory, "imgui-frag", ShaderStages.Fragment, _colorSpaceHandling);
- _vertexShader = factory.CreateShader(new ShaderDescription(ShaderStages.Vertex, vertexShaderBytes, _gd.BackendType == GraphicsBackend.Vulkan ? "main" : "VS"));
- _fragmentShader = factory.CreateShader(new ShaderDescription(ShaderStages.Fragment, fragmentShaderBytes, _gd.BackendType == GraphicsBackend.Vulkan ? "main" : "FS"));
+ byte[] vertexShaderBytes = LoadEmbeddedShaderCode(gd.ResourceFactory, "imgui-vertex", ShaderStages.Vertex,
+ _colorSpaceHandling);
+ byte[] fragmentShaderBytes = LoadEmbeddedShaderCode(gd.ResourceFactory, "imgui-frag", ShaderStages.Fragment,
+ _colorSpaceHandling);
+ _vertexShader = factory.CreateShader(new ShaderDescription(ShaderStages.Vertex, vertexShaderBytes,
+ _gd.BackendType == GraphicsBackend.Vulkan ? "main" : "VS"));
+ _vertexShader.Name = "ImGui.NET Vertex Shader";
+ _fragmentShader = factory.CreateShader(new ShaderDescription(ShaderStages.Fragment, fragmentShaderBytes,
+ _gd.BackendType == GraphicsBackend.Vulkan ? "main" : "FS"));
+ _fragmentShader.Name = "ImGui.NET Fragment Shader";
VertexLayoutDescription[] vertexLayouts = new VertexLayoutDescription[]
{
new VertexLayoutDescription(
- new VertexElementDescription("in_position", VertexElementSemantic.Position, VertexElementFormat.Float2),
- new VertexElementDescription("in_texCoord", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2),
- new VertexElementDescription("in_color", VertexElementSemantic.Color, VertexElementFormat.Byte4_Norm))
+ new VertexElementDescription("in_position", VertexElementSemantic.Position,
+ VertexElementFormat.Float2),
+ new VertexElementDescription("in_texCoord", VertexElementSemantic.TextureCoordinate,
+ VertexElementFormat.Float2),
+ new VertexElementDescription("in_color", VertexElementSemantic.Color,
+ VertexElementFormat.Byte4_Norm))
};
_layout = factory.CreateResourceLayout(new ResourceLayoutDescription(
- new ResourceLayoutElementDescription("ProjectionMatrixBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex),
+ new ResourceLayoutElementDescription("ProjectionMatrixBuffer", ResourceKind.UniformBuffer,
+ ShaderStages.Vertex),
new ResourceLayoutElementDescription("MainSampler", ResourceKind.Sampler, ShaderStages.Fragment)));
+ _layout.Name = "ImGui.NET Resource Layout";
_textureLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
- new ResourceLayoutElementDescription("MainTexture", ResourceKind.TextureReadOnly, ShaderStages.Fragment)));
+ new ResourceLayoutElementDescription("MainTexture", ResourceKind.TextureReadOnly,
+ ShaderStages.Fragment)));
+ _textureLayout.Name = "ImGui.NET Texture Layout";
GraphicsPipelineDescription pd = new GraphicsPipelineDescription(
BlendStateDescription.SingleAlphaBlend,
new DepthStencilStateDescription(false, false, ComparisonKind.Always),
- new RasterizerStateDescription(FaceCullMode.None, PolygonFillMode.Solid, FrontFace.Clockwise, true, true),
+ new RasterizerStateDescription(FaceCullMode.None, PolygonFillMode.Solid, FrontFace.Clockwise, true,
+ true),
PrimitiveTopology.TriangleList,
new ShaderSetDescription(
vertexLayouts,
@@ -152,10 +173,12 @@ public void CreateDeviceResources(GraphicsDevice gd, OutputDescription outputDes
outputDescription,
ResourceBindingModel.Default);
_pipeline = factory.CreateGraphicsPipeline(ref pd);
+ _pipeline.Name = "ImGui.NET Pipeline";
_mainResourceSet = factory.CreateResourceSet(new ResourceSetDescription(_layout,
_projMatrixBuffer,
gd.PointSampler));
+ _mainResourceSet.Name = "ImGui.NET Main Resource Set";
RecreateFontDeviceTexture(gd);
}
@@ -168,7 +191,9 @@ public IntPtr GetOrCreateImGuiBinding(ResourceFactory factory, TextureView textu
{
if (!_setsByView.TryGetValue(textureView, out ResourceSetInfo rsi))
{
- ResourceSet resourceSet = factory.CreateResourceSet(new ResourceSetDescription(_textureLayout, textureView));
+ ResourceSet resourceSet =
+ factory.CreateResourceSet(new ResourceSetDescription(_textureLayout, textureView));
+ resourceSet.Name = $"ImGui.NET {textureView.Name} Resource Set";
rsi = new ResourceSetInfo(GetNextImGuiBindingID(), resourceSet);
_setsByView.Add(textureView, rsi);
@@ -205,6 +230,7 @@ public IntPtr GetOrCreateImGuiBinding(ResourceFactory factory, Texture texture)
if (!_autoViewsByTexture.TryGetValue(texture, out TextureView textureView))
{
textureView = factory.CreateTextureView(texture);
+ textureView.Name = $"ImGui.NET {texture.Name} View";
_autoViewsByTexture.Add(texture, textureView);
_ownedResources.Add(textureView);
}
@@ -259,33 +285,45 @@ private byte[] LoadEmbeddedShaderCode(
switch (factory.BackendType)
{
case GraphicsBackend.Direct3D11:
- {
- if (stage == ShaderStages.Vertex && colorSpaceHandling == ColorSpaceHandling.Legacy) { name += "-legacy"; }
- string resourceName = name + ".hlsl.bytes";
- return GetEmbeddedResourceBytes(resourceName);
- }
+ {
+ if (stage == ShaderStages.Vertex && colorSpaceHandling == ColorSpaceHandling.Legacy)
+ {
+ name += "-legacy";
+ }
+
+ string resourceName = name + ".hlsl.bytes";
+ return GetEmbeddedResourceBytes(resourceName);
+ }
case GraphicsBackend.OpenGL:
- {
- if (stage == ShaderStages.Vertex && colorSpaceHandling == ColorSpaceHandling.Legacy) { name += "-legacy"; }
- string resourceName = name + ".glsl";
- return GetEmbeddedResourceBytes(resourceName);
- }
+ {
+ if (stage == ShaderStages.Vertex && colorSpaceHandling == ColorSpaceHandling.Legacy)
+ {
+ name += "-legacy";
+ }
+
+ string resourceName = name + ".glsl";
+ return GetEmbeddedResourceBytes(resourceName);
+ }
case GraphicsBackend.OpenGLES:
- {
- if (stage == ShaderStages.Vertex && colorSpaceHandling == ColorSpaceHandling.Legacy) { name += "-legacy"; }
- string resourceName = name + ".glsles";
- return GetEmbeddedResourceBytes(resourceName);
- }
+ {
+ if (stage == ShaderStages.Vertex && colorSpaceHandling == ColorSpaceHandling.Legacy)
+ {
+ name += "-legacy";
+ }
+
+ string resourceName = name + ".glsles";
+ return GetEmbeddedResourceBytes(resourceName);
+ }
case GraphicsBackend.Vulkan:
- {
- string resourceName = name + ".spv";
- return GetEmbeddedResourceBytes(resourceName);
- }
+ {
+ string resourceName = name + ".spv";
+ return GetEmbeddedResourceBytes(resourceName);
+ }
case GraphicsBackend.Metal:
- {
- string resourceName = name + ".metallib";
- return GetEmbeddedResourceBytes(resourceName);
- }
+ {
+ string resourceName = name + ".metallib";
+ return GetEmbeddedResourceBytes(resourceName);
+ }
default:
throw new NotImplementedException();
}
@@ -319,7 +357,7 @@ private byte[] GetEmbeddedResourceBytes(string resourceName)
///
public unsafe void RecreateFontDeviceTexture(GraphicsDevice gd)
{
- ImGuiNET.ImGuiIOPtr io = ImGuiNET.ImGui.GetIO();
+ ImGuiIOPtr io = ImGuiNET.ImGui.GetIO();
// Build
io.Fonts.GetTexDataAsRGBA32(out byte* pixels, out int width, out int height, out int bytesPerPixel);
@@ -349,7 +387,9 @@ public unsafe void RecreateFontDeviceTexture(GraphicsDevice gd)
0);
_fontTextureResourceSet?.Dispose();
- _fontTextureResourceSet = gd.ResourceFactory.CreateResourceSet(new ResourceSetDescription(_textureLayout, _fontTexture));
+ _fontTextureResourceSet =
+ gd.ResourceFactory.CreateResourceSet(new ResourceSetDescription(_textureLayout, _fontTexture));
+ _fontTextureResourceSet.Name = "ImGui.NET Font Texture Resource Set";
io.Fonts.ClearTexData();
}
@@ -415,94 +455,198 @@ private unsafe void SetPerFrameImGuiData(float deltaSeconds)
io.DeltaTime = deltaSeconds; // DeltaTime is in seconds.
}
- private unsafe void UpdateImGuiInput(InputSnapshot snapshot)
+ private bool TryMapKey(Key key, out ImGuiKey result)
{
- ImGuiIOPtr io = ImGuiNET.ImGui.GetIO();
-
- // Determine if any of the mouse buttons were pressed during this snapshot period, even if they are no longer held.
- bool leftPressed = false;
- bool middlePressed = false;
- bool rightPressed = false;
- for (int i = 0; i < snapshot.MouseEvents.Count; i++)
+ ImGuiKey keyToImGuiKeyShortcut(Key keyToConvert, Key startKey1, ImGuiKey startKey2)
{
- MouseEvent me = snapshot.MouseEvents[i];
- if (me.Down)
- {
- switch (me.MouseButton)
- {
- case MouseButton.Left:
- leftPressed = true;
- break;
- case MouseButton.Middle:
- middlePressed = true;
- break;
- case MouseButton.Right:
- rightPressed = true;
- break;
- }
- }
+ int changeFromStart1 = (int)keyToConvert - (int)startKey1;
+ return startKey2 + changeFromStart1;
}
- io.MouseDown[0] = leftPressed || snapshot.IsMouseDown(MouseButton.Left);
- io.MouseDown[1] = rightPressed || snapshot.IsMouseDown(MouseButton.Right);
- io.MouseDown[2] = middlePressed || snapshot.IsMouseDown(MouseButton.Middle);
- io.MousePos = snapshot.MousePosition;
- io.MouseWheel = snapshot.WheelDelta;
-
- IReadOnlyList keyCharPresses = snapshot.KeyCharPresses;
- for (int i = 0; i < keyCharPresses.Count; i++)
+ if (key >= Key.F1 && key <= Key.F12)
{
- char c = keyCharPresses[i];
- ImGuiNET.ImGui.GetIO().AddInputCharacter(c);
+ result = keyToImGuiKeyShortcut(key, Key.F1, ImGuiKey.F1);
+ return true;
}
-
- IReadOnlyList keyEvents = snapshot.KeyEvents;
- for (int i = 0; i < keyEvents.Count; i++)
+ else if (key >= Key.Keypad0 && key <= Key.Keypad9)
{
- KeyEvent keyEvent = keyEvents[i];
- io.KeysDown[(int)keyEvent.Key] = keyEvent.Down;
- if (keyEvent.Key == Key.ControlLeft)
- {
- _controlDown = keyEvent.Down;
- }
- if (keyEvent.Key == Key.ShiftLeft)
- {
- _shiftDown = keyEvent.Down;
- }
- if (keyEvent.Key == Key.AltLeft)
- {
- _altDown = keyEvent.Down;
- }
+ result = keyToImGuiKeyShortcut(key, Key.Keypad0, ImGuiKey.Keypad0);
+ return true;
+ }
+ else if (key >= Key.A && key <= Key.Z)
+ {
+ result = keyToImGuiKeyShortcut(key, Key.A, ImGuiKey.A);
+ return true;
+ }
+ else if (key >= Key.Number0 && key <= Key.Number9)
+ {
+ result = keyToImGuiKeyShortcut(key, Key.Number0, ImGuiKey._0);
+ return true;
}
- io.KeyCtrl = _controlDown;
- io.KeyAlt = _altDown;
- io.KeyShift = _shiftDown;
+ switch (key)
+ {
+ case Key.ShiftLeft:
+ case Key.ShiftRight:
+ result = ImGuiKey.ModShift;
+ return true;
+ case Key.ControlLeft:
+ case Key.ControlRight:
+ result = ImGuiKey.ModCtrl;
+ return true;
+ case Key.AltLeft:
+ case Key.AltRight:
+ result = ImGuiKey.ModAlt;
+ return true;
+ case Key.WinLeft:
+ case Key.WinRight:
+ result = ImGuiKey.ModSuper;
+ return true;
+ case Key.Menu:
+ result = ImGuiKey.Menu;
+ return true;
+ case Key.Up:
+ result = ImGuiKey.UpArrow;
+ return true;
+ case Key.Down:
+ result = ImGuiKey.DownArrow;
+ return true;
+ case Key.Left:
+ result = ImGuiKey.LeftArrow;
+ return true;
+ case Key.Right:
+ result = ImGuiKey.RightArrow;
+ return true;
+ case Key.Enter:
+ result = ImGuiKey.Enter;
+ return true;
+ case Key.Escape:
+ result = ImGuiKey.Escape;
+ return true;
+ case Key.Space:
+ result = ImGuiKey.Space;
+ return true;
+ case Key.Tab:
+ result = ImGuiKey.Tab;
+ return true;
+ case Key.BackSpace:
+ result = ImGuiKey.Backspace;
+ return true;
+ case Key.Insert:
+ result = ImGuiKey.Insert;
+ return true;
+ case Key.Delete:
+ result = ImGuiKey.Delete;
+ return true;
+ case Key.PageUp:
+ result = ImGuiKey.PageUp;
+ return true;
+ case Key.PageDown:
+ result = ImGuiKey.PageDown;
+ return true;
+ case Key.Home:
+ result = ImGuiKey.Home;
+ return true;
+ case Key.End:
+ result = ImGuiKey.End;
+ return true;
+ case Key.CapsLock:
+ result = ImGuiKey.CapsLock;
+ return true;
+ case Key.ScrollLock:
+ result = ImGuiKey.ScrollLock;
+ return true;
+ case Key.PrintScreen:
+ result = ImGuiKey.PrintScreen;
+ return true;
+ case Key.Pause:
+ result = ImGuiKey.Pause;
+ return true;
+ case Key.NumLock:
+ result = ImGuiKey.NumLock;
+ return true;
+ case Key.KeypadDivide:
+ result = ImGuiKey.KeypadDivide;
+ return true;
+ case Key.KeypadMultiply:
+ result = ImGuiKey.KeypadMultiply;
+ return true;
+ case Key.KeypadSubtract:
+ result = ImGuiKey.KeypadSubtract;
+ return true;
+ case Key.KeypadAdd:
+ result = ImGuiKey.KeypadAdd;
+ return true;
+ case Key.KeypadDecimal:
+ result = ImGuiKey.KeypadDecimal;
+ return true;
+ case Key.KeypadEnter:
+ result = ImGuiKey.KeypadEnter;
+ return true;
+ case Key.Tilde:
+ result = ImGuiKey.GraveAccent;
+ return true;
+ case Key.Minus:
+ result = ImGuiKey.Minus;
+ return true;
+ case Key.Plus:
+ result = ImGuiKey.Equal;
+ return true;
+ case Key.BracketLeft:
+ result = ImGuiKey.LeftBracket;
+ return true;
+ case Key.BracketRight:
+ result = ImGuiKey.RightBracket;
+ return true;
+ case Key.Semicolon:
+ result = ImGuiKey.Semicolon;
+ return true;
+ case Key.Quote:
+ result = ImGuiKey.Apostrophe;
+ return true;
+ case Key.Comma:
+ result = ImGuiKey.Comma;
+ return true;
+ case Key.Period:
+ result = ImGuiKey.Period;
+ return true;
+ case Key.Slash:
+ result = ImGuiKey.Slash;
+ return true;
+ case Key.BackSlash:
+ case Key.NonUSBackSlash:
+ result = ImGuiKey.Backslash;
+ return true;
+ default:
+ result = ImGuiKey.GamepadBack;
+ return false;
+ }
}
- private static unsafe void SetOpenTKKeyMappings()
+ private unsafe void UpdateImGuiInput(InputSnapshot snapshot)
{
ImGuiIOPtr io = ImGuiNET.ImGui.GetIO();
- io.KeyMap[(int)ImGuiKey.Tab] = (int)Key.Tab;
- io.KeyMap[(int)ImGuiKey.LeftArrow] = (int)Key.Left;
- io.KeyMap[(int)ImGuiKey.RightArrow] = (int)Key.Right;
- io.KeyMap[(int)ImGuiKey.UpArrow] = (int)Key.Up;
- io.KeyMap[(int)ImGuiKey.DownArrow] = (int)Key.Down;
- io.KeyMap[(int)ImGuiKey.PageUp] = (int)Key.PageUp;
- io.KeyMap[(int)ImGuiKey.PageDown] = (int)Key.PageDown;
- io.KeyMap[(int)ImGuiKey.Home] = (int)Key.Home;
- io.KeyMap[(int)ImGuiKey.End] = (int)Key.End;
- io.KeyMap[(int)ImGuiKey.Delete] = (int)Key.Delete;
- io.KeyMap[(int)ImGuiKey.Backspace] = (int)Key.BackSpace;
- io.KeyMap[(int)ImGuiKey.Enter] = (int)Key.Enter;
- io.KeyMap[(int)ImGuiKey.Escape] = (int)Key.Escape;
- io.KeyMap[(int)ImGuiKey.Space] = (int)Key.Space;
- io.KeyMap[(int)ImGuiKey.A] = (int)Key.A;
- io.KeyMap[(int)ImGuiKey.C] = (int)Key.C;
- io.KeyMap[(int)ImGuiKey.V] = (int)Key.V;
- io.KeyMap[(int)ImGuiKey.X] = (int)Key.X;
- io.KeyMap[(int)ImGuiKey.Y] = (int)Key.Y;
- io.KeyMap[(int)ImGuiKey.Z] = (int)Key.Z;
+ io.AddMousePosEvent(snapshot.MousePosition.X, snapshot.MousePosition.Y);
+ io.AddMouseButtonEvent(0, snapshot.IsMouseDown(MouseButton.Left));
+ io.AddMouseButtonEvent(1, snapshot.IsMouseDown(MouseButton.Right));
+ io.AddMouseButtonEvent(2, snapshot.IsMouseDown(MouseButton.Middle));
+ io.AddMouseButtonEvent(3, snapshot.IsMouseDown(MouseButton.Button1));
+ io.AddMouseButtonEvent(4, snapshot.IsMouseDown(MouseButton.Button2));
+ io.AddMouseWheelEvent(0f, snapshot.WheelDelta);
+
+ for (int i = 0; i < snapshot.KeyCharPresses.Count; i++)
+ {
+ io.AddInputCharacter(snapshot.KeyCharPresses[i]);
+ }
+
+ for (int i = 0; i < snapshot.KeyEvents.Count; i++)
+ {
+ KeyEvent keyEvent = snapshot.KeyEvents[i];
+ if (TryMapKey(keyEvent.Key, out ImGuiKey imguikey))
+ {
+ io.AddKeyEvent(imguikey, keyEvent.Down);
+ }
+ }
}
private unsafe void RenderImDrawData(ImDrawDataPtr draw_data, GraphicsDevice gd, CommandList cl)
@@ -519,19 +663,23 @@ private unsafe void RenderImDrawData(ImDrawDataPtr draw_data, GraphicsDevice gd,
if (totalVBSize > _vertexBuffer.SizeInBytes)
{
_vertexBuffer.Dispose();
- _vertexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)(totalVBSize * 1.5f), BufferUsage.VertexBuffer | BufferUsage.Dynamic));
+ _vertexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)(totalVBSize * 1.5f),
+ BufferUsage.VertexBuffer | BufferUsage.Dynamic));
+ _vertexBuffer.Name = $"ImGui.NET Vertex Buffer";
}
uint totalIBSize = (uint)(draw_data.TotalIdxCount * sizeof(ushort));
if (totalIBSize > _indexBuffer.SizeInBytes)
{
_indexBuffer.Dispose();
- _indexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)(totalIBSize * 1.5f), BufferUsage.IndexBuffer | BufferUsage.Dynamic));
+ _indexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)(totalIBSize * 1.5f),
+ BufferUsage.IndexBuffer | BufferUsage.Dynamic));
+ _indexBuffer.Name = $"ImGui.NET Index Buffer";
}
for (int i = 0; i < draw_data.CmdListsCount; i++)
{
- ImDrawListPtr cmd_list = draw_data.CmdListsRange[i];
+ ImDrawListPtr cmd_list = draw_data.CmdLists[i];
cl.UpdateBuffer(
_vertexBuffer,
@@ -576,7 +724,7 @@ private unsafe void RenderImDrawData(ImDrawDataPtr draw_data, GraphicsDevice gd,
int idx_offset = 0;
for (int n = 0; n < draw_data.CmdListsCount; n++)
{
- ImDrawListPtr cmd_list = draw_data.CmdListsRange[n];
+ ImDrawListPtr cmd_list = draw_data.CmdLists[n];
for (int cmd_i = 0; cmd_i < cmd_list.CmdBuffer.Size; cmd_i++)
{
ImDrawCmdPtr pcmd = cmd_list.CmdBuffer[cmd_i];
@@ -605,11 +753,12 @@ private unsafe void RenderImDrawData(ImDrawDataPtr draw_data, GraphicsDevice gd,
(uint)(pcmd.ClipRect.Z - pcmd.ClipRect.X),
(uint)(pcmd.ClipRect.W - pcmd.ClipRect.Y));
- cl.DrawIndexed(pcmd.ElemCount, 1, (uint)idx_offset, vtx_offset, 0);
+ cl.DrawIndexed(pcmd.ElemCount, 1, pcmd.IdxOffset + (uint)idx_offset,
+ (int)(pcmd.VtxOffset + vtx_offset), 0);
}
-
- idx_offset += (int)pcmd.ElemCount;
}
+
+ idx_offset += cmd_list.IdxBuffer.Size;
vtx_offset += cmd_list.VtxBuffer.Size;
}
}