tsg radial
Documentation about the features and usage of the tsg radial template used to create Radial Menus.

tsg radial
is a scripting module template that simplifies the creation of Radial Menus. The method used for creating the Radial Menus is efficient and allows for intuitive navigation between multiple categories or even separate Radial Modules.
Bookmark the mode prefab below or find the it through the in-game UGC browser by searching with keywords or tags.
Features
A showcase of the radial menu template features and how to modify them to suit your Radial Menu.
Opening a Menu
In tsg radial
a Menu is opened by calling a Custom Event, Global
associated with the desired Menu. The standard for opening Radial Menus is either with the Custom Input key, or by interacting with a switch on the level.


The events for opening a Menu rely on the following parameters:
Identifier: A custom name for the event; suggested to use the naming pattern:
radial{Digit 1}_{category}
as it helps you keep track of what radial belongs whereObject: The player who the Menu should be shown to
Number: A 4-digit number value containing information about the Menu; used for determining which menu to return to when navigating backwards
Digit 1: Radial Module
Digit 2: Radial Category
Digit 3: Radial Page
Digit 4: Menu Item
Having these number values consistent between all Custom Events that open Menus is crucial for the script module to function correctly.


Menu creation
Each menu in tsg radial
is built right before the menu is shown to the player. This way the most updated information can be shown on the menu, and the code used for creating the menu is all in the same place for efficiency.

Menu Items
Radial Menus consist of a maximum 8 Menu Items (selectable sectors) per Menu, which each must be declared in the code so display the desired Title, Description, Icon and Enabled state. The Title and Description utilize a Create UI Message
node, and the Icon and Enabled state are set by opening the properties of the Menu Item
node.

Each Menu Item is fed into a Generic List
running through a For Each Generic Item
loop that adds each Menu Item to the Menu at the index where it shows up in the Generic List. A blank Menu Item can be created by picking a new Menu Item node, leaving the Icon selection as empty, and making the Enabled state False.


Menu Variables
Menu Variables are the core of each Menu. These must be declared via the Declare Menu Variable
node before Menu Items can be assigned to them.
The Menu Variables follow these parameters:
Identifier: A custom name for the Menu; suggested to use the exact same naming pattern:
radial{Digit 1}_{category}
as used for theCustom Event, Global
for creating the Menu as it's more streamlinedScope: Global
Optimally object-scope should be used for player-based menus, but a current bug is preventing object-scoped menus from functioning correctly


Displaying the Menu
After the menu has been built, it's shown to the player in that state using the Show Menu To Player
node. With tsg radial
if another player opens the same menu shortly after with their own building parameters, the previous player's Menu will not be affected.


Logging the Menu
After a Menu is displayed to a player, its Number value is stored at the end of a Generic List named previousMenuValues
. This list is used to look up previous Menus the player has been shown to determine which Menu to navigate back to when closing a Menu. This custom Menu history tracking allows for complex nested Menus to feel intuitive navigating in and out from.
Also a Boolean Variable radialOpen
is set to True, which is used elsewhere to track whether the player has a Menu open or not, as this is not natively tracked.

Menu forwards navigation
The Menu can be navigated with the controller movement stick, mouse movement, or keyboard WASD keys and various inputs for selecting the Menu Items. Selecting a Menu Item will take you to a separate Menu or result in an action such as being granted a weapon.



Menu Item selection
When a Menu Item is selected, a comparison is done to determine which menu the selection was made from. If the Menu where a selection made matches a Menu in the comparison tree, a Custom Event, Global
is fired with data that is used to determine which item was selected.
Also a Boolean Variable radialOpen
is set to False, which is used elsewhere to track whether the player has a Menu open or not, as this is not natively tracked.

The reason why the On Menu Item Selected
node is immediately being turned into a Custom Event, Global is so the comparison tree can be continued on another Script Brain. Below is an example on how to do so:

On Menu Item Selected
Custom Event.
The event for the item selection relies on the following parameters:
Identifier: A custom name for the event; suggested to use nearly the same naming pattern:
radial{Digit 1}_{category}-select
as used for theGet Menu Variable
for comparing the Menu as it's more streamlinedObject: Player who made the Menu Item selection
Number: The index of the selected Menu Item

Selection event
The filtered selection event leads into a function that determines what to do based on which index Menu Item was selected. The function uses a simple comparison tree with an optimized amount of Compare nodes to cover all values from 1-8. Comparing for 8 values is not necessary if the menu contains less selectable Menu Items to begin with.




Menu backwards navigation
tsg radial
has a custom menu history system where closing a Menu by pressing the Cancel button in the center of each radial will take you to the previous Menu you were in. This feature can be disabled if necessary, but is a very useful feature in large menus with multiple categories.



Menu closing filter
When a Menu is closed, the custom value of the closed Menu is removed from the previousMenuValues
list, and it's checked whether the last item in the list is a valid number. If so, the 4-digit number value is filtered through various checks in order to open the correct Menu for the player. This Menu would be the previous Menu the player had been in.
Digit 1 is filtered to determine which Radial Module the Menu belongs in, and a Custom Event, Global
corresponding to the Radial Module is fired. Radial Modules are meant to represent entirely different Radial Menus, each with their own set of nested Menus for example. The 4-digit Menu logging system in tsg radial
supports 9 separate Radial Modules which should be plenty.

