Overhaul the sample program.

* The new sample program now uses Veldrid to render the application.
* The new sample program is based on the official example code.
internals
Eric Mellino 6 years ago
parent eb195f622b
commit ebb5fe2c61
  1. 18
      README.md
  2. 33
      src/ImGui.NET.SampleProgram/ImGui.NET.SampleProgram.csproj
  3. 538
      src/ImGui.NET.SampleProgram/ImGuiController.cs
  4. 11
      src/ImGui.NET.SampleProgram/MemoryEditor.cs
  5. 120
      src/ImGui.NET.SampleProgram/Program.cs
  6. 3
      src/ImGui.NET.SampleProgram/Properties/launchSettings.json
  7. 442
      src/ImGui.NET.SampleProgram/SampleWindow.cs
  8. 13
      src/ImGui.NET.SampleProgram/Shaders/GLSL/imgui-frag.glsl
  9. 20
      src/ImGui.NET.SampleProgram/Shaders/GLSL/imgui-vertex.glsl
  10. 15
      src/ImGui.NET.SampleProgram/Shaders/HLSL/imgui-frag.hlsl
  11. BIN
      src/ImGui.NET.SampleProgram/Shaders/HLSL/imgui-frag.hlsl.bytes
  12. 27
      src/ImGui.NET.SampleProgram/Shaders/HLSL/imgui-vertex.hlsl
  13. BIN
      src/ImGui.NET.SampleProgram/Shaders/HLSL/imgui-vertex.hlsl.bytes
  14. 18
      src/ImGui.NET.SampleProgram/Shaders/Metal/imgui-frag.metal
  15. BIN
      src/ImGui.NET.SampleProgram/Shaders/Metal/imgui-frag.metallib
  16. 27
      src/ImGui.NET.SampleProgram/Shaders/Metal/imgui-vertex.metal
  17. BIN
      src/ImGui.NET.SampleProgram/Shaders/Metal/imgui-vertex.metallib
  18. 2
      src/ImGui.NET.SampleProgram/Shaders/SPIR-V/generate-spirv.bat
  19. 16
      src/ImGui.NET.SampleProgram/Shaders/SPIR-V/imgui-frag.glsl
  20. BIN
      src/ImGui.NET.SampleProgram/Shaders/SPIR-V/imgui-frag.spv
  21. 29
      src/ImGui.NET.SampleProgram/Shaders/SPIR-V/imgui-vertex.glsl
  22. BIN
      src/ImGui.NET.SampleProgram/Shaders/SPIR-V/imgui-vertex.spv
  23. 15
      src/ImGui.NET.SampleProgram/imgui.ini
  24. 36
      src/ImGui.NET.sln
  25. 6
      src/ImGui.NET/IO.cs
  26. 5
      src/ImGui.NET/ImGui.cs

