Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Gum projects can be loaded in a game project. Gum projects are made up of multiple filesincluding:
.gumx - the main Gum project
.gusx - Gum screen files
.gucx - Gum component files
.gutx - Gum standard element files
.png - image files
.fnt - font files
You are not required to use the Gum tool or .gumx projects - you are free to do everything in code if you prefer. Of course using the Gum tool can make it much easier to iterate quickly and experiment so its use is recommended.
Before creating a Gum project, it is recommended that you already have a functional MonoGame project with a Content folder.
If you haven't already downloaded it, you should down the Gum tool. See the Introduction page for information on downloading Gum.
To create a Gum project:
Open the gum tool
Select File->Save Project
Navigate to the Content folder of your game. If desired, create a sub-folder under the Content folder
Save the project - this will save multiple files under the Content folder
To add the files to your .csproj:
Open your .csproj file in a text editor
Add a line to copy all files in the Gum project folder including the .gumx file itself. For an example, see the .csproj file for the MonoGameGumFromFile project: https://github.com/vchelaru/Gum/blob/0e266942560e585359f019ac090a6c1010621c0b/Samples/MonoGameGumFromFile/MonoGameGumFromFile/MonoGameGumFromFile.csproj#L37 Your .csproj may look like this:
Verify that all gum files (see the extension list above) are marked as Copy if newer in Visual Studio
The example above copies the entirety of the content folder to the output folder by using wildcards. If you do not want every file copied over, you can be more selective in what you copy by including only certain file types. For more information about wildcard support in .csproj files, see this page on how to include wildcards in your .csproj:
To load a Gum Project:
Open Game1.cs
Modify the Initialize method so that it has the following lines after initializing SystemManagers:
Note that the ToGraphicalUiElement method has an addToManage
parameter which determines whether the GraphicalUiElement is added to managers. If a GraphicalUiElement is not added to managers, it will not appear on screen.
Alternatively, the AddToManagers method can be explicitly called as shown in the following code:
For an example of a Game1.cs file which loads a project file, see the MonoGameGumFromFile: https://github.com/vchelaru/Gum/blob/0e266942560e585359f019ac090a6c1010621c0b/Samples/MonoGameGumFromFile/MonoGameGumFromFile/Game1.cs#L76-L82
Note that calling ToGraphicalUiElement creates a GraphicalUiElement (Gum object) from the first screen. You can inspect the gumProject.Screens file and select which screen you would like to create if your project has mutliple Screens.
You can access elements within the screen by accessing the GraphicalUiElement that is created, as shown in the following code:
A full Game1 class which loads a project might look like this:
The code above and most samples in the Gum repository assume a Gum project located in the Content folder. If you are placing your Gum project in a subfolder, you need to set the FileManager.RelativeDirectory
to the sbufolder prior to calling ToGraphicalUiElement
. For example:
For a more detailed discussion on file loading and file locations, see the File Loading page.
If your Gum project load results in an exception, you can inspect the exception message for information about the failure. The most common type of failure is a missing file reference.
If you are missing files, you may have not set up the file to copy to the output folder. The following screenshot shows an incorrect setup - the CardInstance.gucx file is not copied, but it probably should be:
This can be changed to copy in Visual Studio, or the .csproj can be modified to include wildcards for copying files over, which can make maintenance easier as the project grows. See the section above for information and examples on setting up your project loading.
Custom runtimes allow the creation of custom classes which are created when loading your Gum project. The use of custom runtimes is especially important if you are developing UI which should respond to user interactions such as clicks or if you are using Gum Forms.
In the context of Gum, a runtime is a class which handles interaction with a Gum component or screen while your game is running. The term runtime is used to distinguish between an object used at runtime (such as a ), or the Gum element (such as ).
Custom runtimes can encapsulate functionality and can be used to build any time of UI including simple UI such as Buttons and Checkboxes, or more complex UI such as ListBoxes or ComboBoxes.
Custom runtimes are classes which you define which inherit from GraphicalUiElement or InteractiveGue. If your runtime needs custom logic but does not respond to user actions then you should use GraphicalUiElement as your base. If your runtime responds to user actions such as clicks, then you should use InteractiveGue as your base. If you are defining a custom runtime to be used as the Visual for Gum Forms, you should also inherit from InteractiveGue.
This tutorial uses InteractiveGue as a base since responding to clicks is the most common reason for creating a custom runtime, and such an object would be suitable for Gum Forms.
The InteractiveGue class inherits from GraphicalUiElement, but adds additional logic for raising events on common mouse actions. These actions are exposed as public events which can be subscribed internally in your InteractiveGue-inheriting class or externally per-instance. This tutorial shows how to handle events both internally and externally.
Custom runtimes fall into one of two categories:
Runtimes defined fully in-code
Runtimes defined in a Gum project
If a custom runtime is defined fully in code, then it must instantiate its own children. Typically these instances are added in a constructor.
Alternatively if a custom runtime is loaded from a Gum project, then it should not define its children since those will come from the loaded Gum project. However, it may need to access those children. It can do so in the AfterFullCreation
method.
The following code shows how to create a custom runtime from Gum. Often times custom runtimes are used for Gum object, so using the standard 2-argument constructor and creating Gum objects is recommended as shown in the following code:
Note that this type of control is assumed to be used as a Forms Button, so it includes the instantiation of a Forms button.
Custom runtime classes can be created for screens using the same approach as components. Typically custom runtimes for screens inherit from GraphicalUiElement rather than InteractiveGue since the screen itself does not need click events.
The following code is an example of a custom runtime for a screen which contains a text instance named TextInstance
:
This type is registered using ElementSaveExtensions:
Calling ToGraphicalUiElement
on the StartScreen results in an instance of the StartScreenRuntime being created.
Once a custom runtime is defined, it needs to be associated with a Gum component. For example, consider a component named StandardButton inside a Buttons folder.
Notice that the name StandardButton does not match the name ClickableButton, and this is often not desirable.
To associate StandardButton with ClickableButton, add the following code before calling ToGraphicalUiElement
:
Now whenever ToGraphicalUiElement is called, all instances of StandardButton will be instantiated as a ClickableButton rather than the default GraphicalUiElement.
If using InteractiveGue, the built-in events are only called if DoUiActivityRecursively is called either directly on the component, or on a parent of the component. Usually DoUiActivityRecursively is called in the context of using Forms, so it is recommended to do so using the FormsUtilities object. By using FormsUtilities you can reduce the amount of code needed for interactivity.
We can add FormsUtilities to our code as shown in the following snippet:
After adding the FormsUtilities calls, all events on any InteractiveGue will automatically be raised so long as the InteractiveGue is part of the hierarchy owned by the CurrentScreen.
Events often need to be customized per instance. For example, a game's MainMenu screen may have buttons for starting the game, going to the options screen, or exiting the game.
The following code shows how to add events to runtime instances. This code assumes that each runtime instance is using a Runtime that inherits from InteractiveGue.
This page assumes you have an existing MonoGame project. This can be an empty project or an existing game.
At the time of this writing Gum + MonoGame has been tested on a variety of platforms including DesktopGL, DirectX, and mobile. It has also been used with Nez and Kni. If your particular platform is not supported please contact us on Discord and we will do our best to add support.
Open your MonoGame project in your preferred IDE.
Add the Gum.MonoGame
NuGet package
Open your Game class (usually Game1.cs)
Add the following code to your Initialize method:
SystemManagers.Default = new SystemManagers(); SystemManagers.Default.Initialize(_graphics.GraphicsDevice, fullInstantiation: true);
Add the following to your Update method:
SystemManagers.Default.Activity(gameTime.TotalGameTime.TotalSeconds);
Add the following to your Draw method after you clear the graphics device:
SystemManagers.Default.Draw();
To test that you have successfully added Gum to the project, add the following code to your Initialize method after SystemManagers.Default.Initialize:
If everything is initialized correctly, you should see a white rectangle at the top-left of the screen.
Gum provides a GumBatch object which works similar to SpriteBatch. It can be used for immediate mode rendering, which allows for calling Begin
, Draw
, and End
just like SpriteBatch. This is useful if your project requires mixing Gum and MonoGame rendering, or if you are more comfortable using a SpriteBatch-like interface.
This page assumes you have an existing MonoGame project. This can be an empty project or an existing game.
Usage of GumBatch is completely optional, and it is only needed if you want to draw Gum objects at a partciular point in your drawing code. If you are using Gum to load .gumx projects, or if you would like Gum to handle all UI or HUD rendering, then you do not need to use GumBatch.
Open your MonoGame project in your preferred IDE.
Add the Gum.MonoGame
NuGet package
To initialize a GumBatch, you must:
Declare a GumBatch at class scope
Initialize the Gum SystemManagers - this is needed whether you use GumBatch or the full Gum retained mode rendering system
Initialize the GumBatch
(optional) load a .fnt file
Draw with gumBatch in your Draw
The following shows a simple Game1.cs file which renders Gum Text:
This code produces the following image:
Note that this code assumes a font .fnt file (and matching .png) are in the Content/Fonts/ folder. All content is loaded relative to the Content folder, just like normal content in MonoGame. Also note that this content does not use the content pipeline, but must be set to Copy to Output.
GumBatch is an object which supports immediate mode rendering, similar to MonoGame's SpriteBatch. GumBatch can support rendering text with DrawString as well as any IRenderableIpso.
For information on getting your project set up to use GumBatch, see the page.
GumBatch can be used to render strings directly. This requires a BitmapFont.
The following code renders a string at X = 100, Y=200:
Multiple strings can be rendered between Begin
and End
calls:
DrawString can accept newlines and color the text:
If your text rendering requires more advanced positioning, wrapping, rotation, sizing, and so on, you can use TextRuntime instances.
TextRuntimes can be used in both GumBatch as well as they can be added to the SystemManagers if you use SystemManagers.Draw (retained mode).
The following code shows how to create a TextRuntime instance and render it using GumBatch:
GumBatch.Draw renders any argument renderable object. If the object has children, then the Draw call performs a hierarchical draw, respecting the parent/child relationship to control draw order.
For example, the following code creates a parent ColoredRectangleRuntime and a child TextRuntime:
Since the Draw call is only called on the Parent, then only the Parent reference is kept at class scope:
GumBatch can be used to render Gum objects on RenderTarget2Ds, just like regular SpriteBatch calls.
The following code shows how to render on a RenderTarget:
Note that if you are rendering multiple objects on a render target, the BlendState must be set as to add the transparency. Using the default BlendState may result in alpha being "removed" from the render target when new instances are drawn.
The following shows how to create a BlendState for objects which have partial transpraency and are to be drawn on RenderTargets:
UI events may require interacting with systems that are async by default (return Tasks). MonoGame projects do not have a default synchronization context for keeping async code on the primary thread, but this can be added fairly easily.
This tutorial shows how to add and work with a synchronization context to allow async calls without leaving the primary thread. The MonoGameGumFromFile project shows how to add a synchronization context. You can view this project .
When a method makes an async call, its continuation is not guaranteed to be on the same thread as the code preceding the async call. For example, consider the following code:
Unfortunatey, the code above may end up crashing or having other unexpected behaviors since the Button's IsEnabled is potentially being assigned on a non-primary thread. This is problematic because the UI may get updated mid-update, causing unexpected results.
Instead, we would like to keep all methods on the primary thread so that we can confidently interact with the UI without worrying about making changes mid-render.
The MonoGameGumFromFile sample includes a class called SingleThreadSynchronizationContext
which provides a simple synchronization context for keeping all async call continuation on the primary thread. You can download the file and add it to your project from here:
Once you have added it to your project, you need to add an instance to your Game class, initialize it in your Initialize method, and call its Update method in the Game's Update, as shown in the following code snippet:
After adding the SingleThreadSynchronizationContext class and after modifying your Game class as shown above, you can make async calls safely.
Keep in mind that the SingleThreadSynchronizationContext class can be modified for your own needs if you are comfortable making these changes.
MonoGame projects can take full advantage of the Gum tool and runtimes to create flexible layouts which are useful for HUDs, Menus, and UI of any complexity.
The Gum UI Tool is a WYSIWYG editor for creating layouts. Projects that are created in the Gum UI tool can be loaded into your MonoGame project with just a few lines of code.
The Gum runtime (called MonoGameGum) is a NuGet package which adds the classes necessary to load and interact with Gum projects.
Absolutely not! The Gum tool can be useful for doing complex layouts, previewing how things may be positioned, and helping you learn how to code with Gum - but it is not required! You can use Gum purely in code to do your own layouts or use only parts of Gum (such as font rendering).
This section uses screenshots of the Gum tool so you can see what is possible with Gum, but everything you see here can also be done purely in code.
If you prefer to dive in and see things working, the Gum repository includes sample projects that show how to work with Gum purely in code, and also how to load a Gum project into a MonoGame project.
You can clone the repository and open the projects in your favorite IDE (like Visual Studio) and try them out.
The direct link to the samples is here:
For more information about the Sample projects, see the .
The Gum UI Tool (usually called "Gum") is a visual editor for creating layouts using the Gum layout engine. Gum has been used on many commercial games to create all types of UI ranging from standard game HUDs to complex forms-based UIs. Gum can be used for any type of game.
The Gum tool is simple to use - you can create your screens by drag+dropping, moving, and resizing objects with the mouse.
Gum is an object oriented design tool, so projects can contain reusable components which contain other components and standard elements (text, sprite, container, etc). Gum also provides inheritance, and behaviors (a concept similar to interfaces in C#). For example, the following PauseMenu component inherits from UserControl - a base type defining the standard visuals for a framed UI element.
The Gum Layout Engine is the core technology behind the Gum UI Tool and the Gum MonoGame runtimes. Gum layouts use a few rules to determine the position and size relationships between parents and children. These rules allow for the creation of virtually any type of layout.
Projects which perform their layouts purely in code can still take advantage of the Gum UI Tool to preview their layouts and to learn about the capiblities of the GraphicalUiElement (the C# object type providing access to all Gum properties).
By default, Gum elements are positioned relative to the top-left of their parent. Similarly, the origin of a Gum element is also its own top-left corner. Therefore, a rectangle that has an X of 100 and a Y of 50 appears as shown in the following image:
The Gum tool helps you visualize the relationship between a child and its parent when the child is selected. Notice that the child draws a line from its origin (its top-left corner) to the top left of its parent. In this case the parent is the entire screen, which has a dotted outline.
A child's position is relative to its parent's position, so changing the position of the parent ultimately changes the absolute position of its child as well. The following animation shows a parent container which has a white rectangle as its child. Notice the child can be moved relative to the parent. If the parent is moved, then the child's absolute position changes as well.
This basic type of layout is similar to layouts provided by most visual APIs including SpriteBatch in MonoGame.
The Gum layout engine is built around the concept of "units". As mentioned above, by default the X and Y values of an element is measured in units from the top-left corner. In other words, the default X Units is absolute pixels from left for X and absolute pixels from top for Y. The Gum tool exposes this as a set of buttons.
At runtime, these properties exist as enums which can be changed. For example, to set an element's XUnits to be relative to the horizontal center of its parent, the following code can be used:
As mentioned above, the Gum tool is very useful for testing out how different properties behave quickly. For example, the following animation shows how X and X Units can be used to change the position of an object relative to its parent:
The position, units, and origin values can be used to create common layouts. The following code could be used to center a child in its parent:
This same layout could be achieved in the Gum UI tool by setting the following values:
X = 0
X Units = Pixels from Center
X Origin = Center
An element's size can also be controlled through units. For example, a child rectangle could set to provide an 8 pixel border inside of its parent container using the following code.
Similarly, the following could be done in the Gum UI tool::
X = 0
X Units = Pixels from Center
X Origin = Center
Y = 0
Y Units = Pixels from Center
Y Origin = Center
Width = -16
Width Units = Relative to Container
Height = -16
Height Units = Relative to Container
Note that the Width and Height are set to -16, which is twice the desired border. This is because the border of 8 pixels must appear on both the left and right sides for Width and both the top and bottom sides for Height.
Notice that each of these properties combines to produce a center layout. While this may seem verbose, this type of fine control provides ultimate flexibility. You aren't limited to simple alignments such as left, right, and center. Rather, you can create layouts where any part of the object is positioned relative to any other part of its parent.
This type of center layout is responsive to changes in the parent, so if the parent changes position or size, the child moves along with it as expected.
Hierarchies can go many levels deep, and each parent child relationship follows the same rules. For example, the following animation shows a relationship where the blue and red children occupy the left and right half of the white rectangle, including a border of 8 pixels around and inbetween the rectangles. Notice that changing the parent size automatically cascades size and position changes to the children.
Children are in control of their own layouts using "unit" values, but parent elements can also apply rules to control layout by setting the Children Layout property. For example, a parent can stack its children from top-to-bottom by setting Children Layout to Top to Bottom Stack. Notice that changing the stacking from top-to-bottom changes the Y positioning of the children. The X position is intentionally staggered to be able to see the position of each rectangle when stacking is turned off.
Children can still control their position values relative to the stacking, so a child can change its X and Y value. If a child changes its Y or Height value in a Top to Bottom Stack, then subsequent children are adjusted react to this change immediately.
Stacking can be combined with wrapping and stack spacing to create list boxes and inventory grids quickly.
Layout dependencies can go from parent-> child and child-> parent to create powerful layouts. We recommend that new users spend some time in the Gum UI Tool to see what can be created and to browse the documentation to see more example images and animations.
If you're ready to use Gum, then head on over to the Setup page. The MonoGame section provides information specific to MonoGame, but the rest of the Gum documentation site provides information which applies both to the Gum UI Tool and coding of Gum in MonoGame projects.
The easiest way to use Gum is to add the NuGet packages to your game project. Alternatively you can link your game to Gum source for additional debugging, to stay up to date with the latest improvements, or if you are interested in contributing.
This document assumes you already have a game project with the Gum NuGet packages linked.
If you have followed the Setup steps, then you should have a game which references the Gum NuGet package.
To replace this package with source references:
Clone the Gum repository
Remove the NuGet package by selecting Gum.MonoGame and pressing the Delete key.
Right-click on your Solution in the Solution Explorer and select Add -> Existing Project...
Select <Gum Root>/MonoGameGum/MonoGameGum.csproj
Repeat the previous step but select the following csproj files:
<Gum Root>/GumCommon/GumCommon.csproj
<Gum Root>/GumDataTypes/GumDataTypesNet6.csproj
<Gum Root>/ToolsUtilities/ToolsUtilitiesStandard.csproj
Right-click on your game project's Dependencies folder and select Add Project Reference...
Check the Gum projects you added to the solution earlier and click OK
You are now fully linked to source. You can build and run your game.
Gum Forms is a set of classes which provide fully-functional forms controls which you can use in your game. Examples of forms controls include:
Button
Checkbox
ListBox
TextBox
Slider
Gum Forms can be used purely in code (no .gumx project required), or you can fully style your forms objects in a Gum project.
The easiest way to add Forms to your project is to use the FormsUtilities
class. Keep in mind that Forms is not a replacement for Gum; rather, it adds objects on top of Gum which provide common UI interaction. In other words, if you are using Forms, you are still using Gum as well. Therefore, when using Forms you must also initialize Gum.
The following code snippet shows how to initialize Forms and Gum, and how to add a single Button to your project:
The code above produces a single button which can be clicked to increment the click count.
Forms can be used with the Gum tool, allowing you to create fully functional UI layouts visually.
To use Forms in a project that loads a Gum project (.gumx) the following steps are needed:
Components must be added to the Gum project which have the necessary behaviors to be used as Forms visuals
The Gum project must be loaded in code, just like any other Gum project
To add components which are used for Forms visuals:
Open your project in Gum, or create a new project
If creating a new project, save the project in a subfolder of your game's Content folder
Select Content -> Add Forms Components
Check the option to include DemoScreenGum, or alternatively add a new screen to your project and drag+drop the desired components into your screen
Once you have saved your project, modify your Gum file to include the project:
Open your .csproj in a text editor (or click on it in Visual Studio)
Add the wildcard addition code to copy all of your Gum projects
Your project is now referenced in your game. Modify the Game file to initialize the Gum systems and to load the .gumx project. Your code might look like this:
The static ModalRoot and PopupRoot properties provide an InteractiveGue which serve as the root for any element which should appear on top of other elements. These properties have the following characteristics:
Automatically created by FormsUtilities.InitializeDefaults
Automatically resized to fit the entire screen, including if the GraphicalUiElement.CanvasHeight
and GraphicalUiElement.CanvasWidth
change.
Both Remains on top of all other elements for its given layer. ModalRoot appears on top of PopupRoot.
These properties can be used in custom code to place elements (such as custom popup and toast elements) above all other elements.
ModalRoot and PopupRoot are used internally by Gum Forms. For example PopupRoot is used to display the ListBox which appears when expanding a ComboBox.
Popups which are placed on the ModalRoot element are considered modal - they block the input of all other controls. This is useful if you would like to create a popup which must be clicked before any other elements receive input. If multiple elements are added to ModalRoot, only the last item (and its children) receive input events. This allows one popup to show another popup.
By contrast, elements added to the PopupRoot are not modal - other elements can receive input.
The ComboBox control normally places its expanded form ListBox on PopupRoot; however if the ComboBox is on a ModalRoot then its ListBox is also added to ModalRoot.
The following code can be used to display a popup to either ModalRoot or PopupRoot depending on the isModal
value.
This page shows the minimum code needed to get Gum up and running in your project. If you want to load a Gum project created in the Gum tool, see the page.
The Gum tool can be used to create Gum projects which can be loaded into your MonoGame project. To download and run the Gum tool, see the .
For more information on loading FNT files, see the documentation.
For a more detailed discussion of using GumBatch, see the page.
Gum produces a set of XML files (and PNG/FNT files for fonts) which can be added to any MonoGame project and loaded with a few lines of code. For information on loading projects, see the page.
A full list of Gum properties can be found in the page, but we will cover a few concepts here to give you an idea of how Gum works.
Also, if you have any questions, head on over to - we're eager to help new users get their Gum projects up and running quickly!
The IsFocused property gets or sets whether a component has focus. For example a TextBox will have its IsFocused set to true if the caret is visible and if it is taking input from the keyboard.
IsFocused can be directly assigned to give focus to an object. For example the following code gives a TextBoxInstance focus:
If you are setting focus on a TextBox in response to a click event, you may need to also clear the Cursor's input. For example, the following would set focus on TextBoxInstance when ButtonInstance is clicked:
The ListBox control provides a scrollable list of ListBoxItems for displaying and selecting from a list.
The following code adds items to a ListBox when a button is clicked. When an item is added, ScrollIntoView
is called so the item is shown.
ListBox items can be selected. The ListBox class provides a number of ways to work with the selection.
Selection can be set by index:
Item can also be selected by the reference itself, assuming the referenced item is part of the list box:
Whenever the selection changes, the SelectionChanged event is raised:
The VisualTemplate lets you customize the type of ListBoxItem created for the ListBox. The following code shows how to assign a VisualTemplate to a runtime object named CustomListBoxItemRuntime:
The VisualTemplate class can optionally pass a parameter representing the item in the list box. This can be used to create different types of items based on the object added. For example the following code would compare the passed object as an integer to whether it is greater than 100 and returns a different item depending on this result:
Note that the code above uses the item to decide which type of list box item to create. If your list box item needs to react to changes on the item, you can also pass the item in the constructor to your list box. This allows for additional initialization based on the item. You can also hold on to the reference of the item to react to changes that may happen on the item, or to push changes to the item.
In other words, you are free to use the item for your game's needs; however, keep in mind that UpdateToObject will be called after your ListBoxItem is constructed. For more information on how to customize UpdateToObject, see the section below.
By default the ListBox calls ToString on each item. This is usually okay if you are dealing with primitive types. For example, the following code adds sequential integers to a ListBox:
Often you may want to add a list of items which should not use their ToString method. For example you may have a list of IDs which represent weapons in a dictionary. The display can be customized by inheriting from ListBoxItem as shown in the following code:
The ScrollViewer control provides a container which can hold Gum objects (including other Gum Forms objects). The user can scroll the ScrollViewer with the mouse or ScrollBar.
By default the ScrollViewer's InnerPanel expands automatically in response to its children and stacks its children top-to-bottom. Of course, this behavior can be changed since the InnterPanel is a standard GraphicalUiElement.
The following code creates a ScrollViewer and adds ColoredRectangleRuntimes to the ScrollViewer.
VerticalScrollBarVisibility controls the visibility of the vertical scroll bar, specifically in regards to the number of items in the ScrollViewer. The available values are:
Auto - the ScrollBar displays only if needed based on the size of the inner panel
Hidden - the ScrollBar remains invisible even if the contents of the inner panel exceed the size of its container
Visible - the ScrollBar always displays
The default is Auto which means that the scroll bar only displays if necessary.
The PasswordBox control is a TextBox-like control which can be used for entering passwords. It uses a SecureString
rather than regular string
and hides the entered characters by using the *
key for each character typed. For more information see the SecureString documentation: https://learn.microsoft.com/en-us/dotnet/api/system.security.securestring?view=net-8.0
The following code adds a password box.
The TextBox control allows users to enter a string. It supports highlighting, copy/paste, selection with mouse and keyboard, and CTRL key for performing operations on entire words.
The following code creates a TextBox.
Selection can be performed programmatically or by the user using the cursor.
The SelectionLength
property can be used to determine if any text is selected. The following code shows how to output the selected characters:
The SelectionStart
and SelectionLength
proerties can be modified to change the visual selection. For example, the following selects the first 5 letters:
The entire text can be selected as shown in the following code:
Selection can also be performed by the user. Double-clicking the text box selects all text.
A push+drag with the mouse selects the text between the start and the current location of the drag.
Holding down the shift key and pressing the arrow keys adjusts the selection.
The TextWrapping property can be used to set whether the TextBox wraps text. By default this value is set to TextWrapping.NoWrap
which means the text does not wrap, but instead extends horizontally.
If TextWrapping is set to `TextWrapping.Wrap, then text wraps to multiple lines. Note that usually this is combined with a taller text box so that multiple lines display properly.
The Slider control provides a way for the user to change a value by dragging the slider thumb.
The following code creates a Slider which allows the user to select a value between 0 and 30, inclusive. The IsSnapToTickEnabled
property results in the value being snapped to the TickFrequency
value. In this case, the value is used to force whole numbers.
Gum Forms provide fully functional controls with minimal setup. These controls can be restyled in code, either per-instance, or globally per control type. Customization can be performed in-code or in the Gum tool.
Individual instances can be customized by modifying the built-in states which are added automatically by the default implementations.
Note that all code in this document assumes that Gum Forms has already been initialized.
The following code shows how to modify a Button instance. A default button can be constructed using the following code:
Notice that this button has subtle color changes when the cursor hovers over or pushes on it.
These cursor actions result in different states being applied to the button. These states are initialized by default when calling the following code:
We can customize the state by modifying the values. For example, we can change the color of the background by adding the following code:
Now the button highlights yellow instead of a lighter blue.
Each Forms instance creates its own Categories dictionary, so modifying the Categories on one instance does not affect the Categories on another instance.
Any property on the button or its children can be modified through states. For example, we can also change the text color and size as shown in the following code. You may need to make the button bigger so it can contain the larger text.
The button text now becomes black and is twice as big when highlighted but notice that the text changes are not undone when the cursor moves off of the button (when the Highlighted state is unset).
The reason that the hover state is not unset is because all variables which are set through states persist until they are undone. Typically if you create states in the Gum tool, the Gum tool forces any state which is set in a category to also be propagated through all other states in the same category. However, when we're setting states in code, we must make sure to apply any states that we care to all other categories.
In this case we can fix the larger text by setting the TextInstance's color and FontScale back to its default:
Each default control type is made up of individual instances, most of which are standard types such as ColoredRectangle and TextInstance. The example above assigns properties on two instances:
ButtonBackground
TextInstance
Since each control (such as Button, CheckBox, or TextBox) has its own individual instances, we need to know the names and types of these instances to add VariableSaves to our states.
We can find the names of these instances by looking at the source code for the default forms implementations.
These can be found in the Gum repository here:
For example, we can look at the DefaultButtonRuntime.cs file and notice that it has a ButtonBackground and TextInstance:
By inspecting the code of other controls we can see which instances are available for styling. We can also look at the existing states which are provided by the default implementations. For example the DefaultButtonRuntime adds states for Enabled, Highlighted, Pushed, and Disabled. Note that this list may change in the future as Gum Forms continues to be developed.
Keep in mind that the Name property of the internal instances is important. For example using the code above, the background object is accessed through "ButtonBackground" rather than "background" when creating new states.
The example above shows how to replace styling on a single Button instance. Instead of changing each instance manually, we can create a derived class which defines its own custom styling.
The first step is to create a new class which inherits from the default Forms control. These can all be found in the DefaultVisuals page linked above.
For example, we can create a derived class which inherits from the base DefaultButtonRuntime as shown in the following code:
Notice that we must implement a constructor with the same parameters as the base class - this is important because Gum calls this constructor for us when we create a Button instance and the parameter list must match.
Now we can implement our own styling inside the if(fullInstantiation)
block. The code to implement styling here is the same as above except this object is the visual, so the category exists on this
. For example, we can make the background pink when highlighted and enabled as shown in the following code:
Next we need to tell Gum Forms to use our new button as the default Button type. We can do this by replacing the default type associated with Button
as shown in the following code. This code should go in Game1 right after FormsUtilities.InitializeDefaults();
, before instantiating any Buttons as shown in the following code:
You may want to also remove or comment out any code for customizing the button explicitly below otherwise your pink styling may get overwritten on the particular instance by the styling written earlier in this tutorial.
By instantiating a Button
, Forms automatically uses your new StyledButtonRuntime
resulting in the button appearing pink.
The section above shows how to customize a button using inheritance. This approach is beneificial if you would like to modify the styling colors on the existing children of the button. Since Gum visuals are regular Gum objects, you can achieve even more customization by creating a new Button class which inherits from InteractiveGue and adding your own controls. In other words, you can add your own instances to the button (such as additional Text instances) or replace existing instances with your own (such as replacing the background ColoredRectangleRuntime with a NineSlice or Sprite).
For example, we can create a NineSlice that uses the following image:
Now we can create a new Button which inherits from InteractiveGue rather than DefaultButtonRuntime to fully customize the appearance of our button. Note that the only requirement that Buttons have is that they contain a Text object named TextIntance, so we should copy this instance from the DefaultButtonRutime code into our own. Our new Button also has a NineSlice which references the button_square_gradient.png from above, and states for Enabled and Pressed.
In general when creating your own Forms control, it can be helpful to reference the existing Default implementation for the control you are creating.
Of course we also need to tell Forms to use our new class as the default button type:
Now we can run our game and see the button in action:
As mentioned above, you are free to add any controls to your custom button including icons, additional Text instances, and additional Sprites for other effects. You can customize your Forms objects to look however you want.
Most controls in Forms share the same common states. The exception is components which can be toggled on/off such as CheckBox. For all other controls the following states exist:
Enabled
Disabled
Highlighted
Pushed
Focused
HighlightedFocused
DisabledFocused
CheckBoxes append the words On, Off, and Indeterminate to the states. For example, a CheckBox can support states including:
EnabledOn
EnabledOff
EnabledIndeterminate
DisabledOn
DisabledOff
DisabledIndetermate
... and so on.
Buttons can be defined fully in the Gum tool. This approach allows you to preview your visuals in the editor, and allows editing of the styles without writing any code.
Conceptually the steps are as follows:
Define a component for your forms type in the Gum tool
Add the states needed for the forms type that you are working with in the proper category
Define a custom runtime for the Forms control in your Visual Studio project
Associate the custom runtime to the forms type using the DefaultFormsComponents dictionary
This section walks you through how to create a custom Button component, and how to use this in your project. Once you understand how to create a Button component, other Forms controls can be created similarly.
The first step is to define a Button component in Gum. This component can be named anything you want. For example, you may name it Button or StandardButton. You can also create components for specific purposes such as CloseButton which would be a button that closes menus.
Components defined in Gum can contain almost anything you want; however, Buttons should usually contain a TextInstance so that the Text property can assign the string on an internal Text object.
The following image shows the a component named StandardButton which contains a ColoredRectangle, a Rectangle, and a Text instance. For other controls, see the DefaultVisuals page linked above.
All Gum Forms components react to various properties by assigning states. For a full list of states needed, see the DefaultVisuals page linked above.
Once you have created a Component in your project, you need to create a custom runtime class. This custom runtime class associates the Component in your .gumx file to a strongly-typed class. This runtime type also enables the creation of Forms controls by instantiating the runtime object, including when an element from the Gum project is converted to a GraphicalUiElement.
The runtime class does not need much code since most of the work is done in the Gum project. The following shows an example custom runtime for the StandardButton component:
This runtime can be associated with the StandardButton component in Gum using the following code in your Game class:
Finally, we can associate the Forms control with the runtime. For example, the following code can be used to create a StandardButtonRuntime whenever the code calls new Button
. Note that this is not a requirement for working with Forms, but it can make testing more convenient.
Note that in this case, we can only associate one type of component runtime with each type of Forms control. In other words, if you write code that instantiates a new Button using the Button constructor, a StandardButtonRuntime will be created internally.
Of course, you are not required to create buttons this way - you can also create buttons by adding instances of your component in your Gum screen in the tool, or by instantiating the desired runtime.
ListBoxItems are typically created automatically when items are added to a ListBox instance. We can modify ListBoxItems by creating a runtime object for our ListBoxItem then assigning the ListBox's VisualTemplate.
You may want to rename the class when creating your own version. For example, you may want to name yours CustomListBoxItemRuntime
.
Once you have created your custom ListBoxItem runtime implementation, you can use it on a list box by assigning the VisualTemplate. Be sure to assign it before adding items to your ListBox, as shown in the following code:
Notice that the code above passes a false value to the tryCreateFormsObject
parameter. This prevents the CustomListBoxItemRuntime from creating its own Forms object that would override the default styling.
Components in a Gum project can be instantiated in custom code. Note that this is not a requirement to use a component since you can also add an instance of the component in your screen.
Before instantiating a component, you must first load the project using the standard .gumx loading code as shown in the following code block:
Once you have instantiated your project, you can create a component as shown in the following code:
The Components property contains a list of all components, so you can also access components by name or other property. For example, the First method can be used to find a component by name as shown in the following code:
Note that the name passed to the First method should match the name given in Gum. For example, in this case the code searches for a component named ColoredRectangleComponent.
If a component is in a folder, then its name is the qualified name relative to the Components folder. For example, the following component's name at runtime is "Buttons/StandardButton"
The ToGraphicalUiElement method can automatically add the component to the root for rendering, or alternatively it can be added to an existing container. If adding to an existing container, then the ToGraphicalUiElement's addToManagers parameter should be false as shown in the following code:
The SetProperty method can be used to set properties on components which are not natively part of GraphicalUiElement. This is useful in the following situations:
Setting a property which may not exist on all GraphicalUiElements, such as the Text property on a GraphicalUiElement for a Text standard element
Setting a property which has been exposed
If a GraphicalUiElement is a Text instance, the Text property can be assigned through SetProperty as shown in the following code:
If a component has an exposed variable, then this variable can be assigned through SetProperty. For example, consider the following component which exposes its Text variable:
This can be assigned through the SetProperty. Be sure to use the name exactly as it appears in Gum:
States can be applied in code by string (unqualified name), or by accessing the state on the backing ComponentSave. Note, this can also be performed on screens and standards.
MonoGameGum provides common runtime types which can be used to build your layouts. The runtime objects correspond to the standard objects in the Gum tool. These provide a type-safe, expressive way of creating and working with Gum. The following runtime objects exist:
ColoredRectangleRuntime
ContainerRuntime
NineSliceRuntime
SpriteRuntime
TextRuntime
Notice that at the time of this writing, only a subset of Gum standard types are available. This is likely to expand over time.
All runtime objects inherit from GraphicalUiElement, which is the base class for all Gum objects. Therefore, all runtime objects share the same properties for position (such as X and XUnits), size (such as Width and WidthUnits), and rotation.
A typical Gum project references many file types. Aside from the XML files created by the Gum tool (such as a .gumx file), a typical Gum project also references .png files and .fnt files.
Files which are referenced by your Gum project (as created in the Gum UI tool) automatically load their necessary dependencies assuming the files are part of the built file system. Typically this means that your project should copy all Gum XML, PNG, and FNT files to the output folder. Gum does not use the MonoGame content pipeline.
When a file is added to a Gum project, the Gum UI tool checks the location of the file. If the file is not relative to the Gum project file (.gumx), the Gum UI tool warns you about the file being located outside of the project's folder. The tool recommends that the file should be copied so that your project remains portable.
If all of your project files are located relative to the .gumx root project file, then your project should be portable, and all referenced files will be automatically resolved for you when instantiating Screens and Components from your Gum project.
The Gum runtime library performs all of its loading from-file, so all of your files must be present in the destination directory. As explained in the page, all of your files should be set to Copy if newer in Visual Studio.
Gum runtime objects can reference files. For example both SpriteRuntime and NineSliceRuntime can reference a Texture2D. Similarly, the TextRuntime type can reference BitmapFonts which are loaded from .fnt and .png files.
All runtime types support the assignment of these files by direct assignment of their appropriate type, or by string name.
For example, a Sprite's texture could be assigned either through the SourceFileName property or the Texture property:
In the case of the SourceFile assignment, the SpriteRuntime loads the Texture2D from disk. By default the file is loaded relative to the Content folder.
You can explicitly load font files if you would like to change fonts in custom code, or if you are using the GumBatch class to do your own Gum rendering.
To load a file, first make sure that your font is added to Visual Studio, usually in the Content folder. In the case of fonts, you should have at least 2 files:
A .png file
A .fnt file
Usually both files are added to the same directory. Be sure to mark both files as Copy if Newer.
The file can be loaded using the BitmapFont constructor:
Whenever a file is assigned on a runtime object, Gum looks for the file in the ToolsUtilities.FileManager.RelativeDirectory
directory. This directory defaults to your game's Content folder.
If your Gum project (.gumx) is located in the Content folder, then you should probably not change this value.
If your project is located in a subfolder of Content, then you must change the relative directory to be the location of your Gum project before you assign files. For example, consider a situation where the Gum project is located in a folder called gum.
To support this situation, you would want to set your relative directory as shown in the following code:
Note that the following operations can result in files being loaded, so if your project is not located in the Content folder then you must set the RelativeDirectory before doing any of the following:
Calling ToGraphicalUiElement
Assigning SourceFileName
Setting custom or cached fonts on a Text object
Setting states (which may assign variables)
It's recommended practice to set the RelativeDirectory to your Gum project's location and to leave it there so you never have to consider subfolders in any code that accesses files directly or indirectly.
By default Gum caches loaded textures. In other words, the following code only results in a single file IO operation:
File caching can be disabled by setting the LoaderManager's CacheTextures property to false as shown in the following code:
Of course, doing so means that Gum will go to disk for every file which can increase load times and result in significantly more video memory usage.
Note that setting CacheTextures to false flushes the cache and disposes all cached content, so you can force the reload of all files by calling setting CacheTextures to false, then back to true as shown in the following code:
Be careful setting CacheTextures to false since all existing textures will be disposed. This means that if you have loaded textures which are still being referenced by runtime objects, you will get an exception if those are still being drawn after setting CacheTextures to false.
If your game includes support for resizing the game window, you may need to write additional code to handle the new width and height. This page discusses the options you have for handling resizing. When a game is resized, the typical response is to adjust GraphicalUiElement.CanvasWidth and GraphicalUiElement.CanvasHeight, but you may also want to zoom your UI depending on the needs of your game.
Desktop projects can set their initial size in the Game constructor as shown in the following code:
By default resizing your Game does not adjust Gum. The following animation shows how Gum behaves by default. Note that the objects in the following animation are properly docked to the corners and center as indicated by the displayed text:
This section discusses how react to the window resizing by adjusting the GraphicalUiElement sizes and performing a layout. The Screen contains a Container which is sized to the entire screen with a small border around the edges. The Container has a ColoredRectangle which fills the entire Container. Each Text object is docked as indicated by its displayed string.
The following code shows how to handle a resize:
You may want to zoom your game rather than provide more visible space to the user when resizing. In this case you need to decide whether to use width or height when deciding how much to zoom your game. For this example we will use height since some users may have monitors with differing aspect ratios.
To properly zoom we need to store the original size in a variable in the Game class so that we can use it to determine the zoom level. The following code is a modified version of the code above with additional logic and variables added to handle zooming:
The FrameworkElement object has two InteractiveGues: PopupRoot and ModalRoot. These are typically created automatically by FormsUtilities but can be assigned manually. In either case, the size of these two containers is automatically managed by FormsUtilities in its Update call so you do not need to update these manually.
This page discusses common troubleshooting techniques when your Gum Forms objects are not behaving as expected.
You can check the WindowOver property to see what the Cursor believes it is over. This can tell you if the Cursor is over the object that you expect it to be over. The following code can be used to output the CursorOver to Visual Studio's output window:
Clicks could be offset if the GraphicalUiElement's CanvasWidth and CanvasHeight are set incorrectly. For more information, see the .
You can also output the Cursor's X and Y values to the screen to compare them to the desired object's bounds, as shown in the following code:
Download this file to your game's Content folder, and mark the file as Copy if Newer. Make sure it appears in Visual Studio. For more information on file loading, see the tutorial.
For Buttons, we can add a ButtonCategory state. You are free to implement as many or as few states as you want. For the full list of states see above in the section.
For more information on using a custom runtime defined in your Gum project, see the tutorial.
The easeist way to create a runtime object for ListBoxItem is to copy the existing DefaultListBoxItemRuntime class which can be found here:
Notice that the DefaultListBoxItemRuntime creates visual states beginning on this line:
If your component is not visible, this may be a file issue. By default Gum project loading will not throw exceptions on missing files, and it will attempt to re-create missing file components. For more information, see the .
For a reference to the type of properties available on GraphicalUiElement, see the section. For information about working with GraphicalUiElement properties in code, see the reference.
ContainerRuntime is a GraphicalUiElement-inheriting object used to organize and perform layout on a specific group of objects. Examples of when to use a container include:
Providing margins inside the screen or another container
Aligning or orienting children along a common position
Changing children layout types, such as stacking children horizontally inside a parent container which stacks its children vertically
To inject spacing between objects when using ratio width or height
ContainerRuntime instances have no visuals, so they cannot be directly observed in game.
To create a ContainerRuntime, instantiate it and add it to the managers as shown in the following code:
Containers are usually used as parents for other runtime objects. To add another runtime instance to a container, add it to the Children list as shown in the following code:
Notice that only the parent object needs to have its AddToManagers method called. Any child added to a parent which has been added to managers is automatically added as well. This membership is cascaded through all children, so if your project has a single root object, then only that root object needs to be added (or removed) from managers.
The following code shows a parent container added to managers. The child container and child text do not need to be added to managers:
The CurrentInputReceiver property gets and sets the current object which is receiving input from the keyboard. Only one element can be the CurrentInputReceiver at one time, but this property may be null if no elements are receiving input.
This property can be set in a number of ways:
Forms objects such as TextBox set themselves as the CurrentInputReceiver when clicked
Setting IsFocused = true on some Forms objects such as TextBoxes sets this
Explicitly setting CurrentInputReceiver sets this value, but keep in mind that doing so may not result in objects updating their states appropriately, so this typically should be assigned internally
The RollOverBubbling event is raised whenever the cursor rolls over an InteractiveGue. A roll is defined as the cursor being positioned over the bounds of an InteractiveGue when the cursor's X or Y values have changed.
This event is raised top-down, with children object having the first opportunity to handle the event. If the event is not handled by the child, then parents have the opportunity to handle the event. If the RoutedEventArgs Handled property is set to true, then no parents receive the event.
The following code shows how to implement ListBox scrolling using the cursor when the cursor is pressed.
The ColoredRectangleRuntime object can be used to draw a solid (filled) rectangle of any color. To draw a rectangle outline (not filled in), see the RectangleRuntime type.
The following code creates a ColoredRectangleRuntime:
The NineSliceRuntime object is used to draw a visual object which references a Texture2D, but which does not stretch the corner pieces of a texture, and which only stretches the edges between the corners along their axis. In other words, the NineSlice (sometimes also referred to as a sprite frame) is used to draw frames in UI which can stretch without introducing visual artifacts.
For more information about the NineSlice type, see the NineSlice page.
The following code can be used to instantiate a NineSliceRuntime which uses a Texture (png file) named Frame.png.
NineSlice textures can be assigned using a string property or Texture2D instance. When assigning using a string, the ToolsUtilities.FileManager.RelativeDirectory
is used to determine the file's directory.
For example, consider a file called Frame.png which is located in the Content directory:
This file can be used as a texture by assigning the RelativeDirectory and then loading Frame.png. Note that RelativeDirectory is usually set to Content, or to the location of the .gumx file.
Alternatively, a Texture2D can be assigned directly
Once a SourceFileName is assigned, the SourceFile property references a valid Texture2D which can be reused.
By default a NineSlice uses it entire texture. This can be customized using texture coordinate and TextureAddress properies as shown in the following code:
Note that if TextureAddress isn't set to Custom, then the four coordinate values are ignored and the entire texture is used.
The Gum repository contains multiple samples on a variety of Gum topics. This page discusses these samples, covering how to get them running on your machine and how to modify them to see different features in action.
Gum samples are located in the Gum repository. The GitHub repository can be found here:
Once you have cloned the repository, navigate to the <Gum Root>/Samples folder.
Notice that multiple samples exist, each in their own folder. Each folder has a .sln file (some contain multiple) which can be opened to view the sample. For example, the sample showing how to work with Gum Forms is located at <Gum Root>/Samples/GumFormsSample/MonoGameGumFormsSample.sln
.
The Samples folder is continually changing, and new samples are being added over time. The remainder of this page covers some of the most common samples.
The MonoGameGumFormsSample includes a number of pages showing different features related to using Gum Forms.
The screens can be switched by modifying the screenNumber
variable in the Initialize code:
The ComplexListBoxItemScreen shows how to create a ListBoxItem which is fully customizable. This page uses a ListBoxItem which has the following characteristics:
The layout is defined in the Gum tool rather than in code
Each item displays multiple pieces of information with multiple Text instances rather than a single Text instance
Each item displays information from a complex view model with multiple properties
The TextRuntime object is used to draw strings to the screen. It supports a variety of options for rendering text including alignment, fonts, coloring, and line wrapping.
To create a TextRuntime, instantiate it and add it to the managers as shown in the following code:
To get a TextRuntime instance from a loaded Gum (gumx) project, add the following code. This code assumes you have an object named CurrentScreen, and that it contains a Text instance named TextInstance:
By default all TextRuntime instances use an Arial 18 pt font. This can be changed by specifying ta custom font.
Fonts on TextRuntime objects can be modified in one of the following ways:
By setting the UseCustomFont
property to true
, then changing the CustomFontFile
property to a desired .fnt file.
By directly assigning the BitmapFont
property on the TextRuntime object, bypassing all other properties.
By setting UseCustomFont
property to false
, then changing the individual Font values. This approach requires following a specific .fnt naming convention.
For most projects, the first approach is recommended since it doesn't require specific naming conventions. The second approach also works well if you are directly loading the BitmapFont object yourself. The third approach is convenient if your project is using the Gum tool, and if the Gum tool has already generated fonts for the specific combinations of values you are assigning.
The following code shows how to load a custom font (the first approach):
Note that .fnt files reference one or more image files, so the image file must also be added to the correct folder. In this case, the WhitePeaberryOutline.fnt file references a WhitePeaberryOutline.png file, so both files are in the same folder.
Also, note that files are loaded from-file rather than using the content pipeline. This means that extensions (such as .fnt) are included in the file path, and that both the .fnt and .png files must have their Copy to Output Directory value set to Copy if newer.
The following code shows how to assign the BitmapFont property on a TextRuntime:
A TextRuntime's font can be controlled by its individual font component values. Setting these values in code will not produce a .fnt file for you - the .fnt file must already be in your project in the FontCache folder. The following values are used to determine the font (.fnt) to load:
FontSize
Font
OutlineThickness
UseFontSmoothing
IsItalic
IsBold
By default, all fonts will be of the format Font{Font}{FontSize}.fnt
. Consider the following code:
This results in the TextRuntime object searching for a font named FontArial24.fnt
.
The following additional suffixes (in order listed below) are added to the font name.
OutlineThicknes - if greater than 0, then the suffix _o
followed by the outline thickness is added. For example, if OutlineThickness is 3, a font might be named FontArial24_3.fnt
UseFontSmoothing - if false, then _noSmooth is appended. For example Font24_noSmooth.fnt
IsItalic - if true, then _Italic is appended. For example Font24_Italic.fnt
IsBold - if true, then _Bold is appended. For example Font24_Bold.fnt
The BmfcSave.GetFontCacheFileNameFor method can be called with any combination to obtain the desired font value. For example, the following code coudl be used to determine the desired .fnt file:
Note that this method does not take into consideration the content folder.
To create a .fnt file, you have a few options:
Open Gum, create a temporary Text instance with the desired properties, then look at the font cache folder
Manually create a .fnt file in a text editor and a corresponding .png. This option requires understanding how the .fnt file format is structured. The best way to learn this is to open an existing font file.
Using Gum to create the font cache is fairly simple, but you must know which fonts you intend to use ahead of time. A font is created automatically by the Gum tool whenever a Text property is changed.
To view the existing font cache, you can click the View Font Cache menu item in Gum.
As you make changes to the Text object, new files are created and added to the font cache folder, as shown in the following animation:
By default TextRuntime instances do not throw exceptions for missing font files even if GraphicalUiElement.ThrowExceptionsForMissingFiles is set to CustomSetPropertyOnRenderable.ThrowExceptionsForMissingFiles. The reason for this is because a TextRuntime's font is decided by a combination multiple properties.
If UseCustomFont is set to false, then the font is determined by the combination of font values (as discussed above). If useCustomFont is set to true, then the font is determined by the CustomFontFile (also as discussed above).
Ultimately the variables which are used for fonts can be assigned in any order, and can be assigned from multiple spots (such as direct assignments, states, or creation from Gum projects).
In other words, the TextRuntime doesn't know when variable assignment is finished. We can address this in a few different ways.
The first is to explicitly load the desired BitmapFont as discussed above. By calling the BitmapFont constructor, missing files will immediately throw an exception.
Another option is to use the GraphicalUiElement.ThrowExceptionsForMissingFiles
method to verify if a font is valid.
The following code example shows how to check for invalid fonts using this method:
For information on creating your own .fnt file with Bitmap Font Generator, see the page.
This code assumes a font file named WhitePeaberryOutline.fnt is located in the Content/WhitePeaberryOutline
folder. By default all Gum content loading is performed relative to the Content folder; however, if UseCustomFont is set to false, then all font loading is performed from the FontCache folder. See the section for more information on loading from the FontCache folder. See the page for more information about loading files in general.
The easiest way to mark all content as "Copy to Output Directory" is to use wildcard items in your .csproj. This is explained in the page.
As mentioned before, when UseCustomFont is set to false the Gum runtime looks for the font in the FontCache folder. For this particular example the font would be located at Content/FontCache/FontArial24.fnt
. Note that if your Gum project is not located at the content root, then your FontCache folder will not be directly in the Content folder either. To fix this problem using the FileManager's RelativeDirectory, see the page.
Use Angelcode Bitmap Font Generator. For more information see the .
The SpriteRuntime object can be used to draw a Texture2D to screen. It supports drawing the entire texture or a portion. It also provides the ability to scale according to the source texture size and aspect ratio.
The following code can be used to instantiate a Sprite which uses a Texture (png file) named BearTexture.png.
A SpriteRuntime's texture can be assigned using the name of the file or a direct Texture2D reference.
The SourceFileName property is used to assign the SpriteRuntime's texture using a file name. The name of the file should (by default) be relative to the Content folder. For example, consider the following line:
This code assumes that the file is relative to the project's Content folder, as shown in the following screenshot:
For more information on working with files at runtime, see the File Loading page.
Assigning Texture
If your game manages its own textures, you can assign a Texture on the SpriteRuntime through its Texture property as shown in the following code.
Note that assigning the SourceFileName property results in the Texture property referencing a texture if a valid texture is found.