UI Modding Basics
Balatro comes with a built-in UI framework that draws most of the elements of the game. It may seem hard to grasp at first but it’s actually quite simple in its structure.
The G.FUNCS
and G.UIDEF
tables
The game uses 2 tables for the UI.
G.FUNCS
It’s the table that holds all of the UI callbacks. Basically, whenever you click on a button, its associated to a function defined here. Functions in G.FUNCS
match the following signature, the UIElement
class being defined in engine/ui.lua
:
function(element: UIElement) -> nil
G.UIDEF
It’s the table that holds the UI definitions for the game. An UI definition is a function that returns a table that has a very strict structure:
G.UIDEF.my_ui_definition = function(element)
return {
n = G.UIT.ROOT,
config = {},
nodes = {}
}
end
Let’s break this down:
n = G.UIT.ROOT
: n here represents the node “type”. There are several node types available in BalatroT
, which is for text nodesB
, for boxes (which can be rounded)C
, for column layoutsR
, for row layoutsO
, for objects (such as cards and such)ROOT
, for the root node of an UI definition
config
: configuration for the node, holds several attributes, each for configuring alignments, or button behavior for instancenodes
: is an array of child nodes
Think of the Balatro UI definition like you would an HTML document. In HTML, you’d write something like this
<div>
<input type="text"></input>
<div>
<span><p>Some Text</p></span>
<span><p>Other Text</p></span>
</div>
</div>
Which would roughly be equivalent to
{
n = G.UIT.ROOT,
config = {},
nodes = {
{
n = G.UIT.I,
config = {},
},
{
n = G.UIT.C,
config = {},
nodes = {
{
n = G.UIT.R,
config = {},
nodes = {
{
n = G.UIT.T,
config = { text = "Some Text" }
},
},
},
{
n = G.UIT.R,
config = {},
nodes = {
{
n = G.UIT.T,
config = { text = "Other Text" }
},
},
},
},
},
},
}
Configuration options for each UI type
Common config options
Text options
For text UI nodes, the following config table is expected, all values are optional (can be nil
), unless specified otherwise.
config.text
, must be specified, unlessconfig.ref_table
andconfig.ref_value
are both provided. The text to display. Type:string
config.colour
, defaults toG.C.UI.TEXT_LIGHT
(which is white with full opacity,#FFFFFFFF
)config.scale
, defaults to1
. Text scaling to apply to the text. Type:float
config.shadow
, defaults tofalse
. Whether to draw a shadow behind the text. Type:boolean
config.focus_args
config.ref_table
: a reference table, basically, thetext
value will be computed by looking upconfig.ref_value
inconfig.ref_table
.config.ref_value
: the value to look up into the providedconfig.ref_table
config.func
config.id
: An unique ID for the nodeconfig.juice
config.outline_colour
: Text outline colour
Box options
Column options
Row options
Object options
Premade UI widget factories
The following functions are defined in functions/UI_definitions.lua
, and use the concepts defined above
to make more complex UI elements.
create_slider(args) -> UIElement
create_toggle(args) -> UIElement
create_option_cycle(args) -> UIElement
create_tabs(args) -> UIElement
create_text_input(args) -> UIElement
create_keyboard_input(args) -> UIElement
Enumerations
Colours
Colors are specified in globals.lua
, you can access them through the G.C
table.
Color Name | Color (hex) | Color (tuple) | Color |
---|---|---|---|
MULT | #FE5F55 |
(1,0.37,0.33,1) |
|
CHIPS | #009DFF |
(0,0.62,1,1) |
|
MONEY | #F3B958 |
(0.95,0.73,0.35,1) |
|
XMULT | #FE5F55 |
(1,0.37,0.33,1) |
|
FILTER | #FF9A00 |
(1,0.6,0,1) |
|
BLUE | #009DFF |
(0,0.62,1,1) |
|
RED | #FE5F55 |
(1,0.37,0.33,1) |
|
GREEN | #4BC292 |
(0.29,0.76,0.57,1) |
|
PALE_GREEN | #56A887 |
(0.34,0.66,0.53,1) |
|
ORANGE | #FDA200 |
(0.99,0.64,0,1) |
|
IMPORTANT | #FF9A00 |
(1,0.6,0,1) |
|
GOLD | #EAC058 |
(0.92,0.75,0.35,1) |
|
YELLOW | #FFFF00FF |
(1,1,0,1) |
|
CLEAR | #00000000 |
(0,0,0,0) |
|
WHITE | #FFFFFFFF |
(1,1,1,1) |
|
PURPLE | #8867A5 |
(0.53,0.4,0.65,1) |
|
BLACK | #374244 |
(0.22,0.26,0.27,1) |
|
L_BLACK | #4F6367 |
(0.31,0.39,0.4,1) |
|
GREY | #5F7377 |
(0.37,0.45,0.47,1) |
|
CHANCE | #4BC292 |
(0.29,0.76,0.57,1) |
|
JOKER_GREY | #BFC7D5 |
(0.75,0.78,0.84,1) |
|
VOUCHER | #CB724C |
(0.8,0.45,0.3,1) |
|
BOOSTER | #646EB7 |
(0.39,0.43,0.72,1) |
|
EDITION | #FFFFFFFF |
(1,1,1,1) |
|
DARK_EDITION | #000000FF |
(0,0,0,1) |
|
ETERNAL | #C75985 |
(0.78,0.35,0.52,1) |
|
PERISHABLE | #4F5DA1 |
(0.31,0.36,0.63,1) |
|
RENTAL | #B18F43 |
(0.69,0.56,0.26,1) |
|
DYN_UI.MAIN | #374244 |
(0.22,0.26,0.27,1) |
|
DYN_UI.DARK | #374244 |
(0.22,0.26,0.27,1) |
|
DYN_UI.BOSS_MAIN | #374244 |
(0.22,0.26,0.27,1) |
|
DYN_UI.BOSS_DARK | #374244 |
(0.22,0.26,0.27,1) |
|
DYN_UI.BOSS_PALE | #374244 |
(0.22,0.26,0.27,1) |
|
SO_1.Hearts | #F03464 |
(0.94,0.2,0.39,1) |
|
SO_1.Diamonds | #F06B3F |
(0.94,0.42,0.25,1) |
|
SO_1.Spades | #403995 |
(0.25,0.22,0.58,1) |
|
SO_1.Clubs | #235955 |
(0.14,0.35,0.33,1) |
|
SO_2.Hearts | #F83B2F |
(0.97,0.23,0.18,1) |
|
SO_2.Diamonds | #E29000 |
(0.89,0.56,0,1) |
|
SO_2.Spades | #4F31B9 |
(0.31,0.19,0.73,1) |
|
SO_2.Clubs | #008EE6 |
(0,0.56,0.9,1) |
|
SUITS.Hearts | #FE5F55 |
(1,0.37,0.33,1) |
|
SUITS.Diamonds | #FE5F55 |
(1,0.37,0.33,1) |
|
SUITS.Spades | #374649 |
(0.22,0.27,0.29,1) |
|
SUITS.Clubs | #424E54 |
(0.26,0.31,0.33,1) |
|
UI.TEXT_LIGHT | #FFFFFFFF |
(1,1,1,1) |
|
UI.TEXT_DARK | #4F6367 |
(0.31,0.39,0.4,1) |
|
UI.TEXT_INACTIVE | #88888899 |
(0.53,0.53,0.53,0.6) |
|
UI.BACKGROUND_LIGHT | #B8D8D8 |
(0.72,0.85,0.85,1) |
|
UI.BACKGROUND_WHITE | #FFFFFFFF |
(1,1,1,1) |
|
UI.BACKGROUND_DARK | #7A9E9F |
(0.48,0.62,0.62,1) |
|
UI.BACKGROUND_INACTIVE | #666666FF |
(0.4,0.4,0.4,1) |
|
UI.OUTLINE_LIGHT | #D8D8D8 |
(0.85,0.85,0.85,1) |
|
UI.OUTLINE_LIGHT_TRANS | #D8D8D866 |
(0.85,0.85,0.85,0.4) |
|
UI.OUTLINE_DARK | #7A9E9F |
(0.48,0.62,0.62,1) |
|
UI.TRANSPARENT_LIGHT | #EEEEEE22 |
(0.93,0.93,0.93,0.13) |
|
UI.TRANSPARENT_DARK | #22222222 |
(0.13,0.13,0.13,0.13) |
|
UI.HOVER | #00000055 |
(0,0,0,0.33) |
|
SET.Default | #CDD9DC |
(0.8,0.85,0.86,1) |
|
SET.Enhanced | #CDD9DC |
(0.8,0.85,0.86,1) |
|
SET.Joker | #424E54 |
(0.26,0.31,0.33,1) |
|
SET.Tarot | #424E54 |
(0.26,0.31,0.33,1) |
|
SET.Planet | #424E54 |
(0.26,0.31,0.33,1) |
|
SET.Spectral | #424E54 |
(0.26,0.31,0.33,1) |
|
SET.Voucher | #424E54 |
(0.26,0.31,0.33,1) |
|
SECONDARY_SET.Default | #9BB6BDFF |
(0.61,0.71,0.74,1) |
|
SECONDARY_SET.Enhanced | #8389DDFF |
(0.51,0.54,0.87,1) |
|
SECONDARY_SET.Joker | #708B91 |
(0.44,0.55,0.57,1) |
|
SECONDARY_SET.Tarot | #A782D1 |
(0.65,0.51,0.82,1) |
|
SECONDARY_SET.Planet | #13AFCE |
(0.07,0.69,0.81,1) |
|
SECONDARY_SET.Spectral | #4584FA |
(0.27,0.52,0.98,1) |
|
SECONDARY_SET.Voucher | #FD682B |
(0.99,0.41,0.17,1) |
|
SECONDARY_SET.Edition | #4CA893 |
(0.3,0.66,0.58,1) |
|
RARITY.1 | #009DFF |
(0,0.62,1,1) |
|
RARITY.2 | #4BC292 |
(0.29,0.76,0.57,1) |
|
RARITY.3 | #FE5F55 |
(1,0.37,0.33,1) |
|
RARITY.4 | #B26CBB |
(0.7,0.42,0.73,1) |
|
BLIND.Small | #50846E |
(0.31,0.52,0.43,1) |
|
BLIND.Big | #50846E |
(0.31,0.52,0.43,1) |
|
BLIND.Boss | #B44430 |
(0.71,0.27,0.19,1) |
|
BLIND.won | #4F6367 |
(0.31,0.39,0.4,1) |
|
HAND_LEVELS.1 | #EFEFEF |
(0.94,0.94,0.94,1) |
|
HAND_LEVELS.2 | #95ACFF |
(0.58,0.67,1,1) |
|
HAND_LEVELS.3 | #65EFAF |
(0.4,0.94,0.69,1) |
|
HAND_LEVELS.4 | #FAE37E |
(0.98,0.89,0.49,1) |
|
HAND_LEVELS.5 | #FFC052 |
(1,0.75,0.32,1) |
|
HAND_LEVELS.6 | #F87D75 |
(0.97,0.49,0.46,1) |
|
HAND_LEVELS.7 | #CAA0EF |
(0.79,0.63,0.94,1) |
|
BACKGROUND.L | #FFFF00FF |
(1,1,0,1) |
|
BACKGROUND.D | #374244 |
(0.22,0.26,0.27,1) |
|
BACKGROUND.C | #374244 |
(0.22,0.26,0.27,1) |