From ed4a035574eacdab027f90aacf40c92e15b72c81 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 12 Feb 2019 20:02:04 -0800 Subject: [PATCH 01/24] ImGui up and running --- .gitignore | 1 + getFNA.sh | 50 +++++++++++- .../ImGui/ImGuiFinalRenderDelegate.cs | 78 +++++++++++++++++++ project_name/project_name.csproj | 24 +++++- 4 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 project_name/ImGui/ImGuiFinalRenderDelegate.cs diff --git a/.gitignore b/.gitignore index 0cb3aef..bf09f5c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_Store FNA/ +ImGui.NET/ fnalibs/ project_name/bin project_name/obj diff --git a/getFNA.sh b/getFNA.sh index 34abdb6..c0a480b 100755 --- a/getFNA.sh +++ b/getFNA.sh @@ -62,6 +62,35 @@ function updateFNA() fi } + +# Clones FNA from the git master branch +function downloadImGui() +{ + checkGit + echo "Downloading ImGui..." + git -C $MY_DIR clone https://github.com/mellinoe/ImGui.NET.git --recursive + if [ $? -eq 0 ]; then + echo "Finished downloading!\n" + else + echo >&2 "ERROR: Unable to download successfully. Maybe try again later?" + fi +} + +# Pulls FNA from the git master branch +function updateImGui() +{ + checkGit + echo "Updating to the latest git version of ImGui.NET..." + git -C "$MY_DIR/ImGui.NET" pull --recurse-submodules + if [ $? -eq 0 ]; then + echo "Finished updating!\n" + else + echo >&2 "ERROR: Unable to update." + exit 1 + fi +} + + # Downloads and extracts prepackaged archive of native libraries ("fnalibs") function getLibs() { @@ -114,17 +143,36 @@ if [[ $shouldDownloadLibs =~ ^[Yy]$ ]]; then getLibs fi +# Dear ImGui +if [ ! -d "$MY_DIR/ImGui.NET" ]; then + read -p "Download ImGui.NET (y/n)? " shouldDownload + if [[ $shouldDownload =~ ^[Yy]$ ]]; then + downloadImGui + fi +else + read -p "Update ImGui.NET (y/n)? " shouldUpdate + if [[ $shouldUpdate =~ ^[Yy]$ ]]; then + updateImGui + fi +fi + # install t4 engine installT4 -# Rename project + +# Only proceed from here if we have not yet renamed the project if [ ! -d "$MY_DIR/project_name" ]; then # old project_name folder already renamed so we are all done here exit 1 fi +# copy over ImGui files before renaming the project +echo "Copying ImGui renderer to project..." +cp "$MY_DIR/ImGui.NET/src/ImGui.NET.SampleProgram.XNA/DrawVertDeclaration.cs" "$MY_DIR/project_name/ImGui" +cp "$MY_DIR/ImGui.NET/src/ImGui.NET.SampleProgram.XNA/ImGuiRenderer.cs" "$MY_DIR/project_name/ImGui" +sed -i '' "s/cimgui/cimgui.dylib/g" ImGui.NET/src/ImGui.NET/Generated/ImGuiNative.gen.cs read -p "Enter the project name to use for your folder and csproj file or 'exit' to quit: " newProjectName if [[ $newProjectName = 'exit' || -z "$newProjectName" ]]; then diff --git a/project_name/ImGui/ImGuiFinalRenderDelegate.cs b/project_name/ImGui/ImGuiFinalRenderDelegate.cs new file mode 100644 index 0000000..29510c7 --- /dev/null +++ b/project_name/ImGui/ImGuiFinalRenderDelegate.cs @@ -0,0 +1,78 @@ +using System; +using System.Reflection; +using ImGuiNET; +using ImGuiNET.SampleProgram.XNA; +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() + { + var core = typeof(Core).GetField("_instance", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as Core; + _imGuiRenderer = new ImGuiRenderer(core); + _imGuiRenderer.RebuildFontAtlas(); + } + + public void handleFinalRender( 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( null ); + Core.graphicsDevice.Clear( letterboxColor ); + + + _imGuiRenderer.BeforeLayout(new GameTime(TimeSpan.FromDays(0), TimeSpan.FromMilliseconds(Time.deltaTime * 1000))); + layoutGui(); + _imGuiRenderer.AfterLayout(); + } + + void layoutGui() + { + ImGui.ShowDemoWindow(); + + var maxSize = new System.Numerics.Vector2(_lastRenderTarget.Width, _lastRenderTarget.Height); + var minSize = 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.Begin("Game Window"); + ImGui.Image(_renderTargetId, ImGui.GetContentRegionAvail()); + ImGui.End(); + } + + public void onAddedToScene() + {} + + public void onSceneBackBufferSizeChanged( int newWidth, int newHeight ) + {} + + public void unload() + {} + } +} diff --git a/project_name/project_name.csproj b/project_name/project_name.csproj index 01f3c9c..fc687f1 100644 --- a/project_name/project_name.csproj +++ b/project_name/project_name.csproj @@ -2,17 +2,19 @@ Exe - net46 + net462 false AnyCPU project_name DesktopGL + True + @@ -66,5 +68,25 @@ PreserveNewest + + + + + osx\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + osx\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + osx\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + osx\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + \ No newline at end of file From 5b29f8e3cc245fd0bd5d9effbe345175aeb49d97 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 12 Feb 2019 20:58:13 -0800 Subject: [PATCH 02/24] Visual Studio support add renderer to project --- getFNA.sh | 19 +- project_name.sln | 4 + project_name/ImGui/DrawVertDeclaration.cs | 28 ++ project_name/ImGui/ImGuiRenderer.cs | 387 ++++++++++++++++++++++ project_name/project_name.csproj | 8 +- 5 files changed, 434 insertions(+), 12 deletions(-) create mode 100644 project_name/ImGui/DrawVertDeclaration.cs create mode 100644 project_name/ImGui/ImGuiRenderer.cs diff --git a/getFNA.sh b/getFNA.sh index c0a480b..ba85897 100755 --- a/getFNA.sh +++ b/getFNA.sh @@ -68,7 +68,9 @@ function downloadImGui() { checkGit echo "Downloading ImGui..." - git -C $MY_DIR clone https://github.com/mellinoe/ImGui.NET.git --recursive + echo "Temporarily using ImGui.NET branch until ImGui.NET master is updated" + #git -C $MY_DIR clone https://github.com/mellinoe/ImGui.NET.git --recursive + git -C $MY_DIR clone -b fix-MonoGame-FNA https://github.com/prime31/ImGui.NET.git --recursive if [ $? -eq 0 ]; then echo "Finished downloading!\n" else @@ -168,12 +170,7 @@ if [ ! -d "$MY_DIR/project_name" ]; then exit 1 fi -# copy over ImGui files before renaming the project -echo "Copying ImGui renderer to project..." -cp "$MY_DIR/ImGui.NET/src/ImGui.NET.SampleProgram.XNA/DrawVertDeclaration.cs" "$MY_DIR/project_name/ImGui" -cp "$MY_DIR/ImGui.NET/src/ImGui.NET.SampleProgram.XNA/ImGuiRenderer.cs" "$MY_DIR/project_name/ImGui" -sed -i '' "s/cimgui/cimgui.dylib/g" ImGui.NET/src/ImGui.NET/Generated/ImGuiNative.gen.cs - + read -p "Enter the project name to use for your folder and csproj file or 'exit' to quit: " newProjectName if [[ $newProjectName = 'exit' || -z "$newProjectName" ]]; then exit 1 @@ -202,4 +199,10 @@ cd Nez.FNA git submodule init git submodule update -printf "\n\nManually run the following command:\n\nnuget restore Nez.FNA/Nez/Nez.sln && msbuild Nez.FNA/Nez/Nez.sln && msbuild /t:restore $newProjectName\n\n" +command -v pbcopy > /dev/null 2>&1 +if [ ! $? -eq 0 ]; then + printf "\n\nManually run the following command:\n\nnuget restore Nez.FNA/Nez/Nez.sln && msbuild Nez.FNA/Nez/Nez.sln && msbuild /t:restore $newProjectName\n\n" +else + echo "nuget restore Nez.FNA/Nez/Nez.sln && msbuild Nez.FNA/Nez/Nez.sln && msbuild /t:restore $newProjectName" | pbcopy + echo "command copied to your clipboard\n" +fi diff --git a/project_name.sln b/project_name.sln index 7d9eda8..bf0682f 100644 --- a/project_name.sln +++ b/project_name.sln @@ -39,6 +39,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FNA", "FNA\FNA.csproj", "{3 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nez.FNA", "Nez.FNA\Nez.FNA\Nez.FNA.csproj", "{11A5855C-B12C-4F8D-B935-56F3D0B671C3}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImGui.NET", "ImGui.NET\src\ImGui.NET\ImGui.NET.csproj", "{AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}" +EndProject Global GlobalSection(ProjectConfigurationPlatforms) = postSolution {8C576ECC-147D-4B4A-8EC1-56533D26A178}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -47,6 +49,8 @@ Global {35253CE1-C864-4CD3-8249-4D1319748E8F}.Debug|Any CPU.Build.0 = Debug|Any CPU {11A5855C-B12C-4F8D-B935-56F3D0B671C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {11A5855C-B12C-4F8D-B935-56F3D0B671C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Debug|Any CPU.ActiveCfg = Release|Any CPU + {AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Debug|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/project_name/ImGui/DrawVertDeclaration.cs b/project_name/ImGui/DrawVertDeclaration.cs new file mode 100644 index 0000000..276e5df --- /dev/null +++ b/project_name/ImGui/DrawVertDeclaration.cs @@ -0,0 +1,28 @@ +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) + ); + } + } +} \ No newline at end of file diff --git a/project_name/ImGui/ImGuiRenderer.cs b/project_name/ImGui/ImGuiRenderer.cs new file mode 100644 index 0000000..0c6886a --- /dev/null +++ b/project_name/ImGui/ImGuiRenderer.cs @@ -0,0 +1,387 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace ImGuiNET.SampleProgram.XNA +{ + /// + /// ImGui renderer for use with XNA-likes (FNA & MonoGame) + /// + public class ImGuiRenderer + { + private Game _game; + + // Graphics + private GraphicsDevice _graphicsDevice; + + private BasicEffect _effect; + private RasterizerState _rasterizerState; + + private byte[] _vertexData; + private VertexBuffer _vertexBuffer; + private int _vertexBufferSize; + + private byte[] _indexData; + private IndexBuffer _indexBuffer; + private int _indexBufferSize; + + // Textures + private Dictionary _loadedTextures; + + private int _textureId; + private IntPtr? _fontTextureId; + + // Input + private int _scrollWheelValue; + + private List _keys = new List(); + + public ImGuiRenderer(Game game) + { + var context = ImGui.CreateContext(); + ImGui.SetCurrentContext(context); + + _game = game ?? throw new ArgumentNullException(nameof(game)); + _graphicsDevice = game.GraphicsDevice; + + _loadedTextures = new Dictionary(); + + _rasterizerState = new RasterizerState() + { + CullMode = CullMode.None, + DepthBias = 0, + FillMode = FillMode.Solid, + MultiSampleAntiAlias = false, + ScissorTestEnable = true, + SlopeScaleDepthBias = 0 + }; + + SetupInput(); + } + + #region ImGuiRenderer + + /// + /// Creates a texture and loads the font data from ImGui. Should be called when the is initialized but before any rendering is done + /// + public virtual unsafe void RebuildFontAtlas() + { + // Get font texture from ImGui + var io = ImGui.GetIO(); + io.Fonts.GetTexDataAsRGBA32(out byte* pixelData, out int width, out int height, out int bytesPerPixel); + + // Copy the data to a managed array + var pixels = new byte[width * height * bytesPerPixel]; + unsafe { 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); + 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); + + // Bind the new texture to an ImGui-friendly id + _fontTextureId = BindTexture(tex2d); + + // Let ImGui know where to find the texture + io.Fonts.SetTexID(_fontTextureId.Value); + io.Fonts.ClearTexData(); // Clears CPU side texture data + } + + /// + /// Creates a pointer to a texture, which can be passed through ImGui calls such as . That pointer is then used by ImGui to let us know what texture to draw + /// + public virtual IntPtr BindTexture(Texture2D texture) + { + var id = new IntPtr(_textureId++); + + _loadedTextures.Add(id, texture); + + return id; + } + + /// + /// Removes a previously created texture pointer, releasing its reference and allowing it to be deallocated + /// + public virtual void UnbindTexture(IntPtr textureId) + { + _loadedTextures.Remove(textureId); + } + + /// + /// Sets up ImGui for a new frame, should be called at frame start + /// + public virtual void BeforeLayout(float deltaTime) + { + ImGui.GetIO().DeltaTime = deltaTime; + UpdateInput(); + ImGui.NewFrame(); + } + + /// + /// 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 + /// + public virtual void AfterLayout() + { + ImGui.Render(); + + unsafe { RenderDrawData(ImGui.GetDrawData()); } + } + + #endregion ImGuiRenderer + + #region Setup & Update + + /// + /// Maps ImGui keys to XNA keys. We use this later on to tell ImGui what keys were pressed + /// + protected virtual void SetupInput() + { + var io = ImGui.GetIO(); + + _keys.Add(io.KeyMap[(int)ImGuiKey.Tab] = (int)Keys.Tab); + _keys.Add(io.KeyMap[(int)ImGuiKey.LeftArrow] = (int)Keys.Left); + _keys.Add(io.KeyMap[(int)ImGuiKey.RightArrow] = (int)Keys.Right); + _keys.Add(io.KeyMap[(int)ImGuiKey.UpArrow] = (int)Keys.Up); + _keys.Add(io.KeyMap[(int)ImGuiKey.DownArrow] = (int)Keys.Down); + _keys.Add(io.KeyMap[(int)ImGuiKey.PageUp] = (int)Keys.PageUp); + _keys.Add(io.KeyMap[(int)ImGuiKey.PageDown] = (int)Keys.PageDown); + _keys.Add(io.KeyMap[(int)ImGuiKey.Home] = (int)Keys.Home); + _keys.Add(io.KeyMap[(int)ImGuiKey.End] = (int)Keys.End); + _keys.Add(io.KeyMap[(int)ImGuiKey.Delete] = (int)Keys.Delete); + _keys.Add(io.KeyMap[(int)ImGuiKey.Backspace] = (int)Keys.Back); + _keys.Add(io.KeyMap[(int)ImGuiKey.Enter] = (int)Keys.Enter); + _keys.Add(io.KeyMap[(int)ImGuiKey.Escape] = (int)Keys.Escape); + _keys.Add(io.KeyMap[(int)ImGuiKey.A] = (int)Keys.A); + _keys.Add(io.KeyMap[(int)ImGuiKey.C] = (int)Keys.C); + _keys.Add(io.KeyMap[(int)ImGuiKey.V] = (int)Keys.V); + _keys.Add(io.KeyMap[(int)ImGuiKey.X] = (int)Keys.X); + _keys.Add(io.KeyMap[(int)ImGuiKey.Y] = (int)Keys.Y); + _keys.Add(io.KeyMap[(int)ImGuiKey.Z] = (int)Keys.Z); + + + // MonoGame-specific ////////////////////// + // _game.Window.TextInput += (s, a) => + // { + // if (a.Character == '\t') return; + + // io.AddInputCharacter(a.Character); + // }; + /////////////////////////////////////////// + + // FNA-specific /////////////////////////// + TextInputEXT.TextInput += c => + { + if (c == '\t') return; + + ImGui.GetIO().AddInputCharacter(c); + }; + /////////////////////////////////////////// + + ImGui.GetIO().Fonts.AddFontDefault(); + } + + /// + /// Updates the to the current matrices and texture + /// + protected virtual Effect UpdateEffect(Texture2D texture) + { + _effect = _effect ?? new BasicEffect(_graphicsDevice); + + var io = ImGui.GetIO(); + + // MonoGame-specific ////////////////////// + //var offset = .5f; + /////////////////////////////////////////// + + // FNA-specific /////////////////////////// + var offset = 0f; + /////////////////////////////////////////// + + _effect.World = Matrix.Identity; + _effect.View = Matrix.Identity; + _effect.Projection = Matrix.CreateOrthographicOffCenter(offset, io.DisplaySize.X + offset, io.DisplaySize.Y + offset, offset, -1f, 1f); + _effect.TextureEnabled = true; + _effect.Texture = texture; + _effect.VertexColorEnabled = true; + + return _effect; + } + + /// + /// Sends XNA input state to ImGui + /// + protected virtual void UpdateInput() + { + var io = ImGui.GetIO(); + + var mouse = Mouse.GetState(); + var keyboard = Keyboard.GetState(); + + for (int i = 0; i < _keys.Count; i++) + { + io.KeysDown[_keys[i]] = keyboard.IsKeyDown((Keys)_keys[i]); + } + + io.KeyShift = keyboard.IsKeyDown(Keys.LeftShift) || keyboard.IsKeyDown(Keys.RightShift); + io.KeyCtrl = keyboard.IsKeyDown(Keys.LeftControl) || keyboard.IsKeyDown(Keys.RightControl); + 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.DisplayFramebufferScale = new System.Numerics.Vector2(1f, 1f); + + io.MousePos = new System.Numerics.Vector2(mouse.X, mouse.Y); + + io.MouseDown[0] = mouse.LeftButton == ButtonState.Pressed; + io.MouseDown[1] = mouse.RightButton == ButtonState.Pressed; + io.MouseDown[2] = mouse.MiddleButton == ButtonState.Pressed; + + var scrollDelta = mouse.ScrollWheelValue - _scrollWheelValue; + io.MouseWheel = scrollDelta > 0 ? 1 : scrollDelta < 0 ? -1 : 0; + _scrollWheelValue = mouse.ScrollWheelValue; + } + + #endregion Setup & Update + + #region Internals + + /// + /// Gets the geometry as set up by ImGui and sends it to the graphics device + /// + private 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; + + _graphicsDevice.BlendFactor = Color.White; + _graphicsDevice.BlendState = BlendState.NonPremultiplied; + _graphicsDevice.RasterizerState = _rasterizerState; + _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); + + UpdateBuffers(drawData); + + RenderCommandLists(drawData); + + // Restore modified state + _graphicsDevice.Viewport = lastViewport; + _graphicsDevice.ScissorRectangle = lastScissorBox; + } + + private unsafe void UpdateBuffers(ImDrawDataPtr drawData) + { + if (drawData.TotalVtxCount == 0) + { + return; + } + + // Expand buffers if we need more room + if (drawData.TotalVtxCount > _vertexBufferSize) + { + _vertexBuffer?.Dispose(); + + _vertexBufferSize = (int)(drawData.TotalVtxCount * 1.5f); + _vertexBuffer = new VertexBuffer(_graphicsDevice, DrawVertDeclaration.Declaration, _vertexBufferSize, BufferUsage.None); + _vertexData = new byte[_vertexBufferSize * DrawVertDeclaration.Size]; + } + + if (drawData.TotalIdxCount > _indexBufferSize) + { + _indexBuffer?.Dispose(); + + _indexBufferSize = (int)(drawData.TotalIdxCount * 1.5f); + _indexBuffer = new IndexBuffer(_graphicsDevice, IndexElementSize.SixteenBits, _indexBufferSize, BufferUsage.None); + _indexData = new byte[_indexBufferSize * sizeof(ushort)]; + } + + // Copy ImGui's vertices and indices to a set of managed byte arrays + int vtxOffset = 0; + int idxOffset = 0; + + for (int n = 0; n < drawData.CmdListsCount; n++) + { + ImDrawListPtr cmdList = drawData.CmdListsRange[n]; + + fixed (void* vtxDstPtr = &_vertexData[vtxOffset * DrawVertDeclaration.Size]) + 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.IdxBuffer.Data, idxDstPtr, _indexData.Length, cmdList.IdxBuffer.Size * sizeof(ushort)); + } + + vtxOffset += cmdList.VtxBuffer.Size; + idxOffset += cmdList.IdxBuffer.Size; + } + + // Copy the managed byte arrays to the gpu vertex- and index buffers + _vertexBuffer.SetData(_vertexData, 0, drawData.TotalVtxCount * DrawVertDeclaration.Size); + _indexBuffer.SetData(_indexData, 0, drawData.TotalIdxCount * sizeof(ushort)); + } + + private unsafe void RenderCommandLists(ImDrawDataPtr drawData) + { + _graphicsDevice.SetVertexBuffer(_vertexBuffer); + _graphicsDevice.Indices = _indexBuffer; + + int vtxOffset = 0; + int idxOffset = 0; + + for (int n = 0; n < drawData.CmdListsCount; n++) + { + ImDrawListPtr cmdList = drawData.CmdListsRange[n]; + + for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++) + { + ImDrawCmdPtr 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( + (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]); + + foreach (var pass in effect.CurrentTechnique.Passes) + { + pass.Apply(); + +#pragma warning disable CS0618 // // FNA does not expose an alternative method. + _graphicsDevice.DrawIndexedPrimitives( + primitiveType: PrimitiveType.TriangleList, + baseVertex: vtxOffset, + minVertexIndex: 0, + numVertices: cmdList.VtxBuffer.Size, + startIndex: idxOffset, + primitiveCount: (int)drawCmd.ElemCount / 3 + ); +#pragma warning restore CS0618 + } + + idxOffset += (int)drawCmd.ElemCount; + } + + vtxOffset += cmdList.VtxBuffer.Size; + } + } + + #endregion Internals + } +} \ No newline at end of file diff --git a/project_name/project_name.csproj b/project_name/project_name.csproj index fc687f1..0cc174c 100644 --- a/project_name/project_name.csproj +++ b/project_name/project_name.csproj @@ -72,19 +72,19 @@ - osx\%(RecursiveDir)%(Filename)%(Extension) + %(RecursiveDir)%(Filename)%(Extension) PreserveNewest - osx\%(RecursiveDir)%(Filename)%(Extension) + %(RecursiveDir)%(Filename)%(Extension) PreserveNewest - osx\%(RecursiveDir)%(Filename)%(Extension) + %(RecursiveDir)%(Filename)%(Extension) PreserveNewest - osx\%(RecursiveDir)%(Filename)%(Extension) + %(RecursiveDir)%(Filename)%(Extension) PreserveNewest From b2a1c6037272e82470bf156d595729559f9d59fd Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 12 Feb 2019 22:48:11 -0800 Subject: [PATCH 03/24] make slick the install process --- .gitignore | 1 + getFNA.sh | 44 ++++++++++++------- project_name/Game1.cs | 6 ++- .../ImGui/ImGuiFinalRenderDelegate.cs | 2 +- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index bf09f5c..5694e90 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .DS_Store +.vs FNA/ ImGui.NET/ fnalibs/ diff --git a/getFNA.sh b/getFNA.sh index ba85897..55395fe 100755 --- a/getFNA.sh +++ b/getFNA.sh @@ -122,40 +122,50 @@ function getLibs() # Get the directory of this script MY_DIR=$(dirname "$BASH_SOURCE") + +# gather input + # FNA if [ ! -d "$MY_DIR/FNA" ]; then read -p "Download FNA (y/n)? " shouldDownload - if [[ $shouldDownload =~ ^[Yy]$ ]]; then - downloadFNA - fi else read -p "Update FNA (y/n)? " shouldUpdate - if [[ $shouldUpdate =~ ^[Yy]$ ]]; then - updateFNA - fi fi -# FNALIBS if [ ! -d "$MY_DIR/fnalibs" ]; then read -p "Download fnalibs (y/n)? " shouldDownloadLibs else read -p "Redownload fnalibs (y/n)? " shouldDownloadLibs fi + + +# Dear ImGui +if [ ! -d "$MY_DIR/ImGui.NET" ]; then + read -p "Download ImGui.NET (y/n)? " shouldDownload +else + read -p "Update ImGui.NET (y/n)? " shouldUpdate +fi + + +# act on the input + +# FNA +if [[ $shouldDownload =~ ^[Yy]$ ]]; then + downloadFNA +elif [[ $shouldUpdate =~ ^[Yy]$ ]]; then + updateFNA +fi + +# FNALIBS if [[ $shouldDownloadLibs =~ ^[Yy]$ ]]; then getLibs fi # Dear ImGui -if [ ! -d "$MY_DIR/ImGui.NET" ]; then - read -p "Download ImGui.NET (y/n)? " shouldDownload - if [[ $shouldDownload =~ ^[Yy]$ ]]; then - downloadImGui - fi -else - read -p "Update ImGui.NET (y/n)? " shouldUpdate - if [[ $shouldUpdate =~ ^[Yy]$ ]]; then - updateImGui - fi +if [[ $shouldDownload =~ ^[Yy]$ ]]; then + downloadImGui +elif [[ $shouldUpdate =~ ^[Yy]$ ]]; then + updateImGui fi diff --git a/project_name/Game1.cs b/project_name/Game1.cs index a5a2783..45d22e3 100644 --- a/project_name/Game1.cs +++ b/project_name/Game1.cs @@ -14,9 +14,13 @@ namespace project_name #if DEBUG System.Diagnostics.Debug.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(System.Console.Out)); #endif - + + // setup a Scene so we have something to show var newScene = new Scene(); newScene.addRenderer(new DefaultRenderer()); + + // optionally render Nez in an ImGui window + newScene.finalRenderDelegate = new ImGuiFinalRenderDelegate(); var logo = newScene.content.Load("nez-logo-black"); newScene.createEntity("logo") diff --git a/project_name/ImGui/ImGuiFinalRenderDelegate.cs b/project_name/ImGui/ImGuiFinalRenderDelegate.cs index 29510c7..678be53 100644 --- a/project_name/ImGui/ImGuiFinalRenderDelegate.cs +++ b/project_name/ImGui/ImGuiFinalRenderDelegate.cs @@ -39,7 +39,7 @@ namespace Nez Core.graphicsDevice.Clear( letterboxColor ); - _imGuiRenderer.BeforeLayout(new GameTime(TimeSpan.FromDays(0), TimeSpan.FromMilliseconds(Time.deltaTime * 1000))); + _imGuiRenderer.BeforeLayout(Time.time); layoutGui(); _imGuiRenderer.AfterLayout(); } From 943ea5d88a1d0c4625c21abe416701517160c4ff Mon Sep 17 00:00:00 2001 From: Mike Desaro <44787306+mikedJC@users.noreply.github.com> Date: Wed, 13 Feb 2019 09:49:02 -0800 Subject: [PATCH 04/24] nothing but some cleanup here --- project_name/project_name.csproj | 170 +++++++++++++++---------------- 1 file changed, 84 insertions(+), 86 deletions(-) diff --git a/project_name/project_name.csproj b/project_name/project_name.csproj index 0cc174c..f51387d 100644 --- a/project_name/project_name.csproj +++ b/project_name/project_name.csproj @@ -1,92 +1,90 @@ - - - Exe - net462 - false - AnyCPU - project_name - DesktopGL + + Exe + net462 + false + AnyCPU + project_name + DesktopGL True - - - - - - + + + + + + - - - - - - PreserveNewest - - - - - - - Content/%(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - - - - - - - - - - - true - true - - - - - - x86\%(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - x64\%(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - osx\%(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - lib\%(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - lib64\%(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - + + + + + + PreserveNewest + + + + + + + Content/%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + + + + + + + + + + + true + true + + + + + + x86\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + x64\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + osx\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + lib\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + lib64\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + - - %(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - %(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - %(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - %(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - - \ No newline at end of file + + %(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + %(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + %(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + %(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + From a652c155ab56706c959cba6ed25f42d44259102a Mon Sep 17 00:00:00 2001 From: prime31 Date: Wed, 13 Feb 2019 10:20:46 -0800 Subject: [PATCH 05/24] bump to .NET 4.7.1 --- project_name/project_name.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project_name/project_name.csproj b/project_name/project_name.csproj index f51387d..51d68e6 100644 --- a/project_name/project_name.csproj +++ b/project_name/project_name.csproj @@ -1,7 +1,7 @@ Exe - net462 + net471 false AnyCPU project_name From fda738047c50c86221e2234168b8f1a9099aba2f Mon Sep 17 00:00:00 2001 From: Mike Date: Wed, 13 Feb 2019 15:09:44 -0800 Subject: [PATCH 06/24] newlines and readme --- README.md | 2 ++ getFNA.sh | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 920663d..2b0f96b 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ Start new FNA projects with Nez quickly and easily with handy setup scripts, a v That's it! Now you're ready to build and run the base project. When developing raw content (files not processed by the Pipeline tool) should be placed in the `Content` folder and anything that needs processing should go in the `CompiledContent` folder and added to the Pipeline tool. +The setup process will also init a git repo for you with Nez added as a submodule. + If you want to see the output of `Debug.*` calls in the VS Code Debug Console, you have to install a listener by adding this somewhere in your code (Game1 by default has one for you): `System.Diagnostics.Debug.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(System.Console.Out));` diff --git a/getFNA.sh b/getFNA.sh index 55395fe..ad46e46 100755 --- a/getFNA.sh +++ b/getFNA.sh @@ -42,7 +42,7 @@ function downloadFNA() echo "Downloading FNA..." git -C $MY_DIR clone https://github.com/FNA-XNA/FNA.git --recursive if [ $? -eq 0 ]; then - echo "Finished downloading!\n" + echo "Finished downloading!" else echo >&2 "ERROR: Unable to download successfully. Maybe try again later?" fi @@ -55,7 +55,7 @@ function updateFNA() echo "Updating to the latest git version of FNA..." git -C "$MY_DIR/FNA" pull --recurse-submodules if [ $? -eq 0 ]; then - echo "Finished updating!\n" + echo "Finished updating!" else echo >&2 "ERROR: Unable to update." exit 1 @@ -214,5 +214,5 @@ if [ ! $? -eq 0 ]; then printf "\n\nManually run the following command:\n\nnuget restore Nez.FNA/Nez/Nez.sln && msbuild Nez.FNA/Nez/Nez.sln && msbuild /t:restore $newProjectName\n\n" else echo "nuget restore Nez.FNA/Nez/Nez.sln && msbuild Nez.FNA/Nez/Nez.sln && msbuild /t:restore $newProjectName" | pbcopy - echo "command copied to your clipboard\n" + echo "command copied to your clipboard" fi From 00a70f8f1e04cfee02cef9cc2d491e77a773efd0 Mon Sep 17 00:00:00 2001 From: Mike Date: Wed, 13 Feb 2019 18:27:08 -0800 Subject: [PATCH 07/24] MG content builder working in VS now too --- MonoGameContent.targets | 93 ++++++++++++++++ getFNA.sh | 6 +- project_name/project_name.csproj | 181 ++++++++++++++++--------------- 3 files changed, 190 insertions(+), 90 deletions(-) create mode 100644 MonoGameContent.targets diff --git a/MonoGameContent.targets b/MonoGameContent.targets new file mode 100644 index 0000000..fa00c36 --- /dev/null +++ b/MonoGameContent.targets @@ -0,0 +1,93 @@ + + + + /Library/Frameworks/Mono.framework/External/xbuild + $(MSBuildProgramFiles32) + bin/DesktopGL + obj/DesktopGL + + + + + + + + + + + + true + + + + + $(MonoGameInstallDirectory)\MonoGame\v3.0\ + + /Library/Frameworks/Mono.framework/Versions/Current/bin/mono + /usr/local/bin/mono + /usr/bin/mono + mono + $(MonoGameInstallDir)Tools\MGCB.exe + "$(MonoGameContentBuilderExe)" + $(MonoExe) $(MonoGameContentBuilderCmd) + $(MonoMacResourcePrefix) + $(IPhoneResourcePrefix) + $(MonoAndroidAssetsPrefix) + $(PlatformResourcePrefix)\ + + /quiet +
/platform:$(MonoGamePlatform)
+
+ + + + + + + + + + +
+ + + + + BuildContent; + $(BuildDependsOn); + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/getFNA.sh b/getFNA.sh index ad46e46..c899546 100755 --- a/getFNA.sh +++ b/getFNA.sh @@ -72,7 +72,7 @@ function downloadImGui() #git -C $MY_DIR clone https://github.com/mellinoe/ImGui.NET.git --recursive git -C $MY_DIR clone -b fix-MonoGame-FNA https://github.com/prime31/ImGui.NET.git --recursive if [ $? -eq 0 ]; then - echo "Finished downloading!\n" + echo "Finished downloading!" else echo >&2 "ERROR: Unable to download successfully. Maybe try again later?" fi @@ -214,5 +214,7 @@ if [ ! $? -eq 0 ]; then printf "\n\nManually run the following command:\n\nnuget restore Nez.FNA/Nez/Nez.sln && msbuild Nez.FNA/Nez/Nez.sln && msbuild /t:restore $newProjectName\n\n" else echo "nuget restore Nez.FNA/Nez/Nez.sln && msbuild Nez.FNA/Nez/Nez.sln && msbuild /t:restore $newProjectName" | pbcopy - echo "command copied to your clipboard" + echo "" + echo "A build command was copied to your clipboard. Paste and run it now." + echo "" fi diff --git a/project_name/project_name.csproj b/project_name/project_name.csproj index 51d68e6..934c629 100644 --- a/project_name/project_name.csproj +++ b/project_name/project_name.csproj @@ -1,90 +1,95 @@ + - - Exe - net471 - false - AnyCPU - project_name - DesktopGL - True - - - - - - - - - - - - - PreserveNewest - - - - - - - Content/%(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - - - - - - - - - - - true - true - - - - - - x86\%(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - x64\%(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - osx\%(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - lib\%(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - lib64\%(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - - - - - %(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - %(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - %(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - - %(RecursiveDir)%(Filename)%(Extension) - PreserveNewest - - + + Exe + net471 + false + AnyCPU + project_name + DesktopGL + True + + + + + + + + + + + + + PreserveNewest + + + + + + + Content/%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + + + + + + + + + + + + + + + true + true + + + + + + x86\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + x64\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + osx\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + lib\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + lib64\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + + + + + %(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + %(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + %(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + %(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + From 1f1ef826978c9e6805eb421e5721073024f08a6b Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 14 Feb 2019 14:36:47 -0800 Subject: [PATCH 08/24] move to using nuget for ImGui.NET --- getFNA.sh | 45 ------------------- project_name.sln | 2 - .../ImGui/ImGuiFinalRenderDelegate.cs | 4 +- project_name/project_name.csproj | 25 +++++++---- 4 files changed, 18 insertions(+), 58 deletions(-) diff --git a/getFNA.sh b/getFNA.sh index c899546..2e1d67a 100755 --- a/getFNA.sh +++ b/getFNA.sh @@ -63,36 +63,6 @@ function updateFNA() } -# Clones FNA from the git master branch -function downloadImGui() -{ - checkGit - echo "Downloading ImGui..." - echo "Temporarily using ImGui.NET branch until ImGui.NET master is updated" - #git -C $MY_DIR clone https://github.com/mellinoe/ImGui.NET.git --recursive - git -C $MY_DIR clone -b fix-MonoGame-FNA https://github.com/prime31/ImGui.NET.git --recursive - if [ $? -eq 0 ]; then - echo "Finished downloading!" - else - echo >&2 "ERROR: Unable to download successfully. Maybe try again later?" - fi -} - -# Pulls FNA from the git master branch -function updateImGui() -{ - checkGit - echo "Updating to the latest git version of ImGui.NET..." - git -C "$MY_DIR/ImGui.NET" pull --recurse-submodules - if [ $? -eq 0 ]; then - echo "Finished updating!\n" - else - echo >&2 "ERROR: Unable to update." - exit 1 - fi -} - - # Downloads and extracts prepackaged archive of native libraries ("fnalibs") function getLibs() { @@ -139,14 +109,6 @@ else fi -# Dear ImGui -if [ ! -d "$MY_DIR/ImGui.NET" ]; then - read -p "Download ImGui.NET (y/n)? " shouldDownload -else - read -p "Update ImGui.NET (y/n)? " shouldUpdate -fi - - # act on the input # FNA @@ -161,13 +123,6 @@ if [[ $shouldDownloadLibs =~ ^[Yy]$ ]]; then getLibs fi -# Dear ImGui -if [[ $shouldDownload =~ ^[Yy]$ ]]; then - downloadImGui -elif [[ $shouldUpdate =~ ^[Yy]$ ]]; then - updateImGui -fi - # install t4 engine installT4 diff --git a/project_name.sln b/project_name.sln index bf0682f..76a9c87 100644 --- a/project_name.sln +++ b/project_name.sln @@ -39,8 +39,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FNA", "FNA\FNA.csproj", "{3 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nez.FNA", "Nez.FNA\Nez.FNA\Nez.FNA.csproj", "{11A5855C-B12C-4F8D-B935-56F3D0B671C3}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImGui.NET", "ImGui.NET\src\ImGui.NET\ImGui.NET.csproj", "{AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}" -EndProject Global GlobalSection(ProjectConfigurationPlatforms) = postSolution {8C576ECC-147D-4B4A-8EC1-56533D26A178}.Debug|Any CPU.ActiveCfg = Debug|Any CPU diff --git a/project_name/ImGui/ImGuiFinalRenderDelegate.cs b/project_name/ImGui/ImGuiFinalRenderDelegate.cs index 678be53..349dbf1 100644 --- a/project_name/ImGui/ImGuiFinalRenderDelegate.cs +++ b/project_name/ImGui/ImGuiFinalRenderDelegate.cs @@ -17,9 +17,9 @@ namespace Nez public ImGuiFinalRenderDelegate() { - var core = typeof(Core).GetField("_instance", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as Core; - _imGuiRenderer = new ImGuiRenderer(core); + _imGuiRenderer = new ImGuiRenderer(Core.instance); _imGuiRenderer.RebuildFontAtlas(); + ImGui.GetIO().ConfigWindowsMoveFromTitleBarOnly = true; } public void handleFinalRender( Color letterboxColor, RenderTarget2D source, Rectangle finalRenderDestinationRect, SamplerState samplerState ) diff --git a/project_name/project_name.csproj b/project_name/project_name.csproj index 934c629..e257a0f 100644 --- a/project_name/project_name.csproj +++ b/project_name/project_name.csproj @@ -14,7 +14,6 @@ - @@ -74,22 +73,30 @@ + + $(NuGetPackageRoot)\imgui.net\**\runtimes\ + + - - %(RecursiveDir)%(Filename)%(Extension) + + %(Filename)%(Extension) PreserveNewest - - %(RecursiveDir)%(Filename)%(Extension) + + %(Filename)%(Extension) PreserveNewest - - %(RecursiveDir)%(Filename)%(Extension) + + libcimgui.dylib PreserveNewest - - %(RecursiveDir)%(Filename)%(Extension) + + %(Filename)%(Extension) PreserveNewest + + + +
From 6ebd635a618e39f5ef949188242bb793584a814d Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 14 Feb 2019 17:34:12 -0800 Subject: [PATCH 09/24] cleanup the ImGui code stuffs --- project_name/ImGui/DrawVertDeclaration.cs | 28 - .../ImGui/ImGuiFinalRenderDelegate.cs | 134 ++-- project_name/ImGui/ImGuiRenderer.cs | 746 +++++++++--------- 3 files changed, 456 insertions(+), 452 deletions(-) delete mode 100644 project_name/ImGui/DrawVertDeclaration.cs diff --git a/project_name/ImGui/DrawVertDeclaration.cs b/project_name/ImGui/DrawVertDeclaration.cs deleted file mode 100644 index 276e5df..0000000 --- a/project_name/ImGui/DrawVertDeclaration.cs +++ /dev/null @@ -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) - ); - } - } -} \ No newline at end of file diff --git a/project_name/ImGui/ImGuiFinalRenderDelegate.cs b/project_name/ImGui/ImGuiFinalRenderDelegate.cs index 349dbf1..4d70719 100644 --- a/project_name/ImGui/ImGuiFinalRenderDelegate.cs +++ b/project_name/ImGui/ImGuiFinalRenderDelegate.cs @@ -1,7 +1,6 @@ using System; using System.Reflection; using ImGuiNET; -using ImGuiNET.SampleProgram.XNA; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; @@ -11,68 +10,99 @@ namespace Nez { public Scene scene { get; set; } - ImGuiRenderer _imGuiRenderer; - RenderTarget2D _lastRenderTarget; - IntPtr _renderTargetId; + ImGuiRenderer _imGuiRenderer; + RenderTarget2D _lastRenderTarget; + IntPtr _renderTargetId; - public ImGuiFinalRenderDelegate() - { - _imGuiRenderer = new ImGuiRenderer(Core.instance); - _imGuiRenderer.RebuildFontAtlas(); - ImGui.GetIO().ConfigWindowsMoveFromTitleBarOnly = true; - } - - public void handleFinalRender( Color letterboxColor, RenderTarget2D source, Rectangle finalRenderDestinationRect, SamplerState samplerState ) + public ImGuiFinalRenderDelegate() { - 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(); + _imGuiRenderer = new ImGuiRenderer( Core.instance ); + _imGuiRenderer.rebuildFontAtlas(); } - void layoutGui() - { - ImGui.ShowDemoWindow(); + [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; + } - var maxSize = new System.Numerics.Vector2(_lastRenderTarget.Width, _lastRenderTarget.Height); - var minSize = maxSize / 4; - unsafe - { - ImGui.SetNextWindowSizeConstraints(minSize, maxSize, data => - { - var size = (*data).CurrentSize; - var ratio = size.X / _lastRenderTarget.Width; - (*data).DesiredSize.Y = ratio * _lastRenderTarget.Height; - }); - } + void layoutGui() + { + ImGui.ShowDemoWindow(); - ImGui.SetNextWindowPos(new System.Numerics.Vector2(0, 0), ImGuiCond.FirstUseEver); - ImGui.Begin("Game Window"); - ImGui.Image(_renderTargetId, ImGui.GetContentRegionAvail()); - ImGui.End(); - } + 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" ); + + 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() - {} + { } public void onSceneBackBufferSizeChanged( int newWidth, int newHeight ) - {} + { } public void unload() - {} + { } + + #endregion } } diff --git a/project_name/ImGui/ImGuiRenderer.cs b/project_name/ImGui/ImGuiRenderer.cs index 0c6886a..41c7523 100644 --- a/project_name/ImGui/ImGuiRenderer.cs +++ b/project_name/ImGui/ImGuiRenderer.cs @@ -1,387 +1,389 @@ 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 { - /// - /// ImGui renderer for use with XNA-likes (FNA & MonoGame) - /// - public class ImGuiRenderer - { - private Game _game; - - // Graphics - private GraphicsDevice _graphicsDevice; - - private BasicEffect _effect; - private RasterizerState _rasterizerState; - - private byte[] _vertexData; - private VertexBuffer _vertexBuffer; - private int _vertexBufferSize; - - private byte[] _indexData; - private IndexBuffer _indexBuffer; - private int _indexBufferSize; - - // Textures - private Dictionary _loadedTextures; - - private int _textureId; - private IntPtr? _fontTextureId; - - // Input - private int _scrollWheelValue; - - private List _keys = new List(); - - public ImGuiRenderer(Game game) - { - var context = ImGui.CreateContext(); - ImGui.SetCurrentContext(context); - - _game = game ?? throw new ArgumentNullException(nameof(game)); - _graphicsDevice = game.GraphicsDevice; - - _loadedTextures = new Dictionary(); - - _rasterizerState = new RasterizerState() - { - CullMode = CullMode.None, - DepthBias = 0, - FillMode = FillMode.Solid, - MultiSampleAntiAlias = false, - ScissorTestEnable = true, - SlopeScaleDepthBias = 0 - }; - - SetupInput(); - } - - #region ImGuiRenderer - - /// - /// Creates a texture and loads the font data from ImGui. Should be called when the is initialized but before any rendering is done - /// - public virtual unsafe void RebuildFontAtlas() - { - // Get font texture from ImGui - var io = ImGui.GetIO(); - io.Fonts.GetTexDataAsRGBA32(out byte* pixelData, out int width, out int height, out int bytesPerPixel); - - // Copy the data to a managed array - var pixels = new byte[width * height * bytesPerPixel]; - unsafe { 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); - 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); - - // Bind the new texture to an ImGui-friendly id - _fontTextureId = BindTexture(tex2d); - - // Let ImGui know where to find the texture - io.Fonts.SetTexID(_fontTextureId.Value); - io.Fonts.ClearTexData(); // Clears CPU side texture data - } - - /// - /// Creates a pointer to a texture, which can be passed through ImGui calls such as . That pointer is then used by ImGui to let us know what texture to draw - /// - public virtual IntPtr BindTexture(Texture2D texture) - { - var id = new IntPtr(_textureId++); - - _loadedTextures.Add(id, texture); - - return id; - } - - /// - /// Removes a previously created texture pointer, releasing its reference and allowing it to be deallocated - /// - public virtual void UnbindTexture(IntPtr textureId) - { - _loadedTextures.Remove(textureId); - } - - /// - /// Sets up ImGui for a new frame, should be called at frame start - /// - public virtual void BeforeLayout(float deltaTime) - { - ImGui.GetIO().DeltaTime = deltaTime; - UpdateInput(); - ImGui.NewFrame(); - } - - /// - /// 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 - /// - public virtual void AfterLayout() - { - ImGui.Render(); - - unsafe { RenderDrawData(ImGui.GetDrawData()); } - } - - #endregion ImGuiRenderer - - #region Setup & Update - - /// - /// Maps ImGui keys to XNA keys. We use this later on to tell ImGui what keys were pressed - /// - protected virtual void SetupInput() - { - var io = ImGui.GetIO(); - - _keys.Add(io.KeyMap[(int)ImGuiKey.Tab] = (int)Keys.Tab); - _keys.Add(io.KeyMap[(int)ImGuiKey.LeftArrow] = (int)Keys.Left); - _keys.Add(io.KeyMap[(int)ImGuiKey.RightArrow] = (int)Keys.Right); - _keys.Add(io.KeyMap[(int)ImGuiKey.UpArrow] = (int)Keys.Up); - _keys.Add(io.KeyMap[(int)ImGuiKey.DownArrow] = (int)Keys.Down); - _keys.Add(io.KeyMap[(int)ImGuiKey.PageUp] = (int)Keys.PageUp); - _keys.Add(io.KeyMap[(int)ImGuiKey.PageDown] = (int)Keys.PageDown); - _keys.Add(io.KeyMap[(int)ImGuiKey.Home] = (int)Keys.Home); - _keys.Add(io.KeyMap[(int)ImGuiKey.End] = (int)Keys.End); - _keys.Add(io.KeyMap[(int)ImGuiKey.Delete] = (int)Keys.Delete); - _keys.Add(io.KeyMap[(int)ImGuiKey.Backspace] = (int)Keys.Back); - _keys.Add(io.KeyMap[(int)ImGuiKey.Enter] = (int)Keys.Enter); - _keys.Add(io.KeyMap[(int)ImGuiKey.Escape] = (int)Keys.Escape); - _keys.Add(io.KeyMap[(int)ImGuiKey.A] = (int)Keys.A); - _keys.Add(io.KeyMap[(int)ImGuiKey.C] = (int)Keys.C); - _keys.Add(io.KeyMap[(int)ImGuiKey.V] = (int)Keys.V); - _keys.Add(io.KeyMap[(int)ImGuiKey.X] = (int)Keys.X); - _keys.Add(io.KeyMap[(int)ImGuiKey.Y] = (int)Keys.Y); - _keys.Add(io.KeyMap[(int)ImGuiKey.Z] = (int)Keys.Z); - - - // MonoGame-specific ////////////////////// - // _game.Window.TextInput += (s, a) => - // { - // if (a.Character == '\t') return; - - // io.AddInputCharacter(a.Character); - // }; - /////////////////////////////////////////// - - // FNA-specific /////////////////////////// - TextInputEXT.TextInput += c => - { - if (c == '\t') return; - - ImGui.GetIO().AddInputCharacter(c); - }; - /////////////////////////////////////////// - - ImGui.GetIO().Fonts.AddFontDefault(); - } - - /// - /// Updates the to the current matrices and texture - /// - protected virtual Effect UpdateEffect(Texture2D texture) - { - _effect = _effect ?? new BasicEffect(_graphicsDevice); - - var io = ImGui.GetIO(); - - // MonoGame-specific ////////////////////// - //var offset = .5f; - /////////////////////////////////////////// - - // FNA-specific /////////////////////////// - var offset = 0f; - /////////////////////////////////////////// - - _effect.World = Matrix.Identity; - _effect.View = Matrix.Identity; - _effect.Projection = Matrix.CreateOrthographicOffCenter(offset, io.DisplaySize.X + offset, io.DisplaySize.Y + offset, offset, -1f, 1f); - _effect.TextureEnabled = true; - _effect.Texture = texture; - _effect.VertexColorEnabled = true; - - return _effect; - } - - /// - /// Sends XNA input state to ImGui - /// - protected virtual void UpdateInput() - { - var io = ImGui.GetIO(); - - var mouse = Mouse.GetState(); - var keyboard = Keyboard.GetState(); - - for (int i = 0; i < _keys.Count; i++) - { - io.KeysDown[_keys[i]] = keyboard.IsKeyDown((Keys)_keys[i]); - } - - io.KeyShift = keyboard.IsKeyDown(Keys.LeftShift) || keyboard.IsKeyDown(Keys.RightShift); - io.KeyCtrl = keyboard.IsKeyDown(Keys.LeftControl) || keyboard.IsKeyDown(Keys.RightControl); - 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.DisplayFramebufferScale = new System.Numerics.Vector2(1f, 1f); - - io.MousePos = new System.Numerics.Vector2(mouse.X, mouse.Y); - - io.MouseDown[0] = mouse.LeftButton == ButtonState.Pressed; - io.MouseDown[1] = mouse.RightButton == ButtonState.Pressed; - io.MouseDown[2] = mouse.MiddleButton == ButtonState.Pressed; - - var scrollDelta = mouse.ScrollWheelValue - _scrollWheelValue; - io.MouseWheel = scrollDelta > 0 ? 1 : scrollDelta < 0 ? -1 : 0; - _scrollWheelValue = mouse.ScrollWheelValue; - } - - #endregion Setup & Update - - #region Internals - - /// - /// Gets the geometry as set up by ImGui and sends it to the graphics device - /// - private 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; - - _graphicsDevice.BlendFactor = Color.White; - _graphicsDevice.BlendState = BlendState.NonPremultiplied; - _graphicsDevice.RasterizerState = _rasterizerState; - _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); - - UpdateBuffers(drawData); - - RenderCommandLists(drawData); - - // Restore modified state - _graphicsDevice.Viewport = lastViewport; - _graphicsDevice.ScissorRectangle = lastScissorBox; - } - - private unsafe void UpdateBuffers(ImDrawDataPtr drawData) - { - if (drawData.TotalVtxCount == 0) - { - return; - } - - // Expand buffers if we need more room - if (drawData.TotalVtxCount > _vertexBufferSize) - { - _vertexBuffer?.Dispose(); - - _vertexBufferSize = (int)(drawData.TotalVtxCount * 1.5f); - _vertexBuffer = new VertexBuffer(_graphicsDevice, DrawVertDeclaration.Declaration, _vertexBufferSize, BufferUsage.None); - _vertexData = new byte[_vertexBufferSize * DrawVertDeclaration.Size]; - } - - if (drawData.TotalIdxCount > _indexBufferSize) - { - _indexBuffer?.Dispose(); - - _indexBufferSize = (int)(drawData.TotalIdxCount * 1.5f); - _indexBuffer = new IndexBuffer(_graphicsDevice, IndexElementSize.SixteenBits, _indexBufferSize, BufferUsage.None); - _indexData = new byte[_indexBufferSize * sizeof(ushort)]; - } - - // Copy ImGui's vertices and indices to a set of managed byte arrays - int vtxOffset = 0; - int idxOffset = 0; - - for (int n = 0; n < drawData.CmdListsCount; n++) - { - ImDrawListPtr cmdList = drawData.CmdListsRange[n]; - - fixed (void* vtxDstPtr = &_vertexData[vtxOffset * DrawVertDeclaration.Size]) - 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.IdxBuffer.Data, idxDstPtr, _indexData.Length, cmdList.IdxBuffer.Size * sizeof(ushort)); - } - - vtxOffset += cmdList.VtxBuffer.Size; - idxOffset += cmdList.IdxBuffer.Size; - } - - // Copy the managed byte arrays to the gpu vertex- and index buffers - _vertexBuffer.SetData(_vertexData, 0, drawData.TotalVtxCount * DrawVertDeclaration.Size); - _indexBuffer.SetData(_indexData, 0, drawData.TotalIdxCount * sizeof(ushort)); - } - - private unsafe void RenderCommandLists(ImDrawDataPtr drawData) - { - _graphicsDevice.SetVertexBuffer(_vertexBuffer); - _graphicsDevice.Indices = _indexBuffer; - - int vtxOffset = 0; - int idxOffset = 0; - - for (int n = 0; n < drawData.CmdListsCount; n++) - { - ImDrawListPtr cmdList = drawData.CmdListsRange[n]; - - for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++) - { - ImDrawCmdPtr 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( - (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]); - - foreach (var pass in effect.CurrentTechnique.Passes) - { - pass.Apply(); + /// + /// ImGui renderer for use with XNA-likes (FNA and MonoGame) + /// + public class ImGuiRenderer + { + // Graphics + BasicEffect _effect; + RasterizerState _rasterizerState; + + readonly VertexDeclaration _vertexDeclaration; + readonly int _vertexDeclarationSize; + + byte[] _vertexData; + VertexBuffer _vertexBuffer; + int _vertexBufferSize; + + byte[] _indexData; + IndexBuffer _indexBuffer; + int _indexBufferSize; + + // Textures + Dictionary _loadedTextures; + + int _textureId; + IntPtr? _fontTextureId; + + // Input + int _scrollWheelValue; + + List _keys = new List(); + + 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 ); + + _loadedTextures = new Dictionary(); + + _rasterizerState = new RasterizerState() + { + CullMode = CullMode.None, + DepthBias = 0, + FillMode = FillMode.Solid, + MultiSampleAntiAlias = false, + ScissorTestEnable = true, + SlopeScaleDepthBias = 0 + }; + + setupInput(); + } + + #region ImGuiRenderer + + /// + /// Creates a texture and loads the font data from ImGui. Should be called when the is initialized but before any rendering is done + /// + public unsafe void rebuildFontAtlas() + { + // Get font texture from ImGui + var io = ImGui.GetIO(); + io.Fonts.GetTexDataAsRGBA32( out byte* pixelData, out int width, out int height, out int bytesPerPixel ); + + // Copy the data to a managed array + var pixels = new byte[width * height * bytesPerPixel]; + Marshal.Copy( new IntPtr( pixelData ), pixels, 0, pixels.Length ); + + // Create and register the texture as an XNA texture + var tex2d = new Texture2D( Core.graphicsDevice, width, height, false, SurfaceFormat.Color ); + tex2d.SetData( pixels ); + + // 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 ); + + // Let ImGui know where to find the texture + io.Fonts.SetTexID( _fontTextureId.Value ); + io.Fonts.ClearTexData(); // Clears CPU side texture data + } + + /// + /// Creates a pointer to a texture, which can be passed through ImGui calls such as . That pointer is then used by ImGui to let us know what texture to draw + /// + public IntPtr bindTexture( Texture2D texture ) + { + var id = new IntPtr( _textureId++ ); + _loadedTextures.Add( id, texture ); + return id; + } + + /// + /// Removes a previously created texture pointer, releasing its reference and allowing it to be deallocated + /// + public void unbindTexture( IntPtr textureId ) + { + _loadedTextures.Remove( textureId ); + } + + /// + /// Sets up ImGui for a new frame, should be called at frame start + /// + public void beforeLayout( float deltaTime ) + { + ImGui.GetIO().DeltaTime = deltaTime; + updateInput(); + ImGui.NewFrame(); + } + + /// + /// 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 + /// + public void afterLayout() + { + ImGui.Render(); + unsafe { renderDrawData( ImGui.GetDrawData() ); } + } + + #endregion ImGuiRenderer + + #region Setup & Update + + /// + /// Maps ImGui keys to XNA keys. We use this later on to tell ImGui what keys were pressed + /// + void setupInput() + { + var io = ImGui.GetIO(); + + _keys.Add( io.KeyMap[(int)ImGuiKey.Tab] = (int)Keys.Tab ); + _keys.Add( io.KeyMap[(int)ImGuiKey.LeftArrow] = (int)Keys.Left ); + _keys.Add( io.KeyMap[(int)ImGuiKey.RightArrow] = (int)Keys.Right ); + _keys.Add( io.KeyMap[(int)ImGuiKey.UpArrow] = (int)Keys.Up ); + _keys.Add( io.KeyMap[(int)ImGuiKey.DownArrow] = (int)Keys.Down ); + _keys.Add( io.KeyMap[(int)ImGuiKey.PageUp] = (int)Keys.PageUp ); + _keys.Add( io.KeyMap[(int)ImGuiKey.PageDown] = (int)Keys.PageDown ); + _keys.Add( io.KeyMap[(int)ImGuiKey.Home] = (int)Keys.Home ); + _keys.Add( io.KeyMap[(int)ImGuiKey.End] = (int)Keys.End ); + _keys.Add( io.KeyMap[(int)ImGuiKey.Delete] = (int)Keys.Delete ); + _keys.Add( io.KeyMap[(int)ImGuiKey.Backspace] = (int)Keys.Back ); + _keys.Add( io.KeyMap[(int)ImGuiKey.Enter] = (int)Keys.Enter ); + _keys.Add( io.KeyMap[(int)ImGuiKey.Escape] = (int)Keys.Escape ); + _keys.Add( io.KeyMap[(int)ImGuiKey.A] = (int)Keys.A ); + _keys.Add( io.KeyMap[(int)ImGuiKey.C] = (int)Keys.C ); + _keys.Add( io.KeyMap[(int)ImGuiKey.V] = (int)Keys.V ); + _keys.Add( io.KeyMap[(int)ImGuiKey.X] = (int)Keys.X ); + _keys.Add( io.KeyMap[(int)ImGuiKey.Y] = (int)Keys.Y ); + _keys.Add( io.KeyMap[(int)ImGuiKey.Z] = (int)Keys.Z ); + + + // MonoGame-specific ////////////////////// + // _game.Window.TextInput += (s, a) => + // { + // if (a.Character == '\t') return; + + // io.AddInputCharacter(a.Character); + // }; + /////////////////////////////////////////// + + // FNA-specific /////////////////////////// + TextInputEXT.TextInput += c => + { + if( c == '\t' ) return; + + ImGui.GetIO().AddInputCharacter( c ); + }; + /////////////////////////////////////////// + + ImGui.GetIO().Fonts.AddFontDefault(); + } + + /// + /// Updates the to the current matrices and texture + /// + Effect updateEffect( Texture2D texture ) + { + _effect = _effect ?? new BasicEffect( Core.graphicsDevice ); + + var io = ImGui.GetIO(); + + // MonoGame-specific ////////////////////// + //var offset = .5f; + /////////////////////////////////////////// + + // FNA-specific /////////////////////////// + var offset = 0f; + /////////////////////////////////////////// + + _effect.World = Matrix.Identity; + _effect.View = Matrix.Identity; + _effect.Projection = Matrix.CreateOrthographicOffCenter( offset, io.DisplaySize.X + offset, io.DisplaySize.Y + offset, offset, -1f, 1f ); + _effect.TextureEnabled = true; + _effect.Texture = texture; + _effect.VertexColorEnabled = true; + + return _effect; + } + + /// + /// Sends XNA input state to ImGui + /// + void updateInput() + { + var io = ImGui.GetIO(); + + var mouse = Mouse.GetState(); + var keyboard = Keyboard.GetState(); + + for( int i = 0; i < _keys.Count; i++ ) + { + io.KeysDown[_keys[i]] = keyboard.IsKeyDown( (Keys)_keys[i] ); + } + + io.KeyShift = keyboard.IsKeyDown( Keys.LeftShift ) || keyboard.IsKeyDown( Keys.RightShift ); + io.KeyCtrl = keyboard.IsKeyDown( Keys.LeftControl ) || keyboard.IsKeyDown( Keys.RightControl ); + 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( 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 ); + + io.MouseDown[0] = mouse.LeftButton == ButtonState.Pressed; + io.MouseDown[1] = mouse.RightButton == ButtonState.Pressed; + io.MouseDown[2] = mouse.MiddleButton == ButtonState.Pressed; + + var scrollDelta = mouse.ScrollWheelValue - _scrollWheelValue; + io.MouseWheel = scrollDelta > 0 ? 1 : scrollDelta < 0 ? -1 : 0; + _scrollWheelValue = mouse.ScrollWheelValue; + } + + #endregion Setup & Update + + #region Internals + + /// + /// Gets the geometry as set up by ImGui and sends it to the graphics device + /// + void renderDrawData( ImDrawDataPtr drawData ) + { + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers + var lastViewport = Core.graphicsDevice.Viewport; + var lastScissorBox = Core.graphicsDevice.ScissorRectangle; + + 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 + Core.graphicsDevice.Viewport = new Viewport( 0, 0, Core.graphicsDevice.PresentationParameters.BackBufferWidth, Core.graphicsDevice.PresentationParameters.BackBufferHeight ); + + updateBuffers( drawData ); + renderCommandLists( drawData ); + + // Restore modified state + Core.graphicsDevice.Viewport = lastViewport; + Core.graphicsDevice.ScissorRectangle = lastScissorBox; + } + + unsafe void updateBuffers( ImDrawDataPtr drawData ) + { + if( drawData.TotalVtxCount == 0 ) + { + return; + } + + // Expand buffers if we need more room + if( drawData.TotalVtxCount > _vertexBufferSize ) + { + _vertexBuffer?.Dispose(); + + _vertexBufferSize = (int)( drawData.TotalVtxCount * 1.5f ); + _vertexBuffer = new VertexBuffer( Core.graphicsDevice, _vertexDeclaration, _vertexBufferSize, BufferUsage.None ); + _vertexData = new byte[_vertexBufferSize * _vertexDeclarationSize]; + } + + if( drawData.TotalIdxCount > _indexBufferSize ) + { + _indexBuffer?.Dispose(); + + _indexBufferSize = (int)( drawData.TotalIdxCount * 1.5f ); + _indexBuffer = new IndexBuffer( Core.graphicsDevice, IndexElementSize.SixteenBits, _indexBufferSize, BufferUsage.None ); + _indexData = new byte[_indexBufferSize * sizeof( ushort )]; + } + + // Copy ImGui's vertices and indices to a set of managed byte arrays + int vtxOffset = 0; + int idxOffset = 0; + + for( var n = 0; n < drawData.CmdListsCount; n++ ) + { + var cmdList = drawData.CmdListsRange[n]; + + 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 * _vertexDeclarationSize ); + Buffer.MemoryCopy( (void*)cmdList.IdxBuffer.Data, idxDstPtr, _indexData.Length, cmdList.IdxBuffer.Size * sizeof( ushort ) ); + } + + vtxOffset += cmdList.VtxBuffer.Size; + idxOffset += cmdList.IdxBuffer.Size; + } + + // Copy the managed byte arrays to the gpu vertex- and index buffers + _vertexBuffer.SetData( _vertexData, 0, drawData.TotalVtxCount * _vertexDeclarationSize ); + _indexBuffer.SetData( _indexData, 0, drawData.TotalIdxCount * sizeof( ushort ) ); + } + + unsafe void renderCommandLists( ImDrawDataPtr drawData ) + { + Core.graphicsDevice.SetVertexBuffer( _vertexBuffer ); + Core.graphicsDevice.Indices = _indexBuffer; + + int vtxOffset = 0; + int idxOffset = 0; + + for( int n = 0; n < drawData.CmdListsCount; n++ ) + { + var cmdList = drawData.CmdListsRange[n]; + for( int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; 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" ); + } + + 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] ); + foreach( var pass in effect.CurrentTechnique.Passes ) + { + pass.Apply(); #pragma warning disable CS0618 // // FNA does not expose an alternative method. - _graphicsDevice.DrawIndexedPrimitives( - primitiveType: PrimitiveType.TriangleList, - baseVertex: vtxOffset, - minVertexIndex: 0, - numVertices: cmdList.VtxBuffer.Size, - startIndex: idxOffset, - primitiveCount: (int)drawCmd.ElemCount / 3 - ); + Core.graphicsDevice.DrawIndexedPrimitives( + primitiveType: PrimitiveType.TriangleList, + baseVertex: vtxOffset, + minVertexIndex: 0, + numVertices: cmdList.VtxBuffer.Size, + startIndex: idxOffset, + primitiveCount: (int)drawCmd.ElemCount / 3 + ); #pragma warning restore CS0618 - } + } - idxOffset += (int)drawCmd.ElemCount; - } + idxOffset += (int)drawCmd.ElemCount; + } - vtxOffset += cmdList.VtxBuffer.Size; - } - } + vtxOffset += cmdList.VtxBuffer.Size; + } + } - #endregion Internals - } + #endregion Internals + } } \ No newline at end of file From 26251573a879707a74def69a6594214b2711b4e5 Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 14 Feb 2019 18:57:57 -0800 Subject: [PATCH 10/24] remove debug code --- project_name/ImGui/ImGuiFinalRenderDelegate.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/project_name/ImGui/ImGuiFinalRenderDelegate.cs b/project_name/ImGui/ImGuiFinalRenderDelegate.cs index 4d70719..8f2dbf7 100644 --- a/project_name/ImGui/ImGuiFinalRenderDelegate.cs +++ b/project_name/ImGui/ImGuiFinalRenderDelegate.cs @@ -50,20 +50,6 @@ namespace Nez 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(); From 7f05b2a1ec8b900fadca500158b81fc2f54d89ae Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 14 Feb 2019 18:59:45 -0800 Subject: [PATCH 11/24] dont allow dragging windows besides from title bar --- project_name/ImGui/ImGuiFinalRenderDelegate.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/project_name/ImGui/ImGuiFinalRenderDelegate.cs b/project_name/ImGui/ImGuiFinalRenderDelegate.cs index 8f2dbf7..7853005 100644 --- a/project_name/ImGui/ImGuiFinalRenderDelegate.cs +++ b/project_name/ImGui/ImGuiFinalRenderDelegate.cs @@ -18,6 +18,7 @@ namespace Nez { _imGuiRenderer = new ImGuiRenderer( Core.instance ); _imGuiRenderer.rebuildFontAtlas(); + ImGui.GetIO().ConfigWindowsMoveFromTitleBarOnly = true; } [Console.Command( "toggle-imgui", "Toggles the Dear ImGui renderer" )] From d0572471ffbaef6f90dbe66b0596b4cc0c73766d Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 14 Feb 2019 20:11:05 -0800 Subject: [PATCH 12/24] push everything up one directory so vs code works more betters --- .../.vscode => .vscode}/buildEffects.sh | 1 + {project_name/.vscode => .vscode}/launch.json | 4 +-- .../.vscode => .vscode}/processT4Templates.sh | 1 + .../.vscode => .vscode}/settings.json | 0 {project_name/.vscode => .vscode}/tasks.json | 18 ++++++------ README.md | 4 +-- getFNA.sh | 12 ++++---- project_name.code-workspace | 14 ---------- project_name.sln | 28 ++----------------- .../T4Templates/ContentPathGenerator.tt | 9 ++++-- project_name/project_name.sln | 24 ---------------- 11 files changed, 30 insertions(+), 85 deletions(-) rename {project_name/.vscode => .vscode}/buildEffects.sh (97%) rename {project_name/.vscode => .vscode}/launch.json (79%) rename {project_name/.vscode => .vscode}/processT4Templates.sh (97%) rename {project_name/.vscode => .vscode}/settings.json (100%) rename {project_name/.vscode => .vscode}/tasks.json (80%) delete mode 100644 project_name.code-workspace delete mode 100644 project_name/project_name.sln diff --git a/project_name/.vscode/buildEffects.sh b/.vscode/buildEffects.sh similarity index 97% rename from project_name/.vscode/buildEffects.sh rename to .vscode/buildEffects.sh index 5e0174e..1cd37eb 100755 --- a/project_name/.vscode/buildEffects.sh +++ b/.vscode/buildEffects.sh @@ -6,6 +6,7 @@ printf "Starting build process...\n" +cd project_name for file in `find ./Content/** -name "*.fx"` ; do # Hush, wine... diff --git a/project_name/.vscode/launch.json b/.vscode/launch.json similarity index 79% rename from project_name/.vscode/launch.json rename to .vscode/launch.json index d2adc58..cae6c1a 100644 --- a/project_name/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,12 +8,12 @@ "name": "Launch", "type": "mono", "request": "launch", - "program": "${workspaceFolder}/bin/Debug/project_name.exe", + "program": "${workspaceFolder}/project_name/bin/Debug/project_name.exe", "cwd": "${workspaceFolder}", "preLaunchTask": "Build (Debug)", "osx":{ "env": { - "DYLD_LIBRARY_PATH": "${workspaceFolder}/bin/Debug/osx/" + "DYLD_LIBRARY_PATH": "${workspaceFolder}/project_name/bin/Debug/osx/" }, } }, diff --git a/project_name/.vscode/processT4Templates.sh b/.vscode/processT4Templates.sh similarity index 97% rename from project_name/.vscode/processT4Templates.sh rename to .vscode/processT4Templates.sh index 06531f9..8461ec8 100755 --- a/project_name/.vscode/processT4Templates.sh +++ b/.vscode/processT4Templates.sh @@ -6,6 +6,7 @@ printf "Starting T4 processing...\n" +cd project_name for file in `find ./T4Templates/** -name "*.tt"` ; do # Build the template diff --git a/project_name/.vscode/settings.json b/.vscode/settings.json similarity index 100% rename from project_name/.vscode/settings.json rename to .vscode/settings.json diff --git a/project_name/.vscode/tasks.json b/.vscode/tasks.json similarity index 80% rename from project_name/.vscode/tasks.json rename to .vscode/tasks.json index dc3564f..d609b37 100644 --- a/project_name/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -12,7 +12,7 @@ { "label": "Clean Project", "type": "shell", - "command": "msbuild /t:clean /p:configuration=Debug ; msbuild /t:clean /p:configuration=Release", + "command": "msbuild project_name /t:clean /p:configuration=Debug ; msbuild project_name /t:clean /p:configuration=Release", "group": "build", "problemMatcher": "$msCompile", }, @@ -22,6 +22,7 @@ "type": "shell", "command": "msbuild", "args": [ + "project_name", "/p:configuration=Debug", "/t:build" ], @@ -35,6 +36,7 @@ "type": "shell", "command": "msbuild", "args": [ + "project_name", "/p:configuration=Release", "/t:build" ], @@ -47,13 +49,13 @@ "type": "shell", "group": "build", "osx":{ - "command": "DYLD_LIBRARY_PATH=${workspaceFolder}/bin/Debug/osx/ mono ${workspaceFolder}/bin/Debug/project_name.exe" + "command": "DYLD_LIBRARY_PATH=${workspaceFolder}/project_name/bin/Debug/osx/ mono ${workspaceFolder}/project_name/bin/Debug/project_name.exe" }, "windows":{ "command": "cmd", "args": [ "/k", - "${workspaceFolder}/bin/Debug/project_name.exe" + "${workspaceFolder}/project_name/bin/Debug/project_name.exe" ] }, "dependsOn": "Build (Debug)", @@ -65,13 +67,13 @@ "type": "shell", "group": "build", "osx":{ - "command": "DYLD_LIBRARY_PATH=${workspaceFolder}/bin/Release/osx/ mono ${workspaceFolder}/bin/Release/project_name.exe" + "command": "DYLD_LIBRARY_PATH=${workspaceFolder}/project_name/bin/Release/osx/ mono ${workspaceFolder}/project_name/bin/Release/project_name.exe" }, "windows":{ "command": "cmd", "args": [ "/k", - "${workspaceFolder}/bin/Release/project_name.exe" + "${workspaceFolder}/project_name/bin/Release/project_name.exe" ] }, "dependsOn": "Build (Release)", @@ -97,7 +99,7 @@ "group": "build", "command": "mono /Applications/Pipeline.app/Contents/MonoBundle/MGCB.exe /@:Content.mgcb", "options": { - "cwd": "${workspaceFolder}/CompiledContent" + "cwd": "${workspaceFolder}/project_name/CompiledContent" }, "problemMatcher": "$msCompile" }, @@ -108,7 +110,7 @@ "group": "build", "command": "mono /Applications/Pipeline.app/Contents/MonoBundle/MGCB.exe /@:Content.mgcb -r", "options": { - "cwd": "${workspaceFolder}/CompiledContent" + "cwd": "${workspaceFolder}/project_name/CompiledContent" }, "problemMatcher": "$msCompile" }, @@ -117,7 +119,7 @@ "label": "Open Pipeline Tool", "type": "shell", "group": "build", - "command": "export MONOGAME_PIPELINE_PROJECT=${workspaceFolder}/CompiledContent/Content.mgcb && /Applications/Pipeline.app/Contents/MacOS/Pipeline", + "command": "export MONOGAME_PIPELINE_PROJECT=${workspaceFolder}/project_name/CompiledContent/Content.mgcb && /Applications/Pipeline.app/Contents/MacOS/Pipeline", "problemMatcher": "$msCompile" }, diff --git a/README.md b/README.md index 2b0f96b..9ff168e 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ Start new FNA projects with Nez quickly and easily with handy setup scripts, a v ## Setup Instructions ## 1. Download and unzip the ZIP archive (don't clone the repo!) 2. Run `./getFNA.sh` (macOS) to download the latest Nez, FNA and fnalibs to the directory. You can run this script again if you want to update either FNA or the fnalibs at a later point. Nez is setup as a submodule so you can update it in the normal fashion. -3. Open the newly-created and named `PROJECT_NAME_YOU_CHOSE.code-workspace` file (or open the project folder in Visual Studio Code or the top-level sln in Visual Studio) +3. Open the root folder that contains the .sln file in Visual Studio Code or the .sln file directly in Visual Studio -That's it! Now you're ready to build and run the base project. When developing raw content (files not processed by the Pipeline tool) should be placed in the `Content` folder and anything that needs processing should go in the `CompiledContent` folder and added to the Pipeline tool. +That's it! Now you're ready to build and run the base project. When developing, raw content (files not processed by the Pipeline tool) should be placed in the `Content` folder and anything that needs processing should go in the `CompiledContent` folder and added to the Pipeline tool. The setup process will also init a git repo for you with Nez added as a submodule. diff --git a/getFNA.sh b/getFNA.sh index 2e1d67a..c39e27b 100755 --- a/getFNA.sh +++ b/getFNA.sh @@ -141,17 +141,17 @@ if [[ $newProjectName = 'exit' || -z "$newProjectName" ]]; then exit 1 fi -sed -i '' "s/project_name/$newProjectName/g" project_name.code-workspace sed -i '' "s/project_name/$newProjectName/g" project_name.sln sed -i '' "s/project_name/$newProjectName/g" .gitignore sed -i '' "s/project_name/$newProjectName/g" project_name/project_name.sln sed -i '' "s/project_name/$newProjectName/g" project_name/project_name.csproj -sed -i '' "s/project_name/$newProjectName/g" project_name/Game1.cs +sed -i '' "s/project_name/$newProjectName/g" project_name/Game1.cs sed -i '' "s/project_name/$newProjectName/g" project_name/Program.cs -sed -i '' "s/project_name/$newProjectName/g" project_name/.vscode/tasks.json -sed -i '' "s/project_name/$newProjectName/g" project_name/.vscode/launch.json +sed -i '' "s/project_name/$newProjectName/g" .vscode/tasks.json +sed -i '' "s/project_name/$newProjectName/g" .vscode/launch.json +sed -i '' "s/project_name/$newProjectName/g" .vscode/buildEffects.sh +sed -i '' "s/project_name/$newProjectName/g" .vscode/processT4Templates.sh -mv project_name.code-workspace "$newProjectName.code-workspace" mv project_name.sln "$newProjectName.sln" mv project_name/project_name.sln "project_name/$newProjectName.sln" mv project_name/project_name.csproj "project_name/$newProjectName.csproj" @@ -159,7 +159,7 @@ mv project_name/project_name.csproj.user "project_name/$newProjectName.csproj.us mv project_name "$newProjectName" git init -git submodule add git@github.com:prime31/Nez.FNA.git +git submodule add https://github.com/prime31/Nez.FNA.git cd Nez.FNA git submodule init git submodule update diff --git a/project_name.code-workspace b/project_name.code-workspace deleted file mode 100644 index a2a64fb..0000000 --- a/project_name.code-workspace +++ /dev/null @@ -1,14 +0,0 @@ -{ - "folders": [ - { - "path": "project_name" - }, - { - "path": "Nez.FNA/Nez/Nez.Portable" - } - ], - "settings": { - "omnisharp.autoStart": true, - "csharp.referencesCodeLens.enabled": false - } -} \ No newline at end of file diff --git a/project_name.sln b/project_name.sln index 76a9c87..8a4b74f 100644 --- a/project_name.sln +++ b/project_name.sln @@ -6,39 +6,15 @@ Debug|Any CPU = Debug|Any CPU Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x86 = Release|x86 + GlobalSection(ProjectConfigurationPlatforms) = postSolution -{D488C5AD-5192-4A08-88FD-22219586ED9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU -{D488C5AD-5192-4A08-88FD-22219586ED9F}.Debug|Any CPU.Build.0 = Debug|Any CPU -{D488C5AD-5192-4A08-88FD-22219586ED9F}.Debug|x86.ActiveCfg = Debug|x86 -{D488C5AD-5192-4A08-88FD-22219586ED9F}.Debug|x86.Build.0 = Debug|x86 -{D488C5AD-5192-4A08-88FD-22219586ED9F}.Release|Any CPU.ActiveCfg = Release|Any CPU -{D488C5AD-5192-4A08-88FD-22219586ED9F}.Release|Any CPU.Build.0 = Release|Any CPU -{D488C5AD-5192-4A08-88FD-22219586ED9F}.Release|x86.ActiveCfg = Release|x86 -{D488C5AD-5192-4A08-88FD-22219586ED9F}.Release|x86.Build.0 = Release|x86 -{35253CE1-C864-4CD3-8249-4D1319748E8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU -{35253CE1-C864-4CD3-8249-4D1319748E8F}.Debug|Any CPU.Build.0 = Debug|Any CPU -{35253CE1-C864-4CD3-8249-4D1319748E8F}.Debug|x86.ActiveCfg = Debug|Any CPU -{35253CE1-C864-4CD3-8249-4D1319748E8F}.Debug|x86.Build.0 = Debug|Any CPU -{35253CE1-C864-4CD3-8249-4D1319748E8F}.Release|Any CPU.ActiveCfg = Release|Any CPU -{35253CE1-C864-4CD3-8249-4D1319748E8F}.Release|Any CPU.Build.0 = Release|Any CPU -{35253CE1-C864-4CD3-8249-4D1319748E8F}.Release|x86.ActiveCfg = Release|Any CPU -{35253CE1-C864-4CD3-8249-4D1319748E8F}.Release|x86.Build.0 = Release|Any CPU -{F6DF8289-8138-41C7-B747-E672AFEE44A4}.Debug|Any CPU.ActiveCfg = Debug|x86 -{F6DF8289-8138-41C7-B747-E672AFEE44A4}.Debug|Any CPU.Build.0 = Debug|x86 -{F6DF8289-8138-41C7-B747-E672AFEE44A4}.Debug|x86.ActiveCfg = Debug|x86 -{F6DF8289-8138-41C7-B747-E672AFEE44A4}.Debug|x86.Build.0 = Debug|x86 -{F6DF8289-8138-41C7-B747-E672AFEE44A4}.Release|Any CPU.ActiveCfg = Release|x86 -{F6DF8289-8138-41C7-B747-E672AFEE44A4}.Release|Any CPU.Build.0 = Release|x86 -{F6DF8289-8138-41C7-B747-E672AFEE44A4}.Release|x86.ActiveCfg = Release|x86 -{F6DF8289-8138-41C7-B747-E672AFEE44A4}.Release|x86.Build.0 = Release|x86 -GlobalSection(SolutionProperties) = preSolution -HideSolutionNode = FALSE Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "project_name", "project_name\project_name.csproj", "{8C576ECC-147D-4B4A-8EC1-56533D26A178}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FNA", "FNA\FNA.csproj", "{35253CE1-C864-4CD3-8249-4D1319748E8F}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nez.FNA", "Nez.FNA\Nez.FNA\Nez.FNA.csproj", "{11A5855C-B12C-4F8D-B935-56F3D0B671C3}" EndProject + Global GlobalSection(ProjectConfigurationPlatforms) = postSolution {8C576ECC-147D-4B4A-8EC1-56533D26A178}.Debug|Any CPU.ActiveCfg = Debug|Any CPU diff --git a/project_name/T4Templates/ContentPathGenerator.tt b/project_name/T4Templates/ContentPathGenerator.tt index 3376cc3..876e4e6 100644 --- a/project_name/T4Templates/ContentPathGenerator.tt +++ b/project_name/T4Templates/ContentPathGenerator.tt @@ -49,6 +49,9 @@ namespace Nez <#+ + // all the valid file extensions we should add to the output file + private string[] fileExtensionsToCopy = new string[] { ".xnb", ".png", ".ogg", ".wav", ".fxb" }; + // C# reserved keywords private System.Collections.Generic.List keywords = new System.Collections.Generic.List { @@ -63,7 +66,7 @@ namespace Nez void printDirectoryClass( string dir, int depth, string sourceFolder ) { var dirInfo = new DirectoryInfo( dir ); - var firstIndent = new string( ' ', depth * 5 ); + var firstIndent = new string( ' ', depth * 4 ); var className = generateClassName( dirInfo.Name, true ); WriteLine( "{0}public static class {1}\n{2}{{", firstIndent, className, firstIndent ); @@ -81,10 +84,10 @@ namespace Nez // prints a const string for each file in the directory void printContentFiles( string dir, int depth, string sourceFolder ) { - var firstIndent = new string( '\t', depth ); + var firstIndent = new string( ' ', depth * 4 ); var files = Directory.EnumerateFiles( dir ) - .Where( s => s.EndsWith( ".xnb" ) || s.EndsWith( ".png" ) || s.EndsWith( ".ogg" ) || s.EndsWith( ".wav" ) || s.EndsWith( ".fxb" ) ); + .Where( s => Array.IndexOf( fileExtensionsToCopy, Path.GetExtension( s ) ) >= 0 ); foreach( var file in files ) { // clear out all of the path up to the sourceFolder so we get just the relative path to the Content folder diff --git a/project_name/project_name.sln b/project_name/project_name.sln deleted file mode 100644 index 8576363..0000000 --- a/project_name/project_name.sln +++ /dev/null @@ -1,24 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "project_name", "project_name.csproj", "{BD11109C-8FD1-4FFE-A3EF-8390A1EAE1A1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FNA", "../FNA/FNA.csproj", "{35253CE1-C864-4CD3-8249-4D1319748E8F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nez.FNA", "../Nez.FNA/Nez.FNA/Nez.FNA.csproj", "{11A5855C-B12C-4F8D-B935-56F3D0B671C3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nez.PipelineImporter", "../Nez.FNA/Nez/Nez.PipelineImporter/Nez.PipelineImporter.csproj", "{63E831F4-B847-4150-B5AF-CBE059EE27B8}" -EndProject - -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {BD11109C-8FD1-4FFE-A3EF-8390A1EAE1A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BD11109C-8FD1-4FFE-A3EF-8390A1EAE1A1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BD11109C-8FD1-4FFE-A3EF-8390A1EAE1A1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BD11109C-8FD1-4FFE-A3EF-8390A1EAE1A1}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal From 729d5fa918d5f1eb3349c3d7f3af109bb689793a Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 14 Feb 2019 20:40:40 -0800 Subject: [PATCH 13/24] clean up hidden files --- .vscode/settings.json | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 5c6593d..a301ce6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,13 +8,28 @@ "csharp.referencesCodeLens.enabled": false, "files.exclude": { - "obj": true, - "bin": true, - "CompiledContent/bin": true, - "CompiledContent/obj": true, - "CompiledContent/.mgstats": true, - "*.csproj.user": true, - "*.csproj": true, - "*.sln": true + "**/.[^v]*": true, // hide any file that start with a '.' but keep the .vscode folder + "getFNA.sh": true, + "MonoGameContent.targets": true, + ".vs": true, + "**/obj": true, + "**/bin": true, + ".gitignore": true, + ".gitmodules": true, + "README.md": true, + "fnalibs": true, + "**/CompiledContent/bin": true, + "**/CompiledContent/obj": true, + "**/CompiledContent/.mgstats": true, + "**/*.csproj.user": true, + "**/*.csproj": true, + "*.sln": true, + "FNA/[^src]*": true, // hide everything but the src folder + "Nez.FNA/[^Nez]*": true, // hide everything bug the Nez folder + "Nez.FNA/Nez.FNA*": true, // we miss the Nez.FNA* stuff with the above line so hide that too + "Nez.FNA/Nez/{[^DN]*}": true, // hide everything except what begins with D or N + "Nez.FNA/Nez/Nez.VisualStudio*": true, + "Nez.FNA/Nez/Nez.Xamarin*": true, + "Nez.FNA/Nez/Nez.Naming*": true, } } \ No newline at end of file From 3f135e7036f0b8f1ff1e89f10f1acd85b470659a Mon Sep 17 00:00:00 2001 From: prime31 Date: Fri, 15 Feb 2019 09:50:39 -0800 Subject: [PATCH 14/24] switch to replacing project_name to avoid ** --- .vscode/settings.json | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index a301ce6..c1b69bd 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,21 +8,20 @@ "csharp.referencesCodeLens.enabled": false, "files.exclude": { - "**/.[^v]*": true, // hide any file that start with a '.' but keep the .vscode folder + "**/.[^v]*": true, // hide any files that start with a '.' but keep the .vscode folder + ".vs": true, // Visual Studio settings "getFNA.sh": true, "MonoGameContent.targets": true, - ".vs": true, - "**/obj": true, - "**/bin": true, + "project_name/obj": true, + "project_name/bin": true, ".gitignore": true, ".gitmodules": true, "README.md": true, "fnalibs": true, - "**/CompiledContent/bin": true, - "**/CompiledContent/obj": true, - "**/CompiledContent/.mgstats": true, - "**/*.csproj.user": true, - "**/*.csproj": true, + "project_name/CompiledContent/bin": true, + "project_name/CompiledContent/obj": true, + "project_name/CompiledContent/.mgstats": true, + "project_name/*.csproj*": true, "*.sln": true, "FNA/[^src]*": true, // hide everything but the src folder "Nez.FNA/[^Nez]*": true, // hide everything bug the Nez folder @@ -32,4 +31,4 @@ "Nez.FNA/Nez/Nez.Xamarin*": true, "Nez.FNA/Nez/Nez.Naming*": true, } -} \ No newline at end of file +} From 3eaae226a0856ed6407670c36a08f5b30e93529c Mon Sep 17 00:00:00 2001 From: prime31 Date: Fri, 15 Feb 2019 09:51:52 -0800 Subject: [PATCH 15/24] process settings.json file --- getFNA.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/getFNA.sh b/getFNA.sh index c39e27b..8e72375 100755 --- a/getFNA.sh +++ b/getFNA.sh @@ -148,6 +148,7 @@ sed -i '' "s/project_name/$newProjectName/g" project_name/project_name.csproj sed -i '' "s/project_name/$newProjectName/g" project_name/Game1.cs sed -i '' "s/project_name/$newProjectName/g" project_name/Program.cs sed -i '' "s/project_name/$newProjectName/g" .vscode/tasks.json +sed -i '' "s/project_name/$newProjectName/g" .vscode/settings.json sed -i '' "s/project_name/$newProjectName/g" .vscode/launch.json sed -i '' "s/project_name/$newProjectName/g" .vscode/buildEffects.sh sed -i '' "s/project_name/$newProjectName/g" .vscode/processT4Templates.sh From 6b45dac4188aad6b85658bf635640cfdf821e16a Mon Sep 17 00:00:00 2001 From: prime31 Date: Fri, 15 Feb 2019 10:04:55 -0800 Subject: [PATCH 16/24] create the output dir before processing --- .vscode/processT4Templates.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.vscode/processT4Templates.sh b/.vscode/processT4Templates.sh index 8461ec8..f6339ff 100755 --- a/.vscode/processT4Templates.sh +++ b/.vscode/processT4Templates.sh @@ -7,6 +7,10 @@ printf "Starting T4 processing...\n" cd project_name + +# create our output directory +mkdir -p T4Templates/Output + for file in `find ./T4Templates/** -name "*.tt"` ; do # Build the template From 744b9154fdd5f8c8b20d86ace5664da7c9d0771a Mon Sep 17 00:00:00 2001 From: prime31 Date: Fri, 15 Feb 2019 10:24:46 -0800 Subject: [PATCH 17/24] spelling --- .vscode/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index c1b69bd..41175eb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -24,7 +24,7 @@ "project_name/*.csproj*": true, "*.sln": true, "FNA/[^src]*": true, // hide everything but the src folder - "Nez.FNA/[^Nez]*": true, // hide everything bug the Nez folder + "Nez.FNA/[^Nez]*": true, // hide everything but the Nez folder "Nez.FNA/Nez.FNA*": true, // we miss the Nez.FNA* stuff with the above line so hide that too "Nez.FNA/Nez/{[^DN]*}": true, // hide everything except what begins with D or N "Nez.FNA/Nez/Nez.VisualStudio*": true, From bd7a3a008dbaf422ff4f1a6e8733de89d4b25e5c Mon Sep 17 00:00:00 2001 From: prime31 Date: Fri, 15 Feb 2019 10:26:35 -0800 Subject: [PATCH 18/24] consolidate --- .vscode/settings.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 41175eb..ce3c2d5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -27,8 +27,6 @@ "Nez.FNA/[^Nez]*": true, // hide everything but the Nez folder "Nez.FNA/Nez.FNA*": true, // we miss the Nez.FNA* stuff with the above line so hide that too "Nez.FNA/Nez/{[^DN]*}": true, // hide everything except what begins with D or N - "Nez.FNA/Nez/Nez.VisualStudio*": true, - "Nez.FNA/Nez/Nez.Xamarin*": true, - "Nez.FNA/Nez/Nez.Naming*": true, + "Nez.FNA/Nez/Nez.*.*": true, } } From 4f960556b778ac10e88f581d478132dfe38a2e45 Mon Sep 17 00:00:00 2001 From: prime31 Date: Fri, 15 Feb 2019 10:34:16 -0800 Subject: [PATCH 19/24] simplify duped commands --- getFNA.sh | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/getFNA.sh b/getFNA.sh index 8e72375..b6f04d5 100755 --- a/getFNA.sh +++ b/getFNA.sh @@ -141,17 +141,11 @@ if [[ $newProjectName = 'exit' || -z "$newProjectName" ]]; then exit 1 fi -sed -i '' "s/project_name/$newProjectName/g" project_name.sln -sed -i '' "s/project_name/$newProjectName/g" .gitignore -sed -i '' "s/project_name/$newProjectName/g" project_name/project_name.sln -sed -i '' "s/project_name/$newProjectName/g" project_name/project_name.csproj -sed -i '' "s/project_name/$newProjectName/g" project_name/Game1.cs -sed -i '' "s/project_name/$newProjectName/g" project_name/Program.cs -sed -i '' "s/project_name/$newProjectName/g" .vscode/tasks.json -sed -i '' "s/project_name/$newProjectName/g" .vscode/settings.json -sed -i '' "s/project_name/$newProjectName/g" .vscode/launch.json -sed -i '' "s/project_name/$newProjectName/g" .vscode/buildEffects.sh -sed -i '' "s/project_name/$newProjectName/g" .vscode/processT4Templates.sh +# any files that need to have project_name replaced with the new project name should be here +files=(project_name.sln .gitignore project_name/project_name.sln project_name/project_name.csproj project_name/Game1.cs project_name/Program.cs .vscode/tasks.json .vscode/settings.json .vscode/launch.json .vscode/buildEffects.sh .vscode/processT4Templates.sh) +for file in "${files[@]}"; do + sed -i '' "s/project_name/$newProjectName/g" $file +done mv project_name.sln "$newProjectName.sln" mv project_name/project_name.sln "project_name/$newProjectName.sln" From dd48baaefe08de43a6e5548a813678cc9341f98e Mon Sep 17 00:00:00 2001 From: prime31 Date: Fri, 15 Feb 2019 10:51:36 -0800 Subject: [PATCH 20/24] VS fix --- project_name.sln | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/project_name.sln b/project_name.sln index 8a4b74f..66b23b2 100644 --- a/project_name.sln +++ b/project_name.sln @@ -1,20 +1,12 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -GlobalSection(SolutionConfigurationPlatforms) = preSolution -Debug|Any CPU = Debug|Any CPU -Debug|x86 = Debug|x86 -Release|Any CPU = Release|Any CPU -Release|x86 = Release|x86 - -GlobalSection(ProjectConfigurationPlatforms) = postSolution -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "project_name", "project_name\project_name.csproj", "{8C576ECC-147D-4B4A-8EC1-56533D26A178}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "project_name", "project_name\project_name.csproj", "{3CB9E917-FEF7-453F-A88D-6B85B552B058}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FNA", "FNA\FNA.csproj", "{35253CE1-C864-4CD3-8249-4D1319748E8F}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nez.FNA", "Nez.FNA\Nez.FNA\Nez.FNA.csproj", "{11A5855C-B12C-4F8D-B935-56F3D0B671C3}" EndProject - Global GlobalSection(ProjectConfigurationPlatforms) = postSolution {8C576ECC-147D-4B4A-8EC1-56533D26A178}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -25,6 +17,8 @@ Global {11A5855C-B12C-4F8D-B935-56F3D0B671C3}.Debug|Any CPU.Build.0 = Debug|Any CPU {AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Debug|Any CPU.ActiveCfg = Release|Any CPU {AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Debug|Any CPU.Build.0 = Release|Any CPU + {3CB9E917-FEF7-453F-A88D-6B85B552B058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CB9E917-FEF7-453F-A88D-6B85B552B058}.Debug|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU From ba222d1dc9cd770d33242e6020042e78677afcf2 Mon Sep 17 00:00:00 2001 From: prime31 Date: Fri, 15 Feb 2019 10:57:04 -0800 Subject: [PATCH 21/24] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9ff168e..10c48de 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Start new FNA projects with Nez quickly and easily with handy setup scripts, a v ## Setup Instructions ## 1. Download and unzip the ZIP archive (don't clone the repo!) -2. Run `./getFNA.sh` (macOS) to download the latest Nez, FNA and fnalibs to the directory. You can run this script again if you want to update either FNA or the fnalibs at a later point. Nez is setup as a submodule so you can update it in the normal fashion. +2. Run `./getFNA.sh` (macOS) to download the latest Nez, FNA and fnalibs to the directory. You can run this script again if you want to update either FNA or the fnalibs at a later point. If you get missing DLL errors when running in Visual Studio copy the FNA libs into your `/usr/local/lib` folder. With Visual Studio Code `DYLD_LIBRARY_PATH` is set automatically so it won't show the DLL not found error. Nez is setup as a submodule so you can update it in the normal fashion. 3. Open the root folder that contains the .sln file in Visual Studio Code or the .sln file directly in Visual Studio That's it! Now you're ready to build and run the base project. When developing, raw content (files not processed by the Pipeline tool) should be placed in the `Content` folder and anything that needs processing should go in the `CompiledContent` folder and added to the Pipeline tool. From ef9814253ce19e9da26a3f7523983d0566aa89e9 Mon Sep 17 00:00:00 2001 From: Mike Date: Sun, 17 Feb 2019 01:13:43 -0800 Subject: [PATCH 22/24] switch to new ImGuiManager --- .vscode/tasks.json | 5 +- project_name/Game1.cs | 8 +- .../ImGui/ImGuiFinalRenderDelegate.cs | 95 -------- project_name/ImGui/ImGuiManager.cs | 221 ++++++++++++++++++ project_name/ImGui/ImGuiRenderer.cs | 16 +- 5 files changed, 235 insertions(+), 110 deletions(-) delete mode 100644 project_name/ImGui/ImGuiFinalRenderDelegate.cs create mode 100644 project_name/ImGui/ImGuiManager.cs diff --git a/.vscode/tasks.json b/.vscode/tasks.json index d609b37..3d8b600 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -97,10 +97,7 @@ "label": "Build Content", "type": "shell", "group": "build", - "command": "mono /Applications/Pipeline.app/Contents/MonoBundle/MGCB.exe /@:Content.mgcb", - "options": { - "cwd": "${workspaceFolder}/project_name/CompiledContent" - }, + "command": "msbuild /t:BuildContent", "problemMatcher": "$msCompile" }, diff --git a/project_name/Game1.cs b/project_name/Game1.cs index 45d22e3..e474f16 100644 --- a/project_name/Game1.cs +++ b/project_name/Game1.cs @@ -18,9 +18,6 @@ namespace project_name // setup a Scene so we have something to show var newScene = new Scene(); newScene.addRenderer(new DefaultRenderer()); - - // optionally render Nez in an ImGui window - newScene.finalRenderDelegate = new ImGuiFinalRenderDelegate(); var logo = newScene.content.Load("nez-logo-black"); newScene.createEntity("logo") @@ -28,6 +25,11 @@ namespace project_name .addComponent(new Nez.Sprites.Sprite(logo)); scene = newScene; + + // optionally render Nez in an ImGui window + var imGuiManager = new ImGuiManager(); + Core.registerGlobalManager( imGuiManager ); + imGuiManager.setEnabled( true ); } } } \ No newline at end of file diff --git a/project_name/ImGui/ImGuiFinalRenderDelegate.cs b/project_name/ImGui/ImGuiFinalRenderDelegate.cs deleted file mode 100644 index 7853005..0000000 --- a/project_name/ImGui/ImGuiFinalRenderDelegate.cs +++ /dev/null @@ -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 - } -} diff --git a/project_name/ImGui/ImGuiManager.cs b/project_name/ImGui/ImGuiManager.cs new file mode 100644 index 0000000..d7a4b8f --- /dev/null +++ b/project_name/ImGui/ImGuiManager.cs @@ -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 drawCommands = new List(); + 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(); + } + + /// + /// this is where we issue any and all ImGui commands to be drawn + /// + 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 + + /// + /// registers an Action that will be called and any ImGui drawing can be done in it + /// + /// + public void registerDrawCommand( Action drawCommand ) + { + drawCommands.Add( drawCommand ); + } + + /// + /// removes the Action from the draw commands + /// + /// + public void unregisterDrawCommand( Action drawCommand ) + { + drawCommands.Remove( drawCommand ); + } + + /// + /// adds the font to the atlas and regenerates it + /// + /// + /// + /// + 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(); + if( service == null ) + { + service = new ImGuiManager(); + Core.registerGlobalManager( service ); + } + + service.setEnabled( !service.enabled ); + } + + } +} \ No newline at end of file diff --git a/project_name/ImGui/ImGuiRenderer.cs b/project_name/ImGui/ImGuiRenderer.cs index 41c7523..0905145 100644 --- a/project_name/ImGui/ImGuiRenderer.cs +++ b/project_name/ImGui/ImGuiRenderer.cs @@ -9,10 +9,12 @@ using System.Runtime.InteropServices; namespace ImGuiNET { /// - /// ImGui renderer for use with XNA-likes (FNA and MonoGame) + /// ImGui renderer for use with XNA-likes (FNA & MonoGame) /// public class ImGuiRenderer { + public ImFontPtr defaultFontPtr { get; private set; } + // Graphics BasicEffect _effect; RasterizerState _rasterizerState; @@ -29,7 +31,7 @@ namespace ImGuiNET int _indexBufferSize; // Textures - Dictionary _loadedTextures; + Dictionary _loadedTextures = new Dictionary(); int _textureId; IntPtr? _fontTextureId; @@ -52,10 +54,7 @@ namespace ImGuiNET new VertexElement( 16, VertexElementFormat.Color, VertexElementUsage.Color, 0 ) ); - var context = ImGui.CreateContext(); - ImGui.SetCurrentContext( context ); - - _loadedTextures = new Dictionary(); + ImGui.SetCurrentContext( ImGui.CreateContext() ); _rasterizerState = new RasterizerState() { @@ -79,6 +78,9 @@ namespace ImGuiNET { // Get font texture from ImGui var io = ImGui.GetIO(); + + defaultFontPtr = ImGui.GetIO().Fonts.AddFontDefault(); + io.Fonts.GetTexDataAsRGBA32( out byte* pixelData, out int width, out int height, out int bytesPerPixel ); // Copy the data to a managed array @@ -187,8 +189,6 @@ namespace ImGuiNET ImGui.GetIO().AddInputCharacter( c ); }; /////////////////////////////////////////// - - ImGui.GetIO().Fonts.AddFontDefault(); } /// From 2e933229b101f1a082ad09b82ccf542b56e15283 Mon Sep 17 00:00:00 2001 From: Mike Date: Sun, 17 Feb 2019 13:09:54 -0800 Subject: [PATCH 23/24] move to using Nez instead of Nez.FNA --- .vscode/settings.json | 17 +- .vscode/tasks.json | 3 + getFNA.sh | 11 +- project_name.sln | 15 +- project_name/Game1.cs | 1 + project_name/ImGui/ImGuiManager.cs | 221 ---------------- project_name/ImGui/ImGuiRenderer.cs | 389 ---------------------------- project_name/project_name.csproj | 31 +-- 8 files changed, 27 insertions(+), 661 deletions(-) delete mode 100644 project_name/ImGui/ImGuiManager.cs delete mode 100644 project_name/ImGui/ImGuiRenderer.cs diff --git a/.vscode/settings.json b/.vscode/settings.json index ce3c2d5..2882144 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,22 +11,19 @@ "**/.[^v]*": true, // hide any files that start with a '.' but keep the .vscode folder ".vs": true, // Visual Studio settings "getFNA.sh": true, + "imgui.ini": true, "MonoGameContent.targets": true, - "project_name/obj": true, - "project_name/bin": true, + "**/obj": true, + "**/bin": true, ".gitignore": true, ".gitmodules": true, "README.md": true, "fnalibs": true, - "project_name/CompiledContent/bin": true, - "project_name/CompiledContent/obj": true, "project_name/CompiledContent/.mgstats": true, - "project_name/*.csproj*": true, - "*.sln": true, + "**/*.csproj*": true, + "**/*.sln": true, "FNA/[^src]*": true, // hide everything but the src folder - "Nez.FNA/[^Nez]*": true, // hide everything but the Nez folder - "Nez.FNA/Nez.FNA*": true, // we miss the Nez.FNA* stuff with the above line so hide that too - "Nez.FNA/Nez/{[^DN]*}": true, // hide everything except what begins with D or N - "Nez.FNA/Nez/Nez.*.*": true, + "Nez/{[^DN]*}": true, // hide everything except what begins with D or N + "Nez/Nez.*.*": true, // hide the files in the root of the repo } } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 3d8b600..e27f8d5 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -98,6 +98,9 @@ "type": "shell", "group": "build", "command": "msbuild /t:BuildContent", + "options": { + "cwd": "${workspaceFolder}/project_name" + }, "problemMatcher": "$msCompile" }, diff --git a/getFNA.sh b/getFNA.sh index b6f04d5..64a2e36 100755 --- a/getFNA.sh +++ b/getFNA.sh @@ -82,6 +82,7 @@ function getLibs() tar xjC $MY_DIR/fnalibs -f $MY_DIR/fnalibs.tar.bz2 if [ $? -eq 0 ]; then echo "Finished decompressing!" + echo "" rm $MY_DIR/fnalibs.tar.bz2 else >&2 echo "ERROR: Unable to decompress successfully." @@ -142,7 +143,7 @@ if [[ $newProjectName = 'exit' || -z "$newProjectName" ]]; then fi # any files that need to have project_name replaced with the new project name should be here -files=(project_name.sln .gitignore project_name/project_name.sln project_name/project_name.csproj project_name/Game1.cs project_name/Program.cs .vscode/tasks.json .vscode/settings.json .vscode/launch.json .vscode/buildEffects.sh .vscode/processT4Templates.sh) +files=(project_name.sln .gitignore project_name/project_name.csproj project_name/Game1.cs project_name/Program.cs .vscode/tasks.json .vscode/settings.json .vscode/launch.json .vscode/buildEffects.sh .vscode/processT4Templates.sh) for file in "${files[@]}"; do sed -i '' "s/project_name/$newProjectName/g" $file done @@ -154,16 +155,16 @@ mv project_name/project_name.csproj.user "project_name/$newProjectName.csproj.us mv project_name "$newProjectName" git init -git submodule add https://github.com/prime31/Nez.FNA.git -cd Nez.FNA +git submodule add https://github.com/prime31/Nez.git +cd Nez git submodule init git submodule update command -v pbcopy > /dev/null 2>&1 if [ ! $? -eq 0 ]; then - printf "\n\nManually run the following command:\n\nnuget restore Nez.FNA/Nez/Nez.sln && msbuild Nez.FNA/Nez/Nez.sln && msbuild /t:restore $newProjectName\n\n" + printf "\n\nManually run the following command:\n\nnuget restore Nez/Nez.sln && msbuild Nez/Nez.sln && msbuild /t:restore $newProjectName\n\n" else - echo "nuget restore Nez.FNA/Nez/Nez.sln && msbuild Nez.FNA/Nez/Nez.sln && msbuild /t:restore $newProjectName" | pbcopy + echo "nuget restore Nez/Nez.sln && msbuild Nez/Nez.sln && msbuild /t:restore $newProjectName" | pbcopy echo "" echo "A build command was copied to your clipboard. Paste and run it now." echo "" diff --git a/project_name.sln b/project_name.sln index 66b23b2..daf790d 100644 --- a/project_name.sln +++ b/project_name.sln @@ -5,20 +5,21 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "project_name", "project_nam EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FNA", "FNA\FNA.csproj", "{35253CE1-C864-4CD3-8249-4D1319748E8F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nez.FNA", "Nez.FNA\Nez.FNA\Nez.FNA.csproj", "{11A5855C-B12C-4F8D-B935-56F3D0B671C3}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nez.FNA", "Nez\Nez.Portable\Nez.FNA.csproj", "{11A5855C-B12C-4F8D-B935-56F3D0B671C3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nez.FNA.ImGui", "Nez\Nez.ImGui\Nez.FNA.ImGui.csproj", "{16DA6D66-4DFD-46D4-A367-C02B48B80CAA}" +EndProject + Global GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8C576ECC-147D-4B4A-8EC1-56533D26A178}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8C576ECC-147D-4B4A-8EC1-56533D26A178}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CB9E917-FEF7-453F-A88D-6B85B552B058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CB9E917-FEF7-453F-A88D-6B85B552B058}.Debug|Any CPU.Build.0 = Debug|Any CPU {35253CE1-C864-4CD3-8249-4D1319748E8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {35253CE1-C864-4CD3-8249-4D1319748E8F}.Debug|Any CPU.Build.0 = Debug|Any CPU {11A5855C-B12C-4F8D-B935-56F3D0B671C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {11A5855C-B12C-4F8D-B935-56F3D0B671C3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Debug|Any CPU.ActiveCfg = Release|Any CPU - {AD548A1D-01B2-410E-B3ED-ADAC05C3C4A3}.Debug|Any CPU.Build.0 = Release|Any CPU - {3CB9E917-FEF7-453F-A88D-6B85B552B058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3CB9E917-FEF7-453F-A88D-6B85B552B058}.Debug|Any CPU.Build.0 = Debug|Any CPU + {16DA6D66-4DFD-46D4-A367-C02B48B80CAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {16DA6D66-4DFD-46D4-A367-C02B48B80CAA}.Debug|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/project_name/Game1.cs b/project_name/Game1.cs index e474f16..9f9faa5 100644 --- a/project_name/Game1.cs +++ b/project_name/Game1.cs @@ -1,4 +1,5 @@ using Nez; +using Nez.ImGuiTools; namespace project_name { diff --git a/project_name/ImGui/ImGuiManager.cs b/project_name/ImGui/ImGuiManager.cs deleted file mode 100644 index d7a4b8f..0000000 --- a/project_name/ImGui/ImGuiManager.cs +++ /dev/null @@ -1,221 +0,0 @@ -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 drawCommands = new List(); - 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(); - } - - /// - /// this is where we issue any and all ImGui commands to be drawn - /// - 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 - - /// - /// registers an Action that will be called and any ImGui drawing can be done in it - /// - /// - public void registerDrawCommand( Action drawCommand ) - { - drawCommands.Add( drawCommand ); - } - - /// - /// removes the Action from the draw commands - /// - /// - public void unregisterDrawCommand( Action drawCommand ) - { - drawCommands.Remove( drawCommand ); - } - - /// - /// adds the font to the atlas and regenerates it - /// - /// - /// - /// - 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(); - if( service == null ) - { - service = new ImGuiManager(); - Core.registerGlobalManager( service ); - } - - service.setEnabled( !service.enabled ); - } - - } -} \ No newline at end of file diff --git a/project_name/ImGui/ImGuiRenderer.cs b/project_name/ImGui/ImGuiRenderer.cs deleted file mode 100644 index 0905145..0000000 --- a/project_name/ImGui/ImGuiRenderer.cs +++ /dev/null @@ -1,389 +0,0 @@ -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 -{ - /// - /// ImGui renderer for use with XNA-likes (FNA & MonoGame) - /// - public class ImGuiRenderer - { - public ImFontPtr defaultFontPtr { get; private set; } - - // Graphics - BasicEffect _effect; - RasterizerState _rasterizerState; - - readonly VertexDeclaration _vertexDeclaration; - readonly int _vertexDeclarationSize; - - byte[] _vertexData; - VertexBuffer _vertexBuffer; - int _vertexBufferSize; - - byte[] _indexData; - IndexBuffer _indexBuffer; - int _indexBufferSize; - - // Textures - Dictionary _loadedTextures = new Dictionary(); - - int _textureId; - IntPtr? _fontTextureId; - - // Input - int _scrollWheelValue; - - List _keys = new List(); - - 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 ) - ); - - ImGui.SetCurrentContext( ImGui.CreateContext() ); - - _rasterizerState = new RasterizerState() - { - CullMode = CullMode.None, - DepthBias = 0, - FillMode = FillMode.Solid, - MultiSampleAntiAlias = false, - ScissorTestEnable = true, - SlopeScaleDepthBias = 0 - }; - - setupInput(); - } - - #region ImGuiRenderer - - /// - /// Creates a texture and loads the font data from ImGui. Should be called when the is initialized but before any rendering is done - /// - public unsafe void rebuildFontAtlas() - { - // Get font texture from ImGui - var io = ImGui.GetIO(); - - defaultFontPtr = ImGui.GetIO().Fonts.AddFontDefault(); - - io.Fonts.GetTexDataAsRGBA32( out byte* pixelData, out int width, out int height, out int bytesPerPixel ); - - // Copy the data to a managed array - var pixels = new byte[width * height * bytesPerPixel]; - Marshal.Copy( new IntPtr( pixelData ), pixels, 0, pixels.Length ); - - // Create and register the texture as an XNA texture - var tex2d = new Texture2D( Core.graphicsDevice, width, height, false, SurfaceFormat.Color ); - tex2d.SetData( pixels ); - - // 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 ); - - // Let ImGui know where to find the texture - io.Fonts.SetTexID( _fontTextureId.Value ); - io.Fonts.ClearTexData(); // Clears CPU side texture data - } - - /// - /// Creates a pointer to a texture, which can be passed through ImGui calls such as . That pointer is then used by ImGui to let us know what texture to draw - /// - public IntPtr bindTexture( Texture2D texture ) - { - var id = new IntPtr( _textureId++ ); - _loadedTextures.Add( id, texture ); - return id; - } - - /// - /// Removes a previously created texture pointer, releasing its reference and allowing it to be deallocated - /// - public void unbindTexture( IntPtr textureId ) - { - _loadedTextures.Remove( textureId ); - } - - /// - /// Sets up ImGui for a new frame, should be called at frame start - /// - public void beforeLayout( float deltaTime ) - { - ImGui.GetIO().DeltaTime = deltaTime; - updateInput(); - ImGui.NewFrame(); - } - - /// - /// 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 - /// - public void afterLayout() - { - ImGui.Render(); - unsafe { renderDrawData( ImGui.GetDrawData() ); } - } - - #endregion ImGuiRenderer - - #region Setup & Update - - /// - /// Maps ImGui keys to XNA keys. We use this later on to tell ImGui what keys were pressed - /// - void setupInput() - { - var io = ImGui.GetIO(); - - _keys.Add( io.KeyMap[(int)ImGuiKey.Tab] = (int)Keys.Tab ); - _keys.Add( io.KeyMap[(int)ImGuiKey.LeftArrow] = (int)Keys.Left ); - _keys.Add( io.KeyMap[(int)ImGuiKey.RightArrow] = (int)Keys.Right ); - _keys.Add( io.KeyMap[(int)ImGuiKey.UpArrow] = (int)Keys.Up ); - _keys.Add( io.KeyMap[(int)ImGuiKey.DownArrow] = (int)Keys.Down ); - _keys.Add( io.KeyMap[(int)ImGuiKey.PageUp] = (int)Keys.PageUp ); - _keys.Add( io.KeyMap[(int)ImGuiKey.PageDown] = (int)Keys.PageDown ); - _keys.Add( io.KeyMap[(int)ImGuiKey.Home] = (int)Keys.Home ); - _keys.Add( io.KeyMap[(int)ImGuiKey.End] = (int)Keys.End ); - _keys.Add( io.KeyMap[(int)ImGuiKey.Delete] = (int)Keys.Delete ); - _keys.Add( io.KeyMap[(int)ImGuiKey.Backspace] = (int)Keys.Back ); - _keys.Add( io.KeyMap[(int)ImGuiKey.Enter] = (int)Keys.Enter ); - _keys.Add( io.KeyMap[(int)ImGuiKey.Escape] = (int)Keys.Escape ); - _keys.Add( io.KeyMap[(int)ImGuiKey.A] = (int)Keys.A ); - _keys.Add( io.KeyMap[(int)ImGuiKey.C] = (int)Keys.C ); - _keys.Add( io.KeyMap[(int)ImGuiKey.V] = (int)Keys.V ); - _keys.Add( io.KeyMap[(int)ImGuiKey.X] = (int)Keys.X ); - _keys.Add( io.KeyMap[(int)ImGuiKey.Y] = (int)Keys.Y ); - _keys.Add( io.KeyMap[(int)ImGuiKey.Z] = (int)Keys.Z ); - - - // MonoGame-specific ////////////////////// - // _game.Window.TextInput += (s, a) => - // { - // if (a.Character == '\t') return; - - // io.AddInputCharacter(a.Character); - // }; - /////////////////////////////////////////// - - // FNA-specific /////////////////////////// - TextInputEXT.TextInput += c => - { - if( c == '\t' ) return; - - ImGui.GetIO().AddInputCharacter( c ); - }; - /////////////////////////////////////////// - } - - /// - /// Updates the to the current matrices and texture - /// - Effect updateEffect( Texture2D texture ) - { - _effect = _effect ?? new BasicEffect( Core.graphicsDevice ); - - var io = ImGui.GetIO(); - - // MonoGame-specific ////////////////////// - //var offset = .5f; - /////////////////////////////////////////// - - // FNA-specific /////////////////////////// - var offset = 0f; - /////////////////////////////////////////// - - _effect.World = Matrix.Identity; - _effect.View = Matrix.Identity; - _effect.Projection = Matrix.CreateOrthographicOffCenter( offset, io.DisplaySize.X + offset, io.DisplaySize.Y + offset, offset, -1f, 1f ); - _effect.TextureEnabled = true; - _effect.Texture = texture; - _effect.VertexColorEnabled = true; - - return _effect; - } - - /// - /// Sends XNA input state to ImGui - /// - void updateInput() - { - var io = ImGui.GetIO(); - - var mouse = Mouse.GetState(); - var keyboard = Keyboard.GetState(); - - for( int i = 0; i < _keys.Count; i++ ) - { - io.KeysDown[_keys[i]] = keyboard.IsKeyDown( (Keys)_keys[i] ); - } - - io.KeyShift = keyboard.IsKeyDown( Keys.LeftShift ) || keyboard.IsKeyDown( Keys.RightShift ); - io.KeyCtrl = keyboard.IsKeyDown( Keys.LeftControl ) || keyboard.IsKeyDown( Keys.RightControl ); - 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( 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 ); - - io.MouseDown[0] = mouse.LeftButton == ButtonState.Pressed; - io.MouseDown[1] = mouse.RightButton == ButtonState.Pressed; - io.MouseDown[2] = mouse.MiddleButton == ButtonState.Pressed; - - var scrollDelta = mouse.ScrollWheelValue - _scrollWheelValue; - io.MouseWheel = scrollDelta > 0 ? 1 : scrollDelta < 0 ? -1 : 0; - _scrollWheelValue = mouse.ScrollWheelValue; - } - - #endregion Setup & Update - - #region Internals - - /// - /// Gets the geometry as set up by ImGui and sends it to the graphics device - /// - void renderDrawData( ImDrawDataPtr drawData ) - { - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers - var lastViewport = Core.graphicsDevice.Viewport; - var lastScissorBox = Core.graphicsDevice.ScissorRectangle; - - 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 - Core.graphicsDevice.Viewport = new Viewport( 0, 0, Core.graphicsDevice.PresentationParameters.BackBufferWidth, Core.graphicsDevice.PresentationParameters.BackBufferHeight ); - - updateBuffers( drawData ); - renderCommandLists( drawData ); - - // Restore modified state - Core.graphicsDevice.Viewport = lastViewport; - Core.graphicsDevice.ScissorRectangle = lastScissorBox; - } - - unsafe void updateBuffers( ImDrawDataPtr drawData ) - { - if( drawData.TotalVtxCount == 0 ) - { - return; - } - - // Expand buffers if we need more room - if( drawData.TotalVtxCount > _vertexBufferSize ) - { - _vertexBuffer?.Dispose(); - - _vertexBufferSize = (int)( drawData.TotalVtxCount * 1.5f ); - _vertexBuffer = new VertexBuffer( Core.graphicsDevice, _vertexDeclaration, _vertexBufferSize, BufferUsage.None ); - _vertexData = new byte[_vertexBufferSize * _vertexDeclarationSize]; - } - - if( drawData.TotalIdxCount > _indexBufferSize ) - { - _indexBuffer?.Dispose(); - - _indexBufferSize = (int)( drawData.TotalIdxCount * 1.5f ); - _indexBuffer = new IndexBuffer( Core.graphicsDevice, IndexElementSize.SixteenBits, _indexBufferSize, BufferUsage.None ); - _indexData = new byte[_indexBufferSize * sizeof( ushort )]; - } - - // Copy ImGui's vertices and indices to a set of managed byte arrays - int vtxOffset = 0; - int idxOffset = 0; - - for( var n = 0; n < drawData.CmdListsCount; n++ ) - { - var cmdList = drawData.CmdListsRange[n]; - - 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 * _vertexDeclarationSize ); - Buffer.MemoryCopy( (void*)cmdList.IdxBuffer.Data, idxDstPtr, _indexData.Length, cmdList.IdxBuffer.Size * sizeof( ushort ) ); - } - - vtxOffset += cmdList.VtxBuffer.Size; - idxOffset += cmdList.IdxBuffer.Size; - } - - // Copy the managed byte arrays to the gpu vertex- and index buffers - _vertexBuffer.SetData( _vertexData, 0, drawData.TotalVtxCount * _vertexDeclarationSize ); - _indexBuffer.SetData( _indexData, 0, drawData.TotalIdxCount * sizeof( ushort ) ); - } - - unsafe void renderCommandLists( ImDrawDataPtr drawData ) - { - Core.graphicsDevice.SetVertexBuffer( _vertexBuffer ); - Core.graphicsDevice.Indices = _indexBuffer; - - int vtxOffset = 0; - int idxOffset = 0; - - for( int n = 0; n < drawData.CmdListsCount; n++ ) - { - var cmdList = drawData.CmdListsRange[n]; - for( int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; 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" ); - } - - 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] ); - foreach( var pass in effect.CurrentTechnique.Passes ) - { - pass.Apply(); - -#pragma warning disable CS0618 // // FNA does not expose an alternative method. - Core.graphicsDevice.DrawIndexedPrimitives( - primitiveType: PrimitiveType.TriangleList, - baseVertex: vtxOffset, - minVertexIndex: 0, - numVertices: cmdList.VtxBuffer.Size, - startIndex: idxOffset, - primitiveCount: (int)drawCmd.ElemCount / 3 - ); -#pragma warning restore CS0618 - } - - idxOffset += (int)drawCmd.ElemCount; - } - - vtxOffset += cmdList.VtxBuffer.Size; - } - } - - #endregion Internals - } -} \ No newline at end of file diff --git a/project_name/project_name.csproj b/project_name/project_name.csproj index e257a0f..c73e4ef 100644 --- a/project_name/project_name.csproj +++ b/project_name/project_name.csproj @@ -13,7 +13,8 @@ - + + @@ -71,32 +72,4 @@ PreserveNewest - - - - $(NuGetPackageRoot)\imgui.net\**\runtimes\ - - - - - %(Filename)%(Extension) - PreserveNewest - - - %(Filename)%(Extension) - PreserveNewest - - - libcimgui.dylib - PreserveNewest - - - %(Filename)%(Extension) - PreserveNewest - - - - - - From 624c8aaf7aebe5094f523af653d665b546316d48 Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 18 Feb 2019 07:11:26 -0800 Subject: [PATCH 24/24] include Nez built-ins --- project_name/project_name.csproj | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/project_name/project_name.csproj b/project_name/project_name.csproj index c73e4ef..f6134a9 100644 --- a/project_name/project_name.csproj +++ b/project_name/project_name.csproj @@ -17,6 +17,18 @@ + + + + Content/nez/effects/%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + Content/nez/textures/%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + +