From b06e8ab08297d5cb8bff1037681436199d4e54fe Mon Sep 17 00:00:00 2001 From: Eric Mellino Date: Fri, 16 Feb 2018 00:22:28 -0800 Subject: [PATCH] Wrap several more native structures to facilitate docking. --- NativeDrawContext.cs | 55 ++++++++ NativeSimpleColumns.cs | 10 ++ src/ImGui.NET.SampleProgram/SampleWindow.cs | 4 +- src/ImGui.NET/ImGui.NET.csproj | 7 +- src/ImGui.NET/ImGuiNative.cs | 4 +- src/ImGui.NET/ImRect.cs | 26 ++++ src/ImGui.NET/NativeContext.cs | 140 ++++++++++++++++++++ src/ImGui.NET/NativeTestEditState.cs | 72 ++++++++++ src/ImGui.NET/NativeWindow.cs | 73 ++++++++++ 9 files changed, 386 insertions(+), 5 deletions(-) create mode 100644 NativeDrawContext.cs create mode 100644 NativeSimpleColumns.cs create mode 100644 src/ImGui.NET/ImRect.cs create mode 100644 src/ImGui.NET/NativeContext.cs create mode 100644 src/ImGui.NET/NativeTestEditState.cs create mode 100644 src/ImGui.NET/NativeWindow.cs diff --git a/NativeDrawContext.cs b/NativeDrawContext.cs new file mode 100644 index 0000000..477524b --- /dev/null +++ b/NativeDrawContext.cs @@ -0,0 +1,55 @@ +using System.Numerics; + +namespace ImGuiNET +{ + // Transient per-window data, reset at the beginning of the frame + public unsafe struct NativeDrawContext + { + public Vector2 CursorPos; + public Vector2 CursorPosPrevLine; + public Vector2 CursorStartPos; + public Vector2 CursorMaxPos; // Implicitly calculate the size of our contents, always extending. Saved into window->SizeContents at the end of the frame + public float CurrentLineHeight; + public float CurrentLineTextBaseOffset; + public float PrevLineHeight; + public float PrevLineTextBaseOffset; + public float LogLinePosY; + public int TreeDepth; + public uint LastItemId; + public ImRect LastItemRect; + public byte LastItemHoveredAndUsable; // Item rectangle is hovered, and its window is currently interactable with (not blocked by a popup preventing access to the window) + public byte LastItemHoveredRect; // Item rectangle is hovered, but its window may or not be currently interactable with (might be blocked by a popup preventing access to the window) + public byte MenuBarAppending; + public float MenuBarOffsetX; + public ImVector ChildWindows; + public Storage StateStorage; + public int LayoutType; + + // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. + public float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window + public float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f] + public byte AllowKeyboardFocus; // == AllowKeyboardFocusStack.back() [empty == true] + public byte ButtonRepeat; // == ButtonRepeatStack.back() [empty == false] + public ImVector ItemWidthStack; + public ImVector TextWrapPosStack; + public ImVector AllowKeyboardFocusStack; + public ImVector ButtonRepeatStack; + public ImVector GroupStack; + public ColorEditFlags ColorEditMode; + public fixed int StackSizesBackup[6]; // Store size of various stacks for asserting + + public float IndentX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) + public float GroupOffsetX; + public float ColumnsOffsetX; // Offset to the current column (if ColumnsCurrent > 0). + public int ColumnsCurrent; + public int ColumnsCount; + public float ColumnsMinX; + public float ColumnsMaxX; + public float ColumnsStartPosY; + public float ColumnsCellMinY; + public float ColumnsCellMaxY; + public byte ColumnsShowBorders; + public uint ColumnsSetId; + public ImVector ColumnsData; + } +} diff --git a/NativeSimpleColumns.cs b/NativeSimpleColumns.cs new file mode 100644 index 0000000..8690ad4 --- /dev/null +++ b/NativeSimpleColumns.cs @@ -0,0 +1,10 @@ +namespace ImGuiNET +{ + public unsafe struct NativeSimpleColumns + { + public int Count; + public float Spacing; + public float Width, NextWidth; + public fixed float Pos[8], NextWidths[8]; + }; +} diff --git a/src/ImGui.NET.SampleProgram/SampleWindow.cs b/src/ImGui.NET.SampleProgram/SampleWindow.cs index 6bd7217..c718cca 100644 --- a/src/ImGui.NET.SampleProgram/SampleWindow.cs +++ b/src/ImGui.NET.SampleProgram/SampleWindow.cs @@ -14,7 +14,7 @@ namespace ImGuiNET { public class SampleWindow { - private NativeWindow _nativeWindow; + private OpenTK.NativeWindow _nativeWindow; private GraphicsContext _graphicsContext; private int s_fontTexture; private int _pressCount; @@ -35,7 +35,7 @@ namespace ImGuiNET public unsafe SampleWindow() { int desiredWidth = 960, desiredHeight = 540; - _nativeWindow = new NativeWindow(desiredWidth, desiredHeight, "ImGui.NET", GameWindowFlags.Default, OpenTK.Graphics.GraphicsMode.Default, DisplayDevice.Default); + _nativeWindow = new OpenTK.NativeWindow(desiredWidth, desiredHeight, "ImGui.NET", GameWindowFlags.Default, OpenTK.Graphics.GraphicsMode.Default, DisplayDevice.Default); _scaleFactor = _nativeWindow.Width / desiredWidth; GraphicsContextFlags flags = GraphicsContextFlags.Default; diff --git a/src/ImGui.NET/ImGui.NET.csproj b/src/ImGui.NET/ImGui.NET.csproj index de533e5..6571fd7 100644 --- a/src/ImGui.NET/ImGui.NET.csproj +++ b/src/ImGui.NET/ImGui.NET.csproj @@ -1,7 +1,7 @@  A .NET wrapper for the dear ImGui library. - 0.4.1 + 0.4.2 Eric Mellino netstandard1.1 true @@ -14,7 +14,12 @@ https://github.com/mellinoe/imgui.net true $(OutputPath)\ImGui.NET.xml + ImGuiNET + + + + diff --git a/src/ImGui.NET/ImGuiNative.cs b/src/ImGui.NET/ImGuiNative.cs index 1a0b2fc..e94ac59 100644 --- a/src/ImGui.NET/ImGuiNative.cs +++ b/src/ImGui.NET/ImGuiNative.cs @@ -354,11 +354,11 @@ namespace ImGuiNET public delegate void ImGuiContextFreeFunction(IntPtr ptr); [DllImport(cimguiLib, CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr igCreateContext(ImGuiContextAllocationFunction malloc_fn, ImGuiContextFreeFunction free_fn); + public static extern NativeContext* igCreateContext(ImGuiContextAllocationFunction malloc_fn, ImGuiContextFreeFunction free_fn); [DllImport(cimguiLib, CallingConvention = CallingConvention.Cdecl)] public static extern void igDestroyContext(IntPtr ctx); [DllImport(cimguiLib, CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr igGetCurrentContext(); + public static extern NativeContext* igGetCurrentContext(); [DllImport(cimguiLib, CallingConvention = CallingConvention.Cdecl)] public static extern void igSetCurrentContext(IntPtr ctx); diff --git a/src/ImGui.NET/ImRect.cs b/src/ImGui.NET/ImRect.cs new file mode 100644 index 0000000..e6aa639 --- /dev/null +++ b/src/ImGui.NET/ImRect.cs @@ -0,0 +1,26 @@ +using System.Numerics; + +namespace ImGuiNET +{ + public struct ImRect + { + public Vector2 Min; + public Vector2 Max; + + public ImRect(Vector2 min, Vector2 max) + { + Min = min; + Max = max; + } + + public bool Contains(Vector2 p) + { + return p.X >= Min.X && p.Y >= Min.Y && p.X < Max.X && p.Y < Max.Y; + } + + public Vector2 GetSize() + { + return Max - Min; + } + } +} diff --git a/src/ImGui.NET/NativeContext.cs b/src/ImGui.NET/NativeContext.cs new file mode 100644 index 0000000..44e1db4 --- /dev/null +++ b/src/ImGui.NET/NativeContext.cs @@ -0,0 +1,140 @@ +using System; +using System.Numerics; + +namespace ImGuiNET +{ + public unsafe struct NativeContext + { + public byte Initialized; + public NativeIO IO; + public NativeStyle Style; + public NativeFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() + public float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window. + public float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height. + public NativeDrawListSharedData DrawListSharedData; + + public float Time; + public int FrameCount; + public int FrameCountEnded; + public int FrameCountRendered; + public ImVector Windows; + public ImVector WindowsSortBuffer; + public ImVector CurrentWindowStack; + public Storage WindowsById; + public int WindowsActiveCount; + public NativeWindow* CurrentWindow; // Being drawn into + public NativeWindow* NavWindow; // Nav/focused window for navigation + public NativeWindow* HoveredWindow; // Will catch mouse inputs + public NativeWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only) + public uint HoveredId; // Hovered widget + public byte HoveredIdAllowOverlap; + public uint HoveredIdPreviousFrame; + public float HoveredIdTimer; + public uint ActiveId; // Active widget + public uint ActiveIdPreviousFrame; + public float ActiveIdTimer; + public byte ActiveIdIsAlive; // Active widget has been seen this frame + public byte ActiveIdIsJustActivated; // Set at the time of activation for one frame + public byte ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always) + public Vector2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) + public NativeWindow* ActiveIdWindow; + public NativeWindow* MovingWindow; // Track the child window we clicked on to move a window. + public uint MovingWindowMoveId; // == MovingWindow->MoveId + public ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() + public ImVector StyleModifiers; // Stack for PushStyleVar()/PopStyleVar() + public ImVector FontStack; // Stack for PushFont()/PopFont() + public ImVector OpenPopupStack; // Which popups are open (persistent) + public ImVector CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame) + + // Storage for SetNexWindow** and SetNextTreeNode*** functions + public Vector2 SetNextWindowPosVal; + public Vector2 SetNextWindowPosPivot; + public Vector2 SetNextWindowSizeVal; + public Vector2 SetNextWindowContentSizeVal; + public byte SetNextWindowCollapsedVal; + public Condition SetNextWindowPosCond; + public Condition SetNextWindowSizeCond; + public Condition SetNextWindowContentSizeCond; + public Condition SetNextWindowCollapsedCond; + public ImRect SetNextWindowSizeConstraintRect; // Valid if 'SetNextWindowSizeConstraint' is true + public IntPtr SetNextWindowSizeConstraintCallback; + public void* SetNextWindowSizeConstraintCallbackUserData; + public byte SetNextWindowSizeConstraint; + public byte SetNextWindowFocus; + public byte SetNextTreeNodeOpenVal; + public Condition SetNextTreeNodeOpenCond; + + // Render + public DrawData RenderDrawData; // Main ImDrawData instance to pass render information to the user + public ImVector RenderDrawLists0; + public ImVector RenderDrawLists1; + public ImVector RenderDrawLists2; + public float ModalWindowDarkeningRatio; + public DrawList OverlayDrawList; // Optional software render of mouse cursors, if io.MouseDrawCursor is set + a few debug overlays + public int MouseCursor; + public fixed byte MouseCursorData[7 * (4 + 8 + 8 + 16 + 16)]; + + // Drag and Drop + public byte DragDropActive; + public int DragDropSourceFlags; + public int DragDropMouseButton; + public NativePayload DragDropPayload; + public ImRect DragDropTargetRect; + public uint DragDropTargetId; + public float DragDropAcceptIdCurrRectSurface; + public uint DragDropAcceptIdCurr; // Target item id (set at the time of accepting the payload) + public uint DragDropAcceptIdPrev; // Target item id from previous frame (we need to store this to allow for overlapping drag and drop targets) + public int DragDropAcceptFrameCount; // Last time a target expressed a desire to accept the source + public ImVector DragDropPayloadBufHeap; // We don't expose the ImVector<> directly + public fixed byte DragDropPayloadBufLocal[8]; + + // Widget state + public ImGuiTextEditState InputTextState; + public NativeFont InputTextPasswordFont; + public uint ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc. + public int ColorEditOptions; // Store user options for color edit widgets + public Vector4 ColorPickerRef; + public float DragCurrentValue; // Currently dragged value, always float, not rounded by end-user precision settings + public Vector2 DragLastMouseDelta; + public float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio + public float DragSpeedScaleSlow; + public float DragSpeedScaleFast; + public Vector2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? + public int TooltipOverrideCount; + public ImVector PrivateClipboard; // If no custom clipboard handler is defined + public Vector2 OsImePosRequest, OsImePosSet; // Cursor position request & last passed to the OS Input Method Editor + + // Settings + public float SettingsDirtyTimer; // Save .ini Settings on disk when time reaches zero + public ImVector SettingsWindows; // .ini settings for NativeWindow + public ImVector SettingsHandlers; // List of .ini settings handlers + + // Logging + public byte LogEnabled; + public void* LogFile; // If != NULL log to stdout/ file + public void* LogClipboard; // Else log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators. + public int LogStartDepth; + public int LogAutoExpandMaxDepth; + + // Misc + public fixed float FramerateSecPerFrame[120]; // calculate estimate of framerate for user + public int FramerateSecPerFrameIdx; + public float FramerateSecPerFrameAccum; + public int WantCaptureMouseNextFrame; // explicit capture via CaptureInputs() sets those flags + public int WantCaptureKeyboardNextFrame; + public int WantTextInputNextFrame; + public fixed byte TempBuffer[1024 * 3 + 1]; // temporary text buffer + } + + public unsafe struct NativeDrawListSharedData + { + public Vector2 TexUvWhitePixel; // UV of white pixel in the atlas + public NativeFont* Font; // Current/default font (optional, for simplified AddText overload) + public float FontSize; // Current/default font size (optional, for simplified AddText overload) + public float CurveTessellationTol; + public Vector4 ClipRectFullscreen; // Value for PushClipRectFullscreen() + + // Const data + public fixed float CircleVtx12[12 * 2]; + } +} diff --git a/src/ImGui.NET/NativeTestEditState.cs b/src/ImGui.NET/NativeTestEditState.cs new file mode 100644 index 0000000..996a9e4 --- /dev/null +++ b/src/ImGui.NET/NativeTestEditState.cs @@ -0,0 +1,72 @@ +namespace ImGuiNET +{ + public unsafe struct ImGuiTextEditState + { + public uint Id; // widget id owning the text state + public ImVector Text; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer. + public ImVector InitialText; // backup of end-user buffer at the time of focus (in UTF-8, unaltered) + public ImVector TempTextBuffer; + public int CurLenA, CurLenW; // we need to maintain our buffer length in both UTF-8 and wchar format. + public int BufSizeA; // end-user buffer size + public float ScrollX; + public STB_TexteditState StbState; + public float CursorAnim; + public byte CursorFollow; + public byte SelectedAllMouseLock; + } + + public unsafe struct STB_TexteditState + { + ///////////////////// + // + // public data + // + + public int cursor; + // position of the text cursor within the string + + public int select_start; // selection start point + public int select_end; + // selection start and end point in characters; if equal, no selection. + // note that start may be less than or greater than end (e.g. when + // dragging the mouse, start is where the initial click was, and you + // can drag in either direction) + + public byte insert_mode; + // each textfield keeps its own insert mode state. to keep an app-wide + // insert mode, copy this value in/out of the app state + + ///////////////////// + // + // private data + // + public byte cursor_at_end_of_line; // not implemented yet + public byte initialized; + public byte has_preferred_x; + public byte single_line; + public byte padding1, padding2, padding3; + public float preferred_x; // this determines where the cursor up/down tries to seek to along x + public StbUndoState undostate; + } + + public unsafe struct StbUndoState + { + const int STB_TEXTEDIT_UNDOSTATECOUNT = 99; + const int STB_TEXTEDIT_UNDOCHARCOUNT = 999; + + // private data + public fixed byte undo_rec[STB_TEXTEDIT_UNDOSTATECOUNT * (4 + 2 + 2)]; + public fixed int undo_char[STB_TEXTEDIT_UNDOCHARCOUNT]; + public short undo_point, redo_point; + public short undo_char_point, redo_char_point; + } + + public struct StbUndoRecord + { + // private data + public int where; + public short insert_length; + public short delete_length; + public short char_storage; + } +} diff --git a/src/ImGui.NET/NativeWindow.cs b/src/ImGui.NET/NativeWindow.cs new file mode 100644 index 0000000..e424abd --- /dev/null +++ b/src/ImGui.NET/NativeWindow.cs @@ -0,0 +1,73 @@ +using System.Numerics; + +namespace ImGuiNET +{ + public unsafe struct NativeWindow + { + public byte* Name; + public uint ID; // == ImHash(Name) + public WindowFlags Flags; // See enum ImGuiWindowFlags_ + public Vector2 PosFloat; + public Vector2 Pos; // Position rounded-up to nearest pixel + public Vector2 Size; // Current size (==SizeFull or collapsed title bar size) + public Vector2 SizeFull; // Size when non collapsed + public Vector2 SizeFullAtLastBegin; // Copy of SizeFull at the end of Begin. This is the reference value we'll use on the next frame to decide if we need scrollbars. + public Vector2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame. Include decoration, window title, border, menu, etc. + public Vector2 SizeContentsExplicit; // Size of contents explicitly set by the user via SetNextWindowContentSize() + public ImRect ContentsRegionRect; // Maximum visible content position in window coordinates. ~~ (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis + public Vector2 WindowPadding; // Window padding at the time of begin. + public float WindowRounding; // Window rounding at the time of begin. + public float WindowBorderSize; // Window border size at the time of begin. + public uint MoveId; // == window->GetID("#MOVE") + public Vector2 Scroll; + public Vector2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change) + public Vector2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered + public byte ScrollbarX, ScrollbarY; + public Vector2 ScrollbarSizes; + public byte Active; // Set to true on Begin() + public byte WasActive; + public byte WriteAccessed; // Set to true when any widget access the current window + public byte Collapsed; // Set when collapsing window to become only title-bar + public byte SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed) + public byte Appearing; // Set during the frame where the window is appearing (or re-appearing) + public byte CloseButton; // Set when the window has a close button (p_open != NULL) + public int BeginOrderWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0. + public int BeginOrderWithinContext; // Order within entire imgui context. This is mostly used for debugging submission order related issues. + public int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) + public uint PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) + public int AutoFitFramesX, AutoFitFramesY; + public byte AutoFitOnlyGrows; + public int AutoFitChildAxises; + public int AutoPosLastDirection; + public int HiddenFrames; + public Condition SetWindowPosAllowFlags; // store condition flags for next SetWindowPos() call. + public Condition SetWindowSizeAllowFlags; // store condition flags for next SetWindowSize() call. + public Condition SetWindowCollapsedAllowFlags; // store condition flags for next SetWindowCollapsed() call. + public Vector2 SetWindowPosVal; // store window position when using a non-zero Pivot (position set needs to be processed when we know the window size) + public Vector2 SetWindowPosPivot; // store window pivot for positioning. Vector2(0,0) when positioning from top-left corner; Vector2(0.5f,0.5f) for centering; Vector2(1,1) for bottom right. + + public NativeDrawContext DC; // Temporary per-window data, reset at the beginning of the frame + public ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack + public ImRect ClipRect; // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2. + public ImRect WindowRectClipped; // = WindowRect just after setup in Begin(). == window->Rect() for root window. + public ImRect InnerRect; + public int LastFrameActive; + public float ItemWidthDefault; + public NativeSimpleColumns MenuColumns; // Simplified columns storage for menu items + public Storage StateStorage; + public ImVector ColumnsStorage; + public float FontWindowScale; // Scale multiplier per-window + public NativeDrawList* DrawList; + public NativeWindow* ParentWindow; // If we are a child _or_ popup window, this is pointing to our parent. Otherwise NULL. + public NativeWindow* RootWindow; // Generally point to ourself. If we are a child window, this is pointing to the first non-child parent window. + public NativeWindow* RootNonPopupWindow; // Generally point to ourself. Used to display TitleBgActive color and for selecting which window to use for NavWindowing + + // Navigation / Focus + int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister() + int FocusIdxTabCounter; // (same, but only count widgets which you can Tab through) + int FocusIdxAllRequestCurrent; // Item being requested for focus + int FocusIdxTabRequestCurrent; // Tab-able item being requested for focus + int FocusIdxAllRequestNext; // Item being requested for focus, for next update (relies on layout to be stable between the frame pressing TAB and the next frame) + int FocusIdxTabRequestNext; // " + } +}