Skip to main content

editor/
editor.rs

1//! A playground for the editor in the inspector.
2//!
3//!   `cargo run --example editor`
4//!
5//! Crabs walk around and bounce off the edges (in a sim system, so pausing
6//! stops them). Press ` (backquote, left of 1) to open the inspector, then
7//! Pause: now you're editing.
8//!
9//! - Click a crab to select it, drag to move it; right-drag pans, wheel zooms.
10//! - Delete, Ctrl/Cmd+D duplicate, Ctrl/Cmd+Z undo.
11//! - Edit → Prefab: the `crab` button, then click in the world to place one.
12//! - Play runs the crabs; Stop puts them back where they were at Play.
13//! - Edit → Scene → Save writes `assets/levels/level.json`; the next start
14//!   loads it instead of the default crabs.
15
16use ponko::*;
17use serde::{Deserialize, Serialize};
18
19/// Walks in a straight line, turning around at the window's edges.
20#[derive(Serialize, Deserialize, Clone, Copy)]
21#[serde(default)]
22struct Walker {
23    /// Pixels per second.
24    speed: f32,
25    /// Direction, in radians.
26    heading: f32,
27}
28
29impl Default for Walker {
30    fn default() -> Self {
31        Self {
32            speed: 60.0,
33            heading: 0.0,
34        }
35    }
36}
37
38const LEVEL: &str = "levels/level.json";
39
40fn walk(ctx: &mut Ctx) {
41    let dt = ctx.dt();
42    let bounds = ctx.window_size();
43    ctx.world.query::<(&mut Transform2D, &mut Walker)>().for_each(|(t, w)| {
44        let mut v = Vec2::from_angle(w.heading) * w.speed;
45        t.position += v * dt;
46        if !(0.0..=bounds.x).contains(&t.position.x) {
47            v.x = -v.x;
48        }
49        if !(0.0..=bounds.y).contains(&t.position.y) {
50            v.y = -v.y;
51        }
52        t.position = t.position.clamp(Vec2::ZERO, bounds);
53        w.heading = v.to_angle();
54    });
55}
56
57fn main() {
58    Game::new("Crabby Engine: editor", 1280, 720)
59        .inspector(true)
60        .sim_system(walk)
61        .run(|ctx| {
62            ctx.clear(Color::hex(0x24323F));
63            ctx.world.reflect::<Walker>();
64            if ctx.load_scene(LEVEL).is_ok() {
65                println!("loaded assets/{LEVEL}");
66                return;
67            }
68            let crab = ctx.load_texture("crab.png");
69            let mut rng = Rng::new(7);
70            for _ in 0..12 {
71                let at = vec2(rng.range(100.0, 1180.0), rng.range(100.0, 620.0));
72                let walker = Walker {
73                    speed: rng.range(30.0, 90.0),
74                    heading: rng.range(0.0, std::f32::consts::TAU),
75                };
76                ctx.world.spawn((Transform2D::at(at), Sprite::new(crab), walker));
77            }
78        });
79}