MonoGame.Forms - Create your Editor Environment!

MonoGame.Forms 2.0 - DirectX and OpenGL

The next big major release:

  • 60 commits
  • 116 files changed

To sum this release up:

  • Created the SwapChainRenderTarget_GL to enable drawing of the BackBufferData in DesktopGL projects.
  • It’s now possible to change the BackColor and the ForeColor of custom controls.
  • Using the MonoGame Logo as GraphicsDeviceControl Image.
  • The Documentation (Wiki) now differentiates between the MonoGame.Forms.DX.dll and the MonoGame.Forms.GL.dll.
  • Dev Notes:
    • Updated nuspec files for DX and GL projects.
    • Added .target file to the GL project to automatically include and copy neccessary libs and files.
    • Automatically building nuget packages on Release builds.
    • Created .batch file to push all NuGet packages with one double click.

Change the style of your controls to keep the overview and feel of your custom editor project!

Note: The MonoGame logo is placed automatically inside a newly
created control to make it clear, that it is a render control with
MonoGame functionality!

This is an accepted idea from @SpiceyWolf


A documentation (Wiki) example:

Wiki

I also updated the Readme.md file. Be sure to check it out!


NuGet
NuGet

The old MonoGame.Forms library is still available on NuGet. Take a look at the Readme to get more information.

Thank you! :heart:

lol glad u liked the icon on the control idea xD I felt it made the lib feel more crisp >: P

1 Like

Yeah you’re right - If I want close app if it still running ( hidden from background )

Now @SandboxBlizz my dear I have got Gtk Sharp 2.x with MonoGame :smiley:

But I don’t know why does it not show textures because I already copy to debug directory.

Real code:

Gtk2Backend.cs

using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using Microsoft.Xna.Framework;

namespace Microsoft.XNA.Framework.Gtk2
{
    public class Gtk2Backend
    {
        /// <summary>
        /// Gets or Sets the backend ContentManager.
        /// </summary>
        public static ContentManager Content
        {
            get { return MasterWindow.Instance.Content; }
            set { MasterWindow.Instance.Content = value; }
        }

        /// <summary>
        /// Gets the backend GraphicsDevice.
        /// </summary>
        public static GraphicsDevice GraphicsDevice
        {
            get { return MasterWindow.Instance.GraphicsDevice; }
        }

        /// <summary>
        /// Gets the backend GraphicsDeviceManager.
        /// </summary>
        public static GraphicsDeviceManager GraphicsDeviceManager
        {
            get { return MasterWindow.Instance.DeviceManager; }
        }

        /// <summary>
        /// Begins the drawing process making present unusable.
        /// </summary>
        public static bool BeginDraw(uint width, uint height)
        {
            return MasterWindow.Instance.BeginRender(width, height);
        }

        /// <summary>
        /// Finalizes the drawing and makes present usable.
        /// </summary>
        public static void EndDraw()
        {
            MasterWindow.Instance.EndRender();
        }

        /// <summary>
        /// Returns a bitmap of the BackBuffer to be drawn to a control.
        /// </summary>
        public static Bitmap Present()
        {
            return MasterWindow.Instance.BackBuffer;
        }

        private class MasterWindow : Game
        {
            internal GraphicsDeviceManager DeviceManager;
            internal Bitmap BackBuffer;
            private bool isDrawing;

            #region Singleton
            private static readonly Lazy<MasterWindow> _instance = new Lazy<MasterWindow>
                (() => new MasterWindow(), System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);

            internal static MasterWindow Instance { get { return _instance.Value; } }

            // Constructor
            private MasterWindow() : base()
            {
                // Init Graphics Device
                DeviceManager = new GraphicsDeviceManager(this);

                // Make sure the entire game window is created
                RunOneFrame();
            }

            protected override void Dispose(bool disposing)
            {
                if (BackBuffer != null)
                {
                    BackBuffer.Dispose();
                    BackBuffer = null;
                }

                DeviceManager.Dispose();
                base.Dispose(disposing);
            }
            #endregion

            internal bool BeginRender(uint width, uint height)
            {
                if (isDrawing)
                    throw new Exception("Draw operation already in progress!");

                // Clear BackBuffer if doing new render
                if (BackBuffer != null)
                {
                    BackBuffer.Dispose();
                    BackBuffer = null;
                }

                // Prepair the screen
                DeviceManager.PreferredBackBufferWidth = (Int32)width;
                DeviceManager.PreferredBackBufferHeight = (Int32)height;

                DeviceManager.ApplyChanges();

                isDrawing = true;
                return true;
            }

