1use std::sync::{Arc, Mutex};
5
6pub struct EngineState {
8 rotation: Arc<Mutex<f32>>,
9 pub(crate) input_state: Arc<Mutex<crate::input::InputState>>,
10}
11
12impl Clone for EngineState {
14 fn clone(&self) -> Self {
15 Self {
16 rotation: self.rotation.clone(),
17 input_state: self.input_state.clone(),
18 }
19 }
20}
21
22impl EngineState {
23 pub fn new() -> Self {
24 Self {
25 rotation: Arc::new(Mutex::new(0.0)),
26 input_state: Arc::new(Mutex::new(crate::input::InputState::new())),
27 }
28 }
29
30 pub fn set_rotation(&self, angle: f32) {
31 if let Ok(mut rot) = self.rotation.lock() {
32 *rot = angle;
33 }
34 }
35
36 pub fn get_rotation(&self) -> f32 {
37 self.rotation.lock().map(|r| *r).unwrap_or(0.0)
38 }
39
40 pub fn is_key_pressed(&self, key_code: u32) -> bool {
41 if let Ok(input) = self.input_state.lock() {
42 if let Some(code) = crate::input::u32_to_key_code(key_code) {
43 return input.is_key_pressed(code);
44 }
45 }
46 false
47 }
48
49 pub fn get_mouse_position(&self) -> (f32, f32) {
50 if let Ok(input) = self.input_state.lock() {
51 return input.mouse_position();
52 }
53 (0.0, 0.0)
54 }
55
56 pub fn get_mouse_delta(&self) -> (f32, f32) {
57 if let Ok(input) = self.input_state.lock() {
58 return input.mouse_delta();
59 }
60 (0.0, 0.0)
61 }
62}
63
64static mut ENGINE_STATE_PTR: *mut EngineState = std::ptr::null_mut();
66
67#[no_mangle]
69pub extern "C" fn engine_register_state_ptr(ptr: *mut EngineState) {
70 unsafe {
71 ENGINE_STATE_PTR = ptr;
72 }
73}
74
75#[no_mangle]
78pub extern "C" fn engine_set_rotation_callback(angle: f32) {
79 unsafe {
80 if !ENGINE_STATE_PTR.is_null() {
81 (*ENGINE_STATE_PTR).set_rotation(angle);
82 }
83 }
84}
85
86#[no_mangle]
87pub extern "C" fn engine_get_rotation_callback() -> f32 {
88 unsafe {
89 if !ENGINE_STATE_PTR.is_null() {
90 (*ENGINE_STATE_PTR).get_rotation()
91 } else {
92 0.0
93 }
94 }
95}
96
97#[no_mangle]
99pub extern "C" fn engine_is_key_pressed(key_code: u32) -> bool {
100 unsafe {
101 if !ENGINE_STATE_PTR.is_null() {
102 (*ENGINE_STATE_PTR).is_key_pressed(key_code)
103 } else {
104 false
105 }
106 }
107}
108
109#[no_mangle]
110pub extern "C" fn engine_get_mouse_x() -> f32 {
111 unsafe {
112 if !ENGINE_STATE_PTR.is_null() {
113 (*ENGINE_STATE_PTR).get_mouse_position().0
114 } else {
115 0.0
116 }
117 }
118}
119
120#[no_mangle]
121pub extern "C" fn engine_get_mouse_y() -> f32 {
122 unsafe {
123 if !ENGINE_STATE_PTR.is_null() {
124 (*ENGINE_STATE_PTR).get_mouse_position().1
125 } else {
126 0.0
127 }
128 }
129}
130
131#[no_mangle]
132pub extern "C" fn engine_get_mouse_delta_x() -> f32 {
133 unsafe {
134 if !ENGINE_STATE_PTR.is_null() {
135 (*ENGINE_STATE_PTR).get_mouse_delta().0
136 } else {
137 0.0
138 }
139 }
140}
141
142#[no_mangle]
143pub extern "C" fn engine_get_mouse_delta_y() -> f32 {
144 unsafe {
145 if !ENGINE_STATE_PTR.is_null() {
146 (*ENGINE_STATE_PTR).get_mouse_delta().1
147 } else {
148 0.0
149 }
150 }
151}
152
153static mut CAMERA_PTR: *mut crate::camera::Camera = std::ptr::null_mut();
155
156#[no_mangle]
158pub extern "C" fn engine_register_camera_ptr(ptr: *mut crate::camera::Camera) {
159 unsafe {
160 CAMERA_PTR = ptr;
161 eprintln!("DEBUG: engine_register_camera_ptr called with ptr: {:p}", ptr);
162 }
163}
164
165#[no_mangle]
166pub extern "C" fn engine_camera_set_position(x: f32, y: f32, z: f32) {
167 unsafe {
168 if !CAMERA_PTR.is_null() {
169 (*CAMERA_PTR).set_position(x, y, z);
170 }
171 }
172}
173
174#[no_mangle]
175pub extern "C" fn engine_camera_set_rotation(pitch: f32, yaw: f32) {
176 unsafe {
177 if !CAMERA_PTR.is_null() {
178 (*CAMERA_PTR).set_rotation(pitch, yaw);
179 }
180 }
181}
182
183#[no_mangle]
184pub extern "C" fn engine_camera_translate(dx: f32, dy: f32, dz: f32) {
185 unsafe {
186 if CAMERA_PTR.is_null() {
187 eprintln!("DEBUG: CAMERA_PTR is null in engine_camera_translate!");
188 return;
189 }
190 (*CAMERA_PTR).translate(dx, dy, dz);
191 }
192}
193
194#[no_mangle]
195pub extern "C" fn engine_camera_set_fov(fov: f32) {
196 unsafe {
197 if !CAMERA_PTR.is_null() {
198 (*CAMERA_PTR).set_fov(fov);
199 }
200 }
201}
202
203pub fn init_bridge() -> EngineState {
206 let state = EngineState::new();
207 let state_ptr = Box::leak(Box::new(EngineState {
208 rotation: state.rotation.clone(),
209 input_state: state.input_state.clone(),
210 }));
211 unsafe {
212 ENGINE_STATE_PTR = state_ptr;
213 }
214 state
215}
216
217pub fn get_rotation(state: &EngineState) -> f32 {
219 state.get_rotation()
220}