/// <summary>
        /// Sets per-frame data based on the associated window.
        /// This is called by Update(float).
        /// </summary>
        private void SetPerFrameImGuiData(float deltaSeconds)
        {
            ImGuiIOPtr io = ImGui.GetIO();

            io.DisplaySize = new Vector2(
                _windowWidth / _scaleFactor.X,
                _windowHeight / _scaleFactor.Y);
            io.DisplayFramebufferScale = _scaleFactor;
            io.DeltaTime = deltaSeconds;             // DeltaTime is in seconds.

            ImGuiPlatformIOPtr platformIo = ImGui.GetPlatformIO();

            platformIo.MainViewport.Pos  = new Vector2(_window.X, _window.Y);
            platformIo.MainViewport.Size = new Vector2(_window.Width, _window.Height);
        }
Esempio n. 2
0
        private static unsafe void SubmitBaseUI()
        {
            // 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.Begin("Transform Example");
            {
                ImGui.Checkbox("Calculate By Hand?", ref _transformUIData._byHand);
                ImGui.SliderFloat("Uniform Scale", ref _transformUIData._uniformScale, 0.001f, 1.0f, _transformUIData.UniformScale.ToString("0.00000"), 1);  // Edit 1 float using a slider from 0.0f to 1.0f
                ImGui.SliderFloat2("Translation (X, Y)", ref _transformUIData._translate, -1.0f, 1.0f);
                ImGui.SliderFloat("Rotation", ref _transformUIData._rotateZ, -360.0f, 360.0f, _transformUIData.RotateZ.ToString("0.0000"), 1);
            }
            ImGui.End();
            ImGuiIOPtr io = ImGui.GetIO();

            SetThing(out io.DeltaTime, 2f);
        }
Esempio n. 3
0
        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 m_floatValue, 0, 1, m_floatValue.ToString("0.000"), 1); // Edit 1 float using a slider from 0.0f to 1.0f
                ImGui.ColorEdit3("clear color", ref m_clearColor);                                     // Edit 3 floats representing a color
                ImGui.Text($"Mouse position: {ImGui.GetMousePos()}");
                float framerate = ImGui.GetIO().Framerate;
                ImGui.Text($"Application average {1000.0f / framerate:0.##} ms/frame ({framerate:0.#} FPS)");
            }

            ImGuiIOPtr io = ImGui.GetIO();

            SetThing(out io.DeltaTime, 2f);
        }
Esempio n. 4
0
        /// <summary>
        /// Recreates the device texture used to render text.
        /// </summary>
        public unsafe void RecreateFontDeviceTexture(GraphicsDevice gd)
        {
            ImGuiIOPtr io = ImGui.GetIO();
            //添加中文字体
            var songti = @"C:\Windows\Fonts\STSONG.TTF";

            io.Fonts.AddFontFromFileTTF(songti, 16f);

            //var font= io.FontAtlas.AddDefaultFont();
            // Build
            fonttex textureData = io.Fonts.GetTexDataAsRGBA32() GetTexDataAsRGBA32();

            // Store our identifier
            io.Fonts.SetTexID(_fontAtlasID);

            _fontTexture = gd.ResourceFactory.CreateTexture(TextureDescription.Texture2D(
                                                                (uint)textureData.Width,
                                                                (uint)textureData.Height,
                                                                1,
                                                                1,
                                                                PixelFormat.R8_G8_B8_A8_UNorm,
                                                                TextureUsage.Sampled));
            _fontTexture.Name = "ImGui.NET Font Texture";
            gd.UpdateTexture(
                _fontTexture,
                (IntPtr)textureData.Pixels,
                (uint)(textureData.BytesPerPixel * textureData.Width * textureData.Height),
                0,
                0,
                0,
                (uint)textureData.Width,
                (uint)textureData.Height,
                1,
                0,
                0);
            _fontTextureView = gd.ResourceFactory.CreateTextureView(_fontTexture);

            io.FontAtlas.ClearTexData();
        }
Esempio n. 5
0
        private static void UpdateJoystickDPadState(ImGuiIOPtr io)
        {
            var dpadXPos = Joystick.GetAxisPosition(JoystickId, _dPadInfo.xAxis);

            if (_dPadInfo.xInverted)
            {
                dpadXPos = -dpadXPos;
            }

            var dpadYPos = Joystick.GetAxisPosition(JoystickId, _dPadInfo.yAxis);

            if (_dPadInfo.yInverted)
            {
                dpadYPos = -dpadYPos;
            }

            io.NavInputs[(int)ImGuiNavInput.DpadLeft]  = dpadXPos < -_dPadInfo.threshold ? 1f : 0f;
            io.NavInputs[(int)ImGuiNavInput.DpadRight] = dpadXPos > _dPadInfo.threshold ? 1f : 0f;

            io.NavInputs[(int)ImGuiNavInput.DpadUp]   = dpadYPos < -_dPadInfo.threshold ? 1f : 0f;
            io.NavInputs[(int)ImGuiNavInput.DpadDown] = dpadYPos > _dPadInfo.threshold ? 1f : 0f;
        }
