MonoGame.Forms - Create your Editor Environment!

Hi, I’m very interested in this, as I’m making a GameBoy emulator and I’m going to use MonoGame for the rendering and sound, and WinForms for the UI controls and GameBoy debugger.

Someone said WinForms uses GDI+ and therefore MonoGame will be slow. Is this true? I really have no idea about MonoGame nor WinForms so I can’t answer this question myself.

Thanks.

Even when embedded in WinForms, MonoGame will use DirectX or OpenGL for rendering, so MG will not run slower than usual.

This may sound like a “dumb” question but could someone explain exactly what MonoGame-Forms is.

Is this a way to add a complete GUI to your MonoGame Project?

Thank you…

@SNaidamast

No, this is exactly not the purpose of MonoGame.Forms.

To quote the headline of the readme file:

MonoGame.Forms is the easiest way of integrating a MonoGame render window into your
Windows Forms project. It should make your life much easier, when you
want to create your own editor environment.

So the purpose of MonoGame.Forms is - for example - creating your own editor tool, which needs a rendering window, for your own game.
This could be a level editor or a particle effect editor for example.

You basically create a new WindowsForms project and then add the MonoGame.Forms library to this project, to make the rendering capabillities of the MonoGame.Framework available in your editor project in a very easy way.

Also what @KiloMikeCodesStuff said should be possible. Creating your GameBoy emulator with MonoGame.Forms should be very doable, when you know how to render your contents using the MonoGame.Framework. Everything else is just the usual business of WindowsForms (working with a complete GUI solution for projects like that).

I also reccommend reading the README file and the Wiki (which describes the class library) to get a better overview.

Regarding developing games inside MonoGame.Forms: Yes, it’s kinda possible. The library has native Keyboard and GamePad support of the MonoGame.Framework as well as RenderTarget support. However it only supports the Windows platform and I have never tested things like fullscreen support and different resolutions (but it’s possible to resize the render controls), because - as I said - this is not the purpose of the MonoGame.Forms library.

I recommend using the MonoGame.Forms library for tools and editors only. Not for whole games on a bigger scope.

1 Like

Thank you for your informative reply, sqrMin1… :slight_smile:

So then, if I am ever able to complete my military simulation, I could then use this library to create, for example, a scenario editor. Is this a better understanding of your software?

Yes, you could do that, but it realy depends on your needs.

For example: it’s also possible to create a scenario editor without the need of a rendering window, as long as such an editor only needs to process and handle plain data.

But if you need a graphical / rendered representation of such data (which includes realtime updates), then MonoGame.Forms is there to help you with that.

MonoGame.Forms 1.6.5.3 - MSAA Accessibility

  • The maximum MultiSampleCount (MSAA Antialising) of the users GraphicsDevice is now cached in PresentationParameters.MultiSampleCount, so this information becomes easy to access in custom controls, which is useful when working with custom RenderTargets.
  • It’s now possible to get the clamped MultiSampleCount in custom controls by calling GetClampedMultisampleCount(int).
  • This function always returns the desired MultiSampleCount clamped to the nearest power of two in a descending order (e.g.: input = 7; output = 4).

NuGet: NuGet Gallery | MonoGame.Forms 1.6.7.1


Easy to work with MultiSampling in MonoGame.Forms:

MonoGame.Forms 1.6.6.0 - MSAA Accessibility (Refreshed)

  • GetClampedMultisampleCount is now internal.
  • Added public void SetMultiSampleCount(int) which calls the new internal event Action<int> UpdateMultiSampleCount, so the wanted MultiSampleCount will be available in all editor service classes.
  • Added internal AntialisingRenderTarget and internal void RefreshAntiAlisingRenderTarget, which automatically updates itself based on ClientSize and WantedMultiSampleCount.
  • GraphicsDeviceService is now internal.
  • as well as the corresponding field in GraphicsDeviceControl.
  • Added the internal int MaxMultiSampleCount and cache the value there instead of in the presentation parameters, to make this value save from manipulation, because it is used by the GetClampedMultisampleCount in GraphicsDeviceControl as a fallback.

