Coherent UI for .NET  2.5.3
A modern user interface library for games
 All Classes Namespaces Functions Variables Enumerations Enumerator Properties Events Pages
XNA/MonoGame Sample

For instructions on deploying the sample, please read .NET Sample guides.

This sample illustrates the usage of Coherent UI in a XNA/MonoGame application. The application code is largely the same for both platforms, with exceptions for content loading and input handling, which will be discussed shortly.

The sample is composed of the following files:

Game1.cs - contains the game logic.
InputHandling.cs (used with either Input_Windows.cs or Input_Linux.cs for XNA/MonoGame respectively) - utilities for converting SlimDX supplied input events to Coherent events.
Listeners.cs - classes providing handlers for Coherent UI callbacks

A detailed description of each file follows.

Game1.cs

The Game1 class contains the game logic - initialization, content loading, updating and drawing.

In the initialization step the view context and the Input system are initialized normally.

Warning
Note again that the ContextListener class passed as parameter to the view context is saved to a member variable, because the if it wasn't it would be garbage collected and the system would throw an exception. This is valid for the ViewListener as well.
Note
XNA(Windows) only

The content to be loaded is a cursor texture, since XNA hides the mouse pointer. We keep a mouse position that is updated in the input handler and draw a sprite in that position to emulate a cursor.
Mono(Linux) only

No content is loaded in the MonoGame sample. If you want to change the cursor in MonoGame, you'd have to build the content under Windows and then use it on other platforms. Check the MonoGame documentation for details.

In the Update method we update the view context and the Input system. This is where we poll the UI context listener for readiness so we know we can create a View.The view can only be created using shared memory (UsesSharedMemory = true;) because XNA doesn't support shared textures.

The Draw method fetches the composited surfaces from Coherent UI and stretches the texture on the whole window.

InputHandling.cs

This file contains methods for converting KeyEventArgs / MouseEventArgs to Coherent UI events. Some non-essential fields for key/mouse states have been left out (such as IsCapsOn, IsNumLockOn, IsNumPad, IsAutoRepeat) because of platform differences.

The code that actually converts platform specific events to KeyEventArgs / MouseEventArgs is in the Input_Linux.cs and Input_Windows.cs files.

Note
Windows only

Since XNA's input state is obtained via polling and Coherent UI expects input events, we'd like to have event-driven input in XNA instead. The easiest way to achieve that is by using windows hooks so we get to execute some code when receiving windows messages. You can examine the code for doing that in Input_Windows.cs.
Linux only

MonoGame's input state is obtained via polling and Coherent UI expects input events so we have to make an event-driven input system. Since the closest equivalent of Windows hooks for Linux are some signal acrobatics (as suggested by the Qt Documentation) and that's too much trouble to be worth it, we'll just create two snapshots of the key state (and two more for the mouse state) for the current and previous frames and generate events based on the difference. This presents some limitations and difficulties, such as converting an input key value to a printable character if possible. To keep things simple the sample convertor supports only standard US keyboards (i.e. latin letters, digits and common symbols).
The code for this event-driven system based on state difference can be found in the Input_Linux.cs file.

Listeners.cs

You'll find the ContextListener and MyViewListener classes here.

The ContextListener class is the view context listener, which serves the purpose to notify the user when the view context is ready to operate.

The MyViewListener class is what handles the important events for drawing. Since XNA does not shared textures, we can only use the shared memory transport mechanism.

The ViewListener subscribes for the DrawMemory event and the event handler sets the texture data to the received pixels array. To do that we use the SetData method (and unbind the texture from the graphics device beforehand, because SetData requires it).
There is one other manipulation that we must do before setting the data - swap the red and blue channels of the pixels, because the SurfaceFormat.Color format doesn't match with the one of the array (and there are no other RGBA formats supported by XNA). This is done in an unsafe code block to speed up the operation, since otherwise the runtime does a bounds check which slows down execution.