A professional game-authoring environment for CNA — the C++ reimplementation of the XNA 4.0 framework.
Status: early. CNA Studio was bootstrapped on 2026-09-14 from the CNA Editor prototype developed in
cna-lab(seedocs/ORIGIN.md). That prototype is real, working software — it opens projects, edits scenes, drives gizmos, imports glTF, plays the game in a separate process and builds it — and it is the foundation this product is being built on. What is new is the goal: CNA Studio is a long-lived professional tool, not a prototype, and the roadmap to get there isplan.md.The default build stays dependency-free: no CNA checkout, no GPU, no window, 566 assertions across 17 CTest suites in about seven seconds.
The 3D viewport, orbited, with the example project's imported Crate.gltf standing in the grid
beside the two sprites.
CNA Studio produces CNA games, not CNA Studio games.
A game authored in CNA Studio is an ordinary CNA C++ project. You can open it in CLion, configure
it with its own CMakeLists.txt, build it with ordinary tools and ship it — with CNA Studio
uninstalled. Studio is an authoring environment and a productivity multiplier; it is never a
runtime dependency, never a mandatory build step, and never an opaque container the game lives
inside.
CNA Studio ← authoring environment (this repository)
↓ produces
CNA game project ← ordinary C++: source, assets, scenes, CMake
↓ builds against
CNA ← the framework
↓ runs on
platform + renderer + audio + input
CNA must be able to survive without CNA Studio. A game must be able to survive without CNA Studio. Every architectural decision in this repository is tested against those two sentences.
CNA Studio is not a new engine, and it is not part of CNA. It is a set of tools on top of CNA, built against the same public API a game uses:
- a document editor — scenes, entities, components, undo;
- an asset pipeline — stable ids, importers, dependency tracking;
- a runtime bridge — play mode in a separate
cna-playerprocess; - a plugin SDK — importers, component types, panels, gizmos, exporters.
A project declares which kind it is, so a pure XNA-style port is never forced through an entity model it does not want:
| Project kind | What Studio offers |
|---|---|
CnaNative |
Scenes, entities, components, inspector, gizmos, prefabs, play mode, a 2D and a 3D viewport |
XnaCompatible |
Asset browser, importer settings, content preview, renderer configuration, Play — and nothing else. The game keeps its own Initialize/LoadContent/Update/Draw |
The default build has no external dependencies — no CNA checkout, no GPU, no window:
cmake -S . -B build
cmake --build build -j
ctest --test-dir build --output-on-failureRequires a C++23 compiler (GCC 13+, Clang 16+, MSVC 19.38+) and CMake ≥ 3.20.
Try it against the bundled example project:
./build/cna-studio --headless --project=examples/HelloSprites/HelloSprites.cnaproject[info] cna-studio starting (ui=null, viewport=null)
[info] Opened project 'HelloSprites' (CnaNative) at .../examples/HelloSprites
[info] Assets: 4 found, 0 new, 0 moved, 0 missing
[info] Opened scene 'Level01' with 5 entities
The CNA-backed viewport is opt-in, because it needs two sibling checkouts:
cd ..
git clone https://github.com/libcna/cna.git
git clone https://github.com/libcna/sharp-runtime.git
cd cna-studio
cmake -S . -B build-cna -DCNA_STUDIO_WITH_CNA=ON -DCNA_DEVICES=ON
cmake --build build-cna -j
# Opens a real window with Studio in it.
./build-cna/cna-studio --project=examples/HelloSprites/HelloSprites.cnaprojectCNA itself needs SDL3's build dependencies (on Debian/Ubuntu: libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxi-dev libxfixes-dev libxss-dev libxtst-dev libxkbcommon-dev libwayland-dev wayland-protocols libdecor-0-dev) plus FFmpeg headers (libavcodec-dev libavformat-dev libavutil-dev libswresample-dev). -DCNA_DEVICES=ON is what gives Studio a
working clipboard.
| Option | Default | Meaning |
|---|---|---|
CNA_STUDIO_WITH_CNA |
OFF |
Build the CNA-backed viewport, UI renderer and input platform |
CNA_STUDIO_WITH_IMGUI |
ON |
Build the legacy Dear ImGui UI (vendored; no system dependencies) |
CNA_STUDIO_BUILD_TESTS |
ON |
Build the test suite |
CNA_STUDIO_WARNINGS_AS_ERRORS |
OFF |
-Werror / /WX |
CNA_STUDIO_CNA_ROOT |
../cna |
Where to find the CNA checkout |
CNA_STUDIO_PLAYER_BACKENDS |
(empty) | Extra renderers to build cna-player for. Each is a full CNA build |
Run cna-studio --help for the command-line options.
The native Studio UI (plan.md Phases 3-7) is being grown underneath the existing
Dear ImGui presentation. Its shell -- menu bar, toolbar, docks, viewport, status bar -- is real
geometry today but is not yet interactive, so it is reachable as a preview rather than as a UI
you can click:
./build/cna-studio --shell-preview=shell.png --shell-size=1280x720
# cna-studio: shell preview 1280x720, theme 'CNA Studio Dark', scale 1,
# 3 draw calls, 1380 vertices -> shell.pngThis needs no GPU and no display. The shell's geometry is CNA-free and is rasterised on the
CPU, which is the same property that gives it golden-image regression tests before graphical CI
exists. --shell-theme=light and --shell-scale=2.0 render the other theme and High-DPI.
┌─────────────────────────── cna-studio ────────────────────────────┐
│ Hierarchy Viewport Inspector │
│ Assets Console │
└───────────────────────────────────────────────────────────────────┘
│
┌────────────────────┴────────────────────┐
▼ ▼
cna-studio-ui-imgui cna-studio-context
(legacy, being replaced) (project, scene, registry,
│ assets, undo, selection)
│ UiDrawData ▼ ▲ UiInputState
└──────────────┬───┴──────────────┐
▼ │
cna-studio-viewport ──────────┘
← the ONLY module that links CNA
· CnaUiRenderer (draws the UI)
· CnaUiPlatform (mouse/keys/text)
· CnaStudioViewport (draws the scene)
┌────────────────────┬────────────────────┐
▼ ▼ ▼
cna-studio-scene cna-studio-assets cna-studio-project
└────────────────────┼────────────────────┘
▼
cna-studio-core
(Uuid · JSON · PropertyValue ·
ComponentDescriptor · CommandHistory)
cna-studio-plugins cna-studio-runtime-bridge cna-studio-player
(manifest, loading) (protocol, TCP, spawn) ─IPC─▶ (cna-player process)
Everything except cna-studio-viewport is CNA-free. That is enforced by the build graph, not by
review: a stray #include <Microsoft/Xna/...> elsewhere fails to compile.
Undo is a hard rule. Every document mutation is a StudioCommand pushed through
CommandHistory — from the inspector, from a gizmo, from a plugin, from the bridge. Retrofitting
undo is the mistake that cannot be repaired incrementally.
Reflection is hand-written. C++ has none, so ComponentDescriptor supplies it. The inspector,
the serialiser and SetPropertyCommand are all generic over it — including for component types
supplied by a plugin Studio was never compiled against.
Assets are referenced by id, never by path. Every asset gets a UUID in a .cnaasset sidecar.
Moving Assets/player.png into Assets/Characters/ touches no scene and breaks no reference.
Play mode is a separate process. Structurally required: Studio and the game are linked against different CNA builds and cannot share an address space. A game crash also cannot take Studio down.
The UI toolkit is behind an abstraction. No panel calls Dear ImGui directly — which is what makes replacing it (see below) a migration rather than a rewrite.
Studio's own UI is drawn with the same API a game has. No CNA::Internal::*, no authored
shader, no per-renderer code. If CNA cannot draw Studio's UI, that is a gap in CNA worth finding;
the ones found so far are in docs/CNA-GAPS.md.
.cnaproject, .cnascene, .cnaasset and .cnaprefab are CNA ecosystem formats, not Studio
formats. They did not change when the product was renamed, and they will not change without a
migration path and tests. Two JSON keys inside them still read editorState and
editorApiVersion: those are serialized contracts that existing files and built plugins already
depend on, and they are deliberately pinned. See docs/FORMATS.md.
cna-studio/
├── plan.md The CNA Studio master roadmap, STUDIO-NNNNN ids
├── ANALYSIS.md Architecture analysis inherited from the prototype
├── HANDOFF.md State of the work in progress
├── docs/
│ ├── ORIGIN.md Where this repository came from, and the verified baseline
│ ├── ARCHITECTURE.md The CNA Studio architecture
│ ├── CNA-GAPS.md Deficiencies in CNA that Studio has found
│ ├── FORMATS.md .cnaproject / .cnascene / .cnaasset / wire protocol
│ └── LEGACY-EDITOR-TASK-MAP.md Where the prototype's ED-* tasks went
├── include/CNA/Studio/ Public headers
├── src/ One directory per module
├── third_party/imgui/ Dear ImGui — legacy UI, being replaced
├── third_party/cgltf/ cgltf, with its symbols prefixed
├── tests/ 566 assertions, no third-party framework
└── examples/HelloSprites/ A project Studio opens end to end
House rules, matching CNA's own:
- C++23,
-Wall -Wextra -Wpedanticclean. // SPDX-License-Identifier: MS-PLat the top of every file.- Doxygen
@briefon every public type and method. - Every document mutation goes through a
StudioCommand. - Only
cna-studio-viewportmay include CNA headers. - New behaviour comes with a test. The suite runs headless in a few seconds.
- The UI layer talks to
UiDrawData/UiInputState, never straight to a toolkit or to CNA.
Microsoft Public License (Ms-PL), matching CNA. See LICENSE.