Use Antialising (MSAA) in your custom controls like this:

protected override void Initialize()
{
   base.Initialize();

   SetMultiSampleCount(8); //Usual numbers are 0, 2, 4, 8
}

protected override void Draw()
{
   base.Draw();

   Editor.BeginAntialising();

   Editor.spriteBatch.Begin();

   //Your drawings

   Editor.spriteBatch.End();

   Editor.EndAntialising();
}

As you can see, everything between BeginAntialising() and EndAntialising() will be affected by MSAA.

NuGet: NuGet Gallery | MonoGame.Forms 1.6.7.1

MonoGame.Forms 1.6.6.2 - Antialising Fixes

  • Added missing nuget references to SharpDX.dll, SharpDX.DXGI.dll and SharpDX.Direct3D11.dll.
  • Added public int GetFrameRate to get the current frame rate of a custom control.
  • Changed internal event Action UpdateMultiSampleCount to public so the user can react to multi sample changes in custom controls.
  • The AntialisingRenderTarget now correctly gets disposed on refreshing.
  • Fixed a NullReferenceException when the SwapChainRenderTarget is null.
  • Rethought the disabling of the AntialisingRenderTarget after a ControlResize event. It automatically reactivates itself after 500 milliseconds after a ControlResize event occours.
  • This prevents OutOfMemoryExceptions on recreating the AntialisingRenderTarget as well as NullReferenceExceptions if the current internal Rendertarget is lost, when switching from the AntialisingRenderTarget to the SwapChainRenderTarget.

Dev Note for the next Build (1.6.7.0):
Planning to implement a RenderTarget Manager where users can add their custom RenderTargets to, so they becoming automatically updated internally (based on the ClientSize for example).

NuGet: NuGet Gallery | MonoGame.Forms 1.6.7.1

2 Likes

MonoGame.Forms 1.6.7.1 - Render Target Manager

  • Added a RenderTargetManager to fully manage custom RenderTarget2D’s internally - based on ClientSize and MultiSampleCount.
  • Fixed memory leaks on reinitialization of custom controls.
  • Added public event Action RenderTargetsRefreshed so the user can get notified when the RenderTarget2D’s, hold by the RenderTargetManager, got refreshed.
  • Renamed events to make it more clear what they are meaning:
  • UpdateSwapChainRenderTarget -> SwapChainRenderTargetRefreshed
  • UpdateMultiSampleCount -> MultiSampleCountRefreshed
  • Made SwapChainRenderTargetRefreshed internal.
  • Changed some XML comments so they are better understandable.

Using the RenderTargetManager

protected override void Initialize()
{
    base.Initialize();

    // Adding a new Rendertarget2D with the keyname "MyTarget" to the Manager
        Editor.GetRenderTargetManager.CreateNewRenderTarget2D("MyTarget", false);
}

public override void Draw()
{    
    // Set the new RenderTarget
    Editor.BeginRenderTarget("MyTarget", clearColor: Color.Transparent);

    // Your Drawings ...

        // Automatically revert to the SwapChainRenderTarget
        Editor.EndRenderTarget("MyTarget", drawToSpriteBatch: false, clearGraphics: false); 
}

NuGet: https://www.nuget.org/packages/MonoGame.Forms/

I’ve been working with forms for a bit, and I’ve run into a small snag. I think I know the issue, but I’m not sure how to get around it.

I have my main window, which has the map editor portion of it(using UpdateWindow). I use OnMouseMove to drag objects around and it works fine.

I have a second form I open sometimes using ShowDialog() which has a different UpdateWindow. When I use OnMouseMove and other mouse events on here, it sometimes will work, sometimes won’t, and other times I’ll drag things around and then it will stop working.

I’m assuming the mouse events are conflicting between the two UpdateWindow’s since the first one is still open in the background. Any good way around this?

