A GUI screen
Status: Implemented for screens built from vanilla widgets and for RmlUi document screens. Data bindings in documents, overlays and buttons added to vanilla screens are Planned.
Goal: a Ruby Settings screen opened with a key: a slider, a checkbox and a Done button, then the same screen as an RML document.
Language: Lua, with C++ at the end. APIs: Screens, widgets and 2d drawing, GUI screens (RmlUi), Input and keybinds.
1. A widget screen
local radius, glow = 8, true
local function open_settings()
cl.screen.open{
title = "Ruby Settings",
pause = false,
init = function(s) -- runs again after every resize
local cx = s:width() // 2
s:slider(cx - 100, 50, 200, 20, "Radius", 1, 32, radius, 1, function(w) radius = w:value() end)
s:checkbox(cx - 100, 80, "Glow", glow, function(w) glow = w:value() == 1 end)
s:button(cx - 100, s:height() - 40, 200, 20, "Done", function() s:close() end)
end,
render = function(s, g)
g:text_centered("Ruby Settings", s:width() // 2, 20, 0xFFFFFF, true)
end,
}
end
Keep the values outside the screen (radius, glow): the widgets are rebuilt on every resize. To keep them across restarts, use the config API (Config and a config screen).
2. Open it with a key
local key
cl.on("lifecycle.client_setup", function()
key = cl.keybind.register{ id = "my_mod:settings", default_key = "key.keyboard.o", label = "Ruby settings" }
end)
cl.on("tick.client_post", function()
if key then while key:consume_click() do open_settings() end end
end)
3. The same screen as a document
assets/my_mod/gui/settings.rml:
<rml>
<head>
<link type="text/rcss" href="settings.rcss"/>
<title>Ruby Settings</title>
</head>
<body>
<p id="title">Ruby Settings</p>
<mc-slider id="radius" min="1" max="32" step="1">Radius</mc-slider>
<mc-checkbox id="glow">Glow</mc-checkbox>
<mc-button id="done">Done</mc-button>
</body>
</rml>
local function open_settings_doc()
cl.rml.open{
path = "assets/my_mod/gui/settings.rml",
on_event = function(doc, id, event, value)
if id == "done" and event == "click" then doc:close()
elseif id == "radius" and event == "change" then radius = tonumber(value) or radius
elseif id == "glow" and event == "change" then glow = value == "true" or value == "1" end
end,
}
end
Documents may only reference files in your own mod folder (the sandbox rule); images go through the resource packs.
4. C++
void open_settings() {
clight::screen::open({
.title = "Ruby Settings",
.pause = false,
.init = [this](clight::Screen s) {
const int32_t cx = s.width() / 2;
s.slider(cx - 100, 50, 200, 20, "Radius", 1, 32, radius_, 1, [this](clight::Widget w) { radius_ = w.value(); });
s.button(cx - 100, s.height() - 40, 200, 20, "Done", [s] { s.close(); });
},
});
}
Why it stays fast
Nothing runs while the screen is closed. Widgets are vanilla’s own, drawn in the GUI batch with everything else.