-
Notifications
You must be signed in to change notification settings - Fork 12
Generic context menu
The Generic Context Menu is an MVC controller designed to manage all instances of context menus. Its primary objective is to provide a unified mechanism for rendering context menus across Decentraland. This ensures visual consistency and allows the menus to respond dynamically to real-time values, such as feature flags, without requiring the creation of new prefabs for each instance.
Like other MVC controllers, it is invoked by issuing a command through the mvcManager
:
mvcManager.ShowAsync(GenericContextMenuController.IssueCommand(new GenericContextMenuParameter()))
The minimal parameters required are:
- A reference to the configuration class (
GenericContextMenu
). - A
Vector2
specifying the anchor position of the context menu.
Additional optional parameters include:
- A
Rect
that defines the usable space for the context menu (default is the full viewport). This parameter ensures that the menu's position avoids overlapping with the defined rectangle. - An action triggered when the context menu is shown.
- An action triggered when the context menu is closed.
- A task that, upon completion, closes the context menu (clicking outside the menu also closes it).
Currently, the following basic components are available:
- Button with text and icon (
ButtonContextMenuControlSettings
) - Toggle with text (
ToggleContextMenuControlSettings
) - Graphical separator (
SeparatorContextMenuControlSettings
) – A simple grey line used as a divider. - User profile info (
UserProfileContextMenuControlSettings
) - Presents name, claimed name badge and user address similar to the user Passport
Each component comes with its own set of configuration parameters. Default graphical settings are provided but can be overridden as needed. The minimum required parameters are those specific to the component (e.g. for a button are: text, sprite and an action).
Some components, like the toggle, support initial values. These can be set in their respective settings class before the context menu is invoked.
Here is an example of how the context menu can be configured and used.
GenericContextMenu contextMenu = new GenericContextMenu()
.AddControl(publicToggleSettings = new ToggleContextMenuControlSettings(
view.publicToggleText,
toggleValue => SetPublicRequested?.Invoke(currentReelData, toggleValue)))
.AddControl(new SeparatorContextMenuControlSettings())
.AddControl(new ButtonContextMenuControlSettings(
view.shareButtonText,
view.shareButtonSprite,
() => ShareToXRequested?.Invoke(currentReelData)))
.AddControl(new ButtonContextMenuControlSettings(
view.copyButtonText,
view.copyButtonSprite,
() => CopyPictureLinkRequested?.Invoke(currentReelData)))
.AddControl(new ButtonContextMenuControlSettings(
view.downloadButtonText,
view.downloadButtonSprite,
() => DownloadRequested?.Invoke(currentReelData)))
.AddControl(new ButtonContextMenuControlSettings(
view.deleteButtonText,
view.deleteButtonSprite,
() => DeletePictureRequested?.Invoke(currentReelData)));
publicToggleSettings.SetInitialValue(cameraReelResponse.isPublic);
mvcManager.ShowAsync(GenericContextMenuController.IssueCommand(
new GenericContextMenuParameter(
contextMenu,
buttonRectTransform.position,
actionOnShow: () => isContextMenuOpen = true,
actionOnHide: () =>
{
isContextMenuOpen = false;
if (view.gameObject.activeSelf)
HideControl();
},
closeTask: closeContextMenuTask?.Task)));
We need to create a class that implements IContextMenuControlSettings
where all the available configs are stored, suchs as:
- UI tweaks
- Action to execute on interaction
- configuration data (e.g. the initial boolean value in toggle component)
This is also a good place to create a method that lets you set the initial data, since this instance can be stored upon creation of the context menu itself.
We need to create a class that behaves as the View of our component. This class must inherit GenericContextMenuComponentBase
and will hold the references of all the GameObjects
we need to use in our component.
The superclass will force us to implement two methods:
-
UnregisterListeners
: will be called upon disable, therefore it's were we can remove all listeners registered to our components -
RegisterCloseListener
: it is called on setup and provides anAction
that closes the context menu itself, therefore we will register it on every interactable component that upon interaction, we want them to trigger the menu close.
This class is the perfect place to create a configuration method that has our control settings as parameter so that we can apply our configurations.
We also need to manage our new component inside the pool manager. We therefore need to create a new IObjectPool
for our new View type.
We finally need to manage the Get
and Release
action of the new component. This is done inside the GetContextMenuComponent
function where we have access to its settings.
As for the release we just need to manage the new type inside ReleaseAllCurrentControls
.
We finally need only to create our new prefab for our control that will have the new View component attached.
Once it is completed we need to extend the GenericContextMenuPlugin.cs
plugin to reference and load the new prefab. Remember to also assign it in the Global Plugins Settings
asset file.