Editor UI helper that builds property rows for a sidebar. It creates labeled rows, wide rows, and vector rows with per-axis float controls, arranging labels and controls with fixed label width or full-width controls as needed.
using Editor;
using Sandbox;
namespace RedSnail.WaterTool2.Editor;
/// <summary>
/// Property rows sized for the tool sidebar. The stock control sheet row keeps a wide label column next to a control
/// that asks for more room than the sidebar has, so the control runs off the edge. These rows give the label a short
/// fixed width and hand the control the rest, or put the label above a full-width control for the ones that need the
/// room (a resource picker), or one full-width field per axis for a vector.
/// </summary>
internal static class SidebarRows
{
private const float LabelWidth = 80.0f;
private const float Spacing = 4.0f;
/// <summary>
/// Label beside the control.
/// </summary>
public static Widget Add(Layout _Group, SerializedProperty _Property)
{
return AddRow(_Group, _Property, false);
}
/// <summary>
/// Label above the control, which then spans the sidebar.
/// </summary>
public static Widget AddWide(Layout _Group, SerializedProperty _Property)
{
return AddRow(_Group, _Property, true);
}
/// <summary>
/// A vector as its label followed by one full-width field per axis.
/// </summary>
public static Widget AddVector(Layout _Group, SerializedProperty _Property)
{
if (!_Property.TryGetAsObject(out SerializedObject components) || components is null)
return AddWide(_Group, _Property);
string tooltip = _Property.Description ?? _Property.DisplayName;
var block = new Widget
{
Layout = Layout.Column(),
ToolTip = tooltip
};
block.Layout.Spacing = 2.0f;
block.Layout.Add(new Label(_Property.DisplayName) { ToolTip = tooltip });
AddAxis(block.Layout, components.GetProperty("x"), Theme.Red, "X");
AddAxis(block.Layout, components.GetProperty("y"), Theme.Green, "Y");
AddAxis(block.Layout, components.GetProperty("z"), Theme.Blue, "Z");
_Group.Add(block);
return block;
}
private static void AddAxis(Layout _Layout, SerializedProperty _Axis, Color _Color, string _Badge)
{
if (_Axis is null)
return;
var control = new FloatControlWidget(_Axis)
{
HighlightColor = _Color,
Label = _Badge,
MinimumWidth = 0.0f,
HorizontalSizeMode = SizeMode.Flexible
};
_Layout.Add(control);
}
private static Widget AddRow(Layout _Group, SerializedProperty _Property, bool _Wide)
{
if (_Property is null)
return null;
var control = ControlWidget.Create(_Property);
if (control is null)
return null;
string tooltip = _Property.Description ?? _Property.DisplayName;
bool checkbox = _Property.PropertyType == typeof(bool);
control.MinimumWidth = 0.0f;
control.HorizontalSizeMode = SizeMode.Flexible;
control.ToolTip = tooltip;
// A checkbox is square; stretched it turns into a bar.
if (checkbox)
control.FixedWidth = Theme.RowHeight;
var label = new Label(_Property.DisplayName)
{
ToolTip = tooltip,
Alignment = TextFlag.LeftCenter
};
var row = new Widget
{
Layout = _Wide && !checkbox ? Layout.Column() : Layout.Row(),
ToolTip = tooltip
};
row.Layout.Spacing = Spacing;
if (_Wide && !checkbox)
{
row.Layout.Add(label);
row.Layout.Add(control);
}
else
{
label.FixedWidth = LabelWidth;
row.Layout.Add(label);
row.Layout.Add(control, checkbox ? 0 : 1);
if (checkbox)
row.Layout.AddStretchCell();
}
_Group.Add(row);
return row;
}
}