Revision Difference
UI#544628
<cat>Dev.UI</cat>
<title>UI Basics</title>
# Basics
UI entities are implemented using HTML and/or C#. Entities can be styled using SCSS, a preprocessor scripting language that is interpreted/compiled into Cascading Style Sheets (CSS). This is done out of the box.
# Simple UI (static or hybrid)
For static entities without any dynamic component (static banner, simple non-changing crosshair, etc.) HTML UI might be sufficient.
You can still reference C# classes within the HTML using regular HTML-Tags. The referenced C# classes can still react dynamically to the game loop.
## Example: Static crosshair w/ dynamic C# chatbox
```html
<link rel="stylesheet" href="minimalhud.scss">
<div>
<text class="title">My Minimal Game</text>
<!-- A crosshair in just css -->
<div style="position: absolute; left: 50%; top: 50%; background-color: white; border-radius: 10px; width: 4px; height: 4px; transform: translate( -50% -50% );"></div>
<chatbox></chatbox>
</div>
```
Source: [sbox-minimal - MinimalHud.html](https://github.com/Facepunch/sbox-minimal/blob/293768fa6d16ccdc57b777d8d8a70177a65f78ac/code/MinimalHud.html)
# Advanced UI (dynamic)
For more complex scenarios (e.g. HUD's) a UI implementation using C# is recommended (and probably the only good solution).
UI components can be implemented using the abstract class `Panel`. This abstract class has a method `override void Tick()` so you can access the game loop.
UI components can either be mounted directly or through other UI Components using `RootPanel.AddChild<E>();`. Usually done in the constructor of the class.
To add (S)CSS to the components, simply use `RootPanel.StyleSheet.Load( "/ui/PATH_TO_SCSS.scss" );` in the constructor.
## Example: HUD w/ health display
Down below you can see an example from the sandbox gamemode.
`SandboxHud` implements the `HudEntity<RootPanel>` class and loads a stylesheet and all other UI components.
The `Health` class implements `Panel` and adds a bunch of stuff to the UI within its constructor.
It also has access to the local player's health within the `Tick`-override, so the UI can be updated accordingly.
```cs
using Sandbox;
using Sandbox.UI;
[Library]
public partial class SandboxHud : HudEntity<RootPanel>
{
public SandboxHud()
{
if ( !IsClient )
return;
RootPanel.StyleSheet.Load( "/ui/SandboxHud.scss" );
RootPanel.AddChild<NameTags>();
RootPanel.AddChild<CrosshairCanvas>();
RootPanel.AddChild<ChatBox>();
RootPanel.AddChild<VoiceList>();
RootPanel.AddChild<KillFeed>();
RootPanel.AddChild<Scoreboard<ScoreboardEntry>>();
RootPanel.AddChild<Health>();
RootPanel.AddChild<InventoryBar>();
RootPanel.AddChild<CurrentTool>();
RootPanel.AddChild<SpawnMenu>();
}
}
```
Source: [sandbox - SandboxHud.cs](https://github.com/Facepunch/sandbox/blob/0ae8ada7fae4b3876fd3d82d0385fa72dbacbf6f/code/ui/SandboxHud.cs)
```cs
using Sandbox;
using Sandbox.UI;
using Sandbox.UI.Construct;
public class Health : Panel
{
public Label Label;
public Health()
{
Add.Label( "🩸", "icon" );⤶
Label = Add.Label( "100", "value" );
}
public override void Tick()
{
var player = Local.Pawn;
if ( player == null ) return;
Label.Text = $"{player.Health:n0}";
Label.Text = $"{player.Health.CeilToInt()}";
}
}
```⤶
Source: [sandbox - Health.cs](https://github.com/Facepunch/sandbox/blob/0ae8ada7fae4b3876fd3d82d0385fa72dbacbf6f/code/ui/Health.cs)
⤶
```⤶
Source: [sandbox - Health.cs](https://github.com/Facepunch/sandbox/blob/69b8565a78b646520c47463a33ee2fa85d726762/code/ui/Health.cs)
# Tips
- If editing a Panel's style in code, use `Panel.Style.Dirty()` or you will not see those changes.