callbacks global

This commit is contained in:
Jaroslaw Konik 2025-05-12 12:08:04 +02:00
parent e95f025b07
commit cbde11d17b
4 changed files with 43 additions and 14 deletions

View file

@ -65,7 +65,7 @@ where
fn into_callback_system(self, world: &mut World) -> CallbackSystem<R>; fn into_callback_system(self, world: &mut World) -> CallbackSystem<R>;
} }
impl<R: Runtime, Out, FN, Marker> IntoCallbackSystem<R, (), Out, Marker> for FN impl<R: Runtime, Out: Send + 'static, FN, Marker> IntoCallbackSystem<R, (), Out, Marker> for FN
where where
FN: IntoSystem<(), Out, Marker>, FN: IntoSystem<(), Out, Marker>,
Out: for<'a> IntoRuntimeValueWithEngine<'a, Out, R>, Out: for<'a> IntoRuntimeValueWithEngine<'a, Out, R>,
@ -90,12 +90,12 @@ where
macro_rules! impl_tuple { macro_rules! impl_tuple {
($($idx:tt $t:tt),+) => { ($($idx:tt $t:tt),+) => {
impl<RN: Runtime, $($t,)+ Out, FN, Marker> IntoCallbackSystem<RN, In<($($t,)+)>, Out, Marker> impl<RN: Runtime, $($t,)+ Out: Send + 'static, FN, Marker> IntoCallbackSystem<RN, In<($($t,)+)>, Out, Marker>
for FN for FN
where where
FN: IntoSystem<In<($($t,)+)>, Out, Marker>, FN: IntoSystem<In<($($t,)+)>, Out, Marker>,
Out: for<'a> IntoRuntimeValueWithEngine<'a, Out, RN>, Out: for<'a> IntoRuntimeValueWithEngine<'a, Out, RN>,
$($t: 'static + for<'a> FromRuntimeValueWithEngine<'a, RN>,)+ $($t: Send + 'static + for<'a> FromRuntimeValueWithEngine<'a, RN>,)+
{ {
fn into_callback_system(self, world: &mut World) -> CallbackSystem<RN> { fn into_callback_system(self, world: &mut World) -> CallbackSystem<RN> {
let mut inner_system = IntoSystem::into_system(self); let mut inner_system = IntoSystem::into_system(self);

View file

@ -303,7 +303,10 @@ pub trait Runtime: Resource + Default {
/// Provides mutable reference to raw scripting engine instance. /// Provides mutable reference to raw scripting engine instance.
/// Can be used to directly interact with an interpreter to use interfaces /// Can be used to directly interact with an interpreter to use interfaces
/// that bevy_scriptum does not provided adapters for. /// that bevy_scriptum does not provided adapters for.
fn with_engine_mut<T>(&mut self, f: impl FnOnce(&mut Self::RawEngine) -> T) -> T; fn with_engine_mut<T: Send + 'static>(
&mut self,
f: impl FnOnce(&mut Self::RawEngine) -> T + Send + 'static,
) -> T;
/// Provides immutable reference to raw scripting engine instance. /// Provides immutable reference to raw scripting engine instance.
/// Can be used to directly interact with an interpreter to use interfaces /// Can be used to directly interact with an interpreter to use interfaces

View file

@ -1,6 +1,6 @@
// TODO: make sure ruby is statically linked // TODO: make sure ruby is statically linked
use std::{ use std::{
sync::LazyLock, sync::{LazyLock, Mutex},
thread::{self, JoinHandle}, thread::{self, JoinHandle},
}; };
@ -49,6 +49,7 @@ struct RubyThread {
handle: Option<JoinHandle<()>>, handle: Option<JoinHandle<()>>,
} }
// TODO: Can we put references to those in runtime struct?
static RUBY_THREAD: LazyLock<RubyThread> = LazyLock::new(|| RubyThread::spawn()); static RUBY_THREAD: LazyLock<RubyThread> = LazyLock::new(|| RubyThread::spawn());
impl RubyThread { impl RubyThread {
@ -112,8 +113,11 @@ impl Runtime for RubyRuntime {
type RawEngine = magnus::Ruby; type RawEngine = magnus::Ruby;
fn with_engine_mut<T>(&mut self, f: impl FnOnce(&mut Self::RawEngine) -> T) -> T { fn with_engine_mut<T: Send + 'static>(
f(&mut magnus::Ruby::get().unwrap()) &mut self,
f: impl FnOnce(&mut Self::RawEngine) -> T + Send + 'static,
) -> T {
RUBY_THREAD.execute_in(Box::new(move |mut ruby| f(&mut ruby)))
} }
fn with_engine<T: Send + 'static>( fn with_engine<T: Send + 'static>(
@ -150,12 +154,34 @@ impl Runtime for RubyRuntime {
+ Sync + Sync
+ 'static, + 'static,
) -> Result<(), crate::ScriptingError> { ) -> Result<(), crate::ScriptingError> {
static RUBY_CALLBACKS: LazyLock<
Mutex<
Vec<
Box<
dyn Fn(
(),
Vec<RubyValue>,
) -> Result<
crate::promise::Promise<(), RubyValue>,
crate::ScriptingError,
> + Send
+ Sync
+ 'static,
>,
>,
>,
> = LazyLock::new(|| Mutex::new(Vec::new()));
let mut callbacks = RUBY_CALLBACKS.lock().unwrap();
callbacks.push(Box::new(f));
fn callback() -> magnus::Value { fn callback() -> magnus::Value {
let ruby = magnus::Ruby::get().unwrap(); let ruby = magnus::Ruby::get().unwrap();
let method_name: magnus::value::StaticSymbol = let method_name: magnus::value::StaticSymbol =
ruby.class_object().funcall("__method__", ()).unwrap(); ruby.class_object().funcall("__method__", ()).unwrap();
let method_name = method_name.to_string(); let method_name = method_name.to_string();
dbg!(method_name); let mut callbacks = RUBY_CALLBACKS.lock().unwrap();
let f = callbacks.pop().unwrap();
f((), vec![]);
ruby.qnil().as_value() ruby.qnil().as_value()
} }

View file

@ -493,13 +493,13 @@ mod ruby_tests {
type ScriptData = RubyScriptData; type ScriptData = RubyScriptData;
fn assert_state_key_value_i64(world: &World, _entity_id: Entity, key: &str, value: i64) { fn assert_state_key_value_i64(world: &World, _entity_id: Entity, key: &str, value: i64) {
// let state: magnus::value::Value = Ruby::get() // let runtime = world.get_resource::<RubyRuntime>().unwrap();
// .unwrap() // let key = key.to_string();
// .class_object() // runtime.with_engine(move |engine| {
// .const_get("STATE") // let state: magnus::value::Value = engine.class_object().const_get("STATE").unwrap();
// .unwrap(); // let res: i64 = state.funcall_public("[]", (key,)).unwrap();
// let res: i64 = state.funcall_public("[]", (key.to_string(),)).unwrap();
// assert_eq!(res, value) // assert_eq!(res, value)
// })
} }
fn assert_state_key_value_i32(world: &World, _entity_id: Entity, key: &str, value: i32) { fn assert_state_key_value_i32(world: &World, _entity_id: Entity, key: &str, value: i32) {