Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Zig RmlUi

⚠️ This project is in its early days. Data binding still needs additional work for structs and array types, and the API is subject to change

A library that contains Zig bindings for RmlUi, C++ user interface library based on the HTML and CSS standards.

Installation

Option A. Install with package manager

zig fetch --save https://github.com/silbinarywolf/rmlui/archive/REPLACE_WITH_WANTED_COMMIT.tar.gz"

Option B. Copy-paste the dependency into your project directly and put in a third-party folder. This is recommended if you want to easily hack on it or tweak it.

.{
    .name = .yourzigproject,
    .dependencies = .{
        .rmlui = .{
            .path = "third-party/rmlui",
        },
    },
}

Examples

  • SDL3: An example of how to get setup with SDL3 and how bindings work

How does this Zig library work?

I've handwritten a C-API wrapper that call out to the C++ code, similar to how cimgui works with ImGui.

However because the binding logic for RmlUi relies on C++ templating (generics), I've had to spend some time understanding how those types are registered with RmlUi and then write specific Zig code that works similarly, such as generating a type id dynamically once when a value is bound here.

Initialization and Loop

An example of what the setup and application loop looks like when consuming this library, based on the provided SDL3 example.

// This is an overly simplified example to give you the gist
// of how this library works
const rml = @import("rml");
const rmldebug = @import("rmldebug");
const rmlsdl = @import("rmlsdl");

pub fn main() !void {
    // Setup platform-specific interfaces (ie. SDL3)
    rml.setSystemInterface(...);
    rml.setRenderInterface(...);
    rml.setFileInterface(...);
    
    try rml.initialise();
    defer rml.shutdown();

    const context = try rml.createContext("main", 1280, 720, .default);
    defer context.destroy();

    try rmldebug.initialise(context);

    const lato_font_family_name = "Lato";
    try rml.loadFontFaceFromMemory(@embedFile("data/Lato-Regular.ttf"), lato_font_family_name, .{});

    // Example of data binding setup, based on the tutorial here:
    // https://mikke89.github.io/RmlUiDoc/pages/data_bindings/examples.html
    const MyData = struct {
        // FixedString is a Zig-API provided type with a fixed capacity, for two-way binding
        title: rml.FixedString(256) = .initComptime("Hello World!"),
        animal: rml.FixedString(128) = .initComptime("dog"),
        // []const u8 strings are readonly and cannot be updated in an <input> field, but you can bind and update them via "dirtyVariable"
        readonly_text: []const u8 = "the cat is meowing",
        show_text: bool = true,
    };
    var my_data: MyData = .{};
    const my_model = modelblk: {
        var dmc = try context.createDataModel("my_model", .default);
        try dmc.bind("title", &my_data.title);
        try dmc.bind("animal", &my_data.animal);
        try dmc.bind("readonly_text", &my_data.readonly_text);
        try dmc.bind("show_text", &my_data.show_text);

        break :modelblk dmc.getModelHandle();
    };

    // Load Document
    const document = try context.loadDocumentFromMemory(@embedFile("data/main.rml"), "data/main.rml");
    document.show(.default);

    while (!has_quit) {
        // Event Loop
        while (SDL_PollEvent(...)) {
             if (!rmlsdl.inputEventHandler(context, window, &sdl_event)) {
                // If false, then RmlUi consumed/processed that event, don't process it ourselves
                continue;
            }
        }

        // Update
        if (my_model.isVariableDirty("animal")) {
            my_data.title = try .format("Hello {s}!", .{my_data.animal.string()});
            my_model.dirtyVariable("title");

            my_data.other_text = "the cats meowing has ceased...";
            my_model.dirtyVariable("other_text");
        }
        _ = context.update(); // Run RmlUi input handling logic, etc

        // Draw
        sdl.SDL_SetRenderDrawColor(renderer, 20, 20, 20, 0);
        sdl.SDL_RenderClear(renderer);

        render_interface.beginFrame();
        _ = context.render(); // Render RmlUi
        render_interface.endFrame();

        sdl.SDL_RenderPresent(renderer)
    }
}

Credits

  • mikke89 for maintaining this awesome library.

About

Zig bindings for the RmlUi, the HTML/CSS user interface library

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages