public static DragInt ( string label, int &value, float speed, int minValue, int maxValue, string displayText ) : bool | ||
label | string | |
value | int | |
speed | float | |
minValue | int | |
maxValue | int | |
displayText | string | |
return | bool |
private static unsafe void SubmitUI() { // Demo code adapted from the official Dear ImGui demo program: // https://github.com/ocornut/imgui/blob/master/examples/example_win32_directx11/main.cpp#L172 // 1. Show a simple window. // Tip: if we don't call ImGui.BeginWindow()/ImGui.EndWindow() the widgets automatically appears in a window called "Debug". { ImGui.Text("Hello, world!"); // Display some text (you can use a format string too) ImGui.SliderFloat("float", ref _f, 0, 1, _f.ToString("0.000"), 1); // Edit 1 float using a slider from 0.0f to 1.0f //ImGui.ColorEdit3("clear color", ref _clearColor); // Edit 3 floats representing a color ImGui.Text($"Mouse position: {ImGui.GetMousePos()}"); ImGui.Checkbox("Demo Window", ref _showDemoWindow); // Edit bools storing our windows open/close state ImGui.Checkbox("Another Window", ref _showAnotherWindow); ImGui.Checkbox("Memory Editor", ref _showMemoryEditor); if (ImGui.Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) { _counter++; } ImGui.SameLine(0, -1); ImGui.Text($"counter = {_counter}"); ImGui.DragInt("Draggable Int", ref _dragInt); float framerate = ImGui.GetIO().Framerate; ImGui.Text($"Application average {1000.0f / framerate:0.##} ms/frame ({framerate:0.#} FPS)"); } // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. if (_showAnotherWindow) { ImGui.Begin("Another Window", ref _showAnotherWindow); ImGui.Text("Hello from another window!"); if (ImGui.Button("Close Me")) { _showAnotherWindow = false; } ImGui.End(); } // 3. Show the ImGui demo window. Most of the sample code is in ImGui.ShowDemoWindow(). Read its code to learn more about Dear ImGui! if (_showDemoWindow) { // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. // Here we just want to make the demo initial state a bit more friendly! ImGui.SetNextWindowPos(new Vector2(650, 20), ImGuiCond.FirstUseEver); ImGui.ShowDemoWindow(ref _showDemoWindow); } ImGuiIOPtr io = ImGui.GetIO(); SetThing(out io.DeltaTime, 2f); if (_showMemoryEditor) { _memoryEditor.Draw("Memory Editor", _memoryEditorData, _memoryEditorData.Length); } }
public unsafe void Draw(string title, byte[] mem_data, int mem_size, int base_display_addr = 0) { if (!ImGui.BeginWindow(title)) { ImGui.EndWindow(); return; } float line_height = ImGuiNative.igGetTextLineHeight(); int line_total_count = (mem_size + Rows - 1) / Rows; ImGuiNative.igSetNextWindowContentSize(new Vector2(0.0f, line_total_count * line_height)); ImGui.BeginChild("##scrolling", new Vector2(0, -ImGuiNative.igGetFrameHeightWithSpacing()), false, 0); ImGui.PushStyleVar(StyleVar.FramePadding, new Vector2(0, 0)); ImGui.PushStyleVar(StyleVar.ItemSpacing, new Vector2(0, 0)); int addr_digits_count = 0; for (int n = base_display_addr + mem_size - 1; n > 0; n >>= 4) { addr_digits_count++; } float glyph_width = ImGui.GetTextSize("F").X; float cell_width = glyph_width * 3; // "FF " we include trailing space in the width to easily catch clicks everywhere var clipper = new ImGuiListClipper(line_total_count, line_height); int visible_start_addr = clipper.DisplayStart * Rows; int visible_end_addr = clipper.DisplayEnd * Rows; bool data_next = false; if (!AllowEdits || DataEditingAddr >= mem_size) { DataEditingAddr = -1; } int data_editing_addr_backup = DataEditingAddr; if (DataEditingAddr != -1) { if (ImGui.IsKeyPressed(ImGui.GetKeyIndex(GuiKey.UpArrow)) && DataEditingAddr >= Rows) { DataEditingAddr -= Rows; DataEditingTakeFocus = true; } else if (ImGui.IsKeyPressed(ImGui.GetKeyIndex(GuiKey.DownArrow)) && DataEditingAddr < mem_size - Rows) { DataEditingAddr += Rows; DataEditingTakeFocus = true; } else if (ImGui.IsKeyPressed(ImGui.GetKeyIndex(GuiKey.LeftArrow)) && DataEditingAddr > 0) { DataEditingAddr -= 1; DataEditingTakeFocus = true; } else if (ImGui.IsKeyPressed(ImGui.GetKeyIndex(GuiKey.RightArrow)) && DataEditingAddr < mem_size - 1) { DataEditingAddr += 1; DataEditingTakeFocus = true; } } if ((DataEditingAddr / Rows) != (data_editing_addr_backup / Rows)) { // Track cursor movements float scroll_offset = ((DataEditingAddr / Rows) - (data_editing_addr_backup / Rows)) * line_height; bool scroll_desired = (scroll_offset < 0.0f && DataEditingAddr < visible_start_addr + Rows * 2) || (scroll_offset > 0.0f && DataEditingAddr > visible_end_addr - Rows * 2); if (scroll_desired) { ImGuiNative.igSetScrollY(ImGuiNative.igGetScrollY() + scroll_offset); } } for (int line_i = clipper.DisplayStart; line_i < clipper.DisplayEnd; line_i++) // display only visible items { int addr = line_i * Rows; ImGui.Text(FixedHex(base_display_addr + addr, addr_digits_count) + ": "); ImGui.SameLine(); // Draw Hexadecimal float line_start_x = ImGuiNative.igGetCursorPosX(); for (int n = 0; n < Rows && addr < mem_size; n++, addr++) { ImGui.SameLine(line_start_x + cell_width * n); if (DataEditingAddr == addr) { // Display text input on current byte ImGui.PushID(addr); // FIXME: We should have a way to retrieve the text edit cursor position more easily in the API, this is rather tedious. TextEditCallback callback = (data) => { int *p_cursor_pos = (int *)data->UserData; if (!data->HasSelection()) { *p_cursor_pos = data->CursorPos; } return(0); }; int cursor_pos = -1; bool data_write = false; if (DataEditingTakeFocus) { ImGui.SetKeyboardFocusHere(); ReplaceChars(DataInput, FixedHex(mem_data[addr], 2)); ReplaceChars(AddrInput, FixedHex(base_display_addr + addr, addr_digits_count)); } ImGui.PushItemWidth(ImGui.GetTextSize("FF").X); var flags = InputTextFlags.CharsHexadecimal | InputTextFlags.EnterReturnsTrue | InputTextFlags.AutoSelectAll | InputTextFlags.NoHorizontalScroll | InputTextFlags.AlwaysInsertMode | InputTextFlags.CallbackAlways; if (ImGui.InputText("##data", DataInput, 32, flags, callback, new IntPtr(&cursor_pos))) { data_write = data_next = true; } else if (!DataEditingTakeFocus && !ImGui.IsLastItemActive()) { DataEditingAddr = -1; } DataEditingTakeFocus = false; ImGui.PopItemWidth(); if (cursor_pos >= 2) { data_write = data_next = true; } if (data_write) { int data; if (TryHexParse(DataInput, out data)) { mem_data[addr] = (byte)data; } } ImGui.PopID(); } else { ImGui.Text(FixedHex(mem_data[addr], 2)); if (AllowEdits && ImGui.IsItemHovered(HoveredFlags.Default) && ImGui.IsMouseClicked(0)) { DataEditingTakeFocus = true; DataEditingAddr = addr; } } } ImGui.SameLine(line_start_x + cell_width * Rows + glyph_width * 2); //separator line drawing replaced by printing a pipe char // Draw ASCII values addr = line_i * Rows; var asciiVal = new System.Text.StringBuilder(2 + Rows); asciiVal.Append("| "); for (int n = 0; n < Rows && addr < mem_size; n++, addr++) { int c = mem_data[addr]; asciiVal.Append((c >= 32 && c < 128) ? Convert.ToChar(c) : '.'); } ImGui.TextUnformatted(asciiVal.ToString()); //use unformatted, so string can contain the '%' character } //clipper.End(); //not implemented ImGui.PopStyleVar(2); ImGui.EndChild(); if (data_next && DataEditingAddr < mem_size) { DataEditingAddr = DataEditingAddr + 1; DataEditingTakeFocus = true; } ImGui.Separator(); ImGuiNative.igAlignTextToFramePadding(); ImGui.PushItemWidth(50); ImGuiNative.igPushAllowKeyboardFocus(false); int rows_backup = Rows; if (ImGui.DragInt("##rows", ref Rows, 0.2f, 4, 32, "%.0f rows")) { if (Rows <= 0) { Rows = 4; } Vector2 new_window_size = ImGui.GetWindowSize(); new_window_size.X += (Rows - rows_backup) * (cell_width + glyph_width); ImGui.SetWindowSize(new_window_size); } ImGuiNative.igPopAllowKeyboardFocus(); ImGui.PopItemWidth(); ImGui.SameLine(); ImGui.Text(string.Format(" Range {0}..{1} ", FixedHex(base_display_addr, addr_digits_count), FixedHex(base_display_addr + mem_size - 1, addr_digits_count))); ImGui.SameLine(); ImGui.PushItemWidth(70); if (ImGui.InputText("##addr", AddrInput, 32, InputTextFlags.CharsHexadecimal | InputTextFlags.EnterReturnsTrue, null)) { int goto_addr; if (TryHexParse(AddrInput, out goto_addr)) { goto_addr -= base_display_addr; if (goto_addr >= 0 && goto_addr < mem_size) { ImGui.BeginChild("##scrolling"); ImGuiNative.igSetScrollFromPosY(ImGui.GetCursorStartPos().Y + (goto_addr / Rows) * ImGuiNative.igGetTextLineHeight()); ImGui.EndChild(); DataEditingAddr = goto_addr; DataEditingTakeFocus = true; } } } ImGui.PopItemWidth(); ImGui.EndWindow(); }
private static unsafe void SubmitUI() { // Demo code adapted from the official Dear ImGui demo program: // https://github.com/ocornut/imgui/blob/master/examples/example_win32_directx11/main.cpp#L172 // 1. Show a simple window. // Tip: if we don't call ImGui.BeginWindow()/ImGui.EndWindow() the widgets automatically appears in a window called "Debug". { ImGui.Text("Hello, world!"); // Display some text (you can use a format string too) ImGui.SliderFloat("float", ref _f, 0, 1, _f.ToString("0.000")); // Edit 1 float using a slider from 0.0f to 1.0f //ImGui.ColorEdit3("clear color", ref _clearColor); // Edit 3 floats representing a color ImGui.Text($"Mouse position: {ImGui.GetMousePos()}"); ImGui.Checkbox("Demo Window", ref _showDemoWindow); // Edit bools storing our windows open/close state ImGui.Checkbox("Another Window", ref _showAnotherWindow); ImGui.Checkbox("Memory Editor", ref _showMemoryEditor); if (ImGui.Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) { _counter++; } ImGui.SameLine(0, -1); ImGui.Text($"counter = {_counter}"); ImGui.DragInt("Draggable Int", ref _dragInt); float framerate = ImGui.GetIO().Framerate; ImGui.Text($"Application average {1000.0f / framerate:0.##} ms/frame ({framerate:0.#} FPS)"); } // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. if (_showAnotherWindow) { ImGui.Begin("Another Window", ref _showAnotherWindow); ImGui.Text("Hello from another window!"); if (ImGui.Button("Close Me")) { _showAnotherWindow = false; } ImGui.End(); } // 3. Show the ImGui demo window. Most of the sample code is in ImGui.ShowDemoWindow(). Read its code to learn more about Dear ImGui! if (_showDemoWindow) { // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. // Here we just want to make the demo initial state a bit more friendly! ImGui.SetNextWindowPos(new Vector2(650, 20), ImGuiCond.FirstUseEver); ImGui.ShowDemoWindow(ref _showDemoWindow); } if (ImGui.TreeNode("Tabs")) { if (ImGui.TreeNode("Basic")) { ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags.None; if (ImGui.BeginTabBar("MyTabBar", tab_bar_flags)) { if (ImGui.BeginTabItem("Avocado")) { ImGui.Text("This is the Avocado tab!\nblah blah blah blah blah"); ImGui.EndTabItem(); } if (ImGui.BeginTabItem("Broccoli")) { ImGui.Text("This is the Broccoli tab!\nblah blah blah blah blah"); ImGui.EndTabItem(); } if (ImGui.BeginTabItem("Cucumber")) { ImGui.Text("This is the Cucumber tab!\nblah blah blah blah blah"); ImGui.EndTabItem(); } ImGui.EndTabBar(); } ImGui.Separator(); ImGui.TreePop(); } if (ImGui.TreeNode("Advanced & Close Button")) { // Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0). ImGui.CheckboxFlags("ImGuiTabBarFlags_Reorderable", ref s_tab_bar_flags, (uint)ImGuiTabBarFlags.Reorderable); ImGui.CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", ref s_tab_bar_flags, (uint)ImGuiTabBarFlags.AutoSelectNewTabs); ImGui.CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", ref s_tab_bar_flags, (uint)ImGuiTabBarFlags.NoCloseWithMiddleMouseButton); if ((s_tab_bar_flags & (uint)ImGuiTabBarFlags.FittingPolicyMask) == 0) { s_tab_bar_flags |= (uint)ImGuiTabBarFlags.FittingPolicyDefault; } if (ImGui.CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", ref s_tab_bar_flags, (uint)ImGuiTabBarFlags.FittingPolicyResizeDown)) { s_tab_bar_flags &= ~((uint)ImGuiTabBarFlags.FittingPolicyMask ^ (uint)ImGuiTabBarFlags.FittingPolicyResizeDown); } if (ImGui.CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", ref s_tab_bar_flags, (uint)ImGuiTabBarFlags.FittingPolicyScroll)) { s_tab_bar_flags &= ~((uint)ImGuiTabBarFlags.FittingPolicyMask ^ (uint)ImGuiTabBarFlags.FittingPolicyScroll); } // Tab Bar string[] names = { "Artichoke", "Beetroot", "Celery", "Daikon" }; for (int n = 0; n < s_opened.Length; n++) { if (n > 0) { ImGui.SameLine(); } ImGui.Checkbox(names[n], ref s_opened[n]); } // Passing a bool* to BeginTabItem() is similar to passing one to Begin(): the underlying bool will be set to false when the tab is closed. if (ImGui.BeginTabBar("MyTabBar", (ImGuiTabBarFlags)s_tab_bar_flags)) { for (int n = 0; n < s_opened.Length; n++) { if (s_opened[n] && ImGui.BeginTabItem(names[n], ref s_opened[n])) { ImGui.Text($"This is the {names[n]} tab!"); if ((n & 1) != 0) { ImGui.Text("I am an odd tab."); } ImGui.EndTabItem(); } } ImGui.EndTabBar(); } ImGui.Separator(); ImGui.TreePop(); } ImGui.TreePop(); } ImGuiIOPtr io = ImGui.GetIO(); SetThing(out io.DeltaTime, 2f); if (_showMemoryEditor) { _memoryEditor.Draw("Memory Editor", _memoryEditorData, _memoryEditorData.Length); } }