@ -1,21 +1,31 @@
# ImGui.NET
This is a wrapper for the immediate mode GUI library, Dear ImGui (https://github.com/ocornut/imgui). This utilizes the C API, provided by the cimgui project (https://github.com/Extrawurst/cimgui). ImGui.NET lets you build graphical interfaces using a simple immediate-mode style. Included is a basic sample program that shows how to use the library, which renders the ImGui output using OpenGL via OpenTK.
This is a .NET wrapper for the immediate mode GUI library, Dear ImGui (https://github.com/ocornut/imgui). ImGui.NET lets you build graphical interfaces using a simple immediate-mode style. ImGui.NET is a .NET Standard library, and can be used on all major .NET runtimes and operating systems.
[![NuGet](https://img.shields.io/nuget/v/Veldrid.svg)](https://www.nuget.org/packages/ImGui.NET)
Included is a basic sample program that shows how to use the library, and renders the UI using [Veldrid](https://github.com/mellinoe/veldrid), a portable graphics library for .NET. By itself, Dear ImGui does not care what technology you use for rendering; it simply outputs textured triangles. Examples renderers also exist for MonoGame and OpenTK (OpenGL).
This wrapper is built on top of [cimgui](https://github.com/Extrawurst/cimgui), which exposes a plain C API for Dear ImGui. If you are using Windows, OSX, or a mainline Linux distribution, then the ImGui.NET NuGet package comes bundled with a pre-built native library. If you are using another operating system, then you may need to build the native library yourself; see the cimgui repo for build instructions.
![alt tag](http://i.imgur.com/02RGlsW.png)
[![NuGet](https://img.shields.io/nuget/v/Veldrid.svg)](https://www.nuget.org/packages/ImGui.NET)
# Building
ImGui.NET can be built in Visual Studio or on the command line. The .NET Core SDK is needed to build on the command line, and it can be downloaded [here](https://www.microsoft.com/net/core). Visual Studio 2017 is the minimum VS version supported for building.
# Usage
ImGui.NET currently provides a raw wrapper around the ImGui native API, and also provides a very thin safe, managed API for convenience. It is currently very much like using the native library, which is very simple, flexible, and robust. The easiest way to figure out how to use the library is to read the documentation of imgui itself, mostly in the imgui.cpp, and imgui.h files, as well as the exported functions in cimgui.h. Looking at the sample program code will also give some indication about basic usage.
# See Also
https://github.com/ocornut/imgui
> ImGui is a bloat-free graphical user interface library for C++. It outputs vertex buffers that you can render in your 3D-pipeline enabled application. It is portable, renderer agnostic and self-contained (no external dependencies). It is based on an "immediate mode" graphical user interface paradigm which enables you to build user interfaces with ease.
> Dear ImGui is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies).
> Dear ImGui is designed to enable fast iterations and to empower programmers to create content creation tools and visualization / debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and lacks certain features normally found in more high-level libraries.
> Dear ImGui is particularly suited to integration in games engine (for tooling), real-time 3D applications, fullscreen applications, embedded applications, or any applications on consoles platforms where operating system features are non-standard.
See the [official screenshot thread](https://github.com/ocornut/imgui/issues/123) for examples of many different kinds of interfaces created with Dear ImGui.
https://github.com/Extrawurst/cimgui
> This is a thin c-api wrapper for the excellent C++ intermediate gui imgui. This library is intended as a intermediate layer to be able to use imgui from other languages that can interface with C .

@ -1,15 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp1.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AssemblyName>ImGui.NET.SampleProgram</AssemblyName>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<None Include="..\..\deps\cimgui\win-x64\cimgui.dll" Link="cimgui.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<ProjectReference Include="..\ImGui.NET\ImGui.NET.csproj" />
<PackageReference Include="OpenTK.NETCore" Version="1.1.2364.6424" />
<PackageReference Include="Veldrid" Version="4.3.3" />
<PackageReference Include="Veldrid.StartupUtilities" Version="4.3.3" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Shaders/GLSL/imgui-vertex.glsl" LogicalName="imgui-vertex.glsl" />
<EmbeddedResource Include="Shaders/GLSL/imgui-frag.glsl" LogicalName="imgui-frag.glsl" />
<EmbeddedResource Include="Shaders/HLSL/imgui-vertex.hlsl.bytes" LogicalName="imgui-vertex.hlsl.bytes" />
<EmbeddedResource Include="Shaders/HLSL/imgui-frag.hlsl.bytes" LogicalName="imgui-frag.hlsl.bytes" />
<EmbeddedResource Include="Shaders/SPIR-V/imgui-vertex.spv" LogicalName="imgui-vertex.spv" />
<EmbeddedResource Include="Shaders/SPIR-V/imgui-frag.spv" LogicalName="imgui-frag.spv" />
<EmbeddedResource Include="Shaders/Metal/imgui-vertex.metallib" LogicalName="imgui-vertex.metallib" />
<EmbeddedResource Include="Shaders/Metal/imgui-frag.metallib" LogicalName="imgui-frag.metallib" />
</ItemGroup>
<ItemGroup>
<Content Include="$(RepositoryRootDirectory)/deps/cimgui/win-x64/cimgui.dll" CopyToOutputDirectory="PreserveNewest" />
<Content Include="$(RepositoryRootDirectory)/deps/cimgui/osx-x64/cimgui.dylib" CopyToOutputDirectory="PreserveNewest" />
<Content Include="$(RepositoryRootDirectory)/deps/cimgui/linux-x64/cimgui.so" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Project>

@ -0,0 +1,538 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Reflection;
using System.IO;
using Veldrid;
namespace ImGuiNET
{
/// <summary>
/// A modified version of Veldrid.ImGui's ImGuiRenderer.
/// Manages input for ImGui and handles rendering ImGui's DrawLists with Veldrid.
/// </summary>
public class ImGuiController : IDisposable
{
private GraphicsDevice _gd;
private bool _frameBegun;
// Veldrid objects
private DeviceBuffer _vertexBuffer;
private DeviceBuffer _indexBuffer;
private DeviceBuffer _projMatrixBuffer;
private Texture _fontTexture;
private TextureView _fontTextureView;
private Shader _vertexShader;
private Shader _fragmentShader;
private ResourceLayout _layout;
private ResourceLayout _textureLayout;
private Pipeline _pipeline;
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;
private Vector2 _scaleFactor = Vector2.One;
// Image trackers
private readonly Dictionary<TextureView, ResourceSetInfo> _setsByView
= new Dictionary<TextureView, ResourceSetInfo>();
private readonly Dictionary<Texture, TextureView> _autoViewsByTexture
= new Dictionary<Texture, TextureView>();
private readonly Dictionary<IntPtr, ResourceSetInfo> _viewsById = new Dictionary<IntPtr, ResourceSetInfo>();
private readonly List<IDisposable> _ownedResources = new List<IDisposable>();
private int _lastAssignedID = 100;
/// <summary>
/// Constructs a new ImGuiRenderer.
/// </summary>
public ImGuiController(GraphicsDevice gd, OutputDescription outputDescription, int width, int height)
{
_gd = gd;
_windowWidth = width;
_windowHeight = height;
ImGui.GetIO().FontAtlas.AddDefaultFont();
CreateDeviceResources(gd, outputDescription);
SetOpenTKKeyMappings();
SetPerFrameImGuiData(1f / 60f);
ImGui.NewFrame();
_frameBegun = true;
}
public void WindowResized(int width, int height)
{
_windowWidth = width;
_windowHeight = height;
}
public void DestroyDeviceObjects()
{
Dispose();
}
public void CreateDeviceResources(GraphicsDevice gd, OutputDescription outputDescription)
{
_gd = gd;
ResourceFactory factory = gd.ResourceFactory;
_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.Name = "ImGui.NET Index Buffer";
RecreateFontDeviceTexture(gd);
_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);
byte[] fragmentShaderBytes = LoadEmbeddedShaderCode(gd.ResourceFactory, "imgui-frag", ShaderStages.Fragment);
_vertexShader = factory.CreateShader(new ShaderDescription(ShaderStages.Vertex, vertexShaderBytes, "VS"));
_fragmentShader = factory.CreateShader(new ShaderDescription(ShaderStages.Fragment, fragmentShaderBytes, "FS"));
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))
};
_layout = factory.CreateResourceLayout(new ResourceLayoutDescription(
new ResourceLayoutElementDescription("ProjectionMatrixBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex),
new ResourceLayoutElementDescription("MainSampler", ResourceKind.Sampler, ShaderStages.Fragment)));
_textureLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
new ResourceLayoutElementDescription("MainTexture", ResourceKind.TextureReadOnly, ShaderStages.Fragment)));
GraphicsPipelineDescription pd = new GraphicsPipelineDescription(
BlendStateDescription.SingleAlphaBlend,
new DepthStencilStateDescription(false, false, ComparisonKind.Always),
new RasterizerStateDescription(FaceCullMode.None, PolygonFillMode.Solid, FrontFace.Clockwise, false, true),
PrimitiveTopology.TriangleList,
new ShaderSetDescription(vertexLayouts, new[] { _vertexShader, _fragmentShader }),
new ResourceLayout[] { _layout, _textureLayout },
outputDescription);
_pipeline = factory.CreateGraphicsPipeline(ref pd);
_mainResourceSet = factory.CreateResourceSet(new ResourceSetDescription(_layout,
_projMatrixBuffer,
gd.PointSampler));
_fontTextureResourceSet = factory.CreateResourceSet(new ResourceSetDescription(_textureLayout, _fontTextureView));
}
/// <summary>
/// Gets or creates a handle for a texture to be drawn with ImGui.
/// Pass the returned handle to Image() or ImageButton().
/// </summary>
public IntPtr GetOrCreateImGuiBinding(ResourceFactory factory, TextureView textureView)
{
if (!_setsByView.TryGetValue(textureView, out ResourceSetInfo rsi))
{
ResourceSet resourceSet = factory.CreateResourceSet(new ResourceSetDescription(_textureLayout, textureView));
rsi = new ResourceSetInfo(GetNextImGuiBindingID(), resourceSet);
_setsByView.Add(textureView, rsi);
_viewsById.Add(rsi.ImGuiBinding, rsi);
_ownedResources.Add(resourceSet);
}
return rsi.ImGuiBinding;
}
private IntPtr GetNextImGuiBindingID()
{
int newID = _lastAssignedID++;
return (IntPtr)newID;
}
/// <summary>
/// Gets or creates a handle for a texture to be drawn with ImGui.
/// Pass the returned handle to Image() or ImageButton().
/// </summary>
public IntPtr GetOrCreateImGuiBinding(ResourceFactory factory, Texture texture)
{
if (!_autoViewsByTexture.TryGetValue(texture, out TextureView textureView))
{
textureView = factory.CreateTextureView(texture);
_autoViewsByTexture.Add(texture, textureView);
_ownedResources.Add(textureView);
}
return GetOrCreateImGuiBinding(factory, textureView);
}
/// <summary>
/// Retrieves the shader texture binding for the given helper handle.
/// </summary>
public ResourceSet GetImageResourceSet(IntPtr imGuiBinding)
{
if (!_viewsById.TryGetValue(imGuiBinding, out ResourceSetInfo tvi))
{
throw new InvalidOperationException("No registered ImGui binding with id " + imGuiBinding.ToString());
}
return tvi.ResourceSet;
}
public void ClearCachedImageResources()
{
foreach (IDisposable resource in _ownedResources)
{
resource.Dispose();
}
_ownedResources.Clear();
_setsByView.Clear();
_viewsById.Clear();
_autoViewsByTexture.Clear();
_lastAssignedID = 100;
}
private byte[] LoadEmbeddedShaderCode(ResourceFactory factory, string name, ShaderStages stage)
{
switch (factory.BackendType)
{
case GraphicsBackend.Direct3D11:
{
string resourceName = name + ".hlsl.bytes";
return GetEmbeddedResourceBytes(resourceName);
}
case GraphicsBackend.OpenGL:
{
string resourceName = name + ".glsl";
return GetEmbeddedResourceBytes(resourceName);
}
case GraphicsBackend.Vulkan:
{
string resourceName = name + ".spv";
return GetEmbeddedResourceBytes(resourceName);
}
case GraphicsBackend.Metal:
{
string resourceName = name + ".metallib";
return GetEmbeddedResourceBytes(resourceName);
}
default:
throw new NotImplementedException();
}
}
private byte[] GetEmbeddedResourceBytes(string resourceName)
{
Assembly assembly = typeof(ImGuiController).Assembly;
using (Stream s = assembly.GetManifestResourceStream(resourceName))
{
byte[] ret = new byte[s.Length];
s.Read(ret, 0, (int)s.Length);
return ret;
}
}
/// <summary>
/// Recreates the device texture used to render text.
/// </summary>
public unsafe void RecreateFontDeviceTexture(GraphicsDevice gd)
{
IO io = ImGui.GetIO();
// Build
FontTextureData textureData = io.FontAtlas.GetTexDataAsRGBA32();
// Store our identifier
io.FontAtlas.SetTexID(_fontAtlasID);
_fontTexture = gd.ResourceFactory.CreateTexture(TextureDescription.Texture2D(
(uint)textureData.Width,
(uint)textureData.Height,
1,
1,
PixelFormat.R8_G8_B8_A8_UNorm,
TextureUsage.Sampled));
_fontTexture.Name = "ImGui.NET Font Texture";
gd.UpdateTexture(
_fontTexture,
(IntPtr)textureData.Pixels,
(uint)(textureData.BytesPerPixel * textureData.Width * textureData.Height),
0,
0,
0,
(uint)textureData.Width,
(uint)textureData.Height,
1,
0,
0);
_fontTextureView = gd.ResourceFactory.CreateTextureView(_fontTexture);
io.FontAtlas.ClearTexData();
}
/// <summary>
/// Renders the ImGui draw list data.
/// This method requires a <see cref="GraphicsDevice"/> because it may create new DeviceBuffers if the size of vertex
/// or index data has increased beyond the capacity of the existing buffers.
/// A <see cref="CommandList"/> is needed to submit drawing and resource update commands.
/// </summary>
public unsafe void Render(GraphicsDevice gd, CommandList cl)
{
if (_frameBegun)
{
_frameBegun = false;
ImGui.Render();
RenderImDrawData(ImGui.GetDrawData(), gd, cl);
}
}
/// <summary>
/// Updates ImGui input and IO configuration state.
/// </summary>
public void Update(float deltaSeconds, InputSnapshot snapshot)
{
if (_frameBegun)
{
ImGui.Render();
}
SetPerFrameImGuiData(deltaSeconds);
UpdateImGuiInput(snapshot);
_frameBegun = true;
ImGui.NewFrame();
}
/// <summary>
/// Sets per-frame data based on the associated window.
/// This is called by Update(float).
/// </summary>
private unsafe void SetPerFrameImGuiData(float deltaSeconds)
{
IO io = ImGui.GetIO();
io.DisplaySize = new Vector2(
_windowWidth / _scaleFactor.X,
_windowHeight / _scaleFactor.Y);
io.DisplayFramebufferScale = _scaleFactor;
io.DeltaTime = deltaSeconds; // DeltaTime is in seconds.
}
private unsafe void UpdateImGuiInput(InputSnapshot snapshot)
{
IO io = ImGui.GetIO();
Vector2 mousePosition = snapshot.MousePosition;
io.MousePosition = mousePosition;
io.MouseDown[0] = snapshot.IsMouseDown(MouseButton.Left);
io.MouseDown[1] = snapshot.IsMouseDown(MouseButton.Right);
io.MouseDown[2] = snapshot.IsMouseDown(MouseButton.Middle);
float delta = snapshot.WheelDelta;
io.MouseWheel = delta;
ImGui.GetIO().MouseWheel = delta;
IReadOnlyList<char> keyCharPresses = snapshot.KeyCharPresses;
for (int i = 0; i < keyCharPresses.Count; i++)
{
char c = keyCharPresses[i];
ImGui.AddInputCharacter(c);
}
IReadOnlyList<KeyEvent> keyEvents = snapshot.KeyEvents;
for (int i = 0; i < keyEvents.Count; i++)
{
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;
}
}
io.CtrlPressed = _controlDown;
io.AltPressed = _altDown;
io.ShiftPressed = _shiftDown;
}
private static unsafe void SetOpenTKKeyMappings()
{
IO io = ImGui.GetIO();
io.KeyMap[GuiKey.Tab] = (int)Key.Tab;
io.KeyMap[GuiKey.LeftArrow] = (int)Key.Left;
io.KeyMap[GuiKey.RightArrow] = (int)Key.Right;
io.KeyMap[GuiKey.UpArrow] = (int)Key.Up;
io.KeyMap[GuiKey.DownArrow] = (int)Key.Down;
io.KeyMap[GuiKey.PageUp] = (int)Key.PageUp;
io.KeyMap[GuiKey.PageDown] = (int)Key.PageDown;
io.KeyMap[GuiKey.Home] = (int)Key.Home;
io.KeyMap[GuiKey.End] = (int)Key.End;
io.KeyMap[GuiKey.Delete] = (int)Key.Delete;
io.KeyMap[GuiKey.Backspace] = (int)Key.BackSpace;
io.KeyMap[GuiKey.Enter] = (int)Key.Enter;
io.KeyMap[GuiKey.Escape] = (int)Key.Escape;
io.KeyMap[GuiKey.A] = (int)Key.A;
io.KeyMap[GuiKey.C] = (int)Key.C;
io.KeyMap[GuiKey.V] = (int)Key.V;
io.KeyMap[GuiKey.X] = (int)Key.X;
io.KeyMap[GuiKey.Y] = (int)Key.Y;
io.KeyMap[GuiKey.Z] = (int)Key.Z;
}
private unsafe void RenderImDrawData(DrawData* draw_data, GraphicsDevice gd, CommandList cl)
{
uint vertexOffsetInVertices = 0;
uint indexOffsetInElements = 0;
if (draw_data->CmdListsCount == 0)
{
return;
}
uint totalVBSize = (uint)(draw_data->TotalVtxCount * sizeof(DrawVert));
if (totalVBSize > _vertexBuffer.SizeInBytes)
{
gd.DisposeWhenIdle(_vertexBuffer);
_vertexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)(totalVBSize * 1.5f), BufferUsage.VertexBuffer | BufferUsage.Dynamic));
}
uint totalIBSize = (uint)(draw_data->TotalIdxCount * sizeof(ushort));
if (totalIBSize > _indexBuffer.SizeInBytes)
{
gd.DisposeWhenIdle(_indexBuffer);
_indexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)(totalIBSize * 1.5f), BufferUsage.IndexBuffer | BufferUsage.Dynamic));
}
for (int i = 0; i < draw_data->CmdListsCount; i++)
{
NativeDrawList* cmd_list = draw_data->CmdLists[i];
cl.UpdateBuffer(
_vertexBuffer,
vertexOffsetInVertices * (uint)sizeof(DrawVert),
(IntPtr)cmd_list->VtxBuffer.Data,
(uint)(cmd_list->VtxBuffer.Size * sizeof(DrawVert)));
cl.UpdateBuffer(
_indexBuffer,
indexOffsetInElements * (uint)sizeof(ushort),
(IntPtr)cmd_list->IdxBuffer.Data,
(uint)(cmd_list->IdxBuffer.Size * sizeof(ushort)));
vertexOffsetInVertices += (uint)cmd_list->VtxBuffer.Size;
indexOffsetInElements += (uint)cmd_list->IdxBuffer.Size;
}
// Setup orthographic projection matrix into our constant buffer
{
IO io = ImGui.GetIO();
Matrix4x4 mvp = Matrix4x4.CreateOrthographicOffCenter(
0f,
io.DisplaySize.X,
io.DisplaySize.Y,
0.0f,
-1.0f,
1.0f);
_gd.UpdateBuffer(_projMatrixBuffer, 0, ref mvp);
}
cl.SetVertexBuffer(0, _vertexBuffer);
cl.SetIndexBuffer(_indexBuffer, IndexFormat.UInt16);
cl.SetPipeline(_pipeline);
cl.SetGraphicsResourceSet(0, _mainResourceSet);
ImGui.ScaleClipRects(draw_data, ImGui.GetIO().DisplayFramebufferScale);
// Render command lists
int vtx_offset = 0;
int idx_offset = 0;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
NativeDrawList* cmd_list = draw_data->CmdLists[n];
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
DrawCmd* pcmd = &(((DrawCmd*)cmd_list->CmdBuffer.Data)[cmd_i]);
if (pcmd->UserCallback != IntPtr.Zero)
{
throw new NotImplementedException();
}
else
{
if (pcmd->TextureId != IntPtr.Zero)
{
if (pcmd->TextureId == _fontAtlasID)
{
cl.SetGraphicsResourceSet(1, _fontTextureResourceSet);
}
else
{
cl.SetGraphicsResourceSet(1, GetImageResourceSet(pcmd->TextureId));
}
}
cl.SetScissorRect(
0,
(uint)pcmd->ClipRect.X,
(uint)pcmd->ClipRect.Y,
(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);
}
idx_offset += (int)pcmd->ElemCount;
}
vtx_offset += cmd_list->VtxBuffer.Size;
}
}
/// <summary>
/// Frees all graphics resources used by the renderer.
/// </summary>
public void Dispose()
{
_vertexBuffer.Dispose();
_indexBuffer.Dispose();
_projMatrixBuffer.Dispose();
_fontTexture.Dispose();
_fontTextureView.Dispose();
_vertexShader.Dispose();
_fragmentShader.Dispose();
_layout.Dispose();
_textureLayout.Dispose();
_pipeline.Dispose();
_mainResourceSet.Dispose();
foreach (IDisposable resource in _ownedResources)
{
resource.Dispose();
}
}
private struct ResourceSetInfo
{
public readonly IntPtr ImGuiBinding;
public readonly ResourceSet ResourceSet;
public ResourceSetInfo(IntPtr imGuiBinding, ResourceSet resourceSet)
{
ImGuiBinding = imGuiBinding;
ResourceSet = resourceSet;
}
}
}
}

