9eead719b0
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>
112 lines
3.6 KiB
Rust
112 lines
3.6 KiB
Rust
//! `scene_basic` — a runnable tour of the Stage 3 scene graph.
|
|
//!
|
|
//! Run with:
|
|
//! ```sh
|
|
//! cargo run -p oxide-examples --bin scene_basic
|
|
//! ```
|
|
//!
|
|
//! This example has no window or GPU dependency. It builds a small entity
|
|
//! hierarchy, prints each node's local and resolved world transform, reparents
|
|
//! a node, and round-trips the whole scene through RON — so the Stage 3 scene
|
|
//! API can be reviewed by eye.
|
|
|
|
use oxide_engine::prelude::*;
|
|
use oxide_engine::scene::DespawnPolicy;
|
|
|
|
fn main() {
|
|
env_logger::init();
|
|
println!("Oxide scene demo — Stage 3 scene graph\n");
|
|
|
|
let mut scene = Scene::new();
|
|
|
|
// A little solar-system-ish hierarchy: sun → planet → moon, plus a probe.
|
|
let sun = scene.spawn("sun", Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)));
|
|
let planet = scene.spawn_child(
|
|
sun,
|
|
"planet",
|
|
Transform::from_trs(
|
|
Vec3::new(10.0, 0.0, 0.0),
|
|
Quat::from_rotation_y(90_f32.to_radians()),
|
|
Vec3::ONE,
|
|
),
|
|
);
|
|
let moon = scene.spawn_child(
|
|
planet,
|
|
"moon",
|
|
Transform::from_translation(Vec3::new(0.0, 0.0, 2.0)),
|
|
);
|
|
let probe = scene.spawn_child(planet, "probe", Transform::from_translation(Vec3::Y));
|
|
|
|
println!("== Hierarchy & world transforms ==");
|
|
print_tree(&scene);
|
|
|
|
// World transforms compose down the chain: the moon inherits the planet's
|
|
// rotation, so its local +Z offset lands along the world axes accordingly.
|
|
let moon_world = scene.world_transform(moon).unwrap();
|
|
println!(
|
|
"\nmoon local pos : {}",
|
|
scene.local_transform(moon).unwrap().translation
|
|
);
|
|
println!("moon world pos : {}", moon_world.translation);
|
|
|
|
// Reparent the probe directly under the sun and observe its world transform
|
|
// change (its local transform is preserved).
|
|
println!("\n== Reparent probe: planet → sun ==");
|
|
scene.set_parent(probe, Some(sun)).unwrap();
|
|
println!(
|
|
"probe world pos: {}",
|
|
scene.world_transform(probe).unwrap().translation
|
|
);
|
|
|
|
// Disable a node (later systems will skip disabled subtrees).
|
|
scene.set_enabled(moon, false);
|
|
println!(
|
|
"\nmoon enabled? : {}",
|
|
scene.is_enabled(moon).unwrap_or(true)
|
|
);
|
|
|
|
// Serialize → deserialize round-trip.
|
|
println!("\n== RON serialization ==");
|
|
let ron = scene.to_ron().expect("serialize");
|
|
println!("{ron}");
|
|
let restored = Scene::from_ron(&ron).expect("deserialize");
|
|
println!(
|
|
"restored {} entities, {} roots",
|
|
restored.len(),
|
|
restored.roots().len()
|
|
);
|
|
|
|
// Despawn the planet, detaching its children up to its parent.
|
|
println!("\n== Despawn planet (detach children) ==");
|
|
scene.despawn(planet, DespawnPolicy::DetachChildren);
|
|
print_tree(&scene);
|
|
}
|
|
|
|
/// Prints the scene as an indented tree with each node's world position.
|
|
fn print_tree(scene: &Scene) {
|
|
let worlds = scene.world_transforms();
|
|
for &root in scene.roots() {
|
|
print_node(scene, root, 0, &worlds);
|
|
}
|
|
}
|
|
|
|
fn print_node(
|
|
scene: &Scene,
|
|
entity: oxide_engine::scene::Entity,
|
|
depth: usize,
|
|
worlds: &std::collections::HashMap<oxide_engine::scene::Entity, Transform>,
|
|
) {
|
|
let indent = " ".repeat(depth);
|
|
let name = scene.name(entity).unwrap_or_default();
|
|
let enabled = scene.is_enabled(entity).unwrap_or(true);
|
|
let world = worlds
|
|
.get(&entity)
|
|
.map(|t| t.translation)
|
|
.unwrap_or(Vec3::ZERO);
|
|
let tag = if enabled { "" } else { " (disabled)" };
|
|
println!("{indent}- {name}{tag} world={world}");
|
|
for &child in scene.children(entity) {
|
|
print_node(scene, child, depth + 1, worlds);
|
|
}
|
|
}
|