Projects: the Editor, Projects, Templates, and Packaging

← Overview | Code Reload | Status & Roadmap | Home

Status: Designed, not implemented.


The Problem

A project's code is compiled into the editor: Playground.exe is the editor and the Playground game in one executable, and the project folder is fixed when it is built (TNX_PROJECT_DIR). So:

  • the engine can't be packaged on its own: scripts/package.py ships the editor only with Playground in it;
  • a new project means copying a folder and its CMakeLists.txt by hand, and the editor can't open it;
  • there are no templates, and nothing to share one with.

The Idea

The editor is a program of its own that opens a project. A project is a folder with a project file, its content, and its C++, built as a module the editor loads. The engine is a shared library in development builds, so the editor, the project's module and the project's game executable all use one copy of it. A packaged game links everything statically, as today, and pays nothing for any of this.

Engine and project are meant to be built together: one CMake tree, one IDE, changes to either in the same session. The editor can also build the project itself, for anyone without an IDE open.

Every project has C++. Node graphs are C++ (TrinyxParser reads annotated methods into graphs and graph edits are written back as code), so a project's module exists from the first moment, even if it only holds a game mode.

Loading the project's module is the same mechanism as reloading it: that design's first stage is this design's foundation.


Shape

A project

MyGame/
  MyGame.tnxproject      the project's name, its module, and the engine it was made with
  MyGameDefaults.ini     the project's settings (default scene, start state, rates, limits)
  EditorDefaults.ini     the editor's overrides of them
  Keybinds.ini           input bindings
  CMakeLists.txt         generated once; the project owns it from then on
  src/                   the module's C++ (Constructs, game modes, widget classes, graphs)
  content/               scenes, widget assets, strings, meshes, ...
  Saved/                 per-user state: layouts, settings, logs (ignored by version control)

The project file is JSON, like every other Trinyx file, and small: what can't be found by looking in the folder. Settings stay in the .ini files, so nothing is in two places.

{
    "project": "MyGame",
    "version": 1,
    "module": "MyGame",
    "engine": { "version": "0.9", "path": "D:/Dev/TrinyxEngine" }
}

module is left out when it is the project's name. A program opens a project with --project <file or folder>; without it, the folder its build names (TNX_PROJECT_DIR), or for a packaged game the executable's folder.

engine.path is where the engine's source is, relative to the project or absolute; empty means the engine installed on this machine (below). New projects go in a Trinyx Projects folder in the user's Documents by default; New Project can put one anywhere.

CMake: one function

The engine provides trinyx_add_project(<Name> [SOURCES ...]). A project's CMakeLists.txt is a few lines that call it; the function makes:

TargetDevelopment buildsPackaged game
<Name>ModuleShared library of the project's code, linking the engine's shared libraryStatic, linked whole into the game
<Name>Small game executable that loads the moduleThe whole game, statically linked
TrinyxEditorThe engine's editor host (one per engine, not per project)Not built

It also sets what TNX_PROJECT_DIR sets today, from the project file, so the project folder is never compiled in.

The engine as a shared library

In development builds the engine (Trinyx), GG-UI (GGUI, GGUIText) and Foundation are shared libraries; a packaged game links them statically.

  • Exports are marked by hand, one macro per library (TNX_API, GGUI_API, GGUITEXT_API, FOUNDATION_API), on whole classes and on free functions. What isn't marked isn't public, even in a public header, on Windows and on Linux (built with hidden visibility). Templates need no mark; the non-template core under one does.
  • One copy of shared state. Singletons and registries keep their instance in the library's sources, never in a header, so every module sees the same one.
  • Type IDs by name. A component's or entity type's ID is asked of the engine by the type's name the first time a module uses it, then cached. Every module gets the same ID, and a reloaded module gets the ID it had before.
  • Checked, not remembered. A script lists public classes and functions without a mark (presubmit runs it), and a test module that includes every public header must link.

Two ways to lay out the tree

  • Engine workspace: the engine repository at the top, projects as folders in it (as Playground, Testbed and ResilienceDemo are today). For engine development.
  • Project workspace: the project at the top; its CMakeLists.txt adds the engine from engine.path (add_subdirectory) or finds the installed one (find_package(Trinyx)). For game development, with the engine's source in the same IDE when it is a source engine.

