dioxus_spline/
runtime.rs

1use core::fmt;
2use std::fmt::Debug;
3
4use crate::speobject::SPEObject;
5use serde::{Deserialize, Serialize};
6use wasm_bindgen::prelude::*;
7use wasm_bindgen::JsValue;
8use web_sys::HtmlCanvasElement;
9
10/// An enum matching @splinetool/runtime `SplineEventName tstype
11#[allow(non_camel_case_types)]
12#[derive(Clone, Copy, Debug)]
13#[wasm_bindgen]
14pub enum SplineEventName {
15    mouseDown,
16    mouseUp,
17    mouseHover,
18    keyDown,
19    keyUp,
20    start,
21    lookAt,
22    follow,
23    scroll,
24    collision,
25    rendered,
26}
27
28impl fmt::Display for SplineEventName {
29    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
30        write!(f, "{:?}", self)
31    }
32}
33
34#[derive(Deserialize, Serialize, Debug)]
35pub struct SplineEvent {
36    pub target: Target,
37}
38
39#[derive(Deserialize, Serialize, Debug)]
40pub struct Target {
41    pub name: String,
42    pub id: String,
43}
44
45impl From<JsValue> for SplineEvent {
46    fn from(value: JsValue) -> Self {
47        serde_wasm_bindgen::from_value(value).unwrap()
48    }
49}
50
51#[wasm_bindgen(module = "/src/runtime.js")]
52extern "C" {
53
54    #[derive(Clone)]
55    #[wasm_bindgen]
56    type Application;
57
58    #[wasm_bindgen(constructor)]
59    fn new_(canvas: &HtmlCanvasElement, render_on_demand: bool) -> Application;
60
61    #[wasm_bindgen(method, js_name = load)]
62    async fn load_(this: &Application, scene: String);
63
64    #[wasm_bindgen(method, js_name = addEventListener)]
65    fn add_event_listener_(
66        this: &Application,
67        event_name: &str,
68        callback: &Closure<dyn FnMut(JsValue)>,
69    );
70
71    #[wasm_bindgen(method, js_name = removeEventListener)]
72    fn remove_event_listener_(this: &Application, event_name: &str);
73
74    #[wasm_bindgen(method, js_name = dispose)]
75    fn dispose_(this: &Application);
76
77    #[wasm_bindgen(method, js_name = findObjectByName)]
78    fn find_object_by_name_(this: &Application, name: String) -> JsValue;
79
80    #[wasm_bindgen(method, js_name = findObjectById)]
81    fn find_object_by_id_(this: &Application, id: String) -> JsValue;
82
83    #[wasm_bindgen(method, js_name = getAllObjects)]
84    fn get_all_objects_(this: &Application) -> Vec<JsValue>;
85
86    #[wasm_bindgen(method, js_name = emitEvent)]
87    fn emit_event_(this: &Application, eventName: SplineEventName, nameOrUuid: String);
88
89    #[wasm_bindgen(method, js_name = emitEventReverse)]
90    fn emit_event_reverse_(this: &Application, eventName: SplineEventName, nameOrUuid: String);
91
92    #[wasm_bindgen(method, js_name = setZoom)]
93    fn set_zoom_(this: &Application, zoomValue: f64);
94
95    #[wasm_bindgen(method, js_name = setBackgroundColor)]
96    fn set_background_color_(this: &Application, color: String);
97
98    /// Experimental
99    #[wasm_bindgen(method, js_name = setGlobalEvents)]
100    fn set_global_events_(this: &Application, global: bool);
101
102    #[wasm_bindgen(method, js_name = setSize)]
103    fn set_size_(this: &Application, width: f64, height: f64);
104
105    /// Experimental
106    #[wasm_bindgen(method, getter, js_name = data)]
107    fn data_(this: &Application) -> JsValue;
108
109    /// Experimental
110    #[wasm_bindgen(method, getter, js_name = eventManager)]
111    fn event_manager_(this: &Application) -> JsValue;
112
113    /// Experimental
114    #[wasm_bindgen(method, getter, js_name = controls)]
115    fn controls_(this: &Application) -> JsValue;
116
117    /// Experimental
118    #[wasm_bindgen(method, getter, js_name = isStopped)]
119    fn is_stopped_(this: &Application) -> bool;
120
121    /// Experimental
122    #[wasm_bindgen(method, js_name = stop)]
123    fn stop_(this: &Application);
124
125    /// Experimental
126    #[wasm_bindgen(method, js_name = play)]
127    fn play_(this: &Application);
128
129    /// Experimental
130    #[wasm_bindgen(method, js_name = requestRender)]
131    fn request_render_(this: &Application);
132
133    /// Experimental
134    #[wasm_bindgen(method, js_name = setVariables)]
135    fn set_variables_(this: &Application, variables: JsValue);
136
137    /// Experimental
138    #[wasm_bindgen(method, js_name = setVariable)]
139    fn set_variable_(this: &Application, name: String, value: JsValue);
140
141    /// Experimental
142    #[wasm_bindgen(method, js_name = getVariables)]
143    fn get_variables_(this: &Application) -> JsValue;
144
145    /// Experimental
146    #[wasm_bindgen(method, js_name = getVariable)]
147    fn get_variable_(this: &Application, name: String) -> JsValue;
148}
149
150#[derive(Clone)]
151pub struct SplineApplication {
152    app: Application,
153}
154
155impl SplineApplication {
156    pub fn new(canvas: &HtmlCanvasElement, render_on_demand: bool) -> Self {
157        let app = Application::new_(canvas, render_on_demand);
158        SplineApplication { app }
159    }
160
161    pub async fn load(&self, scene: String) {
162        self.app.load_(scene).await;
163    }
164
165    pub fn add_event_listener<F>(&self, event_name: &str, callback: F)
166    where
167        F: FnMut(JsValue) + 'static,
168    {
169        let closure = Closure::wrap(Box::new(callback) as Box<dyn FnMut(JsValue)>);
170        self.app.add_event_listener_(event_name, &closure);
171        closure.forget();
172    }
173
174    pub fn remove_event_listener(&self, event_name: &str) {
175        self.app.remove_event_listener_(event_name);
176    }
177
178    pub fn dispose(&self) {
179        self.app.dispose_();
180    }
181
182    pub fn find_object_by_name(&self, name: String) -> SPEObject {
183        let obj = self.app.find_object_by_name_(name);
184        SPEObject::new(obj)
185    }
186
187    pub fn find_object_by_id(&self, id: String) -> SPEObject {
188        let obj = self.app.find_object_by_id_(id);
189        SPEObject::new(obj)
190    }
191
192    pub fn get_all_objects(&self) -> Vec<SPEObject> {
193        let objs = self.app.get_all_objects_();
194        objs.iter().map(|obj| SPEObject::new(obj.clone())).collect()
195    }
196
197    #[deprecated(note = "Experimental")]
198    pub fn emit_event(&self, event_name: SplineEventName, name_or_uuid: String) {
199        self.app.emit_event_(event_name, name_or_uuid);
200    }
201
202    #[deprecated(note = "Experimental")]
203    pub fn emit_event_reverse(&self, event_name: SplineEventName, name_or_uuid: String) {
204        self.app.emit_event_reverse_(event_name, name_or_uuid);
205    }
206
207    #[deprecated(note = "Experimental")]
208    pub fn set_zoom(&self, zoom_value: f64) {
209        self.app.set_zoom_(zoom_value);
210    }
211
212    pub fn set_background_color(&self, color: String) {
213        self.app.set_background_color_(color);
214    }
215
216    #[deprecated(note = "Experimental")]
217    pub fn set_global_events(&self, global: bool) {
218        self.app.set_global_events_(global);
219    }
220
221    pub fn set_size(&self, width: f64, height: f64) {
222        self.app.set_size_(width, height);
223    }
224
225    #[deprecated(note = "Experimental")]
226    pub fn data(&self) -> JsValue {
227        self.app.data_()
228    }
229
230    #[deprecated(note = "Experimental")]
231    pub fn event_manager(&self) -> JsValue {
232        self.app.event_manager_()
233    }
234
235    #[deprecated(note = "Experimental")]
236    pub fn controls(&self) -> JsValue {
237        self.app.controls_()
238    }
239
240    #[deprecated(note = "Experimental")]
241    pub fn is_stopped(&self) -> bool {
242        self.app.is_stopped_()
243    }
244
245    #[deprecated(note = "Experimental")]
246    pub fn stop(&self) {
247        self.app.stop_();
248    }
249
250    #[deprecated(note = "Experimental")]
251    pub fn play(&self) {
252        self.app.play_();
253    }
254
255    #[deprecated(note = "Experimental")]
256    pub fn request_render(&self) {
257        self.app.request_render_();
258    }
259
260    #[deprecated(note = "Experimental")]
261    pub fn set_variables(&self, variables: JsValue) {
262        self.app.set_variables_(variables);
263    }
264
265    #[deprecated(note = "Experimental")]
266    pub fn set_variable(&self, name: String, value: JsValue) {
267        self.app.set_variable_(name, value);
268    }
269
270    #[deprecated(note = "Experimental")]
271    pub fn get_variables(&self) -> JsValue {
272        self.app.get_variables_()
273    }
274
275    #[deprecated(note = "Experimental")]
276    pub fn get_variable(&self, name: String) -> JsValue {
277        self.app.get_variable_(name)
278    }
279}