Skip to content

MonoGame & FNA sample upgrade #518

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 76 additions & 29 deletions src/ImGui.NET.SampleProgram.XNA/ImGuiRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ namespace ImGuiNET.SampleProgram.XNA
/// <summary>
/// ImGui renderer for use with XNA-likes (FNA & MonoGame)
/// </summary>
public class ImGuiRenderer
public class ImGuiRenderer : IDisposable
{
private Game _game;
private readonly Game _game;

// Graphics
private GraphicsDevice _graphicsDevice;
private readonly GraphicsDevice _graphicsDevice;

private BasicEffect _effect;
private RasterizerState _rasterizerState;
private readonly RasterizerState _rasterizerState;

private byte[] _vertexData;
private VertexBuffer _vertexBuffer;
Expand All @@ -29,7 +29,7 @@ public class ImGuiRenderer
private int _indexBufferSize;

// Textures
private Dictionary<IntPtr, Texture2D> _loadedTextures;
private readonly Dictionary<IntPtr, Texture2D> _loadedTextures;

private int _textureId;
private IntPtr? _fontTextureId;
Expand All @@ -38,7 +38,9 @@ public class ImGuiRenderer
private int _scrollWheelValue;
private int _horizontalScrollWheelValue;
private readonly float WHEEL_DELTA = 120;
private Keys[] _allKeys = Enum.GetValues<Keys>();
private readonly Keys[] _allKeys = Enum.GetValues<Keys>();

private bool _isDisposed;

public ImGuiRenderer(Game game)
{
Expand All @@ -63,6 +65,12 @@ public ImGuiRenderer(Game game)
SetupInput();
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

#region ImGuiRenderer

/// <summary>
Expand All @@ -81,6 +89,8 @@ public virtual unsafe void RebuildFontAtlas()
// Create and register the texture as an XNA texture
var tex2d = new Texture2D(_graphicsDevice, width, height, false, SurfaceFormat.Color);
tex2d.SetData(pixels);
tex2d.Name = "ImGui font atlas";
tex2d.Tag = "ImGui";

// Should a texture already have been build previously, unbind it first so it can be deallocated
if (_fontTextureId.HasValue) UnbindTexture(_fontTextureId.Value);
Expand Down Expand Up @@ -120,6 +130,9 @@ public virtual void BeforeLayout(GameTime gameTime)
{
ImGui.GetIO().DeltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

// Enable docking
ImGui.GetIO().ConfigFlags |= ImGuiConfigFlags.DockingEnable;

UpdateInput();

ImGui.NewFrame();
Expand All @@ -144,24 +157,12 @@ public virtual void AfterLayout()
/// </summary>
protected virtual void SetupInput()
{
var io = ImGui.GetIO();

// MonoGame-specific //////////////////////
_game.Window.TextInput += (s, a) =>
{
if (a.Character == '\t') return;
io.AddInputCharacter(a.Character);
};

_game.Window.TextInput += OnTextInput;
///////////////////////////////////////////

// FNA-specific ///////////////////////////
//TextInputEXT.TextInput += c =>
//{
// if (c == '\t') return;

// ImGui.GetIO().AddInputCharacter(c);
//};
// TextInputEXT.TextInput += OnTextInput;
///////////////////////////////////////////
}

Expand All @@ -170,7 +171,7 @@ protected virtual void SetupInput()
/// </summary>
protected virtual Effect UpdateEffect(Texture2D texture)
{
_effect = _effect ?? new BasicEffect(_graphicsDevice);
_effect ??= new BasicEffect(_graphicsDevice);

var io = ImGui.GetIO();

Expand All @@ -180,6 +181,8 @@ protected virtual Effect UpdateEffect(Texture2D texture)
_effect.TextureEnabled = true;
_effect.Texture = texture;
_effect.VertexColorEnabled = true;
_effect.Name = $"{texture.Name}_effect";
_effect.Tag = "ImGui";

return _effect;
}
Expand All @@ -190,7 +193,7 @@ protected virtual Effect UpdateEffect(Texture2D texture)
protected virtual void UpdateInput()
{
if (!_game.IsActive) return;

var io = ImGui.GetIO();

var mouse = Mouse.GetState();
Expand All @@ -202,6 +205,7 @@ protected virtual void UpdateInput()
io.AddMouseButtonEvent(3, mouse.XButton1 == ButtonState.Pressed);
io.AddMouseButtonEvent(4, mouse.XButton2 == ButtonState.Pressed);

// FNA-specific information. FNA does not have horizontal scroll wheel support. So you need to set 0f for horizontal scroll wheel value.
io.AddMouseWheelEvent(
(mouse.HorizontalScrollWheelValue - _horizontalScrollWheelValue) / WHEEL_DELTA,
(mouse.ScrollWheelValue - _scrollWheelValue) / WHEEL_DELTA);
Expand All @@ -220,11 +224,11 @@ protected virtual void UpdateInput()
io.DisplayFramebufferScale = new System.Numerics.Vector2(1f, 1f);
}

private bool TryMapKeys(Keys key, out ImGuiKey imguikey)
private static bool TryMapKeys(Keys key, out ImGuiKey imguikey)
{
//Special case not handed in the switch...
//If the actual key we put in is "None", return none and true.
//otherwise, return none and false.
// Special case not handed in the switch...
// If the actual key we put in is "None", return none and true.
// otherwise, return none and false.
if (key == Keys.None)
{
imguikey = ImGuiKey.None;
Expand Down Expand Up @@ -390,12 +394,12 @@ private unsafe void RenderCommandLists(ImDrawDataPtr drawData)
{
ImDrawCmdPtr drawCmd = cmdList.CmdBuffer[cmdi];

if (drawCmd.ElemCount == 0)
if (drawCmd.ElemCount == 0)
{
continue;
}

if (!_loadedTextures.ContainsKey(drawCmd.TextureId))
if (!_loadedTextures.TryGetValue(drawCmd.TextureId, out Texture2D value))
{
throw new InvalidOperationException($"Could not find a texture with id '{drawCmd.TextureId}', please check your bindings");
}
Expand All @@ -407,7 +411,7 @@ private unsafe void RenderCommandLists(ImDrawDataPtr drawData)
(int)(drawCmd.ClipRect.W - drawCmd.ClipRect.Y)
);

var effect = UpdateEffect(_loadedTextures[drawCmd.TextureId]);
var effect = UpdateEffect(value);

foreach (var pass in effect.CurrentTechnique.Passes)
{
Expand All @@ -431,6 +435,49 @@ private unsafe void RenderCommandLists(ImDrawDataPtr drawData)
}
}

// MonoGame-specific //////////////////////
private void OnTextInput(object s, TextInputEventArgs a)
{
if (a.Character == '\t') return;
ImGui.GetIO().AddInputCharacter(a.Character);
}
///////////////////////////////////////////

// FNA-specific ///////////////////////////
// private void OnTextInput(char c)
// {
// if (c == '\t') return;
// ImGui.GetIO().AddInputCharacter(c);
// }
///////////////////////////////////////////

protected virtual void Dispose(bool disposing)
{
if (_isDisposed) return;

if (disposing)
{
_vertexBuffer?.Dispose();
_indexBuffer?.Dispose();
_effect?.Dispose();

foreach (var texture in _loadedTextures)
{
texture.Value?.Dispose();
}

// MonoGame-specific //////////////////////
_game.Window.TextInput -= OnTextInput;
///////////////////////////////////////////

// FNA-specific ///////////////////////////
// TextInputEXT.TextInput -= OnTextInput;
///////////////////////////////////////////
}

_isDisposed = true;
}

#endregion Internals
}
}
9 changes: 8 additions & 1 deletion src/ImGui.NET.SampleProgram.XNA/SampleGame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public SampleGame()
_graphics = new GraphicsDeviceManager(this);
_graphics.PreferredBackBufferWidth = 1024;
_graphics.PreferredBackBufferHeight = 768;
_graphics.PreferMultiSampling = true;
_graphics.PreferMultiSampling = false;

IsMouseVisible = true;
}
Expand Down Expand Up @@ -52,6 +52,13 @@ protected override void LoadContent()
base.LoadContent();
}

protected override void UnloadContent()
{
_imGuiRenderer.Dispose();
Content.Unload();
base.UnloadContent();
}

protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(new Color(clear_color.X, clear_color.Y, clear_color.Z));
Expand Down