@ -57,6 +57,7 @@ namespace ImGuiNET
public unsafe void Draw(string title, byte[] mem_data, int mem_size, int base_display_addr = 0)
{
ImGui.SetNextWindowSize(new Vector2(500, 350), Condition.FirstUseEver);
if (!ImGui.BeginWindow(title))
{
ImGui.EndWindow();
@ -155,7 +156,7 @@ namespace ImGuiNET
{
int data;
if (TryHexParse(DataInput, out data))
mem_data[addr] = (byte)data;
mem_data[addr] = (byte)data;
}
ImGui.PopID();
}
@ -196,7 +197,7 @@ namespace ImGuiNET
}
ImGui.Separator();
ImGuiNative.igAlignTextToFramePadding();
ImGui.PushItemWidth(50);
ImGuiNative.igPushAllowKeyboardFocus(false);
@ -211,7 +212,7 @@ namespace ImGuiNET
ImGuiNative.igPopAllowKeyboardFocus();
ImGui.PopItemWidth();
ImGui.SameLine();
ImGui.Text(string.Format(" Range {0}..{1} ", FixedHex(base_display_addr, addr_digits_count),
ImGui.Text(string.Format(" Range {0}..{1} ", FixedHex(base_display_addr, addr_digits_count),
FixedHex(base_display_addr + mem_size - 1, addr_digits_count)));
ImGui.SameLine();
ImGui.PushItemWidth(70);
@ -232,7 +233,7 @@ namespace ImGuiNET
}
}
ImGui.PopItemWidth();
ImGui.EndWindow();
}
}
@ -268,4 +269,4 @@ namespace ImGuiNET
}
}
}
}
}

