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...
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...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
The component tutorial shows how objects can be sized and positioned according to the container that they are a part of. Although this is the default behavior, the parent of an instance can be explicitly set to another instance.
This functionality is useful for
Stacking objects on top of each other or side by side
Placing objects next to other objects which are dynamically sized
Creating tables and other complicated layout objects
For this example we'll create a Text object which includes a value and a unit of measurement. Specifically we'll create two text objects - one will display a numerical value, the other will say "feet". We will use two text objects so that we can independently color them.
To do this:
Create a new component called MeasurementDisplay
Drop two Text objects in the newly-created component
Name the first "ValueText"
Name the second "UnitsDisplay"
Next we'll make the UnitsDisplay use the ValueText as its parent:
Select the UnitsDisplay Text object
Change its Parent to ValueText
Change its X Units to "PixelsFromRight". This will make the text object be positioned according to its parent's right edge
Change its X to 10 - this means the UnitsDisplay text will be 10 units offset from the right edge of its parent ValueText
Change its Y to 0
Next we'll want the parent text (ValueText) to automatically size according to its contents. To do this, set its Width to 0. Setting Width to 0 on a text instance means that the text's width will be equal to the size needed to display the text.
Now that we have the texts set up, let's modify the color of the UnitsDisplay:
Select the UnitsDisplay
Change Red to 200
Change Green to 150
Change Blue to 0
Now the Text variable in ValueText can be changed, and when doing so the UnitsDisplay will automatically change positions:
States are a powerful way to create expressive groups of variables. Some UI elements may require a combination of states to be applied simultaneously.
For example, consider creating a CheckBox element. This CheckBox may have one set of states for whether it is checked:
Checked
Unchecked
But it may also need a second set of states for being enabled and disabled (which may modify the color of the Text and graphics for the check box:
Enabled
Disabled
In this case multiple states need to coexist and may be combined. Categories allow you to organize states so that multiple states can be set simultaneously.
For this tutorial we'll create a new component. This component will have state categories for size and for color. To do this:
Open Gum
Create a new Component called "CategoryDemo"
Right-click anywhere in the State box and select "Add Category"
Enter the name "Size" for the new category and click OK
Repeat the above steps to create a "Color" category
Now we can add states to the categories. To do this:
Right-click on the "Size" category and select "Add State"
Enter the name "Small" for the new state
Right-click on the "Size" category again and select "Add State"
Add a second state to "Big"
Right-click on the "Color" category and select "Add State
Add a state called "Red"
Right-click on the "Color" category again and select "Add State
Add a state called "Blue"
Now that we have states set up we need to add a visual element to the component so that we can see our changes.
To do this, drag+drop a ColoredRectangle into your component
To modify a state, you can select it and edit in the preview window or change properties in the Variables tab to modify what the state sets. Notice that normally for a component like this the ColoredRectangleInstance would have its width and height be relative to its container, but we're not doing this for the sake of keeping the tutorial shorter.
First we'll set the Size states. To do this:
Select the "Big" state
Resize the colored rectangle so it is larger than the default
Select the "Small" state
Resize the colored rectangle so it is smaller than the default
Next we'll set the Color states. To do this:
Select the "Red" state
Set the Red, Green, Blue values to: 255, 0, 0
Select the "Blue" state
Set the Red, Green, Blue values to: 0, 0, 255
Now that we have our CategoryDemo component set up with multiple categories, we can view these states on any CategoryDemo instance. To do this:
Create a Screen called CategoryDemoScreen
Drop an instance of the CategoryDemo component into the CategoryDemoScreen
Select the newly-created CategoryDemoInstance
Scroll down in the Variables list and notice that the instance has drop-downs for each category.
You can set each state independently and the states will combine
If a variable is modified in one of the states in a category, then all of the states in that category are automatically assigned the default value, and this value is explicitly set. This concept makes working with states far more predictable.
For example, we can consider a component which has:
A single ColoredRectangle
A category called RectangleSizeCategory
States called Big, Medium, and Small
Initially, all states in a category do not explicitly assign any variables. We can see this by selecting the category and observing the Variables tab.
If a variable is changed in one of the states in the category, then that variable propagates to all other states, and the Category lists this as one of the variables that it modifies.
For example, we can select the Big category and change the ColoredRectangle.Width property to 150.
Once this value is changed, the RectangleSizeCategory lists this as a variable that it modifies in the Variables tab.
If we select any of the other states in the category, they show that they explicitly set the Width value as well (the value has a white background instead of light green). The value is inherited from the default state.
Once a variable is set in a category, all states are required to set this value. A variable cannot be removed from a single state in a category. Rather, to remove a variable, all states in the category must remove the variable. This can be done by selecting the category and pressing the X button next to the variable name.
Gum supports creating and previewing animations in the editor through the use of states. The general workflow for creating an animation is as follows:
Create states representing the keyframes in the animation (usually one category per animation)
Add an animation to the component or screen
Add states to the animation and adjust their time
Set interpolation values for each keyframe to control "easing"
Gum's animation system is very powerful and can be used in a variety of situations:
Animations which play when a screen or component is shown or hidden
Animations used to transition between behavior states such as changing a button from regular to highlighted state
Lengthy animations which can last multiple seconds for complex transitions
Animations are stored separate from the screen or component on the file system. If a screen or component contains at least one animation then Gum will save a Gum Animation XML file (.ganx extension) with the word "Animations" appended on the screen or component's name. In other words GameScreen would have a file called GameScreenAnimations.ganx in the same folder containing information about its animations.
Once an animation has been made it can be played back in editor. The following shows how an animation is played back, both in real time and also by dragging the slider.
This page walks you through the basics of using the Gum UI tool (which we'll refer to simply as Gum for this and all other documentation).
Gum separates its elements into three categories: Screens, Components, and Standard (Behaviors are an advanced topic that we'll skip for these tutorials):
Standard elements represent the building-blocks for screens and components, and all projects use the same set of standard elements. To see the list of elements, expand the Standard tree item. Clicking on any element will display it in the preview window.
Sprite element is selected in the image above. Notice that since a SourceFile is not set, the Sprite renders as a red X.
Note that through plugins the Standard list can be expanded. For example, Gum supports additional standard types through a Skia plugin.
Components are objects which can contain standard elements and instances of other components. Components can be very simple, such as a Label, or very complex, such as an options menu with dozens of items.
Screens are objects which can contain standard elements and instances of other components. Unlike Components, Screens cannot be added to other Screens. Screens exist mainly for organization.
Components and screens are similar - both can contain instances of standard elements, and both can contain other components. The only difference between screens and components is that screens cannot contain other screens.
You can think of screens like a screen in a video game. Examples include a main menu, credits screen, options screen, and level selection screen. You can think of components as elements which are composed of multiple standard elements. Examples include a Button component which is made up of a Sprite instance and a Text instance, or a Logo component which may be made up of multiple Sprites and Text objects.
To create a screen:
Right-click on the Screens tree item and select Add Screen
Enter the name of the new screen - such as MainMenu
The newly-created screen is created and selected
Instances of standard and component elements can be added to screens and components. To add an instance:
Select the destination screen or component. For example, select the MainMenu screen
Push the left mouse button (but don't release it) on the Text item. If you happen to release the mouse button, this will select the Text item, so you need to re-select the destination (MainMenu).
Drag the Text item onto the preview window
Release the mouse button. A new text instance appears in your screen.
Once an instance is a part of a screen or component it can be edited visually in the preview window. The selected instance has eight (8) handles surrounding it. These are called the resize handles and can be used to change the selected instance's width and height.
In the case of the Text object, the resize handles are used to control how the text object performs line wrapping.
You can use the resize handles to resize the instance, or you can simply push the mouse button and drag inside the instance to change its position. Notice that an object's outline is displayed when the cursor is hovering over the instance.
Gum is the best Game UI Layout tool available. It provides a flexible, efficient layout engine capable of producing virtually any layout. Gum can be used in a variety of contexts including in the FlatRedBall game engine, MonoGame, and Meadow. The Gum layout engine can also be included in any .NET project without requiring the use of a particular graphical API.
Gum UI includes advanced layout functionality to create and preview your UI
Gum allows the creation of components which can be instanced and customized in screens and other components
Adjust an object’s origin, position units, size units, and stacking to create fluid UI
Grab the NuGet, add a few lines of code, see your Gum project in game!
Gum objects can be created and modified in code. Create fully-featured UI by subscribing to common UI events.
Gum is actively maintained and provides lots of ways to get answers:
Check the rest of the documentation here
Join the Discord chat (shared discord with FlatRedBall)
Create an issue on Github
Gum supports loading image files for Sprites and NineSlices. We'll discuss how to load files, and how they are referenced in Gum.
First we'll set up a workspace. To do this 1. Create a Screen. I'll call my Screen "SpriteScreen" 1. Drag+drop a Sprite into the newly-created Screen
Setting the Sprite SourceFile
The "SourceFile" property controls the image that the Sprite displays. Common examples of source file types are .png and .tga. To add a source file
Select a Sprite
Click on the "SourceFile" box
Click the "..." button to bring up a file window
Navigate to the location of the file you would like to load
Click "Open" in the file window
Once the source file is set the image will appear in Gum
Files referenced by Gum projects will be relative to the root gum project itself. Therefore, you may notice that the source file begins with a "../", indicating that the relative location of the file is not a subfolder of the Gum project. For portability you may want to keep all source files in a folder located under your gum project (which has the extension .gumx).
The Variables tab in Gum displays all available variables when editing an instance. While the visual editor is very handy for quick edits such as positioning and resizing instances, the Variables tab exposes all variables. It is also useful for making fine changes to instances, such as by moving an instance by a single pixel.
The Variables tab shows variables for the selected instance or element.
Variables can be edited simply by changing values on the selected variable. For example, to move the text to the right, change its X value to a positive number:
Gum provides a flexible positioning system. The position of an element is a result of a number of variables. We'll go over a few here.
By default all instances are positioned by their top-left corner. For example, setting the Text instance's X and Y to 0 aligned its top-left position to the top-left of the screen (which is identified by a dotted line.
We can change the origin of the Text object by setting its "X Origin" and "Y Origin" values. Notice that if X Origin is set to "Center" then the Text object is positioned by its center:
Notice that I had to pan the view to be able to see the Text object. Gum provides multiple ways to pan the view:
Press and hold the middle mouse button while the cursor is over the preview window. While the middle mouse button is down, move the mouse cursor.
Use the scroll bars on the bottom and side of the view
Hold down CTRL and press the arrow keys
Changing the X Origin value changes the origin of the selected instance; however, it is still positioned relative to the top-left corner of the Text instance's container - which in this case is the entire screen designated by the dotted outline rectangle.
We can change the origin that the Text is relative to by changing the X Units. By default the X Units variable is set to Pixels from Left for X and Pixels from Top for Y.
Changing the X Units to Pixels from Right will cause the Text to be positioned on the right-side of the screen.
The X,Y values, Origin values, and Units values are all available for every type of element in Gum; however, these values only change the bounds. In the case of a Text object we may be interested in how the text is aligned within the bounds. The Text object offers two variables for aligning its text: Horizontal Alignment and Vertical Alignment. Changing the Horizontal Alignment to Center centers the Text within its bounds:
You may have noticed that some variables in the Variables tab have a green background while others have a white background. For example, in the image above the TextInstance's Vertical Alignment is green. The reason for this is because instances are not required to define values for every variable. Whenever an instance does not set a variable value, it uses the value that is defined in the Standard Element definition.
To see how this works, select the Text item under the Standard folder. Notice that all values have a white background. Notice the default values for Horizontal Alignment and Vertical Alignment:
If the default Horizontal Alignment and Vertical Alignment values are changed, the changes will immediately be reflected in the preview window for the default Text configuration:
Now if we select the TextIntance we will see that the VerticalAlignment is visibly using the Bottom value; however the Horizontal Alignment is still using center - this is because a value that is explicitly set on an instance will always override the default value set in the Standard element. Notice that Horizontal Alignment has a white background (indicating a custom value) and Vertical Alignment has a green background (indicating a default value).
Values can be reverted back to their default simply by right-clicking on the variable name in the Variables tab and selecting Make Default
The ability to expose variables in Gum makes components very powerful and flexible. For this example we will continue the Button example from the last tutorial.
The last tutorial set up a Button component with Text and ColoredRectangle instances. The two were set up to be positioned correctly according to the size of the button.
We then created a MainMenu screen and added a few instances of the Button component to the MainMenu screen.
While the size and positioning functionality in our button works well, the Text itself always says "Hello".
By default each instance of our Button cannot access values that are contained inside the ColoredRectangleInstance or TextInstance. However, we can "expose" these variables so that they can be modified in our MainMenu screen.
To do this:
Select TextInstance under Button
Find the "Text" variable in the Variables tab (Second column, under the "States" panel)
Right-click on the text box and select "Expose Variable"
Enter the name "Text" for the variable name
You can verify that the Text value is exposed by clicking the "Button" component and seeing the "Text" variable under the "Exposed" category:
Now that the Text variable is an exposed variable, it can be set per-instance. To do this:
Select one of the Buttons in MainMenu
Change its Text to "Button 1"
Feel free to set different Text values on all of the buttons. Notice that the Text may word-wrap.
States allow you to set multiple variables at one time. Examples of states might include:
A button with Regular, Highlighted, Pressed, and Disabled states
A game logo in Large and Small modes
A game where multiple options can be selected
This tutorial builds upon the previous tutorial where a Button component was created. To follow along you will need to have a Button component created as defined in the earlier tutorials.
First we'll define two new states. All components and screens have a "Default" state automatically. This Default state is uncategorized, but all other states must be in a category. Therefore, we'll first add a new category:
Right-click in the States tab
Select Add Category
Enter the name ButtonStateCategory
To add a new state:
Right-click on ButtonStateCategory
Select Add State
Enter the name "Highlighted"
Click OK
The Button component will now have a new state called Highlighted:
Once a state is defined and selected, setting a variable will associate that variable with a given state. In other words, any variable that is set when the "Highlighted" state is selected will associate the variable with the Highlighted state.
For this example, we will make the button become a lighter blue when highlighted. To do this:
Verify the Highlighted state is selected
Select the ColoredRectangleInstance
Set the Green and Red values to 100
Notice that the Green and Red values are rendered with a white background rather than green - indicating that they are values that are explicitly set in the Highlight state.
The values that have just been set apply only to the state that was selected - the Highlight state. This means that clicking on the Default state will switch the button back to the default colors. By clicking on the states in Gum you can preview and edit states easily.
Whenever a state in a category sets a variable, that variable is set across all states in that category. So far this tutorial only created a single state called Highlighted, but if additional states are set, all will explicitly set the Red and Green state. This topic is covered in more detail in the next tutorial.
Components are objects which are created in Gum which can contain instances of other components and of standard objects. Examples of components include:
Check boxes
Buttons
Popup Menus
To understand how components work, we'll create a simple Button component. To do this:
Right-click on the Components folder in Gum and select "Add Component"
Name the Component "Button"
Drag+drop a "ColoredRectangle" standard element into the Button component
Drag+drop a "Text" standard element into the Button component
Since both the ColoredRectangleInstance and TextInstance are using white text you may not be able to see the Text. Let's change the ColoredRectangleInstance's color:
Select the ColoredRectangleInstance
Change Red to 0
Change Green to 0
Set Blue to 255 - this should change the background from being green (default) to white (custom value). To do this, simply delete and re-type 255 in the Blue box, or click in the box and press enter.
Now you should be able to see the Text on top of the rectangle:
At this point we have what will eventually become a button, but it still needs some work. First, we're going to adjust the size of the objects contained in the button. At this point you can see that the colored rectangle (the blue background for the button) is not the same size as the button. Not only do we want to make the blue colored rectangle larger, but we also want it to automatically match the Button's size (the dotted outline).
To do this:
Select the ColoredRectangleInstance
Change Height Units to "Relative to Container"
Change the Width Units to "Relative to Container"
Change the Height to 0. This means that the Height of the ColoredRectangleInstance will match the Height of its container (the Button Component) since it's using "Relative to Container" Height Units.
Change the Width to 0. Just like with Height, this means that the Width of the ColoredRectangleInstance will match the Width of its container.
Now the ColoredRectangleInstance will automatically match the Button's Width and Height:
Next we'll position the Text. We'll want to adjust the Text so that it is always centered, and line-wraps with the size of the button. First let's center the Text:
Select the TextInstance
Change its HorizontalAlignment to Center
Change its VerticalAlignment to Center
At this point the Text is vertically and horizontally centered within its boundaries, but we want to have the boundaries centered within the Button. To do this:
Keep TextInstance selected
Change the X Units to "Pixels From Center"
Change the X Origin to "Center"
Change X to 0
Now let's make it centered on the Y as well:
Keep the TextInstance selected
Change the Y Units to "Pixels From Center"
Change the Y Origin to "Center"
Change Y to 0
Finally, let's make the width of the text match the width of the button. For the Text we'll actually leave a border around the edge so the Text doesn't line wrap right against the edge of the button. To do this:
Keep the TextInstance selected
Change the Width Units to "Relative to Container"
Change Width to -40. This means that the width of the Text will be 40 pixels less than the width of its container. Since the button is centered this means a 20 pixel border on the left and 20 on the right (20+20=40).
Buttons are typically wider than they are tall. To match this common layout, let's set the default values on the Button:
Select the Button component
Change Width to 120
Change Height to 36
Notice that whenever you change these values, the contained objects (text and colored rectangle) adjust automatically.
Now that we have a component created, we can add instances of this component the same way we have added standard elements. To do this:
Create a new Screen. I'll call mine MainMenu
Drag+drop the Button component into the Screen
You can now resize and position the Button instance. You can also add multiple buttons and adjust the individually.
See the section (Exposing Variables) to learn how to change the text independently for each button!
Circle - circle outline. These are usually not used for UI, but can be used if you are defining collision in your Gum objects for a game.
ColoredRectangle - filled-in rectangle. These are often used for solid-colored backgrounds and frames.
Container - invisible object used to contain other objects. These are used to provide margins, change layouts (such as vertical vs horizontal stacking), and to organize your UI.
NineSlice - visual object which uses nine sprites to create a resizable object from a source PNG (or portion of a PNG). The corner sprites (4) are not resized. The top, bottom, left, and right sprites are stretched on one axis. The middle sprite stretches both horizontally and vertically. These are used to create resizable frames.
Polygon - polygon outline which can have any number of points. These are usually not used for UI, but can be used if you are defining collision in your Gum objects for a game.
Rectangle - rectangle outline. These can be used for single-line frames or if you are defining collision in your Gum objects for a game.
Sprite - a visual object which displays a source PNG (or a portion of a PNG). These are used for icons, backgrounds, and other visual objects which are usually not resized dynamically.
Text - a visual object which can display charcters. These are used for any situation where text needs to be displayed such as labels and paragraphs.
Animation keyframes are defined by creating states in categories. If an animation uses two states in the same category then the animation will tween between the
Bottom-up stacks can be used to display stacks of elements which should move up as more are added. This concept is similar to messages received in a chat window. Gum layout can be used to produce this type of stack.
A bottom-up stack will be a container, which could be an instance of a container or a component since components ultimately are containers. For this example we'll use a container.
For this container to stack we'll set the following variables:
Children Layout set to Top to Bottom Stack so all children stack vertically
Height Units set to Relative to Children so the container resizes itself as more children are added
Height set to 0 so the height of the container is based purely on its children
Stack Spacing set to 2 (optional) to add spacing between each child
Now the container can have children added. Any type of child will stack. For this tutorial we'll use ColoredRectangle instances. Add a few instances to the Container and they stack vertically.
Finally we can have the stack grow up instead of down. To do this, change the following variables on the parent container:
Y Origin set to Bottom
Y Units set to Pixels from Bottom
Now as new children are added, the parent stack grows and all items shift up.
Although Gum naturally provides a NineSlice object, the Gum layout system can be used to create a custom NineSlice component. Such a component could be used if additional flexibility beyond what is provided by the standard NineSlice is needed.
As implied by the name, the NineSlice object is composed of nine Sprites. First we'll create the component:
Open Gum
Open or create a new Gum project
Right-click on the Components folder
Select Add Component
Name the Component CustomNineSlice
Next, we'll add corner Sprite instances to our CustomNineSlice. We'll be using the alignment tab to position Sprites. The alignment tab provides a quick way to place objects, but the same can be achieved using the following variables individually:
Drag+drop a Sprite element onto the CustomNineSlice component
Click the Alignment tab
Repeat the steps above three more times, creating one Sprite for each of the four corners
Notice that if we resize our CustomNineSlice component, each of the four sprites remains in the corner.
Next we'll add the four sprites which will sit on the edge of our component:
Drag+drop a Sprite element onto the CustomNineSlice component
Click on the alignment tab
Dock the newly-created Sprite to the top of its container. Docking sets the width of the sprite to match the width of the component. We'll address this in the next step.
To accommodate for the corner Sprites, we need to adjust the width of the top Sprite. Set the newly-created Sprite's Width to -128. Since the Sprite uses a Width Units of RelativeToContainer, Setting the value to -128 will make the sprite be 128 units smaller than the container. We picked 128 because each of the corner sprites is 64.
Repeat the above steps, but instead setting the dock to create sprites on the left, right, and bottom. adjust width and height values as necessary.
The last Sprite we'll add is the center Sprite:
Drag+drop a Sprite element onto the CustomNineSlice component
Click on the alignment tab
Dock the newly-created Sprite to the center of its container.
Set both the newly created Sprite's Width and Height to -128
Unlike the regular NineSlice, changing the texture values requires a considerable amount of variable modification. To change the CustomNineSlice to use 9 separate textures, the following values must be set:
Each of the Sprite instances must have its SourceFile value set
The edge Sprites will have to have their Width and Height values modified to account for the possible resizing of the corner sprites
The center Sprite will have to have both its Width and Height values modified
If using a sprite sheet, then all of the work above will need to be done plus the texture coordinate values will need to be modified.
This article shows how to create an animated component. It will contain an animation which can be used when the component first appears.
First we'll create a component which will be animated. To do this:
Right-click on Components
Select Add Component
Enter the name TextComponent and click OK
Drag+drop the Text Standard into the TextComponent to create a Text instance
Select the Alignment tab and click the middle button to have the TextInstance fill the TextComponent
Now that we have a component we'll add the states needed for animation. We'll add all states in a category called HideShow. Animation states should always be categorized. To create the states:
Right click in the States list box
Select Add Category
Enter the name HideShow
Right-click on the HideShow folder
Select Add State
Enter the name Hidden and click OK
Right-click on the HideShow folder
Select Add State
Select Shown
Now that we have the states defined we can set values for the states. In this case the only thing we'll be modifying is the TextInstance's Font Scale value. To do this:
Select TextInstance
Select the Hidden state
Set the Font Scale to 0. This makes the Text so small that it's invisible
Select the Shown state
Verify the Font Scale is 1, or set it to 1 if not. This makes the Text regular size
The two states we created above will be used as the keyframes for our animation. The animation will begin in the Hidden state then interpolate to the Shown state. To add this animation:
Verify that TextComponent or any objects under it are selected
Select State Animation ->View Animations
Click the Add Animation button
Name the animation Show and click OK
Select the Show animation and click Add State
Select the Hidden state and click OK - this is the first keyframe in our animation
Click Add State again
Select Shown and click OK
The animation can now be played or previewed:
The Interpolation Type value sets how one keyframe blends to another. By default keyframes use Linear interpolation, which is a constant change from one state to another. When interpolating from one keyframe to another, the first keframe defines the interpolation type. In our case the Hidden frame defines the interpolation type. We can change the Interpolation Type and preview the animation:
Select the Hidden keyframe
Change Interpolation Type to Elastic
Playing the animation will reflect these changes.
Behaviors can define requirements which can be reused across multiple components to standardize instance names and behaviors. If a component uses a behavior, then it is forced to include categories and instances according to the behavior definition.
Behaviors are used to define requirements for components, to simplify the creation of new components, and to reduce the chances of spelling and implementation mistakes.
Currently the Gum tool supports instance requirements on behaviors, but these requirements must be added by modifying the behavior XML file rather than adding instances through the tool. This will likely change in future versions of Gum
C# programmers may find the concept of behaviors to be similar to interfaces in code. Behaviors define requirements for components, but they give components the flexibility to implement these requirements, just like interfaces define required properties and methods which classes can implement.
To add a behavior:
Right-click on the Behaviors folder
Select Add Behavior
Enter the new behavior name. Often time the word Behavior is added at the end of the name, such as ButtonBehavior
New behaviors appear in the Project tab.
For example, the ButtonBehavior may have the following:
ButtonCategory (Category)
Enabled (State)
Disabled (State)
Focused (State)
Pushed (State)
A behavior can have as many categories and states as needed.
Once a behavior is added, it can be used in a component. To add a behavior to a component
Select a component which should use the behavior
Click the Behaviors tab
Click the Edit button
Check the desired behaviors - a component may use multiple behaviors
Click OK
Notice that once a behavior is added to a component, the component automatically creates the matching categories and states.
These categories cannot be removed as long as the component continues to use the behavior.
Gum Screens and Components support defining a base type. By setting a base type, a screen or component automatically inherits the following from the base type:
Variable values
Exposed variables
Instances
Available variables, such as stacking if inheriting from a container
Inheritance is useful if your project needs multiple screens or components which share common variables or instances.
All components use inheritance even if the Base Type variable is not set explicitly. By default components inherit from the Container type.
By inheriting from the Container type, components have access to all component variables such as Children Layout.
Components can inherit from standard types. For example, instead of inheriting from Container a component may inherit from ColoredRectangle. By doing so, it has access to all properties on the ColoredRectangle type.
Most components inherit from the Container type. If a component needs to display visuals, such as a ColoredRectangle, typically the ColoredRectangle is added as a child to the component rather than being used as a Base Type.
Components can inherit from other components. By doing so the component inherits all children and exposed variables.
A component which inherits from another component is often called a derived component. The component which is being inherited from is often called a base component.
A base component can be used to define instances which the derived component can modify. For example a component named ButtonBase may define that all components have a ColoredRectangle named Background and a Text named TextInstance.
If another component uses ButtonBase as its Base Type, then this component automatically gets Background and TextInstance children which match the base instances.
The CancelButton can modify variables on the added children. For example the CancelButton can modify the Text on the TextInstance and the color values on the Background.
The derived component has the following restrictions when working with children
Name cannot be changed. For example Background must always be named Background.
Base Type cannot be changed. For example, the base type for Background must be ColoredRectangle
Children defined in the base cannot be removed. For example, the Background child cannot be deleted from CancelButton
If the base type adds new instances, then the derived types automatically get the same instances added as well. Similarly, if the base type deletes a child, then the child is also removed from the derived type.
Derived types get access to all of the exposed variables in the base type. For example, if ButtonBase exposes the TextInstance's Text property, this is also available on the derived component.
Base types allow for the customization of a component, including the creation of many variants. Similarly, States also allow for the customization of a component in similar ways. When deciding between whether to use states or inheritance, keep the following in mind:
States are often used to set variables temporarily, while inheritance is permanent. For example, a button may set its background color values in response to being highlighted. By contrast, a Cancel button may always say "Cancel".
States do not allow for the creation of new instances. Although derived components cannot delete children which are defined by their Base Type, derived components can add additional instances.
Components can use multiple categories. Therefore, it may not be clear which category defines the type of component. A component can only have one Base Type, so its type is defined clearly.
Gum supports creating animations which can play other animations. This is especially useful when creating animations in Screens that contain components which themselves have animations. This tutorial will build upon the where we created an animated component called TextComponent.
First we'll create a Screen called AnimatedScreen. To do this:
Right-click on Screens
Select "Add Screen"
Enter the name "AnimatedScreen" and click the OK button
Drag+drop a few TextComponents into the Screen and spread them out visually
The animation we will be creating in our Screen will start with all TextComponents being invisible, then each one appearing by playing their Show animation. The animations will be slightly staggered. First we'll add the initial state where all of the TextComponents are invisible. To do this:
Verify that the AnimatedScreen is selected
Right-click in the states area and select "Add State"
Name the state "AllInvisible" and click OK
Select one of the TextComponents
Set its State to Hidden
Repeat setting the State to Hidden for the other TextComponents
Now we have all of the states and animations that we'll use as keyframes in our animation. To create the animation:
Select AnimatedScreen
Select "State Animation" -> "View Animations"
Click "Add Animation"
Name the animation "ShowAll"
Select the ShowAll animation
Click "Add State"
Select "AllInvisible" and click OK
The animation now sets all TextComponents to their Hidden state initially.
Next we'll be adding animations to animate the TextComponent instances to visible. To do this:
Bring up the animation window for AnimatedScren if it is not already showing
Select "ShowAll"
Click "Add Sub-animation"
Select the first TextComponentInstance
Select the Show animation and click OK
Select the newly-created animation and set its Time to 0.5
Repeat the above steps to add animations for the other two TextComponents, but set their times to 1.0 and 1.5
Now the animation can be played or previewed with the slider bar:
Introduction
Health bars are common UI elements in games. A similar element to health bars are progress bars. Even though the two are used in different situations, the layout for these two is the same.
First we'll define the component:
Open Gum
Open or create a new Gum project
Right-click on the Components folder
Name the component HealthBar
Resize the HealthBar component so it is wider than it is tall. For example, assign a Width of 200 and Height 32.
Next we'll add a background to our HealthBar Component
Drag+drop a ColoredRectangle into the HealthBar
Select the newly-created ColoredRectangleInstance
Select the Alignment tab
Click the Fill Dock button
Change the ColoredRectangleInstance color to black
Now we have a black background to our HealthBar
The HealthBar displays its current health with another rectangle. This second rectangle will be contained inside a container, which will provide a boundary. To add an inner container:
Drag+drop a Container onto the HealthBar
Select the Alignment tab
Click the Fill Dock button
Change Width and Height to -8 to provide a 4 pixel margin on each side.
Finally we'll add the foreground rectangle which displays the health:
Drag+drop another ColoredRectangle onto the ContainerInstance
Click the Alignment tab
Click the Fill Dock button
Change the following values:
X Units to Pixels from Left
X Origin to Left
Width to Percentage of Container
Width to 100
Now, the Width value can change between 0 and 100 to indicate the health percentage.
Exposing the Width of the inner rectangle may be needed to change instances of each HealthBar.
Anchor the newly-created Sprite to the top-left of its container
Now the Sprites will stretch and adjust whenever the CustomNineSlice is resized.
Once a behavior has been created, it can be given categories and states. Any component which uses this behavior is required to have the same categories and states. States can be added and removed the same as when working with states in other elements. For more information, see the page.
The Clips Children property controls whether children of a component or container can render outside of the bounds of their parent. By default this is false, which means that all children can fully-render, regardless of whether they are within the bounds of their parent or not. Setting this value to true will prevent children from rendering outside of the bounds of their parent.
Introduction
The Wrap value controls whether the sprite will wrap its image when rendering portions beyond the image location. If this value is true then wrapping will occur. Otherwise, areas beyond the texture will extend the last pixel - also known as "clamping" the value.
The Wrap variable applies when dealing with a Texture Address of Custom or DimensionsBased.
Components are reusable collections of instances. Components can be added in the project's Components folder. Examples of Components include:
Button
HealthBar
Slider
Menu
Components can be small and reusable, such as a Label, or they can be large complex objects such as a settings menu with dozens of options.
Component instances can be added to other Components or to Screens.
The Inheritance Location options allow you to control where inheritance is specified in generated code (custom or generated code).
When an element is selected, its generated code is displayed in the Gum tool. If automatic or manual saving of generated code is enabled, then this generated code is saved to disk at the desired location. When generated code is saved, it is saved with the Runtime.Generated.cs
suffix. An accompanying custom code file is also saved in the same folder. This custom code is generated initially, but after that it is not re-generated by Gum. This pair of files allows Gum to continue to update the .Generated.cs file without overwriting custom code.
The Inheritance Location option controls whether inheritance is added to custom or generated code. In most cases it's desirable to keep inheritance in generated code; however, some environments (such as .NET Maui) may benefit from writing inheritance in custom code.
This option controls whether generated code is displayed in the Code tab. If checked, generated code is displayed and is updated whenever a change is made in Gum.
Usually this option can remain checked even if you are not using generated code; however, very large components and screens may generate a large amount of code, which can slightly affect Gum's performance when selecting objects or making changes. If you are experiencing slowdowns and you do not need code to be generated, you can uncheck this option.
When a parent uses RelativeToChildren for its for its Width Units or Height Units, it must only consider children which are not positioned relative to the parents' Width or Height, respectively.
For the sake of brevity, this document will discuss Width, Width Units, X, and X Units values. All concepts also apply to Height, Height Units, Y, and Y Units.
Conceptually, parent Width Units and children X Units can create recursive relationships. For example, consider the following situation:
Parent.WidthUnits = RelativeToChildren
Child.XUnits = Percentage
Child.Width = 100
Child.X = 50
In this case the Parent width depends on the Child X and Width values. But the Child X depends on the Parent Width. This creates a recursive relationship which cannot be resolved (or which can be resolved with unexpected results).
Therefore, when determining the Width of a parent using RelativeToChildren WidthUnits, all children which have position or size values relative to their parent are ignored.
Specifically, the following values are considered absolute, and any values besides these will result in a child being ignored when calculating a relative parent Width:
WidthUnits = Absolute, PercentageOfSourceFile, RelativeToChildren
XUnits = PixelsFromLeft, PixelsFromMiddle, PixelsFromRight
Only the following values are considered absolute, and any values besides these will result in a child being ignored when calculating a relative parent Height:
HeightUnits = Absolute, PercentageOfSourceFile, RelativeToChildren
YUnits = PixelsFromTop, PixelsFromMiddle, PixelsFromBottom
Width and Height are calculated independently. This means that a child may be ignored when calculating RelativeToChildren Width, but may be considered when calculating RelativeToChildren Height.
To help explain the way units work, this section two ColoredRectangles. Other types such as Container could be used, but colored rectangle is easier to see in pictures and animations so we'll use this type. Also, like the section above this section uses X and Width values, but the same concepts apply to Y and Height values.
Initially the Parent has a Width of 0 and a Width Units of Relative to Children.
This results in the Parent's width being controlled by the right side of the Child (the red ColoredRectangle). In other words, if the Child is moved or if its Width changes, the Parent's Width also changes.
In this case, the Parent's Width depends on its Child - specifically the right side. The Child's right side is absolute - it does not depend on the parent, so this relationship is not circular. However, if we were to adjust the Child so that its X Units depended on the parent's width, such as by changing X Units to Pixels from Right, the child would now depend on the Parent's width, creating a circular relationship. We can see that once this circular relationship is established, the parent's actual width changes to 0.
To reiterate, after this change, the child's right side depends on the parent's right side, and the parent's right side depends on the child's right side. This circular dependency is resolved by Gum with the parent ignoring the child - in this case the Parent behaves as if the child does not exist when it determines its actual width. This results in the Parent's width depending on no children, so it is set to 0 (the value set on the Parent's width).
These types of circular dependencies can cause confusion but they are okay to use in actual projects. Typically these types of situations exist when a Parent has a mix of children - some of which use absolute positioning, some of which depend on their parent.
For example, we can add a second child - a yellow ColoredRectangle maned Child2. If Child2's right side is absolute, then the Parent will use it to determine its size. Notice that when this happens, the red Child ColoredRectangle adjusts appropriately.
The properties are applied in the following order:
Child2's right side is determined using its absolute X and Width values
Parent's Width value is set according to Child2's right side. Parent ignores Child (the red box) because Child's right side depends on Parent's right side.
Child sets its X according to Parent's right side
A practical example of how this type of relationship might be used is a situation where Parent contains objects that should control its size, but also has elements which react to the size such as a top bar.
The Rotation property can be used to rotate Gum components. It is measured in degrees, where positive values rotate an object counterclockwise about its origin (X Origin and Y Origin).
An object is rotated by its origin, which by default is its top-left corner:
Objects can also be rotated visually by grabbing the rotation handle:
The X Origin and Y Origin properties define the point of rotation for an object. For example, the following shows a rectangle rotated about its center:
Variable References allows any variable on an instance to reference a variable on another instance. The most common use of Variable References is to create a centralized style component which can be referenced throughout a Gum project.
Variables which are assigned through Variable References cannot be directly set on the instance - the value obtained through the reference overwrites any custom value.
The following example creates a Styles component which contains a color value which is referenced by objects in a MainMenu Screen.
Any component can serve as a centralized location for styling, but we use the name Styles by convention.
The Styles component can contain as many objects as are needed to style your project. Additional objects can be added to help indicate how things are used visually. For example, we include a Text object to indicate the red color is the Primary Color.
The color value can be referenced by any other object including objects in different screens or components.
To add a variable reference:
Select the object which should have a variable reference
Click inside the Variable References text box
Type the variable reference. The format of the variable reference is
{VariableName} = {Components or Screens}/{ComponentOrScreenName}.{InstanceName}.{InstanceVariable}
For example, to reference the Red variable in the Styles component, the syntax is
Red = Components/Styles.PrimaryColor.Red
Since color values have three components (Red, Green, and Blue), then all three components must be referenced. In this example, the background can reference the three colors with the following assignment text:
The types of the objects that contain the Variable References or which are being referenced do not matter. For example, a Text object could have its color values depend on the color values defined by a ColoredRectangle in the Styles component.
Once Variable References are set, the referenced instances (instances in Styles) can be changed and the changes will immediately propagate throughout the entire project.
As shown above, Variable References can be used to assign one variable to another. If a variable is referenced, then the variable cannot be manually assigned. The Variable Reference takes priority. For example, if an object references the Red, Green, and Blue variables, then those values cannot be manually set on the object. The values appear disabled and text indicates why they are read-only.
When entering a variable reference, Gum understands implied variable references by filling in the left-side of the equals sign to match the variable name on the right-side. For example, the following can be entered in the Variable References text box:
Gum automatically adds Red =
before the entry, as this is the most likely variable assignment. This addition happens when the text box loses focus, such as when Tab is pressed or when a different text box gains focus.
Assigning color values is a common part of styling, so to help with this situation, Gum also expands the "Color" variable into all three components when the Variable References text box loses focus. For example, the following text can be used to assign all three values at once:
When the Variable References box loses focus, this is expanded to the following assignments:
The examples given above are useful for a centralized styling scenario. Variable references do not require referencing variables from other Screens or Components. If a reference is between two instances in the same Screen or Component, then the variable reference does not need to include the name of the component.
For example, we can assign the X value of one ColoredRectangle (RedRectangle) to the X value of another ColoredRectangle (BlueRectangle) using the following assignment:
This assignment forces the RedRectangle's X value to match the BlueRectangle's X value.
Changing the BlueRectangle's X value automatically updates the RedRectangle's X, even though the two rectangles have no other relationship to each other (such as a parent-child relationship).
Typing a variable name can be tedious, especially when referencing a variable in a different Screen or Component. Qualified variable names can be obtained by right-clicking on the variable name in Gum and selecting the Copy Qualified Variable Name option. This can then be pasted in the Variable References box of any other object.
Usually a variable references the same-named variable from the source, such as Red being assigned to Red. This is not a requirement, and variables can reference other variable values. For example, the Green value could reference the Red value on a source.
Although this is not common, referencing different variables can help create complex UI elements.
The Height Units variable controls how a unit is vertically sized, which may be relative to its parent. By default an object uses Absolute height, where each unit represents 1 pixel of height in pixels. When using Absolute, an object ignores its parents' Width.
The following shows a child ColoredRectangle with 50 Absolute Height:
The following shows a child ColoredRectangle with -10 Relative to Container Height, which means is sized 10 pixels less tall than its parent.
Despite the name referring to a "Container", the size is relative to the parent regardless of the parent's type. If the instance has no parent, then the size is relative to the canvas.
The following shows a child ColoredRectangle with 100 Percentage Height, which means it has 100% of the height of its parent. Note that 100 Percentage is the same as 0 Relative to Container:
Despite the name referring to a "Container", the size is relative to the parent regardless of the parent's type. If the instance has no parent, then the size is relative to the canvas.
Ratio of Container can be used to fill available space or to share available space with other objects using a ratio.
Despite the name referring to a "Container", the total size available for ratios is relative to the parent regardless of the parent's type. If the instance has no parent, then the size is relative to the canvas.
The simplest case is a single child in a container with its Height Units set to Ratio of Container.
In this case the blue ColoredRectangle has no siblings (its container has no other children), so it occupies the entire parent height. If a second child is added (by copy/pasting the existing child), then each child is given 1 ratio value, which means each is 1/2 of the size of the entire parent.
To better visualize the effect of ratio, it's common to set the parent's Children Layout to Top to Bottom Stack, and to give each child a different color as shown in the following image.
As more children are added, each child's height is adjusted to make room for the new children.
Ratio values are distributed among all siblings using Ratio of Container proportionally. The image above shows four siblings, each given 1/4 of the ratio. If one of the the ratios changes (such as by increasing the second sibling's Height value to 3), then all siblings adjust in response to this change.
In this case, the total ratio is 6 (1 + 3 + 1 + 1), so the red is given 3/6 (1/2) of the container's height, while each of the others is given 1/6 of the container's height.
Values of 0 are supported, resulting in the object drawing with an absolute height of 0.
Ratio of Container is calculated after accounting for the height of children which are using absolute height. For example, if the height of the first child is 80 with a Height Units of Absolute, then the other three shrink to give the first the necessary room.
This effect can also be seen by adjusting the height using the handles.
Gum ignores invisible objects when calculating available space for Ratio Width units. Therefore, if a sibling is invisible, Gum treats it as if it has 0 height which allows all other Ratio siblings to expand.
Ratio of Container also respects Stack Spacing. A Stack Spacing value greater than 0 removes the available space for all children with a Height Units of Relative to Container.
The following image shows a child ColoredRectangle with 50 RelativeToChildren Height, which means that it is 50 pixels taller than is necessary to contain its children. Since the rectangle has no children, this is the same as having 50 Absolute Height:
RelativeToChildren can be used to size an object based on the position and sizes of a container's children. The following image shows a container with 0 RelativeToChildren Height, which mans that its height is set just large enough to contain its children. Notice that if the children are moved, the rectangle's height adjusts. Both children are considered so the container adjusts its height according to the bottom-most side of either child:
A non-zero Height when using RelativeToChildren can be used to add additional padding to a parent container. The following shows how changing the height can adjust the absolute height relative to children:
If a parent sets its Height Units to Relative to Children, then it must resize itself to contain its children. Normally, the height of the entire parent is determined by the child which needs the most space vertically. If the parent uses an Auto Grid Vertical layout, then the children control the size of the cells rather than the entire parent. Since all cells must be the same size, the child which needs the most amount of space vertically determines the height of all cells.
For example, the following image shows a four by four grid, each containing one white rectangle. The first rectangle has an absolute width and height of 100, so each cell is sized to be 100x100. Note that the other rectangles are 50x50.
The largest child determines the cell size for all other children. Therefore, if a child is moved or resized so it outgrows its cell, then the parent height adjusts in response.
The term "children" can refer to:
Instances added to a parent, such as ColoredRectangles added to a Container
Individual letters in a Text instance - each letter and line of text can expand the height of its parent
The following animation shows a Text instance which has its Height Units set to RelativeToChildren. As more lines of text are added, the Text automatically expands in size.
Percentage of Other Dimension adjusts the object's effective height so it remains proportional to the Width value multiplied by the Height value (as a percentage). For example, if a Height value of 200 is entered, then the effective height is 200% (2x) of the width.
The following image shows a child ColoredRectangle with a Height of 200 Percentage of Other Dimension. In this image, the Width value is 50 units, so the effective height is 100 units:
The Sprite type has an extra Height Unit called Percentage of Source File, which sets the height of the Sprite according to the file that it is displaying. This is the default Height Unit for Sprites.
The following image shows a child Sprite with 200 Percentage of Source File Height, which means it draws two times as tall as its source image:
Parenting allows UI elements to be positioned and sized according to other UI elements. Parenting hierarchies can go many levels deep and the parent/child relationship can be visualized by the white line connecting the parent to the child when the child is selected.
To change the parent/child relationship in the tree view:
Select a child
Drag+drop the child onto the desired parent
The child can be detached from its parent by drag+dropping it onto the Component.
Drag+dropping onto a parent may set the Parent property to an instance inside of the parent's Component type sets its Default Child Container value. For more information see the Default Child Container page.
To set a parent/child relationship:
Select the child
Change the Parent property to the desired parent:
The Width Units variable controls how a unit is horizontally sized, which may be relative to its parent. By default an object uses Absolute width, where each unit represents 1 pixel of width in absolute terms. When using Absolute, an object ignores its parents' Width.
The following shows a child ColoredRectangle with 50 Absolute Width:
The following image shows a child ColoredRectangle with -10 RelativeToContainer Width, so it sizes itself 10 pixels less wide than its parent.
Despite the name referring to a "Container", the size is relative to the parent regardless of the parent's type. If the instance has no parent, then the size is relative to the canvas.
The following shows a child ColoredRectangle with 100 Percentage of Container Width, which means it has 100% of the width of its parent. Note that 100 Percentage is the same as 0 Relative to Container:
Despite the name referring to a "Container", the size is relative to the parent regardless of the parent's type. If the instance has no parent, then the size is relative to the canvas.
Ratio of Container can be used to fill available space or to share available space with other objects using a ratio. It behaves similar to a Height Units of Ratio of Container, but operates horizontally rather than vertically.
Despite the name referring to a "Container", the total size available for ratios is relative to the parent regardless of the parent's type. If the instance has no parent, then the size is relative to the canvas.
The following image shows a child ColoredRectangle with 50 Relative to Children Width, which means that it is sized 50 pixels wider than is necessary to contain its children. Since the rectangle has no children, this is the same as having 50 Absolute Width:
Relative to Children can be used to size an object based on the position and sizes of a container's children. The following image shows a container with 0 Relative to Children Width, which means that its width is set just large enough to contain its children.
A non-zero Width when using Relative to Children can be used to add additional padding to a parent container. The following image shows a container with 20 pixels of padding width:
Relative to Children dynamically adjusts to changes in properties on the children. In the following animation the container has a Children Layout of Left to Right Stack. Adding additional children expands the container automatically:
If a parent sets its Width Units to Relative to Children, then it must resize itself to contain its children. Normally the width of the entire parent is determined by the child which needs the most space horizontally. If the parent uses an Auto Grid Horizontal layout, then the children control the size of the cells rather than the entire parent. Since all cells must be the same size, the child which needs the most amount of space horizontally determines the width of all cells.
For example, the following image shows a four by four grid, each containing one white rectangle. The first rectangle has an absolute width and height of 100, so each cell is sized to be 100x100. Note that the other rectangles are 50x50.
The largest child determines the cell size for all other children. Therefore, if a child is moved or resized so it outgrows its cell, then the parent width adjusts in response.
Setting a Text instance's Width Units to Relative to Children results in the Text object adjusting according to its text contents. For example, setting the Width Units to Relative to Children and setting the Width to 0 results in the Text object automatically adjusting its actual width according to the text it contains.
Percentage of Other Dimension adjusts the object's effective width so it remains proportional to the Height value multiplied by the Width value (as a percentage). For example, if a Width value of 200 is entered, then the effective width is 200% (2x) of the height.
The following image shows a child ColoredRectangle with a Width of 200 Percentage of Other Dimension. In this image, the Height value is 50 units, so the effective width is 100 units:
The Sprite type has an extra With Unit called Percentage of Source File, which sets the width of the Sprite according to the file that it is displaying. This is the default Width Unit for Sprites.
The following image shows a child Sprite with 200 Percentage of Source File Width, which means it draws two times as wide as its source image:
Absolute Multiplied by Font Scale is a property which multiplies the Font Scale property at runtime with the width value. This can be used to create widths which are responsive to font scales for devices which may have variable text sizes.
At the time of this writing, the Gum tool always uses a Font Scale of 1, so this cannot be previewed in the tool. However, when a Gum project is loaded at runtime, the runtime may apply a Font Scale value such as using the Text size from Windows.
The X Origin variable controls the point which an object is positioned by. By default the X Origin is Left. The X Origin is shown visually as a white "X" in the editor.
The following image shows a ColoredRectangle with its X Origin set to Left:
The following image shows a ColoredRectangle with its X Origin set to Center:
The following image shows a ColoredRectangle with its X Origin set to Right:
The X Units variable controls how a unit is horizontally positioned relative to its parent. By default an object is positioned relative to the left of its parent, where each unit represents 1 pixel.
The following shows a child ColoredRectangle positioned 50 PixelsFromLeft relative to its parent:
The following shows a child ColoredRectangle positioned 50 PixelsFromCenterX relative to its parent:
The following shows a child ColoredRectangle positioned 50 PixelsFromRight relative to its Parent:
The following shows a child ColoredRectangle positioned 50 PercentageWidth relative to its Parent. In other words, it will be positioned halfway between the left and right edges of the Parent:
The Y Units variable controls how a unit is vertically positioned relative to its parent. By default an object is positioned relative to the top of its parent, where each unit represents 1 pixel downward.
The followingshows a child ColoredRectangle positioned 50 PixelsFromTop relative to its parent:
The followingshows a child ColoredRectangle positioned 50 PixelsFromCenterY relative to its parent:
The followingshows a child ColoredRectangle positioned 50 PixelsFromCenterYInverted relative to its parent. Note that coordinates are "inverted", which means that increasing the Y value moves the object up rather than down. This value exists to simplify integration with engines which may use positive Y as up:
The followingshows a child ColoredRectangle positioned 50 PixelsFromBottom relative to its parent:
The followingshows a child ColoredRectangle positioned 50 PercentageHeight relative to its parent:
Default Child Container specifies which instance should contain children which are added to instances of the current component.
By default this value is blank, which means that children will treat the entire component as their parent. If this value is set, children which are dropped on instances of this component type will use the instance as their parent.
Default Child Container is typically set on containers which are designed to hold children, but which have margins or decoration around the dedicated container instance. Examples include list boxes, tree views, and frames.
Consider a Component named Frame which has two instances: OuterRectangle and InnerRectangle.
This Component is designed to keep all of is children inside the InnerRectangle, so that any child automatically respects the margin specified by InnerRectangle.
To make this kind of relationship the default, the Frame can set its Default Child Container property to InnerRectangle.
Once this value is set, instances which are drag+dropped onto Frame instances will use the InnerRectangle as their parent, as shown in the following animation.
When one instance is drag+dropped onto another instance, the Parent property is set according to the parent's Default Child Container.
Using the example above, the RectangleInstance is dropped on the ContainerTestInstance. Since the ContainerTestInstance is of type Frame, then the Default Child Container is applied on the drop, which results in the RectangleInstance's Parent being set to ContainerTestInstance.InnerRectangle.
ColoredRectangles are used to display solid color rectangles. It can be used to provide a solid colored background or placeholders for content such as Sprites. ColoredRectangles are also useful for quickly blocking out a UI or learning about Gum's layout with a visual object.
As the name suggests, ColoredRectangles have a Color property which can be modified.
The Children Layout property determines how a container positions its children. The default value is "Regular" which means that children are positioned according to their and .
Top to Bottom Stack results in the children stacking one on top of another, from top to bottom.
Left to Right Stack results in the children stacking one beside another, from left to right.
Auto Grid Horizontal results in the children being placed in a grid, filling in horizontally first before wrapping to the next row.
Auto Grid Vertical results in the children being placed in a grid, filling in vertically first before wrapping to a new column.
The following shows how to use the ChildrenLayout property to change the default position of a Container's children. The following animation shows the different Children Layouts being set:
Regular layout positions each child independent of every other child. The position of one child does not affect the position other children. This is the default layout for containers.
Top to Bottom Stack results in each child being positioned after its previous sibling vertically. This can be used to create horizontal stacks.
Left to Right Stack results in each child being positioned after its previous sibling horizontally. This can be used to create vertical stacks.
When children stack, each child's X or Y depends on the boundary of its previous sibling. When stacking vertically, the child's Y value begins at the bottom side of the previous item. Similarly, when stacking horizontally, the child's X value begins at the right side of the previous item.
For example, the following image shows a Text object with a Y value of 20. Notice that it is positioned 20 units below the item above it.
This effect is easy to notice when dragging an object inside a stack, as shown in the following animation:
If instances are stacked in a container, the stacking controls the instance values based on the direction of the stack. Containers with a Top to Bottom Stack control the Y value of their children. Similarly, Containers with a Left to Right Stack control the X value of their children. The position value which is not controlled by the stack can be changed freely without any impact on the stacking.
For example, if a container stacks its children using a Top to Bottom Stack, the children in the stack are free to change their X values. The following animation shows how children can be left, center, or right anchored (which changes their X Units and X Origin) without affecting the other children in the stack.
An object will stack only if its position unit values are top or left for vertical or horizontal stacks. For example, if a child is part of a Top to Bottom Stack, it will only stack if its Y Units is set to Pixels from Top. Otherwise it ignores its parents stacking behavior.
In general this behavior can cause unexpected behavior, especially if additional siblings follow the child which is not using the default Pixels from Top or Pixels from Left, so changing this value on the primary stacking direction is not recommended.
For example, consider a parent which contains two children - a blue and a red rectangle.
This overlapping may not be desirable, so keep this in mind when changing a stacked child's origin.
Children of a container which uses the TopToBottomStack or LeftToWriteStack will be ordered according to their order in the tree view on the left. By default this is the order in which the children are added to a parent container.
Children can be reordered using the right-click menu on an instance.
Alternatively, children order can be changed by clicking on the item in the tree view, holding down the ALT key, then pressing the up or down arrows.
Auto Grid Horizontal and Auto Grid Vertical layouts result in each child of the container being placed in its own cell. All position and size values are relative to the entire cell, so children can expand to fill their cell or be positioned according to any side or corner.
The following shows a container with an Auto Grid Horizontal and Vertical Cells of 2, resulting in a 2x2 grid. As children are added to the container through copy/paste, each child is placed in its own cell.
The number of cells is controlled by the Auto Grid Horizontal Cells and Auto Grid Vertical Cells. Increasing the number of cells results in the rows or columns adjusting automatically.
Each child occupies one cell, and the order of the children controls the order of the placement in grids. The first child occupies the top-left row. If using Auto Grid Horizontal, each child is placed to the right of its preceding sibling, wrapping to the next line when reaching the end of a row. If using Auto Grid Vertical, each child is placed below its preceding sibling, wrapping to the next column when reaching the end of a column.
Children can be reordered by using the alt+arrow key in the tree view, resulting in reordering just like when using a stacking Children Layout.
Children treat their particular cell in the grid as their parent, so any sizes or positions will be based on their parent cell. In other words, if a child's WidthUnits is set to RelativeToContainer, the container in this case is the cell, not the entire Container instance.
If additional children are added beyond the number of cells in a grid, additional children will spill over the bounds of the grid. The following animation shows a 3x3 grid using Auto Grid Horizontal. As more children are added, additional rows are added below the bounds of the grid.
When using Auto Grid Horizontal, the number of columns is fixed, but additional rows can be added beyond the bounds of the container.
When using Auto Grid Vertical, the number of rows is fixed, but additional columns can be added beyond the bounds of the container.
NineSlice is a standard component which can be used to create visual objects which can stretch to any size without creating distortion on the source image. For example, consider the following image:
This image could be used to create nine slices of various sizes without any distortion:
The NineSlice achieves this effect by splitting the texture into nine pieces, and scales each one differently to prevent distortion. Highlighting a nine slice shows how it is split:
This is achieved by splitting the texture into 1/3 sections wide and tall. The following image shows how the original image will be split:
The simplest way to assign a texture to a NineSlice is to use a single file. Setting the SourceFile to a single PNG will result in the NineSlice using that one texture, where each section of the NineSlice displays 1/3 of the width of the file and 1/3 of the height of the file.
A NineSlice's Texture Address property can be used to change the portion of the source texture that it uses. More info can be found in the Texture Address subpage.
Alternatively, nine files can be used to specify each section of the NineSlice independently. To use nine individual files, each file must be given a specific suffix.
The following suffixes can be added to create nine slice graphics. For example, assuming your NineSlice image is called "Image" and you are using the .png file format:
Image_BottomCenter.png
Image_BottomLeft.png
Image_BottomRight.png
Image_Center.png
Image_Left.png
Image_Right.png
Image_TopCenter.png
Image_TopLeft.png
Image_TopRight.png
NineSlice Properties
The Stack Spacing variable controls the additional padding between children when a container uses a Children Layout of either Top to Bottom Stack or Left to Right Stack. Stack Spacing serves as an alternative to adjusting the position of each item in a stack.
A larger Stack Spacing value increases the spacing between each child. By default Stack Spacing is set to 0 which means that no spacing is added between items in a stack.
Changing the stack spacing adds gaps between each child as shown in the following animation.
Stack Spacing can also be a negative value resulting in overlapping children. The items in the following animation are partially transparent to show the overlap.
Stack Spacing can be used for either Top to Bottom or Left to Right Stacking.
Stack Spacing can be used on container instances which stack and wrap their children. As stack spacing increases, the amount of space allocated to each object also increases, resulting in wrapping occurring earlier.
If wrapping occurs, then stack spacing applies spacing between rows and columns as shown the following animation:
The Custom Frame Texture Coordinate Width property allows a NineSlice to customize the number of pixels used on the source texture when defining its outer frame. This allows for fine control over which parts of a NineSlice stretch and which parts are used as the corners and edges.
By default this value is null, which means the NineSlice automatically dedicates 1/3 of the texture for the edges.
If the Custom Frame Texture Coordinate Width value is changed, then the source texture applies a fixed pixel size to the borders. For example, using the image above, the frame can be changed to 3 so that only the black and white pixels are part of the border.
The Source File property determines the file that is used by the Sprite. Sprite Source Files support the following formats:
.png files
.achx files (AnimationChains)
Images from URLs
If a Sprite has an empty Source File or if it references a missing file, then the missing file texture is displayed.
Source File can be set by typing a value or using the ... button to browser for a file.
All files are added as paths relative to the .gumx project.
If a file is referenced outside of the .gumx folder, then Gum asks if you would like to copy the file or reference it outside of the current directory. Usually files should be copied to the project folder to keep the entire Gum proejct portable.
Once you have created an .achx file, you can reference it the same as a .png by entering its name or selecting it with the ... button.
When referencing an .achx file, be sure to also check the Animate checkbox and to select the Current Chain Name.
.achx files are XML files which reference one or more other PNG files. If you are moving an .achx file be sure to also move the referenced PNG files.
Gum Sprites can also reference URLs. Gum can display images from URLs with standard file extensions such as .png and .jpg
The Color value is used to perform a multiply color operation on the sprite. Color values can be used to darken or tint a grayscale texture. By default Sprites us a white color, which means the original texture will display unmodified.
The following images show the color values as applied to a multi-color sprite.
Red: 255 Green: 255 Blue: 255
Red: 255 Green: 0 Blue: 0
Red: 0 Green: 255 Blue: 0
Red: 0 Green: 0 Blue: 255
Red: 128 Green: 128 Blue: 128
Red: 0 Green: 0 Blue: 0
The texture address property controls the texture address behavior of a sprite. Specifically it can control whether texture addresses variables are available, and how texture coordinates and sprite size relate.
If the texture address property is set to EntireTexture then the sprite will draw its full image. The sprite will not repeat this texture or render only part of the texture.
If the texture address property is set to Custom then the top, bottom, left, and right properties can be independently set. This allows a sprite to only render a portion of its source texture.
Typically a Texture Address of Custom is used in combination with a Width Units of Percent of File Width and and a Height Units of Percent of File Height. In this case, the size of the sprite depends on the texture coordinates.
If the Texture Address property is set to DimensionsBased then the texture coordinates will adjust internally according to the width and the height of the Sprite. In other words, making the sprite larger or smaller will not stretch the image that it is rendering. Instead the image will be clipped, or clamped/wrapped according to the Wrap property.
Combining the DimensionsBased texture address with the wrap property will let you easily create tiling sprites.
The Blue value controls the color of the Text object. The Blue value has a range of 0 - 255. The Blue value combines with the Red and Green values to create the final color.
For more information on working with color, see the .
Categories can be used to organize similar states into one group (such as a button's Pressed and Unpressed states).
For a tutorial on working with categories, see the
A category can contain one or more states. States within a category have special behavior:
If one state in a category explicitly sets a variable (such as X), then all other states in that category will also explicitly set the variable.
Each category can be set individually on an instance of a component or standard element. In other words, if a component has two categories, each category can be assigned to a state within that category independently.
Normally, when a new state is created, all variables are explicitly unset. The value displayed in the properties window will be the value inherited from the default state.
For example, the following image shows a component with a state called State1 with no variables explicitly assigned. Notice all values are green:
We can see the same behavior on a categorized state. The following image shows the categorized LeftSide state with all inherited values:
As mentioned in the introduction, if a varible is explicitly set on one state in a category, then all other states in that category will that same variable set to its default.
For example, if we set the X variable in the LeftSide state, the X variable in the RightSide state will become explicitly set (black instead of green).
Once the X variable is set on one state in a category, all other states in the same category will automatically have this value set - even new states:
Variables can be removed from states, but this removal must be done at the category level rather than at the individual state. Doing so will remove all variables from all states within a category. To remove a variable in all states in a category:
Select the category itself (not the state)
Click the "X" button next to the variable
Confirm that you would like to remove the variable. Warning: this will remove the variable from all contained states.
This will remove the assignment of the variable from all states in the category.
The Color value controls a Text object's color. The Color value is created by combining the Red, Green, and Blue values.
The Color value can be changed through the color picker, or by changing the individual Red, Green, and Blue color values.
For default Text objects, the Color value modifies the displayed Text color. Gum creates .fnt and .png files where the color is white. If the .png includes any colors that are not white, then the resulting color is produced by multiplying the color value with each pixel. Therefore, if a Font is outlined, then the black pixels remain black.
The Y Origin variable controls the point which an object is positioned by. By default the Y Origin is Top. The Y Origin is shown visually as a white "X" in the editor.
The following image shows a with its Y Origin set to Top:
The following shows a Text with its Y Origin set to Baseline:
Baseline is often used to align fonts of different sizes. The following image shows two Text instances with different font sizes. Both are positioned by their baseline so their bottoms align properly (ignoring descenders, such as on the letter p and the comma).
By contrast, the following image shows the same Text instances using bottom alignment.
Gum Application (binaries):
Gum Source Code:
Currently the Gum tool requires XNA runtimes. Download and install the runtime prior to running Gum:
Since Gum is a prebuilt file in a .zip, Windows blocks the file which results in the "Windows protected your PC" popup:
You can click More info, then Run anyway. Alternatively, you can right-click on the .zip file and select the option to unblock:
Before proceeding, ensure that you have the following prerequisites installed on your macOS:
Homebrew
WINE
Winetricks
Install Homebrew
Install WINE and Winetricks
You can install WINE and Winetricks using Homebrew. Open a terminal and run the following commands:
The following goes through the steps do download and run the setup_gum_mac.sh
automation script. This script goes through the steps for you with minimal interaction to setup your environment on macOS to run the GUM tool using WINE. If you would prefer to do this setup manually, please see the Manual Setup Steps section below.
Open a terminal and cd
to the directory that the script was downloaded to
Make the script executable
Execute the script
The following goes through the steps setup your environment on macOS to run the GUM tool using WINE.
Open a new terminal
Install .NET Framework 4.8 using winetricks
with the following command:
This command initiates the installation of .NET Framework 4.8. A total of two installer dialogs appear one after another. Follow the steps for both to complete the installation. This process may take a several minutes, so please be patient.
Download the XNA 4.0 Redistributable MSI file from Microsoft. You can download it using the following command:
After downloading the MSI file, install it using the following command:
Follow the installation prompts. At the end of the installation, it may display an error related to launching DirectX. This is normal; just click "Close" on the error dialog.
Download the Gum Tool ZIP file from the FlatRedBall website and save it to your preferred location. You can download it using the following command:
Unzip the downloaded Gum Tool ZIP file into the Program Files directory of the WINE folder. Run the following command in the terminal:
After unzipping the Gum Tool, remove the downloaded ZIP file using the following command:
Create a script to run the Gum Tool. Run the following command in the terminal:
Make the script executable by running:
To ensure you can run the Gum Tool from any directory, add the script directory to your PATH.
For Bash SHELL
For ZSH Shell
Reload the shell configuration to apply the changes. Run the following command:
For BASH Shell
For ZSH Shell
Congratulations! You have now successfully set up the Gum Tool on macOS using WINE. You can open the Gum Tool by simply typing the following command in the terminal:
If the command doesn't work immediately, try closing and reopening the terminal.
The Font variable sets the font family used by the text.
The Font dropdown has access to any font which is installed locally.
To use a font in Gum, download the font and install it by double-clicking or right-clicking on the font.
Gum performs rendering using rasterized fonts. In other words, it renders using pre-made .png files which contain all of the characters in a font.
You can view the Font Cache in your project by selecting Content -> View Font Cache.
This folder contains all font files used by your project.
Note that each font has three files:
bmfc - Bitmap Font Generator configuration file. This can be opened in Bitmap Font Generator to see the settings that have been used to export the other files
fnt - Bitmap Font Generator font file. This is a text file indicating the location of each character in the matching png files. It also includes kerning pairs.
png - This is the image file containing the letters for the font. The font may contain multiple image files if the character set or font size are large enough.
Each PNG can be opened in an image editor to view the packed characters. For example, the following shows the Arial 24 font. The blue background has been added manually to make the white characters visible:
Fonts are generated as needed by Gum. This happens whenever a property changes on a Text object requiring a new font. Gum only re-generates fonts if a matching font doesn't already exist. The following animation shows new fonts being generated as a Text's Font Size is changed.
Fonts are generated in response to any of the following properties changing:
Font
The font scale property allows you to zoom a font in or out, effectively making the text larger or smaller. Unlike using the font size property, font scale will not re-create the font (when using standard fonts). Font scale is also necessary for resizing custom fonts.
By default Text objects Font Scale value of 1.
Font scale can be increased, but doing so can make fonts pixellated. For example, setting the Font Scale value to 5 makes each pixel on the font 5x as large, resulting in a pixellated text object.
Similarly, FontScale can be set to a value smaller than 1, resulting in a shrunk font.
Font Size controls how large a font appears on screen. Each font size and Font combination creates its own rasterized font, so using a lot of different font sizes will increase the amount of texture memory your game needs.
The Font Size property can be set in Gum to make a text object's font larger or smaller. For example, the following shows a Text object with a font size of 18:
Changing the font size will increase the size of the Text object. For example, here is the same Text object with a Font Size of 36:
The first time a Font and Font Size combination are referenced, Gum creates a file in the FontCache folder. You may notice a small pause in Gum when setting Font and Font Size combinations for the first time as the file is created, but subsequent changes will be fast.
The FontCache folder is located in the following location:
/FontCache/
The Green value controls the color of the Text object. The Green value has a range of 0 - 255. The Green value combines with the Blue and Red values to create the final color.
For more information on working with color, see the .
OutlineThickness can be used to create an outline around a font. The outline is saved in the .png of the font itself, so each value for OutlineThickness results in a new .fnt file and associated .png files created in the FontCache folder.
The OutlineThickness can be set on a Text object like any other variable.
OutlineThickness changes appear in the Gum window.
This value controls the number of letters that the Text object will show. This value is used when displaying the text, but is not used when calculating the Text size or line wrapping.
If the value is <NULL>, then there is no maximum - all letters are displayed.
Max Letters To Show limits the number of characters (including spaces). By default this value is <NULL>, which means a Text object will display its full string. Setting this value will adjust the display of the text, but it will not impact any layout values.
For example, by default a Text object displays all of its letters. Note that the Width is fixed, and the Height depends on the contained text - the Height is automatically set on the Text object according to the contents of the text.
Setting Max Letters To Show value to 30 restricts the Text object to displaying its first 30 characters, but the size and line wrapping do not change.
Max Letters To Show applies after all layout and text positioning has been applied. Therefore, centered text may appear off-center. The following text would appear centered if Max Letters To Show allowed the entire text to be displayed, but since it is cut-off, it appears off-center.
Containers are used to group objects to simply movement, alignment, positioning, and size. Containers are usually invisible, although they can draw their outlines in Gum to help visualize their position and size.
The Wraps Children property controls whether children wrap or stack beyond their container's boundaries when the container's is set to Top to Bottom Stack or Left to Right Stack.
If a parent has Wraps children set to true, the wrapping adjusts in response to resizing the parent.
Similarly, resizing a child may result in the stacking changing.
The row height in a Left to Right Stack is determined by the largest child in the row.
Similarly, column width in a Top to bottom Stack is determined by the largest child in the column.
The Texture Address variable can be used to define the area that the NineSlice displays. By default the Texture Address is set to Entire Texture which means the NineSlice will display the entire source file (split up among the nine pieces).
The following screenshot shows an entire texture being used for a NineSlice.
The entire texture is split up into 3 sections horizontally and 3 sections vertically, matching up the texture coordinates used to display the NineSlice's 9 sections.
The Custom value allows specifying a custom set of coordinates for the Nine Slice. Custom is most often used to when an image is part of a sprite sheet. The following example uses this image:
The NineSlice uses the following variables:
Texture Address = Custom
Texture Top = 0
Texture Left = 0
Texture Height = 40
Texture Width = 40
These values result in the the following NineSlice:
Text Overflow Horizontal Mode controls how truncated words are treated. Horizontal truncation is only performed if the Text instance is using a Text Overflow Vertical Mode of Truncate Line. For information more see the page.
Truncate Word results in words which do not fit in the Text instance's bounds being completely removed.
The following animation shows words (and lines) truncated in response to changing a Text instance's size.
Ellipsis Letter results in letters which do not fit in the Text instance's bounds being replaced by an ellipsis (...) which fits in the bounds of the Text instance.
The following animation shows words (and lines) replaced by ellipsis in response to changing a Text instance's size.
Note that additional letters must be removed from the Text instance so the added ellipsis fits in the Text instance's bounds.
The Red value controls the color of the Text object. The Red value has a range of 0 - 255. The Red value combines with the Blue and Green values to create the final color.
For more information on working with color, see the .
Text Overflow Vertical Mode controls whether lines of text can draw outside of the bounds of the Text object vertically.
Spill enables the drawing of text lines outside of the vertical bounds of a Text instance. The following image shows a Text instance with wrapped text using Spill.
Truncate Line removes lines which fall outside of the bounds of the Text instance. The following animation shows lines of text truncating in response to changing the Text instance's height.
Note that if the Text instance's height becomes too small then all text disappears.
The Use Custom Font variable controls whether a Text object uses a premade .fnt file (if true) or if it Gum automatically creates font files according to the Text's Font, Font Size, and Outline Thickness variables.
Use Custom Font is false by default.
If Use Custom Font is set to true, then Gum displays the Custom Font File variable, which can point to a .fnt file created by Bitmap Font Generator.
If Use Custom Font is set to true, then the Font, Font Size, and Outline Thickness variables can no longer be set - as they are part of the font file itself.
The Font Scale variable is still available when using custom fonts.
To set a custom font
Click the ... button
Navigate to the location of the desired .fnt file
Select the file and click Open
Custom font files are .fnt files created by BitmapFontGenerator. Gum automatically creates .fnt files whenever a font value changes when UseCustomFonts is unchecked.
To create your own font file:
Select Options -> Font Settings
Use the dropdown to select the font you would like to use. All .ttf files installed on the current machine should appear in the dropdown. If you would like to install a new .ttf, restart Bitmap Font Generator after installing the font.
After changing the settings, click OK
Select which characters you would like included in your font. Adding characters can increase the font size, but may be required depending on which characters you intend to use.
Select Options->Export Options
Select a Bit depth of 32 (or else transparencies won’t come through).
Select the texture width and height. For best performance, select a size which will contain all of the characters you have selected. Also, many game engines prefer textures which are power of two such as 256, 512, 1024, or 2048. Sizes larger than 2048 may not render properly on some hardware.
Change the Textures option to png – Portable Network Graphics
Be sure to keep the Font descriptor as Text.
Press OK to apply the changes
Also, note that if you are using outline, you will want to have the following values:
A: outline
R: glyph
G: glyph
B: glyph
You can verify that the settings will produce a proper PNG by selecting Options -> Visualize. If you see “No Output!” then you need to select characters to export. See the above step for more information.
To save the font, select Options->Save bitmap font as… to save your .fnt and .png files.
Once you have saved your files, you can select the .fnt to use in your project.
The Hiero tool can also be used to generate .fnt files:
To generate a font:
Download and open the Hiero tool
Set the values needed for your font, such as font type, size, and effects
Select File -> Save BMFont Files (text)...
Select the location to save the files, such as in your project's Contents folder, or the subfolder which contains your Gum project
This .fnt file can now be loaded in the Gum tool or in code just like any other .fnt file.
The Code tab provides generated code for your current Gum objects.
This tab provides the following functionality:
Immediate display of generated code for the selected object
Ability to see generated code for individual instances in an object or for an entire component/screen
Ability to generate code automatically for a variety of target platforms
If you are working with Gum in a C# environment then the Code tab can help you write Gum code.
To enable code generation:
Select a Screen, Component, or instance
Check the Is CodeGen Plugin Enabled checkbox
Check the Show CodeGen Preview checkbox to display the current selection in the preview window
The generation of code may make selection slightly slower, especially when viewing complex screens or components. If you are experiencing performance problems, you may consider unchecking the Show CodeGen Preview checkbox when performing editing.
If you have a single instance selected, the preview window displays the code for creating the instance and assigning its variables. This is especially useful if you are unsure how to reproduce a particular layout in code. For example, the following image shows the generated code for a Text named TextInstance.
The generated code shows all of the assignments necessary to reproduce the current instance's layout. Keep in mind that only explicitly-set variables are displayed. Any default (green background) variables are not assigned in generated code.
If a Screen or Component is selected, then an entire class for the component is displayed in the preview window. This generated code includes:
using
statements
A partial
class with the suggested name. The name appends the word "Runtime" to the Screen or Component name
enum
declaration for all categories
Properties for each category including switch statements assigning all properties for each state
A property for each instance in the Screen or Component
Initialization of all variables including variables on the instances
The Code tab supports the automatic copying of files to disk. By using this feature, C# projects can automatically stay in sync with Gum projects, eliminating the need to write custom Runtime objects.
Projects should be backed up or committed to source control before enabling automatic code generation to make it easy to undo changes.
To set up automatic code generation, first enable the code generation plugin as shown above. The Show CodeGen Preview checkbox does not need to be checked.
Next, modify the values in the Project-Wide Code Generation section and the Element Code Generation section as discussed in the following sections:
Select the desired Output Library, such as MonoGame.
If you are planning on loading the .gumx project, select the FindByName option.
If you would like the entire project generated, select the FullyInCode option. This option enables working in Gum to create layouts which will work fully in code without loading a .gumx file. This is especially improtant if you are working on a platform with limited IO access. Generated code can run faster than loading a .gumx file since it does not require file IO, XML parsing, and reflection.
Add the following using statement at the end of the Project-wide Using Statement box so that references to standard runtime types are found.
If you plan on creating Screens, you should also add using statements for your component runtimes
Enter the location of the folder containing the .csproj file in the Code Project Root text box. If an absolute path is entered, it will be saved to a relative path so that generation works for all users working on a project regardless of where a project is cloned even though it appears absolute in Gum. For example: C:\Users\Owner\Documents\GitHub\Gum\Samples\MonoGameGumCodeGeneration\
Enter the project's Root Namespace, such as MyGame
.
Enter the type that you would like all Screen runtimes to inherit from. If you're not sure what to enter, then use GraphicalUiElement
. If your game uses a custom class that you have written for all Screens, then use the name of that class. You can switch to custom classes later as your project grows.
Select NeverGenerate for components which should not generate to disk
Select GenerateManually if you would like to generate code only when the Generate Code button is clicked.
Select GenerateAutomaticallyOnPropertyChange to generate code whenever a property changed. This option is useful once you are comfortable with code generation. It results in code being generated automatically as you make edits in Gum.
The Generation Scope options control whether the entire selected object is shown in the generated code window or if only the current state is selected.
If Selected Object is selected, then the entire object's generated code is displayed.
The Selected State option is useful if you would like to see only the changes made by the selected state.
The Is CodeGen Plugin Enabled checkbox controls whether Gum generates code automatically to the destination location specified by the Code Project Root. Gum automatically generates code if:
The Is CodeGen Plugin Enabled is checked
A Code Project Root is specified
An object has its Generation Behavior set to GenerateAutomaticallyOnPropertyChange
If this option is unchecked, then code will not automatically be saved to disk even if the other options are set.
For more information on automatic code generation, see the section on .
Top to Bottom and Left to Right stacks separate their children using the Stack Spacing property. For more information, see the page.
In most cases children which are stacked should use a Left if the parent uses a LeftToRightStack and should use a Top if the parent uses a Top To Bottom Stack.
In the image shown above, the red rectangle is positioned directly to the right of the blue rectangle. Notice that if the red rectangle's is changed to Center, the red rectangle overlaps the blue rectangle.
If the red rectangle's is changed to Right, then its right side will align with the right side of the blue rectangle, resulting in the red overlapping the blue completely. In this case the stacking is essentially cancelled out by the .
The property controls how stacking behaves beyond boundaries. For more information, see the page.
Gum natively supports referencing Animation Chain XML files (.achx) which are created by the FlatRedBall AnimationEditor. For more information on creating .achx files, see the FlatRedBall .
Sprites can also reference images without extensions, such as urls from
The following image shows a with its Y Origin set to Center:
The following image shows a with its Y Origin set to Bottom:
Baseline refers to the bottom of the text for letters without descenders. For more information see the .
Homebrew is a package manager for macOS. If you haven't installed Homebrew yet, you can install it by following the instructions on the .
Download the setup_gum.mac.sh script
This dropdown appears only if is set to false.
The .fnt file format used by Gum is the Angelcode BitmapFontGenerator format. This can be produced by a number of applications. Note that this is not the same as the old .fnt extension used for Windows fonts.
Download Bitmap Font Generator from
The Export delegate allows you to create a custom export for Gum elements. This delegate will automatically be called by Gum whenever an element is saved. By default this occurs whenever the user makes any modification to the element. If your export is especially processor intensive you may consider not adding your export logic here and rather requiring an explicit export by the user.
The following code will show a message box whenever an element is exported. Keep in mind this is only for demonstration purposes. By default Gum auto-saves every change made by the user, and showing a message box after every save can be very annoying for users of your plugin.
The above example shows how to react to a component being exported, but it doesn't get at the heart of what an export plugin does.
The first thing that an export plugin needs to do is to access properties on an element (such as its position and size) as well as the instances contained within the element. This information is available through the ElementSave class.
For more information on how to access properties and instances from the ElementSave, see the Gum Class Overview page.
The following shows what a very simple exporter might look like:
This may produce output that looks like this:
dll files created for plugins are files which are not required for Gum to function. In other words, if the file is there Gum will use it. If not, Gum can operate normally. This means that in your Visual Studio solution the project that you have created to hold your plugin will not automatically be copied to the build output folder. Fortunately Visual Studio supports post-build events which allow you to copy the built .dll to the plugins folder.
To access the post build event on a project:
Right-click on your project in the Solution Explorer
Select "Properties"
Select the "Build Events" tab on the properties page
Notice the "Post-build event command line:" section
To add a post build event, you will need to add command line commands to copy the .dll and .pdb to the plugin folder. Post-build events are simply run in a command line environment after the build succeeds. Therefore you can put any logic in here, including running other .exe or .bat files.
For this example we will assume that the project is called PluginProject. You will want to change the following text to match your project's name. To copy the files, paste (and modify) the following:
Notice that "PluginProject" appears 8 times in the text above, so be sure to replace all instances with your project name.
The copy script copies the .pdb file to allow you to debug your plugin. Specifically the PDB enables breakpoints to trigger and to break on exceptions.
Gum is an open-source tool which enables you to pull code for any other project, or to make modifications so that the tool fits your needs.
Gum uses the following technologies:
.NET 4.6 (included with Visual Studio)
Windows Forms (included with .NET 4.0)
XNA Game Studio 4.0 https://msxna.codeplex.com/
For information on running from source, see Running from Source.
For information on how to write Gum plugins, visit this page: Plugins
Gum is an open source project so you can run it from source instead of running the pre-compiled project.
Download the source file from GitHub
If you downloaded the .zip file from the GitHub main page, unzip the file
If you downloaded the file through a Git client, be sure to be on the master
branch
Locate the Gum.sln file
If you downloaded the .zip, it is in the root folder of the zip
If you cloned the repository, it is at the root of the Gum folder
Double-click it to open Visual Studio, or open Visual Studio and load the .sln
Run the build configuration in "x86". The build configuration may default to "Mixed Platforms". If you do not change it Gum will not compile.
If your project depends on plugins, be sure to build solution, rather than pressing F5. This guarantees that all plugins are built and copied correctly.
This page discusses all of the classes in Gum at a high level to give you an understanding of how they relate to each other.
The following hierarchy shows a typical (although small) Gum project:
Gum Project Save
ScreenSave
InstanceSave
InstanceSave
StateSave
VariableSave
VariableSave
VariableSave
ScreenSave (etc...)
ComponentSave
InstanceSave
StateSave
VariableSave
VariableSave
VariableSave
ComponentSave (etc...)
StandardElementSave
StateSave
VariableSave
VariableSave
Notice that GumProjects contain ScreenSaves, ComponentSaves, and StandardElementSaves. ScreenSaves, ComponentSaves and StandardElementSaves all share the same base class: ElementSave. Therefore, a lot of Glue code will work with ElementSaves rather than the specific derived type.
ElementSaves can contain instances, and each instance is of type InstanceSave. Therefore, if you wanted to print out information about all of the instances in a given screen you might do something like this:
This page discusses how to write plugins for Gum. Plugins are a useful way to modify Gum because they allow you to customize Gum without making project-specific, technology-specific, or organization-specific modifications to the core source code. This means that you can customize the Gum experience while still maintaining ties to the core source code.
To begin writing a plugin:
Obtain the Gum source code. You can download the .zip or get the source through a version control client
Create a copy of Gum.sln. You will want to work with your own .sln file so that the project containing your plugin can be debugged easily. For example, you might want to call your solution GumWithPlugins.sln
Open your new .sln file in Visual Studio
Now that you have created a .sln which will contain your plugin project, you can add this project:
Right-click on your solution
Select "Add ->New Project..."
Select "Class Library" as the type
Verify that you are targeting .NET 4.5
Enter the name of your project, such as MyPluginProject
Click OK
Next you'll need to reference the Gum libraries. To do this:
Right-click on your project's References
Select "Add Reference"
Verify that "Solution" is selected (Assuming Visual Studio 2012)
Check the following projects:
Gum
GumDataTypes
InputLibrary
RenderingLibrary
ToolsUtilities
Click OK
Since Gum references XNA, and XNA doesn't have 64 bit libraries, you will need to modify your project's build configuration. To do this:
Select the "Build"->"Configuration Manager" menu item
Change the Active solution platform" from "Mixed Platforms" to "x86" if it isn't already set to x86. If your Active solution is set to "Any CPU", change that to "x86"
If your plugin project's Platform is set to "Any CPU", use the drop down to pick "x86" if it exists. If not, select ""
Change the New platform to "x86"
Click "OK"
Make sure your plugin project is set to build
Click Close to close the Configuration Manager
Adding a Plugin class
Next you'll want to add a Plugin class. This is a class that inherits from PluginBase. To do this:
Right-click on your project
Select "Add->Class..."
Name your class "MyPlugin" or whatever you want your plugin to be called
Add the following using:
Modify your plugin so it's public and inherits from PluginBase:
Add the following implementation into your plugin class:
Now that you have a simple plugin, you need to do two things to test this plugin out. The first is to mark the plugin as a class that is exported using Microsoft Extension Framework. To do this:
Right-click on your project's References item in the Solution Explorer
Select "Add Reference..."
Click the "Assemblies->Framework" tab
Check "System.ComponentModel.Composition"
Click OK
Add the following using statement to your plugin class: using System.ComponentModel.Composition;
Modify your class definition so it looks like this (we're making it public and also adding the Export attribute:
Now you can right-click on your project and select Build and it will generate a .dll for your project. This .dll file needs to be in the Plugins folder under the Gum binary. That is, from the location of your .sln file, you can go to . Once there, you will need to create a folder for your plugin (like MyPlugin) and place your .dll there.
To verify that your plugin is working correctly:
Run Gum
Click Plugins->"Manage Plugins"
This may happen if you are targeting different versions of the .NET framework. At the time of this writing Gum targets .NET 4.5. Therefore, you'll want to make sure that your Plugin project also targets .NET 4.5. To do this:
Right-click on your project
Select "Properties"
Select the "Application" tab
Verify that the "Target Framework:" is set to .NET Framework 4.5 (or whatever version Gum is currently on)
The AddAndRemoveVariablesForType event allows plugins to add and remove variables from standard elements. Since Gum is designed to work with external engines the properties presented by standard types (such as Sprite) may not align with the feature set of the external engine. Variables can be added and removed to create a more natural development experience for users of Gum.
The following code can be used to add a variable to the Sprite standard element. This variable will be a float variable with the name "MyCustomVariable".
First the event must be added in the StartUp method:
The HandleAddAndRemoveVariablesForType method handles the event being raised and adds the necessary variables. Note that in this case we are only handling variables for the Sprite type, but the same method could be used for all types:
The end result would be that the Sprite object displays the variable when selected:
The example above shows how to add variables, but you can also remove variables from standard types. For example if your engine does not support texture wrapping on Sprites, you may do the following:
To prevent accidental deletion of data, Gum will still present variables which are defined in the XML files for standard elements even if the variable is removed through a plugin. Therefore, to fully remove a variable (like Wrap), it must be removed from the underlying XML file as well. This can be done by removing the individual file from the XML file, or deleting the entire XML file (which will cause Glue to regenerate it). Keep in mind that deleting and regenerating the entire XML file will result in all other changes being lost.
The syntax used to add new variables in plugins is the same as how Gum adds standard properties. For an extensive example on how to add variables, see the StandardElementsManager.Initialize method.
The project properties window allows you to modify properties that apply across the entire project (as opposed to a single screen or component).
To open the Project Properties tab, select Edit -> Properties.
Gum allows you to change the canvas width and height of a project. This canvas width/height can both give you a sense of size when creating UIs, as well as provide a container for objects with no parents. In other words, objects that sit directly in a screen (as opposed to in another container) will be positioned and sized according to the canvas width/height.
The canvas width and height can be changed through the project properties page.
Gum supports localization using a localization CSV. Adding a localization file to your Gum project is useful since it allows previewing your layout with different languages. Some languages have text which is longer than other languages. By checking your localization in Gum you can adjust your layout so that it properly handles longer text.
Localization can be added using a CSV file. The first column in a localization file is the string ID, which is the key that is used to perform localization look-ups. These keys should suggest the text which is displayed, but should also have some kind of prefix or suffix to differentiate string IDs from untranslated text.
Each additional column can contain translations for a single language. The top row of the CSV is ignored by Gum, so you can add titles for the language to make your CSV more readable.
The following shows what a sample CSV might look like:
Notice the string IDs in the table above have the "T_" prefix. This is not a requirement - you are free to use any string ID convention you choose.
Notice that comments using two forward slashes (similar to languages like C#) can be used to add comments which are ignored by Gum.
Once you have created a CSV with the desired entries, you can reference this by clicking the ... button to browse for the file in Gum.
After selecting the localization file, you can choose which language index is being displayed. Note that this is a 0-based index, with the left-most column being 0. For example, using the table above a Language Index of 1 would result in the English column being displayed.
Once you have added a localization file, Gum recognizes this and displays Text properties as an editable drop-down. You can type in a string ID, or you can use the drop-down to select from available options.
Localized text appears in Gum based on the selected ID. You can change the Language Index at any time to see localization applied immediately in your screens and components.
The Font Ranges setting controls which characters are included in default fonts. The Font Ranges value is ignored when using custom font (.fnt) files.
The default Font Ranges value is 32-126,160-255
which maps to the first page of the Bitmap font generator character set, labeled as Latin + Latin Supplement.
Various websites provide a list of unicode character sets such as https://unicode-table.com/en/blocks/
Additional characters can be added by modifying the Font Ranges character set. Individual characters can be added or entire ranges. For example, to add the Latin Extended A set, the Font Ranges value can be changed to 32-126,160-255,256-383
. Note that the last range of 256-383 could be merged with the previous to produce the following range: 32-126:160-383
. Note that the ranges are inclusive on both ends, so a range of 160-383 will include the characters 160 and 383 along with all values in between.
Changing the font ranges immediately refreshes the page. Note that all fonts are re-created so this operation can take some time.
The following animation shows the Ā character being included and excluded from the Font Range, causing it to appear and disappear in the displayed text.
Note that expanding the character set results in larger font PNG files which can impact the size and performance of games using the Gum files.
The AddMenuItem function allows adding menu items to Gum. The AddMenuItem accepts an enumerable of strings which allow you to embed menu items under a root menu item.
The following shows how to create a menu item called "My Plugin" which contains two items: First and Second. Clicking each item results in a message box appearing. Add the following to your plugin's StartUp function.
The Camera object is used to adjust the position of all objects in a game and provide zooming capabilities. By default the camera is positioned at 0,0, so all objects are drawn in screen space. Games which need to render objects in world space can do so by applying camera offsets.
By default the Camera's position is at X=0 and Y=0, with the top-left of the Camera defining its position. If the camera moves, then all Gum objects appear to move in the opposite direction. For example, increasing the Camera's X value results in the camera "moving" to the right, resulting in objects in screen moving to the left.
The following code shows how to move objects in response to the MouseState:
By default the Camera's Zoom value is set to 1. This Zoom value applies a global zoom to all drawn UI. This can be adjusted to make all UI bigger.
The following code shows how to zoom in and out.
Note that the text that is positioned along the right and bottom does not update its position in response to the zoom. The reason for this is because the canvas size has not been adjusted.
This can be fixed by also adjusting the canvas as shown in the following code. Note the following code assumes a default width of 800 and height of 600:
The Is Italic value controls whether the Text instance uses an auto-generated font which applies font smooth (anti-aliasing). This effect of this value can be easily observed if zoomed in.
This value is true by default because it usually produces more visually appealing fonts. If your project is using an intentionally pixelated font then you may want to disable this property to preserve the pixelated aesthetic.
The Project Tab displays all Screens, Components, Standard Elements, and Behaviors in a project. Each element type is organized in its own subfolder.
The search bar can be used to find elements in your project by searching for their name. By default the following are searched:
Screen Names
Component Names
Standard Element Names
Behavior Names
Additionally, variable values can be searched by checking the Search variables checkbox. When checked, variable values are searched for the entered text.
Text objects have a Text property which controls the displayed text. By default this value is set to "Hello".
The Text property can be changed in the multi-line edit window.
Text will wrap according to the Text object's Width.
The enter key can be used to add new lines to text.
Gum text supports inline styling using BBCode-like syntax. To add inline styling, surround text with variable assignment tags as shown in the following screenshot:
The following table shows the available variables that can be used for inline styling:
Note that changing Font and FontSize results in new Fonts created in the Font Cache.
BBCode can span multiple lines, whether the newlines happen due to line wrapping or through the addition of newlines in the text.
Multiple tags can overlap each other allowing you to combine tags for a single piece of text. For example, the following sets text to both bold and orange:
Styles can contain other styles as many levels deep as necessary.
The GraphicalUiElement class represents any visual element in the Gum runtime. An instance of a GraphicalUiElement exists for every instance of the base rendering types (such as ) as well as instances of components. When loading a .gumx file in a project (such as a MonoGame or FlatRedBall project), each Screen is also a GraphicalUiElement.
The Categories member provides more detailed control over a DataUiGrid. The easiest way to work with a DataUiGrid is to assign its Instance and let it automatically create UI for all public members. Working with Categories requires more code but gives the most flexibility in setting up a grid.
The following makes the grid only show a single value called "Some Value" which always has a value of 10. An actual implementation may modify some backing variable.
The DataUiGrid is similar to Winforms PropertyGrid - a reflection-based UI object which can be used to display the properties on objects in real-time. It is used for the properties on Gum objects, but is written to be general purpose to be used in any applications.
It is included in the WpfDataUi.dll file which is part of Gum, so this library can be pulled out and used in any other application.
The DataUiGrid can be used with reflection or its Categories can be manually populated. Using reflection is easier to set up, but does not provide as much flexibility. Manually building up Categories takes more work, but provide the most flexibility.
The following references are needed for displaying the DataUiGrid:
PresentationCore
PresentationFramework
System.Xaml
WindowsBase
To add a grid to your XAML you'll need to:
If using .NET 6+, add the following using:
If using .NET 4.7, add the following using:
Add the following inside a layout container (like a Grid):
You can construct a grid in code just like any other WPF control.
To use the grid in code you simply need to set its Instance member to an instance object you want to view. For example:
This will produce a grid which looks like this:
Alternatively the Instance property can be data bound as shown in the following XAML:
The default behavior for DataUiGrid is to reflect properties from the assigned Instance. When the Instance is assigned, the Grid automatically populates its Categories with members based on reflection.
Properties which have the System.ComponentModel.CategoryAttribute
will be categorized according to the category assigned. Otherwise, properties will be put in the Uncategorized category.
By default all public fields and properties are displayed in a DataUiGrid. To control which properties are shown, the categories can be cleared, and individual InstanceMembers can be added for the desired properties.
For example, the following code clears the properties, and shows only X, Y, and Z:
The BlendState property allows a GraphicalUiElement to blend with what is drawn before it. BlendStates can be used to control both color and alpha blending. Most games do not need to modify BlendState, and coverage of BlendStates is beyond the scope of this documentation.
The Gum BlendStates type mimics the XNA (MonoGame) BlendState. For more information see on BlendState, see the MonoGame BlendState API reference:
For examples of custom BlendStates, see this post:
By default Gum objects render directly to the back buffer, so the alpha value of the back buffer does not matter.
If you are rendering to a render target, then you may want to modify the blend state so that the object being renders adds to the alpha. The following code shows how to do this:
CanvasHeight is a static property which tells the Gum layout engine the size of the canvas. This is used for layouts on GraphicalUiElements which have no parent.
CanvasHeight and CanvasWidth are typically assigned to the height and width of your canvas. This can depend on the development environment. These values are used for layouts, especially layouts which depend on the canvas (or window) width and height.
Setting these values does not automaticaly cause all GraphicalUiElements to perform their layout calls. If these values are changed then any GraphicalUiElements which have no parents should have their Layout method called. Setting properties on a GraphicalUiElement (such as changing WidthUnits) may also perform a layout.
If your game is not zoomed, then the CanvasWidth and CanvasHeight should match the graphicsDevice width and height as shown in the following code:
If responding to a window resize or zoom change you may need to also call UpdateLayout on any objects which do not have parents. Usually this is a single root object, as shown in the following code:
The AnimateSelf method performs .achx animation logic, advancing the displayed frame on the calling GraphicalUiElement and its children. This call is recursive, so it is typically only called on the root GraphicalUiElement (such as the current Screen).
The following shows how to call AnimateSelf on a GraphicalUiElement. Typically this is called every frame in activity. For example, this code shows how to animate a GraphicalUiElement in a MonoGame project:
AnimateSelf is called automatically in FlatRedBall projects in generated code.
ApplyState can be used to apply a state (StateSave) to a GraphicalUiElement. States can be set by direct StateSave reference, or by unqualified name. Direct StateSave assignment supports states defined in Gum or dynamically created states.
String ID | English | Spanish |
---|---|---|
Tag | Example | Result |
---|---|---|
T_OK
OK
OK
T_Cancel
Cancel
Cancelar
T_Submit
Submit
Entregar
T_Back
Back
Regresar
T_Next
Next
Siguiente
// This is ignored
Color
This is [Color=orange]orange[/Color] text.
Red Green Blue
This is [Red=0][Green=128][Blue=255]light blue[/Red][/Green][/Blue] text.
FontScale
This is [FontScale=2]big[/FontScale] text.
IsBold
This is [IsBold=true]bold[/IsBold] text.
IsItalic
This is [IsItalic=true]italic[/IsItalic] text.
Font
This is [Font=Papyrus]Papyrus[/Font] text.
FontSize
This is [FontSize=36]bigger[/FontSize] text.
OutlineThickness
This is [OutlineThickness=2]outlined[/OutlineThickness] text.