solar_system/solar_system.rs
1//! # Solar System
2//!
3//! A three-level parent-child hierarchy: **Sun → Planet → Moon**.
4//! The Sun drives the entire system — rotating the Sun automatically
5//! carries the Planet (and Moon) around it, demonstrating how Vertra
6//! propagates world transforms down the object tree.
7//!
8//! Editor mode is enabled on startup so you can inspect and manipulate
9//! any object with the gizmo. The `on_editor_event` callback logs every
10//! gizmo mode change and axis drag to stdout.
11//!
12//! **Run:**
13//! ```sh
14//! cargo run --example solar_system
15//! ```
16//!
17//! **Editor keybinds:**
18//! | Key | Action |
19//! |------------|--------------------------------------|
20//! | `T` | Switch to Translate gizmo |
21//! | `R` | Switch to Rotate gizmo |
22//! | `E` | Switch to Scale gizmo |
23//! | `F` | Frame / focus on selected object |
24//! | `Escape` | Exit editor mode (enter play mode) |
25//! | `RMB drag` | Orbit camera |
26//! | `MMB drag` | Pan camera |
27//! | Scroll | Dolly in / out |
28
29use vertra::camera::Camera;
30use vertra::window::Window;
31use vertra::transform::Transform;
32use vertra::geometry::Geometry;
33use vertra::objects::Object;
34
35struct AppState {
36 sun_id: Option<usize>,
37 earth_id: Option<usize>,
38 moon_id: Option<usize>,
39}
40
41fn main() {
42 let initial_state = AppState {
43 sun_id: None,
44 earth_id: None,
45 moon_id: None,
46 };
47
48 Window::new(initial_state)
49 .with_title("Simple Solar Simulation")
50 .with_camera(
51 Camera::new()
52 .with_position([0.0, 8.0, -12.0])
53 .with_rotation(90.0, -30.0)
54 )
55 .on_startup(|state, scene, _| {
56 // 1. The Sun (Center)
57 let sun = Object {
58 name: "Sun".to_string(),
59 str_id: "sun".to_string (),
60 transform: Transform::from_position(0.0, 0.0, 0.0),
61 geometry: Some(Geometry::Cube { size: 2.0 }),
62 color: [1.0, 0.9, 0.2, 1.0],
63 ..Default::default()
64 };
65 let sun_id = scene.spawn(sun, None);
66
67 // 2. The Planet (Child)
68 let planet = Object {
69 name: "Planet".to_string(),
70 str_id: "earth".to_string(),
71 transform: Transform::from_position(6.0, 0.0, 0.0),
72 geometry: Some(Geometry::Sphere { radius: 0.8, subdivisions: 24 }),
73 color: [0.2, 0.5, 1.0, 1.0],
74 ..Default::default()
75 };
76 let planet_id = scene.spawn(planet, Some(sun_id));
77
78 // 3. The Moon (Grandchild)
79 let moon = Object {
80 name: "Moon".to_string(),
81 str_id: "moon".to_string(),
82 transform: Transform::from_position(1.5, 0.0, 0.0),
83 geometry: Some(Geometry::Sphere { radius: 0.3, subdivisions: 16 }),
84 color: [0.7, 0.7, 0.7, 1.0],
85 ..Default::default()
86 };
87 scene.spawn(moon, Some(planet_id));
88
89 state.sun_id = scene.world.get_id("sun");
90 state.earth_id = scene.world.get_id("earth");
91 state.moon_id = scene.world.get_id("moon");
92 scene.enable_editor_mode();
93 })
94 .on_update(|state, scene, ctx| {
95 // Rotate the Sun (the planet will orbit automatically)
96 if let Some(sun) = state.sun_id.and_then(|id| scene.world.get_mut(id)) {
97 sun.transform.rotation[1] += 30.0 * ctx.dt;
98 }
99
100 // Rotate the Planet (Earth)
101 if let Some(planet) = state.earth_id.and_then(|id| scene.world.get_mut(id)) {
102 planet.transform.rotation[1] += 100.0 * ctx.dt;
103 }
104 })
105 .create();
106}