@ -1,11 +1,121 @@
using System;
using System.Linq;
using System.Numerics;
using Veldrid;
using Veldrid.Sdl2;
using Veldrid.StartupUtilities;
namespace ImGuiNET
{
public class Program
class Program
{
public static unsafe void Main(string[] args)
private static Sdl2Window _window;
private static GraphicsDevice _gd;
private static CommandList _cl;
private static ImGuiController _controller;
private static MemoryEditor _memoryEditor;
// UI state
private static float _f = 0.0f;
private static int _counter = 0;
private static Vector3 _clearColor = new Vector3(0.45f, 0.55f, 0.6f);
private static bool _showDemoWindow = true;
private static bool _showAnotherWindow = false;
private static bool _showMemoryEditor = false;
private static byte[] _memoryEditorData;
static void Main(string[] args)
{
var window = new SampleWindow();
window.RunWindowLoop();
// Create window, GraphicsDevice, and all resources necessary for the demo.
VeldridStartup.CreateWindowAndGraphicsDevice(
new WindowCreateInfo(50, 50, 1280, 720, WindowState.Normal, "ImGui.NET Sample Program"),
new GraphicsDeviceOptions(true, null, true),
GraphicsBackend.Vulkan,
out _window,
out _gd);
_window.Resized += () =>
{
_gd.MainSwapchain.Resize((uint)_window.Width, (uint)_window.Height);
_controller.WindowResized(_window.Width, _window.Height);
};
_cl = _gd.ResourceFactory.CreateCommandList();
_controller = new ImGuiController(_gd, _gd.MainSwapchain.Framebuffer.OutputDescription, _window.Width, _window.Height);
_memoryEditor = new MemoryEditor();
Random random = new Random();
_memoryEditorData = Enumerable.Range(0, 1024).Select(i => (byte)random.Next(255)).ToArray();
// Main application loop
while (_window.Exists)
{
InputSnapshot snapshot = _window.PumpEvents();
if (!_window.Exists) { break; }
_controller.Update(1f / 60f, snapshot); // Feed the input events to our ImGui controller, which passes them through to ImGui.
SubmitUI();
_cl.Begin();
_cl.SetFramebuffer(_gd.MainSwapchain.Framebuffer);
_cl.ClearColorTarget(0, new RgbaFloat(_clearColor.X, _clearColor.Y, _clearColor.Z, 1f));
_controller.Render(_gd, _cl);
_cl.End();
_gd.SubmitCommands(_cl);
_gd.SwapBuffers(_gd.MainSwapchain);
}
// Clean up Veldrid resources
_gd.WaitForIdle();
_controller.Dispose();
_cl.Dispose();
_gd.Dispose();
}
private static void SubmitUI()
{
// Demo code adapted from the official Dear ImGui demo program:
// https://github.com/ocornut/imgui/blob/master/examples/example_win32_directx11/main.cpp#L172
// 1. Show a simple window.
// Tip: if we don't call ImGui.BeginWindow()/ImGui.EndWindow() the widgets automatically appears in a window called "Debug".
{
ImGui.Text("Hello, world!"); // Display some text (you can use a format string too)
ImGui.SliderFloat("float", ref _f, 0, 1, _f.ToString("0.000"), 1); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui.ColorEdit3("clear color", ref _clearColor); // Edit 3 floats representing a color
ImGui.Checkbox("Demo Window", ref _showDemoWindow); // Edit bools storing our windows open/close state
ImGui.Checkbox("Another Window", ref _showAnotherWindow);
ImGui.Checkbox("Memory Editor", ref _showMemoryEditor);
if (ImGui.Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated)
_counter++;
ImGui.SameLine();
ImGui.Text($"counter = {_counter}");
ImGui.Text($"Application average {1000.0f / ImGui.GetIO().Framerate:0.##} ms/frame ({ImGui.GetIO().Framerate:0.#} FPS)");
}
// 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows.
if (_showAnotherWindow)
{
ImGui.BeginWindow("Another Window", ref _showAnotherWindow, WindowFlags.Default);
ImGui.Text("Hello from another window!");
if (ImGui.Button("Close Me"))
_showAnotherWindow = false;
ImGui.EndWindow();
}
// 3. Show the ImGui demo window. Most of the sample code is in ImGui.ShowDemoWindow(). Read its code to learn more about Dear ImGui!
if (_showDemoWindow)
{
// Normally user code doesn't need/want to call this because positions are saved in .ini file anyway.
// Here we just want to make the demo initial state a bit more friendly!
ImGui.SetNextWindowPos(new Vector2(650, 20), Condition.FirstUseEver);
ImGuiNative.igShowDemoWindow(ref _showDemoWindow);
}
if (_showMemoryEditor)
{
_memoryEditor.Draw("Memory Editor", _memoryEditorData, _memoryEditorData.Length);
}
}
}
}
}

