App wrappers for all of the sample code usage

internals
Eric Mellino 9 years ago
parent 52b84f81ff
commit 1e600bff54
  1. 3
      src/ImGui.NET.SampleProgram/Program.cs
  2. 194
      src/ImGui.NET.SampleProgram/SampleWindow.cs
  3. 19
      src/ImGui.NET/DrawData.cs
  4. 506
      src/ImGui.NET/IO.cs
  5. 1
      src/ImGui.NET/ImGui.NET.Net46.csproj
  6. 4
      src/ImGui.NET/ImGui.NET.csproj
  7. 69
      src/ImGui.NET/ImGui.cs
  8. 2
      src/ImGui.NET/ImGuiNative.cs
  9. 305
      src/ImGui.NET/NativeIO.cs

@ -4,7 +4,8 @@ namespace ImGuiNET
{
public static unsafe void Main(string[] args)
{
new SampleWindow().RunWindowLoop();
var window = new SampleWindow();
window.RunWindowLoop();
}
}
}

@ -30,11 +30,10 @@ namespace ImGuiNET
public unsafe SampleWindow()
{
_nativeWindow = new NativeWindow(960, 540, "ImGui.NET", GameWindowFlags.Default, OpenTK.Graphics.GraphicsMode.Default, DisplayDevice.Default);
_nativeWindow.WindowBorder = WindowBorder.Resizable;
GraphicsContextFlags flags = GraphicsContextFlags.Default;
_graphicsContext = new GraphicsContext(GraphicsMode.Default, _nativeWindow.WindowInfo, 3, 0, flags);
_graphicsContext.MakeCurrent(_nativeWindow.WindowInfo);
_graphicsContext.LoadAll(); // wtf is this?
((IGraphicsContextInternal)_graphicsContext).LoadAll(); // wtf is this?
GL.ClearColor(Color.Black);
_nativeWindow.Visible = true;
@ -42,10 +41,9 @@ namespace ImGuiNET
_nativeWindow.KeyUp += OnKeyUp;
_nativeWindow.KeyPress += OnKeyPress;
IO* io = ImGuiNative.igGetIO();
ImGuiNative.ImFontAtlas_AddFontDefault(io->FontAtlas);
ImGui.LoadDefaultFont();
SetOpenTKKeyMappings(io);
SetOpenTKKeyMappings();
_textInputBufferLength = 1024;
_textInputBuffer = Marshal.AllocHGlobal(_textInputBufferLength);
@ -60,85 +58,94 @@ namespace ImGuiNET
private void OnKeyPress(object sender, KeyPressEventArgs e)
{
ImGuiNative.ImGuiIO_AddInputCharacter(e.KeyChar);
ImGui.AddInputCharacter(e.KeyChar);
}
private static unsafe void SetOpenTKKeyMappings(IO* io)
private static unsafe void SetOpenTKKeyMappings()
{
io->KeyMap[(int)GuiKey.Tab] = (int)Key.Tab;
io->KeyMap[(int)GuiKey.LeftArrow] = (int)Key.Left;
io->KeyMap[(int)GuiKey.RightArrow] = (int)Key.Right;
io->KeyMap[(int)GuiKey.UpArrow] = (int)Key.Up;
io->KeyMap[(int)GuiKey.DownArrow] = (int)Key.Down;
io->KeyMap[(int)GuiKey.PageUp] = (int)Key.PageUp;
io->KeyMap[(int)GuiKey.PageDown] = (int)Key.PageDown;
io->KeyMap[(int)GuiKey.Home] = (int)Key.Home;
io->KeyMap[(int)GuiKey.End] = (int)Key.End;
io->KeyMap[(int)GuiKey.Delete] = (int)Key.Delete;
io->KeyMap[(int)GuiKey.Backspace] = (int)Key.BackSpace;
io->KeyMap[(int)GuiKey.Enter] = (int)Key.Enter;
io->KeyMap[(int)GuiKey.Escape] = (int)Key.Escape;
io->KeyMap[(int)GuiKey.A] = (int)Key.A;
io->KeyMap[(int)GuiKey.C] = (int)Key.C;
io->KeyMap[(int)GuiKey.V] = (int)Key.V;
io->KeyMap[(int)GuiKey.X] = (int)Key.X;
io->KeyMap[(int)GuiKey.Y] = (int)Key.Y;
io->KeyMap[(int)GuiKey.Z] = (int)Key.Z;
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)
{
var ptr = ImGuiNative.igGetIO();
ptr->KeysDown[(int)e.Key] = 1;
UpdateModifiers(e, ptr);
ImGui.GetIO().KeysDown[(int)e.Key] = true;
UpdateModifiers(e);
}
private unsafe void OnKeyUp(object sender, KeyboardKeyEventArgs e)
{
var ptr = ImGuiNative.igGetIO();
ptr->KeysDown[(int)e.Key] = 0;
UpdateModifiers(e, ptr);
ImGui.GetIO().KeysDown[(int)e.Key] = false;
UpdateModifiers(e);
}
private static unsafe void UpdateModifiers(KeyboardKeyEventArgs e, IO* ptr)
private static unsafe void UpdateModifiers(KeyboardKeyEventArgs e)
{
ptr->KeyAlt = e.Alt ? (byte)1 : (byte)0;
ptr->KeyCtrl = e.Control ? (byte)1 : (byte)0;
ptr->KeyShift = e.Shift ? (byte)1 : (byte)0;
IO io = ImGui.GetIO();
io.AltPressed = e.Alt;
io.CtrlPressed = e.Control;
io.ShiftPressed = e.Shift;
}
private unsafe void CreateDeviceObjects()
{
IO* io = ImGuiNative.igGetIO();
IO io = ImGui.GetIO();
// Build texture atlas
byte* pixels;
int width, height;
ImGuiNative.ImFontAtlas_GetTexDataAsAlpha8(io->FontAtlas, &pixels, &width, &height, null);
Alpha8TexData 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, width, height, 0, PixelFormat.Alpha, PixelType.UnsignedByte, new IntPtr(pixels));
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->TexID = new IntPtr(s_fontTexture).ToPointer();
io.FontAtlas.SetTexID(s_fontTexture);
// Cleanup (don't clear the input data if you want to append new fonts later)
//io.Fonts->ClearInputData();
ImGuiNative.ImFontAtlas_ClearTexData(io->FontAtlas);
io.FontAtlas.ClearTexData();
GL.BindTexture(TextureTarget.Texture2D, 0);
}
public void RunWindowLoop()
{
_nativeWindow.Visible = true;
while (_nativeWindow.Visible)
{
_previousFrameStartTime = DateTime.UtcNow;
RenderFrame();
_nativeWindow.ProcessEvents();
DateTime afterFrameTime = DateTime.UtcNow;
@ -151,79 +158,78 @@ namespace ImGuiNET
{
Thread.Sleep(0);
}
Thread.Sleep((int)(sleepTime * 1000));
}
}
}
private unsafe void RenderFrame()
{
IO* io = ImGuiNative.igGetIO();
io->DisplaySize = new System.Numerics.Vector2(_nativeWindow.Width, _nativeWindow.Height);
io->DisplayFramebufferScale = new System.Numerics.Vector2(1, 1);
io->DeltaTime = (1f / 60f);
IO io = ImGui.GetIO();
io.DisplaySize = new System.Numerics.Vector2(_nativeWindow.Width, _nativeWindow.Height);
io.DisplayFramebufferScale = new System.Numerics.Vector2(1, 1);
io.DeltaTime = (1f / 60f);
UpdateImGuiInput(io);
ImGuiNative.igNewFrame();
ImGui.NewFrame();
SubmitImGuiStiff();
SubmitImGuiStuff();
ImGuiNative.igRender();
ImGui.Render();
DrawData* data = ImGuiNative.igGetDrawData();
DrawData* data = ImGui.GetDrawData();
RenderImDrawData(data);
}
private unsafe void SubmitImGuiStiff()
private unsafe void SubmitImGuiStuff()
{
ImGuiNative.igGetStyle()->WindowRounding = 0;
ImGui.GetStyle().WindowRounding = 0;
ImGuiNative.igSetNextWindowSize(new System.Numerics.Vector2(_nativeWindow.Width - 10, _nativeWindow.Height - 20), SetCondition.Always);
ImGuiNative.igSetNextWindowPosCenter(SetCondition.Always);
ImGuiNative.igBegin("ImGUI.NET Sample Program", ref _mainWindowOpened, WindowFlags.NoResize | WindowFlags.NoTitleBar | WindowFlags.NoMove);
ImGui.SetNextWindowSize(new System.Numerics.Vector2(_nativeWindow.Width - 10, _nativeWindow.Height - 20), SetCondition.Always);
ImGui.SetNextWindowPosCenter(SetCondition.Always);
ImGui.BeginWindow("ImGUI.NET Sample Program", ref _mainWindowOpened, WindowFlags.NoResize | WindowFlags.NoTitleBar | WindowFlags.NoMove);
ImGuiNative.igBeginMainMenuBar();
if (ImGuiNative.igBeginMenu("Help"))
ImGui.BeginMainMenuBar();
if (ImGui.BeginMenu("Help"))
{
if (ImGuiNative.igMenuItem("About", "Ctrl-Alt-A", false, true))
if (ImGui.MenuItem("About", "Ctrl-Alt-A", false, true))
{
}
ImGuiNative.igEndMenu();
ImGui.EndMenu();
}
ImGuiNative.igEndMainMenuBar();
ImGui.EndMainMenuBar();
ImGuiNative.igText("Hello,");
ImGuiNative.igText("World!");
ImGuiNative.igText("From ImGui.NET. ...Did that work?");
var pos = ImGuiNative.igGetIO()->MousePos;
bool leftPressed = ImGuiNative.igGetIO()->MouseDown[0] == 1;
ImGuiNative.igText("Current mouse position: " + pos + ". Pressed=" + leftPressed);
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);
if (ImGuiNative.igButton("Press me!", new System.Numerics.Vector2(120, 30)))
if (ImGui.Button("Press me!", new System.Numerics.Vector2(120, 30)))
{
_pressCount += 1;
}
ImGuiNative.igTextColored(new System.Numerics.Vector4(0, 1, 1, 1), $"Button pressed {_pressCount} times.");
ImGui.TextColored(new System.Numerics.Vector4(0, 1, 1, 1), $"Button pressed {_pressCount} times.");
ImGuiNative.igInputTextMultiline("Input some numbers:",
ImGui.InputTextMultiline("Input some numbers:",
_textInputBuffer, (uint)_textInputBufferLength,
new System.Numerics.Vector2(360, 240),
InputTextFlags.CharsDecimal,
OnTextEdited, null);
OnTextEdited);
ImGuiNative.igSliderFloat("SlidableValue", ref _sliderVal, -50f, 100f, $"{_sliderVal.ToString("##0.00")}", 1);
ImGui.SliderFloat("SlidableValue", ref _sliderVal, -50f, 100f, $"{_sliderVal.ToString("##0.00")}", 1.0f);
if (ImGuiNative.igTreeNode("First Item"))
if (ImGui.TreeNode("First Item"))
{
ImGuiNative.igText("Word!");
ImGuiNative.igTreePop();
ImGui.Text("Word!");
ImGui.TreePop();
}
if (ImGuiNative.igTreeNode("Second Item"))
if (ImGui.TreeNode("Second Item"))
{
ImGuiNative.igColorButton(_buttonColor, false, true);
ImGui.ColorButton(_buttonColor, false, true);
if (ImGui.Button("Push me to change color", new System.Numerics.Vector2(120, 30)))
{
_buttonColor = new System.Numerics.Vector4(_buttonColor.Y + .25f, _buttonColor.Z, _buttonColor.X, _buttonColor.W);
@ -233,20 +239,24 @@ namespace ImGuiNET
}
}
ImGuiNative.igTreePop();
ImGui.TreePop();
}
ImGuiNative.igEnd();
ImGui.EndWindow();
if (ImGui.GetIO().AltPressed && ImGui.GetIO().KeysDown[(int)Key.F4])
{
_nativeWindow.Close();
}
}
private unsafe int OnTextEdited(TextEditCallbackData* data)
{
char currentEventChar = (char)data->EventChar;
Console.WriteLine("Event char: " + currentEventChar);
return 0;
}
private unsafe void UpdateImGuiInput(IO* io)
private unsafe void UpdateImGuiInput(IO io)
{
MouseState cursorState = Mouse.GetCursorState();
MouseState mouseState = Mouse.GetState();
@ -254,21 +264,21 @@ namespace ImGuiNET
if (_nativeWindow.Bounds.Contains(cursorState.X, cursorState.Y))
{
Point windowPoint = _nativeWindow.PointToClient(new Point(cursorState.X, cursorState.Y));
io->MousePos = new System.Numerics.Vector2(windowPoint.X, windowPoint.Y);
io.MousePosition = new System.Numerics.Vector2(windowPoint.X, windowPoint.Y);
}
else
{
io->MousePos = new System.Numerics.Vector2(-1f, -1f);
io.MousePosition = new System.Numerics.Vector2(-1f, -1f);
}
io->MouseDown[0] = (mouseState.LeftButton == ButtonState.Pressed) ? (byte)255 : (byte)0; // Left
io->MouseDown[1] = (mouseState.RightButton == ButtonState.Pressed) ? (byte)255 : (byte)0; // Right
io->MouseDown[2] = (mouseState.MiddleButton == ButtonState.Pressed) ? (byte)255 : (byte)0; // Middle
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;
io.MouseWheel = delta;
}
private unsafe void RenderImDrawData(DrawData* draw_data)
@ -301,15 +311,15 @@ namespace ImGuiNET
GL.UseProgram(0);
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
IO* io = ImGuiNative.igGetIO();
float fb_height = io->DisplaySize.Y * io->DisplayFramebufferScale.Y;
ImGui.ScaleClipRects(draw_data, io->DisplayFramebufferScale);
IO io = ImGui.GetIO();
float fb_height = io.DisplaySize.Y * io.DisplayFramebufferScale.Y;
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->DisplaySize.Y, 0.0f, -1.0f, 1.0f);
GL.Ortho(0.0f, io.DisplaySize.X, io.DisplaySize.Y, 0.0f, -1.0f, 1.0f);
GL.MatrixMode(MatrixMode.Modelview);
GL.PushMatrix();
GL.LoadIdentity();