Hey @thera and thanks for your message.

You could do the following to get around this:

  • If you just want to move entities inside your editor you could replace all Windows Forms events with native events from the MonoGame.Framework (e.g. Mouse.GetState(), Keyboard.GetState()).

  • If you don’t want to replace all Windows Forms events you currently have, you could try to disable your main window control right before you open your second form.

Did you take a look at the MapHost sample from the MonoGame.Forms repo? It will show you how to handle multiple render windows visible at the same time.

If you prefer to work with multiple float style render windows like in your example, then I recommend using the DockPanelSuit together with MonoGame.Forms.

Thanks for the suggestions. Worse case scenario, I can definitely, go the route of using Mouse.GetState().

In regards to your second suggestion, I’m assuming you’re referring to the Enabled property for the control? I’ve tried that to no success. I’ll study the maphost sample a bit further though, thank you!

Edit: I think I figured out what it is, although I’ll have to think a bit on how to fix it. Both of the UpdateWindow controls utilize zooming in and out, so I need transform the mouse coordinates. Whenever it doesn’t work, its returning a different Matrix, which is probably the control from the base form.

 Matrix viewMatrix = Editor.Cam.get_transformation(Editor.graphics);

            return viewMatrix * Matrix.Identity;

I’ll have to mull this over for a bit haha.

Yes, but I saw why it can’t work after your message. Somehow I forgot to implement this. In the moment the custom controls just checking for Visibility and for AutomaticInvalidation. I will write a patch to make It work in the next iteration of MonoGame.Forms.

You could try to turn off the AutomaticInvalidation on your main window. Then no control events are getting raised and also the Update and Draw methods won’t get updated anymore.

This could also resolve the issue with different matrices.

Normally you wouldn’t have such problems, when using multiple controls on one Form. I have not tested the use case of having multiple Forms together with custom render controls. MonoGame.Forms works best when hosting multiple custom render controls on Panels for example.

When working with several custom controls in different windows (e.g. floating windows), then the DockPanelSuit will be a great help. I use it myself for this purpose and during the development of MonoGame.Forms I always made sure that it works flawlessly with this library. So I can really recommend it in this case.

But if you want to create a simpler editor environment I recommend having multiple custom render controls in Panels and Tabs on one Form only.

I tried setting the following:

this.AutoValidate = AutoValidate.Disable;

This didn’t seem to help. So I tried setting the controls CauseValidation = false and I think it has helped. Unfortuantly it’s a bit ‘random’ when it doesn’t work, so I’ll have to play around with it and see if it acts up, but so far its promising

DockPanelSuit looks very cool, and I’ll definately check it out in more detail. Thanks for your help! :slight_smile:

Sorry, it wasn’t clear enough from my side. I meant this. (Wiki)

It’s a part of the library and you can set this property directly from a custom render control.

Oh, I was getting a bit confused since I couldn’t find it! I’ll test with that, thanks for letting me know.

Nothing support with OpenGL DesktopGL :frowning:

I played around with DesktopGL support in the past and I successfully managed to get a SDL GameWindow embed in a Form, which makes it possible to use / create a MonoGame DesktopGL project in WindowsForms.

But the problem is that it only worked using P/Invoke, which destroys the cross platform compatibility. So I decided to not support DesktopGL for now.

A way better solution would be to have a seperate SwapChainRenderTarget for OpenGL. This would be also the easiest and most obvious way to implement this feature in MonoGame.Forms, because the library uses the exact same technique for WindowsDX (SwapChainRenderTarget in MonoGame).

A SwapChainRenderTarget for OpenGL is btw also suggested on the MonoGame repo:

I really don’t understand because OpenTK can’t but I feel issue looks like it works only OpenGL.net right?

You mean SwapChainRenderTarget works with OpenGL.net?

Thanks for understanding. so sad how do Mac and Linux users wait longer until we have gray hairs?