1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#![deny(clippy::all, clippy::pedantic)]
#![allow(dead_code, clippy::module_name_repetitions, clippy::must_use_candidate)]
use atlas::AtlasPage;
use std::ffi::CStr;
use std::{os::raw::c_char, path::Path};
use thiserror::Error;
pub mod ffi;
pub mod animation;
pub mod atlas;
pub mod enums;
pub mod skeleton;
mod spine_ptr;
use spine_ptr::*;
#[derive(Debug, Error)]
pub enum SpineError {
#[error("LOL")]
FailLoadAtlas(String),
#[error("{}", 0)]
FailLoadSkeleton(String),
}
#[allow(clippy::mut_mut)]
#[no_mangle]
extern "C" fn _spAtlasPage_createTexture(
atlas_page_ptr: *mut ffi::spAtlasPage,
path: *const std::os::raw::c_char,
) {
std::panic::catch_unwind(|| {
let path = unsafe { CStr::from_ptr(path).to_str().unwrap().to_owned() };
let mut atlas_page = AtlasPage {
inner: SpineMutPtr::new(atlas_page_ptr, None),
};
let atlas_object_ptr = unsafe { (*atlas_page.inner.as_mut().atlas).rendererObject };
if !atlas_object_ptr.is_null() {
let closure: &mut &mut dyn FnMut(&AtlasPage, &Path) -> u32 =
unsafe { &mut *(atlas_object_ptr as *mut _) };
atlas_page.set_texture_id(closure(&atlas_page, Path::new(&path)));
}
})
.unwrap_or_else(|e| println!("ERROR: {:?}", e));
}
#[no_mangle]
extern "C" fn _spAtlasPage_disposeTexture(atlas: *mut ffi::spAtlasPage) {
std::panic::catch_unwind(|| {
let _atlas_page = AtlasPage {
inner: SpineMutPtr::new(atlas, None),
};
})
.unwrap_or_else(|e| println!("ERROR: {:?}", e));
}
#[no_mangle]
unsafe extern "C" fn _spUtil_readFile(path: *const c_char, length: *mut i32) -> *mut c_char {
std::panic::catch_unwind(|| ffi::_spReadFile(path, length)).unwrap_or_else(|e| {
println!("ERROR: {:?}", e);
std::ptr::null_mut()
})
}
#[cfg(test)]
pub(crate) mod tests {
use std::path::PathBuf;
pub struct TestCase {
name: &'static str,
atlas: &'static str,
binary: &'static str,
json: &'static str,
path: &'static str,
}
impl TestCase {
pub fn name(&self) -> &str {
self.name
}
pub fn atlas(&self) -> PathBuf {
PathBuf::from(self.path).join(self.atlas)
}
pub fn binary(&self) -> PathBuf {
PathBuf::from(self.path).join(self.binary)
}
pub fn json(&self) -> PathBuf {
PathBuf::from(self.path).join(self.json)
}
}
pub const TEST_CASES: &[TestCase] = &[TestCase {
name: "dragon",
atlas: "dragon.atlas",
binary: "dragon-ess.skel",
json: "dragon-ess.json",
path: "../spine-example/examples/dragon/export",
}];
}