@ -2,14 +2,25 @@
namespace ImGuiNET
{
// All draw data to render an ImGui frame
/// <summary>
/// All draw data to render an ImGui frame
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public unsafe struct DrawData
{
public byte Valid; // Only valid after Render() is called and before the next NewFrame() is called.
/// <summary>
/// Only valid after Render() is called and before the next NewFrame() is called.
/// </summary>
public byte Valid;
public DrawList** CmdLists;
public int CmdListsCount;
public int TotalVtxCount; // For convenience, sum of all cmd_lists vtx_buffer.Size
public int TotalIdxCount; // For convenience, sum of all cmd_lists idx_buffer.Size
/// <summary>
/// For convenience, sum of all cmd_lists vtx_buffer.Size
/// </summary>
public int TotalVtxCount;
/// <summary>
/// For convenience, sum of all cmd_lists idx_buffer.Size
/// </summary>
public int TotalIdxCount;
};
}

@ -4,302 +4,214 @@ using System.Runtime.InteropServices;
namespace ImGuiNET
{
[StructLayout(LayoutKind.Sequential)]
public unsafe struct IO
{
//------------------------------------------------------------------
// Settings (fill once)
//------------------------------------------------------------------
/// <summary>
/// Display size, in pixels. For clamping windows positions.
/// Default value: [unset]
/// </summary>
public Vector2 DisplaySize;
/// <summary>
/// Time elapsed since last frame, in seconds.
/// Default value: 1.0f / 10.0f.
/// </summary>
public float DeltaTime;
/// <summary>
/// Maximum time between saving positions/sizes to .ini file, in seconds.
/// Default value: 5.0f.
/// </summary>
public float IniSavingRate;
/// <summary>
/// Path to .ini file. NULL to disable .ini saving.
/// Default value: "imgui.ini"
/// </summary>
public IntPtr IniFilename;
/// <summary>
/// Path to .log file (default parameter to ImGui::LogToFile when no file is specified).
/// Default value: "imgui_log.txt"
/// </summary>
public IntPtr LogFilename;
/// <summary>
/// Time for a double-click, in seconds.
/// Default value: 0.30f.
/// </summary>
public float MouseDoubleClickTime;
/// <summary>
/// Distance threshold to stay in to validate a double-click, in pixels.
/// Default Value: 6.0f.
/// </summary>
public float MouseDoubleClickMaxDist;
/// <summary>
/// Distance threshold before considering we are dragging.
/// Default Value: 6.0f.
/// </summary>
public float MouseDragThreshold;
/// <summary>
/// Map of indices into the KeysDown[512] entries array.
/// Default values: [unset]
/// </summary>
public fixed int KeyMap[(int)GuiKey.Count];
/// <summary>
/// When holding a key/button, time before it starts repeating, in seconds. (for actions where 'repeat' is active).
/// Default value: 0.250f.
/// </summary>
public float KeyRepeatDelay;
/// <summary>
/// When holding a key/button, rate at which it repeats, in seconds.
/// Default value: 0.020f.
/// </summary>
public float KeyRepeatRate;
/// <summary>
/// Store your own data for retrieval by callbacks.
/// Default value; IntPtr.Zero.
/// </summary>
public IntPtr UserData;
/// <summary>
/// Load and assemble one or more fonts into a single tightly packed texture. Output to Fonts array.
/// Default value: [auto]
/// </summary>
public FontAtlas* FontAtlas;
/// <summary>
/// Global scale all fonts.
/// Default value: 1.0f.
/// </summary>
public float FontGlobalScale;
/// <summary>
/// Allow user scaling text of individual window with CTRL+Wheel.
/// Default value: false.
/// </summary>
public byte FontAllowUserScaling;
/// <summary>
/// For retina display or other situations where window coordinates are different from framebuffer coordinates.
/// User storage only, presently not used by ImGui.
/// Default value: (1.0f, 1.0f).
/// </summary>
public Vector2 DisplayFramebufferScale;
/// <summary>
/// If you use DisplaySize as a virtual space larger than your screen, set DisplayVisibleMin/Max to the visible area.
/// Default value: (0.0f, 0.0f)
/// </summary>
public Vector2 DisplayVisibleMin;
/// <summary>
/// If the values are the same, we defaults to Min=0.0f) and Max=DisplaySize.
/// Default value: (0.0f, 0.0f).
/// </summary>
public Vector2 DisplayVisibleMax; // <unset> (0.0f,0.0f) // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize
//------------------------------------------------------------------
// User Functions
//------------------------------------------------------------------
/// <summary>
/// Rendering function, will be called in Render().
/// Alternatively you can keep this to NULL and call GetDrawData() after Render() to get the same pointer.
/// </summary>
public IntPtr RenderDrawListsFn;
/// <summary>
/// Optional: access OS clipboard
/// (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures)
/// </summary>
public IntPtr GetClipboardTextFn;
/// <summary>
/// Optional: access OS clipboard
/// (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures)
/// </summary>
public IntPtr SetClipboardTextFn;
/// <summary>
/// Optional: override memory allocations. MemFreeFn() may be called with a NULL pointer.
/// (default to posix malloc/free)
/// </summary>
public IntPtr MemAllocFn;
/// <summary>
/// Optional: override memory allocations. MemFreeFn() may be called with a NULL pointer.
/// (default to posix malloc/free)
/// </summary>
public IntPtr MemFreeFn;
/// <summary>
/// Optional: notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME in Windows)
/// (default to use native imm32 api on Windows)
/// </summary>
public IntPtr ImeSetInputScreenPosFn;
/// <summary>
/// (Windows) Set this to your HWND to get automatic IME cursor positioning.
/// </summary>
public IntPtr ImeWindowHandle;
//------------------------------------------------------------------
// Input - Fill before calling NewFrame()
//------------------------------------------------------------------
/// <summary>
/// Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.).
/// </summary>
public Vector2 MousePos;
/// <summary>
/// Mouse buttons: left, right, middle + extras.
/// ImGui itself mostly only uses left button (BeginPopupContext** are using right button).
/// Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API.
/// </summary>
public fixed byte MouseDown[5];
/// <summary>
/// Mouse wheel: 1 unit scrolls about 5 lines text.
/// </summary>
public float MouseWheel;
/// <summary>
/// Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor).
/// </summary>
public byte MouseDrawCursor;
/// <summary>
/// Keyboard modifier pressed: Control.
/// </summary>
public byte KeyCtrl;
/// <summary>
/// Keyboard modifier pressed: Shift
/// </summary>
public byte KeyShift;
/// <summary>
/// Keyboard modifier pressed: Alt
/// </summary>
public byte KeyAlt;
/// <summary>
/// Keyboard keys that are pressed (in whatever storage order you naturally have access to keyboard data)
/// </summary>
public fixed byte KeysDown[512];
/// <summary>
/// List of characters input (translated by user from keypress+keyboard state).
/// Fill using AddInputCharacter() helper.
/// </summary>
public fixed ushort InputCharacters[16 + 1];
//------------------------------------------------------------------
// Output - Retrieve after calling NewFrame(), you can use them to discard inputs or hide them from the rest of your application
//------------------------------------------------------------------
/// <summary>
/// Mouse is hovering a window or widget is active (= ImGui will use your mouse input).
/// </summary>
public byte WantCaptureMouse;
/// <summary>
/// Widget is active (= ImGui will use your keyboard input).
/// </summary>
public byte WantCaptureKeyboard;
/// <summary>
/// Some text input widget is active, which will read input characters from the InputCharacters array.
/// </summary>
public byte WantTextInput;
/// <summary>
/// Framerate estimation, in frame per second. Rolling average estimation based on IO.DeltaTime over 120 frames.
/// </summary>
public float Framerate;
/// <summary>
/// Number of active memory allocations.
/// </summary>
public int MetricsAllocs;
/// <summary>
/// Vertices output during last call to Render().
/// </summary>
public int MetricsRenderVertices;
/// <summary>
/// Indices output during last call to Render() = number of triangles * 3
/// </summary>
public int MetricsRenderIndices;
/// <summary>
/// Number of visible windows (exclude child windows)
/// </summary>
public int MetricsActiveWindows;
//------------------------------------------------------------------
// [Internal] ImGui will maintain those fields for you
//------------------------------------------------------------------
/// <summary>
/// Previous mouse position
/// </summary>
public Vector2 MousePosPrev;
/// <summary>
/// Mouse delta. Note that this is zero if either current or previous position are negative to allow mouse enabling/disabling.
/// </summary>
public Vector2 MouseDelta;
/// <summary>
/// Mouse button went from !Down to Down
/// </summary>
public fixed byte MouseClicked[5];
/// <summary>
/// Position at time of clicking
/// </summary>
public Vector2 MouseClickedPos0;
/// <summary>
/// Position at time of clicking
/// </summary>
public Vector2 MouseClickedPos1;
/// <summary>
/// Position at time of clicking
/// </summary>
public Vector2 MouseClickedPos2;
/// <summary>
/// Position at time of clicking
/// </summary>
public Vector2 MouseClickedPos3;
/// <summary>
/// Position at time of clicking
/// </summary>
public Vector2 MouseClickedPos4;
/// <summary>
/// Time of last click (used to figure out double-click)
/// </summary>
public fixed float MouseClickedTime[5];
/// <summary>
/// Has mouse button been double-clicked?
/// </summary>
public fixed byte MouseDoubleClicked[5];
/// <summary>
/// Mouse button went from Down to !Down
/// </summary>
public fixed byte MouseReleased[5];
/// <summary>
/// Track if button was clicked inside a window.
/// We don't request mouse capture from the application if click started outside ImGui bounds.
/// </summary>
public fixed byte MouseDownOwned[5];
/// <summary>
/// Duration the mouse button has been down (0.0f == just clicked).
/// </summary>
public fixed float MouseDownDuration[5];
/// <summary>
/// Previous time the mouse button has been down
/// </summary>
public fixed float MouseDownDurationPrev[5];
/// <summary>
/// Squared maximum distance of how much mouse has traveled from the click point
/// </summary>
public fixed float MouseDragMaxDistanceSqr[5];
/// <summary>
/// Duration the keyboard key has been down (0.0f == just pressed)
/// </summary>
public fixed float KeysDownDuration[512];
/// <summary>
/// Previous duration the key has been down
/// </summary>
public fixed float KeysDownDurationPrev[512];
public unsafe class IO
{
private NativeIO* _nativePtr;
internal IO(NativeIO* nativePtr)
{
_nativePtr = nativePtr;
MouseDown = new MouseDownStates(nativePtr);
KeyMap = new KeyMap(_nativePtr);
KeysDown = new KeyDownStates(_nativePtr);
FontAtlas = new FontAtlasWrapped(_nativePtr->FontAtlas);
}
public NativeIO* GetNativePointer() => _nativePtr;
public float DeltaTime
{
get { return _nativePtr->DeltaTime; }
set { _nativePtr->DeltaTime = value; }
}
public Vector2 DisplayFramebufferScale
{
get { return _nativePtr->DisplayFramebufferScale; }
set { _nativePtr->DisplayFramebufferScale = value; }
}
public Vector2 DisplaySize
{
get { return _nativePtr->DisplaySize; }
set { _nativePtr->DisplaySize = value; }
}
public Vector2 MousePosition
{
get { return _nativePtr->MousePos; }
set { _nativePtr->MousePos = value; }
}
public float MouseWheel
{
get { return _nativePtr->MouseWheel; }
set { _nativePtr->MouseWheel = value; }
}
public MouseDownStates MouseDown { get; }
public KeyMap KeyMap { get; }
public KeyDownStates KeysDown { get; }
public FontAtlasWrapped FontAtlas { get; }
public bool AltPressed
{
get { return _nativePtr->KeyAlt == 1; }
set { _nativePtr->KeyAlt = value ? (byte)1 : (byte)0; }
}
public bool CtrlPressed
{
get { return _nativePtr->KeyCtrl == 1; }
set { _nativePtr->KeyCtrl = value ? (byte)1 : (byte)0; }
}
public bool ShiftPressed
{
get { return _nativePtr->KeyShift == 1; }
set { _nativePtr->KeyShift = value ? (byte)1 : (byte)0; }
}
}
public unsafe class KeyMap
{
private readonly NativeIO* _nativePtr;
public KeyMap(NativeIO* nativePtr)
{
_nativePtr = nativePtr;
}
public int this[GuiKey key]
{
get
{
return _nativePtr->KeyMap[(int)key];
}
set
{
_nativePtr->KeyMap[(int)key] = value;
}
}
}
public unsafe class MouseDownStates
{
private readonly NativeIO* _nativePtr;
public MouseDownStates(NativeIO* nativePtr)
{
_nativePtr = nativePtr;
}
public bool this[int button]
{
get
{
if (button < 0 || button > 5)
{
throw new ArgumentOutOfRangeException(nameof(button));
}
return _nativePtr->MouseDown[button] == 1;
}
set
{
if (button < 0 || button > 5)
{
throw new ArgumentOutOfRangeException(nameof(button));
}
byte pressed = value ? (byte)1 : (byte)0;
_nativePtr->MouseDown[button] = pressed;
}
}
}
public unsafe class KeyDownStates
{
private readonly NativeIO* _nativePtr;
public KeyDownStates(NativeIO* nativePtr)
{
_nativePtr = nativePtr;
}
public bool this[int key]
{
get
{
if (key < 0 || key > 512)
{
throw new ArgumentOutOfRangeException(nameof(key));
}
return _nativePtr->KeysDown[key] == 1;
}
set
{
if (key < 0 || key > 512)
{
throw new ArgumentOutOfRangeException(nameof(key));
}
byte pressed = value ? (byte)1 : (byte)0;
_nativePtr->KeysDown[key] = pressed;
}
}
}
public unsafe class FontAtlasWrapped
{
private readonly FontAtlas* _atlasPtr;
public FontAtlasWrapped(FontAtlas* atlasPtr)
{
_atlasPtr = atlasPtr;
}
public Alpha8TexData GetTexDataAsAlpha8()
{
byte* pixels;
int width, height;
int bytesPerPixel;
ImGuiNative.ImFontAtlas_GetTexDataAsAlpha8(_atlasPtr, &pixels, &width, &height, &bytesPerPixel);
return new Alpha8TexData(pixels, width, height, bytesPerPixel);
}
public void SetTexID(int textureID)
{
SetTexID(new IntPtr(textureID));
}
public void SetTexID(IntPtr textureID)
{
ImGuiNative.ImFontAtlas_SetTexID(_atlasPtr, textureID.ToPointer());
}
public void ClearTexData()
{
ImGuiNative.ImFontAtlas_ClearTexData(_atlasPtr);
}
}
public unsafe struct Alpha8TexData
{
public readonly byte* Pixels;
public readonly int Width;
public readonly int Height;
public readonly int BytesPerPixel;
public Alpha8TexData(byte* pixels, int width, int height, int bytesPerPixel)
{
Pixels = pixels;
Width = width;
Height = height;
BytesPerPixel = bytesPerPixel;
}
}
}

@ -16,6 +16,7 @@
<Compile Include="Align.cs" />
<Compile Include="ColorTarget.cs" />
<Compile Include="MouseCursorKind.cs" />
<Compile Include="NativeIO.cs" />
<Compile Include="SelectableFlags.cs" />
<Compile Include="StyleVar.cs" />
<Compile Include="WindowFlags.cs" />

@ -13,6 +13,7 @@
<Compile Include="Align.cs" />
<Compile Include="ColorTarget.cs" />
<Compile Include="MouseCursorKind.cs" />
<Compile Include="NativeIO.cs" />
<Compile Include="SelectableFlags.cs" />
<Compile Include="StyleVar.cs" />
<Compile Include="TextInputBuffer.cs" />
@ -87,5 +88,8 @@
<ItemGroup>
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
<Reference Include="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>

@ -16,9 +16,20 @@ namespace ImGuiNET
ImGuiNative.igRender();
}
private static unsafe readonly IO s_io = new IO(ImGuiNative.igGetIO());
public static unsafe IO GetIO() => s_io;
private static unsafe readonly StyleWrapped s_style = new StyleWrapped(ImGuiNative.igGetStyle());
public static unsafe StyleWrapped GetStyle()
{
return s_style;
}
public static unsafe void LoadDefaultFont()
{
IO* ioPtr = ImGuiNative.igGetIO();
NativeIO* ioPtr = ImGuiNative.igGetIO();
ImGuiNative.ImFontAtlas_AddFontDefault(ioPtr->FontAtlas);
}
@ -57,6 +68,11 @@ namespace ImGuiNET
ImGuiNative.igSetNextWindowPosCenter(condition);
}
public static void AddInputCharacter(char keyChar)
{
ImGuiNative.ImGuiIO_AddInputCharacter(keyChar);
}
/// <summary>
/// Helper to scale the ClipRect field of each ImDrawCmd.
/// Use if your final output buffer is at a different scale than ImGui expects,
@ -111,6 +127,11 @@ namespace ImGuiNET
return ImGuiNative.igBegin2(windowTitle, ref opened, new Vector2(), backgroundAlpha, flags);
}
public static bool BeginMenu(string label)
{
return ImGuiNative.igBeginMenu(label, true);
}
public static bool BeginMenu(string label, bool enabled)
{
return ImGuiNative.igBeginMenu(label, enabled);
@ -189,6 +210,16 @@ namespace ImGuiNET
ImGuiNative.igPushStyleColor(target, color);
}
public static unsafe void InputTextMultiline(string label, IntPtr textBuffer, uint bufferSize, Vector2 size, InputTextFlags flags, TextEditCallback callback)
{
ImGuiNative.igInputTextMultiline(label, textBuffer, bufferSize, size, flags, callback, null);
}
public static unsafe DrawData* GetDrawData()
{
return ImGuiNative.igGetDrawData();
}
public static unsafe void InputTextMultiline(string label, IntPtr textBuffer, uint bufferSize, Vector2 size, InputTextFlags flags, TextEditCallback callback, IntPtr userData)
{
ImGuiNative.igInputTextMultiline(label, textBuffer, bufferSize, size, flags, callback, userData.ToPointer());
@ -234,6 +265,16 @@ namespace ImGuiNET
return Selectable(label, isSelected, SelectableFlags.Default);
}
public static void BeginMainMenuBar()
{
ImGuiNative.igBeginMainMenuBar();
}
public static void EndMainMenuBar()
{
ImGuiNative.igEndMainMenuBar();
}
public static bool Selectable(string label, bool isSelected, SelectableFlags flags)
{
return Selectable(label, isSelected, flags, new Vector2());
@ -254,6 +295,16 @@ namespace ImGuiNET
return result;
}
public static void SliderFloat(string sliderLabel, ref float value, float min, float max, string displayText, float power)
{
ImGuiNative.igSliderFloat(sliderLabel, ref value, min, max, displayText, power);
}
public static void TextColored(Vector4 colorRGBA, string text)
{
ImGuiNative.igTextColored(colorRGBA, text);
}
public static void SameLine()
{
ImGuiNative.igSameLine(0, 0);
@ -296,4 +347,20 @@ namespace ImGuiNET
return result;
}
}
public unsafe class StyleWrapped
{
private readonly Style* _stylePtr;
public StyleWrapped(Style* style)
{
_stylePtr = style;
}
public float WindowRounding
{
get { return _stylePtr->WindowRounding; }
set { _stylePtr->WindowRounding = value; }
}
}
}