            internal void EndRender()
            {
                // Exit if not drawing anything
                if (!isDrawing) return;

                // Create Surface Image
                var width = DeviceManager.PreferredBackBufferWidth;
                var height = DeviceManager.PreferredBackBufferHeight;

                var bmp = new Bitmap(width, height, PixelFormat.Format32bppRgb);
                var bmpData = bmp.LockBits(
                    new System.Drawing.Rectangle(0, 0, width, height),
                    ImageLockMode.WriteOnly,
                    PixelFormat.Format32bppRgb);
                var pixelData = new int[width * height];

                // Get buffer data
                GraphicsDevice.GetBackBufferData(pixelData);
                for (int i = 0; i < pixelData.Length; i++)
#pragma warning disable // Caused by bitwise function requiring uint to int conversion
                    pixelData[i] = (int)( // Swap bgra - rgba
                            (pixelData[i] & 0x000000ff) << 16 |
                            (pixelData[i] & 0x0000FF00) |
                            (pixelData[i] & 0x00FF0000) >> 16 |
                            (pixelData[i] & 0xFF000000));
#pragma warning disable

                // Convert to bitmap
                Marshal.Copy(pixelData, 0, bmpData.Scan0, pixelData.Length);
                bmp.UnlockBits(bmpData);
                BackBuffer = bmp;

                // Mark as done drawing.
                isDrawing = false;
            }
        }
    }
}

RenderArea.cs

using System;
using Cairo;
using Microsoft.Xna.Framework.Graphics;

namespace Microsoft.XNA.Framework.Gtk2
{
    public class RenderArea : Gtk.DrawingArea
    {
        private Gdk.Color _clearColor;
        private Viewport _view;
        public event EventHandler Render;

        public RenderArea()
        {
        }

        public Gdk.Color BackColor
        {
            get
            {
                return _clearColor;
            }
            set
            {
                _clearColor = new Gdk.Color((byte)value.Red, (byte)value.Green, (byte)value.Blue);
            }
        }

        protected override bool OnConfigureEvent(Gdk.EventConfigure evnt)
        {
            BackColor = BackColor;
            _view = new Viewport(0, 0, Allocation.Width, Allocation.Height);

            Render += OnRender;
            SizeAllocated += sizeAllocatedHandler;

            return base.OnConfigureEvent(evnt);
        }

        private void sizeAllocatedHandler(object o, Gtk.SizeAllocatedArgs args)
        {
            _view = new Viewport(0, 0, args.Allocation.Width, args.Allocation.Height);
        }

        protected override bool OnExposeEvent(Gdk.EventExpose evnt)
        {
            Cairo.Context ctx;
            ctx = Gdk.CairoHelper.Create(GdkWindow);


            PointD p1, p2, p3, p4;
            p1 = new PointD(0, 0);
            p2 = new PointD(Allocation.Width, 0);
            p3 = new PointD(Allocation.Width, Allocation.Height);
            p4 = new PointD(0, Allocation.Height);

            ctx.MoveTo(p1);
            ctx.LineTo(p2);
            ctx.LineTo(p3);
            ctx.LineTo(p4);
            ctx.LineTo(p1);
            ctx.ClosePath();

#pragma warning disable CS0612 // Type or member is obsolete
#pragma warning disable CS0618 // Type or member is obsolete
            ctx.Color = new Cairo.Color(_clearColor.Red, _clearColor.Green, _clearColor.Blue);
            ctx.FillPreserve();
            ctx.Paint();

            Gtk2Backend.BeginDraw((uint)Allocation.Width, (uint)Allocation.Height);
            Gtk2Backend.GraphicsDevice.Clear(new Microsoft.Xna.Framework.Color(_clearColor.Red / 65535f, _clearColor.Green / 65535f, _clearColor.Blue / 65535f, 1f));
            Gtk2Backend.GraphicsDevice.Viewport = _view;

            Render -= OnRender;
            Gtk2Backend.EndDraw();

            return base.OnExposeEvent(evnt);
        }

        protected virtual void OnRender(object sender, EventArgs e)
        {
            
        }
    }
}

Download it and convert to texture

MainWindow.cs

using System;
using Gtk;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.XNA.Framework.Gtk2;

namespace MonoGame_Gtk2.Desktop
{
    public class MainWindowWithMonoGame : Gtk.Window
    {
        // Gtk Sharp 2
        private Gtk.Fixed _fixed;
        private RenderArea _renderArea;
        private RenderArea _renderArea2;

        // MonoGame 
        private GraphicsDeviceManager graphics;
        private SpriteBatch _sb;
        private Texture2D texture;

        public MainWindowWithMonoGame() : base(Gtk.WindowType.Toplevel)
        {
            Title = "MonoGame embeds into Gtk Sharp 2";
            SetDefaultSize(800, 400);
            DeleteEvent += DeleteEventHandler;

            _fixed = new Gtk.Fixed();

            _renderArea = new RenderArea();
            _renderArea.SetSizeRequest(380, 380);
            _renderArea.BackColor = new Gdk.Color(1, 0, 0);
            _renderArea.Render += OnRender;
            _fixed.Put(_renderArea, 10, 10);
            Add(_fixed);

            _renderArea2 = new RenderArea();
            _renderArea2.SetSizeRequest(380, 380);
            _renderArea2.BackColor = new Gdk.Color((byte)0.61, (byte)0.79, (byte)0.66);
            _renderArea2.Render += OnRender2;
            _fixed.Put(_renderArea2, 410, 10);

            ShowAll();

            graphics = Gtk2Backend.GraphicsDeviceManager;
            Gtk2Backend.Content.RootDirectory = "Content";
            _sb = new SpriteBatch(Gtk2Backend.GraphicsDevice);
            texture = Gtk2Backend.Content.Load<Texture2D>("pengiun_happy");
        }

