cleanup the ImGui code stuffs

This commit is contained in:
Mike 2019-02-14 17:34:12 -08:00
parent 1f1ef82697
commit 6ebd635a61
3 changed files with 456 additions and 452 deletions

View File

@ -1,28 +0,0 @@
using Microsoft.Xna.Framework.Graphics;
namespace ImGuiNET.SampleProgram.XNA
{
public static class DrawVertDeclaration
{
public static readonly VertexDeclaration Declaration;
public static readonly int Size;
static DrawVertDeclaration()
{
unsafe { Size = sizeof(ImDrawVert); }
Declaration = new VertexDeclaration(
Size,
// Position
new VertexElement(0, VertexElementFormat.Vector2, VertexElementUsage.Position, 0),
// UV
new VertexElement(8, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0),
// Color
new VertexElement(16, VertexElementFormat.Color, VertexElementUsage.Color, 0)
);
}
}
}

View File

@ -1,7 +1,6 @@
using System;
using System.Reflection;
using ImGuiNET;
using ImGuiNET.SampleProgram.XNA;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
@ -18,30 +17,16 @@ namespace Nez
public ImGuiFinalRenderDelegate()
{
_imGuiRenderer = new ImGuiRenderer( Core.instance );
_imGuiRenderer.RebuildFontAtlas();
ImGui.GetIO().ConfigWindowsMoveFromTitleBarOnly = true;
_imGuiRenderer.rebuildFontAtlas();
}
public void handleFinalRender( Color letterboxColor, RenderTarget2D source, Rectangle finalRenderDestinationRect, SamplerState samplerState )
[Console.Command( "toggle-imgui", "Toggles the Dear ImGui renderer" )]
static void toggleImGui()
{
if(_lastRenderTarget != source)
{
// unbind the old texture if we had one
if(_lastRenderTarget != null)
_imGuiRenderer.UnbindTexture(_renderTargetId);
// bind the new texture
_lastRenderTarget = source;
_renderTargetId = _imGuiRenderer.BindTexture(source);
}
Core.graphicsDevice.setRenderTarget( null );
Core.graphicsDevice.Clear( letterboxColor );
_imGuiRenderer.BeforeLayout(Time.time);
layoutGui();
_imGuiRenderer.AfterLayout();
if( Core.scene.finalRenderDelegate == null )
Core.scene.finalRenderDelegate = new ImGuiFinalRenderDelegate();
else
Core.scene.finalRenderDelegate = null;
}
void layoutGui()
@ -50,6 +35,7 @@ namespace Nez
var maxSize = new System.Numerics.Vector2( _lastRenderTarget.Width, _lastRenderTarget.Height );
var minSize = maxSize / 4;
maxSize *= 4;
unsafe
{
ImGui.SetNextWindowSizeConstraints( minSize, maxSize, data =>
@ -61,9 +47,51 @@ namespace Nez
}
ImGui.SetNextWindowPos( new System.Numerics.Vector2( 0, 0 ), ImGuiCond.FirstUseEver );
ImGui.PushStyleVar( ImGuiStyleVar.WindowPadding, new System.Numerics.Vector2( 0, 0 ) );
ImGui.Begin( "Game Window" );
Nugget.InputDisplay.cursorScreenPos = new Vector2( ImGui.GetCursorScreenPos().X, ImGui.GetCursorScreenPos().Y );
Nugget.InputDisplay.scaleX = ImGui.GetContentRegionAvail().X / _lastRenderTarget.Width;
Nugget.InputDisplay.scaleY = ImGui.GetContentRegionAvail().Y / _lastRenderTarget.Height;
//Debug.log( $"window pos: {ImGui.GetWindowPos()}" );
//Debug.log( $"avail size: {ImGui.GetContentRegionAvail()}" );
//Debug.log( $"rt {_lastRenderTarget.Width} x {_lastRenderTarget.Height}" );
//Debug.log( $"scaleX: {ImGui.GetContentRegionAvail().X / _lastRenderTarget.Width}" );
//Debug.log( $"scaleY: {ImGui.GetContentRegionAvail().Y / _lastRenderTarget.Height}" );
//Debug.log( ImGui.GetWindowSize() - ImGui.GetContentRegionAvail() );
//Debug.log( $"titleHeight: {titleHeight}" );
//Debug.log( $"screenPos: {ImGui.GetCursorScreenPos()}" );
ImGui.Image( _renderTargetId, ImGui.GetContentRegionAvail() );
ImGui.End();
ImGui.PopStyleVar();
}
#region IFinalRenderDelegate
public void handleFinalRender( RenderTarget2D finalRenderTarget, Color letterboxColor, RenderTarget2D source, Rectangle finalRenderDestinationRect, SamplerState samplerState )
{
if( _lastRenderTarget != source )
{
// unbind the old texture if we had one
if( _lastRenderTarget != null )
_imGuiRenderer.unbindTexture( _renderTargetId );
// bind the new texture
_lastRenderTarget = source;
_renderTargetId = _imGuiRenderer.bindTexture( source );
}
Core.graphicsDevice.setRenderTarget( finalRenderTarget );
Core.graphicsDevice.Clear( letterboxColor );
_imGuiRenderer.beforeLayout( Time.deltaTime );
layoutGui();
_imGuiRenderer.afterLayout();
}
public void onAddedToScene()
@ -74,5 +102,7 @@ namespace Nez
public void unload()
{ }
#endregion
}
}