@ -1,442 +0,0 @@
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
using System;
using System.Runtime.InteropServices;
using System.Threading;
#if NETFRAMEWORK
using System.Drawing;
#endif
namespace ImGuiNET
{
public class SampleWindow
{
private OpenTK.NativeWindow _nativeWindow;
private GraphicsContext _graphicsContext;
private int s_fontTexture;
private int _pressCount;
private IntPtr _textInputBuffer;
private int _textInputBufferLength;
private float _wheelPosition;
private float _sliderVal;
private System.Numerics.Vector4 _buttonColor = new System.Numerics.Vector4(55f / 255f, 155f / 255f, 1f, 1f);
private bool _mainWindowOpened;
private static double s_desiredFrameLength = 1f / 60.0f;
private DateTime _previousFrameStartTime;
private float _scaleFactor;
private System.Numerics.Vector3 _positionValue = new System.Numerics.Vector3(500);
private MemoryEditor _memoryEditor = new MemoryEditor();
private byte[] _memoryEditorData;
public unsafe SampleWindow()
{
int desiredWidth = 960, desiredHeight = 540;
_nativeWindow = new OpenTK.NativeWindow(desiredWidth, desiredHeight, "ImGui.NET", GameWindowFlags.Default, OpenTK.Graphics.GraphicsMode.Default, DisplayDevice.Default);
_scaleFactor = _nativeWindow.Width / desiredWidth;
GraphicsContextFlags flags = GraphicsContextFlags.Default;
_graphicsContext = new GraphicsContext(GraphicsMode.Default, _nativeWindow.WindowInfo, 3, 0, flags);
_graphicsContext.MakeCurrent(_nativeWindow.WindowInfo);
((IGraphicsContextInternal)_graphicsContext).LoadAll(); // wtf is this?
GL.ClearColor(Color.Black);
_nativeWindow.Visible = true;
_nativeWindow.X = _nativeWindow.X; // Work around OpenTK bug (?) on Ubuntu.
_nativeWindow.KeyDown += OnKeyDown;
_nativeWindow.KeyUp += OnKeyUp;
_nativeWindow.KeyPress += OnKeyPress;
ImGui.GetIO().FontAtlas.AddDefaultFont();
SetOpenTKKeyMappings();
_textInputBufferLength = 1024;
_textInputBuffer = Marshal.AllocHGlobal(_textInputBufferLength);
long* ptr = (long*)_textInputBuffer.ToPointer();
for (int i = 0; i < 1024 / sizeof(long); i++)
{
ptr[i] = 0;
}
_memoryEditorData = new byte[1024];
var rnd = new Random();
for (int i = 0; i < _memoryEditorData.Length; i++)
{
_memoryEditorData[i] = (byte) rnd.Next(255);
}
CreateDeviceObjects();
}
private void OnKeyPress(object sender, KeyPressEventArgs e)
{
Console.Write("Char typed: " + e.KeyChar);
ImGui.AddInputCharacter(e.KeyChar);
}
private static unsafe void SetOpenTKKeyMappings()
{
IO io = ImGui.GetIO();
io.KeyMap[GuiKey.Tab] = (int)Key.Tab;
io.KeyMap[GuiKey.LeftArrow] = (int)Key.Left;
io.KeyMap[GuiKey.RightArrow] = (int)Key.Right;
io.KeyMap[GuiKey.UpArrow] = (int)Key.Up;
io.KeyMap[GuiKey.DownArrow] = (int)Key.Down;
io.KeyMap[GuiKey.PageUp] = (int)Key.PageUp;
io.KeyMap[GuiKey.PageDown] = (int)Key.PageDown;
io.KeyMap[GuiKey.Home] = (int)Key.Home;
io.KeyMap[GuiKey.End] = (int)Key.End;
io.KeyMap[GuiKey.Delete] = (int)Key.Delete;
io.KeyMap[GuiKey.Backspace] = (int)Key.BackSpace;
io.KeyMap[GuiKey.Enter] = (int)Key.Enter;
io.KeyMap[GuiKey.Escape] = (int)Key.Escape;
io.KeyMap[GuiKey.A] = (int)Key.A;
io.KeyMap[GuiKey.C] = (int)Key.C;
io.KeyMap[GuiKey.V] = (int)Key.V;
io.KeyMap[GuiKey.X] = (int)Key.X;
io.KeyMap[GuiKey.Y] = (int)Key.Y;
io.KeyMap[GuiKey.Z] = (int)Key.Z;
}
private unsafe void OnKeyDown(object sender, KeyboardKeyEventArgs e)
{
ImGui.GetIO().KeysDown[(int)e.Key] = true;
UpdateModifiers(e);
}
private unsafe void OnKeyUp(object sender, KeyboardKeyEventArgs e)
{
ImGui.GetIO().KeysDown[(int)e.Key] = false;
UpdateModifiers(e);
}
private static unsafe void UpdateModifiers(KeyboardKeyEventArgs e)
{
IO io = ImGui.GetIO();
io.AltPressed = e.Alt;
io.CtrlPressed = e.Control;
io.ShiftPressed = e.Shift;
}
private unsafe void CreateDeviceObjects()
{
IO io = ImGui.GetIO();
// Build texture atlas
FontTextureData texData = io.FontAtlas.GetTexDataAsAlpha8();
// Create OpenGL texture
s_fontTexture = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, s_fontTexture);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);
GL.TexImage2D(
TextureTarget.Texture2D,
0,
PixelInternalFormat.Alpha,
texData.Width,
texData.Height,
0,
PixelFormat.Alpha,
PixelType.UnsignedByte,
new IntPtr(texData.Pixels));
// Store the texture identifier in the ImFontAtlas substructure.
io.FontAtlas.SetTexID(s_fontTexture);
// Cleanup (don't clear the input data if you want to append new fonts later)
//io.Fonts->ClearInputData();
io.FontAtlas.ClearTexData();
GL.BindTexture(TextureTarget.Texture2D, 0);
}
public void RunWindowLoop()
{
_nativeWindow.Visible = true;
while (_nativeWindow.Exists)
{
_previousFrameStartTime = DateTime.UtcNow;
RenderFrame();
_nativeWindow.ProcessEvents();
DateTime afterFrameTime = DateTime.UtcNow;
double elapsed = (afterFrameTime - _previousFrameStartTime).TotalSeconds;
double sleepTime = s_desiredFrameLength - elapsed;
if (sleepTime > 0.0)
{
DateTime finishTime = afterFrameTime + TimeSpan.FromSeconds(sleepTime);
while (DateTime.UtcNow < finishTime)
{
Thread.Sleep(0);
}
}
}
}
private unsafe void RenderFrame()
{
IO io = ImGui.GetIO();
io.DisplaySize = new System.Numerics.Vector2(_nativeWindow.Width, _nativeWindow.Height);
io.DisplayFramebufferScale = new System.Numerics.Vector2(_scaleFactor);
io.DeltaTime = (1f / 60f);
UpdateImGuiInput(io);
ImGui.NewFrame();
SubmitImGuiStuff();
ImGui.Render();
DrawData* data = ImGui.GetDrawData();
RenderImDrawData(data);
}
private unsafe void SubmitImGuiStuff()
{
ImGui.GetStyle().WindowRounding = 0;
ImGui.SetNextWindowSize(new System.Numerics.Vector2(_nativeWindow.Width - 10, _nativeWindow.Height - 20), Condition.Always);
ImGui.SetNextWindowPos(ImGui.GetIO().DisplaySize, Condition.Always, new System.Numerics.Vector2(1f));
ImGui.BeginWindow("ImGUI.NET Sample Program", ref _mainWindowOpened, WindowFlags.NoResize | WindowFlags.NoTitleBar | WindowFlags.NoMove);
ImGui.BeginMainMenuBar();
if (ImGui.BeginMenu("Help"))
{
if (ImGui.MenuItem("About", "Ctrl-Alt-A", false, true))
{
}
ImGui.EndMenu();
}
ImGui.EndMainMenuBar();
ImGui.Text("Hello,");
ImGui.Text("World!");
ImGui.Text("From ImGui.NET. ...Did that work?");
var pos = ImGui.GetIO().MousePosition;
bool leftPressed = ImGui.GetIO().MouseDown[0];
ImGui.Text("Current mouse position: " + pos + ". Pressed=" + leftPressed);
ImGui.ShowStyleSelector("Select style");
if (ImGui.Button("Increment the counter."))
{
_pressCount += 1;
}
ImGui.Text($"Button pressed {_pressCount} times.", new System.Numerics.Vector4(0, 1, 1, 1));
ImGui.InputTextMultiline("Input some text:",
_textInputBuffer, (uint)_textInputBufferLength,
new System.Numerics.Vector2(360, 240),
InputTextFlags.Default,
OnTextEdited);
ImGui.SliderFloat("SlidableValue", ref _sliderVal, -50f, 100f, $"{_sliderVal.ToString("##0.00")}", 1.0f);
ImGui.DragVector3("Vector3", ref _positionValue, -100, 100);
if (ImGui.TreeNode("First Item"))
{
ImGui.Text("Word!");
ImGui.TreePop();
}
if (ImGui.TreeNode("Second Item"))
{
ImGui.ColorButton("Color button", _buttonColor, ColorEditFlags.Default, new System.Numerics.Vector2(0, 0));
if (ImGui.Button("Push me to change color", new System.Numerics.Vector2(0, 30)))
{
_buttonColor = new System.Numerics.Vector4(_buttonColor.Y + .25f, _buttonColor.Z, _buttonColor.X, _buttonColor.W);
if (_buttonColor.X > 1.0f)
{
_buttonColor.X -= 1.0f;
}
}
ImGui.TreePop();
}
if (ImGui.Button("Press me!", new System.Numerics.Vector2(100, 30)))
{
ImGuiNative.igOpenPopup("SmallButtonPopup");
}
if (ImGui.BeginPopup("SmallButtonPopup"))
{
ImGui.Text("Here's a popup menu.");
ImGui.Text("With two lines.");
ImGui.EndPopup();
}
if (ImGui.Button("Open Modal window"))
{
ImGui.OpenPopup("ModalPopup");
}
if (ImGui.BeginPopupModal("ModalPopup"))
{
ImGui.Text("You can't press on anything else right now.");
ImGui.Text("You are stuck here.");
if (ImGui.Button("OK", new System.Numerics.Vector2(0, 0))) { }
ImGui.SameLine();
ImGui.Dummy(100f, 0f);
ImGui.SameLine();
if (ImGui.Button("Please go away", new System.Numerics.Vector2(0, 0))) { ImGui.CloseCurrentPopup(); }
ImGui.EndPopup();
}
ImGui.Text("I have a context menu.");
if (ImGui.BeginPopupContextItem("ItemContextMenu"))
{
if (ImGui.Selectable("How's this for a great menu?")) { }
ImGui.Selectable("Just click somewhere to get rid of me.");
ImGui.EndPopup();
}
ImGui.Text("ProgressBar:");
ImGui.ProgressBar(0.5f, new System.Numerics.Vector2(300, 20), "50%");
ImGui.EndWindow();
_memoryEditor.Draw("Memory editor", _memoryEditorData, _memoryEditorData.Length);
if (ImGui.GetIO().AltPressed && ImGui.GetIO().KeysDown[(int)Key.F4])
{
_nativeWindow.Close();
}
}
private unsafe int OnTextEdited(TextEditCallbackData* data)
{
char currentEventChar = (char)data->EventChar;
return 0;
}
private unsafe void UpdateImGuiInput(IO io)
{
MouseState cursorState = Mouse.GetCursorState();
MouseState mouseState = Mouse.GetState();
if (_nativeWindow.Focused)
{
Point windowPoint = _nativeWindow.PointToClient(new Point(cursorState.X, cursorState.Y));
io.MousePosition = new System.Numerics.Vector2(windowPoint.X / io.DisplayFramebufferScale.X, windowPoint.Y / io.DisplayFramebufferScale.Y);
}
else
{
io.MousePosition = new System.Numerics.Vector2(-1f, -1f);
}
io.MouseDown[0] = mouseState.LeftButton == ButtonState.Pressed;
io.MouseDown[1] = mouseState.RightButton == ButtonState.Pressed;
io.MouseDown[2] = mouseState.MiddleButton == ButtonState.Pressed;
float newWheelPos = mouseState.WheelPrecise;
float delta = newWheelPos - _wheelPosition;
_wheelPosition = newWheelPos;
io.MouseWheel = delta;
}
private unsafe void RenderImDrawData(DrawData* draw_data)
{
// Rendering
int display_w, display_h;
display_w = _nativeWindow.Width;
display_h = _nativeWindow.Height;
Vector4 clear_color = new Vector4(114f / 255f, 144f / 255f, 154f / 255f, 1.0f);
GL.Viewport(0, 0, display_w, display_h);
GL.ClearColor(clear_color.X, clear_color.Y, clear_color.Z, clear_color.W);
GL.Clear(ClearBufferMask.ColorBufferBit);
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers.
int last_texture;
GL.GetInteger(GetPName.TextureBinding2D, out last_texture);
GL.PushAttrib(AttribMask.EnableBit | AttribMask.ColorBufferBit | AttribMask.TransformBit);
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
GL.Disable(EnableCap.CullFace);
GL.Disable(EnableCap.DepthTest);
GL.Enable(EnableCap.ScissorTest);
GL.EnableClientState(ArrayCap.VertexArray);
GL.EnableClientState(ArrayCap.TextureCoordArray);
GL.EnableClientState(ArrayCap.ColorArray);
GL.Enable(EnableCap.Texture2D);
GL.UseProgram(0);
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
IO io = ImGui.GetIO();
ImGui.ScaleClipRects(draw_data, io.DisplayFramebufferScale);
// Setup orthographic projection matrix
GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
GL.LoadIdentity();
GL.Ortho(
0.0f,
io.DisplaySize.X / io.DisplayFramebufferScale.X,
io.DisplaySize.Y / io.DisplayFramebufferScale.Y,
0.0f,
-1.0f,
1.0f);
GL.MatrixMode(MatrixMode.Modelview);
GL.PushMatrix();
GL.LoadIdentity();
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
NativeDrawList* cmd_list = draw_data->CmdLists[n];
byte* vtx_buffer = (byte*)cmd_list->VtxBuffer.Data;
ushort* idx_buffer = (ushort*)cmd_list->IdxBuffer.Data;
GL.VertexPointer(2, VertexPointerType.Float, sizeof(DrawVert), new IntPtr(vtx_buffer + DrawVert.PosOffset));
GL.TexCoordPointer(2, TexCoordPointerType.Float, sizeof(DrawVert), new IntPtr(vtx_buffer + DrawVert.UVOffset));
GL.ColorPointer(4, ColorPointerType.UnsignedByte, sizeof(DrawVert), new IntPtr(vtx_buffer + DrawVert.ColOffset));
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
DrawCmd* pcmd = &(((DrawCmd*)cmd_list->CmdBuffer.Data)[cmd_i]);
if (pcmd->UserCallback != IntPtr.Zero)
{
throw new NotImplementedException();
}
else
{
GL.BindTexture(TextureTarget.Texture2D, pcmd->TextureId.ToInt32());
GL.Scissor(
(int)pcmd->ClipRect.X,
(int)(io.DisplaySize.Y - pcmd->ClipRect.W),
(int)(pcmd->ClipRect.Z - pcmd->ClipRect.X),
(int)(pcmd->ClipRect.W - pcmd->ClipRect.Y));
GL.DrawElements(PrimitiveType.Triangles, (int)pcmd->ElemCount, DrawElementsType.UnsignedShort, new IntPtr(idx_buffer));
}
idx_buffer += pcmd->ElemCount;
}
}
// Restore modified state
GL.DisableClientState(ArrayCap.ColorArray);
GL.DisableClientState(ArrayCap.TextureCoordArray);
GL.DisableClientState(ArrayCap.VertexArray);
GL.BindTexture(TextureTarget.Texture2D, last_texture);
GL.MatrixMode(MatrixMode.Modelview);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.PopAttrib();
_graphicsContext.SwapBuffers();
}
}
}