        private void OnRender(object sender, EventArgs e)
        {
            _sb.Begin();
            _sb.Draw(texture, Vector2.Zero, Color.White);
            _sb.End();
        }

        private void OnRender2(object sender, EventArgs e)
        {
            _sb.Begin();
            _sb.Draw(texture, Vector2.Zero, Color.White);
            _sb.End();
        }

        private void DeleteEventHandler(object o, DeleteEventArgs args)
        {
            Environment.Exit(-1);
            Gtk.Application.Quit();
        }
    }
}

That is real from Ubuntu 16.04 ^^

I am too far for showing textures and flat colorable textures… I don’t know I will check vertices :slight_smile:

/// EDIT: I found issue because Bitmap and BitmapData can’t work for Gtk Sharp 2.x Because both classes image and pixbuf for Gtk Sharp are very different to Bitmap and BitmnapData.

Is it correct or wrong? I really don’t know how do I Bitmap and BitmapData like for Gtk Sharp 2?

using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System;
//using System.Drawing;
//using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using Microsoft.Xna.Framework;
using Gdk;
/**
 * 
 *  I try for Gtk Sharp 2 with PixBuf it works only for Gtk Sharp 2 but Bitmap is for WinForms
 *  How do I fix with bixelDates from byte[] because Gdk.Color() has only byte r, byte g and byte b
 *  Who know pixbuf works for Gtk Sharp 2. Thanks
 * 
 */

namespace Microsoft.XNA.Framework.Gtk2
{
    public class Gtk2Backend
    {
        /// <summary>
        /// Gets or Sets the backend ContentManager.
        /// </summary>
        public static ContentManager Content
        {
            get { return MasterWindow.Instance.Content; }
            set { MasterWindow.Instance.Content = value; }
        }

        /// <summary>
        /// Gets the backend GraphicsDevice.
        /// </summary>
        public static GraphicsDevice GraphicsDevice
        {
            get { return MasterWindow.Instance.GraphicsDevice; }
        }

        /// <summary>
        /// Gets the backend GraphicsDeviceManager.
        /// </summary>
        public static GraphicsDeviceManager GraphicsDeviceManager
        {
            get { return MasterWindow.Instance.DeviceManager; }
        }

        /// <summary>
        /// Begins the drawing process making present unusable.
        /// </summary>
        public static bool BeginDraw(uint width, uint height)
        {
            return MasterWindow.Instance.BeginRender(width, height);
        }

        /// <summary>
        /// Finalizes the drawing and makes present usable.
        /// </summary>
        public static void EndDraw()
        {
            MasterWindow.Instance.EndRender();
        }

        /// <summary>
        /// Returns a bitmap of the BackBuffer to be drawn to a control.
        /// </summary>
        /*public static Bitmap Present()
        {
            return MasterWindow.Instance.BackBuffer;
        }*/

        private class MasterWindow : Game
        {
            internal GraphicsDeviceManager DeviceManager;

            // For WinForms
            //internal Bitmap BackBuffer;

            // for Gtk Sharp 2
            internal Pixbuf BackBufferGtk;

            private bool isDrawing;

            #region Singleton
            private static readonly Lazy<MasterWindow> _instance = new Lazy<MasterWindow>
                (() => new MasterWindow(), System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);

            internal static MasterWindow Instance { get { return _instance.Value; } }

            // Constructor
            private MasterWindow() : base()
            {
                // Init Graphics Device
                DeviceManager = new GraphicsDeviceManager(this);

                // Make sure the entire game window is created
                RunOneFrame();
            }

            protected override void Dispose(bool disposing)
            {
            /*    if (BackBuffer != null)
                {
                    BackBuffer.Dispose();
                    BackBuffer = null;
                }*/

                if (BackBufferGtk != null)
                {
                    BackBufferGtk.Dispose();
                    BackBufferGtk = null;
                }

                DeviceManager.Dispose();
                base.Dispose(disposing);
            }
            #endregion

            internal bool BeginRender(uint width, uint height)
            {
                if (isDrawing)
                    throw new Exception("Draw operation already in progress!");

                // Clear BackBuffer if doing new render
          /*      if (BackBuffer != null)
                {
                    BackBuffer.Dispose();
                    BackBuffer = null;
                }*/

                // Gtk
                if(BackBufferGtk != null)
                {
                    BackBufferGtk.Dispose();
                    BackBufferGtk = null;
                }

                // Prepair the screen
                DeviceManager.PreferredBackBufferWidth = (Int32)width;
                DeviceManager.PreferredBackBufferHeight = (Int32)height;

                DeviceManager.ApplyChanges();

                isDrawing = true;
                return true;
            }

