Editor UI widgets for the Metrify package. MeterFloatControlWidget renders a float property annotated with [Meters] as a float control labeled "m" and converting stored inches to metres visually. MeterVectorControlWidget renders a Vector3 with three axis float controls (x,y,z) each shown in metres and color-coded.
using Editor;
using Sandbox;
namespace Metrify;
/// <summary>
/// Draws a [Meters] float in metres, with an "m" suffix label.
/// </summary>
[CustomEditor( typeof( float ), WithAllAttributes = new[] { typeof( MetersAttribute ) } )]
public sealed class MeterFloatControlWidget : ControlWidget
{
public override bool SupportsMultiEdit => true;
private readonly FloatControlWidget _control;
public MeterFloatControlWidget( SerializedProperty property ) : base( property )
{
HorizontalSizeMode = SizeMode.CanGrow | SizeMode.Expand;
Layout = Layout.Row();
Layout.Spacing = 2;
_control = Layout.Add( new FloatControlWidget( new MeterFloatProperty( property ) )
{
Label = "m",
HighlightColor = Theme.Green,
ToolTip = "Metres — stored as inches (s&box world units)"
}, 1 );
}
public override void StartEditing() => _control?.StartEditing();
protected override void OnPaint()
{
// child widget paints itself
}
protected override void PaintUnder()
{
// nothing
}
}
/// <summary>
/// Draws a [Meters] Vector3 with each axis in metres.
/// </summary>
[CustomEditor( typeof( Vector3 ), WithAllAttributes = new[] { typeof( MetersAttribute ) } )]
public sealed class MeterVectorControlWidget : ControlWidget
{
public override bool SupportsMultiEdit => true;
private FloatControlWidget _first;
public MeterVectorControlWidget( SerializedProperty property ) : base( property )
{
HorizontalSizeMode = SizeMode.CanGrow | SizeMode.Expand;
if ( !property.TryGetAsObject( out var obj ) )
{
Log.Warning( $"[Meters] could not read {property.Name} as an object" );
return;
}
Layout = Layout.Row();
Layout.Spacing = 2;
_first = AddAxis( obj, "x", Theme.Red, "X" );
AddAxis( obj, "y", Theme.Green, "Y" );
AddAxis( obj, "z", Theme.Blue, "Z" );
}
private FloatControlWidget AddAxis( SerializedObject obj, string name, Color color, string label )
{
var axis = obj.GetProperty( name );
if ( axis is null ) return null;
var control = Layout.Add( new FloatControlWidget( new MeterFloatProperty( axis ) )
{
Label = label,
HighlightColor = color,
ToolTip = "Metres — stored as inches (s&box world units)"
}, 1 );
control.MinimumWidth = Theme.RowHeight;
control.HorizontalSizeMode = SizeMode.CanGrow | SizeMode.Expand;
return control;
}
public override void StartEditing() => _first?.StartEditing();
protected override void OnPaint()
{
// child widgets paint themselves
}
protected override void PaintUnder()
{
// nothing
}
}