UI/ContextMenu/IContextMenuEvent.cs
/// <summary>
/// Lets scene components and systems add actions to an object's right-click menu.
/// Options are collected with a sort order (lower is higher in the menu), then the Inspector builds the menu.
/// The built-ins use 100 (Ignite/Extinguish), 200 (Delete) and 300 (Break); the default of 0 lands above them.
/// </summary>
public interface IContextMenuEvent : ISceneEvent<IContextMenuEvent>
{
public sealed record Option( string Icon, string Text, Action Action, Action<Sandbox.UI.Menu> SubmenuBuilder, int Order );
public sealed class Event( GameObject target )
{
/// <summary>
/// The network root of the object that was right-clicked.
/// </summary>
public GameObject Target { get; } = target;
private readonly List<Option> _options = new();
/// <summary>
/// Options collected so far, sorted by order. Stable, so options sharing an order keep insertion order.
/// </summary>
public IEnumerable<Option> Options => _options.OrderBy( o => o.Order );
public void AddOption( string icon, string text, Action action, int order = 0 )
{
_options.Add( new Option( icon, text, action, null, order ) );
}
public void AddSubmenu( string icon, string text, Action<Sandbox.UI.Menu> builder, int order = 0 )
{
_options.Add( new Option( icon, text, null, builder, order ) );
}
/// <summary>
/// Build the collected options into a menu.
/// </summary>
public void Populate( Sandbox.UI.Menu menu )
{
foreach ( var option in Options )
{
if ( option.SubmenuBuilder is not null )
option.SubmenuBuilder( menu.AddMenu( option.Text, option.Icon ) );
else
menu.AddOption( option.Text, option.Icon, option.Action );
}
}
}
void PopulateContextMenu( Event e ) { }
}