            internal void EndRender()
            {
                // Exit if not drawing anything
                if (!isDrawing) return;

                // Create Surface Image
                var width = DeviceManager.PreferredBackBufferWidth;
                var height = DeviceManager.PreferredBackBufferHeight;

            /*    var bmp = new Bitmap(width, height, PixelFormat.Format32bppRgb);
                var bmpData = bmp.LockBits(
                    new System.Drawing.Rectangle(0, 0, width, height),
                    ImageLockMode.WriteOnly,
                    PixelFormat.Format32bppRgb);
                var pixelData = new int[width * height];

                // Get buffer data
                GraphicsDevice.GetBackBufferData(pixelData);
                for (int i = 0; i < pixelData.Length; i++)
#pragma warning disable // Caused by bitwise function requiring uint to int conversion
                    pixelData[i] = (int)( // Swap bgra - rgba
                            (pixelData[i] & 0x000000ff) << 16 |
                            (pixelData[i] & 0x0000FF00) |
                            (pixelData[i] & 0x00FF0000) >> 16 |
                            (pixelData[i] & 0xFF000000));
#pragma warning disable

                // Convert to bitmap
                Marshal.Copy(pixelData, 0, bmpData.Scan0, pixelData.Length);
                bmp.UnlockBits(bmpData);
                BackBuffer = bmp;   */

                /*
                 *  For Gtk Support
                 */
                byte[] pixelDatas = new byte[width * height];
                GraphicsDevice.GetBackBufferData<byte>(pixelDatas);
                Pixbuf pix = new Pixbuf(pixelDatas, width, height);
                for (int i = 0; i < pixelDatas.Length; i++)
                    pixelDatas[i] = (byte)( // Swap bgra - rgba
                            (pixelDatas[i] & 0x000000ff) << 16 |
                            (pixelDatas[i] & 0x0000FF00) |
                            (pixelDatas[i] & 0x00FF0000) >> 16 );

                Marshal.Copy(pixelDatas, 0, IntPtr.Zero, pixelDatas.Length);
                BackBufferGtk = pix;
                // Mark as done drawing.
                isDrawing = false;
            }
        }
    }
}

But I am not sure 100% what is wrong or correct for pixbuf is like BitmapData and image is like Bitmap?

/// EDIT 2:
I found Stockoverflow:

What does it mean? Gdk.Image and Gtk.Image? What is different? Gtk.Image = Bitmap and Gdk.Image means BitmapData?
Thanks!

// Yeah colors of Clear are córrectly. But I tried vertices, textures and models no successfully :confused:

How do I fix?

Because I already updated RenderArea and MainWindow

RenderArea.cs

using System;
using Gtk;

namespace Microsoft.XNA.Framework.Gtk2
{
    public class RenderArea : Gtk.DrawingArea
    {
        private Cairo.Color _clearColor;
        private Xna.Framework.Graphics.Viewport _view;
        public event EventHandler Render;

        public RenderArea()
        {
            BackColor = BackColor;
            _view = new Xna.Framework.Graphics.Viewport(0, 0, Allocation.Width, Allocation.Height);

            Render += OnRender;
            SizeAllocated += sizeAllocatedHandler;
            ExposeEvent += new ExposeEventHandler(OnDrawingAreaExposed);
        }

        public Cairo.Color BackColor
        {
            get
            {
                return _clearColor;
            }
            set
            {
                _clearColor = new Cairo.Color(value.R, value.G, value.B, value.A);
            }
        }

        private void sizeAllocatedHandler(object o, Gtk.SizeAllocatedArgs args)
        {
            _view = new Xna.Framework.Graphics.Viewport(0, 0, args.Allocation.Width, args.Allocation.Height);
        }

        private void OnDrawingAreaExposed(object o, ExposeEventArgs args)
        {
            DrawingArea area = (DrawingArea)o;
            Cairo.Context cr = Gdk.CairoHelper.Create(area.GdkWindow);
            Cairo.PointD p1, p2, p3, p4;
            p1 = new Cairo.PointD(0, 0);
            p2 = new Cairo.PointD(Allocation.Width, 0);
            p3 = new Cairo.PointD(Allocation.Width, Allocation.Height);
            p4 = new Cairo.PointD(0, Allocation.Height);

            cr.MoveTo(p1);
            cr.LineTo(p2);
            cr.LineTo(p3);
            cr.LineTo(p4);
            cr.LineTo(p1);
            cr.ClosePath();
            cr.Restore();
#pragma warning disable CS0618 // Type or member is obsolete
            cr.Color = _clearColor;
#pragma warning restore CS0618 // Type or member is obsolete
            cr.FillPreserve();
            cr.SetSourceColor(_clearColor);
            area.ModifyBg(StateType.Normal, new Gdk.Color((byte)_clearColor.R, (byte)_clearColor.G, (byte)_clearColor.B));

            Gtk2Backend.BeginDraw((uint)Allocation.Width, (uint)Allocation.Height);
            Microsoft.Xna.Framework.Color MgClearColor = new Microsoft.Xna.Framework.Color((float)_clearColor.R, (float)_clearColor.G, (float)_clearColor.B, (float)_clearColor.B);
            Gtk2Backend.GraphicsDevice.Clear(MgClearColor);
            Gtk2Backend.GraphicsDevice.Viewport = _view;

            Render -= OnRender;

            Gtk2Backend.EndDraw();
            cr.GetTarget().Dispose();
        }

