spine_sys/
animation.rs

1#![allow(clippy::needless_pass_by_value)]
2
3use crate::{
4    ffi,
5    skeleton::{Skeleton, SkeletonData},
6    SpineMutPtr,
7};
8use std::{
9    ffi::{CStr, CString},
10    marker::PhantomData,
11};
12
13pub struct TrackIndex(i32);
14impl TrackIndex {
15    pub fn zero() -> Self {
16        Self(0)
17    }
18}
19impl Default for TrackIndex {
20    fn default() -> Self {
21        Self::zero()
22    }
23}
24
25pub struct Animation<'a> {
26    pub(crate) inner: *mut ffi::spAnimation,
27    pub(crate) _lifetime: PhantomData<&'a ()>,
28}
29impl<'a> Animation<'a> {
30    pub fn name(&self) -> &str {
31        unsafe { CStr::from_ptr(self.inner.as_ref().unwrap().name) }
32            .to_str()
33            .unwrap()
34    }
35
36    pub fn duration(&self) -> f32 {
37        unsafe { self.inner.as_ref().unwrap().duration }
38    }
39    //    pub fn apply(&self, skeleton: &mut Skeleton, last_time: f32, time: f32, loop_: i32) {}
40}
41
42pub struct AnimationState {
43    pub(crate) inner: SpineMutPtr<ffi::spAnimationState>,
44    pub(crate) parent: SpineMutPtr<ffi::spAnimationStateData>,
45}
46impl AnimationState {
47    pub fn new(data: &AnimationStateData) -> Self {
48        Self {
49            inner: SpineMutPtr::new(
50                unsafe { ffi::spAnimationState_create(data.inner.as_mut_ptr()) },
51                Some(ffi::spAnimationState_dispose),
52            ),
53            parent: data.inner.clone(),
54        }
55    }
56
57    pub fn update(&mut self, delta: f32) {
58        unsafe {
59            ffi::spAnimationState_update(self.inner.as_mut_ptr(), delta);
60        }
61    }
62
63    pub fn clear_track(&self, track: TrackIndex) {
64        unsafe {
65            ffi::spAnimationState_clearTrack(self.inner.as_mut_ptr(), track.0);
66        }
67    }
68
69    pub fn clear(&self) {
70        unsafe {
71            ffi::spAnimationState_clearTracks(self.inner.as_mut_ptr());
72        }
73    }
74
75    pub fn set(&mut self, animation: &Animation, track_index: TrackIndex, do_loop: bool) {
76        unsafe {
77            let _track_entry = ffi::spAnimationState_setAnimation(
78                self.inner.as_mut_ptr(),
79                track_index.0,
80                animation.inner,
81                do_loop as std::os::raw::c_int,
82            );
83        }
84    }
85
86    pub fn set_by_name(&mut self, animation_name: &str, track_index: TrackIndex, do_loop: bool) {
87        let name = CString::new(animation_name).unwrap();
88        unsafe {
89            let track_entry = ffi::spAnimationState_setAnimationByName(
90                self.inner.as_mut_ptr(),
91                track_index.0,
92                name.as_ptr(),
93                do_loop as std::os::raw::c_int,
94            );
95            if track_entry.is_null() {
96                panic!("Failed to set animation?");
97            }
98        }
99    }
100
101    pub fn apply(&self, skeleton: &mut Skeleton) -> bool {
102        unsafe {
103            ffi::spAnimationState_apply(self.inner.as_mut_ptr(), skeleton.inner.as_mut_ptr()) != 0
104        }
105    }
106}
107
108pub struct AnimationStateData {
109    pub(crate) inner: SpineMutPtr<ffi::spAnimationStateData>,
110    pub(crate) parent: SpineMutPtr<ffi::spSkeletonData>,
111}
112impl AnimationStateData {
113    pub fn new(data: &SkeletonData) -> Self {
114        Self {
115            inner: SpineMutPtr::new(
116                unsafe { ffi::spAnimationStateData_create(data.inner.as_mut_ptr()) },
117                Some(ffi::spAnimationStateData_dispose),
118            ),
119            parent: data.inner.clone(),
120        }
121    }
122
123    fn get_mix(&mut self, from: &Animation, to: &Animation) -> f32 {
124        unsafe { ffi::spAnimationStateData_getMix(self.inner.as_mut_ptr(), from.inner, to.inner) }
125    }
126
127    fn set_mix(&mut self, from: &Animation, to: &Animation, mix: f32) {
128        unsafe {
129            ffi::spAnimationStateData_setMix(self.inner.as_mut_ptr(), from.inner, to.inner, mix)
130        }
131    }
132
133    fn set_mix_by_name(&mut self, from: &str, to: &str, mix: f32) {
134        let from = CString::new(from).unwrap();
135        let to = CString::new(to).unwrap();
136
137        unsafe {
138            ffi::spAnimationStateData_setMixByName(
139                self.inner.as_mut_ptr(),
140                from.as_ptr(),
141                to.as_ptr(),
142                mix,
143            )
144        }
145    }
146}