@ -0,0 +1,13 @@
#version 330 core
uniform sampler2D FontTexture;
in vec4 color;
in vec2 texCoord;
out vec4 outputColor;
void main()
{
outputColor = color * texture(FontTexture, texCoord);
}

@ -0,0 +1,20 @@
#version 330 core
uniform ProjectionMatrixBuffer
{
mat4 projection_matrix;
};
in vec2 in_position;
in vec2 in_texCoord;
in vec4 in_color;
out vec4 color;
out vec2 texCoord;
void main()
{
gl_Position = projection_matrix * vec4(in_position, 0, 1);
color = in_color;
texCoord = in_texCoord;
}

@ -0,0 +1,15 @@
struct PS_INPUT
{
float4 pos : SV_POSITION;
float4 col : COLOR0;
float2 uv : TEXCOORD0;
};
Texture2D FontTexture : register(t0);
sampler FontSampler : register(s0);
float4 FS(PS_INPUT input) : SV_Target
{
float4 out_col = input.col * FontTexture.Sample(FontSampler, input.uv);
return out_col;
}

@ -0,0 +1,27 @@
cbuffer ProjectionMatrixBuffer : register(b0)
{
float4x4 ProjectionMatrix;
};
struct VS_INPUT
{
float2 pos : POSITION;
float2 uv : TEXCOORD0;
float4 col : COLOR0;
};
struct PS_INPUT
{
float4 pos : SV_POSITION;
float4 col : COLOR0;
float2 uv : TEXCOORD0;
};
PS_INPUT VS(VS_INPUT input)
{
PS_INPUT output;
output.pos = mul(ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));
output.col = input.col;
output.uv = input.uv;
return output;
}