        protected virtual void OnRender(object sender, EventArgs e)
        {
            
        }
    }
}

I tried like example of RB

But it doesn’t see MonoGame embedding Gtk Sharp 2.x

I already tried texture and font . No showing. What do I miss? Do you think I need replace Bitmap and BitmapData from GraphicsDevice.GetBackBufferData(pixelData);?

Hello @SpiceyWolf I already tried but nothing vertices and textures in RenderArea :confused:

It seems nothing… I need know for Gtk2Backend.Present(); !!! It need for Gtk Sharp 2

I really miss to Present() from Gtk2Backend / UniversalBackend

because Gtk Sharp 2 doesn’t support for Bitmap / BitmapData that is reason It uses only Image from Gtk or Gdk and PixBuf??

Hi @SpiceyWolf

You’re correct but Gtk Sharp has Dotnet.Graphics for System.Drawing support.

I have tried to resolve. But It crashed since running.

private void OnDrawingAreaExposed(object o, ExposeEventArgs args)
{
    DrawingArea area = (DrawingArea)o;
    area = this;
    Cairo.Context cr = Gdk.CairoHelper.Create(area.GdkWindow);
    Cairo.PointD p1, p2, p3, p4;
    p1 = new Cairo.PointD(0, 0);
    p2 = new Cairo.PointD(Allocation.Width, 0);
    p3 = new Cairo.PointD(Allocation.Width, Allocation.Height);
    p4 = new Cairo.PointD(0, Allocation.Height);

    cr.MoveTo(p1);
    cr.LineTo(p2);
    cr.LineTo(p3);
    cr.LineTo(p4);
    cr.LineTo(p1);
    cr.ClosePath();
    cr.Restore();

#pragma warning disable CS0618 // Type or member is obsolete
cr.Color = _clearColor;
#pragma warning restore CS0618 // Type or member is obsolete
cr.FillPreserve();
cr.SetSourceColor(_clearColor);
area.ModifyBg(StateType.Normal, new Gdk.Color((byte)_clearColor.R, (byte)_clearColor.G, (byte)_clearColor.B));

    Gtk2Backend.BeginDraw((uint)Allocation.Width, (uint)Allocation.Height);
    Xna.Framework.Color MgClearColor = new Xna.Framework.Color((float)_clearColor.R, (float)_clearColor.G, (float)_clearColor.B, (float)_clearColor.B);
    Gtk2Backend.GraphicsDevice.Clear(MgClearColor);
    Gtk2Backend.GraphicsDevice.Viewport = _view;

    Render?.Invoke(o, EventArgs.Empty);
    
    Gtk2Backend.EndDraw();

		using(Graphics g = Gtk.DotNet.Graphics.FromDrawable(area.GdkWindow)){
			g.DrawImage(Gtk2Backend.Present(), Allocation.Width, Allocation.Height);
    }
} 

Not working yet :confused:

Guys,

This “showcase” thread has turned into a stream of issues.

I’m not the maintainer of this project so I could be completely out of line here but it seems to me that it’d be better to be posting issues about the project on github rather than in this thread.

That way, each issue could be discussed individually and closed when it’s no longer an issue.

Just my two cents.

5 Likes

Hello I am here - I already tried to fix for Gtk Sharp 3.x for Windows but it looks very bright - It doesn’t make normal color.

using Cairo;
using Gtk;
using System;

namespace MonoGame.Framework.Gtk3
{
    public class RenderArea : DrawingArea
    {
        private Cairo.Color _clearColor;
        private Microsoft.Xna.Framework.Graphics.Viewport _view;
        public event EventHandler Rendered;

        public RenderArea()
        {
            BackgroundColor = BackgroundColor;
            _view = new Microsoft.Xna.Framework.Graphics.Viewport(0, 0, Allocation.Width, Allocation.Height);

            Rendered += new EventHandler(OnRender);
            Drawn += new DrawnHandler(drawnHandler);
        }

        protected virtual void OnRender(object sender, EventArgs e)
        {
        }

