ok i'll wait the official

This commit is contained in:
4sval 2022-09-03 14:30:01 +02:00
parent eabf6d9bcf
commit 97b03ed0c7
4 changed files with 8 additions and 519 deletions

View File

@ -1,496 +0,0 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Numerics;
using FModel.Framework;
using ImGuiNET;
using Silk.NET.Input;
using Silk.NET.Input.Extensions;
using Silk.NET.Maths;
using Silk.NET.OpenGL;
using Silk.NET.Windowing;
using Shader = FModel.Views.Snooper.Shader;
using Texture = FModel.Views.Snooper.Texture;
namespace FModel.Extensions;
/// <summary>
/// because we use ImTool for docking purposes we pasted
/// https://github.com/dotnet/Silk.NET/blob/main/src/OpenGL/Extensions/Silk.NET.OpenGL.Extensions.ImGui/ImGuiController.cs
/// </summary>
public class ImGuiControllerExtensions : IDisposable
{
private GL _gl;
private IView _view;
private IInputContext _input;
private bool _frameBegun;
private readonly List<char> _pressedChars = new ();
private IKeyboard _keyboard;
private int _attribLocationTex;
private int _attribLocationProjMtx;
private int _attribLocationVtxPos;
private int _attribLocationVtxUV;
private int _attribLocationVtxColor;
private uint _vboHandle;
private uint _elementsHandle;
private uint _vertexArrayObject;
private Texture _fontTexture;
private Shader _shader;
private int _windowWidth;
private int _windowHeight;
public IntPtr Context;
public ImGuiControllerExtensions(GL gl, IView view, IInputContext input, ImGuiFontConfig? imGuiFontConfig = null)
{
Init(gl, view, input);
var io = ImGui.GetIO();
if (imGuiFontConfig is not null)
{
io.Fonts.AddFontFromFileTTF(imGuiFontConfig.Value.FontPath, imGuiFontConfig.Value.FontSize);
}
io.BackendFlags |= ImGuiBackendFlags.RendererHasVtxOffset;
CreateDeviceResources();
SetKeyMappings();
SetPerFrameImGuiData(1f / 60f);
BeginFrame();
}
public void MakeCurrent()
{
ImGui.SetCurrentContext(Context);
}
private void Init(GL gl, IView view, IInputContext input)
{
_gl = gl;
_view = view;
_input = input;
_windowWidth = view.Size.X;
_windowHeight = view.Size.Y;
Context = ImGui.CreateContext();
ImGui.SetCurrentContext(Context);
ImGui.StyleColorsDark();
}
private void BeginFrame()
{
ImGui.NewFrame();
_frameBegun = true;
_keyboard = _input.Keyboards[0];
_view.Resize += WindowResized;
_keyboard.KeyChar += OnKeyChar;
}
private void OnKeyChar(IKeyboard arg1, char arg2)
{
_pressedChars.Add(arg2);
}
private void WindowResized(Vector2D<int> size)
{
_windowWidth = size.X;
_windowHeight = size.Y;
}
public void Render()
{
if (!_frameBegun) return;
var oldCtx = ImGui.GetCurrentContext();
if (oldCtx != Context)
ImGui.SetCurrentContext(Context);
_frameBegun = false;
ImGui.Render();
RenderImDrawData(ImGui.GetDrawData());
if (oldCtx != Context)
ImGui.SetCurrentContext(oldCtx);
}
public void Update(float deltaSeconds)
{
var oldCtx = ImGui.GetCurrentContext();
if (oldCtx != Context)
ImGui.SetCurrentContext(Context);
if (_frameBegun)
ImGui.Render();
SetPerFrameImGuiData(deltaSeconds);
UpdateImGuiInput();
_frameBegun = true;
ImGui.NewFrame();
if (oldCtx != Context)
ImGui.SetCurrentContext(oldCtx);
}
private void SetPerFrameImGuiData(float deltaSeconds)
{
var io = ImGui.GetIO();
io.DisplaySize = new Vector2(_windowWidth, _windowHeight);
if (_windowWidth > 0 && _windowHeight > 0)
{
io.DisplayFramebufferScale = new Vector2(_view.FramebufferSize.X / _windowWidth,
_view.FramebufferSize.Y / _windowHeight);
}
io.DeltaTime = deltaSeconds; // DeltaTime is in seconds.
}
private static Key[] keyEnumArr = (Key[]) Enum.GetValues(typeof(Key));
private void UpdateImGuiInput()
{
var io = ImGui.GetIO();
var mouseState = _input.Mice[0].CaptureState();
var keyboardState = _input.Keyboards[0];
io.MouseDown[0] = mouseState.IsButtonPressed(MouseButton.Left);
io.MouseDown[1] = mouseState.IsButtonPressed(MouseButton.Right);
io.MouseDown[2] = mouseState.IsButtonPressed(MouseButton.Middle);
var point = new Point((int) mouseState.Position.X, (int) mouseState.Position.Y);
io.MousePos = new Vector2(point.X, point.Y);
var wheel = mouseState.GetScrollWheels()[0];
io.MouseWheel = wheel.Y;
io.MouseWheelH = wheel.X;
foreach (var key in keyEnumArr)
{
if (key == Key.Unknown)
{
continue;
}
io.KeysDown[(int) key] = keyboardState.IsKeyPressed(key);
}
foreach (var c in _pressedChars)
{
io.AddInputCharacter(c);
}
_pressedChars.Clear();
io.KeyCtrl = keyboardState.IsKeyPressed(Key.ControlLeft) || keyboardState.IsKeyPressed(Key.ControlRight);
io.KeyAlt = keyboardState.IsKeyPressed(Key.AltLeft) || keyboardState.IsKeyPressed(Key.AltRight);
io.KeyShift = keyboardState.IsKeyPressed(Key.ShiftLeft) || keyboardState.IsKeyPressed(Key.ShiftRight);
io.KeySuper = keyboardState.IsKeyPressed(Key.SuperLeft) || keyboardState.IsKeyPressed(Key.SuperRight);
}
private void PressChar(char keyChar)
{
_pressedChars.Add(keyChar);
}
private static void SetKeyMappings()
{
var 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;
}
private unsafe void SetupRenderState(ImDrawDataPtr drawDataPtr, int framebufferWidth, int framebufferHeight)
{
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
_gl.Enable(GLEnum.Blend);
_gl.BlendEquation(GLEnum.FuncAdd);
_gl.BlendFuncSeparate(GLEnum.SrcAlpha, GLEnum.OneMinusSrcAlpha, GLEnum.One, GLEnum.OneMinusSrcAlpha);
_gl.Disable(GLEnum.CullFace);
_gl.Disable(GLEnum.DepthTest);
_gl.Disable(GLEnum.StencilTest);
_gl.Enable(GLEnum.ScissorTest);
_gl.Disable(GLEnum.PrimitiveRestart);
_gl.PolygonMode(GLEnum.FrontAndBack, GLEnum.Fill);
float L = drawDataPtr.DisplayPos.X;
float R = drawDataPtr.DisplayPos.X + drawDataPtr.DisplaySize.X;
float T = drawDataPtr.DisplayPos.Y;
float B = drawDataPtr.DisplayPos.Y + drawDataPtr.DisplaySize.Y;
Span<float> orthoProjection = stackalloc float[] {
2.0f / (R - L), 0.0f, 0.0f, 0.0f,
0.0f, 2.0f / (T - B), 0.0f, 0.0f,
0.0f, 0.0f, -1.0f, 0.0f,
(R + L) / (L - R), (T + B) / (B - T), 0.0f, 1.0f,
};
_shader.Use();
_gl.Uniform1(_attribLocationTex, 0);
_gl.UniformMatrix4(_attribLocationProjMtx, 1, false, orthoProjection);
_gl.BindSampler(0, 0);
// Setup desired GL state
// Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts)
// The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound.
_vertexArrayObject = _gl.GenVertexArray();
_gl.BindVertexArray(_vertexArrayObject);
// Bind vertex/index buffers and setup attributes for ImDrawVert
_gl.BindBuffer(GLEnum.ArrayBuffer, _vboHandle);
_gl.BindBuffer(GLEnum.ElementArrayBuffer, _elementsHandle);
_gl.EnableVertexAttribArray((uint) _attribLocationVtxPos);
_gl.EnableVertexAttribArray((uint) _attribLocationVtxUV);
_gl.EnableVertexAttribArray((uint) _attribLocationVtxColor);
_gl.VertexAttribPointer((uint) _attribLocationVtxPos, 2, GLEnum.Float, false, (uint) sizeof(ImDrawVert), (void*) 0);
_gl.VertexAttribPointer((uint) _attribLocationVtxUV, 2, GLEnum.Float, false, (uint) sizeof(ImDrawVert), (void*) 8);
_gl.VertexAttribPointer((uint) _attribLocationVtxColor, 4, GLEnum.UnsignedByte, true, (uint) sizeof(ImDrawVert), (void*) 16);
}
private unsafe void RenderImDrawData(ImDrawDataPtr drawDataPtr)
{
int framebufferWidth = (int) (drawDataPtr.DisplaySize.X * drawDataPtr.FramebufferScale.X);
int framebufferHeight = (int) (drawDataPtr.DisplaySize.Y * drawDataPtr.FramebufferScale.Y);
if (framebufferWidth <= 0 || framebufferHeight <= 0)
return;
// Backup GL state
_gl.GetInteger(GLEnum.ActiveTexture, out int lastActiveTexture);
_gl.ActiveTexture(GLEnum.Texture0);
_gl.GetInteger(GLEnum.CurrentProgram, out int lastProgram);
_gl.GetInteger(GLEnum.TextureBinding2D, out int lastTexture);
_gl.GetInteger(GLEnum.SamplerBinding, out int lastSampler);
_gl.GetInteger(GLEnum.ArrayBufferBinding, out int lastArrayBuffer);
_gl.GetInteger(GLEnum.VertexArrayBinding, out int lastVertexArrayObject);
Span<int> lastPolygonMode = stackalloc int[2];
_gl.GetInteger(GLEnum.PolygonMode, lastPolygonMode);
Span<int> lastScissorBox = stackalloc int[4];
_gl.GetInteger(GLEnum.ScissorBox, lastScissorBox);
_gl.GetInteger(GLEnum.BlendSrcRgb, out int lastBlendSrcRgb);
_gl.GetInteger(GLEnum.BlendDstRgb, out int lastBlendDstRgb);
_gl.GetInteger(GLEnum.BlendSrcAlpha, out int lastBlendSrcAlpha);
_gl.GetInteger(GLEnum.BlendDstAlpha, out int lastBlendDstAlpha);
_gl.GetInteger(GLEnum.BlendEquationRgb, out int lastBlendEquationRgb);
_gl.GetInteger(GLEnum.BlendEquationAlpha, out int lastBlendEquationAlpha);
bool lastEnableBlend = _gl.IsEnabled(GLEnum.Blend);
bool lastEnableCullFace = _gl.IsEnabled(GLEnum.CullFace);
bool lastEnableDepthTest = _gl.IsEnabled(GLEnum.DepthTest);
bool lastEnableStencilTest = _gl.IsEnabled(GLEnum.StencilTest);
bool lastEnableScissorTest = _gl.IsEnabled(GLEnum.ScissorTest);
bool lastEnablePrimitiveRestart = _gl.IsEnabled(GLEnum.PrimitiveRestart);
SetupRenderState(drawDataPtr, framebufferWidth, framebufferHeight);
// Will project scissor/clipping rectangles into framebuffer space
Vector2 clipOff = drawDataPtr.DisplayPos; // (0,0) unless using multi-viewports
Vector2 clipScale = drawDataPtr.FramebufferScale; // (1,1) unless using retina display which are often (2,2)
// Render command lists
for (int n = 0; n < drawDataPtr.CmdListsCount; n++)
{
ImDrawListPtr cmdListPtr = drawDataPtr.CmdListsRange[n];
// Upload vertex/index buffers
_gl.BufferData(GLEnum.ArrayBuffer, (nuint) (cmdListPtr.VtxBuffer.Size * sizeof(ImDrawVert)), (void*) cmdListPtr.VtxBuffer.Data, GLEnum.StreamDraw);
_gl.BufferData(GLEnum.ElementArrayBuffer, (nuint) (cmdListPtr.IdxBuffer.Size * sizeof(ushort)), (void*) cmdListPtr.IdxBuffer.Data, GLEnum.StreamDraw);
for (int cmd_i = 0; cmd_i < cmdListPtr.CmdBuffer.Size; cmd_i++)
{
ImDrawCmdPtr cmdPtr = cmdListPtr.CmdBuffer[cmd_i];
if (cmdPtr.UserCallback != IntPtr.Zero)
throw new NotImplementedException();
Vector4 clipRect;
clipRect.X = (cmdPtr.ClipRect.X - clipOff.X) * clipScale.X;
clipRect.Y = (cmdPtr.ClipRect.Y - clipOff.Y) * clipScale.Y;
clipRect.Z = (cmdPtr.ClipRect.Z - clipOff.X) * clipScale.X;
clipRect.W = (cmdPtr.ClipRect.W - clipOff.Y) * clipScale.Y;
if (clipRect.X < framebufferWidth && clipRect.Y < framebufferHeight && clipRect.Z >= 0.0f && clipRect.W >= 0.0f)
{
// Apply scissor/clipping rectangle
_gl.Scissor((int) clipRect.X, (int) (framebufferHeight - clipRect.W), (uint) (clipRect.Z - clipRect.X), (uint) (clipRect.W - clipRect.Y));
// Bind texture, Draw
_gl.BindTexture(GLEnum.Texture2D, (uint) cmdPtr.TextureId);
_gl.DrawElementsBaseVertex(GLEnum.Triangles, cmdPtr.ElemCount, GLEnum.UnsignedShort, (void*) (cmdPtr.IdxOffset * sizeof(ushort)), (int) cmdPtr.VtxOffset);
}
}
}
// Destroy the temporary VAO
_gl.DeleteVertexArray(_vertexArrayObject);
_vertexArrayObject = 0;
// Restore modified GL state
_gl.UseProgram((uint) lastProgram);
_gl.BindTexture(GLEnum.Texture2D, (uint) lastTexture);
_gl.BindSampler(0, (uint) lastSampler);
_gl.ActiveTexture((GLEnum) lastActiveTexture);
_gl.BindVertexArray((uint) lastVertexArrayObject);
_gl.BindBuffer(GLEnum.ArrayBuffer, (uint) lastArrayBuffer);
_gl.BlendEquationSeparate((GLEnum) lastBlendEquationRgb, (GLEnum) lastBlendEquationAlpha);
_gl.BlendFuncSeparate((GLEnum) lastBlendSrcRgb, (GLEnum) lastBlendDstRgb, (GLEnum) lastBlendSrcAlpha, (GLEnum) lastBlendDstAlpha);
if (lastEnableBlend)
{
_gl.Enable(GLEnum.Blend);
}
else
{
_gl.Disable(GLEnum.Blend);
}
if (lastEnableCullFace)
{
_gl.Enable(GLEnum.CullFace);
}
else
{
_gl.Disable(GLEnum.CullFace);
}
if (lastEnableDepthTest)
{
_gl.Enable(GLEnum.DepthTest);
}
else
{
_gl.Disable(GLEnum.DepthTest);
}
if (lastEnableStencilTest)
{
_gl.Enable(GLEnum.StencilTest);
}
else
{
_gl.Disable(GLEnum.StencilTest);
}
if (lastEnableScissorTest)
{
_gl.Enable(GLEnum.ScissorTest);
}
else
{
_gl.Disable(GLEnum.ScissorTest);
}
if (lastEnablePrimitiveRestart)
{
_gl.Enable(GLEnum.PrimitiveRestart);
}
else
{
_gl.Disable(GLEnum.PrimitiveRestart);
}
_gl.PolygonMode(GLEnum.FrontAndBack, (GLEnum) lastPolygonMode[0]);
_gl.Scissor(lastScissorBox[0], lastScissorBox[1], (uint) lastScissorBox[2], (uint) lastScissorBox[3]);
}
private void CreateDeviceResources()
{
// Backup GL state
_gl.GetInteger(GLEnum.TextureBinding2D, out int lastTexture);
_gl.GetInteger(GLEnum.ArrayBufferBinding, out int lastArrayBuffer);
_gl.GetInteger(GLEnum.VertexArrayBinding, out int lastVertexArray);
_shader = new Shader(_gl, "imgui");
_attribLocationTex = _shader.GetUniformLocation("Texture");
_attribLocationProjMtx = _shader.GetUniformLocation("ProjMtx");
_attribLocationVtxPos = _shader.GetAttribLocation("Position");
_attribLocationVtxUV = _shader.GetAttribLocation("UV");
_attribLocationVtxColor = _shader.GetAttribLocation("Color");
_vboHandle = _gl.GenBuffer();
_elementsHandle = _gl.GenBuffer();
RecreateFontDeviceTexture();
// Restore modified GL state
_gl.BindTexture(GLEnum.Texture2D, (uint) lastTexture);
_gl.BindBuffer(GLEnum.ArrayBuffer, (uint) lastArrayBuffer);
_gl.BindVertexArray((uint) lastVertexArray);
}
/// <summary>
/// Creates the texture used to render text.
/// </summary>
private unsafe void RecreateFontDeviceTexture()
{
// Build texture atlas
var io = ImGui.GetIO();
io.Fonts.GetTexDataAsRGBA32(out IntPtr pixels, out int width, out int height, out int bytesPerPixel); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
// Upload texture to graphics system
_gl.GetInteger(GLEnum.TextureBinding2D, out int lastTexture);
_fontTexture = new Texture(_gl, (uint) width, (uint) height, pixels);
_fontTexture.Bind(TextureTarget.Texture2D);
_fontTexture.SetMagFilter(TextureMagFilter.Linear);
_fontTexture.SetMinFilter(TextureMinFilter.Linear);
// Store our identifier
io.Fonts.SetTexID(_fontTexture.GetPointer());
// Restore state
_gl.BindTexture(GLEnum.Texture2D, (uint) lastTexture);
}
public void Dispose()
{
_view.Resize -= WindowResized;
_keyboard.KeyChar -= OnKeyChar;
_gl.DeleteBuffer(_vboHandle);
_gl.DeleteBuffer(_elementsHandle);
_gl.DeleteVertexArray(_vertexArrayObject);
_fontTexture.Dispose();
_shader.Dispose();
ImGui.DestroyContext(Context);
}
}