Esempio n. 6
0
        private static void SetKeyMappings()
        {
            ImGuiIOPtr io = ImGui.GetIO();

            io.KeyMap[(int)ImGuiKey.Tab]        = (int)Key.Tab;
            io.KeyMap[(int)ImGuiKey.LeftArrow]  = (int)Key.Left;
            io.KeyMap[(int)ImGuiKey.RightArrow] = (int)Key.Right;
            io.KeyMap[(int)ImGuiKey.UpArrow]    = (int)Key.Up;
            io.KeyMap[(int)ImGuiKey.DownArrow]  = (int)Key.Down;
            io.KeyMap[(int)ImGuiKey.PageUp]     = (int)Key.PageUp;
            io.KeyMap[(int)ImGuiKey.PageDown]   = (int)Key.PageDown;
            io.KeyMap[(int)ImGuiKey.Home]       = (int)Key.Home;
            io.KeyMap[(int)ImGuiKey.End]        = (int)Key.End;
            io.KeyMap[(int)ImGuiKey.Delete]     = (int)Key.Delete;
            io.KeyMap[(int)ImGuiKey.Backspace]  = (int)Key.BackSpace;
            io.KeyMap[(int)ImGuiKey.Enter]      = (int)Key.Enter;
            io.KeyMap[(int)ImGuiKey.Escape]     = (int)Key.Escape;
            io.KeyMap[(int)ImGuiKey.A]          = (int)Key.A;
            io.KeyMap[(int)ImGuiKey.C]          = (int)Key.C;
            io.KeyMap[(int)ImGuiKey.V]          = (int)Key.V;
            io.KeyMap[(int)ImGuiKey.X]          = (int)Key.X;
            io.KeyMap[(int)ImGuiKey.Y]          = (int)Key.Y;
            io.KeyMap[(int)ImGuiKey.Z]          = (int)Key.Z;
        }
Esempio n. 7
0
        private static void UpdateJoystickLStickState(ImGuiIOPtr io)
        {
            var lStickXPos = Joystick.GetAxisPosition(JoystickId, _lStickInfo.xAxis);

            if (_lStickInfo.xInverted)
            {
                lStickXPos = -lStickXPos;
            }

            var lStickYPos = Joystick.GetAxisPosition(JoystickId, _lStickInfo.yAxis);

            if (_lStickInfo.yInverted)
            {
                lStickYPos = -lStickYPos;
            }

            if (lStickXPos < -_lStickInfo.threshold)
            {
                io.NavInputs[(int)ImGuiNavInput.LStickLeft] = MathF.Abs(lStickXPos / 100f);
            }

            if (lStickXPos > _lStickInfo.threshold)
            {
                io.NavInputs[(int)ImGuiNavInput.LStickRight] = lStickXPos / 100f;
            }

            if (lStickYPos < -_lStickInfo.threshold)
            {
                io.NavInputs[(int)ImGuiNavInput.LStickUp] = MathF.Abs(lStickYPos / 100f);
            }

            if (lStickYPos > _lStickInfo.threshold)
            {
                io.NavInputs[(int)ImGuiNavInput.LStickDown] = lStickYPos / 100f;
            }
        }
Esempio n. 8
0
        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);
            }
        }