        private void drawnHandler(object o, DrawnArgs args)
        {
            Context cr = args.Cr;
            PointD p1, p2, p3, p4;
            p1 = new PointD(0, 0);
            p2 = new PointD(Allocation.Width, 0);
            p3 = new PointD(Allocation.Width, Allocation.Height);
            p4 = new PointD(0, Allocation.Height);

            cr.MoveTo(p1);
            cr.LineTo(p2);
            cr.LineTo(p3);
            cr.LineTo(p4);
            cr.LineTo(p1);
            cr.ClosePath();

#pragma warning disable CS0612 // Type or member is obsolete
#pragma warning disable CS0618 // Type or member is obsolete
            cr.Color = _clearColor;
            cr.FillPreserve();
            Surface surf = Surface.CreateForImage(Format.Argb32, Allocation.Width, Allocation.Height);
            cr.SetSourceSurface(surf, 0, 0);

            Gtk3Backend.BeginDraw(Allocation.Width, Allocation.Height);

            Gtk3Backend.GraphicsDevice.Clear(new Microsoft.Xna.Framework.Color((byte)_clearColor.R, (byte)_clearColor.G, (byte)_clearColor.B, (byte)_clearColor.A));

            Gtk3Backend.GraphicsDevice.Viewport = _view;

            Rendered?.Invoke(o, EventArgs.Empty);

            Gtk3Backend.EndDraw();
            Gdk.CairoHelper.SetSourceWindow(cr, GdkWindow, 0, 0);
            cr.Paint();
            cr.GetTarget().Dispose();
            cr.GetTarget().Destroy();
#pragma warning restore CS0618 // Type or member is obsolete
#pragma warning restore CS0612 // Type or member is obsolete
        }

        protected override void OnSizeAllocated(Gdk.Rectangle allocation)
        {
            _view = new Microsoft.Xna.Framework.Graphics.Viewport(allocation.X, allocation.Y, allocation.Width, allocation.Height);
            base.OnSizeAllocated(allocation);
        }

        protected override void Dispose(bool disposing)
        {
            Destroy();
            base.Dispose(disposing);
        }

        public Color BackgroundColor
        {
            get
            {
                return _clearColor;
            }

            set
            {
                _clearColor = new Color(value.R, value.G, value.B, value.A);
            }
        }
    }
}

I already tried with Present() But it is really hard to resolve … I have any possiblities and Gtk.Dotnet.Graphics.fromDrawable()

// EDIT:

From RenderArea.cs:

protected override bool OnDrawn(Context cr)
{
    PointD p1, p2, p3, p4;
    p1 = new PointD(0, 0);
    p2 = new PointD(Allocation.Width, 0);
    p3 = new PointD(Allocation.Width, Allocation.Height);
    p4 = new PointD(0, Allocation.Height);

    cr.MoveTo(p1);
    cr.LineTo(p2);
    cr.LineTo(p3);
    cr.LineTo(p4);
    cr.LineTo(p1);
    cr.ClosePath();

#pragma warning disable CS0612 // Type or member is obsolete
#pragma warning disable CS0618 // Type or member is obsolete
cr.Color = _clearColor;
cr.FillPreserve();
Surface surf = Surface.CreateForImage(Format.Argb32, Allocation.Width, Allocation.Height);
cr.SetSourceSurface(surf, 0, 0);

    Gtk3Backend.BeginDraw(Allocation.Width, Allocation.Height);

    Gtk3Backend.GraphicsDevice.Clear(new Microsoft.Xna.Framework.Color((byte)_clearColor.R, (byte)_clearColor.G, (byte)_clearColor.B, (byte)_clearColor.A));

    Gtk3Backend.GraphicsDevice.Viewport = _view;

    Rendered?.Invoke(null, EventArgs.Empty);

    Gtk3Backend.EndDraw();
    Gdk.CairoHelper.SetSourceWindow(cr, GdkWindow, 0, 0);
    cr.Paint();

    System.Drawing.Graphics graphics = Gtk.DotNet.Graphics.FromDrawable(GdkWindow);
    graphics.DrawImage(Gtk3Backend.Present(), 0, 0, Allocation.Width, Allocation.Height);
    cr.GetTarget().Dispose();
    cr.GetTarget().Destroy();

#pragma warning restore CS0618 // Type or member is obsolete
#pragma warning restore CS0612 // Type or member is obsolete
return base.OnDrawn(cr);
}

Gtk3Backend.cs ( in MasterWindow )