@ -0,0 +1,18 @@
#include <metal_stdlib>
using namespace metal;
struct PS_INPUT
{
float4 pos [[ position ]];
float4 col;
float2 uv;
};
fragment float4 FS(
PS_INPUT input [[ stage_in ]],
texture2d<float> FontTexture [[ texture(0) ]],
sampler FontSampler [[ sampler(0) ]])
{
float4 out_col = input.col * FontTexture.sample(FontSampler, input.uv);
return out_col;
}

@ -0,0 +1,27 @@
#include <metal_stdlib>
using namespace metal;
struct VS_INPUT
{
float2 pos [[ attribute(0) ]];
float2 uv [[ attribute(1) ]];
float4 col [[ attribute(2) ]];
};
struct PS_INPUT
{
float4 pos [[ position ]];
float4 col;
float2 uv;
};
vertex PS_INPUT VS(
VS_INPUT input [[ stage_in ]],
constant float4x4 &ProjectionMatrix [[ buffer(1) ]])
{
PS_INPUT output;
output.pos = ProjectionMatrix * float4(input.pos.xy, 0.f, 1.f);
output.col = input.col;
output.uv = input.uv;
return output;
}

@ -0,0 +1,2 @@
glslangvalidator -V imgui-vertex.glsl -o imgui-vertex.spv -S vert
glslangvalidator -V imgui-frag.glsl -o imgui-frag.spv -S frag

