Thank you! You have successfully joined our subscriber list.
Sorry, our system has encountered an error. Please try again later or contact us.

Spring Update

By Martin Fouilleul — 2025-04-07

Hello! In keeping with my six months blogging cadence, here’s a fresh batch of news on Orca. I mention our new Discord server and my apperance on Zig Showtime, discuss changes in our UI styling API, and report on work in progress such as the Orca debugger or the Zig bindings.

New Discord Server

Orca has its own Discord server now! For a while we were kindly hosted by the Handmade Network, but it was about time we got our own space. The server is used to showcase our work-in-progress, help people try out Orca in its early stage, discuss its design and implementation, and organize our efforts with the project’s contributors. If you’d like to chat or get more frequent sneak peeks of what we’re building, see you there!

Zig Showtime

I’ve recently been invited by Loris Cro on Zig Showtime. I demoed how to write an Orca application from scratch, we discussed about the long-term vision of Orca, and I went into a pretty detailed blackboard session explaning our vector graphics rendering tech. This made for a long chat! It was a blast, and I hope you enjoy it as much as I did.

UI Styling Revamp

Following feedback from early testers, I decided to redesign the styling and theming APIs of our UI system. This consists in the following changes:

Removing style inheritance

Previously, some style attributes, like the background color or the font size, where inherited from the parent box in a style stack fashion (and set to default values by a “theme” struct passed at the beginning of the UI frame). This made for some confusion as to which attributes should be inherited (inheritence doesn’t always make sense), and where was a given attribute inherited from. It also didn’t save much typing in the end, as you’d typically end up re-specifying a bunch of inherited attributes for each widget anyway, as they would often be different from their “container” parent.

These are annoyances that plague style stacks and CSS alike, and I wasn’t happy with it, so we just got rid of style inheritence altogether. Each box now starts with default (ie. zeroed) style attributes, and you have to specify those you care about. Note that you can still set the attributes for a bunch of boxes at once, by using style rules. But the targeting of these boxes is explicit, rather than being defined by their ancestors in the UI tree.

Allowing style attributes to be set directly

Our previous API allowed you to set style attributes through a style struct and style flags: you’d pass a struct containing the values for the attributes you cared about, and the others zeroed out. But since some attributes have legit zero values, you also had to pass a combination of style flags to specify which attributes to apply. This ended up looking like this:

oc_ui_style_next(&(oc_ui_style){
        .size.width = {OC_UI_SIZE_PARENT, 1},
        .size.height = {OC_UI_SIZE_CHILDREN},
        .bgColor = {1, 0, 0, 1},
    },
    UI_STYLE_SIZE | UI_STYLE_BG_COLOR);

oc_ui_box("styled box")
{
    // This box is styled according to the above rule.
}

Not only was it redundant (since the flags you had to specify were essentially repeating the style struct designated initializers), but it also proved cumbersome to make idiomatic bindings for this pattern in other languages.

Note that it was also going through the style rule system, oc_ui_style_next only being a helper to create a rule matching the next box. This made it a bit hard to see where styling was happening when the oc_ui_style_next call was made far before the oc_ui_box call.

I decided to scratch that and let style attributes be specified by individual calls, as well as put this specification inside the styled box:

oc_ui_box("styled box")
{
    oc_ui_set_size(OC_UI_WIDTH, (oc_ui_size){OC_UI_SIZE_PARENT, 1});
    oc_ui_set_size(OC_UI_HEIGHT, (oc_ui_size){OC_UI_SIZE_CHILDREN});    
    oc_ui_set_color(OC_UI_BG_COLOR, (oc_color){1, 0, 0, 1});
}

Simplifying the specification of style rules

Specifying style rules was fairly annoying, involving a builder API to create the rule pattern by appending box selectors to a list, and explicitly managing the rules ordering. To simplify this, I wrote a little parser that builds the pattern from a string, and also changed the way in which rules’ styles are specified to mirror that of boxes:

oc_ui_style_rule("foo.hover .button")
{
    oc_ui_set_size(OC_UI_WIDTH, (oc_ui_size){OC_UI_SIZE_PARENT, 1});
    oc_ui_set_size(OC_UI_HEIGHT, (oc_ui_size){OC_UI_SIZE_CHILDREN});    
    oc_ui_set_color(OC_UI_BG_COLOR, (oc_color){1, 0, 0, 1});    
}

The rule above will match all boxes that have the button tag, and are a descendent of a box named foo that is currently hovered by the mouse.

Introducing style variables

In order to style a UI with a consistent “theme”, it is useful to define style variables that can contain frequently used values. This is done like so:

oc_ui_var_set_i32("myVar", 16); 

You can also create a variable and assign it a default value only if the variable is not already declared:

oc_ui_var_default_i32("myVar", 16);

You can then use the variable to set style attributes:

oc_ui_style_set_var(OC_UI_TEXT_SIZE, "myVar");

Themes are implemented as a set of predefined style variables, which the widgets use to specify their default style. You can tweak the theme by changing the values of those variables.

Added together, these changes made our usage code both shorter and more explicit. It also greatly simplified jumping into the prototyping of our internal debugger’s UI.

Debugger Progress

Speaking of which, I’m making good progress on the Orca debugger, and in the process I’m probably learning a lot more about the Dwarf file format than is healthy for a living organism. The Dwarf situation is more or less what you’d expect when scope creep meets backwards compatibility. We’ll most likely exfiltrate ourselves from this rat’s nest by translating the bits we need to a saner custom format, but in the meantime I’m neck deep in this tangled mess.

Yet, I’m at a point where we can set breakpoints and line step through the source code. I also have a source tree explorer of sorts, a callstack, and a list of in-scope variables. There’s still some work left to compute the locations of these variables and extract their types, in order to display their values in the watch window.

Orca Debugger Source View

You can also browse a list of all the symbols found in the app’s WebAssembly module, and see a bytecode view of each function, along with the values of their registers:

Orca Debugger Bytecode View

Zig build system and Zig bindings

We’ve been testing out Reuben’s Zig build script in a development branch for a little while, and it’s great. It takes care of fetching and checking the correct dependencies, driving code generation, caching artifacts, and only rebuilding what’s necessary. It still needs some tweaks and cleanup, but we should be able to switch to it entirely and leave our kludgy python scripts behind soon! This should make it a lot easier to onboard new contributors, so I’m pretty excited about it.

Julian has undertaken a rewrite of the Zig bindings to make them more idiomatic to Zig, as well as sync them with the latest API changes. Previously we had a script to generate Zig APIs from our language-agnostic API definition contained in a api.json file, but automatic translation only gets you so far. Now the idea is to target a specific version of the API definition, but manually write higher quality bindings. This way the bindings maintainers can easily track changes to the the API file (or even flag them automatically in CI), and update bindings accordingly. Basing the bindings on the api.json (as opposed to the C headers) also helps identify lacking metadata in the API (e.g. bounds checking or mutability annotations), which would be useful for other languages as well.

Until Next Time

Thanks for reading! I hope this update made you excited about the work we’re doing. If so don’t hesitate to join the Orca Discord server and start a conversation! As a reminder, if you want to support Orca and help me push it forward, you can do so by donating on Github Sponsors. Any help is greatly appreciated!

I wish you a wonderful spring~