Clay for Defold native extension

I’ve always been in favor of immediate mode GUI and I’ve used Clay for lots of side-projects. It’s a renderer-agnostic UI layout framework. I’ve put together a native extension to have Clay layout elements which are then mapped to native Defold GUI nodes.

Instead of Clay’s heavily macro’d C API, there’s a Lua interface. You can have a look at the example project to see how this works.

Clay itself is a really fast layout engine, tens of thousands of elements in less than a millisecond. And by using Defold layers, you can do a lot of batched draw calls. The speed bottleneck is in parsing big, nested Lua tables, unfortunately.

This derpy example lays out 11,366 UI elements, but we only have 267 Defold GUI nodes, and with batching it’s all done in 11 drawcalls.

12 Likes

Nice I will give it a try! Being bad at UI, I like code only layout solutions :sweat_smile:

I was searching for clay UI examples and stepped on this article:

This has nothing to do with your Clay UI but is a nice article about every UI elements and how to use them, seems usefull.

Anyway, I’ll try your extension, I like the fact that is use the native Defold GUI for rendering, I wonder if we can mix it with DRUID UI to layout Druid widgets?

1 Like

I’m not up to speed with how Druid works. If it needs some additional data to be propagated from Lua into the associated GUI node, then you can look at how slice9 is propagated as userdata in the native extension.

I had a look at your code, and I think it would be a bad idea to integrate a druid widget inside a Clay element. Druid is just a framework that use true defold gui nodes, but if Druid modify things on nodes, Clay would not know that they changed and it will probably break its layout.
But I have a question: can we use the defold api to modify Clay-generated nodes after the end_layout() ? Can we get the node_id back from Clay and act on the node?
Like if clay was doing the initial layout then we act on the nodes with gui api?

Anyway, I think we can easily do the reverse: create a Druid widget that has a node which is the root of a Clay surface.
Like this, the tree hierarchy stay separated and in control of each engine.
Like we could have a Druid UI but for a specific menu use Clay to render a responsive flex layout in an area.

I will give it a try.

This would be cool as the thing that bothers me with Imgui is that it is rendered outside of the defold gui system, you cannot integrate it into an existing defold gui.

Feel free to play around with it! I think I should have stated a little bit more clearly what my intended outcome with this was :slight_smile:

Passing back the GUI nodes’ ids to Lua after end_layout is a bit tricky. It’s dealing with the two opposed UI paradigms in immediate and retained mode. The architecture I went for was to make Defold’s GUI nodes invicible. They will be added, removed, or reused on each update. I can’t guarantee a node persists, like in retained mode.

However, you can create multiple Clay surfaces, attached to different GUI root nodes, and call begin/end layout on them. Each surface comes with a little bit of overhead, but you can intentionally set a low max number of elements.