View File

@ -133,7 +133,6 @@
<PackageReference Include="DiscordRichPresence" Version="1.0.175" />
<PackageReference Include="EpicManifestParser" Version="1.2.70-temp" />
<PackageReference Include="HelixToolkit.SharpDX.Core.Wpf" Version="2.21.0" />
<PackageReference Include="ImTool" Version="1.3.6" />
<PackageReference Include="K4os.Compression.LZ4.Streams" Version="1.2.16" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NVorbis" Version="0.10.4" />
@ -145,6 +144,7 @@
<PackageReference Include="Silk.NET.Input" Version="2.16.0" />
<PackageReference Include="Silk.NET.Input.Extensions" Version="2.16.0" />
<PackageReference Include="Silk.NET.OpenGL" Version="2.16.0" />
<PackageReference Include="Silk.NET.OpenGL.Extensions.ImGui" Version="2.16.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
<PackageReference Include="SkiaSharp.HarfBuzz" Version="2.88.0" />
<PackageReference Include="SkiaSharp.Svg" Version="1.60.0" />

View File

@ -1,16 +0,0 @@
using System;
namespace FModel.Framework;
public readonly struct ImGuiFontConfig
{
public ImGuiFontConfig(string fontPath, int fontSize)
{
if (fontSize <= 0) throw new ArgumentOutOfRangeException(nameof(fontSize));
FontPath = fontPath ?? throw new ArgumentNullException(nameof(fontPath));
FontSize = fontSize;
}
public string FontPath { get; }
public int FontSize { get; }
}