I add someting lines for support with Cairo.

    internal void EndRender()
    {
        // Exit if not drawing anything
        if (!isDrawing) return;

        // Create Surface Image
        var width = DeviceManager.PreferredBackBufferWidth;
        var height = DeviceManager.PreferredBackBufferHeight;

        var bmp = new Bitmap(width, height, PixelFormat.Format32bppRgb);
        var bmpData = bmp.LockBits(
            new System.Drawing.Rectangle(0, 0, width, height),
            ImageLockMode.WriteOnly,
            PixelFormat.Format32bppRgb);
        var pixelData = new int[width * height];

        // Get buffer data
        GraphicsDevice.GetBackBufferData(pixelData);
        for (int i = 0; i < pixelData.Length; i++)

#pragma warning disable // Caused by bitwise function requiring uint to int conversion
pixelData[i] = (int)( // Swap bgra - rgba
(pixelData[i] & 0x000000ff) << 16 |
(pixelData[i] & 0x0000FF00) |
(pixelData[i] & 0x00FF0000) >> 16 |
(pixelData[i] & 0xFF000000));
#pragma warning disable

        // Convert to bitmap
        Cairo.Context cr;
        Cairo.ImageSurface imgsrf = new Cairo.ImageSurface(bmpData.Scan0,
        Cairo.Format.Argb32, width, height, width * 4);
        cr = new Cairo.Context(imgsrf);
        Marshal.Copy(pixelData, 0, bmpData.Scan0, pixelData.Length);
        bmp.UnlockBits(bmpData);
        BackBuffer = bmp;

        // Mark as done drawing.
        isDrawing = false;
    } 

Result: NotsupportedException :frowning:

So close my success :confused: I wish that Gtk Sharp 3.x works like Winforms

// EDIT. I tried Gtk.Bin but Gtk.Bin is same like Gtk.DrawingArea
Gtk.Widget or Gtk.Container are quick closing gtk App. :frowning:

Thanks my great witch! Welcome in our community! Please don’t convert us as frogs!

Nice job hehe I will try for Gtk Sharp 3.2 I know far onExposedEvent for Gtk Sharp 2.x and onDrawn for Gtk Sharp 3.x

Nice work! But why do you need WinForms? Timer. Don’t need with WinForms.

Just without Timer - I already tested with Gtk Sharp 3 = It works fine 100 % Wow I have replaced:

onExposedEvent to onDrawn
Dispose to Destory

PS: Why do you not use Cairo.Color or Gdk.RGBA?

It is okay for that. I wish I need extra features

Timer removed I don’t need - It works fine.

Fixing point for Gtk Sharp 3 without Timer - Please use Timeout of Gtk Sharp because it support like Timeout

That is why not using Timer of WinForms.

But for me without.

I will write later. I am still supervising.

Now download you can download this from mega.nz

Please remember your work like me! You should write pure c# not stetic! Because stetic of Gtk Sharp 2 or 3 are not good. That is why you need write pure C#. It is better to understand like my code:

public MyClass()
{
  Title = "My Class Hello Window";
  ...
}

Remember quiting of Gtk Sharp is "DeleteEvent += OnDeleteEventHandler;

than you can write sometimes:

private void onDeleteEventHandler(object o, DeleteEventArgs args)
{
    Application.Quit();
    Environment.Exit(-1);
}

// EDIT Yeaaaah Timer is for WinForms and for Gtk Sharp need custom Timer as GLibTimer.cs I have written…
Updated Zip in same file!

GLibTimer.cs:

using System;

namespace Game1.Source
{
    public delegate void TimerElapsedHandler(object sender, TimerElapsedEventArgs args);

    public class TimerElapsedEventArgs : EventArgs
    {
        DateTime signalTime;

        public TimerElapsedEventArgs()
        {
            signalTime = DateTime.Now;
        }
    }

    public class GLibTimer
    {
        private bool _enabled;
        public bool enabled
        {
            get
            {
                return _enabled;
            }
            set
            {
                _enabled = value;
                if (_enabled)
                    Start();
                else
                    Stop();
            }
        }
        protected uint timerId;

        public event TimerElapsedHandler TimerElapsedEvent;
        public uint TimerInterval;
        public bool autoReset;

        public GLibTimer() : this(0) { }

        public GLibTimer(uint timerInterval)
        {
            _enabled = false;
            TimerInterval = timerInterval;
            autoReset = true;
            timerId = 0;
        }

        public void Start()
        {
            _enabled = true;
            timerId = GLib.Timeout.Add(TimerInterval, OnTimeout);
        }

        public void Stop()
        {
            _enabled = false;
            GLib.Source.Remove(timerId);
        }

        protected bool OnTimeout()
        {
            if (_enabled)
            {
                if (TimerElapsedEvent != null)
                    TimerElapsedEvent(this, new TimerElapsedEventArgs());
            }
            return _enabled & autoReset;
        }
    }
}

Yay I am happy now. I know how does it fix like same hehehe.

// EDIT: Now it replaced Timer for Gtk Sharp like WinForms :smiley: But

Tick = TimerElapsedEvent
Enabled = enabled
inverval = TimerInterval

Now I have added interval into RenderWidget :smiley:

Yay Updated to mega.nz Yay!

God thanks for resolving - Haha @SpiceyWolf can’t magicia that :smiley:

I have hacked to poor magician @SpiceyWolf and have resolved :smiley:

