mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-05 14:54:53 +08:00
185 lines
6.7 KiB
Rust
185 lines
6.7 KiB
Rust
use std::ffi::{CStr, CString};
|
|
use std::os::raw::{c_char, c_float, c_int, c_void};
|
|
|
|
// Include the generated bindings
|
|
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
|
|
|
// Headless texture loader functions with debug prints
|
|
extern "C" fn headless_texture_loader(path: *const c_char) -> *mut c_void {
|
|
unsafe {
|
|
let path_str = if !path.is_null() {
|
|
CStr::from_ptr(path).to_string_lossy()
|
|
} else {
|
|
"NULL".into()
|
|
};
|
|
println!("DEBUG: texture_loader called with path: {}", path_str);
|
|
|
|
let ptr = std::alloc::alloc(std::alloc::Layout::from_size_align(8, 8).unwrap());
|
|
println!("DEBUG: texture_loader returning: {:?}", ptr);
|
|
ptr as *mut c_void
|
|
}
|
|
}
|
|
|
|
extern "C" fn headless_texture_unloader(texture: *mut c_void) -> () {
|
|
println!("DEBUG: texture_unloader called with texture: {:?}", texture);
|
|
|
|
if !texture.is_null() && texture as usize > 1 {
|
|
unsafe {
|
|
println!("DEBUG: deallocating texture: {:?}", texture);
|
|
std::alloc::dealloc(texture as *mut u8, std::alloc::Layout::from_size_align(8, 8).unwrap());
|
|
println!("DEBUG: texture deallocation completed");
|
|
}
|
|
} else {
|
|
println!("DEBUG: skipping deallocation (null or invalid pointer)");
|
|
}
|
|
println!("DEBUG: texture_unloader returning");
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn test_spine_basic() -> c_int {
|
|
unsafe {
|
|
println!("Starting spine test...");
|
|
spine_bone_set_y_down(false);
|
|
println!("Set y_down...");
|
|
|
|
// Load real spineboy atlas data
|
|
let atlas_file = std::fs::read_to_string("../../../examples/spineboy/export/spineboy-pma.atlas")
|
|
.expect("Failed to read atlas file");
|
|
let atlas_data = CString::new(atlas_file).unwrap();
|
|
let atlas_dir = CString::new("../../../examples/spineboy/export/").unwrap();
|
|
|
|
println!("About to load atlas...");
|
|
let atlas = spine_atlas_load_callback(
|
|
atlas_data.as_ptr(),
|
|
atlas_dir.as_ptr(),
|
|
Some(headless_texture_loader),
|
|
Some(headless_texture_unloader),
|
|
);
|
|
println!("Atlas loaded: {:?}", atlas);
|
|
|
|
if atlas.is_null() {
|
|
println!("Atlas is null!");
|
|
return 1; // Failed to load atlas
|
|
}
|
|
|
|
// Load real spineboy skeleton data (binary format like the C test)
|
|
println!("Reading skeleton file...");
|
|
let skeleton_file = std::fs::read("../../../examples/spineboy/export/spineboy-pro.skel")
|
|
.expect("Failed to read skeleton file");
|
|
println!("Skeleton file size: {} bytes", skeleton_file.len());
|
|
let skeleton_path = CString::new("../../../examples/spineboy/export/spineboy-pro.skel").unwrap();
|
|
|
|
println!("About to call spine_skeleton_data_load_binary...");
|
|
let result = spine_skeleton_data_load_binary(atlas, skeleton_file.as_ptr(), skeleton_file.len() as i32, skeleton_path.as_ptr());
|
|
println!("spine_skeleton_data_load_binary returned: {:?}", result);
|
|
|
|
if result.is_null() {
|
|
println!("Result is null!");
|
|
return 2;
|
|
}
|
|
|
|
println!("About to call spine_skeleton_data_result_get_data...");
|
|
println!("Result pointer: {:?}", result);
|
|
println!("Result is null: {}", result.is_null());
|
|
|
|
// Try to read the error first to see if result is valid
|
|
println!("Checking if result has error...");
|
|
let error_ptr = spine_skeleton_data_result_get_error(result);
|
|
println!("Error check completed. Error ptr: {:?}", error_ptr);
|
|
|
|
if !error_ptr.is_null() {
|
|
let error_str = CStr::from_ptr(error_ptr);
|
|
println!("Found error: {:?}", error_str);
|
|
spine_skeleton_data_result_dispose(result);
|
|
spine_atlas_dispose(atlas);
|
|
return 2;
|
|
}
|
|
|
|
println!("No error found, getting skeleton data...");
|
|
let skeleton_data = spine_skeleton_data_result_get_data(result);
|
|
|
|
if skeleton_data.is_null() {
|
|
let error = spine_skeleton_data_result_get_error(result);
|
|
if !error.is_null() {
|
|
let error_str = CStr::from_ptr(error);
|
|
eprintln!("Skeleton data error: {:?}", error_str);
|
|
}
|
|
spine_skeleton_data_result_dispose(result);
|
|
spine_atlas_dispose(atlas);
|
|
return 2; // Failed to load skeleton data
|
|
}
|
|
|
|
println!("Skeleton data is valid: {:?}", skeleton_data);
|
|
// Test skeleton creation immediately
|
|
println!("Creating skeleton...");
|
|
let skeleton = spine_skeleton_create(skeleton_data);
|
|
println!("Skeleton create returned: {:?}", skeleton);
|
|
if skeleton.is_null() {
|
|
spine_skeleton_data_result_dispose(result);
|
|
spine_atlas_dispose(atlas);
|
|
return 3; // Failed to create skeleton
|
|
}
|
|
|
|
// Test basic operations
|
|
println!("Calling spine_skeleton_setup_pose...");
|
|
spine_skeleton_setup_pose(skeleton);
|
|
println!("Setup pose completed");
|
|
|
|
println!("Calling spine_skeleton_update_world_transform_1...");
|
|
spine_skeleton_update_world_transform_1(skeleton, 1); // SPINE_PHYSICS_UPDATE = 1
|
|
println!("Update world transform completed");
|
|
|
|
println!("Getting skeleton position...");
|
|
let x = spine_skeleton_get_x(skeleton);
|
|
println!("Got x: {}", x);
|
|
let y = spine_skeleton_get_y(skeleton);
|
|
println!("Got y: {}", y);
|
|
|
|
// Cleanup
|
|
println!("Disposing skeleton...");
|
|
spine_skeleton_dispose(skeleton);
|
|
println!("Skeleton disposed");
|
|
|
|
println!("Disposing skeleton data result...");
|
|
spine_skeleton_data_result_dispose(result);
|
|
println!("Skeleton data result disposed");
|
|
|
|
// Test atlas disposal to get proper crash backtrace
|
|
println!("About to call spine_atlas_dispose - crash expected...");
|
|
spine_atlas_dispose(atlas);
|
|
println!("Atlas disposal completed successfully");
|
|
|
|
// Verify we got reasonable values
|
|
println!("Verifying values...");
|
|
if x.is_finite() && y.is_finite() {
|
|
println!("SUCCESS! Test completed successfully");
|
|
0 // Success
|
|
} else {
|
|
println!("FAILED! Invalid values");
|
|
4 // Invalid values
|
|
}
|
|
}
|
|
}
|
|
|
|
// WASM export for web testing
|
|
#[cfg(target_arch = "wasm32")]
|
|
mod wasm {
|
|
use super::*;
|
|
use std::os::raw::c_int;
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn run_spine_test() -> c_int {
|
|
test_spine_basic()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_spine_basic_works() {
|
|
let result = test_spine_basic();
|
|
assert_eq!(result, 0, "Spine basic test should succeed");
|
|
}
|
|
} |