The event for the Menu filtering relies on the following parameters:
Identifier: A custom name for the event; suggested to use the naming pattern:
menuClose_radial{Digit 1}
as it helps you keep track of which Radial Module is being processedObject: Player who closed the Menu
Number: The remaining 3-digit number value after the first filtered value has been excluded

Then the second, third and fourth digits are filtered to determine the exact Menu that should be shown to the player.
Digit 2 determines the Radial Category. If the desired Menu has no nested menus, the Selection event for that Menu is fired with Digit 4 fed into the Number value of the event.
Digit 3 determines the Radial Page. If the desired Menu has a nested menu, a branch is created that compares which page matches the comparison. The same Selection event for the desired Menu is fired as before.
Digit 4 determines the Menu Item or the Menu itself. In this pattern this value is usually 0, which is used in the Selection event only for this purpose to return the desired Menu to the player.


Here's an example following how the value 110
is filtered:

110
is processed in the Menu filtering eventBackground events
The essential background events that serve as the foundation for some features of tsg radial
. These events should be left untouched when using the scripting module.
Initialization events and declarations
Custom Events created to ensure smooth timing and predictable execution of the rest of the code.

Declarations for all variables and traits in one place. More variable declarations are needed when new Menu Variables are used.

Menu state events
Essential events for tracking if a player has a Menu open, logging the menu values, and ways of forcefully closing the menu.




Example setups
Examples of using tsg radial
to make various types of Menus.
Value update on Menu open
Object-based values can be fed into the Create UI Message
nodes in order to alter what values show up in the Menu messages. These values update each time the event is called to open the Menu.
This Menu example also features a button-like Menu Item that reopens the same Menu after selecting the Menu Item at index 1 so the same Menu Item can be quickly pressed multiple times.


A menu for toggling Skulls where the description of each Menu Item is updated based on if the Skull is enabled or not. First the Menu Items are added to the Menu, and then the Enabled state of them is re-evaluated with a separate for-loop that updates the Menu Item descriptions.
When any Menu Item in this Menu is selected, the same Menu is returned to the player to make the menu act in a button-like manner in addition to toggling the selected Skull.



Variable Enabled state values
By feeding a comparison output Boolean into the Enabled state property of a Menu Item, Menus can be built that display items in enabled or disabled states based on if the player meets the criteria for them to be selectable. In this example the player has enough points to spawn an allied Elite squad, but not a Brute squad.



tsg radial-example
A display of more example setups covering nearly everything tsg radial
is capable of can be found in the module variant tsg radial-example
. Bookmark the mode prefab below or find the it through the in-game UGC browser by searching with keywords or tags.

tsg radial-machinima
A Machinima control Radial Menu built from tsg radial
. Options for Camera Mode toggle, Weapon lowering, Fists and empty Sword grant, Fly mode toggle and item grants. Can be loaded as a standalone mode on any map. Bookmark the mode prefab below or find the it through the in-game UGC browser by searching with keywords or tags.
This Menu Module also contains examples of granting every type of weapon, equipment, vehicle and grenade.
Trivia
Bug workarounds
There's a few mentions of some features in tsg radial
being workarounds for bugs, so here's an explanation of all of them. Some of them are known issues listed by Halo Studios which are found here.
Only one node instance working
Using any of the nodes listed below more than once will result in only one instance of the node functioning:
On Custom Input Tap
On Custom Input Hold
On Menu Item Selected
On Player Started Sprinting
On Player Stopped Sprinting
The workaround for this is to immediately turn the node into a Custom Event, Global Async
that serves the same purpose and can be used in multiple scripts. In tsg radial
this is done with the nodes: On Custom Input Tap & On Menu Item Selected.


Unprompted Menus displaying for players
Radial menus may appear during gameplay without players invoking them.
The workaround for this isn't mentioned in the documentation as it's a stealthy fix, but all that's required is to disable the visibility of the current Menu using the Show Menu To Player
node right after the On Menu Item Selected
& On Menu Close
nodes.


Menu Item selection doesn't work
Selecting a Menu Item from a global-scoped Menu that has been disabled after the Menu has been shown to the player doesn't prompt a Menu Item selection.
This is not a bug, but something we have to workaround as object-scoped Menus are broken in their own ways currently, requiring us to use global-scoped menus. For the workaround, all of the Menu Items in the Menu that was just shown to the player are set to Enabled so issues don't arise for anyone who had the Menu previously open.

Undetected Menu closing
Opening two instances of the same global-scoped Menu simultaneously may close one instance of the Menu.
Another workaround required when working with global-scoped Menus since all players are trying to access the same global-scoped menu, some player may get caught in the process of the menu being built for some other player, and have the Menu just not show up for them when prompted.
What this results in is the custom tracking for radialOpen
still being True cause it's assumed that the Menu got shown, but now the player is stuck with the movement locking traits. The workaround is a fallback to remove said traits by just changing the aim rotation, which is often the first thing players will do when they want to start moving again.
It's also convenient that you can't change your aim rotation while a Menu is open, so it works as a good fallback for removing the traits if something else were to prompt the Menu closing without the scripting catching on.

Known Issues
A list of known issues that couldn't be fixed:
Two players opening the same Menu at the simultaneously may often result in one player's Menu not displaying.
Two players opening the same Menu at the simultaneously may rarely result in one player's Menu displaying for the other player.
Two players opening the same Menu at the simultaneously may rarely result in one player's Menu showing all Menu Items in the Enabled state.
Navigation between nested Menus becomes slower with latency to the server.
Contributors
Okom
Last updated