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_tableandconfig.ref_valueare both provided. The text to display. Type:stringconfig.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:floatconfig.shadow, defaults tofalse. Whether to draw a shadow behind the text. Type:booleanconfig.focus_argsconfig.ref_table: a reference table, basically, thetextvalue will be computed by looking upconfig.ref_valueinconfig.ref_table.config.ref_value: the value to look up into the providedconfig.ref_tableconfig.funcconfig.id: An unique ID for the nodeconfig.juiceconfig.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) |