Esempio n. 9
0
        private void RenderImDrawData(ImDrawDataPtr draw_data, GraphicsDevice gd, CommandList cl)
        {
            uint vertexOffsetInVertices = 0;
            uint indexOffsetInElements  = 0;

            if (draw_data.CmdListsCount == 0)
            {
                return;
            }

            uint totalVBSize = (uint)(draw_data.TotalVtxCount * Unsafe.SizeOf <ImDrawVert>());

            if (totalVBSize > _vertexBuffer.SizeInBytes)
            {
                gd.DisposeWhenIdle(_vertexBuffer);
                _vertexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)(totalVBSize * 1.5f), BufferUsage.VertexBuffer | BufferUsage.Dynamic));
            }

            uint totalIBSize = (uint)(draw_data.TotalIdxCount * sizeof(ushort));

            if (totalIBSize > _indexBuffer.SizeInBytes)
            {
                gd.DisposeWhenIdle(_indexBuffer);
                _indexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)(totalIBSize * 1.5f), BufferUsage.IndexBuffer | BufferUsage.Dynamic));
            }

            for (int i = 0; i < draw_data.CmdListsCount; i++)
            {
                ImDrawListPtr cmd_list = draw_data.CmdListsRange[i];

                cl.UpdateBuffer(
                    _vertexBuffer,
                    vertexOffsetInVertices * (uint)Unsafe.SizeOf <ImDrawVert>(),
                    cmd_list.VtxBuffer.Data,
                    (uint)(cmd_list.VtxBuffer.Size * Unsafe.SizeOf <ImDrawVert>()));

                cl.UpdateBuffer(
                    _indexBuffer,
                    indexOffsetInElements * sizeof(ushort),
                    cmd_list.IdxBuffer.Data,
                    (uint)(cmd_list.IdxBuffer.Size * sizeof(ushort)));

                vertexOffsetInVertices += (uint)cmd_list.VtxBuffer.Size;
                indexOffsetInElements  += (uint)cmd_list.IdxBuffer.Size;
            }

            // Setup orthographic projection matrix into our constant buffer
            ImGuiIOPtr io  = ImGui.GetIO();
            Matrix4x4  mvp = Matrix4x4.CreateOrthographicOffCenter(
                0f,
                io.DisplaySize.X,
                io.DisplaySize.Y,
                0.0f,
                -1.0f,
                1.0f);

            _gd.UpdateBuffer(_projMatrixBuffer, 0, ref mvp);

            cl.SetVertexBuffer(0, _vertexBuffer);
            cl.SetIndexBuffer(_indexBuffer, IndexFormat.UInt16);
            cl.SetPipeline(_pipeline);
            cl.SetGraphicsResourceSet(0, _mainResourceSet);

            draw_data.ScaleClipRects(io.DisplayFramebufferScale);

            // Render command lists
            int vtx_offset = 0;
            int idx_offset = 0;

            for (int n = 0; n < draw_data.CmdListsCount; n++)
            {
                ImDrawListPtr cmd_list = draw_data.CmdListsRange[n];
                for (int cmd_i = 0; cmd_i < cmd_list.CmdBuffer.Size; cmd_i++)
                {
                    ImDrawCmdPtr pcmd = cmd_list.CmdBuffer[cmd_i];
                    if (pcmd.UserCallback != IntPtr.Zero)
                    {
                        throw new NotImplementedException();
                    }
                    else
                    {
                        if (pcmd.TextureId != IntPtr.Zero)
                        {
                            if (pcmd.TextureId == _fontAtlasID)
                            {
                                cl.SetGraphicsResourceSet(1, _fontTextureResourceSet);
                            }
                            else
                            {
                                cl.SetGraphicsResourceSet(1, GetImageResourceSet(pcmd.TextureId));
                            }
                        }

                        cl.SetScissorRect(
                            0,
                            (uint)pcmd.ClipRect.X,
                            (uint)pcmd.ClipRect.Y,
                            (uint)(pcmd.ClipRect.Z - pcmd.ClipRect.X),
                            (uint)(pcmd.ClipRect.W - pcmd.ClipRect.Y));

                        cl.DrawIndexed(pcmd.ElemCount, 1, (uint)idx_offset, vtx_offset, 0);
                    }

                    idx_offset += (int)pcmd.ElemCount;
                }
                vtx_offset += cmd_list.VtxBuffer.Size;
            }
        }
