Sandbox Logo
02 June 2023

UI Improvements

We have improved the UI system! Again!
We have support for CSS masks now. These allow you to adjust the transparency of a panel independently from its contents.

You can use these to give UIs some nice polish - here's a quick example showing how you can fade a section to show that it's scrollable:
Other use cases include pie menus, scroll indicators, loading wheels, etc.

We support the main mask properties:
mask-image: url( /ui/tests/background.png ); mask-mode: alpha; mask-size: 256px; mask-position: center; mask-repeat: no-repeat;
Or, if you prefer, you can use the "mask" shorthand:
mask: linear-gradient( to top, white, black ) center bottom / 100% 100px;
We also have our own custom "mask-scope" property. This lets you apply the mask to a specific set of filters, which can be useful if you only want to blur a certain area.
mask-image: url( /ui/tests/alpha-inv.png ); mask-mode: alpha; mask-scope: filter; mask-size: cover; filter-blur: 10px; filter-brightness: 0.25;
We've added support for drawing SVGs in UI.  These can draw pixel perfect images no matter what size you tell it to be.


SVGs can be painted whatever color they're told to be or fall back to the defaults defined in the file.  This is useful for icons.


We now have support for RenderFragments in our Razor style templates.

RenderFragments allow you to capture a bit of UI in a function, and place it wherever you want.  For example, you might define a component like this.
<root> <div class="header">@Header</div> <div class="body">@Body</div> <div class="footer">@Footer</div> </root> @code { public RenderFragment Header { get; set; } public RenderFragment Body { get; set; } public RenderFragment Footer { get; set; } }
Which you'd be able to use like this:
<InfoCard> <Header>My Card</Header> <Body> <div class="title">This is my card</div> </Body> <Footer> <div class="button" onclick="@CloseCard">Close Card</div> </Footer> </InfoCard>
Things get a lot more exciting when you start mixing it with generics and context arguments, you can read more about that here. Once you get the hang of this stuff there isn't a lot of UI stuff you can't really easily make.

<TableComponent T="TypeDescription" Items="@TypeList">

<Header>Type Descriptions</Header>

<Row Context="">

@if (context is not TypeDescription a)
return;

<span>@a.TargetType</span>
<span>@a.Title</span>

</Row>

</TableComponent>
We added WebSurface UI elements that can be used in both the game and the editor.

Under the hood, these are using Steam's HTML renderer, so code weight wise it's pretty much free - because it's just APIs in Steamworks. I was actually pleasantly surprised with how well it works now, having played with it a while ago and not having much luck.

You can render these to a texture too, so it's feasible for things like in-game computers etc. The only real problem with that is we have no control over the sound in terms of making it come from the 3D world or adjusting its volume.
You can now click and drag to scroll around. This has also created a couple of Panel APIs that should enable creating dragging and dropping systems relatively easily, although we'll add official support for that at some point.


Panels can scroll horizontally now too. We support overflow, overflow-x and overflow-y styles.