gotchas¶
common surprises and their fixes.
host panel width doesn't fill the screen¶
setting Width = Length.Percent(100) on your root container does not fill the screen. the engine creates GooPanel.Panel (the host that goo reconciles into) with an undefined width, and percent of undefined collapses to undefined in yoga's layout. height happens to stretch via the parent's cross-axis rule, so the issue only bites the width axis. this catches every hud-builder on day one.
the fix is to style the host panel itself in OnEnabled:
using Goo;
using Sandbox.UI;
namespace Sandbox;
public class MyHud : GooPanel<Container>
{
protected override Container Build() => new Container
{
BackgroundColor = Color.White,
// your content here
};
protected override void OnEnabled()
{
base.OnEnabled();
Panel.Style.Width = Length.Percent(100);
Panel.Style.Height = Length.Percent(100);
}
}
Panel is the engine host that GooPanel reconciles into. calling base.OnEnabled() keeps goo's per-enable bookkeeping running.
this is intentional. goo doesn't size the host panel for you because filling the screen is one valid choice and a content-sized tooltip is another. picking either as a forced default makes the other harder.
container can't be a static field or held across rebuilds¶
Container rents pooled storage when you construct it, and the pool is only alive during a Build() call. two things to avoid:
// breaks at static init.
private static readonly Container Card = new Container { ... };
// breaks on the second build.
private Container _root;
protected override Container Build()
{
_root ??= new Container { ... };
return _root;
}
both throw InvalidOperationException with a message pointing here.
the reusable unit in goo is the function that builds a container, not the container itself. same model as react: you don't keep <div> literals in fields, you keep the function that returns one.
public class MyHud : GooPanel<Container>
{
protected override Container Build() => new Container
{
Card("hello"),
Card("world"),
};
static Container Card(string text) => new Container
{
Padding = 12,
BackgroundColor = Color.White,
new Text(text),
};
}
helpers can live in other files, other classes, anywhere. as long as they're called transitively from Build(), the pool is active and everything works.