@ -12,7 +12,7 @@ namespace ImGuiNET
private const string cimguiLib = "cimgui";
[DllImport(cimguiLib)]
public static extern IO* igGetIO(); /* { return (IO*)igGetIO_Raw().ToPointer(); } */
public static extern NativeIO* igGetIO(); /* { return (IO*)igGetIO_Raw().ToPointer(); } */
[DllImport(cimguiLib)]
public static extern Style* igGetStyle();

@ -0,0 +1,305 @@
using System;
using System.Numerics;
using System.Runtime.InteropServices;
namespace ImGuiNET
{
[StructLayout(LayoutKind.Sequential)]
public unsafe struct NativeIO
{
//------------------------------------------------------------------
// Settings (fill once)
//------------------------------------------------------------------
/// <summary>
/// Display size, in pixels. For clamping windows positions.
/// Default value: [unset]
/// </summary>
public Vector2 DisplaySize;
/// <summary>
/// Time elapsed since last frame, in seconds.
/// Default value: 1.0f / 10.0f.
/// </summary>
public float DeltaTime;
/// <summary>
/// Maximum time between saving positions/sizes to .ini file, in seconds.
/// Default value: 5.0f.
/// </summary>
public float IniSavingRate;
/// <summary>
/// Path to .ini file. NULL to disable .ini saving.
/// Default value: "imgui.ini"
/// </summary>
public IntPtr IniFilename;
/// <summary>
/// Path to .log file (default parameter to ImGui::LogToFile when no file is specified).
/// Default value: "imgui_log.txt"
/// </summary>
public IntPtr LogFilename;
/// <summary>
/// Time for a double-click, in seconds.
/// Default value: 0.30f.
/// </summary>
public float MouseDoubleClickTime;
/// <summary>
/// Distance threshold to stay in to validate a double-click, in pixels.
/// Default Value: 6.0f.
/// </summary>
public float MouseDoubleClickMaxDist;
/// <summary>
/// Distance threshold before considering we are dragging.
/// Default Value: 6.0f.
/// </summary>
public float MouseDragThreshold;
/// <summary>
/// Map of indices into the KeysDown[512] entries array.
/// Default values: [unset]
/// </summary>
public fixed int KeyMap[(int)GuiKey.Count];
/// <summary>
/// When holding a key/button, time before it starts repeating, in seconds. (for actions where 'repeat' is active).
/// Default value: 0.250f.
/// </summary>
public float KeyRepeatDelay;
/// <summary>
/// When holding a key/button, rate at which it repeats, in seconds.
/// Default value: 0.020f.
/// </summary>
public float KeyRepeatRate;
/// <summary>
/// Store your own data for retrieval by callbacks.
/// Default value; IntPtr.Zero.
/// </summary>
public IntPtr UserData;
/// <summary>
/// Load and assemble one or more fonts into a single tightly packed texture. Output to Fonts array.
/// Default value: [auto]
/// </summary>
public FontAtlas* FontAtlas;
/// <summary>
/// Global scale all fonts.
/// Default value: 1.0f.
/// </summary>
public float FontGlobalScale;
/// <summary>
/// Allow user scaling text of individual window with CTRL+Wheel.
/// Default value: false.
/// </summary>
public byte FontAllowUserScaling;
/// <summary>
/// For retina display or other situations where window coordinates are different from framebuffer coordinates.
/// User storage only, presently not used by ImGui.
/// Default value: (1.0f, 1.0f).
/// </summary>
public Vector2 DisplayFramebufferScale;
/// <summary>
/// If you use DisplaySize as a virtual space larger than your screen, set DisplayVisibleMin/Max to the visible area.
/// Default value: (0.0f, 0.0f)
/// </summary>
public Vector2 DisplayVisibleMin;
/// <summary>
/// If the values are the same, we defaults to Min=0.0f) and Max=DisplaySize.
/// Default value: (0.0f, 0.0f).
/// </summary>
public Vector2 DisplayVisibleMax; // <unset> (0.0f,0.0f) // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize
//------------------------------------------------------------------
// User Functions
//------------------------------------------------------------------
/// <summary>
/// Rendering function, will be called in Render().
/// Alternatively you can keep this to NULL and call GetDrawData() after Render() to get the same pointer.
/// </summary>
public IntPtr RenderDrawListsFn;
/// <summary>
/// Optional: access OS clipboard
/// (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures)
/// </summary>
public IntPtr GetClipboardTextFn;
/// <summary>
/// Optional: access OS clipboard
/// (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures)
/// </summary>
public IntPtr SetClipboardTextFn;
/// <summary>
/// Optional: override memory allocations. MemFreeFn() may be called with a NULL pointer.
/// (default to posix malloc/free)
/// </summary>
public IntPtr MemAllocFn;
/// <summary>
/// Optional: override memory allocations. MemFreeFn() may be called with a NULL pointer.
/// (default to posix malloc/free)
/// </summary>
public IntPtr MemFreeFn;
/// <summary>
/// Optional: notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME in Windows)
/// (default to use native imm32 api on Windows)
/// </summary>
public IntPtr ImeSetInputScreenPosFn;
/// <summary>
/// (Windows) Set this to your HWND to get automatic IME cursor positioning.
/// </summary>
public IntPtr ImeWindowHandle;
//------------------------------------------------------------------
// Input - Fill before calling NewFrame()
//------------------------------------------------------------------
/// <summary>
/// Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.).
/// </summary>
public Vector2 MousePos;
/// <summary>
/// Mouse buttons: left, right, middle + extras.
/// ImGui itself mostly only uses left button (BeginPopupContext** are using right button).
/// Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API.
/// </summary>
public fixed byte MouseDown[5];
/// <summary>
/// Mouse wheel: 1 unit scrolls about 5 lines text.
/// </summary>
public float MouseWheel;
/// <summary>
/// Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor).
/// </summary>
public byte MouseDrawCursor;
/// <summary>
/// Keyboard modifier pressed: Control.
/// </summary>
public byte KeyCtrl;
/// <summary>
/// Keyboard modifier pressed: Shift
/// </summary>
public byte KeyShift;
/// <summary>
/// Keyboard modifier pressed: Alt
/// </summary>
public byte KeyAlt;
/// <summary>
/// Keyboard keys that are pressed (in whatever storage order you naturally have access to keyboard data)
/// </summary>
public fixed byte KeysDown[512];
/// <summary>
/// List of characters input (translated by user from keypress+keyboard state).
/// Fill using AddInputCharacter() helper.
/// </summary>
public fixed ushort InputCharacters[16 + 1];
//------------------------------------------------------------------
// Output - Retrieve after calling NewFrame(), you can use them to discard inputs or hide them from the rest of your application
//------------------------------------------------------------------
/// <summary>
/// Mouse is hovering a window or widget is active (= ImGui will use your mouse input).
/// </summary>
public byte WantCaptureMouse;
/// <summary>
/// Widget is active (= ImGui will use your keyboard input).
/// </summary>
public byte WantCaptureKeyboard;
/// <summary>
/// Some text input widget is active, which will read input characters from the InputCharacters array.
/// </summary>
public byte WantTextInput;
/// <summary>
/// Framerate estimation, in frame per second. Rolling average estimation based on IO.DeltaTime over 120 frames.
/// </summary>
public float Framerate;
/// <summary>
/// Number of active memory allocations.
/// </summary>
public int MetricsAllocs;
/// <summary>
/// Vertices output during last call to Render().
/// </summary>
public int MetricsRenderVertices;
/// <summary>
/// Indices output during last call to Render() = number of triangles * 3
/// </summary>
public int MetricsRenderIndices;
/// <summary>
/// Number of visible windows (exclude child windows)
/// </summary>
public int MetricsActiveWindows;
//------------------------------------------------------------------
// [Internal] ImGui will maintain those fields for you
//------------------------------------------------------------------
/// <summary>
/// Previous mouse position
/// </summary>
public Vector2 MousePosPrev;
/// <summary>
/// Mouse delta. Note that this is zero if either current or previous position are negative to allow mouse enabling/disabling.
/// </summary>
public Vector2 MouseDelta;
/// <summary>
/// Mouse button went from !Down to Down
/// </summary>
public fixed byte MouseClicked[5];
/// <summary>
/// Position at time of clicking
/// </summary>
public Vector2 MouseClickedPos0;
/// <summary>
/// Position at time of clicking
/// </summary>
public Vector2 MouseClickedPos1;
/// <summary>
/// Position at time of clicking
/// </summary>
public Vector2 MouseClickedPos2;
/// <summary>
/// Position at time of clicking
/// </summary>
public Vector2 MouseClickedPos3;
/// <summary>
/// Position at time of clicking
/// </summary>
public Vector2 MouseClickedPos4;
/// <summary>
/// Time of last click (used to figure out double-click)
/// </summary>
public fixed float MouseClickedTime[5];
/// <summary>
/// Has mouse button been double-clicked?
/// </summary>
public fixed byte MouseDoubleClicked[5];
/// <summary>
/// Mouse button went from Down to !Down
/// </summary>
public fixed byte MouseReleased[5];
/// <summary>
/// Track if button was clicked inside a window.
/// We don't request mouse capture from the application if click started outside ImGui bounds.
/// </summary>
public fixed byte MouseDownOwned[5];
/// <summary>
/// Duration the mouse button has been down (0.0f == just clicked).
/// </summary>
public fixed float MouseDownDuration[5];
/// <summary>
/// Previous time the mouse button has been down
/// </summary>
public fixed float MouseDownDurationPrev[5];
/// <summary>
/// Squared maximum distance of how much mouse has traveled from the click point
/// </summary>
public fixed float MouseDragMaxDistanceSqr[5];
/// <summary>
/// Duration the keyboard key has been down (0.0f == just pressed)
/// </summary>
public fixed float KeysDownDuration[512];
/// <summary>
/// Previous duration the key has been down
/// </summary>
public fixed float KeysDownDurationPrev[512];
}
}
Loading…
Cancel
Save