The SettingsView control provides common settings for controlling your game's audio and full screen status.
Specifically, the SettingsView can be used to control:
Song (music) volume
Sound effect volume
Full screen/windowed
Note that future versions of SettingsView may expand to include more controls and settings in the future.
The first step in using the SettingsView is to add an instance of the view to your Gum screen. If your project has included FlatRedBall.Forms then you have a default SettingsView in Gum.
Once the SettingsView has been created and added to a Screen. By default the music slider modifies AudioManager.MasterSongVolume and the sound effect slider modifies AudioManager.MasterSoundVolume.
This behavior can be disabled by setting IsAutoApplyingChangesToEngine to false.
By default the IsFullscreen property does not automatically apply a full screen/windowed status to the engine. At the time of this writing full screen status is typically controlled through generated code, so the SettingsView does not have access to the methods necessary to set full screen/windowed.
To toggle full screen you can either bind a ViewModel to the IsFullscreen property or you can subscribe to the FullscreenSet property.
The following code shows how to subscribe to the FullscreenSet property:
This code assumes that you are using the generated CameraSetup code provided by the Display Settings window.
The DialogBox control is used to display dialog to the screen. It provides a number of common dialog functionality including:
Typewriter (letter by letter) display of the text
Multi-page display using an IEnumerable
Task (async) support for logic after
Force display of entire page and page advance input
Input support using keyboard, mouse, and gamepads
Like other FlatRedBall.Forms controls, the easiest way to create a DialogBox is to add a DialogBox instance into your screen. By default dialog boxes are visible, but you may want to mark yours as invisible in your Gum screen so it doesn't display in game until you need it to display. For most games only a single DialogBox instance is needed unless you intend to have multiple dialog boxes displayed at the same time.
To display a dialog box, use one of the Show methods. The simplest is to call Show with a string, as shown in the following code:
Alternatively, multiple pages can be displayed using an IEnumerable such as a string array as shown in the following code snippet:
DialogBox can display multiple pages through the Show and ShowAsync methods. Each string is treated as an entire page if it fits. A single string will be be broken up into multiple pages if it is too large.
The following code results in multiple pages automatically being set.
Automatic paging only applies if the number of lines is limited on the backing Text object. The default implementation of the DialogBox should automatically limit the number of lines.
The default implementation's Text property has the following relevant properties:
Note that if the Text property can extend indefinitely - either by allowing it through a Text Overflow Vertical Mode of Spill or by having a Height Units of Relative to Children.
The ShowAsync method returns a task which can be used to await for all pages to be shown and for the final page to be dismissed. A common usage of ShowAsync is in a scripted sequence. For example, a scripted sequence may combine dialog and player movement. Since the player can choose when to advance text, the amount of time that a DialogBox is displayed must be awaited. The following shows how code might be used to implement a scripted sequence which combines dialog being displayed and player movement.
Note that if your game requires advancing the dialog with the Keyboard or Xbox360GamePad, then the DialogBox must have its IsFocused property set to true. See the section on IsFocused for more information.
The DialogBox control provides a few approaches for showing multiple pages. As shown above, the Show method can take an array of string
s. Alternatively, the ShowAsync
method can be used to show one page at a time.
This approach is useful if your DialogBox implementation has additional properties for each page of dialog. For example, a DialogBox can be modified in Gum to have a Text instance displaying the name of the person speaking.
Since the Show method exists on the standard DialogBox, it does not have a way to specify the speaker. We can access the visual on the DialogBox to modify the SpeakerTextInstance directly through the Visual property.
Note that to access the SpeakerTextInstance, the Visual must be used, which is a reference to the Gum object. The dialogBox
is an instance of the standard DialogBox
forms object, so it ony provides methods and properties common to every DialogBox
. For more information about Forms vs Gum objects, see the Forms vs Gum in Code Tutorial.
DialogBox text fully support styling, including pages. The following code results in styled text.
More information on styled text can be found in the Gum documentation: https://docs.flatredball.com/gum/gum-elements/text/text#using-bbcode-for-inline-styling
DialogBox responds to input and can respond to two types of input: confirm input and cancel input.
Confirm input performs the following actions:
If dialog is printing out character-by-character, the entire page is immediately displayed
If the entire page is displayed and the DialogBox has more pages to display, the page is cleared and the next page begins displaying
If the entire page is displayed and the DialogBox has no more pages to display, the dialog box is dismissed
Cancel input performs the following actions:
If dialog is printing out character-by-character, the entire page is immediately displayed
If the entire page is displayed and the DialogBox has more pages to display, the page is cleared and the next page is displayed in its entirety
If the entire page is displayed and the DialogBox has no more pages to display, the dialog box is dismissed
In other words, confirm and cancel input behave the same except that cancel immediately prints out the next page, giving players the choice to skip letter-by-letter display.
Dialog can be advanced with Mouse, Keyboard, Xbox360GamePad, and a custom Func
predicate named AdvancePageInputPredicate
. Note that if a DialogBox has a non-null AdvancePageInputPredicate
, then all other forms of input are ignored. This allows games to fully customize a DialogBox's page advance logic.
The Mouse can only perform confirm input. If a dialog is clicked, then its confirm action is executed.
The Keyboard's IInputDevice implementation is used for confirm and cancel actions:
Space (DefaultPrimaryActionInput) is used to confirm
Escape (DefaultCancelInput) is used to cancel
Note that the keyboard actions will only apply if the DialogBox has focus. For example, the following code shows how to give a DialogBox focus:
For more information on IsFocused and DialogBoxes, see the section below.
Xbox360GamePad Input
Xbox360GamePads can be used to advance dialog. A DialogBox must have focus for the Xbox360GamePads to advance dialog, just like the Keyboard. Furthermore, the desired Xbox360GamePads must be added to the GuiManager's GamePadsForUiControl as shown in the following code:
For more information, see the GuiManager.GamePadsForUiControl page.
Once gamepads are added, the dialog box can be shown and focused just like in the example above for Keyboard input.
To customize advance behavior, the AdvancePageInputPredicate delegate can be used to control DialogBox advancement. This method can be used to advance dialog box behavior using custom input or other conditions such as the completion of a tutorial. DialogBoxes must have focus or their AdvancePageInputPredicate will not apply.
The following code shows how to advance the page on a secondary click. Note that this code does not perform any additional logic, such as whether the cursor is over the DialogBox. This means that right-clicking anywhere on the screen advances the dialog.
As mentioned above, assigning AdvancePageInputPredicate prevents all other default page advance logic, so the user will not be able to advance the dialog with the keyboard, gamepads, or with a left-click on the DialogBox.
As mentioned in the section on DialogBox Input, Xbox360Gamepad and Keyboard input will only advance and dismiss the dialog box if IsFocused is set to true. This must be set explicitly to give the dialog box focus. Note that mouse clicks will advance the dialog box automatically even if the DialogBox's IsFocused is not set to true.
Typically IsFocused is set to true whenever dialog is displayed. When a DialogBox is dismissed, it is hidden and its IsFocused is set to false. This means that if multiple DialogBox pages are displayed one-after-another using ShowAsync
, IsFocused
must be set to true before each ShowAsync
call is performed, as shown in the following code:
The dismiss method can be used to visually remove a DialogBox and raise events as if it has been advanced. The Dismiss method performs the following logic:
Makes the DialogBox invisible (sets IsVisible to false)
Raises the PageAdvanced and FinishedShowing events
Clears all pages so that the dialog box can be used "fresh"
Removes focus (sets IsFocused to false)
HeightUnits of RelativeToContainer - the height unit depends on the container, so the height does not increase as more lines of Text are added.
Text Overflow Vertical Mode of Truncate Line - this prevents text from spilling over the bounds.
The OnScreenKeyboard, also referred to as a "software keyboard", can be used to enter text in a TextBox using a GamePad. Console games and games which use a controller as a primary input device will usually include some form of OnScreenKeyboard for text entry. Although the OnScreenKeyboard is primarily designed to be used with a GamePad, the mouse can also be used to click on the individual keys. The OnScreenKeyboard must always be paired with a TextBox. Creating an OnScreenKeyboard without pairing it to a TextBox will result in runtime exceptions when the user attempts to click on one of the keys.
Strictly speaking, the OnScreenKeyboard has no layout requirements - it can have any controls. However, to be functional, it must contain at least one object implementing ButtonBehavior. A typical keyboard will have many ButtonBehavior-implementing instances - one for each key. Buttons can be either buttons with special functionality or regular keys. A button is designated as being special by its name. The following names provide special functionality:
KeyBackspace - deletes the character before the caret
KeyReturn - currently not functional as of February 19, 2021, but will provide functionality in future versions
KeyLeft - moves the caret to the left one character
KeyRight - moves the caret to the right one character
KeySpace - inserts the space character at the current caret index
Any button which does not have one of the names listed above will insert the same character as its text into the text box. This behavior allows keyboards to be fully customizable - they can provide as many or as few characters as desired.
Note that although the diagram above displays buttons as direct children of the OnScreenKeyboard, buttons can be added as children of containers, and the hierarchy can be of any depth. All buttons will be recursively found and used by the keyboard.
The OnScreenKeyboard must be paired with a TextBox instance. Usually this is done by placing an instance of an OnScreenKeyboard in the same Screen or Component as a TextBox, and adding the following code in the initialization of the Forms object:
The code above assumes that the OnScreenKeyboard and TextBox are named KeyboardInstance and TextBoxInstance, respectively. Once this association is made, clicking on a key will modify the TextBox. Note that by default, the TextBox will lose focus when a button on the OnScreenKeyboard is clicked. This can be solved by setting the TextBox instance's LosesFocusWhenClickedOff to false.
As mentioned above, the OnScreenKeyboard requires an associated TextBox. The easiest approach for implementing an OnScreenKeyboard is to place both controls in a Gum page.
This implementation will create a matching Forms class. For example, if above is in GameScreenGum, then your project would have a class called GameScreenGumForms. This Forms class will contain both the Keyboard and TextBox so the setup can be performed as shown in the following code:
Alternatively, initialization can happen in the FlatRedBall Screen using the Forms object as shown in the following code snippet:
For this example, the following Gum layout will be used:
Note that the button will not be used except to show that tabbing to a different control is possible when the keyboard is not active. The following code enables full control of the text box with the gamepad:
The code above results in a fully functional keyboard controlled by the gamepad, as shown in the following animation: