ranim/
link_magic.rs

1//! Scene types for dylib / inventory registration and runtime use.
2use crate::{Output, OutputFormat, Scene, SceneConfig};
3use ranim_core::RanimScene;
4
5#[cfg(target_arch = "wasm32")]
6use wasm_bindgen::prelude::*;
7
8/// Static scene type for inventory registration
9#[doc(hidden)]
10pub struct StaticScene {
11    /// Scene name
12    pub name: &'static str,
13    /// Scene constructor
14    pub constructor: fn(&mut RanimScene),
15    /// Scene config
16    pub config: StaticSceneConfig,
17    /// Scene outputs
18    pub outputs: &'static [StaticOutput],
19}
20
21/// Static scene config for inventory registration
22#[doc(hidden)]
23pub struct StaticSceneConfig {
24    /// The clear color
25    pub clear_color: &'static str,
26}
27
28/// Static output for inventory registration
29#[doc(hidden)]
30pub struct StaticOutput {
31    /// The width of the output texture in pixels.
32    pub width: u32,
33    /// The height of the output texture in pixels.
34    pub height: u32,
35    /// The frame rate of the output video.
36    pub fps: u32,
37    /// Whether to save the frames.
38    pub save_frames: bool,
39    /// The name of the video, uses scene's name by default.
40    pub name: Option<&'static str>,
41    /// The directory to save the output
42    pub dir: &'static str,
43    /// The output format
44    pub format: OutputFormat,
45}
46
47impl StaticOutput {
48    /// 1920x1080 60fps save_frames=false dir="./"
49    pub const DEFAULT: Self = Self {
50        width: 1920,
51        height: 1080,
52        fps: 60,
53        save_frames: false,
54        name: None,
55        dir: "./",
56        format: OutputFormat::Mp4,
57    };
58}
59
60// MARK: inventory + FFI
61
62pub use inventory;
63
64inventory::collect!(StaticScene);
65
66#[doc(hidden)]
67#[unsafe(no_mangle)]
68pub extern "C" fn get_scene(idx: usize) -> *const StaticScene {
69    inventory::iter::<StaticScene>()
70        .skip(idx)
71        .take(1)
72        .next()
73        .unwrap()
74}
75
76#[doc(hidden)]
77#[unsafe(no_mangle)]
78pub extern "C" fn scene_cnt() -> usize {
79    inventory::iter::<StaticScene>().count()
80}
81
82/// Return a scene with matched name
83#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
84pub fn find_scene(name: &str) -> Option<Scene> {
85    inventory::iter::<StaticScene>()
86        .find(|s| s.name == name)
87        .map(Scene::from)
88}
89
90// MARK: From impls (Static -> Owned)
91
92impl From<&StaticScene> for Scene {
93    fn from(s: &StaticScene) -> Self {
94        Self {
95            name: s.name.to_string(),
96            constructor: s.constructor,
97            config: SceneConfig::from(&s.config),
98            outputs: s.outputs.iter().map(Output::from).collect(),
99        }
100    }
101}
102
103impl From<&StaticSceneConfig> for SceneConfig {
104    fn from(c: &StaticSceneConfig) -> Self {
105        Self {
106            clear_color: c.clear_color.to_string(),
107        }
108    }
109}
110
111impl From<&StaticOutput> for Output {
112    fn from(o: &StaticOutput) -> Self {
113        Self {
114            width: o.width,
115            height: o.height,
116            fps: o.fps,
117            save_frames: o.save_frames,
118            name: o.name.map(|n| n.to_string()),
119            dir: o.dir.to_string(),
120            format: o.format,
121        }
122    }
123}