Skip to main content

concinnity_core/components/
scene.rs

1// Scene marker schema.
2
3use crate::ecs::asset_id::AssetId;
4use crate::ecs::asset_id::de_opt_asset_ref;
5
6/// A named group of world content.
7///
8/// [Prop](#prop)s belong to a Scene by naming convention: props whose `name`
9/// begins with `<scene_name>_` are associated with that Scene. Props not
10/// prefixed by any scene name are visible in every scene.
11///
12/// The first declared Scene is active at world start. Scene changes are driven
13/// by actions: a UI `scene:<name>` action ([HitRegion](#hitregion) /
14/// [KeyBinding](#keybinding)) or a [Behavior](#behavior) scene node jumps to
15/// the named scene, with the transition ("Cut" or "FadeBlack") declared on the
16/// jump.
17#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
18#[serde(default)]
19pub struct Scene {
20    /// Asset identity; injected via `inject_name`. Not part of `args`.
21    #[serde(skip)]
22    pub asset_id: AssetId,
23    /// A [CameraShot](#camerashot) or [Camera3D](#camera3d) to activate when
24    /// this scene becomes active. `None` keeps the current camera unchanged.
25    #[serde(deserialize_with = "de_opt_asset_ref")]
26    pub camera_shot: Option<AssetId>,
27}
28
29#[cfg(test)]
30mod tests {
31    use super::*;
32
33    #[test]
34    fn a_scene_with_no_shot_leaves_the_camera_where_it_is() {
35        let s = Scene::default();
36        assert!(s.camera_shot.is_none());
37        assert_eq!(s.asset_id, AssetId::default());
38        assert!(
39            serde_json::from_str::<Scene>("{}")
40                .unwrap()
41                .camera_shot
42                .is_none()
43        );
44    }
45
46    #[test]
47    fn a_named_shot_parses_and_round_trips_through_postcard() {
48        crate::test_support::install_resolvers();
49        let s: Scene = serde_json::from_str(r#"{"camera_shot":"establishing"}"#).unwrap();
50        assert_eq!(s.camera_shot, Some(AssetId(12)));
51
52        let bytes = postcard::to_allocvec(&s).unwrap();
53        let back: Scene = postcard::from_bytes(&bytes).unwrap();
54        assert_eq!(back.camera_shot, Some(AssetId(12)));
55        assert_eq!(back.asset_id, AssetId::default());
56    }
57}