bridge: add in-process node registry and transform updates with logging; import CustomElement; implement Ctrl::Default; add sdxr_node_count() for diagnostics

This commit is contained in:
MayaTheShy
2025-11-08 13:53:57 -05:00
parent 6779e2106c
commit b5b563a6b2

View File

@@ -1,5 +1,6 @@
// Rust C-ABI bridge for StardustXR client integration. // Rust C-ABI bridge for StardustXR client integration.
use std::collections::HashMap;
use std::ffi::CStr; use std::ffi::CStr;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Mutex; use std::sync::Mutex;
@@ -11,8 +12,8 @@ use stardust_xr_asteroids::{
client::ClientState, client::ClientState,
elements::PlaySpace, elements::PlaySpace,
Migrate, Reify, Migrate, Reify,
CustomElement, Element,
}; };
use stardust_xr_asteroids::CustomElement;
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
#[derive(Default, serde::Serialize, serde::Deserialize)] #[derive(Default, serde::Serialize, serde::Deserialize)]
@@ -44,11 +45,30 @@ lazy_static::lazy_static! {
} }
#[derive(Default)] #[derive(Default)]
struct Node {
id: u64,
name: String,
transform: Mat4,
}
struct Ctrl { struct Ctrl {
rt: Option<Runtime>, rt: Option<Runtime>,
handle: Option<JoinHandle<()>>, // client running thread handle: Option<JoinHandle<()>>, // client running thread
tx: Option<tokio::sync::mpsc::UnboundedSender<Command>>, tx: Option<tokio::sync::mpsc::UnboundedSender<Command>>,
next_id: u64, next_id: u64,
nodes: HashMap<u64, Node>,
}
impl Default for Ctrl {
fn default() -> Self {
Self {
rt: None,
handle: None,
tx: None,
next_id: 1,
nodes: HashMap::new(),
}
}
} }
#[no_mangle] #[no_mangle]
@@ -68,24 +88,40 @@ pub extern "C" fn sdxr_start(app_id: *const std::os::raw::c_char) -> i32 {
.expect("tokio runtime"); .expect("tokio runtime");
let handle = std::thread::spawn(move || { let handle = std::thread::spawn(move || {
let res = rt.block_on(async move { let res = rt.block_on(async move {
// Run the client with our BridgeState // Run the client with our BridgeState (root PlaySpace)
let _state = BridgeState {}; let _state = BridgeState {};
// Launch a task to apply incoming commands once the client is up // Spawn command processor task
let cmd_task = tokio::spawn(async move { let cmd_task = tokio::spawn(async move {
// This is a placeholder; in a full implementation we would // We cannot mutate CTRL from inside this async task directly, so we
// hold references to created nodes. For now we simply drain. // accumulate changes and apply them via a secondary channel or by
// locking CTRL per message. Simplicity first: lock per command.
while let Some(cmd) = rx.recv().await { while let Some(cmd) = rx.recv().await {
match cmd { match cmd {
Command::Create { .. } => {} Command::Create { c_id, name, transform } => {
Command::Update { .. } => {} if let Ok(mut ctrl_locked) = CTRL.lock() {
ctrl_locked.nodes.insert(c_id, Node { id: c_id, name: name.clone(), transform });
}
println!("[bridge] create node id={} name={}", c_id, name);
}
Command::Update { c_id, transform } => {
if let Ok(mut ctrl_locked) = CTRL.lock() {
if let Some(n) = ctrl_locked.nodes.get_mut(&c_id) {
n.transform = transform;
println!("[bridge] update node id={}", c_id);
} else {
println!("[bridge] update for unknown node id={}", c_id);
}
}
}
Command::Shutdown => break, Command::Shutdown => break,
} }
} }
}); });
ast::client::run::<BridgeState>(&[]).await; ast::client::run::<BridgeState>(&[]).await;
// Do not await cmd_task here; runtime shutdown will cancel it // Runtime shutdown will drop task; we ignore join result intentionally.
let _ = cmd_task;
}); });
drop(rt); drop(rt);
let _ = res; let _ = res;
@@ -141,3 +177,11 @@ pub extern "C" fn sdxr_update_node(id: u64, mat4: *const f32) -> i32 {
if let Some(tx) = &ctrl.tx { let _ = tx.send(Command::Update { c_id: id, transform: mat }); } if let Some(tx) = &ctrl.tx { let _ = tx.send(Command::Update { c_id: id, transform: mat }); }
0 0
} }
// Optional: expose number of nodes for diagnostics
#[no_mangle]
pub extern "C" fn sdxr_node_count() -> u64 {
if !STARTED.load(Ordering::SeqCst) { return 0; }
let ctrl = CTRL.lock().unwrap();
ctrl.nodes.len() as u64
}