Skip to main content

gltforge_unity/
unity_game_object.rs

1use crate::{unity_gltf::UnityGltf, write_name};
2use gltforge_unity_core::unity_transform::IDENTITY;
3
4/// Return the total number of GameObjects in the document.
5///
6/// # Safety
7/// `ptr` must be a valid, non-null handle.
8#[unsafe(no_mangle)]
9pub unsafe extern "C" fn gltforge_game_object_count(ptr: *const UnityGltf) -> u32 {
10    unsafe { &*ptr }.game_objects.len() as u32
11}
12
13/// Return the name of GameObject `go_idx` as UTF-8 bytes, or null if absent.
14///
15/// # Safety
16/// `ptr` must be a valid, non-null handle. `out_len` may be null.
17#[unsafe(no_mangle)]
18pub unsafe extern "C" fn gltforge_game_object_name(
19    ptr: *const UnityGltf,
20    go_idx: u32,
21    out_len: *mut u32,
22) -> *const u8 {
23    let gltf = unsafe { &*ptr };
24    let name = gltf.game_objects.get(&go_idx).map(|n| &n.name);
25    unsafe { write_name(name, out_len) }
26}
27
28/// Return the number of children of GameObject `go_idx`.
29///
30/// # Safety
31/// `ptr` must be a valid, non-null handle.
32#[unsafe(no_mangle)]
33pub unsafe extern "C" fn gltforge_game_object_child_count(
34    ptr: *const UnityGltf,
35    go_idx: u32,
36) -> u32 {
37    unsafe { &*ptr }
38        .game_objects
39        .get(&go_idx)
40        .map(|n| n.children.len() as u32)
41        .unwrap_or(0)
42}
43
44/// Return the index of the `slot`-th child of GameObject `go_idx`.
45/// Returns `u32::MAX` if out of range.
46///
47/// # Safety
48/// `ptr` must be a valid, non-null handle.
49#[unsafe(no_mangle)]
50pub unsafe extern "C" fn gltforge_game_object_child(
51    ptr: *const UnityGltf,
52    go_idx: u32,
53    slot: u32,
54) -> u32 {
55    unsafe { &*ptr }
56        .game_objects
57        .get(&go_idx)
58        .and_then(|n| n.children.get(slot as usize))
59        .copied()
60        .unwrap_or(u32::MAX)
61}
62
63/// Return the number of mesh references on GameObject `go_idx`.
64///
65/// # Safety
66/// `ptr` must be a valid, non-null handle.
67#[unsafe(no_mangle)]
68pub unsafe extern "C" fn gltforge_game_object_mesh_count(
69    ptr: *const UnityGltf,
70    go_idx: u32,
71) -> u32 {
72    unsafe { &*ptr }
73        .game_objects
74        .get(&go_idx)
75        .map(|n| n.mesh_indices.len() as u32)
76        .unwrap_or(0)
77}
78
79/// Return the mesh index of the `slot`-th mesh reference on GameObject `go_idx`.
80/// Returns `u32::MAX` if out of range.
81///
82/// # Safety
83/// `ptr` must be a valid, non-null handle.
84#[unsafe(no_mangle)]
85pub unsafe extern "C" fn gltforge_game_object_mesh_index(
86    ptr: *const UnityGltf,
87    go_idx: u32,
88    slot: u32,
89) -> u32 {
90    unsafe { &*ptr }
91        .game_objects
92        .get(&go_idx)
93        .and_then(|n| n.mesh_indices.get(slot as usize))
94        .copied()
95        .unwrap_or(u32::MAX)
96}
97
98/// Write the local transform of GameObject `go_idx` into the caller-supplied 10-element `f32` buffer.
99///
100/// Layout: `[px, py, pz,  rx, ry, rz, rw,  sx, sy, sz]`
101/// — position (Unity left-handed), rotation quaternion (xyzw, Unity left-handed), scale.
102/// Falls back to identity if the index is out of range.
103///
104/// # Safety
105/// `ptr` must be a valid, non-null handle. `out` must point to at least 10 writable `f32` values.
106#[unsafe(no_mangle)]
107pub unsafe extern "C" fn gltforge_game_object_transform(
108    ptr: *const UnityGltf,
109    go_idx: u32,
110    out: *mut f32,
111) {
112    let gltf = unsafe { &*ptr };
113    let t = gltf
114        .game_objects
115        .get(&go_idx)
116        .map(|n| &n.transform)
117        .unwrap_or(&IDENTITY);
118    let out = unsafe { std::slice::from_raw_parts_mut(out, 10) };
119    out[0] = t.position[0];
120    out[1] = t.position[1];
121    out[2] = t.position[2];
122    out[3] = t.rotation[0];
123    out[4] = t.rotation[1];
124    out[5] = t.rotation[2];
125    out[6] = t.rotation[3];
126    out[7] = t.scale[0];
127    out[8] = t.scale[1];
128    out[9] = t.scale[2];
129}