View File

@ -1,19 +1,18 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using FModel.Extensions;
using FModel.Framework;
using ImGuiNET;
using Silk.NET.Input;
using Silk.NET.Maths;
using Silk.NET.OpenGL;
using Silk.NET.OpenGL.Extensions.ImGui;
using Silk.NET.Windowing;
namespace FModel.Views.Snooper;
public class SnimGui : IDisposable
{
private readonly ImGuiControllerExtensions _controller;
private readonly ImGuiController _controller;
private readonly GraphicsAPI _api;
private readonly Vector2 _outlinerSize;
@ -28,14 +27,14 @@ public class SnimGui : IDisposable
private int _selectedModel;
private int _selectedSection;
private const ImGuiWindowFlags _noResize = ImGuiWindowFlags.NoResize| ImGuiWindowFlags.NoMove; // delete once we have a proper docking branch
private const ImGuiWindowFlags _noResize = ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove; // delete once we have a proper docking branch
private const ImGuiCond _firstUse = ImGuiCond.Appearing; // switch to FirstUseEver once the docking branch will not be useful anymore...
private const uint _dockspaceId = 1337;
public SnimGui(GL gl, IWindow window, IInputContext input)
{
var fontConfig = new ImGuiFontConfig("C:\\Windows\\Fonts\\segoeui.ttf", 16);
_controller = new ImGuiControllerExtensions(gl, window, input, fontConfig);
_controller = new ImGuiController(gl, window, input, fontConfig);
_api = window.API;
var style = ImGui.GetStyle();
@ -80,7 +79,9 @@ public class SnimGui : IDisposable
ImGui.SetNextWindowPos(new Vector2(0, 0));
ImGui.SetNextWindowSize(new Vector2(size.X, size.Y));
ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero);
ImGui.Begin("Snooper", flags);
ImGui.PopStyleVar();
ImGui.DockSpace(_dockspaceId);
}
@ -378,7 +379,7 @@ public class SnimGui : IDisposable
io.ConfigFlags |= ImGuiConfigFlags.DockingEnable;
io.ConfigFlags |= ImGuiConfigFlags.ViewportsEnable;
io.ConfigWindowsMoveFromTitleBarOnly = true;
// io.ConfigDockingWithShift = true;
io.ConfigDockingWithShift = true;
// style.WindowPadding = Vector2.Zero;
// style.Colors[(int) ImGuiCol.Text] = new Vector4(0.95f, 0.96f, 0.98f, 1.00f);