UI/Controls/ClientInputControl.cs
namespace Sandbox.UI;
[CustomEditor( typeof( ClientInput ) )]
public partial class ClientInputControl : BaseControl
{
Panel _preview;
InputHint _inputHint;
IconPanel _fallbackIcon;
Label _bindLabel;
public override bool SupportsMultiEdit => true;
public ClientInputControl()
{
_preview = AddChild<Panel>( "preview" );
_inputHint = _preview.AddChild<InputHint>( "hint" );
_fallbackIcon = _preview.AddChild<IconPanel>( "fallback" );
_fallbackIcon.Text = "keyboard";
_bindLabel = AddChild<Label>( "bind-label" );
}
public override void Rebuild()
{
if ( Property == null ) return;
var action = Property.GetValue<ClientInput>().Action;
if ( string.IsNullOrWhiteSpace( action ) )
{
_inputHint.Action = null;
_inputHint.SetClass( "hidden", true );
_fallbackIcon.SetClass( "hidden", false );
_bindLabel.Text = "No Binding";
SetClass( "no-binding", true );
return;
}
_inputHint.Action = action;
_inputHint.SetClass( "hidden", false );
_fallbackIcon.SetClass( "hidden", true );
SetClass( "no-binding", false );
var match = Input.GetActions().FirstOrDefault( a => a.Name == action );
_bindLabel.Text = match != null ? (match.Title ?? match.Name) : action;
}
protected override void OnClick( MousePanelEvent e )
{
base.OnClick( e );
var menu = Sandbox.MenuPanel.Open( this );
menu.AddOption( "", "No Binding", () => OnBindChanged( "" ) );
menu.AddSpacer();
var grouped = Input.GetActions()
.GroupBy( a => a.GroupName ?? "" )
.OrderBy( g => g.Key );
foreach ( var group in grouped )
{
if ( string.IsNullOrWhiteSpace( group.Key ) )
{
foreach ( var action in group )
{
var a = action;
menu.AddOption( "", ActionLabel( a ), () => OnBindChanged( a.Name ) );
}
}
else
{
var groupActions = group.ToList();
menu.AddSubmenu( "", group.Key, sub =>
{
foreach ( var action in groupActions )
{
var a = action;
sub.AddOption( "", ActionLabel( a ), () => OnBindChanged( a.Name ) );
}
} );
}
}
}
string ActionLabel( InputAction a )
{
var title = !string.IsNullOrEmpty( a.Title ) ? a.Title : a.Name;
var origin = Input.GetButtonOrigin( a.Name );
return origin != null ? $"{title} ({origin})" : title;
}
void OnBindChanged( string value )
{
var current = Property.GetValue<ClientInput>();
current.Action = value;
Property.SetValue( current );
// tony: when setting Action in current, and setting the value, the property changed event doesn't show the updated action
// not too sure why
foreach ( var target in Property.Parent?.Targets ?? Enumerable.Empty<object>() )
{
if ( target is Component component )
GameManager.ChangeProperty( component, Property.Name, current );
}
Rebuild();
}
}