About Store Forum Documentation Contact



Post Reply 
RmlUi
Author Message
Fex Offline
Gold Supporter

Post: #1
RmlUi
Claude Code was able to one-shot RmlUi integration into Esenthel.

I'm not a web-dev person, but with Vibe Designing coming soon
( e.g. https://claude.ai/design ) , I think there is value in having a UI
system defined by a declarative language like HTML/CSS.

This also makes it much easier for users to mod or skin the UI if they
want. But really, it's about making it easier for the AI to do it.
Claude Code really seems to struggle with building Esenthel GUIs
programmatically that look good and have the correct font size, etc.,
but with HTML/CSS this problem doesn't exist.

I haven't profiled this, the implementation has not been optimized,
and I'm sure there is a performance penalty. That said, RmlUi is
highly regarded and is designed for games; it is not a full WebKit.

An integration of RmlUi v6.2 (MIT) as
a retained-mode HTML/CSS UI library that coexists with Esenthel's built-in
Gui system without touching it. Both run in the same frame — the native
widget set is still available for lightweight 3D-integrated controls, while
RmlUi handles HTML/CSS/animation-heavy UI (menus, HUDs, settings screens,
chat windows). A single RmlUi render backend lives inside the Engine static
library and drives RmlUi's vertex stream through the engine's existing 2D
batcher, so every renderer backend (DX11, DX12, Vulkan, OpenGL) gets RmlUi
for free with zero backend-specific code.

Game HUD tutorial
[Image: nWMwv7tq]


Using Esenthel GUI elements and RmlUi elements side-by-side tutorial
[Image: 3cB1Nk65]


Quick start:

Code:
#include "Gui/RmlUi.h"                            // EE::RmlUi::* facade

// In a single .cpp where you author Rml event listeners, DOM manipulation,
// etc. — wrap the RmlUi includes so Esenthel macros and X11 defines don't
// collide with RmlUi's template parameters and enum names:
#include "../../ThirdPartyLibs/begin.h"
#undef T1  #undef T2  #undef T3  #undef T4  #undef T5
#undef T6  #undef T7  #undef T8  #undef T9  #undef T10  #undef T11
#undef Always  #undef NotUseful
#include <RmlUi/Core.h>
#include "../../ThirdPartyLibs/end.h"

static Rml::Context         *Ctx=null;
static Rml::ElementDocument *Doc=null;

Bool Init()
{
    EE::RmlUi::Init();                                                 // install render + system interfaces
    EE::RmlUi::LoadFontFace("Data/RmlUi/LatoLatin-Regular.ttf");
    Ctx=EE::RmlUi::CreateContext();                                    // sized to D.resW()/D.resH()
    Doc=Ctx->LoadDocument("Data/RmlUi/demo.rml");
    if(Doc)Doc->Show();
    return true;
}
void Shut()   { EE::RmlUi::Shut(); }
Bool Update() {
    if(Kb.bp(KB_ESC))return false;
    Gui.update();
    EE::RmlUi::PumpInput(Ctx);                                         // Ms/Kb -> context
    EE::RmlUi::Update   (Ctx);                                         // events, animations, dirty geometry
    return true;
}
void Draw()   {
    Renderer(RenderScene);                                             // optional 3D world
    Gui.draw();                                                        // Esenthel Gui above 3D
    EE::RmlUi::Render(Ctx);                                            // RmlUi on top of everything
}

Shipped features:
  • Single-TU backendEngine/Source/Gui/RmlUi.cpp is the only engine
    source file that includes RmlUi headers. It subclasses
    Rml::RenderInterface and Rml::SystemInterface, owns the 1×1 white
    fallback texture, and exports the EE::RmlUi:: facade used by app code.
    Macro pollution is neutralised locally: Esenthel's template-shortcut
    macros T1..T11 (from Engine/H/_/defines.h, they collide with
    robin_hood.h's template parameters) and X11's Always / NotUseful
    (not stripped by Engine/H/_/headers.h) are undefined inside the
    ThirdPartyLibs/begin.h / end.h bracket just for this one TU.
  • API-agnostic renderingRenderGeometry feeds RmlUi's pixel-space
    vertex stream into the engine's existing 2D path. Per-vertex
    conversion goes through D.pixelToScreen(Vec2) (canonical helper; no
    hand-rolled Y-flip). D.alpha(ALPHA_MERGE) handles RmlUi's
    premultiplied RGBA (which it emits since v5). Scissor goes through
    D.clip(&engine_rect) / D.pixelToScreen(RectI). Works identically on
    DX11, DX12, Vulkan, OpenGL.
  • Untextured-path fallback — RmlUi calls RenderGeometry with
    texture=0 for solid-colour geometry. The backend binds a pre-built
    1×1 opaque-white Image so the textured shader path effectively
    degenerates to plain vertex colour. This avoids needing a separate
    colour-only code path.
  • FreeType sharing — RmlUi's default FreeType font engine is pointed
    at Esenthel's prebuilt EE_FreeType static lib via
    FREETYPE_INCLUDE_DIRS / FREETYPE_LIBRARY cache vars in
    ThirdPartyLibs/RmlUi/CMakeLists.txt, so one copy of FreeType ships in
    the final link. EE_RMLUI_USE_BUNDLED_FREETYPE=ON is an escape hatch
    if the prebuilt's config flags ever diverge from what RmlUi expects.
  • Texture uploadLoadTexture routes to Image.Import, accepting
    every format Esenthel's asset pipeline supports (BMP/PNG/JPG/JXL/WEBP/
    AVIF/HEIF/TGA/TIF/DDS/PSD/ICO/HDR). GenerateTexture uploads raw
    RGBA8 via a soft image, lock/write, row-copy, unlock, and GPU upload
    (used for the font atlas and procedural decorator textures).
  • Dual-mode input pumpEE::RmlUi::PumpInput(ctx) polls
    mouse position, mouse buttons, and wheel every frame, walks all
    256 KB_KEY values firing key down/up events on edge changes, and
    pumps text characters out of Kb.k.c. When the focused RmlUi element
    is an input field or textarea the key queue is drained so fast typing
    never drops characters; otherwise the head of the queue is peeked
    non-destructively so the built-in Gui still sees the same keys on the
    same frame.
  • Opt-in via CMakeoption(EE_RMLUI "... " ON) in the root
    CMakeLists.txt, default ON on Linux x64 + Windows x64, fatal on iOS
    / Android (deferred until those platforms are tested). With
    EE_RMLUI=OFF every integration TU is empty, the
    rmlui_core / rmlui_debugger targets are not added to
    the build graph, and the tutorial targets are skipped in
    Tutorials/CMakeLists.txt.
  • Built from source — RmlUi v6.2 is vendored at
    ThirdPartyLibs/RmlUi/lib/ and compiled via subdirectory inclusion so
    rmlui_core + rmlui_debugger become Engine interface link deps.
    No prebuilt library like the other third-parties, because upstream
    ships clean CMake and the library is small. ABI-visible flags are
    forced onto both targets so they match Engine's ABI.
  • Debugger overlayrmlui_debugger is linked automatically when
    EE_RMLUI=ON. Call Rml::Debugger::Initialise(ctx) once, then
    Rml::Debugger::SetVisible(true) (or bind to a key) to pop up the live
    inspector — Event Log, Element Info, Outlines, Data Models tabs.
  • Thin facadeEngine/H/Gui/RmlUi.h exposes only the
    EE::RmlUi:: lifecycle and helper functions. It forward-declares
    Rml::Context, ElementDocument, RenderInterface, and
    SystemInterface, so app translation units that just drive lifecycle
    do not pay to parse all of &lt;RmlUi/Core.h&gt;. App translation units
    that want event listeners, DOM mutation, or typed element access can
    include &lt;RmlUi/Core.h&gt; themselves.

Non-invasive integration — zero changes to Engine/Source/Gui/Gui.cpp,
Gui.draw, Gui.update, no new state in DisplayClass, no new
alpha mode, no new shaders. The pre-existing VI + D 2D path is the
only rendering surface used; the existing 2D shaders are the only ones
touched. The tutorial harness (Tutorials/TutorialAuto.{h,cpp},
Tutorials/stdafx.h) is unchanged. EE_RMLUI=OFF builds are
pixel-identical to pre-integration builds (verified against
Tutorial_05_Bars, Tutorial_04_BatchedDrawing,
Tutorial_12_RenderToTexture).

RCSS gotcha — RmlUi's transition/animation parser recognises tween
names as defined in Source/Core/PropertyParserAnimation.cpp. Unlike
standard CSS, it does not accept bare linear or the CSS keyword
ease; use linear-in-out and cubic-in-out (or any of the
supported {back,bounce,circular,cubic,elastic,exponential,linear,quadratic,quartic,quintic​,sine}-{in,out,in-out}
variants). Multi-transitions are comma-separated.

Deferred work:
  • Custom Rml::FontEngineInterface on top of Esenthel's Font class, so
    .pak-packaged fonts could feed RmlUi. Upstream's default FreeType
    engine is sufficient for now; TTF files ship alongside the tutorials.
  • Rml::FileInterface on EE::File — would let RmlUi resolve
    .rml / .rcss / texture paths through engine .pak archives. The
    stdio fopen default is used currently; tutorials ship plain files
    under Tutorials/Data/RmlUi/.
  • Data Binding (MVC layer via Rml::DataModelConstructor) — supported by
    the linked rmlui_core but not yet demonstrated by a tutorial.
  • Lua bindings (rmlui_lua) — disabled in the wrapper (RMLUI_LUA_BINDINGS=OFF);
    enabling would require wiring an Esenthel Lua runtime into the engine
    first.
  • Windows smoke sweep via run_smoke_test.ps1. Linux is covered
    (all five tutorials + three regression targets pass).

Available in this repo:
https://github.com/DrewGilpin/EsenthelEngine
Yesterday 02:58 PM
Find all posts by this user Quote this message in a reply
RedcrowProd Offline
Member

Post: #2
RE: RmlUi
interesting amount of work done by claude, have you tried running an actual project with it ? how production ready is it if you try to build something with it ?
what is the cost if you dont mind sharing?
Today 01:21 AM
Find all posts by this user Quote this message in a reply
Fex Offline
Gold Supporter

Post: #3
RE: RmlUi
For my actual job we ship software updates to customers every week where every line of code has been written by AI, it writes better code than the majority of professional programmers, people saying otherwise are just coping. Speed-wise, there is no comparison, months of work done in hours by AI. Days of work done in minutes.

The Claude Code I use is the $200 a month plan (20x). It is used on the command line, I start every feature by telling it "use plan mode" and tell it to "ultrathink" on the majority of the prompts. This week I have used 41% of the "usage" allotment with 2 days left in the week. Last week when doing the DX12/Vulkan renderers I used 91%, I was actively trying to use as much as possible that week having it running on 3 other repos besides the engine most of the week as much as I could prompt.

It builds game features just as quickly. For example it added an SQL ACID compliant banking/inventory/trading system to a multiplayer game in ~2 hours of it working (human testing/iteration took another ~4 hours). This wasn't a simple integration either, it is a backend system with multiple database servers, multiple physics servers (need to check that players are not dead/in range etc), multiple connection servers, and clients connected via UDP. It also wrote integration and unit tests as part of this work.

I feel compelled to use it, as I think AI is being heavily subsidized now, I'm afraid in the future hosted AI inference will no longer be this cheap. I hope I am wrong, but I see it being like Uber/Lyft etc were when they were in the "capture market share" mode, where they were losing money providing the best service possible.
Today 01:35 PM
Find all posts by this user Quote this message in a reply
Post Reply