Esempio n. 10
0
        private void UpdateImGuiInput(InputSnapshot snapshot)
        {
            ImGuiIOPtr io = ImGui.GetIO();

            Vector2 mousePosition = snapshot.MousePosition;

            // Determine if any of the mouse buttons were pressed during this snapshot period, even if they are no longer held.
            bool leftPressed   = false;
            bool middlePressed = false;
            bool rightPressed  = false;

            foreach (MouseEvent me in snapshot.MouseEvents)
            {
                if (me.Down)
                {
                    switch (me.MouseButton)
                    {
                    case MouseButton.Left:
                        leftPressed = true;
                        break;

                    case MouseButton.Middle:
                        middlePressed = true;
                        break;

                    case MouseButton.Right:
                        rightPressed = true;
                        break;
                    }
                }
            }

            io.MouseDown[0] = leftPressed || snapshot.IsMouseDown(MouseButton.Left);
            io.MouseDown[1] = rightPressed || snapshot.IsMouseDown(MouseButton.Right);
            io.MouseDown[2] = middlePressed || snapshot.IsMouseDown(MouseButton.Middle);
            io.MousePos     = mousePosition;
            io.MouseWheel   = snapshot.WheelDelta;

            IReadOnlyList <char> keyCharPresses = snapshot.KeyCharPresses;

            for (int i = 0; i < keyCharPresses.Count; i++)
            {
                char c = keyCharPresses[i];
                io.AddInputCharacter(c);
            }

            IReadOnlyList <KeyEvent> keyEvents = snapshot.KeyEvents;

            for (int i = 0; i < keyEvents.Count; i++)
            {
                KeyEvent keyEvent = keyEvents[i];
                io.KeysDown[(int)keyEvent.Key] = keyEvent.Down;
                if (keyEvent.Key == Key.ControlLeft)
                {
                    _controlDown = keyEvent.Down;
                }
                if (keyEvent.Key == Key.ShiftLeft)
                {
                    _shiftDown = keyEvent.Down;
                }
                if (keyEvent.Key == Key.AltLeft)
                {
                    _altDown = keyEvent.Down;
                }
                if (keyEvent.Key == Key.WinLeft)
                {
                    _winKeyDown = keyEvent.Down;
                }
            }

            io.KeyCtrl  = _controlDown;
            io.KeyAlt   = _altDown;
            io.KeyShift = _shiftDown;
            io.KeySuper = _winKeyDown;
        }
Esempio n. 11
0
        private static void UpdateJoystickActionState(ImGuiIOPtr io, ImGuiNavInput action)
        {
            var isPressed = Joystick.IsButtonPressed(JoystickId, _joystickMapping[(int)action]);

            io.NavInputs[(int)action] = isPressed ? 1f : 0f;
        }
Esempio n. 12
0
 private static extern void RenderDrawLists(ImDrawDataPtr drawData, ImGuiIOPtr io);