View File

@ -1,52 +1,60 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Nez;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace ImGuiNET.SampleProgram.XNA
namespace ImGuiNET
{
/// <summary>
/// ImGui renderer for use with XNA-likes (FNA & MonoGame)
/// ImGui renderer for use with XNA-likes (FNA and MonoGame)
/// </summary>
public class ImGuiRenderer
{
private Game _game;
// Graphics
private GraphicsDevice _graphicsDevice;
BasicEffect _effect;
RasterizerState _rasterizerState;
private BasicEffect _effect;
private RasterizerState _rasterizerState;
readonly VertexDeclaration _vertexDeclaration;
readonly int _vertexDeclarationSize;
private byte[] _vertexData;
private VertexBuffer _vertexBuffer;
private int _vertexBufferSize;
byte[] _vertexData;
VertexBuffer _vertexBuffer;
int _vertexBufferSize;
private byte[] _indexData;
private IndexBuffer _indexBuffer;
private int _indexBufferSize;
byte[] _indexData;
IndexBuffer _indexBuffer;
int _indexBufferSize;
// Textures
private Dictionary<IntPtr, Texture2D> _loadedTextures;
Dictionary<IntPtr, Texture2D> _loadedTextures;
private int _textureId;
private IntPtr? _fontTextureId;
int _textureId;
IntPtr? _fontTextureId;
// Input
private int _scrollWheelValue;
int _scrollWheelValue;
private List<int> _keys = new List<int>();
List<int> _keys = new List<int>();
public ImGuiRenderer( Game game )
{
unsafe { _vertexDeclarationSize = sizeof( ImDrawVert ); }
_vertexDeclaration = new VertexDeclaration(
_vertexDeclarationSize,
// Position
new VertexElement( 0, VertexElementFormat.Vector2, VertexElementUsage.Position, 0 ),
// UV
new VertexElement( 8, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0 ),
// Color
new VertexElement( 16, VertexElementFormat.Color, VertexElementUsage.Color, 0 )
);
var context = ImGui.CreateContext();
ImGui.SetCurrentContext( context );
_game = game ?? throw new ArgumentNullException(nameof(game));
_graphicsDevice = game.GraphicsDevice;
_loadedTextures = new Dictionary<IntPtr, Texture2D>();
_rasterizerState = new RasterizerState()
@ -59,7 +67,7 @@ namespace ImGuiNET.SampleProgram.XNA
SlopeScaleDepthBias = 0
};
SetupInput();
setupInput();
}
#region ImGuiRenderer
@ -67,7 +75,7 @@ namespace ImGuiNET.SampleProgram.XNA
/// <summary>
/// Creates a texture and loads the font data from ImGui. Should be called when the <see cref="GraphicsDevice" /> is initialized but before any rendering is done
/// </summary>
public virtual unsafe void RebuildFontAtlas()
public unsafe void rebuildFontAtlas()
{
// Get font texture from ImGui
var io = ImGui.GetIO();
@ -75,17 +83,18 @@ namespace ImGuiNET.SampleProgram.XNA
// Copy the data to a managed array
var pixels = new byte[width * height * bytesPerPixel];
unsafe { Marshal.Copy(new IntPtr(pixelData), pixels, 0, pixels.Length); }
Marshal.Copy( new IntPtr( pixelData ), pixels, 0, pixels.Length );
// Create and register the texture as an XNA texture
var tex2d = new Texture2D(_graphicsDevice, width, height, false, SurfaceFormat.Color);
var tex2d = new Texture2D( Core.graphicsDevice, width, height, false, SurfaceFormat.Color );
tex2d.SetData( pixels );
// Should a texture already have been build previously, unbind it first so it can be deallocated
if (_fontTextureId.HasValue) UnbindTexture(_fontTextureId.Value);
// Should a texture already have been built previously, unbind it first so it can be deallocated
if( _fontTextureId.HasValue )
unbindTexture( _fontTextureId.Value );
// Bind the new texture to an ImGui-friendly id
_fontTextureId = BindTexture(tex2d);
_fontTextureId = bindTexture( tex2d );
// Let ImGui know where to find the texture
io.Fonts.SetTexID( _fontTextureId.Value );
@ -95,19 +104,17 @@ namespace ImGuiNET.SampleProgram.XNA
/// <summary>
/// Creates a pointer to a texture, which can be passed through ImGui calls such as <see cref="ImGui.Image" />. That pointer is then used by ImGui to let us know what texture to draw
/// </summary>
public virtual IntPtr BindTexture(Texture2D texture)
public IntPtr bindTexture( Texture2D texture )
{
var id = new IntPtr( _textureId++ );
_loadedTextures.Add( id, texture );
return id;
}
/// <summary>
/// Removes a previously created texture pointer, releasing its reference and allowing it to be deallocated
/// </summary>
public virtual void UnbindTexture(IntPtr textureId)
public void unbindTexture( IntPtr textureId )
{
_loadedTextures.Remove( textureId );
}
@ -115,21 +122,20 @@ namespace ImGuiNET.SampleProgram.XNA
/// <summary>
/// Sets up ImGui for a new frame, should be called at frame start
/// </summary>
public virtual void BeforeLayout(float deltaTime)
public void beforeLayout( float deltaTime )
{
ImGui.GetIO().DeltaTime = deltaTime;
UpdateInput();
updateInput();
ImGui.NewFrame();
}
/// <summary>
/// Asks ImGui for the generated geometry data and sends it to the graphics pipeline, should be called after the UI is drawn using ImGui.** calls
/// </summary>
public virtual void AfterLayout()
public void afterLayout()
{
ImGui.Render();
unsafe { RenderDrawData(ImGui.GetDrawData()); }
unsafe { renderDrawData( ImGui.GetDrawData() ); }
}
#endregion ImGuiRenderer
@ -139,7 +145,7 @@ namespace ImGuiNET.SampleProgram.XNA
/// <summary>
/// Maps ImGui keys to XNA keys. We use this later on to tell ImGui what keys were pressed
/// </summary>
protected virtual void SetupInput()
void setupInput()
{
var io = ImGui.GetIO();
@ -188,9 +194,9 @@ namespace ImGuiNET.SampleProgram.XNA
/// <summary>
/// Updates the <see cref="Effect" /> to the current matrices and texture
/// </summary>
protected virtual Effect UpdateEffect(Texture2D texture)
Effect updateEffect( Texture2D texture )
{
_effect = _effect ?? new BasicEffect(_graphicsDevice);
_effect = _effect ?? new BasicEffect( Core.graphicsDevice );
var io = ImGui.GetIO();
@ -215,7 +221,7 @@ namespace ImGuiNET.SampleProgram.XNA
/// <summary>
/// Sends XNA input state to ImGui
/// </summary>
protected virtual void UpdateInput()
void updateInput()
{
var io = ImGui.GetIO();
@ -232,7 +238,7 @@ namespace ImGuiNET.SampleProgram.XNA
io.KeyAlt = keyboard.IsKeyDown( Keys.LeftAlt ) || keyboard.IsKeyDown( Keys.RightAlt );
io.KeySuper = keyboard.IsKeyDown( Keys.LeftWindows ) || keyboard.IsKeyDown( Keys.RightWindows );
io.DisplaySize = new System.Numerics.Vector2(_graphicsDevice.PresentationParameters.BackBufferWidth, _graphicsDevice.PresentationParameters.BackBufferHeight);
io.DisplaySize = new System.Numerics.Vector2( Core.graphicsDevice.PresentationParameters.BackBufferWidth, Core.graphicsDevice.PresentationParameters.BackBufferHeight );
io.DisplayFramebufferScale = new System.Numerics.Vector2( 1f, 1f );
io.MousePos = new System.Numerics.Vector2( mouse.X, mouse.Y );
@ -253,33 +259,32 @@ namespace ImGuiNET.SampleProgram.XNA
/// <summary>
/// Gets the geometry as set up by ImGui and sends it to the graphics device
/// </summary>
private void RenderDrawData(ImDrawDataPtr drawData)
void renderDrawData( ImDrawDataPtr drawData )
{
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers
var lastViewport = _graphicsDevice.Viewport;
var lastScissorBox = _graphicsDevice.ScissorRectangle;
var lastViewport = Core.graphicsDevice.Viewport;
var lastScissorBox = Core.graphicsDevice.ScissorRectangle;
_graphicsDevice.BlendFactor = Color.White;
_graphicsDevice.BlendState = BlendState.NonPremultiplied;
_graphicsDevice.RasterizerState = _rasterizerState;
_graphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
Core.graphicsDevice.BlendFactor = Color.White;
Core.graphicsDevice.BlendState = BlendState.NonPremultiplied;
Core.graphicsDevice.RasterizerState = _rasterizerState;
Core.graphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
drawData.ScaleClipRects( ImGui.GetIO().DisplayFramebufferScale );
// Setup projection
_graphicsDevice.Viewport = new Viewport(0, 0, _graphicsDevice.PresentationParameters.BackBufferWidth, _graphicsDevice.PresentationParameters.BackBufferHeight);
Core.graphicsDevice.Viewport = new Viewport( 0, 0, Core.graphicsDevice.PresentationParameters.BackBufferWidth, Core.graphicsDevice.PresentationParameters.BackBufferHeight );
UpdateBuffers(drawData);
RenderCommandLists(drawData);
updateBuffers( drawData );
renderCommandLists( drawData );
// Restore modified state
_graphicsDevice.Viewport = lastViewport;
_graphicsDevice.ScissorRectangle = lastScissorBox;
Core.graphicsDevice.Viewport = lastViewport;
Core.graphicsDevice.ScissorRectangle = lastScissorBox;
}
private unsafe void UpdateBuffers(ImDrawDataPtr drawData)
unsafe void updateBuffers( ImDrawDataPtr drawData )
{
if( drawData.TotalVtxCount == 0 )
{
@ -292,8 +297,8 @@ namespace ImGuiNET.SampleProgram.XNA
_vertexBuffer?.Dispose();
_vertexBufferSize = (int)( drawData.TotalVtxCount * 1.5f );
_vertexBuffer = new VertexBuffer(_graphicsDevice, DrawVertDeclaration.Declaration, _vertexBufferSize, BufferUsage.None);
_vertexData = new byte[_vertexBufferSize * DrawVertDeclaration.Size];
_vertexBuffer = new VertexBuffer( Core.graphicsDevice, _vertexDeclaration, _vertexBufferSize, BufferUsage.None );
_vertexData = new byte[_vertexBufferSize * _vertexDeclarationSize];
}
if( drawData.TotalIdxCount > _indexBufferSize )
@ -301,7 +306,7 @@ namespace ImGuiNET.SampleProgram.XNA
_indexBuffer?.Dispose();
_indexBufferSize = (int)( drawData.TotalIdxCount * 1.5f );
_indexBuffer = new IndexBuffer(_graphicsDevice, IndexElementSize.SixteenBits, _indexBufferSize, BufferUsage.None);
_indexBuffer = new IndexBuffer( Core.graphicsDevice, IndexElementSize.SixteenBits, _indexBufferSize, BufferUsage.None );
_indexData = new byte[_indexBufferSize * sizeof( ushort )];
}
@ -309,14 +314,14 @@ namespace ImGuiNET.SampleProgram.XNA
int vtxOffset = 0;
int idxOffset = 0;
for (int n = 0; n < drawData.CmdListsCount; n++)
for( var n = 0; n < drawData.CmdListsCount; n++ )
{
ImDrawListPtr cmdList = drawData.CmdListsRange[n];
var cmdList = drawData.CmdListsRange[n];
fixed (void* vtxDstPtr = &_vertexData[vtxOffset * DrawVertDeclaration.Size])
fixed ( void* vtxDstPtr = &_vertexData[vtxOffset * _vertexDeclarationSize] )
fixed ( void* idxDstPtr = &_indexData[idxOffset * sizeof( ushort )] )
{
Buffer.MemoryCopy((void*)cmdList.VtxBuffer.Data, vtxDstPtr, _vertexData.Length, cmdList.VtxBuffer.Size * DrawVertDeclaration.Size);
Buffer.MemoryCopy( (void*)cmdList.VtxBuffer.Data, vtxDstPtr, _vertexData.Length, cmdList.VtxBuffer.Size * _vertexDeclarationSize );
Buffer.MemoryCopy( (void*)cmdList.IdxBuffer.Data, idxDstPtr, _indexData.Length, cmdList.IdxBuffer.Size * sizeof( ushort ) );
}
@ -325,46 +330,43 @@ namespace ImGuiNET.SampleProgram.XNA
}
// Copy the managed byte arrays to the gpu vertex- and index buffers
_vertexBuffer.SetData(_vertexData, 0, drawData.TotalVtxCount * DrawVertDeclaration.Size);
_vertexBuffer.SetData( _vertexData, 0, drawData.TotalVtxCount * _vertexDeclarationSize );
_indexBuffer.SetData( _indexData, 0, drawData.TotalIdxCount * sizeof( ushort ) );
}
private unsafe void RenderCommandLists(ImDrawDataPtr drawData)
unsafe void renderCommandLists( ImDrawDataPtr drawData )
{
_graphicsDevice.SetVertexBuffer(_vertexBuffer);
_graphicsDevice.Indices = _indexBuffer;
Core.graphicsDevice.SetVertexBuffer( _vertexBuffer );
Core.graphicsDevice.Indices = _indexBuffer;
int vtxOffset = 0;
int idxOffset = 0;
for( int n = 0; n < drawData.CmdListsCount; n++ )
{
ImDrawListPtr cmdList = drawData.CmdListsRange[n];
var cmdList = drawData.CmdListsRange[n];
for( int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++ )
{
ImDrawCmdPtr drawCmd = cmdList.CmdBuffer[cmdi];
var drawCmd = cmdList.CmdBuffer[cmdi];
if( !_loadedTextures.ContainsKey( drawCmd.TextureId ) )
{
throw new InvalidOperationException( $"Could not find a texture with id '{drawCmd.TextureId}', please check your bindings" );
}
_graphicsDevice.ScissorRectangle = new Rectangle(
Core.graphicsDevice.ScissorRectangle = new Rectangle(
(int)drawCmd.ClipRect.X,
(int)drawCmd.ClipRect.Y,
(int)( drawCmd.ClipRect.Z - drawCmd.ClipRect.X ),
(int)( drawCmd.ClipRect.W - drawCmd.ClipRect.Y )
);
var effect = UpdateEffect(_loadedTextures[drawCmd.TextureId]);
var effect = updateEffect( _loadedTextures[drawCmd.TextureId] );
foreach( var pass in effect.CurrentTechnique.Passes )
{
pass.Apply();
#pragma warning disable CS0618 // // FNA does not expose an alternative method.
_graphicsDevice.DrawIndexedPrimitives(
Core.graphicsDevice.DrawIndexedPrimitives(
primitiveType: PrimitiveType.TriangleList,
baseVertex: vtxOffset,
minVertexIndex: 0,