All Projects → MarcStan → monogame-framework-wpfinterop

MarcStan / monogame-framework-wpfinterop

Licence: MIT license
Wpf interop code to host MonoGame controls inside WPF windows

Programming Languages

C#
18002 projects

Projects that are alternatives of or similar to monogame-framework-wpfinterop

LDtkMonogame
Monogame renderer and importer for LDtk Level editor
Stars: ✭ 43 (-35.82%)
Mutual labels:  monogame
OpenNFS1
Remake of the original EA Need for Speed 1 using c# and Monogame
Stars: ✭ 157 (+134.33%)
Mutual labels:  monogame
Apos.Content
Content builder library for MonoGame.
Stars: ✭ 14 (-79.1%)
Mutual labels:  monogame
Landlord
Landlord was a planned roguelike game, which may yet be completed one day if I decide I am willing to re-approach it.
Stars: ✭ 40 (-40.3%)
Mutual labels:  monogame
ACViewer
Viewer / Utility for DAT files for the game Asheron's Call
Stars: ✭ 19 (-71.64%)
Mutual labels:  monogame
Apos.Shapes
Shape rendering in MonoGame.
Stars: ✭ 21 (-68.66%)
Mutual labels:  monogame
ArcaneManagedFbx
C# and .NET Framework wrapper for the Autodesk FBX SDK written in C++/CLI (managed C++).
Stars: ✭ 36 (-46.27%)
Mutual labels:  monogame
DungeonMaster.NET
Reimplementation of famous old Dungeon Master game.
Stars: ✭ 23 (-65.67%)
Mutual labels:  monogame
cocos2d-mono
Continuation of Cocos2D-XNA project, with focus on MonoGame
Stars: ✭ 18 (-73.13%)
Mutual labels:  monogame
Wallop
Extensible, living/animated wallpaper engine built in C# using Silk.NET's OpenGL wrapper at its core.
Stars: ✭ 27 (-59.7%)
Mutual labels:  monogame
easy-extends
一个简单快速安装PHP扩展的程序--最简单的方法就是使用Linux
Stars: ✭ 78 (+16.42%)
Mutual labels:  monogame
hevadea
🗺 A game about exploring a randomly generated world.
Stars: ✭ 29 (-56.72%)
Mutual labels:  monogame
Comora
A simple 2D camera for Monogame.
Stars: ✭ 71 (+5.97%)
Mutual labels:  monogame
MonoGame.Primitives2D
Easy-to-use 2D primitives
Stars: ✭ 44 (-34.33%)
Mutual labels:  monogame
AnodyneSharp
A rewrite of the game Anodyne in Monogame
Stars: ✭ 14 (-79.1%)
Mutual labels:  monogame
Transform
Base Monogame objects for managing relative transforms.
Stars: ✭ 19 (-71.64%)
Mutual labels:  monogame
FiniteStateMachine
This project is a finite state machine designed to be used in games.
Stars: ✭ 45 (-32.84%)
Mutual labels:  monogame
Facepunch.Steamworks-MonoGame-Integration
Facepunch.Steamworks + MonoGame.Framework = the easiest SteamAPI Integration for your app!
Stars: ✭ 18 (-73.13%)
Mutual labels:  monogame
monogame-aseprite
MonoGame framework extension to import animations from Aseprite
Stars: ✭ 53 (-20.9%)
Mutual labels:  monogame
CTR-tools
Crash Team Racing (PS1) tools - a C# framework by DCxDemo and a set of tools to parse files found in the original kart racing game by Naughty Dog.
Stars: ✭ 93 (+38.81%)
Mutual labels:  monogame

MonoGame WPF Interop

This (unoffical) package adds WPF support to MonoGame (MonoGame 3.8, requires MonoGame.Framework.WindowsDX).

You can host as many MonoGame controls in Wpf as you want by using the WpfGame control. Note that they are however limited to 60 FPS (this is a WPF limit).

MonoGame.Framework.WpfInterop on NuGet Status

Example usage

public class MyGame : WpfGame
{
    private IGraphicsDeviceService _graphicsDeviceManager;
    private WpfKeyboard _keyboard;
    private WpfMouse _mouse;

    protected override void Initialize()
    {
        // must be initialized. required by Content loading and rendering (will add itself to the Services)
        // note that MonoGame requires this to be initialized in the constructor, while WpfInterop requires it to
        // be called inside Initialize (before base.Initialize())
        _graphicsDeviceManager = new WpfGraphicsDeviceService(this);

        // wpf and keyboard need reference to the host control in order to receive input
        // this means every WpfGame control will have it's own keyboard & mouse manager which will only react if the mouse is in the control
        _keyboard = new WpfKeyboard(this);
        _mouse = new WpfMouse(this);
        
        // must be called after the WpfGraphicsDeviceService instance was created
        base.Initialize();

        // content loading now possible
    }

