s&box
13 September 2017

Dev Blog 3 - UI

How we're using HTML to create a modder friendly UI system
Garry Newman
Programmer
United Kingdom
Using HTML
We're using HTML for our UI right now. I've found that this is a pretty divisive thing to do, so let me explain our work flow and how we're trying to make it not suck asshole. As programmers we tend to think things like "I just want to draw some text to the screen, this is too much". That's a valid point if your entire game UI consists of writing a single string to the hud, don't use HTML. But there's a point where putting in a bit of extra work means a lot less work in the future.
Benefits
There's a few benefits to a HTML system.
  • You don't have to code your own UI system
  • You don't have to code your own Font system
  • You don't have to code your own Styles system
  • You don't have to code your own UI Animation system
  • You don't have to code your own Video system
  • HTML is already used everywhere
  • Lots and lots of tools to edit HTML
  • Styling is easy, fast, versatile
  • Animations are easy, fast
  • Effects like text shadow are easy, fast
  • Blur effects make you feel like 3017
  • Learning html/css/js is a transferable skill
  • Automatically multithreaded
  • Forced separation of view/model/controller
Component Based
After a bit of playing around I landed on a component system for s&box. So instead of making a big webpage and trying to maintain it, you create a lot of smaller components and make them work together. To do this we use vue, and a slightly modified version of their single file components. So lets take a simple example.

Health HUD

Show health and armour on the HUD.

C# Component

The managed component is responsible for providing the data for the UI. One of the things I was keen to do was minimize the amount of javascript you have to write, because ideally all of that logic is in c#, and you're just displaying data in html.
So as you can see this is setting the properties Health and Armour from the local player's health and armour every tick. We add this component when creating the main HUD (you can add new components at any point in time).

Vue file

The vue is a single file, but I'm going to break it down here.
The template section contains the html. The stuff in curly brackets are data. Notice how they have the same name as the properties in the c# file? That's because they're bound to them. Change the value on the managed side and it'll update those. The icons before each number are just material icons. The ":class=" part translates to "set the class "none" if Armour is lower or equal to 0". Then we have the style block, which is self explanatory if you already know css. Maybe daunting if you don't.
This sets the vitals class to absolute positioned. This means it won't show inline, it'll be positioned globally on the page somewhere. We're setting the left and bottom to 16px, so it'll show 16px from the bottom left corner. We set the display mode to flex. This is just to let us vertical align stuff better.
This is setting the style of any "div" elements inside the "vitals" class. Basic styling stuff, font size, color, alignment, spacing.
Remember we added that condition to add the "none" class if armour was 0? This says that any divs under "vitals" with the "none" class should have 20% opacity.
Hotloading
Like everything in s&box, it's completely hotloading. So you can sit in your editor on one monitor editing it and seeing the results in game instantly. Or you can be running around in the game and at any point open up the editor and make a tweak.
It's insanely easy, and insanely fun to play with.
Using Components
Components don't always have to have a managed counterpart. Lets turn the icon next to the health/armour into a component as an example. So we create a new file "icon.vue".
Template is the same. We define a "prop" (property) called type. We take that type and bind it as the class. So now we can update our health code to use the new component.
Notice the difference? We can now use <icon>. And everything works the same.
So this enables you to break down your UI into smaller reusable components. An example of a small reusable component is the steamavatar component.
Something worth noting is that these components can actually have managed components associated with them. That's right, you can create components in the template like this, and if it has a c# counterpart class named the same it'll create it.
Functions
Here's a cool example of using functions from our chatbox implementation. Our template looks like this.
So here we have an input box that pops up when you press enter in game. It looks like this.
Hopefully you can tell from the template that it has a model called "TextEntry" and when enter is pressed it calls "SendMessage". In its managed component, it has this.
[TwoWay] means that it can be updated by html. This means that when you type into the input box it changes the value on the managed side, like magic. We also have a function..
Boom.
Summary
As you can tell this is something that excites me. I've done a lot of UI stuff in the past. I've made my own UI libraries multiple times, in multiple different languages, I've used other engines proper UI libraries. Using HTML for this seems like a no brainer to me. But there are definite challenges to it. The difficulty in getting data between the game and the html is probably the biggest one. Then you have the problems with educating people to use the system. I can imagine that html, css, javascript are all totally daunting if you've never used them before. I've been using them for over 15 years so it comes really naturally and is probably something I take for granted. But like I said earlier, it's a totally transferable skill, there's a whole world full of resources to learn from. Having a HTML renderer in game allows us to connect to our console, and show that in game too :)