2 releases
Uses old Rust 2015
0.1.1 | Nov 25, 2018 |
---|---|
0.1.0 | Nov 24, 2018 |
#1068 in GUI
470KB
3.5K
SLoC
FunGUI
A UI layout system that seperates the description of the interface and the styling/layout. This is designed to be used in games and is currently used in UniverCity.
lib.rs
:
FunGUI is a UI layout system that seperates the description of the interface and the styling/layout.
In FunGUI there are two main systems that come into play that the rest is built around: Nodes and Styles.
Nodes
Nodes are used to describe the user interface without any information about how it should look, only the structure. There are two types of nodes: Elements and Text.
Elements are simply a name which could be anything, there are no special names as everything is controled by the style rules. Elements may contain child nodes.
Text as the name implies is just text. Unlike elements, text may not have any child nodes.
Any node may have properties on it. Properties are used to provide
configuration to a node which is useful if you use the same node type
multiple times. For example an url
property may be used on a text
node to allow the style rules to color it differently or make it clickable.
Example
An example of the node format:
alert(level="warning") {
title {
"This is an alert"
}
content {
"If you would like more info click "
"here"(url="http://....")
"."
}
buttons {
button(focused=true) {
"Accept"
}
button {
"Ignore"
}
}
}
Styles
Styles are used to define the behaviour of a node. This can be something like how the node will render or how the node will react to events.
Styles apply using matching rules to find what nodes they will apply too. Rules
can specific a hierarchy of nodes and what properties the node should have and
their values. This allows for a title
inside an alert
to act differently to
a title
inside an window
for example.
Once a match is found the style rules are applied to the node. Rules can be a
simple constant value or an expression. Expressions perform basic math (+-/*%
)
and boolean operations (|| && <=
etc), reference properties that were matched
and execute functions. Functions can be used for complex properties instead of
spliting them across multiple rules.
Variables and types
Variables are typed and floats/integers are treated as seperate and not casted
automatically, this includes constants in style rules as well. For constants
defining a number as 5
will be an integer whilst 5.0
will be a float. For
variables you can cast using int(val)
or float(val)
.
Special variables
There are two special variables that can be used without using them in a matching
rule: parent_width
and parent_height
. These allow you to size things relative
to the parent's size without needing a custom layout to handle it. Whilst these
are useful in some cases they do come with a larger cost. In order to handle this
the interface may have to re-run the layout system multiple to resolve the variables
causing a slowdown however this will generally only happen the first time the
node has its layout computed.
Example
An example of the style format:
alert {
center = true,
layout = "rows",
width = 500,
height = 400,
}
alert(level="warning") {
background_color = rgb(255, 255, 0),
}
alert > title {
layout = "lined",
width = parent_width,
}
alert > title > @text {
font_color = rgb(0, 0, 0),
font_size = 24,
}
alert > content {
layout = "lined",
width = parent_width,
}
alert > content > @text {
font_color = rgb(0, 0, 0),
font_size = 16,
}
alert > content > @text(url=url) {
font_color = rgb(0, 120, 0),
on_mouse_up = action("visit", url),
}
Layouts
Layouts take some of the style rules and use that to position and size a node.
These can be added via add_layout_engine
and selected using the layout
style
property.
Extension
The Extension
trait paired with the RenderVisitor
trait is the main way that
is used to actually make the user interface do something. By itself FunGUI only
does layout, the extension trait can be used to add events and rendering by adding
its own properties to use in style rules. In UniverCity these are things like
image
and background_color
for rendering and on_mouse_down
for events where
events are lua code defined inline with the styles:
button {
border_width = border_width(15.0),
border = border_image("ui/button", 15, 15, true),
shadow = shadow(2.0, 2.0, rgba(0, 0, 0, 0.3), 3.0, 0.0, "outset"),
layout = "center",
can_hover = true,
}
button(theme="blueprint") {
border_width = border_width(15.0),
border = border_image("ui/button", 15, 15, true),
tint = rgba(0, 255, 255, 0.4),
}
button(on_click=click) {
on_mouse_up = list(click, "init#
audio.play_sound('click')
return true
"),
}
Dependencies
~1MB
~24K SLoC