Both build the same targets. A project created by the editor gets the project-workspace layout.

Engine build options

Some engine options are compile-time (TNX_ENABLE_ROLLBACK, TNX_DETERMINISM, TNX_ENABLE_NETWORK, entity limits). The project file lists the ones the project needs, and its tree builds the engine with them. An installed engine ships built for the default set, plus its source: a project that changes an option builds the engine from that source in its own tree, without the engine's folder being written to.

The editor without a project

TrinyxEditor started with no project shows the Project Browser: recent projects, Open (a folder or a .tnxproject), and New Project. Started with a project (TrinyxEditor MyGame.tnxproject, or a double-click on the file), it loads that project's module and opens its default scene. File gains Open Project… and Recent Projects; switching project unloads the module the way a reload does, then loads the other one.

Building from the editor, or not

Two setups, the same result:

  • The IDE builds. The editor watches the module's output and loads a new build when it appears (the Code Reload path). The editor never runs a compiler.
  • The editor builds. Build (and Build and Reload) runs CMake for the project's tree, with its output in the Log panel and its errors in a Problems list that opens the file at the line. This needs a compiler on the machine; the Project Browser checks for one and says what to install when it's missing.

The project's Saved/ settings say which one this machine uses; both can be on.

New Project and templates

A template is a project folder plus a template.json: name, description, preview image, category, the engine version it needs, and the names to replace when a project is made from it (the template's project and module names become the new project's in file names, the project file, and code).

  • Built-in templates live in the engine (Templates/). The first is Blank: a game mode, a start state, and an empty scene. Others (a player with a camera and a HUD; Host, Join, and Solo menus) come as their features settle.
  • New Project shows them with their previews; you choose one, a name, and a folder. The editor copies it, replaces the names, writes the project file and CMakeLists.txt, builds the module (or waits for the IDE to), and opens the project.
  • Your own templates: File > Save Project as Template… writes a project as a template (without Saved/ and build output). A template packs into one .tnxtemplate file (a zip of the folder) to share; Add Template… in New Project, or a double-click on the file, installs it into the user's template folder. A template made with an older engine is listed with what it needs.

Packaging

  • Package Project (File menu, and scripts/package.py --project MyGame.tnxproject for CI): builds the project's game executable in its packaged configuration (static, TNX_PACKAGE), stages its content, config, the engine's assets and shaders, and the runtime libraries it needs, and writes a folder and a zip. The menu and the command line run the same code and write the same thing.
  • Package Engine (scripts/package.py --engine): the editor, the engine's shared library built for the default options, its headers, its CMake package (TrinyxConfig.cmake), its source, and the built-in templates. Unzipped anywhere, it opens to the Project Browser and can make, build, and package projects.
  • package.py's current Editor and demo modes become Package Project of Playground and of ResilienceDemo.

Stages

  1. Foundation: the editor opens a project.
    • The engine as a shared library in development builds; trinyx_add_project; Playground, ResilienceDemo, and Testbed moved onto it.
    • The project file; the project folder found at runtime, never compiled in.
    • TrinyxEditor as its own executable, loading a project's module: Code Reload stage 1 (module-owned registries, the safe point, unload and load in order), which reload then reuses.
    • The Project Browser (recent, open), and Open Project in the editor.
    • Package Engine and Package Project from the command line.
    • A Testbed test makes a project from a template in a temporary folder, builds its module, loads it, and unloads it.
  2. Production: projects from inside the editor.
    • New Project with the Blank template; Save as Template; .tnxtemplate files to share and install.
    • Build and Build and Reload from the editor, with errors in a Problems list; a check for a compiler.
    • Package Project from the File menu, with its progress and output in the Log panel.
    • Engine build options per project.
  3. Differentiators.
    • Upgrading a project to a newer engine: the project file records the version it was made with, and the editor lists and applies what changed (renamed types, moved files) as one undoable step, with a report.
    • Packaging profiles in the project file (platform, configuration, which content), run the same from the menu and from CI, with the build cached between runs.
    • Templates that ask for options when used (networked or not, which starter HUD), built from the same widget and project-file machinery.

Later

  • Source control: New Project writing ignore rules (Saved/, build output) and starting a repository comes with source control in the editor, not before.
  • More templates: a player with a camera and a HUD made in the widget designer; a networked game once Host, Join, and Solo is in.