### Install PlutoVG using CMake
Source: https://github.com/ghsoares/godot-rmlui/blob/main/thirdparty/plutovg/README.md
These bash commands guide you through cloning the PlutoVG repository, configuring the build with CMake, compiling the library, and installing it.
```bash
git clone https://github.com/sammycage/plutovg.git
cd plutovg
cmake -B build .
cmake --build build
cmake --install build
```
--------------------------------
### Install PlutoVG using Meson
Source: https://github.com/ghsoares/godot-rmlui/blob/main/thirdparty/plutovg/README.md
Follow these bash commands to clone the PlutoVG repository, set up the build environment with Meson, compile the library, and install it.
```bash
git clone https://github.com/sammycage/plutovg.git
cd plutovg
meson setup build
Meson compile -C build
Meson install -C build
```
--------------------------------
### Install RmlUi Core Target
Source: https://github.com/ghsoares/godot-rmlui/blob/main/thirdparty/rmlui/Source/Core/CMakeLists.txt
Installs the rmlui_core target, including runtime dependencies, to the appropriate directories (bin, lib). It also installs the PDB file for debugging.
```cmake
# RMLUI_CMAKE_MINIMUM_VERSION_RAISE_NOTICE:
# We use default paths provided from GNUInstallDirs. From CMake 3.14 these paths (CMAKE_INSTALL_...) will be used
# automatically and can be removed from the following call. The same applies to many other calls to install(TARGETS...).
# Note that GNUInstallDirs should still be included in the project root.
install(TARGETS rmlui_core
EXPORT RmlUiTargets
${RMLUI_RUNTIME_DEPENDENCY_SET_ARG}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install_target_pdb(rmlui_core)
```
--------------------------------
### Load and Interact with RMLDocument
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Example of using the `RMLDocument` node in Godot. It loads an RML file and demonstrates how to dynamically toggle CSS classes on an element using GDScript for interactive effects.
```gdscript
extends RMLDocument
func _ready() -> void:
load_from_path("res://ui/fancy_card.rml")
# Dynamically toggle the blur filter class
await get_tree().create_timer(2.0).timeout
var card: RMLElement = as_element().query_selector("#info-card")
if card.is_valid():
card.toggle_class("blurred")
```
--------------------------------
### Basic RML Structure Example
Source: https://github.com/ghsoares/godot-rmlui/blob/main/README.md
An example of a basic RML document structure, including common elements like span, button, svg, and input. This can be loaded using the RMLDocument node.
```xml
Hello!
```
--------------------------------
### Create New RMLDocument
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Use `new_document()` to start with a clean slate when dynamically building the DOM from GDScript. This discards any previously loaded content.
```gdscript
extends RMLDocument
func build_inventory_ui(items: Array[Dictionary]) -> void:
new_document() # start with a clean slate
var root: RMLElement = as_element()
root.set_inner_rml("") # body is already empty, but explicit
for item in items:
var div: RMLElement = create_element("div")
div.set_attribute("class", "item-card")
div.set_text_content(item["name"])
div.set_property("background-color", item.get("color", "#333"))
root.append_child(div)
# Force layout recalculation so get_rect() is accurate immediately
update()
print("First card rect: ", root.get_child(0).get_rect())
```
--------------------------------
### Manage RML Documents with RMLServer
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Example of managing RML documents using RMLServer. It shows how to create, store, and free RML document RIDs to prevent memory leaks. Ensure `free_rid` is called when documents are no longer needed.
```gdscript
extends Node
var _docs: Array[RID] = []
func create_popup(rml_path: String) -> RID:
var rid: RID = RMLServer.create_document_from_path(rml_path)
_docs.append(rid)
return rid
func destroy_popup(rid: RID) -> void:
if rid.is_valid():
RMLServer.free_rid(rid)
_docs.erase(rid)
func _exit_tree() -> void:
# Clean up all open documents on scene exit
for rid in _docs:
if rid.is_valid():
RMLServer.free_rid(rid)
_docs.clear()
```
--------------------------------
### Get RMLDocument Root Element
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Use `as_element()` to get an `RMLElement` reference to the document's root (`
`) element. This is the entry point for DOM traversal and mutation.
```gdscript
extends RMLDocument
func _ready() -> void:
load_from_rml_string("
Hello
")
var body: RMLElement = as_element()
print("Tag: ", body.get_tag_name()) # "body"
print("Children: ", body.get_child_count()) # 1
var p_el: RMLElement = body.get_child(0)
print("Text: ", p_el.get_text_content()) # ["Hello"]
```
--------------------------------
### Draw a Smiley Face with PlutoVG
Source: https://github.com/ghsoares/godot-rmlui/blob/main/thirdparty/plutovg/README.md
This C code demonstrates how to create a smiley face image using PlutoVG. It involves creating a surface, a canvas, drawing arcs for the face, eyes, and mouth, setting colors, line widths, and finally saving the output as a PNG file. Ensure PlutoVG is installed and linked correctly.
```c
#include
int main(void)
{
const int width = 150;
const int height = 150;
const float center_x = width / 2.f;
const float center_y = height / 2.f;
const float face_radius = 70;
const float mouth_radius = 50;
const float eye_radius = 10;
const float eye_offset_x = 25;
const float eye_offset_y = 20;
const float eye_x = center_x - eye_offset_x;
const float eye_y = center_y - eye_offset_y;
plutovg_surface_t* surface = plutovg_surface_create(width, height);
plutovg_canvas_t* canvas = plutovg_canvas_create(surface);
plutovg_canvas_save(canvas);
plutovg_canvas_arc(canvas, center_x, center_y, face_radius, 0, PLUTOVG_TWO_PI, 0);
plutovg_canvas_set_rgb(canvas, 1, 1, 0);
plutovg_canvas_fill_preserve(canvas);
plutovg_canvas_set_rgb(canvas, 0, 0, 0);
plutovg_canvas_set_line_width(canvas, 5);
plutovg_canvas_stroke(canvas);
plutovg_canvas_restore(canvas);
plutovg_canvas_save(canvas);
plutovg_canvas_arc(canvas, eye_x, eye_y, eye_radius, 0, PLUTOVG_TWO_PI, 0);
plutovg_canvas_arc(canvas, center_x + eye_offset_x, eye_y, eye_radius, 0, PLUTOVG_TWO_PI, 0);
plutovg_canvas_set_rgb(canvas, 0, 0, 0);
plutovg_canvas_fill(canvas);
plutovg_canvas_restore(canvas);
plutovg_canvas_save(canvas);
plutovg_canvas_arc(canvas, center_x, center_y, mouth_radius, 0, PLUTOVG_PI, 0);
plutovg_canvas_set_rgb(canvas, 0, 0, 0);
plutovg_canvas_set_line_width(canvas, 5);
plutovg_canvas_stroke(canvas);
plutovg_canvas_restore(canvas);
plutovg_surface_write_to_png(surface, "smiley.png");
plutovg_canvas_destroy(canvas);
plutovg_surface_destroy(surface);
return 0;
}
```
--------------------------------
### Apply and Get Inline Styles with RMLElement
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Use `set_property` to apply inline RCSS styles similar to the HTML `style` attribute. `get_property` retrieves computed styles, falling back to a default if not set. `remove_property` reverts to stylesheet values.
```gdscript
extends RMLDocument
func highlight_element(selector: String, color: String = "#ffeb3b") -> void:
var el: RMLElement = as_element().query_selector(selector)
if not el.is_valid():
return
# Apply inline styles
el.set_property("background-color", color)
el.set_property("border", "2px " + color)
el.set_property("transition", "background-color 0.3s")
# Read back a computed property
var bg: String = el.get_property("background-color", "transparent")
print("Background is now: ", bg)
# Remove an inline override to fall back to stylesheet
await get_tree().create_timer(2.0).timeout
el.remove_property("background-color")
el.remove_property("border")
```
--------------------------------
### RMLElement DOM Traversal and Manipulation
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Provides methods for traversing and manipulating the Document Object Model (DOM) of RML elements. This includes getting parent and child elements, adding, removing, and clearing children.
```APIDOC
## RMLElement DOM Traversal (`get_parent`, `get_children`, `get_child`, `get_child_count`, `append_child`, `remove_child`, `clear_children`)
Provides full parent/child DOM manipulation. Elements are `RefCounted` references; adding/removing them from the tree does not free the underlying data while a reference is held.
```gdscript
extends RMLDocument
func _ready() -> void:
load_from_path("res://ui/inventory.rml")
var grid: RMLElement = as_element().query_selector("#item-grid")
if not grid.is_valid():
return
print("Slot count: ", grid.get_child_count()) # e.g. 16
# Iterate all children
for child in grid.get_children():
var slot := child as RMLElement
if slot.get_attribute("data-empty", "true") == "true":
slot.set_property("opacity", "0.3")
# Move first child to end
var first: RMLElement = grid.get_child(0)
grid.remove_child(first)
grid.append_child(first)
# Check parent linkage
print("Parent tag: ", first.get_parent().get_tag_name()) # "div" (grid)
# Remove all slots and rebuild
grid.clear_children()
for i in range(8):
var slot: RMLElement = create_element("div")
slot.set_attribute("class", "slot")
slot.set_attribute("data-empty", "true")
grid.append_child(slot)
```
```
--------------------------------
### Project Settings
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Control the default stylesheet loaded at startup using project settings. You can enable the built-in default stylesheet or specify a custom one.
```APIDOC
## Project Settings
Two project settings control the default stylesheet loaded at startup.
```gdscript
# Project Settings (Project > Project Settings > RmlUi)
# "RmlUi/load_user_agent_stylesheet" (bool, default: true)
# Loads the built-in default.rcss stylesheet that styles body, headings,
# buttons, scrollbars, inputs, tables, etc.
#
# "RmlUi/custom_user_agent_stylesheet" (String, default: "")
# Path to a custom .rcss file that replaces the built-in stylesheet.
# Leave empty to use the bundled default.
# Override via code (call before the first document is created):
ProjectSettings.set_setting("RmlUi/load_user_agent_stylesheet", true)
ProjectSettings.set_setting("RmlUi/custom_user_agent_stylesheet", "res://ui/my_theme.rcss")
```
```
--------------------------------
### RMLServer Usage
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Headless/offscreen rendering using the RMLServer singleton with raw RIDs. Create documents with create_document_from_path or create_document_from_rml_string, size them with document_set_size, drive input with document_process_event, and render each frame with document_update + document_draw.
```APIDOC
## RMLServer
### Description
For advanced integration — such as rendering UI onto a 3D surface, inside a SubViewport, or in a headless simulation — use `RMLServer` directly. Create documents with `create_document_from_path` or `create_document_from_rml_string`, size them with `document_set_size`, drive input with `document_process_event`, and render each frame with `document_update` + `document_draw` passing a canvas item RID.
### GDScript Example Snippet
```gdscript
# Assuming 'rml_path' is a valid path to an RML file
var rid: RID = RMLServer.create_document_from_path(rml_path)
# Set document size
RMLServer.document_set_size(rid, Vector2(800, 600))
# Process input events (example)
var event = InputEventMouseMotion.new()
event.position = Vector2(100, 100)
RMLServer.document_process_event(rid, event)
# Update and draw the document (requires a CanvasItem RID)
# var canvas_item_rid: RID = ...
# RMLServer.document_update(rid)
# RMLServer.document_draw(rid, canvas_item_rid)
```
```
--------------------------------
### Configure RmlUi Project Settings
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Set project settings to control the default stylesheet loaded at startup. This can be done via the Project Settings UI or programmatically before the first document is created.
```gdscript
# Project Settings (Project > Project Settings > RmlUi)
# "RmlUi/load_user_agent_stylesheet" (bool, default: true)
# Loads the built-in default.rcss stylesheet that styles body, headings,
# buttons, scrollbars, inputs, tables, etc.
#
# "RmlUi/custom_user_agent_stylesheet" (String, default: "")
# Path to a custom .rcss file that replaces the built-in stylesheet.
# Leave empty to use the bundled default.
# Override via code (call before the first document is created):
ProjectSettings.set_setting("RmlUi/load_user_agent_stylesheet", true)
ProjectSettings.set_setting("RmlUi/custom_user_agent_stylesheet", "res://ui/my_theme.rcss")
```
--------------------------------
### Center RMLElement using get_rect() in GDScript
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Calculates and sets the position of an RMLElement to center it within its parent. Ensure the layout is up-to-date by calling RMLDocument.update() before getting the element's rectangle.
```gdscript
extends RMLDocument
func center_popup(popup_selector: String) -> void:
update() # ensure layout is current
var popup: RMLElement = as_element().query_selector(popup_selector)
if not popup.is_valid():
return
var r: Rect2 = popup.get_rect()
var doc_size: Vector2 = size # Control.size — the RMLDocument node size
var center_x: float = (doc_size.x - r.size.x) / 2.0
var center_y: float = (doc_size.y - r.size.y) / 2.0
popup.set_property("position", "absolute")
popup.set_property("left", "%dpx" % int(center_x))
popup.set_property("top", "%dpx" % int(center_y))
print("Popup rect: ", r) # e.g. Rect2(0, 0, 300, 200)
print("Centered at: ", center_x, center_y)
```
--------------------------------
### Manipulate Server-Managed RML Document Root in GDScript
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Demonstrates how to get the root RMLElement of a server-managed RML document using RMLServer.get_document_root. This allows for DOM manipulation similar to RMLDocument, but on documents managed by RMLServer.
```gdscript
func populate_server_document(doc_rid: RID, items: Array[String]) -> void:
var root: RMLElement = RMLServer.get_document_root(doc_rid)
if not root.is_valid():
return
root.clear_children()
for item_text in items:
var li: RMLElement = RMLServer.create_element(doc_rid, "li")
li.set_text_content(item_text)
root.append_child(li)
```
--------------------------------
### Query RMLElements with CSS Selectors
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Use `query_selector()` to find the first matching element or `query_selector_all()` to find all matches using standard CSS selectors. Supports tag, class, id, and combinators.
```gdscript
extends RMLDocument
func _ready() -> void:
load_from_path("res://ui/settings.rml")
# Single element by id
var volume_slider: RMLElement = as_element().query_selector("#volume-slider")
if volume_slider.is_valid():
volume_slider.set_attribute("value", "75")
# All elements with a class
var tabs: Array = as_element().query_selector_all(".tab-button")
for tab in tabs:
var t := tab as RMLElement
if t.is_valid():
t.add_event_listener("click", func(ev: Dictionary):
# Remove active from all, then set on clicked
for other in tabs:
(other as RMLElement).remove_class("active")
(ev["target_element"] as RMLElement).set_class("active")
)
```
--------------------------------
### Create and Render RML Documents Headlessly in GDScript
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Shows how to create RML documents using the RMLServer for headless rendering, such as to a texture. It covers creating documents from paths or strings, setting their size, updating the layout, and drawing to a canvas item.
```gdscript
# Headless document rendering to a custom canvas item
extends Node2D
var _doc_rid: RID
func _ready() -> void:
var server: RMLServer = RMLServer
# Create from file
_doc_rid = server.create_document_from_path("res://ui/minimap.rml")
# OR from inline string
# _doc_rid = server.create_document_from_rml_string(
# ""
# )
if not _doc_rid.is_valid():
push_error("Failed to create document")
return
server.document_set_size(_doc_rid, Vector2i(256, 256))
func _draw() -> void:
if _doc_rid.is_valid():
RMLServer.document_update(_doc_rid)
RMLServer.document_draw(_doc_rid, get_canvas_item())
func _exit_tree() -> void:
if _doc_rid.is_valid():
RMLServer.free_rid(_doc_rid)
_doc_rid = RID()
```
--------------------------------
### Load RML UI from File with RMLDocument
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Load an RML UI layout from a file using `RMLDocument.load_from_path()`. This method resolves paths through Godot's virtual file system. After loading, elements can be queried and updated.
```gdscript
# res://ui/hud.rml
#
#
Score: 0
extends RMLDocument # node type set to RMLDocument in the scene
func _ready() -> void:
load_from_path("res://ui/hud.rml")
# After loading, query the score element and update its text
var score_el: RMLElement = as_element().query_selector("#score")
if score_el.is_valid():
score_el.set_text_content("Score: 42")
```
--------------------------------
### Custom Configuration File and Include Directories
Source: https://github.com/ghsoares/godot-rmlui/blob/main/thirdparty/rmlui/Source/Core/CMakeLists.txt
Allows specifying a custom configuration file and include directories for RmlUi. This is controlled by `RMLUI_CUSTOM_CONFIGURATION_FILE` and `RMLUI_CUSTOM_INCLUDE_DIRS`.
```cmake
if(RMLUI_CUSTOM_CONFIGURATION AND RMLUI_CUSTOM_CONFIGURATION_FILE)
target_compile_definitions(rmlui_core PUBLIC "RMLUI_CUSTOM_CONFIGURATION_FILE=\"${RMLUI_CUSTOM_CONFIGURATION_FILE}\"")
message(STATUS "Including ${RMLUI_CUSTOM_CONFIGURATION_FILE} instead of ")
endif()
if(RMLUI_CUSTOM_CONFIGURATION AND RMLUI_CUSTOM_INCLUDE_DIRS)
target_include_directories(rmlui_core PUBLIC ${RMLUI_CUSTOM_INCLUDE_DIRS})
endif()
if(RMLUI_CUSTOM_CONFIGURATION AND RMLUI_CUSTOM_LINK_LIBRARIES)
target_link_libraries(rmlui_core PUBLIC ${RMLUI_CUSTOM_LINK_LIBRARIES})
endif()
```
--------------------------------
### RMLDocument - new_document()
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Creates a fresh empty document, discarding any previously loaded content. Use this as a reset before dynamically building the DOM entirely from GDScript.
```APIDOC
## RMLDocument - new_document()
Creates a fresh empty document, discarding any previously loaded content. Use this as a reset before dynamically building the DOM entirely from GDScript.
```gdscript
extends RMLDocument
func build_inventory_ui(items: Array[Dictionary]) -> void:
new_document() # start with a clean slate
var root: RMLElement = as_element()
root.set_inner_rml("") # body is already empty, but explicit
for item in items:
var div: RMLElement = create_element("div")
div.set_attribute("class", "item-card")
div.set_text_content(item["name"])
div.set_property("background-color", item.get("color", "#333"))
root.append_child(div)
# Force layout recalculation so get_rect() is accurate immediately
update()
print("First card rect: ", root.get_child(0).get_rect())
```
```
--------------------------------
### RMLDocument — load_from_path
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Loads an RML document from a file path using Godot's virtual file system. This is suitable for authoring full UI screens.
```APIDOC
## RMLDocument — `load_from_path(path: String)`
Replaces the current document with one loaded from an `.rml` file on disk. The file is resolved through Godot's virtual file system so `res://` and `user://` paths both work. This is the simplest way to author a full UI screen.
```gdscript
# res://ui/hud.rml
#
#
Score: 0
extends RMLDocument # node type set to RMLDocument in the scene
func _ready() -> void:
load_from_path("res://ui/hud.rml")
# After loading, query the score element and update its text
var score_el: RMLElement = as_element().query_selector("#score")
if score_el.is_valid():
score_el.set_text_content("Score: 42")
```
```
--------------------------------
### RMLServer Document Creation
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Provides low-level methods for creating RML documents managed by the RMLServer. Documents can be created from a file path, an RML string, or an empty RID. This is useful for managing documents outside the scene tree.
```APIDOC
## RMLServer — `create_document() -> RID` / `create_document_from_path(path) -> RID` / `create_document_from_rml_string(rml) -> RID`
Low-level document creation through the singleton server, returning an opaque `RID`. Use this when you need to manage RmlUi documents outside the scene tree (e.g., render to a texture, headless processing).
```gdscript
# Headless document rendering to a custom canvas item
extends Node2D
var _doc_rid: RID
func _ready() -> void:
var server: RMLServer = RMLServer
# Create from file
_doc_rid = server.create_document_from_path("res://ui/minimap.rml")
# OR from inline string
# _doc_rid = server.create_document_from_rml_string(
# ""
# )
if not _doc_rid.is_valid():
push_error("Failed to create document")
return
server.document_set_size(_doc_rid, Vector2i(256, 256))
func _draw() -> void:
if _doc_rid.is_valid():
RMLServer.document_update(_doc_rid)
RMLServer.document_draw(_doc_rid, get_canvas_item())
func _exit_tree() -> void:
if _doc_rid.is_valid():
RMLServer.free_rid(_doc_rid)
_doc_rid = RID()
```
```
--------------------------------
### Load RML UI from String with RMLDocument
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Load an RML UI layout directly from a string using `RMLDocument.load_from_rml_string()`. This is useful for procedurally generated UIs or small, in-code layouts. Event listeners can be attached after loading.
```gdscript
extends RMLDocument
func _ready() -> void:
var rml := """
"
load_from_rml_string(rml)
# Attach a click handler after loading
var btn: RMLElement = as_element().query_selector("#start-btn")
if btn.is_valid():
btn.add_event_listener("click", _on_start_clicked)
func _on_start_clicked(event: Dictionary) -> void:
# event keys: "type", "target_element", "current_element"
print("Start clicked! Event type: ", event["type"])
# Stop the event from bubbling further
event["stop_propagation"] = true
get_tree().change_scene_to_file("res://game.tscn")
```
--------------------------------
### RMLElement - query_selector() / query_selector_all()
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
CSS-style element selection. query_selector returns the first match; query_selector_all returns all matches as a typed array. Supports standard CSS selectors (tag, class, id, combinators).
```APIDOC
## RMLElement - query_selector(selector: String) -> RMLElement / query_selector_all(selector: String) -> RMLElement[]
CSS-style element selection. `query_selector` returns the first match; `query_selector_all` returns all matches as a typed array. Supports standard CSS selectors (tag, class, id, combinators).
```gdscript
extends RMLDocument
func _ready() -> void:
load_from_path("res://ui/settings.rml")
# Single element by id
var volume_slider: RMLElement = as_element().query_selector("#volume-slider")
if volume_slider.is_valid():
volume_slider.set_attribute("value", "75")
# All elements with a class
var tabs: Array = as_element().query_selector_all(".tab-button")
for tab in tabs:
var t := tab as RMLElement
if t.is_valid():
t.add_event_listener("click", func(ev: Dictionary):
# Remove active from all, then set on clicked
for other in tabs:
(other as RMLElement).remove_class("active")
(ev["target_element"] as RMLElement).set_class("active")
)
```
```
--------------------------------
### RMLDocument Usage
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Scene-integrated UI using the RMLDocument Control node. Drop an RMLDocument node into any scene, extend it in GDScript, call load_from_path in _ready, and use as_element().query_selector(...) to wire up interactivity.
```APIDOC
## RMLDocument
### Description
Scene-integrated UI using the `RMLDocument` Control node. Drop an `RMLDocument` node into any scene, extend it in GDScript, call `load_from_path` in `_ready`, and use `as_element().query_selector(...)` to wire up interactivity — the Control node handles sizing, input forwarding, and rendering automatically.
### GDScript Example
```gdscript
extends RMLDocument
func _ready() -> void:
load_from_path("res://ui/fancy_card.rml")
# Dynamically toggle the blur filter class
await get_tree().create_timer(2.0).timeout
var card: RMLElement = as_element().query_selector("#info-card")
if card.is_valid():
card.toggle_class("blurred")
```
```
--------------------------------
### Add Lottie Plugin Source Files to rmlui_core
Source: https://github.com/ghsoares/godot-rmlui/blob/main/thirdparty/rmlui/Source/Lottie/CMakeLists.txt
Specifies the source files for the Lottie plugin to be compiled directly into the rmlui_core library when the plugin is enabled.
```cmake
target_sources(rmlui_core PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/ElementLottie.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/LottiePlugin.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/LottiePlugin.h"
"${PROJECT_SOURCE_DIR}/Include/RmlUi/Lottie/ElementLottie.h"
)
```
--------------------------------
### Link Lottie Plugin
Source: https://github.com/ghsoares/godot-rmlui/blob/main/thirdparty/rmlui/Source/Core/CMakeLists.txt
Links the rlottie library to the rmlui_core target if the RMLUI_LOTTIE_PLUGIN is enabled. This is for RmlUi's Lottie animation plugin.
```cmake
if(RMLUI_LOTTIE_PLUGIN)
# RMLUI_CMAKE_MINIMUM_VERSION_RAISE_NOTICE:
# From CMake 3.13 we could move this to `Lottie/CMakeLists.txt`, see CMP0079.
target_link_libraries(rmlui_core PRIVATE rlottie::rlottie)
endif()
```
--------------------------------
### RMLServer.load_font_face_from_path and RMLServer.load_font_face_from_buffer
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Registers font files or buffers with RmlUi's font engine. Allows adding custom fonts beyond the default. Returns true on success.
```APIDOC
## RMLServer.load_font_face_from_path / RMLServer.load_font_face_from_buffer
### Description
Registers a font file with RmlUi's font engine. `fallback_face` marks the font as the fallback for unrecognized glyphs. Returns `true` on success. The built-in Open Sans font is loaded automatically; use these methods to add custom fonts.
### Method Signatures
`load_font_face_from_path(path: String, fallback_face: bool = false) -> bool`
`load_font_face_from_buffer(buffer: PackedByteArray, family: String, fallback_face: bool = false, is_italic: bool = false) -> bool`
```
--------------------------------
### Define RMLUI_LOTTIE_PLUGIN Compile Definition
Source: https://github.com/ghsoares/godot-rmlui/blob/main/thirdparty/rmlui/Source/Lottie/CMakeLists.txt
Adds a compile definition 'RMLUI_LOTTIE_PLUGIN' to the rmlui_core target, enabling Lottie plugin specific code paths.
```cmake
target_compile_definitions(rmlui_core PRIVATE "RMLUI_LOTTIE_PLUGIN")
```
--------------------------------
### RML Document with RCSS Styling
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
An RML document demonstrating advanced RCSS styling, including keyframe animations, gradient decorators, box shadows, filters, and backdrop filters. It also shows dynamic class toggling for visual effects.
```xml
Godot RmlUi
HTML/CSS-based UI inside Godot 4.5+
```
--------------------------------
### Configure Tracy Profiling
Source: https://github.com/ghsoares/godot-rmlui/blob/main/thirdparty/rmlui/Source/Core/CMakeLists.txt
Configures RmlUi to use Tracy for profiling. It supports conditional linking and compile definitions based on configuration types and memory profiling flags.
```cmake
if(RMLUI_TRACY_PROFILING)
if(CMAKE_CONFIGURATION_TYPES AND RMLUI_TRACY_CONFIGURATION)
target_link_libraries(rmlui_core PUBLIC "$<$:Tracy::TracyClient>")
target_compile_definitions(rmlui_core PUBLIC "$<$:RMLUI_TRACY_PROFILING>")
if(RMLUI_TRACY_MEMORY_PROFILING)
target_compile_definitions(rmlui_core PRIVATE "$<$:RMLUI_TRACY_MEMORY_PROFILING>")
endif()
message(STATUS "Tracy profiling enabled in configuration `Tracy`.")
else()
target_link_libraries(rmlui_core PUBLIC Tracy::TracyClient)
target_compile_definitions(rmlui_core PUBLIC "RMLUI_TRACY_PROFILING")
if(RMLUI_TRACY_MEMORY_PROFILING)
target_compile_definitions(rmlui_core PRIVATE "RMLUI_TRACY_MEMORY_PROFILING")
endif()
message(STATUS "Tracy profiling enabled.")
endif()
endif()
```
--------------------------------
### Include RMLUI Core and Optional Plugins
Source: https://github.com/ghsoares/godot-rmlui/blob/main/thirdparty/rmlui/Source/CMakeLists.txt
This snippet shows how to add RMLUI subdirectories to the CMake build. Optional plugins are included conditionally based on defined variables.
```cmake
add_subdirectory("Core")
if(RMLUI_LOTTIE_PLUGIN)
add_subdirectory("Lottie")
endif()
if(RMLUI_SVG_PLUGIN)
add_subdirectory("SVG")
endif()
add_subdirectory("Debugger")
if(RMLUI_LUA_BINDINGS)
add_subdirectory("Lua")
endif()
```
--------------------------------
### Update and Draw Server-Managed Document
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
The core rendering loop for server-managed documents. Call `document_update` to recalculate layout, then `document_draw` to issue draw commands. Ensure `queue_redraw` is called to trigger rendering.
```gdscript
extends Node2D
var _doc_rid: RID
func _ready() -> void:
_doc_rid = RMLServer.create_document_from_path("res://ui/hud.rml")
RMLServer.document_set_size(_doc_rid, Vector2i(get_viewport_rect().size))
func _draw() -> void:
if not _doc_rid.is_valid():
return
RMLServer.document_update(_doc_rid)
RMLServer.document_draw(_doc_rid, get_canvas_item())
func _process(_delta: float) -> void:
queue_redraw() # trigger _draw each frame
func _exit_tree() -> void:
if _doc_rid.is_valid():
RMLServer.free_rid(_doc_rid)
```
--------------------------------
### Load RML Document from Path in Godot
Source: https://github.com/ghsoares/godot-rmlui/blob/main/README.md
Use this script to load an RML document from a specified path within your Godot project. Ensure the RML file exists at the given path.
```gdscript
extends RMLDocument
func _ready() -> void:
load_from_path("res://test.rml")
```
--------------------------------
### Load Custom Fonts
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Registers custom font files with RmlUi. Use `load_font_face_from_path` for project files or `load_font_face_from_buffer` for byte arrays. The `fallback_face` parameter marks a font for unrecognized glyphs.
```gdscript
extends Node
func _ready() -> void:
var server: RMLServer = RMLServer
# Load from project file
var ok: bool = server.load_font_face_from_path("res://fonts/MyFont-Regular.ttf")
print("Font loaded: ", ok) # true
# Load italic variant
ok = server.load_font_face_from_path("res://fonts/MyFont-Italic.ttf")
print("Italic loaded: ", ok)
# Load from a FontFile resource buffer (e.g., packed at export time)
var font_file: FontFile = load("res://fonts/FallbackFont.ttf")
if font_file:
var buffer: PackedByteArray = font_file.data
ok = server.load_font_face_from_buffer(buffer, "FallbackFont", true, false)
print("Fallback font loaded: ", ok)
# Now use the custom font in RCSS
# body { font-family: 'MyFont'; }
```
--------------------------------
### RMLDocument - as_element()
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Returns an RMLElement reference to the document's root () element, providing the entry point for all DOM traversal and mutation on the high-level node.
```APIDOC
## RMLDocument - as_element() -> RMLElement
Returns an `RMLElement` reference to the document's root (``) element, providing the entry point for all DOM traversal and mutation on the high-level node.
```gdscript
extends RMLDocument
func _ready() -> void:
load_from_rml_string("
Hello
")
var body: RMLElement = as_element()
print("Tag: ", body.get_tag_name()) # "body"
print("Children: ", body.get_child_count()) # 1
var p_el: RMLElement = body.get_child(0)
print("Text: ", p_el.get_text_content()) # ["Hello"]
```
```
--------------------------------
### RMLDocument - update()
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Forces an immediate layout pass. Call this after bulk DOM mutations if you need to read back layout geometry (e.g., RMLElement.get_rect()) in the same frame without waiting for the next render tick.
```APIDOC
## RMLDocument - update()
Forces an immediate layout pass. Call this after bulk DOM mutations if you need to read back layout geometry (e.g., `RMLElement.get_rect()`) in the same frame without waiting for the next render tick.
```gdscript
extends RMLDocument
func _ready() -> void:
load_from_path("res://ui/tooltip.rml")
var tooltip: RMLElement = as_element().query_selector("#tooltip")
tooltip.set_text_content("This is a very long tooltip message that wraps.")
update() # layout is now current
var r: Rect2 = tooltip.get_rect()
print("Tooltip size after text update: ", r.size) # e.g. (320.0, 48.0)
```
```
--------------------------------
### RMLServer.free_rid
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Releases all resources associated with a server-managed document, including its RmlUi context and render context. Must be called when the document is no longer needed to prevent memory leaks.
```APIDOC
## RMLServer.free_rid
### Description
Releases all resources associated with a server-managed document, including its RmlUi context and render context. Must be called when the document is no longer needed to prevent memory leaks.
### Method Signature
`free_rid(rid: RID)`
### Parameters
* **rid** (RID) - The resource identifier of the document to be freed.
```
--------------------------------
### Manage RMLElement Attributes
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Use `set_attribute()`, `get_attribute()`, and `remove_attribute()` to read, write, and remove arbitrary HTML-style attributes. Values can be strings, integers, or floats.
```gdscript
extends RMLDocument
func _ready() -> void:
load_from_rml_string("")
var hp_bar: RMLElement = as_element().query_selector("#hp")
if hp_bar.is_valid():
# Read current value (returns Variant; default_value used if absent)
var current = hp_bar.get_attribute("value", 100)
print("Current HP: ", current) # 100
# Update value
hp_bar.set_attribute("value", 65)
# Disable the input
hp_bar.set_attribute("disabled", true)
# Remove the disabled state
hp_bar.remove_attribute("disabled")
```
--------------------------------
### Enable Precompiled Headers
Source: https://github.com/ghsoares/godot-rmlui/blob/main/thirdparty/rmlui/Source/Core/CMakeLists.txt
Enables precompiled headers for the rmlui_core target if `RMLUI_PRECOMPILED_HEADERS` is set and the CMake version is 3.16 or greater. Otherwise, it prints a status message indicating the requirement.
```cmake
# RMLUI_CMAKE_MINIMUM_VERSION_RAISE_NOTICE:
# From CMake 3.16 we can skip the version check.
if(RMLUI_PRECOMPILED_HEADERS AND CMAKE_VERSION VERSION_GREATER_EQUAL "3.16")
target_precompile_headers(rmlui_core PRIVATE "${PROJECT_SOURCE_DIR}/Source/Core/precompiled.h")
elseif(RMLUI_PRECOMPILED_HEADERS)
message(STATUS "Could not enable precompiled headers, requires CMake version 3.16 or greater.")
endif()
```
--------------------------------
### Create and Append Table Element
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Creates a 'table' element and its child 'tr' and 'td' elements, setting text content for cells. The element must be appended to the DOM to render.
```gdscript
func build_table(doc_rid: RID, data: Array[Array]) -> void:
var root: RMLElement = RMLServer.get_document_root(doc_rid)
var table: RMLElement = RMLServer.create_element(doc_rid, "table")
for row_data in data:
var tr: RMLElement = RMLServer.create_element(doc_rid, "tr")
for cell_text in row_data:
var td: RMLElement = RMLServer.create_element(doc_rid, "td")
td.set_text_content(str(cell_text))
tr.append_child(td)
table.append_child(tr)
root.append_child(table)
```
--------------------------------
### RMLServer.document_process_event
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Forwards a Godot InputEvent to a server-managed document's RmlUi context, handling various input types. Returns true if the event was consumed by the document.
```APIDOC
## RMLServer.document_process_event
### Description
Forwards a Godot `InputEvent` to a server-managed document's RmlUi context. Handles mouse buttons, mouse motion, scroll wheel, keyboard, and touch input. Returns `true` if the document consumed the event.
### Method Signature
`document_process_event(document: RID, event: InputEvent) -> bool`
```
--------------------------------
### RMLServer `get_document_root()`
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Retrieves an `RMLElement` reference to the root element of a server-managed document. This allows for DOM manipulation using the same API as the high-level `RMLDocument.as_element()`.
```APIDOC
## RMLServer — `get_document_root(document: RID) -> RMLElement`
Retrieves an `RMLElement` reference to the root element of a server-managed document, enabling the same DOM manipulation API as the high-level `RMLDocument.as_element()`.
```gdscript
func populate_server_document(doc_rid: RID, items: Array[String]) -> void:
var root: RMLElement = RMLServer.get_document_root(doc_rid)
if not root.is_valid():
return
root.clear_children()
for item_text in items:
var li: RMLElement = RMLServer.create_element(doc_rid, "li")
li.set_text_content(item_text)
root.append_child(li)
```
```
--------------------------------
### Manipulate RMLElement DOM Tree in GDScript
Source: https://context7.com/ghsoares/godot-rmlui/llms.txt
Demonstrates DOM traversal and manipulation using methods like get_child_count, get_children, get_child, remove_child, append_child, and clear_children. Use this to dynamically modify the structure of RML elements.
```gdscript
extends RMLDocument
func _ready() -> void:
load_from_path("res://ui/inventory.rml")
var grid: RMLElement = as_element().query_selector("#item-grid")
if not grid.is_valid():
return
print("Slot count: ", grid.get_child_count()) # e.g. 16
# Iterate all children
for child in grid.get_children():
var slot := child as RMLElement
if slot.get_attribute("data-empty", "true") == "true":
slot.set_property("opacity", "0.3")
# Move first child to end
var first: RMLElement = grid.get_child(0)
grid.remove_child(first)
grid.append_child(first)
# Check parent linkage
print("Parent tag: ", first.get_parent().get_tag_name()) # "div" (grid)
# Remove all slots and rebuild
grid.clear_children()
for i in range(8):
var slot: RMLElement = create_element("div")
slot.set_attribute("class", "slot")
slot.set_attribute("data-empty", "true")
grid.append_child(slot)
```
--------------------------------
### Add RMLUI Lua Element Source Files
Source: https://github.com/ghsoares/godot-rmlui/blob/main/thirdparty/rmlui/Source/Lua/Elements/CMakeLists.txt
Configures the CMake build system to include specific source files for the RMLUI Lua elements. Uses absolute paths for robustness with different CMake versions.
```cmake
target_sources(rmlui_lua PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/As.h"
"${CMAKE_CURRENT_SOURCE_DIR}/ElementForm.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ElementForm.h"
"${CMAKE_CURRENT_SOURCE_DIR}/ElementFormControl.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ElementFormControl.h"
"${CMAKE_CURRENT_SOURCE_DIR}/ElementFormControlInput.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ElementFormControlInput.h"
"${CMAKE_CURRENT_SOURCE_DIR}/ElementFormControlSelect.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ElementFormControlSelect.h"
"${CMAKE_CURRENT_SOURCE_DIR}/ElementFormControlTextArea.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ElementFormControlTextArea.h"
"${CMAKE_CURRENT_SOURCE_DIR}/ElementTabSet.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ElementTabSet.h"
"${CMAKE_CURRENT_SOURCE_DIR}/SelectOptionsProxy.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/SelectOptionsProxy.h"
)
```