diff --git a/src/ImGui.NET.SampleProgram/Program.cs b/src/ImGui.NET.SampleProgram/Program.cs index 61f11c9..953def4 100644 --- a/src/ImGui.NET.SampleProgram/Program.cs +++ b/src/ImGui.NET.SampleProgram/Program.cs @@ -4,7 +4,8 @@ namespace ImGuiNET { public static unsafe void Main(string[] args) { - new SampleWindow().RunWindowLoop(); + var window = new SampleWindow(); + window.RunWindowLoop(); } } } \ No newline at end of file diff --git a/src/ImGui.NET.SampleProgram/SampleWindow.cs b/src/ImGui.NET.SampleProgram/SampleWindow.cs index 7927f65..5598e20 100644 --- a/src/ImGui.NET.SampleProgram/SampleWindow.cs +++ b/src/ImGui.NET.SampleProgram/SampleWindow.cs @@ -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(); diff --git a/src/ImGui.NET/DrawData.cs b/src/ImGui.NET/DrawData.cs index 2ce11aa..98f2064 100644 --- a/src/ImGui.NET/DrawData.cs +++ b/src/ImGui.NET/DrawData.cs @@ -2,14 +2,25 @@ namespace ImGuiNET { - // All draw data to render an ImGui frame + /// + /// All draw data to render an ImGui frame + /// [StructLayout(LayoutKind.Sequential)] public unsafe struct DrawData { - public byte Valid; // Only valid after Render() is called and before the next NewFrame() is called. + /// + /// Only valid after Render() is called and before the next NewFrame() is called. + /// + 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 + /// + /// For convenience, sum of all cmd_lists vtx_buffer.Size + /// + public int TotalVtxCount; + /// + /// For convenience, sum of all cmd_lists idx_buffer.Size + /// + public int TotalIdxCount; }; } diff --git a/src/ImGui.NET/IO.cs b/src/ImGui.NET/IO.cs index 70660cb..7296a42 100644 --- a/src/ImGui.NET/IO.cs +++ b/src/ImGui.NET/IO.cs @@ -4,302 +4,214 @@ using System.Runtime.InteropServices; namespace ImGuiNET { - [StructLayout(LayoutKind.Sequential)] - public unsafe struct IO + public unsafe class IO { - //------------------------------------------------------------------ - // Settings (fill once) - //------------------------------------------------------------------ - - /// - /// Display size, in pixels. For clamping windows positions. - /// Default value: [unset] - /// - public Vector2 DisplaySize; - /// - /// Time elapsed since last frame, in seconds. - /// Default value: 1.0f / 10.0f. - /// - public float DeltaTime; - /// - /// Maximum time between saving positions/sizes to .ini file, in seconds. - /// Default value: 5.0f. - /// - public float IniSavingRate; - /// - /// Path to .ini file. NULL to disable .ini saving. - /// Default value: "imgui.ini" - /// - public IntPtr IniFilename; - /// - /// Path to .log file (default parameter to ImGui::LogToFile when no file is specified). - /// Default value: "imgui_log.txt" - /// - public IntPtr LogFilename; - /// - /// Time for a double-click, in seconds. - /// Default value: 0.30f. - /// - public float MouseDoubleClickTime; - /// - /// Distance threshold to stay in to validate a double-click, in pixels. - /// Default Value: 6.0f. - /// - public float MouseDoubleClickMaxDist; - /// - /// Distance threshold before considering we are dragging. - /// Default Value: 6.0f. - /// - public float MouseDragThreshold; - - /// - /// Map of indices into the KeysDown[512] entries array. - /// Default values: [unset] - /// - public fixed int KeyMap[(int)GuiKey.Count]; - /// - /// When holding a key/button, time before it starts repeating, in seconds. (for actions where 'repeat' is active). - /// Default value: 0.250f. - /// - public float KeyRepeatDelay; - /// - /// When holding a key/button, rate at which it repeats, in seconds. - /// Default value: 0.020f. - /// - public float KeyRepeatRate; - /// - /// Store your own data for retrieval by callbacks. - /// Default value; IntPtr.Zero. - /// - public IntPtr UserData; - - /// - /// Load and assemble one or more fonts into a single tightly packed texture. Output to Fonts array. - /// Default value: [auto] - /// - public FontAtlas* FontAtlas; - /// - /// Global scale all fonts. - /// Default value: 1.0f. - /// - public float FontGlobalScale; - /// - /// Allow user scaling text of individual window with CTRL+Wheel. - /// Default value: false. - /// - public byte FontAllowUserScaling; - /// - /// 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). - /// - public Vector2 DisplayFramebufferScale; - /// - /// 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) - /// - public Vector2 DisplayVisibleMin; - /// - /// If the values are the same, we defaults to Min=0.0f) and Max=DisplaySize. - /// Default value: (0.0f, 0.0f). - /// - public Vector2 DisplayVisibleMax; // (0.0f,0.0f) // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize - - //------------------------------------------------------------------ - // User Functions - //------------------------------------------------------------------ - - /// - /// Rendering function, will be called in Render(). - /// Alternatively you can keep this to NULL and call GetDrawData() after Render() to get the same pointer. - /// - public IntPtr RenderDrawListsFn; - - /// - /// 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) - /// - public IntPtr GetClipboardTextFn; - /// - /// 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) - /// - public IntPtr SetClipboardTextFn; - - /// - /// Optional: override memory allocations. MemFreeFn() may be called with a NULL pointer. - /// (default to posix malloc/free) - /// - public IntPtr MemAllocFn; - /// - /// Optional: override memory allocations. MemFreeFn() may be called with a NULL pointer. - /// (default to posix malloc/free) - /// - public IntPtr MemFreeFn; - - /// - /// 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) - /// - public IntPtr ImeSetInputScreenPosFn; - /// - /// (Windows) Set this to your HWND to get automatic IME cursor positioning. - /// - public IntPtr ImeWindowHandle; - - //------------------------------------------------------------------ - // Input - Fill before calling NewFrame() - //------------------------------------------------------------------ - - /// - /// Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.). - /// - public Vector2 MousePos; - /// - /// 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. - /// - public fixed byte MouseDown[5]; - /// - /// Mouse wheel: 1 unit scrolls about 5 lines text. - /// - public float MouseWheel; - /// - /// Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). - /// - public byte MouseDrawCursor; - /// - /// Keyboard modifier pressed: Control. - /// - public byte KeyCtrl; - /// - /// Keyboard modifier pressed: Shift - /// - public byte KeyShift; - /// - /// Keyboard modifier pressed: Alt - /// - public byte KeyAlt; - /// - /// Keyboard keys that are pressed (in whatever storage order you naturally have access to keyboard data) - /// - public fixed byte KeysDown[512]; - /// - /// List of characters input (translated by user from keypress+keyboard state). - /// Fill using AddInputCharacter() helper. - /// - 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 - //------------------------------------------------------------------ - - /// - /// Mouse is hovering a window or widget is active (= ImGui will use your mouse input). - /// - public byte WantCaptureMouse; - /// - /// Widget is active (= ImGui will use your keyboard input). - /// - public byte WantCaptureKeyboard; - /// - /// Some text input widget is active, which will read input characters from the InputCharacters array. - /// - public byte WantTextInput; - /// - /// Framerate estimation, in frame per second. Rolling average estimation based on IO.DeltaTime over 120 frames. - /// - public float Framerate; - /// - /// Number of active memory allocations. - /// - public int MetricsAllocs; - /// - /// Vertices output during last call to Render(). - /// - public int MetricsRenderVertices; - /// - /// Indices output during last call to Render() = number of triangles * 3 - /// - public int MetricsRenderIndices; - /// - /// Number of visible windows (exclude child windows) - /// - public int MetricsActiveWindows; - - //------------------------------------------------------------------ - // [Internal] ImGui will maintain those fields for you - //------------------------------------------------------------------ - - /// - /// Previous mouse position - /// - public Vector2 MousePosPrev; - /// - /// Mouse delta. Note that this is zero if either current or previous position are negative to allow mouse enabling/disabling. - /// - public Vector2 MouseDelta; - /// - /// Mouse button went from !Down to Down - /// - public fixed byte MouseClicked[5]; - /// - /// Position at time of clicking - /// - public Vector2 MouseClickedPos0; - /// - /// Position at time of clicking - /// - public Vector2 MouseClickedPos1; - /// - /// Position at time of clicking - /// - public Vector2 MouseClickedPos2; - /// - /// Position at time of clicking - /// - public Vector2 MouseClickedPos3; - /// - /// Position at time of clicking - /// - public Vector2 MouseClickedPos4; - /// - /// Time of last click (used to figure out double-click) - /// - public fixed float MouseClickedTime[5]; - /// - /// Has mouse button been double-clicked? - /// - public fixed byte MouseDoubleClicked[5]; - /// - /// Mouse button went from Down to !Down - /// - public fixed byte MouseReleased[5]; - /// - /// Track if button was clicked inside a window. - /// We don't request mouse capture from the application if click started outside ImGui bounds. - /// - public fixed byte MouseDownOwned[5]; - /// - /// Duration the mouse button has been down (0.0f == just clicked). - /// - public fixed float MouseDownDuration[5]; - /// - /// Previous time the mouse button has been down - /// - public fixed float MouseDownDurationPrev[5]; - /// - /// Squared maximum distance of how much mouse has traveled from the click point - /// - public fixed float MouseDragMaxDistanceSqr[5]; - /// - /// Duration the keyboard key has been down (0.0f == just pressed) - /// - public fixed float KeysDownDuration[512]; - /// - /// Previous duration the key has been down - /// - public fixed float KeysDownDurationPrev[512]; + 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; + } } } diff --git a/src/ImGui.NET/ImGui.NET.Net46.csproj b/src/ImGui.NET/ImGui.NET.Net46.csproj index f8942cf..89ab06f 100644 --- a/src/ImGui.NET/ImGui.NET.Net46.csproj +++ b/src/ImGui.NET/ImGui.NET.Net46.csproj @@ -16,6 +16,7 @@ + diff --git a/src/ImGui.NET/ImGui.NET.csproj b/src/ImGui.NET/ImGui.NET.csproj index a4b413d..c4bf926 100644 --- a/src/ImGui.NET/ImGui.NET.csproj +++ b/src/ImGui.NET/ImGui.NET.csproj @@ -13,6 +13,7 @@ + @@ -87,5 +88,8 @@ + + + \ No newline at end of file diff --git a/src/ImGui.NET/ImGui.cs b/src/ImGui.NET/ImGui.cs index 925bcdd..7a0e490 100644 --- a/src/ImGui.NET/ImGui.cs +++ b/src/ImGui.NET/ImGui.cs @@ -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); + } + /// /// 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; } + } + } } diff --git a/src/ImGui.NET/ImGuiNative.cs b/src/ImGui.NET/ImGuiNative.cs index c4249e1..09871bc 100644 --- a/src/ImGui.NET/ImGuiNative.cs +++ b/src/ImGui.NET/ImGuiNative.cs @@ -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(); diff --git a/src/ImGui.NET/NativeIO.cs b/src/ImGui.NET/NativeIO.cs new file mode 100644 index 0000000..f13627e --- /dev/null +++ b/src/ImGui.NET/NativeIO.cs @@ -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) + //------------------------------------------------------------------ + + /// + /// Display size, in pixels. For clamping windows positions. + /// Default value: [unset] + /// + public Vector2 DisplaySize; + /// + /// Time elapsed since last frame, in seconds. + /// Default value: 1.0f / 10.0f. + /// + public float DeltaTime; + /// + /// Maximum time between saving positions/sizes to .ini file, in seconds. + /// Default value: 5.0f. + /// + public float IniSavingRate; + /// + /// Path to .ini file. NULL to disable .ini saving. + /// Default value: "imgui.ini" + /// + public IntPtr IniFilename; + /// + /// Path to .log file (default parameter to ImGui::LogToFile when no file is specified). + /// Default value: "imgui_log.txt" + /// + public IntPtr LogFilename; + /// + /// Time for a double-click, in seconds. + /// Default value: 0.30f. + /// + public float MouseDoubleClickTime; + /// + /// Distance threshold to stay in to validate a double-click, in pixels. + /// Default Value: 6.0f. + /// + public float MouseDoubleClickMaxDist; + /// + /// Distance threshold before considering we are dragging. + /// Default Value: 6.0f. + /// + public float MouseDragThreshold; + + /// + /// Map of indices into the KeysDown[512] entries array. + /// Default values: [unset] + /// + public fixed int KeyMap[(int)GuiKey.Count]; + /// + /// When holding a key/button, time before it starts repeating, in seconds. (for actions where 'repeat' is active). + /// Default value: 0.250f. + /// + public float KeyRepeatDelay; + /// + /// When holding a key/button, rate at which it repeats, in seconds. + /// Default value: 0.020f. + /// + public float KeyRepeatRate; + /// + /// Store your own data for retrieval by callbacks. + /// Default value; IntPtr.Zero. + /// + public IntPtr UserData; + + /// + /// Load and assemble one or more fonts into a single tightly packed texture. Output to Fonts array. + /// Default value: [auto] + /// + public FontAtlas* FontAtlas; + /// + /// Global scale all fonts. + /// Default value: 1.0f. + /// + public float FontGlobalScale; + /// + /// Allow user scaling text of individual window with CTRL+Wheel. + /// Default value: false. + /// + public byte FontAllowUserScaling; + /// + /// 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). + /// + public Vector2 DisplayFramebufferScale; + /// + /// 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) + /// + public Vector2 DisplayVisibleMin; + /// + /// If the values are the same, we defaults to Min=0.0f) and Max=DisplaySize. + /// Default value: (0.0f, 0.0f). + /// + public Vector2 DisplayVisibleMax; // (0.0f,0.0f) // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize + + //------------------------------------------------------------------ + // User Functions + //------------------------------------------------------------------ + + /// + /// Rendering function, will be called in Render(). + /// Alternatively you can keep this to NULL and call GetDrawData() after Render() to get the same pointer. + /// + public IntPtr RenderDrawListsFn; + + /// + /// 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) + /// + public IntPtr GetClipboardTextFn; + /// + /// 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) + /// + public IntPtr SetClipboardTextFn; + + /// + /// Optional: override memory allocations. MemFreeFn() may be called with a NULL pointer. + /// (default to posix malloc/free) + /// + public IntPtr MemAllocFn; + /// + /// Optional: override memory allocations. MemFreeFn() may be called with a NULL pointer. + /// (default to posix malloc/free) + /// + public IntPtr MemFreeFn; + + /// + /// 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) + /// + public IntPtr ImeSetInputScreenPosFn; + /// + /// (Windows) Set this to your HWND to get automatic IME cursor positioning. + /// + public IntPtr ImeWindowHandle; + + //------------------------------------------------------------------ + // Input - Fill before calling NewFrame() + //------------------------------------------------------------------ + + /// + /// Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.). + /// + public Vector2 MousePos; + /// + /// 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. + /// + public fixed byte MouseDown[5]; + /// + /// Mouse wheel: 1 unit scrolls about 5 lines text. + /// + public float MouseWheel; + /// + /// Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). + /// + public byte MouseDrawCursor; + /// + /// Keyboard modifier pressed: Control. + /// + public byte KeyCtrl; + /// + /// Keyboard modifier pressed: Shift + /// + public byte KeyShift; + /// + /// Keyboard modifier pressed: Alt + /// + public byte KeyAlt; + /// + /// Keyboard keys that are pressed (in whatever storage order you naturally have access to keyboard data) + /// + public fixed byte KeysDown[512]; + /// + /// List of characters input (translated by user from keypress+keyboard state). + /// Fill using AddInputCharacter() helper. + /// + 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 + //------------------------------------------------------------------ + + /// + /// Mouse is hovering a window or widget is active (= ImGui will use your mouse input). + /// + public byte WantCaptureMouse; + /// + /// Widget is active (= ImGui will use your keyboard input). + /// + public byte WantCaptureKeyboard; + /// + /// Some text input widget is active, which will read input characters from the InputCharacters array. + /// + public byte WantTextInput; + /// + /// Framerate estimation, in frame per second. Rolling average estimation based on IO.DeltaTime over 120 frames. + /// + public float Framerate; + /// + /// Number of active memory allocations. + /// + public int MetricsAllocs; + /// + /// Vertices output during last call to Render(). + /// + public int MetricsRenderVertices; + /// + /// Indices output during last call to Render() = number of triangles * 3 + /// + public int MetricsRenderIndices; + /// + /// Number of visible windows (exclude child windows) + /// + public int MetricsActiveWindows; + + //------------------------------------------------------------------ + // [Internal] ImGui will maintain those fields for you + //------------------------------------------------------------------ + + /// + /// Previous mouse position + /// + public Vector2 MousePosPrev; + /// + /// Mouse delta. Note that this is zero if either current or previous position are negative to allow mouse enabling/disabling. + /// + public Vector2 MouseDelta; + /// + /// Mouse button went from !Down to Down + /// + public fixed byte MouseClicked[5]; + /// + /// Position at time of clicking + /// + public Vector2 MouseClickedPos0; + /// + /// Position at time of clicking + /// + public Vector2 MouseClickedPos1; + /// + /// Position at time of clicking + /// + public Vector2 MouseClickedPos2; + /// + /// Position at time of clicking + /// + public Vector2 MouseClickedPos3; + /// + /// Position at time of clicking + /// + public Vector2 MouseClickedPos4; + /// + /// Time of last click (used to figure out double-click) + /// + public fixed float MouseClickedTime[5]; + /// + /// Has mouse button been double-clicked? + /// + public fixed byte MouseDoubleClicked[5]; + /// + /// Mouse button went from Down to !Down + /// + public fixed byte MouseReleased[5]; + /// + /// Track if button was clicked inside a window. + /// We don't request mouse capture from the application if click started outside ImGui bounds. + /// + public fixed byte MouseDownOwned[5]; + /// + /// Duration the mouse button has been down (0.0f == just clicked). + /// + public fixed float MouseDownDuration[5]; + /// + /// Previous time the mouse button has been down + /// + public fixed float MouseDownDurationPrev[5]; + /// + /// Squared maximum distance of how much mouse has traveled from the click point + /// + public fixed float MouseDragMaxDistanceSqr[5]; + /// + /// Duration the keyboard key has been down (0.0f == just pressed) + /// + public fixed float KeysDownDuration[512]; + /// + /// Previous duration the key has been down + /// + public fixed float KeysDownDurationPrev[512]; + } +} \ No newline at end of file