Revision Difference
UI#548180
<cat>UI.Intro</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 Static UI⤶
⤶
For static UIs where nothing is dynamically changed (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> ⤶
```⤶
⤶
# Hybrid UI⤶
⤶
A hybrid UI will give you the readability of HTML and CSS whilst allowing you to also leverage the power of C#.⤶
⤶
If you wanted to interact with the above template in C#, you might save it as MinimalHUD.html, and then create another file called MinimalHUD.cs. Add the UseTemplate attribute to the file and it will automatically pair itself with the .html file.⤶
⤶
```cs⤶
⤶
There's 2 good ways to make UI right now in s&box. You can either use [Razor](https://wiki.facepunch.com/sbox/ui-razor), or make Panels yourself. We recommend using [Razor](https://wiki.facepunch.com/sbox/ui-razor).⤶
⤶
# Making a Panel⤶
⤶
Here's an example panel that has a Label which counts up forever.⤶
⤶
## MyPanel.cs⤶
```cs⤶
[UseTemplate]
public class MinimalHUD : RootPanel⤶
public class MyPanel : Panel⤶
{
// Do stuff.
public Label MyLabel { get; set; }
⤶
public override void Tick()⤶
{⤶
Label.Text = $"{Time.Now}";⤶
}⤶
}
```
⤶
To reference stuff from C#, use the ref attribute:⤶
⤶
```html⤶
<Label @ref="MyTimerLabel">0</Label>⤶
⤶
`[UseTemplate]` will load a template with the same class name (`MyPanel.html`).⤶
⤶
## MyPanel.html⤶
```html⤶
<link rel="stylesheet" href="MyPanel.scss"/>⤶
⤶
<div>⤶
<label class="name" @ref="MyLabel">Placeholder Text</label>⤶
</div>⤶
```
⤶
```cs⤶
public Label MyTimerLabel { get; set; } // This must be a property.⤶
⤶
[Event.Tick]⤶
public override void Tick()⤶
{ ⤶
MyTimerLabel.SetText( Sandbox.Time.Now.ToString() ); ⤶
}⤶
⤶
`<link rel="stylesheet" href="MyPanel.scss"/>` will load a stylesheet with the file name that you specify. It works on relative paths from your `.html` file.⤶
⤶
## MyPanel.scss⤶
```
⤶
S&Box supports some GUI elements in both HTML mark-up and C#. For example:⤶
⤶
```html⤶
<Panel class="my-panel">⤶
<Image src="/materials/ui/cool_image.jpg"></Image>⤶
<Label>This is my cool image</Label>⤶
</Panel>⤶
```⤶
⤶
# Creating UI⤶
⤶
To create a UI all you need to do is create an instance of your UI class on the clientside.
⤶
```cs⤶
⤶
[ClientRpc]⤶
public void CreateUI() {⤶
var ui = new ExampleUserInterface();⤶
MyPanel {⤶
position: absolute;⤶
left: 64px;⤶
top: 64px;⤶
⤶
.name {⤶
font-family: Poppins;⤶
color: white;⤶
font-size: 32px;⤶
}
}
```
⤶
# Tips and Tricks⤶
⤶
- You can set Panel classes - See [Panel.SetClass](https://asset.party/api/Sandbox.UI.Panel.BindClass(string,Func)), and [Panel.BindClass](https://asset.party/api/Sandbox.UI.Panel.SetClass(string,bool))⤶
⤶
- If a panel is not behaving as expected you can troubleshoot it using the Panel Inspector. While in Editor Mode, open the Explorer and hit Panels.⤶
⤶
<upload src="97/8dacf630b9f409d.png" size="32067" name="image.png" />⤶
# Dynamic UI⤶
⤶
For more complex scenarios where you want to dynamically change elements, use of C# will be necessary. A pure C# UI is also quicker to prototype. However, it can quickly become spaghetti code if abused.⤶
⤶
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. ⤶
# Examples⤶
⤶
<warning>These examples may be obsolete.</warning>⤶
⤶
## Example: HUD w/ health display⤶
⤶
Down below you can see an example from our [Sandbox](https://github.com/facepunch/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⤶
⤶
```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()
{
Label = Add.Label( "100", "value" );
}
public override void Tick()
{
var player = Local.Pawn;
if ( player == null ) return;
Label.Text = $"{player.Health.CeilToInt()}";
}
}
```
Source: [sandbox - Health.cs](https://github.com/Facepunch/sandbox/blob/69b8565a78b646520c47463a33ee2fa85d726762/code/ui/Health.cs)
## Example: Interacting with UI
We are able to interact with the stylesheet from the c# file. We can for exemple
- AddClass to a panel/Label
- RemoveClass to a panel/Label
In the exemple below we are removing the health hud if the player is in a car by using
`(Panel, Label or this).AddClass(string classname)` and `(Panel, Label or this).RemoveClass(string classname)`.
```cs
using Sandbox;
using Sandbox.UI;
using Sandbox.UI.Construct;
public class Health : Panel
{
public Label Label;
public Health()
{
Label = Add.Label( "100", "health-label active" );
}
public override void Tick()
{
var player = Local.Pawn;
if ( player == null ) return;
if (player.Health.CeilToInt() == -1)
{
Label.RemoveClass("active")
}
else
{
Label.AddClass("active")
}
Label.Text = $"{player.Health.CeilToInt()}";
}
}
```
```
.health-label
{
position: absolute;
background-color: rgba( black, 0.5 );
right: 100px;
bottom: 48px;
font-size: 40px;
font-weight: bold;
color: white;
height: 80px;
padding: 0 20px;
align-items: center;
opacity: 0;
&.active {
opacity: 1;
}
}
```
⤶
# Troubleshooting Panels⤶
⤶
If a panel is not behaving as expected you can troubleshoot it using the Panel Inspector. First, in the S&box editor, make sure the Panel Inspector is enabled by ticking View->Panels.⤶
⤶
<upload src="b0cef/8da8cf24eac2629.png" size="13513" name="image.png" />⤶
⤶
If you run the game in the editor you will then be able to inspect panels in real-time.⤶
⤶
<upload src="b2aa2/8daccc0cbeaf23d.png" size="337442" name="image.png" />