@ -0,0 +1,16 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
layout(set = 1, binding = 0) uniform texture2D FontTexture;
layout(set = 0, binding = 1) uniform sampler FontSampler;
layout (location = 0) in vec4 color;
layout (location = 1) in vec2 texCoord;
layout (location = 0) out vec4 outputColor;
void main()
{
outputColor = color * texture(sampler2D(FontTexture, FontSampler), texCoord);
}

@ -0,0 +1,29 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
layout (location = 0) in vec2 vsin_position;
layout (location = 1) in vec2 vsin_texCoord;
layout (location = 2) in vec4 vsin_color;
layout (binding = 0) uniform Projection
{
mat4 projection;
};
layout (location = 0) out vec4 vsout_color;
layout (location = 1) out vec2 vsout_texCoord;
out gl_PerVertex
{
vec4 gl_Position;
};
void main()
{
gl_Position = projection * vec4(vsin_position, 0, 1);
vsout_color = vsin_color;
vsout_texCoord = vsin_texCoord;
gl_Position.y = -gl_Position.y;
}

@ -1,15 +0,0 @@
[Debug]
Pos=60,60
Size=400,400
Collapsed=0
[ImGUI.NET Sample Program]
Pos=5,10
Size=950,520
Collapsed=0
[Memory editor]
Pos=210,80
Size=594,403
Collapsed=0

@ -1,28 +1,50 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26228.4
VisualStudioVersion = 15.0.27130.2036
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImGui.NET", "ImGui.NET\ImGui.NET.csproj", "{AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImGui.NET.SampleProgram", "ImGui.NET.SampleProgram\ImGui.NET.SampleProgram.csproj", "{0FBA4057-7708-4FCC-B0D2-D049E647DC5A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImGui.NET.SampleProgram", "ImGui.NET.SampleProgram\ImGui.NET.SampleProgram.csproj", "{D6F62D30-7A37-43A1-BD5B-BE9A3D6F964C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Debug|x64.ActiveCfg = Debug|Any CPU
{AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Debug|x64.Build.0 = Debug|Any CPU
{AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Debug|x86.ActiveCfg = Debug|Any CPU
{AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Debug|x86.Build.0 = Debug|Any CPU
{AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Release|Any CPU.Build.0 = Release|Any CPU
{0FBA4057-7708-4FCC-B0D2-D049E647DC5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0FBA4057-7708-4FCC-B0D2-D049E647DC5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0FBA4057-7708-4FCC-B0D2-D049E647DC5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0FBA4057-7708-4FCC-B0D2-D049E647DC5A}.Release|Any CPU.Build.0 = Release|Any CPU
{AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Release|x64.ActiveCfg = Release|Any CPU
{AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Release|x64.Build.0 = Release|Any CPU
{AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Release|x86.ActiveCfg = Release|Any CPU
{AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Release|x86.Build.0 = Release|Any CPU
{D6F62D30-7A37-43A1-BD5B-BE9A3D6F964C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D6F62D30-7A37-43A1-BD5B-BE9A3D6F964C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D6F62D30-7A37-43A1-BD5B-BE9A3D6F964C}.Debug|x64.ActiveCfg = Debug|Any CPU
{D6F62D30-7A37-43A1-BD5B-BE9A3D6F964C}.Debug|x64.Build.0 = Debug|Any CPU
{D6F62D30-7A37-43A1-BD5B-BE9A3D6F964C}.Debug|x86.ActiveCfg = Debug|Any CPU
{D6F62D30-7A37-43A1-BD5B-BE9A3D6F964C}.Debug|x86.Build.0 = Debug|Any CPU
{D6F62D30-7A37-43A1-BD5B-BE9A3D6F964C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D6F62D30-7A37-43A1-BD5B-BE9A3D6F964C}.Release|Any CPU.Build.0 = Release|Any CPU
{D6F62D30-7A37-43A1-BD5B-BE9A3D6F964C}.Release|x64.ActiveCfg = Release|Any CPU
{D6F62D30-7A37-43A1-BD5B-BE9A3D6F964C}.Release|x64.Build.0 = Release|Any CPU
{D6F62D30-7A37-43A1-BD5B-BE9A3D6F964C}.Release|x86.ActiveCfg = Release|Any CPU
{D6F62D30-7A37-43A1-BD5B-BE9A3D6F964C}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8B446794-E0C0-469F-ACC9-6650375F8BCF}
EndGlobalSection
EndGlobal

@ -138,6 +138,12 @@ namespace ImGuiNET
get { return _nativePtr->WantTextInput == 1; }
set { _nativePtr->WantTextInput = value ? (byte)1 : (byte)0; }
}
public float Framerate
{
get { return _nativePtr->Framerate; }
set { _nativePtr->Framerate = value; }
}
}
public unsafe class KeyMap

@ -491,6 +491,11 @@ namespace ImGuiNET
ImGuiNative.igSetNextWindowFocus();
}
public static void SetNextWindowPos(Vector2 position, Condition condition)
{
ImGuiNative.igSetNextWindowPos(position, condition, Vector2.Zero);
}
public static void SetNextWindowPos(Vector2 position, Condition condition, Vector2 pivot)
{
ImGuiNative.igSetNextWindowPos(position, condition, pivot);

Loading…
Cancel
Save