Skip to content

Commit 4e6e162

Browse files
committed
implement in rhai too
1 parent 1691b3b commit 4e6e162

File tree

7 files changed

+83
-3
lines changed

7 files changed

+83
-3
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
fn on_script_loaded(){
2+
register_callback("on_test", dynamic_on_test);
3+
}
4+
5+
fn dynamic_on_test(){
6+
register_callback("on_test_last", dynamic_on_test_last);
7+
return "on test: I am dynamically registered from a normal callback!";
8+
}
9+
10+
fn dynamic_on_test_last(){
11+
return "on test last: I am dynamically registered from another dynamic callback!";
12+
}

assets/tests/register_callback/rhai/empty.rhai

Whitespace-only changes.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// #main_script dynamic_on_test.rhai
2+
SetCurrentLanguage language="@this_script_language"
3+
InstallPlugin miliseconds_budget=999999
4+
SetupHandler OnTest=null, Update=null
5+
SetupHandler OnTestPostUpdate=null, PostUpdate=null
6+
SetupHandler Last=null, OnTestLast=null
7+
FinalizeApp
8+
9+
LoadScriptAs as_name="@this_script", path="@this_script"
10+
WaitForScriptLoaded name="@this_script"
11+
SpawnEntityWithScript name="test_entity", script="@this_script"
12+
RunUpdateOnce
13+
EmitScriptCallbackEvent emit_response=true, entity="test_entity", label="OnTest", language=null, recipients="EntityScript", script="@this_script"
14+
EmitScriptCallbackEvent emit_response=true, entity="test_entity", label="OnTestLast", language=null, recipients="EntityScript", script="@this_script"
15+
RunUpdateOnce
16+
AssertCallbackSuccess attachment="EntityScript", entity="test_entity", label="OnTest", script="@this_script", expect_string_value="on test: I am dynamically registered from a normal callback!"
17+
AssertCallbackSuccess attachment="EntityScript", entity="test_entity", label="OnTestLast", script="@this_script", expect_string_value="on test last: I am dynamically registered from another dynamic callback!"
18+
19+
// reload, deleting old callbacks, expect stored callbacks to still work
20+
ReloadScriptFrom script="@this_script", path="empty.rhai"
21+
RunUpdateOnce
22+
EmitScriptCallbackEvent emit_response=true, entity="test_entity", label="OnTest", language=null, recipients="EntityScript", script="@this_script"
23+
EmitScriptCallbackEvent emit_response=true, entity="test_entity", label="OnTestLast", language=null, recipients="EntityScript", script="@this_script"
24+
RunUpdateOnce
25+
AssertCallbackSuccess attachment="EntityScript", entity="test_entity", label="OnTest", script="@this_script", expect_string_value="on test: I am dynamically registered from a normal callback!"
26+
AssertCallbackSuccess attachment="EntityScript", entity="test_entity", label="OnTestLast", script="@this_script", expect_string_value="on test last: I am dynamically registered from another dynamic callback!"
27+

crates/languages/bevy_mod_scripting_rhai/src/lib.rs

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Rhai scripting language support for Bevy.
22
3-
use std::{ops::Deref, str::Utf8Error};
3+
use std::{ops::Deref, str::Utf8Error, sync::Arc};
44

55
use crate::bindings::script_value::{FromDynamic, IntoDynamic};
66

@@ -10,7 +10,7 @@ use ::{
1010
bevy_ecs::{entity::Entity, world::World},
1111
};
1212
use bevy_app::App;
13-
use bevy_ecs::world::WorldId;
13+
use bevy_ecs::world::{Mut, WorldId};
1414
use bevy_log::trace;
1515
use bevy_mod_scripting_asset::{Language, ScriptAsset};
1616
use bevy_mod_scripting_bindings::{
@@ -19,6 +19,7 @@ use bevy_mod_scripting_bindings::{
1919
};
2020
use bevy_mod_scripting_core::{
2121
IntoScriptPluginParams, ScriptingPlugin,
22+
callbacks::ScriptCallbacks,
2223
config::{GetPluginThreadConfig, ScriptingPluginConfiguration},
2324
event::CallbackLabel,
2425
make_plugin_config_static,
@@ -30,7 +31,7 @@ use bindings::reference::{ReservedKeyword, RhaiReflectReference, RhaiStaticRefle
3031
use parking_lot::RwLock;
3132
pub use rhai;
3233

33-
use rhai::{AST, CallFnOptions, Dynamic, Engine, EvalAltResult, ParseError, Scope};
34+
use rhai::{AST, CallFnOptions, Dynamic, Engine, EvalAltResult, FnPtr, ParseError, Scope};
3435
/// Bindings for rhai.
3536
pub mod bindings;
3637

@@ -129,6 +130,45 @@ impl AsMut<ScriptingPlugin<Self>> for RhaiScriptingPlugin {
129130
}
130131
}
131132

133+
fn register_plugin_globals(ctxt: &mut Engine) {
134+
let register_callback_fn = |callback: String, func: FnPtr| {
135+
let thread_ctxt = ThreadWorldContainer
136+
.try_get_context()
137+
.map_err(|e| Box::new(EvalAltResult::ErrorSystem("".to_string(), Box::new(e))))?;
138+
let world = thread_ctxt.world;
139+
let attachment = thread_ctxt.attachment;
140+
world
141+
.with_resource_mut(|res: Mut<ScriptCallbacks<RhaiScriptingPlugin>>| {
142+
let mut callbacks = res.callbacks.write();
143+
callbacks.insert(
144+
(attachment.clone(), callback),
145+
Arc::new(
146+
move |args: Vec<ScriptValue>,
147+
rhai: &mut RhaiScriptContext,
148+
world_id: WorldId| {
149+
let config = RhaiScriptingPlugin::readonly_configuration(world_id);
150+
let pre_handling_callbacks = config.pre_handling_callbacks;
151+
let runtime = config.runtime;
152+
let runtime_guard = runtime.read();
153+
pre_handling_callbacks
154+
.iter()
155+
.try_for_each(|init| init(&attachment, rhai))?;
156+
157+
let ret = func
158+
.call::<Dynamic>(&runtime_guard, &rhai.ast, args)
159+
.map_err(IntoInteropError::into_bms_error)?;
160+
ScriptValue::from_dynamic(ret).map_err(IntoInteropError::into_bms_error)
161+
},
162+
),
163+
)
164+
})
165+
.map_err(|e| Box::new(EvalAltResult::ErrorSystem("".to_string(), Box::new(e))))?;
166+
Ok::<_, Box<EvalAltResult>>(())
167+
};
168+
169+
ctxt.register_fn("register_callback", register_callback_fn);
170+
}
171+
132172
impl Default for RhaiScriptingPlugin {
133173
fn default() -> Self {
134174
RhaiScriptingPlugin {
@@ -140,6 +180,7 @@ impl Default for RhaiScriptingPlugin {
140180
engine.build_type::<RhaiReflectReference>();
141181
engine.build_type::<RhaiStaticReflectReference>();
142182
engine.register_iterator_result::<RhaiReflectReference, _>();
183+
register_plugin_globals(&mut engine);
143184
Ok(())
144185
}],
145186
context_initializers: vec![

0 commit comments

Comments
 (0)