Skip to content

Commit 94ba639

Browse files
author
Ross Lombardi
committed
updated my author stuff, additional text changes cuz I can't help myself;
1 parent c2d9553 commit 94ba639

File tree

2 files changed

+41
-20
lines changed

2 files changed

+41
-20
lines changed

blog/2025/2025-10-19-uis-are-hard/index.md

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,18 @@ authors: ['domiran']
77
tags: ['ui', 'opengl', 'article']
88
image: 'ui-overview.png'
99
---
10-
If you're like me, you've thought to yourself at least once: "Hey, making a UI can't be that hard! I wouldn't need to add any more headers or libraries to my project!" Because not having to deal with C++ is a good reason to write your own UI. Well, I did it. What came out the other end is a confusing mixture of knowledge, a lot of head-bashing, years of code that went sideways more than once, and a working UI for a functioning game. Let's see how it works, shall we?
10+
If you're like me, you've thought to yourself at least once: "Hey, making a UI can't be that hard! I wouldn't need to add any more headers or libraries to my project!" Because not having to deal with C++ is a good reason to write your own UI.
11+
12+
Well, I did it for my game, Twin Gods. I can't remember why anymore beyond "hey, that sounds like fun". Am I glad I have it? Yes! You very much learn a lot about how a UI works. Would I do it again? Probably not.
13+
14+
What came out the other end is a confusing mixture of knowledge, a lot of head-bashing, years of code that went sideways more than once, and a working UI for a functioning game. Let's see how it works, shall we?
1115

