Import Oxide engine (Stages 0–10) under MIT license
Full project snapshot migrated to new Gitea remote without history: engine, editor, physics, script, examples, tests, docs, and assets. Relicensed from GPLv3 to MIT and updated repo URLs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# Project System
|
||||
|
||||
`oxide_engine::project` defines what a game is, on disk: a **project**. A project
|
||||
is a root directory containing a project file plus a defined folder layout. The
|
||||
format lives in the engine (not the editor) because the exported runtime and the
|
||||
Stage-16 packer read it too — the editor just adds the create/open/save UI.
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
my-game/
|
||||
├── project.oxide # the project file (RON)
|
||||
├── scenes/ # scene files
|
||||
├── assets/ # meshes, textures, audio, …
|
||||
└── scripts/ # game scripts
|
||||
```
|
||||
|
||||
The project file records the project name, the engine version it was saved with,
|
||||
the enabled [modules](modules.md), and per-project settings.
|
||||
|
||||
## Create, open, save
|
||||
|
||||
```rust
|
||||
use oxide_engine::project::Project;
|
||||
|
||||
// Scaffold a new project (creates the folders + project file).
|
||||
let mut project = Project::create("/path/to/my-game", "My Game")?;
|
||||
|
||||
project.enable_module("render");
|
||||
project.save()?;
|
||||
|
||||
// Reopen later — by directory or by the project file path.
|
||||
let project = Project::open("/path/to/my-game")?;
|
||||
assert_eq!(project.name(), "My Game");
|
||||
assert!(project.is_module_enabled("render"));
|
||||
# Ok::<(), oxide_engine::project::ProjectError>(())
|
||||
```
|
||||
|
||||
Path helpers (`scenes_dir()`, `assets_dir()`, `scripts_dir()`,
|
||||
`project_file_path()`) resolve locations against the root. `create` refuses to
|
||||
overwrite an existing project; `open` reports `NotFound` when there is no project
|
||||
file.
|
||||
|
||||
## Settings storage
|
||||
|
||||
Per-project settings are stored as **opaque per-section RON blobs** keyed by
|
||||
section name, which keeps the project format independent of any particular
|
||||
settings schema:
|
||||
|
||||
```rust
|
||||
# use oxide_engine::project::Project;
|
||||
# let mut project = Project::create(std::env::temp_dir().join("oxide_doc_proj"), "x").unwrap();
|
||||
project.set_settings_section("editor", "(theme:\"dark\")");
|
||||
assert_eq!(project.settings_section("editor"), Some("(theme:\"dark\")"));
|
||||
```
|
||||
|
||||
The typed settings framework serializes its sections to and from these strings,
|
||||
so a section round-trips through the project file without this module knowing the
|
||||
section's shape.
|
||||
|
||||
## Recent projects
|
||||
|
||||
`RecentProjects` is a small most-recently-used list, persisted globally as an
|
||||
editor preference (not inside any project). It de-duplicates and caps:
|
||||
|
||||
```rust
|
||||
use oxide_engine::project::RecentProjects;
|
||||
|
||||
let mut recent = RecentProjects::new(10);
|
||||
recent.record("/path/to/my-game");
|
||||
// recent.save("~/.config/oxide/recent.ron")?; / RecentProjects::load(...)
|
||||
assert_eq!(recent.entries().len(), 1);
|
||||
```
|
||||
|
||||
## Who consumes this
|
||||
|
||||
| Consumer | Stage | Use |
|
||||
|----------|-------|-----|
|
||||
| Editor | 6 | New/Open/Save Project UI, recent list, Project panel/asset browser |
|
||||
| File watcher | 6 | watches `scenes/`, `assets/`, `scripts/` for live reload |
|
||||
| Settings framework | 6 | persists per-project sections into the project file |
|
||||
| Exported runtime / packer | 16 | reads the layout + enabled modules to bundle the game |
|
||||
|
||||
[`Project`]: ../engine/src/project.rs
|
||||
[`RecentProjects`]: ../engine/src/project.rs
|
||||
Reference in New Issue
Block a user