    protected override void Update(GameTime time)
    {
        // every update we can now query the keyboard & mouse for our WpfGame
        var mouseState = _mouse.GetState();
        var keyboardState = _keyboard.GetState();
    }

    protected override void Draw(GameTime time)
    {
    }
}

Now you can use it in any of your WPF forms:

<MyGame Width="800" Height="480" />

Breaking changes (compared to monogame)

Some of the Monogame classes are incompatible with WPF (Game always spawns its own window, Mouse doesn't care which control has focus, ..) so they had to be reimplemented.

As a convention, all reimplemented classes will have the prefix Wpf:

  • WpfGame as a replacement for Game class. Note that due to WPF limitations the WpfGame will always run at a maximum 60 FPS in fixed step (Update and Draw are always called, no Updates are skipped). It is possible to lower the framerate via TargetElapsedTime)
  • WpfMouse and WpfKeyboard provide input per host instance. When multiple WpfGame instances are spawned, only one will receive input at any time
  • WpfGraphicsDeviceService as an implementation of IGraphicsDeviceService and IGraphicsDeviceManager (required by the content manager)
  • WpfGameComponent and WpfDrawableGameComponent as a replacement for the original ones which required a reference to a Game instance

Mouse behaviour

Focus

By default the game takes focus on mouse (h)over. This can be disabled via the FocusOnMouseOver property of WpfGame

Mouse capture

By default the game captures the mouse. This allows capture of mouse events outside the game (e.g. user holds and drags the mouse outside the window, then releases it -> game will still receive mouse up event). The downside is that no overlayed controls (e.g. textboxes on top of the game) will ever receive focus.

Alternatively this can be toggled off via CaptureMouseWithin property of WpfMouse and then allows focus on overlayed controls. The downside is that mouse events outside the game window are no longer registered (e.g. user holds and drags the mouse outside the window, then releases it -> game will still think the mouse is down until the window receives focus again)

Change in behaviour (compared to monogame)

RenderTargets

Rendertargets work slightly different in this WPF interop.

In a normal monogame the rendertarget would be used like this:


    // Draw into rendertarget
    GraphicsDevice.SetRenderTarget(_rendertarget);
    GraphicsDevice.Clear(Color.Transparent);
    _spriteBatch.Begin();
    _spriteBatch.Draw(_texture, Vector2.Zero, Color.White);
    _spriteBatch.End();

    // setting null means we want to draw to the backbuffer again
    GraphicsDevice.SetRenderTarget(null);


    // these draw calls will now render onto backbuffer
    GraphicsDevice.Clear(Color.CornflowerBlue);
    _spriteBatch.Begin();
    _spriteBatch.Draw(this.rendertarget, Vector2.Zero, Color.White);
    _spriteBatch.End();

Instead the WPF interop always uses a rendertarget (internally used to display the renderoutput in WPF), thus in a WPF control the code needs to look like this instead:


    // get and cache the wpf rendertarget (there is always a default rendertarget)
    var wpfRenderTarget = (RenderTarget2D)GraphicsDevice.GetRenderTargets()[0].RenderTarget;

    // Draw into custom rendertarget
    GraphicsDevice.SetRenderTarget(_rendertarget);
    GraphicsDevice.Clear(Color.Transparent);
    _spriteBatch.Begin();
    _spriteBatch.Draw(_texture, Vector2.Zero, Color.White);
    _spriteBatch.End();

    // instead of setting null, set it back to the wpf rendertarget
    // this will ensure that the output will end up visible to the user
    GraphicsDevice.SetRenderTarget(wpfRenderTarget);


    // these draw calls will now render onto backbuffer
    GraphicsDevice.Clear(Color.CornflowerBlue);
    _spriteBatch.Begin();
    _spriteBatch.Draw(this.rendertarget, Vector2.Zero, Color.White);
    _spriteBatch.End();

The reason for this behaviour that the interop sample cannot use the backbuffer (null) and instead needs to use its own rendertarget to interop with WPF.

TabControls

It is perfectly possible to use the WpfGame controls inside TabControls.

By default, WPF fully unloads any tab that is deactivated (e.g. when switching to another tab) and fully reloads the tab when switching back.

The WpfGame does not unload in these cases. See the next few events for details.

WpfGame.Activated/Deactivated

When a WpfGame is hosted inside a tab and the tab is changed, the WpfGame instance is not unloaded. Instead, Deactivated is fired. Likewise when the tab is activated again, Activated is fired.

If the parent window loses focus, Deactivated is fired (but only for the active tab) and when the window receives focus, Activated is called again (only for the active tab).

Initialize/Dispose

Initialize is only called once (per instance, when the window is created) and Dispose is called for every game instance once the window closes.

This means, that initialize is called even for those instances that are in "disabled" tabs. However IsActive can be used to determine whether the current game is inside the active tab (see below).

WpfGame.IsActive

Update/Draw are still called for all inactive tabs and any inactive tab has the IsActive property on WpfGame set to false. Only the active tab has IsActive set to true (and only when the window is the currently active window).

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].