I am happy now. Juhuuu!

// Updated feature with Linux Ubuntu 18.04 appends same Userinterface Yay

1 Like

I used the MonoGame/Xna color since it had to be set manually (No point in adding the extra conversion step for the widget color when you wont ever see the color in a visual designer – its just extra variables) as well I wasnt familiar with GTK timer system it seemed overly complex when I can just import a Winforms Timer (It runs in background anyway). The timer system was needed to control the update intervals so you can have SOME control over the performance as if its updating as often as GTK tries to make it happen it literally Updates constantly without end so for example the animation example i did ended up ALWAYS running at the same speed for all controls and animating extremely quickly. Thats lost performance AND makes more work to correct for without how i did the timer at the same time…

Also that one guy was right we shouldnt be taking over the thread, Ima go through and pull my irrelevant stuff (Only leaving the GTK and Winforms controls here as reference – and sqrMin1 can make do em better if they ever get updates that provide useful info to him) I recommend you pull yours too just to cleanup the mess we made on this thread. (Happy to remove the links if you dont want them referenced here anymore @SandboxBlizz)

Github: https://github.com/SpiceyWolf/MonoGame.Framework.Winforms
Github: https://github.com/SpiceyWolf/MonoGame.Framework.Gtk

2 Likes

Wait you forget to fix Timer under Gtk ( your https://github.com/SpiceyWolf/MonoGame.Framework.Gtk is for Gtk Sharp 2

My new repository is for Gtk Sharp 3.22.x Please remember that! @SandboxBlizz Please add my reference for Gtk Sharp 3.22. to your MonoGame.GtkSharp ( “…Gtk” by @SpiceyWolf and “…Gtk3” by @Jens_Eckervogt ( ME ) and “…Winforms” by @SpiceyWolf to MonoGame.Forms or do you like together?
https://github.com/sourceskyboxer/MonoGame.Framework.Gtk3

Thanks!

If ur on Github you can fork and send a PR to me and ill just take it :open_mouth: -> Throw a credits.txt and put both our names in it tho if u do xD

I forgot I am sorry that I will fix …

UPDATE
https://github.com/sourceskyboxer/MonoGame.Framework.Gtk3/blob/master/Credit.txt

Update now Nuget: https://www.nuget.org/packages/MonoGame.Framework.Gtk3/0.1.0

@SpiceyWolf Can you give me the MonoGame.Framework.Gtk id? Proper Gtk widget support incoming…

1 Like

Basically I need to agree with @craftworkgames that we are about to lose the overview in this thread.

Think of people discovering this topic which contains “MonoGame.Forms” in the headline and experiencing a stream of Gtk issues and they don’t really know what’s happening or why this topic is listed in the “Showcase” category.

So, when having a bigger feature idea and needing to discuss it more deeply (issues etc), then here is a much more elegant solution for the future:

  1. Small discussion about the new feature here in this thread.
  2. Creating a new topic about the new feature in the MonoGame forum (Community Area)
  3. In the first post of the newly created topic place a link to this thread, which connects the two topics internally and makes them visible in each topic (scroll to the top of this thread to see an example of already connected topics [on the right hand side of the first post]).
  4. When you are done with the new feature from the new topic, share the result by creating a reply in this thread with a link to the corresponding post showing the milestone (also GitHub links are very welcome).

This should make everthing clearer for us and new or returning visitors.

Don’t get me wrong: I’m very happy about your effort in making the library better and it makes me proud that we are gathered here to create something awesome!

Further more it’s still allowed to have small discussions or requests here as long as they are have something to do with MonoGame.Forms (respectivly parts of the MonoGame.Framwork itself).

(I wish I could somehow pin this rules here)


I will also take a look at the Gtk implementations but in the moment my time is very limited. So don’t expect it to soon.

Until then: Thank you all for your effort!


Just placing a link to the GitHub repo here for new users to make it easier for them to find the library:

Keep up the good work and have a nice weekend!

1 Like

Also just delete ur past posts relating to the issues -> They are non issues now and irrelevant to the thread :open_mouth: in 12 hours the thread could be cleared up of our mess :smiley: well myne is already gone anyhow >.>

Edit: Oops thought that i hit that reply to Jens – @Jens_Eckervogt do what i said above lol

Edit: Since ur probably seeing this Sqr… I has myself a theory on how to possibly correct the solution with the bitmap to something a little less gross >.> Ill get back with you probably tomorrow on if it works out…

Because you can’t grab nuget ids unless you upload something.

Just FYI, I have Gtk version working locally, don’t think I’ve mentioned it above:

Its directly rendering to Gtk GLArea, plus custom implementations for Input/Window and some other stuff.

3 Likes

PR 2 of 3 is up: https://github.com/MonoGame/MonoGame/pull/6378

Wow your great implementer how did you get successful with GLArea i already tried before but it doesn’t see sprites? How did you implement?

Full source code is available at the link above.