Tiny enough
for an MCU.
A modular C++ 2D engine. Drive an LCD from an ESP32, run the same project on Windows through SDL3, or drop rendering entirely and use it as a headless component framework. Every part is a package you can leave out — the renderer included.
Write the component.
The inspector builds itself.
Fields tagged DEKI_EXPORT are picked up at build time by
the C++26 static-reflection codegen. That one tag is what drives the
inspector widget, MessagePack serialization, undo, and asset
resolution — there is no second place to register anything.
The whole window
Hierarchy and asset browser on the left, scene canvas and console in the middle, inspector on the right. Every panel is an ImGui dock — drag them wherever you want them.
One tag, and the inspector follows
Bobber.h declares two floats and tags them
DEKI_EXPORT. Nothing else registers them anywhere: the
sliders on the right, their ranges, the undo entries and the MessagePack
fields all come from that tag at build time.
DEKI_CATEGORY("Demo") DEKI_DESCRIPTION("Bobs the object up and down on a sine wave.") class Bobber : public Deki::Component { public: DEKI_EXPORT DEKI_SLIDER(0, 64) float amplitudePx = 12.0f; DEKI_EXPORT DEKI_SLIDER(0, 4) float speedHz = 0.6f; DEKI_EXPORT DEKI_SLIDER(0, 1) float phase = 0.0f; void Awake() override; void Update() override; };
#include "Bobber.h" #include <cmath> void Bobber::Awake() { if (Deki::Object* owner = GetOwner()) m_BaseY = owner->GetY(); } void Bobber::Update() { Deki::Object* owner = GetOwner(); if (!owner) return; m_ElapsedS += Deki::Time::GetDeltaTimeF() * 0.001f; // Positions are in meters; the exported amplitude is in pixels so // the inspector value matches what you see on a 320x240 panel. const float ppm = Deki::EngineSettings::Global().pixelsPerMeter; const float wave = std::sin((m_ElapsedS * speedHz + phase) * 6.283185307f); owner->SetY(m_BaseY + (amplitudePx / ppm) * wave); }
The scene tree
Ctrl-click and shift-click to multi-select, drag to reparent or reorder. Structure edits go through the same command history as value edits, so undo covers both.
Pixel-exact with the target
Not an approximation. Edit mode calls the same
RenderToBuffer() as play mode and as a device build, at
whatever the panel actually is — 320×240 here — so
the editor, play mode and the board agree. Rendering is just one
package: leave it out and the rest of the engine still runs.
Everything you need.
Nothing you don't.
Components with reflection
One base class. A class deriving from Deki::Component that declares Awake / Start / Update runs; one that declares none is data. Tag a field DEKI_EXPORT and it appears in the inspector, serializes, and resolves its assets.
Visual editor
Dear ImGui + SDL3 + OpenGL. Hierarchy, inspector, asset browser, console, profiler, and undo that merges continuous edits into one entry.
Hot reload
Edit a component, focus the editor, and it rebuilds and swaps the package and plugin DLLs in place. No restart, no scene reload.
Software renderer
One QuadBlit pipeline, four output formats: RGB565, RGB565A8, RGB888, ARGB8888. Dirty rectangles keep partial panel updates cheap on battery.
Embedded + desktop
ESP32 through ESP-IDF, Windows through SDL3. Platform setup lives in its own package, so retargeting does not touch your code.
Packages as DLLs
Every package is a standalone shared library, never baked into the core. Ship with no rendering, no input, no audio — just the lifecycle.
Asset pipeline
JSON .scene files and .tex textures, keyed by GUID, exported to MessagePack for the device. AssetRef<T> fields resolve to live pointers during Awake.
Tweens & easings
31 easings across Sine, Quad, Cubic, Quart, Quint, Expo, Circ, Back, Elastic and Bounce — as a TweenComponent or straight from TweenManager.
In-editor profiler
Hierarchy, flat and flame-graph views, memory stats and frame capture to PNG, in the editor, with no external dependency.
One codebase.
Tiny boards to big screens.
Swap the integration package to retarget. Display and input are optional too — leave them out for headless services and data loggers.
ESP32
The primary embedded target. Integration is against ESP-IDF itself,
so any variant the SDK supports is in scope.
deki-esp32-integration and
deki-lovyangfx-integration cover SD, memory, display
and touch, and the editor pipeline runs through to hardware.
Windows desktop
Window, input and filesystem via deki-sdl3-integration
and deki-desktop-integration. This is what the editor
itself runs on.
Linux desktop
The engine, the editor and the same two integration packages build and run on GCC 16, verified end to end on a Steam Deck. Opening a project and saving a scene go through the system's own file chooser.
float. Soft-float runs
everything, just much slower.
Sensors in the scene tree.
The engine defines the interfaces (IDekiRTC,
IDekiGPS, IDekiIMU, IDekiAudio).
Chip-specific components implement them and drop into a scene like
anything else, configured in the inspector.
IDekiGPS.Ready to build?
The engine and its packages are on GitHub under Apache 2.0 and usable today. The editor isn't packaged for release yet — leave an email and you'll hear the day it is.