mirror of
https://github.com/prime31/FNA-VSCode-Template.git
synced 2025-10-31 21:50:44 +07:00
switch to new ImGuiManager
This commit is contained in:
parent
ba222d1dc9
commit
ef9814253c
5
.vscode/tasks.json
vendored
5
.vscode/tasks.json
vendored
@ -97,10 +97,7 @@
|
|||||||
"label": "Build Content",
|
"label": "Build Content",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"group": "build",
|
"group": "build",
|
||||||
"command": "mono /Applications/Pipeline.app/Contents/MonoBundle/MGCB.exe /@:Content.mgcb",
|
"command": "msbuild /t:BuildContent",
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}/project_name/CompiledContent"
|
|
||||||
},
|
|
||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -19,15 +19,17 @@ namespace project_name
|
|||||||
var newScene = new Scene();
|
var newScene = new Scene();
|
||||||
newScene.addRenderer(new DefaultRenderer());
|
newScene.addRenderer(new DefaultRenderer());
|
||||||
|
|
||||||
// optionally render Nez in an ImGui window
|
|
||||||
newScene.finalRenderDelegate = new ImGuiFinalRenderDelegate();
|
|
||||||
|
|
||||||
var logo = newScene.content.Load<Microsoft.Xna.Framework.Graphics.Texture2D>("nez-logo-black");
|
var logo = newScene.content.Load<Microsoft.Xna.Framework.Graphics.Texture2D>("nez-logo-black");
|
||||||
newScene.createEntity("logo")
|
newScene.createEntity("logo")
|
||||||
.setPosition(Screen.center)
|
.setPosition(Screen.center)
|
||||||
.addComponent(new Nez.Sprites.Sprite(logo));
|
.addComponent(new Nez.Sprites.Sprite(logo));
|
||||||
|
|
||||||
scene = newScene;
|
scene = newScene;
|
||||||
|
|
||||||
|
// optionally render Nez in an ImGui window
|
||||||
|
var imGuiManager = new ImGuiManager();
|
||||||
|
Core.registerGlobalManager( imGuiManager );
|
||||||
|
imGuiManager.setEnabled( true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,95 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
using ImGuiNET;
|
|
||||||
using Microsoft.Xna.Framework;
|
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
|
||||||
|
|
||||||
namespace Nez
|
|
||||||
{
|
|
||||||
public class ImGuiFinalRenderDelegate : IFinalRenderDelegate
|
|
||||||
{
|
|
||||||
public Scene scene { get; set; }
|
|
||||||
|
|
||||||
ImGuiRenderer _imGuiRenderer;
|
|
||||||
RenderTarget2D _lastRenderTarget;
|
|
||||||
IntPtr _renderTargetId;
|
|
||||||
|
|
||||||
public ImGuiFinalRenderDelegate()
|
|
||||||
{
|
|
||||||
_imGuiRenderer = new ImGuiRenderer( Core.instance );
|
|
||||||
_imGuiRenderer.rebuildFontAtlas();
|
|
||||||
ImGui.GetIO().ConfigWindowsMoveFromTitleBarOnly = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Console.Command( "toggle-imgui", "Toggles the Dear ImGui renderer" )]
|
|
||||||
static void toggleImGui()
|
|
||||||
{
|
|
||||||
if( Core.scene.finalRenderDelegate == null )
|
|
||||||
Core.scene.finalRenderDelegate = new ImGuiFinalRenderDelegate();
|
|
||||||
else
|
|
||||||
Core.scene.finalRenderDelegate = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void layoutGui()
|
|
||||||
{
|
|
||||||
ImGui.ShowDemoWindow();
|
|
||||||
|
|
||||||
var maxSize = new System.Numerics.Vector2( _lastRenderTarget.Width, _lastRenderTarget.Height );
|
|
||||||
var minSize = maxSize / 4;
|
|
||||||
maxSize *= 4;
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
ImGui.SetNextWindowSizeConstraints( minSize, maxSize, data =>
|
|
||||||
{
|
|
||||||
var size = ( *data ).CurrentSize;
|
|
||||||
var ratio = size.X / _lastRenderTarget.Width;
|
|
||||||
( *data ).DesiredSize.Y = ratio * _lastRenderTarget.Height;
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.SetNextWindowPos( new System.Numerics.Vector2( 0, 0 ), ImGuiCond.FirstUseEver );
|
|
||||||
ImGui.PushStyleVar( ImGuiStyleVar.WindowPadding, new System.Numerics.Vector2( 0, 0 ) );
|
|
||||||
ImGui.Begin( "Game Window" );
|
|
||||||
|
|
||||||
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()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public void onSceneBackBufferSizeChanged( int newWidth, int newHeight )
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public void unload()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
221
project_name/ImGui/ImGuiManager.cs
Normal file
221
project_name/ImGui/ImGuiManager.cs
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
using Nez;
|
||||||
|
using ImGuiNET;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Nez
|
||||||
|
{
|
||||||
|
public class ImGuiManager : GlobalManager, IFinalRenderDelegate, IDisposable
|
||||||
|
{
|
||||||
|
public Scene scene { get; set; }
|
||||||
|
public List<Action> drawCommands = new List<Action>();
|
||||||
|
public ImGuiRenderer renderer { get; private set; }
|
||||||
|
|
||||||
|
RenderTarget2D _lastRenderTarget;
|
||||||
|
IntPtr _renderTargetId;
|
||||||
|
bool _isGameWindowFocused;
|
||||||
|
|
||||||
|
public ImGuiManager( string pathToFontFile, float fontSizePixels )
|
||||||
|
{
|
||||||
|
renderer = new ImGuiRenderer( Core.instance );
|
||||||
|
|
||||||
|
if( pathToFontFile != null )
|
||||||
|
ImGui.GetIO().Fonts.AddFontFromFileTTF( pathToFontFile, fontSizePixels );
|
||||||
|
|
||||||
|
renderer.rebuildFontAtlas();
|
||||||
|
|
||||||
|
Core.emitter.addObserver( CoreEvents.SceneChanged, onSceneChanged );
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImGuiManager() : this( null, -1 )
|
||||||
|
{}
|
||||||
|
|
||||||
|
void onSceneChanged()
|
||||||
|
{
|
||||||
|
// when the Scene changes we need to rewire ourselves up as the IFinalRenderDelegate in the new Scene
|
||||||
|
// if we were previously enabled
|
||||||
|
drawCommands.Clear();
|
||||||
|
if( enabled )
|
||||||
|
onEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// this is where we issue any and all ImGui commands to be drawn
|
||||||
|
/// </summary>
|
||||||
|
void layoutGui()
|
||||||
|
{
|
||||||
|
for( var i = drawCommands.Count - 1; i >= 0; i-- )
|
||||||
|
drawCommands[i]();
|
||||||
|
|
||||||
|
ImGui.ShowDemoWindow();
|
||||||
|
|
||||||
|
if( _lastRenderTarget == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
var maxSize = new System.Numerics.Vector2( _lastRenderTarget.Width, _lastRenderTarget.Height );
|
||||||
|
var minSize = maxSize / 4;
|
||||||
|
maxSize *= 4;
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
ImGui.SetNextWindowSizeConstraints( minSize, maxSize, data =>
|
||||||
|
{
|
||||||
|
var size = ( *data ).CurrentSize;
|
||||||
|
var ratio = size.X / _lastRenderTarget.Width;
|
||||||
|
( *data ).DesiredSize.Y = ratio * _lastRenderTarget.Height;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.SetNextWindowPos( new System.Numerics.Vector2( 0, 0 ), ImGuiCond.FirstUseEver );
|
||||||
|
ImGui.PushStyleVar( ImGuiStyleVar.WindowPadding, new System.Numerics.Vector2( 0, 0 ) );
|
||||||
|
ImGui.Begin( "Game Window" );
|
||||||
|
_isGameWindowFocused = ImGui.IsWindowFocused();
|
||||||
|
|
||||||
|
//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 Public API
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// registers an Action that will be called and any ImGui drawing can be done in it
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="drawCommand"></param>
|
||||||
|
public void registerDrawCommand( Action drawCommand )
|
||||||
|
{
|
||||||
|
drawCommands.Add( drawCommand );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// removes the Action from the draw commands
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="drawCommand"></param>
|
||||||
|
public void unregisterDrawCommand( Action drawCommand )
|
||||||
|
{
|
||||||
|
drawCommands.Remove( drawCommand );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// adds the font to the atlas and regenerates it
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pathToFontFile"></param>
|
||||||
|
/// <param name="fontSizePixels"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public ImFontPtr addFontAndRegenerateAtlas( string pathToFontFile, float fontSizePixels )
|
||||||
|
{
|
||||||
|
var fontPtr = ImGui.GetIO().Fonts.AddFontFromFileTTF( pathToFontFile, fontSizePixels );
|
||||||
|
renderer.rebuildFontAtlas();
|
||||||
|
return fontPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region GlobalManager Lifecycle
|
||||||
|
|
||||||
|
public override void onEnabled()
|
||||||
|
{
|
||||||
|
Core.scene.finalRenderDelegate = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void onDisabled()
|
||||||
|
{
|
||||||
|
Core.scene.finalRenderDelegate = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void update()
|
||||||
|
{
|
||||||
|
renderer.beforeLayout( Time.deltaTime );
|
||||||
|
layoutGui();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#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 )
|
||||||
|
renderer.unbindTexture( _renderTargetId );
|
||||||
|
|
||||||
|
// bind the new texture
|
||||||
|
_lastRenderTarget = source;
|
||||||
|
_renderTargetId = renderer.bindTexture( source );
|
||||||
|
}
|
||||||
|
|
||||||
|
Core.graphicsDevice.setRenderTarget( finalRenderTarget );
|
||||||
|
Core.graphicsDevice.Clear( letterboxColor );
|
||||||
|
|
||||||
|
renderer.afterLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onAddedToScene()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public void onSceneBackBufferSizeChanged( int newWidth, int newHeight )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public void unload()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IDisposable Support
|
||||||
|
|
||||||
|
bool _isDisposed = false; // To detect redundant calls
|
||||||
|
|
||||||
|
protected virtual void Dispose( bool disposing )
|
||||||
|
{
|
||||||
|
if( !_isDisposed )
|
||||||
|
{
|
||||||
|
if( disposing )
|
||||||
|
{
|
||||||
|
Core.emitter.removeObserver( CoreEvents.SceneChanged, onSceneChanged );
|
||||||
|
}
|
||||||
|
|
||||||
|
_isDisposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IDisposable.Dispose()
|
||||||
|
{
|
||||||
|
Dispose( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
[Console.Command( "toggle-imgui", "Toggles the Dear ImGui renderer" )]
|
||||||
|
static void toggleImGui()
|
||||||
|
{
|
||||||
|
// install the service if it isnt already there
|
||||||
|
var service = Core.getGlobalManager<ImGuiManager>();
|
||||||
|
if( service == null )
|
||||||
|
{
|
||||||
|
service = new ImGuiManager();
|
||||||
|
Core.registerGlobalManager( service );
|
||||||
|
}
|
||||||
|
|
||||||
|
service.setEnabled( !service.enabled );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,10 +9,12 @@ using System.Runtime.InteropServices;
|
|||||||
namespace ImGuiNET
|
namespace ImGuiNET
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ImGui renderer for use with XNA-likes (FNA and MonoGame)
|
/// ImGui renderer for use with XNA-likes (FNA & MonoGame)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ImGuiRenderer
|
public class ImGuiRenderer
|
||||||
{
|
{
|
||||||
|
public ImFontPtr defaultFontPtr { get; private set; }
|
||||||
|
|
||||||
// Graphics
|
// Graphics
|
||||||
BasicEffect _effect;
|
BasicEffect _effect;
|
||||||
RasterizerState _rasterizerState;
|
RasterizerState _rasterizerState;
|
||||||
@ -29,7 +31,7 @@ namespace ImGuiNET
|
|||||||
int _indexBufferSize;
|
int _indexBufferSize;
|
||||||
|
|
||||||
// Textures
|
// Textures
|
||||||
Dictionary<IntPtr, Texture2D> _loadedTextures;
|
Dictionary<IntPtr, Texture2D> _loadedTextures = new Dictionary<IntPtr, Texture2D>();
|
||||||
|
|
||||||
int _textureId;
|
int _textureId;
|
||||||
IntPtr? _fontTextureId;
|
IntPtr? _fontTextureId;
|
||||||
@ -52,10 +54,7 @@ namespace ImGuiNET
|
|||||||
new VertexElement( 16, VertexElementFormat.Color, VertexElementUsage.Color, 0 )
|
new VertexElement( 16, VertexElementFormat.Color, VertexElementUsage.Color, 0 )
|
||||||
);
|
);
|
||||||
|
|
||||||
var context = ImGui.CreateContext();
|
ImGui.SetCurrentContext( ImGui.CreateContext() );
|
||||||
ImGui.SetCurrentContext( context );
|
|
||||||
|
|
||||||
_loadedTextures = new Dictionary<IntPtr, Texture2D>();
|
|
||||||
|
|
||||||
_rasterizerState = new RasterizerState()
|
_rasterizerState = new RasterizerState()
|
||||||
{
|
{
|
||||||
@ -79,6 +78,9 @@ namespace ImGuiNET
|
|||||||
{
|
{
|
||||||
// Get font texture from ImGui
|
// Get font texture from ImGui
|
||||||
var io = ImGui.GetIO();
|
var io = ImGui.GetIO();
|
||||||
|
|
||||||
|
defaultFontPtr = ImGui.GetIO().Fonts.AddFontDefault();
|
||||||
|
|
||||||
io.Fonts.GetTexDataAsRGBA32( out byte* pixelData, out int width, out int height, out int bytesPerPixel );
|
io.Fonts.GetTexDataAsRGBA32( out byte* pixelData, out int width, out int height, out int bytesPerPixel );
|
||||||
|
|
||||||
// Copy the data to a managed array
|
// Copy the data to a managed array
|
||||||
@ -187,8 +189,6 @@ namespace ImGuiNET
|
|||||||
ImGui.GetIO().AddInputCharacter( c );
|
ImGui.GetIO().AddInputCharacter( c );
|
||||||
};
|
};
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
ImGui.GetIO().Fonts.AddFontDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user