1216
This is not an article to sell you on using my UI ([\*0](#note-id-0)). This is only intended as a showcase of how it works, *why* it works that way, what went into making it, and how difficult it is to make a UI from scratch. And I cannot understate how difficult it is -- *and how much time it takes* -- to make a UI from scratch.
1317

18+
<!-- truncate -->
19+
20+
## There's a Lot to Cover
21+
1422
In this article, we'll cover:
1523

1624
1. Defining a UI element with a simple example
@@ -19,18 +27,10 @@ In this article, we'll cover:
1927
4. The template system
2028
5. How this all helped shape the look of the game's UI
2129

22-
<!-- truncate -->
23-
2430
Other topics, such as data binding (don't be fooled by this only being two words, this is *type-checked* on game startup), callbacks, the click feedback system, the dialog transition system, text rendering (which, [hates you](https://faultlore.com/blah/text-hates-you/)), the UI loader (a rather vital part), the lame UI editor, the script wait system, the UI flow and layout system, how the UI is rendered, the "vis stack" (again, don't be fooled by it only being two words), dialog navigation (yep), the UI event system, lists, the placeholder text system, and how the data is actually organized engine-side will be left to future articles.
2531

2632
![Menu Overview](ui-overview.png)
2733

28-
## But First
29-
30-
I will be blunt: I will neither encourage nor discourage you from using the general paradigm used by Twin Gods' UI. This is only one man's journey from an empty code file to a fully-featured UI that could actually be used in a professional video game. And let me tell you, I'm as surprised as you are.
31-
32-
A few names. Twin Gods' engine is dubbed **Hauntlet**. The UI library has no name so we'll refer to it as "Twin Gods UI", or "TGUI" (because I think HUI sounds silly). Like all the rest of Hauntlet, it is in C++ and is rendered with OpenGL 4.6.
33-
3434
## Let's Begin
3535

3636
Let's see how it all started.
@@ -39,35 +39,43 @@ Let's see how it all started.
3939

4040
Rough, eh? That screenshot is dated 2011. Nevermind the hilarious artwork, how did TGUI go from a fever dream to something someone might not actually downvote on Steam out of sheer anger?
4141

42-
The basics of TGUI have not changed since 2011 ([\*1](#note-id-1)). The main workhorse is a class called `DialogItem`. TGUI has no "controls" as you'd expect of a UI library, which is a relic from its early days as a "I didn't know what I was doing" sort of thing ([\*2](#note-id-2)). Every UI element is a `DialogItem`. `DialogItem` contains a `std::vector<DialogItem>` member. If I remember right, the original version contained only the very basics: support for a background image, on-click event, text, child elements, and the layout type (row, column, pure x/y). It also used to support drag and drop. Implement *that* at your own peril.
42+
The basics of TGUI have not changed since 2011 ([\*1](#note-id-1)). The main workhorse is a class called `DialogItem`. TGUI has no "controls" as you'd expect of a UI library, which is a relic from its early days as a "I didn't know what I was doing" sort of thing ([\*2](#note-id-2)). Every UI element is a `DialogItem`. `DialogItem` contains a `std::vector<DialogItem>` member.
4343

44-
It's gotten more complicated since and, you'll be happy to know, the concept of controls has emerged, though not through the C++ side of things. We'll get to that in later articles. This means that every UI element contains all the attributes used to make up everything seen in the UI. `DialogItem` is reported as being 1,480 bytes in release mode. It's quite large.
44+
If I remember right, the original version contained only the very basics: support for a background image, on-click event, text, child elements, and the layout type (row, column, pure x/y). It also used to support drag and drop. Implement *that* at your own peril.
45+
46+
It's all gotten more complicated since and, you'll be happy to know, the concept of controls has emerged, though not through the C++ side of things. We'll get to that in later articles. This means that every UI element contains all the attributes used to make up everything seen in the UI. `DialogItem` is reported as being 1,480 bytes in release mode. It's quite large.
47+
48+
And, okay, I lied. There is one specific control: lists. For a later article.
4549

4650
But of course, the definition of a TGUI `UIFrame` is just as important as the engine code behind it. TGUI's XML might as well be its own language and is one of its primary strengths, I think.
4751

48-
Ok, I lied. There is one specific control: lists. For a later article.
52+
## But First
53+
54+
I will be blunt: I will neither encourage nor discourage you from using the general paradigm used by Twin Gods' UI. This is only one man's journey from an empty code file to a fully-featured UI that could actually be used in a professional video game.
55+
56+
A few names. Twin Gods' engine is dubbed **Hauntlet**. The UI library has no name so we'll refer to it as "Twin Gods UI", or "TGUI" (because I think HUI sounds silly). Like all the rest of Hauntlet, it is in C++ and is rendered with OpenGL 4.6.
4957

50-
## Eww, XML!
58+
## Defining a UI
5159

5260
All screenshots in this article were captured from the running game.
5361

5462
Here's a simple example UIFrame.
5563

5664
```xml
5765
<UIFrame Name="simple-example" Size="250,50" Anchor="Center" BackColor="White" Background=";materials\unit speech frame.mat">
58-
<Node Name="downbox-1" BackColor="Blue" Text="Hello!" FontStyle="Paragraph-Normal16" />
66+
<Node Name="downbox-1" Text="Hello!" FontStyle="Paragraph-Normal16" />
5967
</UIFrame>
6068
```
6169

6270
That XML produces this UI.
6371

6472
![Simple Example](simple-example.png)
6573

66-
Much of the XML should be self-explanatory but let's cover a few less-obvious points.
74+
Hideous! Much of the XML should be self-explanatory but let's cover a few less-obvious points.
6775

68-
* `BackColor` is applied on top of any materials.
76+
* `BackColor` is applied on top of any materials. If it was "Red", the resulting shader color is then multiplied by red.
6977

70-
* The astute reader may note the `;` hanging out in front of the `Background` attribute. For better or worse TGUI's XML reflects its history, a problem you run into when your code is over a decade old ([\*3](#note-id-3)). The semicolon denotes a material file. `Background="plain texture.png"` would specify a texture directly. A "material" is simply a texture and shader with values for uniforms. Materials came much later. Very recently, in fact.
78+
* The astute reader may note the `;` hanging out in front of the `Background` attribute. For better or worse TGUI's XML reflects its history ([\*3](#note-id-3)). The semicolon denotes a material file. `Background="plain texture.png"` would specify a texture directly. We'll see a material soon.
7179

7280
* `Anchor` is a note to the layout and flow code. It determines the initial position of the dialog. "Center" simply means it is laid out in the middle of its parent. Other options are "TopLeft", "Top", "TopRight", etc.
7381

@@ -343,6 +351,17 @@ Wanna see the XML that makes up the "unit frames"? Well, too bad.
343351

344352
The template system becomes rather mandatory.
345353

354+
## In Conclusione
355+
356+
If there's enough interest, there can be future articles. It's not as if there's a shortage of topics to cover. (See: intro.)
357+
358+
The
359+
360+
P.S.:
361+
It's not a typo, it's Latin. Get cultured.
362+
363+
364+
346365
## Notes
347366

348367
#### (0) {#note-id-0}
@@ -355,7 +374,7 @@ Hauntlet has not been in active development since 2011. For a long time, it was
355374
Arguably, still don't.
356375

357376
#### (3) {#note-id-3}
358-
Somehow, TGUI has survived every massive refactor in Hauntlet, and not for lack of trying. There is a *large* comment inside the `DialogItem` class about introducing official UI element control types. (At this point, it will never get done.)
377+
A problem you run into when your code is over a decade old. Somehow, TGUI has survived every massive refactor in Hauntlet, and not for lack of trying. There is a *large* comment inside the `DialogItem` class about introducing official UI element control types. (At this point, it will never get done.)
359378

360379
#### (4) {#note-id-4}
361380
Fun fact: the original version of TGUI's definition file could be lightly edited to view in a web browser. This was how the initial UI was created.

blog/authors.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ eduameli:
6060

6161
domiran:
6262
name: Ross Lombardi
63-
title: Some Kind of Frog
63+
title: Creator, Twin Gods
6464
image_url: https://avatars.githubusercontent.com/u/90017841?v=4
65+
url: https://store.steampowered.com/app/2495430/Twin_Gods/
6566
socials:
66-
bluesky: https://bsky.app/profile/domiran.bsky.social
67+
bluesky: https://bsky.app/profile/domiran.bsky.social
68+
github: Domiran

0 commit comments

Comments
 (0)