S&box Wiki

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" />