Esempio n. 13
0
        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

                if (ImGui.InputTextMultiline("TestLabel", ref _testInput, ushort.MaxValue, new Vector2(200, 200)))
                {
                }

                ImGui.Text($"Mouse position: {ImGui.GetMousePos()}");
                ImGui.Text($"Mouse down: {ImGui.GetIO().MouseDown[0]}");

                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);
            }
        }
        /// <summary>
        /// Constructs a new ImGuiController.
        /// </summary>
        public ImGuiController(GraphicsDevice gd, Sdl2Window window, OutputDescription outputDescription, int width, int height)
        {
            _gd           = gd;
            _window       = window;
            _windowWidth  = width;
            _windowHeight = height;

            IntPtr context = ImGui.CreateContext();

            ImGui.SetCurrentContext(context);
            ImGuiIOPtr io = ImGui.GetIO();


            io.ConfigFlags |= ImGuiConfigFlags.DockingEnable;
            io.ConfigFlags |= ImGuiConfigFlags.ViewportsEnable;

            ImGuiPlatformIOPtr platformIO   = ImGui.GetPlatformIO();
            ImGuiViewportPtr   mainViewport = platformIO.MainViewport;

            _mainViewportWindow         = new VeldridImGuiWindow(gd, mainViewport, _window);
            mainViewport.PlatformHandle = window.Handle;

            _createWindow       = CreateWindow;
            _destroyWindow      = DestroyWindow;
            _getWindowPos       = GetWindowPos;
            _showWindow         = ShowWindow;
            _setWindowPos       = SetWindowPos;
            _setWindowSize      = SetWindowSize;
            _getWindowSize      = GetWindowSize;
            _setWindowFocus     = SetWindowFocus;
            _getWindowFocus     = GetWindowFocus;
            _getWindowMinimized = GetWindowMinimized;
            _setWindowTitle     = SetWindowTitle;

            platformIO.Platform_CreateWindow       = Marshal.GetFunctionPointerForDelegate(_createWindow);
            platformIO.Platform_DestroyWindow      = Marshal.GetFunctionPointerForDelegate(_destroyWindow);
            platformIO.Platform_ShowWindow         = Marshal.GetFunctionPointerForDelegate(_showWindow);
            platformIO.Platform_SetWindowPos       = Marshal.GetFunctionPointerForDelegate(_setWindowPos);
            platformIO.Platform_SetWindowSize      = Marshal.GetFunctionPointerForDelegate(_setWindowSize);
            platformIO.Platform_SetWindowFocus     = Marshal.GetFunctionPointerForDelegate(_setWindowFocus);
            platformIO.Platform_GetWindowFocus     = Marshal.GetFunctionPointerForDelegate(_getWindowFocus);
            platformIO.Platform_GetWindowMinimized = Marshal.GetFunctionPointerForDelegate(_getWindowMinimized);
            platformIO.Platform_SetWindowTitle     = Marshal.GetFunctionPointerForDelegate(_setWindowTitle);
            platformIO.Platform_GetWindowPos       = Marshal.GetFunctionPointerForDelegate(_getWindowPos);
            platformIO.Platform_GetWindowSize      = Marshal.GetFunctionPointerForDelegate(_getWindowSize);

            unsafe
            {
                io.NativePtr->BackendPlatformName = (byte *)new FixedAsciiString("Veldrid.SDL2 Backend").DataPtr;
            }
            io.BackendFlags |= ImGuiBackendFlags.HasMouseCursors;
            io.BackendFlags |= ImGuiBackendFlags.HasSetMousePos;
            io.BackendFlags |= ImGuiBackendFlags.PlatformHasViewports;
            io.BackendFlags |= ImGuiBackendFlags.RendererHasViewports;

            io.Fonts.AddFontDefault();

            CreateDeviceResources(gd, outputDescription);
            SetKeyMappings();

            SetPerFrameImGuiData(1f / 60f);

            UpdateMonitors();

            ImGui.NewFrame();
            _frameBegun = true;
        }
        private void UpdateImGuiInput(InputSnapshot snapshot)
        {
            ImGuiIOPtr io = ImGui.GetIO();

            // Determine if any of the mouse buttons were pressed during this snapshot period, even if they are no longer held.
            bool leftPressed   = false;
            bool middlePressed = false;
            bool rightPressed  = false;

            foreach (MouseEvent me in snapshot.MouseEvents)
            {
                if (me.Down)
                {
                    switch (me.MouseButton)
                    {
                    case MouseButton.Left:
                        leftPressed = true;
                        break;

                    case MouseButton.Middle:
                        middlePressed = true;
                        break;

                    case MouseButton.Right:
                        rightPressed = true;
                        break;
                    }
                }
            }

            io.MouseDown[0] = leftPressed || snapshot.IsMouseDown(MouseButton.Left);
            io.MouseDown[1] = middlePressed || snapshot.IsMouseDown(MouseButton.Right);
            io.MouseDown[2] = rightPressed || snapshot.IsMouseDown(MouseButton.Middle);

            if (p_sdl_GetGlobalMouseState == null)
            {
                p_sdl_GetGlobalMouseState = Sdl2Native.LoadFunction <SDL_GetGlobalMouseState_t>("SDL_GetGlobalMouseState");
            }

            if ((io.ConfigFlags & ImGuiConfigFlags.ViewportsEnable) != 0)
            {
                int x, y;
                unsafe
                {
                    uint buttons = p_sdl_GetGlobalMouseState(&x, &y);
                    io.MouseDown[0] = (buttons & 0b00001) != 0;
                    io.MouseDown[1] = (buttons & 0b00010) != 0;
                    io.MouseDown[2] = (buttons & 0b00100) != 0;
                    io.MouseDown[3] = (buttons & 0b01000) != 0;
                    io.MouseDown[4] = (buttons & 0b10000) != 0;
                }
                io.MousePos = new Vector2(x, y);
            }
            else
            {
                io.MousePos = snapshot.MousePosition;
            }

            io.MouseWheel = snapshot.WheelDelta;

            IReadOnlyList <char> keyCharPresses = snapshot.KeyCharPresses;

            for (int i = 0; i < keyCharPresses.Count; i++)
            {
                char c = keyCharPresses[i];
                io.AddInputCharacter(c);
            }

            IReadOnlyList <KeyEvent> keyEvents = snapshot.KeyEvents;

            for (int i = 0; i < keyEvents.Count; i++)
            {
                io.KeysDown[(int)keyEvents[i].Key] = keyEvents[i].Down;
            }

            io.KeyCtrl  = io.KeysDown[(int)Key.ControlLeft] || io.KeysDown[(int)Key.ControlRight];
            io.KeyAlt   = io.KeysDown[(int)Key.AltLeft] || io.KeysDown[(int)Key.AltRight];
            io.KeyShift = io.KeysDown[(int)Key.ShiftLeft] || io.KeysDown[(int)Key.ShiftRight];
            io.KeySuper = io.KeysDown[(int)Key.WinLeft] || io.KeysDown[(int)Key.WinRight];

            ImVector <ImGuiViewportPtr> viewports = ImGui.GetPlatformIO().Viewports;

            for (int i = 1; i < viewports.Size; i++)
            {
                ImGuiViewportPtr   v      = viewports[i];
                VeldridImGuiWindow window = ((VeldridImGuiWindow)GCHandle.FromIntPtr(v.PlatformUserData).Target);
                window.Update();
            }
        }