dora_ssr/dora/
model.rs

1/* Copyright (c) 2016-2025 Li Jin <dragon-fly@qq.com>
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
8
9extern "C" {
10	fn model_type() -> i32;
11	fn model_get_duration(slf: i64) -> f32;
12	fn model_set_reversed(slf: i64, val: i32);
13	fn model_is_reversed(slf: i64) -> i32;
14	fn model_is_playing(slf: i64) -> i32;
15	fn model_is_paused(slf: i64) -> i32;
16	fn model_has_animation(slf: i64, name: i64) -> i32;
17	fn model_pause(slf: i64);
18	fn model_resume(slf: i64);
19	fn model_resume_animation(slf: i64, name: i64, looping: i32);
20	fn model_reset(slf: i64);
21	fn model_update_to(slf: i64, elapsed: f32, reversed: i32);
22	fn model_get_node_by_name(slf: i64, name: i64) -> i64;
23	fn model_each_node(slf: i64, func0: i32, stack0: i64) -> i32;
24	fn model_new(filename: i64) -> i64;
25	fn model_dummy() -> i64;
26	fn model_get_clip_file(filename: i64) -> i64;
27	fn model_get_looks(filename: i64) -> i64;
28	fn model_get_animations(filename: i64) -> i64;
29}
30use crate::dora::IObject;
31use crate::dora::IPlayable;
32impl IPlayable for Model { }
33use crate::dora::INode;
34impl INode for Model { }
35/// Another implementation of the 'Playable' animation interface.
36pub struct Model { raw: i64 }
37crate::dora_object!(Model);
38impl Model {
39	pub(crate) fn type_info() -> (i32, fn(i64) -> Option<Box<dyn IObject>>) {
40		(unsafe { model_type() }, |raw: i64| -> Option<Box<dyn IObject>> {
41			match raw {
42				0 => None,
43				_ => Some(Box::new(Model { raw: raw }))
44			}
45		})
46	}
47	/// Gets the duration of the current animation.
48	pub fn get_duration(&self) -> f32 {
49		return unsafe { model_get_duration(self.raw()) };
50	}
51	/// Sets whether the animation model will be played in reverse.
52	pub fn set_reversed(&mut self, val: bool) {
53		unsafe { model_set_reversed(self.raw(), if val { 1 } else { 0 }) };
54	}
55	/// Gets whether the animation model will be played in reverse.
56	pub fn is_reversed(&self) -> bool {
57		return unsafe { model_is_reversed(self.raw()) != 0 };
58	}
59	/// Gets whether the animation model is currently playing.
60	pub fn is_playing(&self) -> bool {
61		return unsafe { model_is_playing(self.raw()) != 0 };
62	}
63	/// Gets whether the animation model is currently paused.
64	pub fn is_paused(&self) -> bool {
65		return unsafe { model_is_paused(self.raw()) != 0 };
66	}
67	/// Checks if an animation exists in the model.
68	///
69	/// # Arguments
70	///
71	/// * `name` - The name of the animation to check.
72	///
73	/// # Returns
74	///
75	/// * `bool` - Whether the animation exists in the model or not.
76	pub fn has_animation(&mut self, name: &str) -> bool {
77		unsafe { return model_has_animation(self.raw(), crate::dora::from_string(name)) != 0; }
78	}
79	/// Pauses the currently playing animation.
80	pub fn pause(&mut self) {
81		unsafe { model_pause(self.raw()); }
82	}
83	/// Resumes the currently paused animation,
84	pub fn resume(&mut self) {
85		unsafe { model_resume(self.raw()); }
86	}
87	/// Resumes the currently paused animation, or plays a new animation if specified.
88	///
89	/// # Arguments
90	///
91	/// * `name` - The name of the animation to play.
92	/// * `loop` - Whether to loop the animation or not.
93	pub fn resume_animation(&mut self, name: &str, looping: bool) {
94		unsafe { model_resume_animation(self.raw(), crate::dora::from_string(name), if looping { 1 } else { 0 }); }
95	}
96	/// Resets the current animation to its initial state.
97	pub fn reset(&mut self) {
98		unsafe { model_reset(self.raw()); }
99	}
100	/// Updates the animation to the specified time, and optionally in reverse.
101	///
102	/// # Arguments
103	///
104	/// * `elapsed` - The time to update to.
105	/// * `reversed` - Whether to play the animation in reverse.
106	pub fn update_to(&mut self, elapsed: f32, reversed: bool) {
107		unsafe { model_update_to(self.raw(), elapsed, if reversed { 1 } else { 0 }); }
108	}
109	/// Gets the node with the specified name.
110	///
111	/// # Arguments
112	///
113	/// * `name` - The name of the node to get.
114	///
115	/// # Returns
116	///
117	/// * The node with the specified name.
118	pub fn get_node_by_name(&mut self, name: &str) -> crate::dora::Node {
119		unsafe { return crate::dora::Node::from(model_get_node_by_name(self.raw(), crate::dora::from_string(name))).unwrap(); }
120	}
121	/// Calls the specified function for each node in the model, and stops if the function returns `false`.
122	///
123	/// # Arguments
124	///
125	/// * `visitorFunc` - The function to call for each node.
126	///
127	/// # Returns
128	///
129	/// * `bool` - Whether the function was called for all nodes or not.
130	pub fn each_node(&mut self, mut visitor_func: Box<dyn FnMut(&dyn crate::dora::INode) -> bool>) -> bool {
131		let mut stack0 = crate::dora::CallStack::new();
132		let stack_raw0 = stack0.raw();
133		let func_id0 = crate::dora::push_function(Box::new(move || {
134			let result = visitor_func(&stack0.pop_cast::<crate::dora::Node>().unwrap());
135			stack0.push_bool(result);
136		}));
137		unsafe { return model_each_node(self.raw(), func_id0, stack_raw0) != 0; }
138	}
139	/// Creates a new instance of 'Model' from the specified model file.
140	///
141	/// # Arguments
142	///
143	/// * `filename` - The filename of the model file to load. Can be filename with or without extension like: "Model/item" or "Model/item.model".
144	///
145	/// # Returns
146	///
147	/// * A new instance of 'Model'.
148	pub fn new(filename: &str) -> Option<Model> {
149		unsafe { return Model::from(model_new(crate::dora::from_string(filename))); }
150	}
151	/// Returns a new dummy instance of 'Model' that can do nothing.
152	///
153	/// # Returns
154	///
155	/// * A new dummy instance of 'Model'.
156	pub fn dummy() -> crate::dora::Model {
157		unsafe { return crate::dora::Model::from(model_dummy()).unwrap(); }
158	}
159	/// Gets the clip file from the specified model file.
160	///
161	/// # Arguments
162	///
163	/// * `filename` - The filename of the model file to search.
164	///
165	/// # Returns
166	///
167	/// * A `String` representing the name of the clip file.
168	pub fn get_clip_file(filename: &str) -> String {
169		unsafe { return crate::dora::to_string(model_get_clip_file(crate::dora::from_string(filename))); }
170	}
171	/// Gets an array of look names from the specified model file.
172	///
173	/// # Arguments
174	///
175	/// * `filename` - The filename of the model file to search.
176	///
177	/// # Returns
178	///
179	/// * A `Vec<String>` representing an array of look names found in the model file.
180	pub fn get_looks(filename: &str) -> Vec<String> {
181		unsafe { return crate::dora::Vector::to_str(model_get_looks(crate::dora::from_string(filename))); }
182	}
183	/// Gets an array of animation names from the specified model file.
184	///
185	/// # Arguments
186	///
187	/// * `filename` - The filename of the model file to search.
188	///
189	/// # Returns
190	///
191	/// * A `Vec<String>` representing an array of animation names found in the model file.
192	pub fn get_animations(filename: &str) -> Vec<String> {
193		unsafe { return crate::dora::Vector::to_str(model_get_animations(crate::dora::from_string(filename))); }
194	}
195}