turing_api/
lib.rs

1use std::ffi::{c_char, CString};
2use paste::paste;
3
4macro_rules! typed_ptr {
5    ( $name:ident ) => {
6        #[repr(C)]
7        #[derive(Copy, Clone)]
8        pub struct $name {
9            ptr: *mut c_char
10        }
11    };
12}
13
14typed_ptr!(_Color);
15typed_ptr!(_ColorNote);
16typed_ptr!(_BombNote);
17typed_ptr!(_ChainHeadNote);
18typed_ptr!(_ChainLinkNote);
19typed_ptr!(_ChainNote);
20typed_ptr!(_Arc);
21typed_ptr!(_Wall);
22typed_ptr!(_Saber);
23// typed_ptr!(_Player);
24typed_ptr!(_Vec2);
25typed_ptr!(_Vec3);
26typed_ptr!(_Vec4);
27typed_ptr!(_Quat);
28
29macro_rules! color_methods {
30    ( $tp:ty, $name:tt ) => {
31        paste! {
32            extern "C" {
33                fn [<_ $name _set_color>]($name: $tp, color: _Color);
34                fn [<_ $name _get_color>]($name: $tp) -> _Color;
35            }
36        }
37    }
38}
39
40macro_rules! position_methods {
41    ( $tp:ty, $name:tt ) => {
42        paste! {
43            extern "C" {
44                fn [<_ $name _set_position>]($name: $tp, pos: _Vec3);
45                fn [<_ $name _get_position>]($name: $tp) -> _Vec3;
46                fn [<_ $name _set_orientation>]($name: $tp, orientation: _Quat);
47                fn [<_ $name _get_orientation>]($name: $tp) -> _Quat;
48            }
49        }
50    }
51}
52
53macro_rules! gameplay_object_methods {
54    ( $tp:ty, $name:tt ) => {
55        paste! {
56            extern "C" {
57                fn [<_create_ $name>](beat: f32) -> $tp;
58                fn [<_beatmap_add_ $name>]($name: $tp);
59                fn [<_beatmap_remove_ $name>]($name: $tp);
60            }
61        }
62        position_methods! { $tp, $name }
63        color_methods! { $tp, $name }
64    };
65}
66
67macro_rules! attrs {
68    ( $tp:ty, $name:tt, $( $attr:ident: $attr_tp:ty ),* $(,)? ) => {
69        extern "C" {
70            paste! {
71                $(
72                fn [<_ $name _get_attr_ $attr>]($name: [<_ $tp>]) -> $attr_tp;
73                fn [<_ $name _set_attr_ $attr>]($name: [<_ $tp>], $attr: $attr_tp);
74                )*
75            }
76        }
77
78        impl $tp {
79            $(
80
81            paste! {
82                pub fn [<get_ $attr>](&self) -> $attr_tp {
83                    unsafe { [<_ $name _get_attr_ $attr>](self._inner) }
84                }
85                pub fn [<set_ $attr>](&self, $attr: $attr_tp) {
86                    unsafe { [<_ $name _set_attr_ $attr>](self._inner, $attr) }
87                }
88            }
89
90            )*
91        }
92    };
93}
94
95gameplay_object_methods! { _ColorNote, color_note }
96gameplay_object_methods! { _BombNote, bomb_note }
97gameplay_object_methods! { _Arc, arc }
98gameplay_object_methods! { _Wall, wall }
99gameplay_object_methods! { _ChainHeadNote, chain_head_note }
100gameplay_object_methods! { _ChainLinkNote, chain_link_note }
101gameplay_object_methods! { _ChainNote, chain_note }
102
103color_methods! { _Saber, saber }
104
105extern "C" {
106    fn _get_left_saber() -> _Saber;
107    fn _get_right_saber() -> _Saber;
108
109    fn _log(message: *const c_char);
110
111    // drops a host-managed object such as color notes, vectors, walls, etc
112    fn _drop_reference(ptr: *mut c_char);
113
114
115    fn _vec2_from_native(x: f32, y: f32) -> _Vec2;
116    fn _vec3_from_native(x: f32, y: f32, z: f32) -> _Vec3;
117    fn _vec4_from_native(x: f32, y: f32, z: f32, w: f32) -> _Vec4;
118    fn _quat_from_native(x: f32, y: f32, z: f32, w: f32) -> _Quat;
119
120    fn _color_set_rgb(color: _Color, r: f32, g: f32, b: f32);
121    fn _color_set_rgba(color: _Color, r: f32, g: f32, b: f32, a: f32);
122
123}
124
125macro_rules! cstr {
126    ( $str:expr ) => {
127        CString::new($str).unwrap()
128    };
129}
130
131// User facing definitions:
132
133pub struct Log {}
134impl Log {
135    pub fn info(message: &str) {
136        let s = format!("info: {}", message);
137        let c = cstr!(s);
138        unsafe { _log(c.as_ptr()) };
139    }
140
141    pub fn warning(message: &str) {
142        let s = format!("warning: {}", message);
143        let c = cstr!(s);
144        unsafe { _log(c.as_ptr()) };
145    }
146
147    pub fn error(message: &str) {
148        let s = format!("error: {}", message);
149        let c = cstr!(s);
150        unsafe { _log(c.as_ptr()) };
151    }
152
153    pub fn debug(message: &str) {
154        let s = format!("debug: {}", message);
155        let c = cstr!(s);
156        unsafe { _log(c.as_ptr()) };
157    }
158
159}
160
161macro_rules! wrapped {
162    ( $name:tt ) => {
163        pub struct $name {
164            _inner: paste! { [<_ $name>] }
165        }
166    };
167}
168
169macro_rules! instantiable_obj {
170    ( $ty:tt, $name:tt ) => {
171        wrapped! { $ty }
172        paste! {
173
174            pub fn [<create_ $name>](beat: f32) -> $ty {
175                unsafe { $ty { _inner: [<_create_ $name>](beat) } }
176            }
177
178            impl Beatmap {
179                pub fn [<add_ $name>]($name: $ty) {
180                    unsafe {
181                        [<_beatmap_add_ $name>]($name._inner);
182                    }
183                }
184            }
185        }
186    };
187}
188
189pub struct Beatmap;
190pub struct Data;
191
192instantiable_obj! { ColorNote, color_note }
193instantiable_obj! { BombNote, bomb_note }
194instantiable_obj! { ChainHeadNote, chain_head_note }
195instantiable_obj! { ChainLinkNote, chain_link_note }
196instantiable_obj! { ChainNote, chain_note }
197instantiable_obj! { Arc, arc }
198instantiable_obj! { Wall, wall }
199
200wrapped! { Vec2 }
201
202
203wrapped! { Vec3 }
204wrapped! { Vec4 }
205wrapped! { Quat }
206wrapped! { Color }
207
208attrs! { Vec2, vec2, x: f32, y: f32 }
209attrs! { Vec3, vec3, x: f32, y: f32, z: f32 }
210attrs! { Vec4, vec4, x: f32, y: f32, z: f32, w: f32 }
211attrs! { Quat, quat, x: f32, y: f32, z: f32, w: f32 }
212attrs! { Color, color, r: f32, g: f32, b: f32, a: f32 }
213
214trait UnityConvertible {
215    type UnityType;
216    fn to_unity_type(self) -> Self::UnityType;
217    fn from_unity_type(t: Self::UnityType) -> Self;
218}
219
220impl UnityConvertible for glam::Vec2 {
221    type UnityType = Vec2;
222    fn to_unity_type(self) -> Self::UnityType {
223        Vec2 { _inner: unsafe { _vec2_from_native(self.x, self.y) } }
224    }
225    fn from_unity_type(t: Self::UnityType) -> Self {
226        glam::Vec2::new(t.get_x(), t.get_y())
227    }
228}
229
230impl UnityConvertible for glam::Vec3 {
231    type UnityType = Vec3;
232    fn to_unity_type(self) -> Self::UnityType {
233        Vec3 { _inner: unsafe { _vec3_from_native(self.x, self.y, self.z) } }
234    }
235    fn from_unity_type(t: Self::UnityType) -> Self {
236        glam::Vec3::new(t.get_x(), t.get_y(), t.get_z())
237    }
238}
239
240impl UnityConvertible for glam::Vec4 {
241    type UnityType = Vec4;
242    fn to_unity_type(self) -> Self::UnityType {
243        Vec4 { _inner: unsafe { _vec4_from_native(self.x, self.y, self.z, self.w) } }
244    }
245    fn from_unity_type(t: Self::UnityType) -> Self {
246        glam::Vec4::new(t.get_x(), t.get_y(), t.get_z(), t.get_w())
247    }
248}
249
250impl UnityConvertible for glam::Quat {
251    type UnityType = Quat;
252    fn to_unity_type(self) -> Self::UnityType {
253        Quat { _inner: unsafe { _quat_from_native(self.x, self.y, self.z, self.w) } }
254    }
255    fn from_unity_type(t: Self::UnityType) -> Self {
256        glam::Quat::from_xyzw(t.get_x(), t.get_y(), t.get_z(), t.get_w())
257    }
258}
259
260
261impl Color {
262    pub fn set_rgb(&self, r: f32, g: f32, b: f32) {
263        unsafe { _color_set_rgb(self._inner, r, g, b) };
264    }
265
266    pub fn set_rgba(&self, r: f32, g: f32, b: f32, a: f32) {
267        unsafe { _color_set_rgba(self._inner, r, g, b, a) };
268    }
269}
270