,
script_contexts: ScriptContext,
+ script_callbacks: ScriptCallbacks
,
}
/// Equivalent of [`SystemParam`] but for dynamic systems, these are the kinds of things
@@ -387,10 +387,12 @@ impl System for DynamicScriptSystem {
if let Some(context) = script_context.get_context(&self.target_attachment) {
let mut context = context.lock();
- let result = context.call_context_dynamic(
+ let result = P::handle(
+ payload,
&self.target_attachment,
&state.callback_label,
- payload,
+ &mut context,
+ state.script_callbacks.clone(),
guard.clone(),
);
drop(context);
@@ -493,6 +495,7 @@ impl System for DynamicScriptSystem {
callback_label: self.name.to_string().into(),
system_params,
script_contexts: world.get_resource_or_init::>().clone(),
+ script_callbacks: world.get_resource_or_init::>().clone(),
})
}
diff --git a/crates/bevy_mod_scripting_display/src/handle.rs b/crates/bevy_mod_scripting_display/src/handle.rs
new file mode 100644
index 0000000000..87fd1add50
--- /dev/null
+++ b/crates/bevy_mod_scripting_display/src/handle.rs
@@ -0,0 +1,44 @@
+use bevy_asset::{Asset, Handle};
+use std::fmt;
+
+/// Display the path of a script or its asset ID.
+#[doc(hidden)]
+pub struct HandleDisplay<'a, T: Asset>(&'a Handle);
+
+impl<'a, A: Asset> fmt::Display for HandleDisplay<'a, A> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if let Some(path) = self.0.path() {
+ write!(f, "path {path}")
+ } else {
+ write!(f, "id {}", self.0.id())
+ }
+ }
+}
+
+impl<'a, A: Asset> fmt::Debug for HandleDisplay<'a, A> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if let Some(path) = self.0.path() {
+ write!(f, "path {path:?}")
+ } else {
+ write!(f, "id {:?}", self.0.id())
+ }
+ }
+}
+
+/// Make a type display-able.
+pub trait DisplayProxy {
+ /// The type that does the displaying.
+ type D<'a>: fmt::Display + fmt::Debug
+ where
+ Self: 'a;
+ /// Return a display-able reference.
+ fn display<'a>(&'a self) -> Self::D<'a>;
+}
+
+impl DisplayProxy for Handle {
+ type D<'a> = HandleDisplay<'a, A>;
+
+ fn display<'a>(&'a self) -> Self::D<'a> {
+ HandleDisplay(self)
+ }
+}
diff --git a/crates/bevy_mod_scripting_display/src/lib.rs b/crates/bevy_mod_scripting_display/src/lib.rs
index 95e72b92ec..7a873dfa59 100644
--- a/crates/bevy_mod_scripting_display/src/lib.rs
+++ b/crates/bevy_mod_scripting_display/src/lib.rs
@@ -4,9 +4,10 @@ use std::{
any::{Any, TypeId},
ops::Deref,
};
+mod handle;
mod impls;
mod printer;
-pub use printer::*;
+pub use {handle::*, printer::*};
use bevy_ecs::{
component::{ComponentId, ComponentInfo},
diff --git a/crates/bevy_mod_scripting_functions/Cargo.toml b/crates/bevy_mod_scripting_functions/Cargo.toml
index 6127883653..fb2c1a13b7 100644
--- a/crates/bevy_mod_scripting_functions/Cargo.toml
+++ b/crates/bevy_mod_scripting_functions/Cargo.toml
@@ -46,6 +46,7 @@ bevy_mod_scripting_core = { workspace = true }
bevy_mod_scripting_bindings = { workspace = true }
bevy_mod_scripting_display = { workspace = true }
bevy_mod_scripting_asset = { workspace = true }
+bevy_mod_scripting_script = { workspace = true }
bevy_mod_scripting_derive = { workspace = true }
bevy_mod_scripting_lua = { path = "../languages/bevy_mod_scripting_lua", optional = true, version = "0.16.0" }
bevy_mod_scripting_rhai = { path = "../languages/bevy_mod_scripting_rhai", optional = true, version = "0.16.0" }
diff --git a/crates/bevy_mod_scripting_functions/src/core.rs b/crates/bevy_mod_scripting_functions/src/core.rs
index c3ffd8584a..7c5c3227e2 100644
--- a/crates/bevy_mod_scripting_functions/src/core.rs
+++ b/crates/bevy_mod_scripting_functions/src/core.rs
@@ -1,6 +1,7 @@
//! Contains functions defined by the [`bevy_mod_scripting_core`] crate
use bevy_mod_scripting_asset::ScriptAsset;
+use bevy_mod_scripting_script::ScriptAttachment;
use bevy_platform::collections::HashMap;
use std::ops::Deref;
@@ -11,7 +12,6 @@ use bevy_mod_scripting_bindings::{
DynamicScriptFunctionMut, FunctionInfo, GlobalNamespace, InteropError, PartialReflectExt,
ReflectReference, ScriptComponentRegistration, ScriptQueryBuilder, ScriptQueryResult,
ScriptResourceRegistration, ScriptTypeRegistration, ThreadWorldContainer, Union,
- WorldContainer,
function::{
from::{Ref, Val},
from_ref::FromScriptRef,
@@ -20,10 +20,7 @@ use bevy_mod_scripting_bindings::{
},
script_value::ScriptValue,
};
-use bevy_mod_scripting_core::{
- script::ScriptAttachment,
- script_system::{ManageScriptSystems, ScriptSystemBuilder},
-};
+use bevy_mod_scripting_core::script_system::{ManageScriptSystems, ScriptSystemBuilder};
use bevy_mod_scripting_derive::script_bindings;
use bevy_mod_scripting_display::{OrFakeId, WithTypeInfo};
use bevy_reflect::PartialReflect;
@@ -832,7 +829,7 @@ impl ReflectReference {
let iter_function = move || {
// world is not thread safe, we can't capture it in the closure
// or it will also be non-thread safe
- let world = ThreadWorldContainer.try_get_world()?;
+ let world = ThreadWorldContainer.try_get_context()?.world;
if len == 0 {
return Ok(ScriptValue::Unit);
}
diff --git a/crates/bevy_mod_scripting_script/Cargo.toml b/crates/bevy_mod_scripting_script/Cargo.toml
new file mode 100644
index 0000000000..f3a6599e37
--- /dev/null
+++ b/crates/bevy_mod_scripting_script/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+name = "bevy_mod_scripting_script"
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+homepage.workspace = true
+repository.workspace = true
+keywords.workspace = true
+categories.workspace = true
+readme.workspace = true
+
+[dependencies]
+bevy_mod_scripting_asset = { workspace = true }
+bevy_mod_scripting_display = { workspace = true }
+bevy_ecs = { workspace = true }
+bevy_reflect = { workspace = true }
+bevy_asset = { workspace = true }
+
+[lints]
+workspace = true
diff --git a/crates/bevy_mod_scripting_script/src/lib.rs b/crates/bevy_mod_scripting_script/src/lib.rs
new file mode 100644
index 0000000000..ecb62e5d76
--- /dev/null
+++ b/crates/bevy_mod_scripting_script/src/lib.rs
@@ -0,0 +1,83 @@
+//! Contains definitions for script related structures
+
+use bevy_asset::Handle;
+use bevy_ecs::entity::Entity;
+use bevy_mod_scripting_asset::ScriptAsset;
+use bevy_mod_scripting_display::DisplayProxy;
+use bevy_reflect::Reflect;
+use std::fmt;
+
+/// Specifies a unique attachment of a script. These attachments are mapped to [`ContextKey`]'s depending on the context policy used.
+#[derive(Debug, Hash, Clone, PartialEq, Eq, Reflect)]
+pub enum ScriptAttachment {
+ /// a script attached to an entity, with an optional domain. By default selecting a domain will put the context of this script on a per-domain basis.
+ EntityScript(Entity, Handle),
+ /// a static script, with an optional domain. By default selecting a domain will put the context of this script on a per-domain basis.
+ StaticScript(Handle),
+}
+
+impl std::fmt::Display for ScriptAttachment {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ ScriptAttachment::EntityScript(entity, script) => {
+ write!(
+ f,
+ "EntityScript(entity: {}, script: {})",
+ entity,
+ script.display(),
+ )
+ }
+ ScriptAttachment::StaticScript(script) => {
+ write!(f, "StaticScript(script: {})", script.display())
+ }
+ }
+ }
+}
+
+impl ScriptAttachment {
+ /// Returns the script handle.
+ pub fn script(&self) -> Handle {
+ match self {
+ ScriptAttachment::EntityScript(_, script) => script.clone(),
+ ScriptAttachment::StaticScript(script) => script.clone(),
+ }
+ }
+
+ /// Returns a mutable reference to the underlying script handle.
+ pub fn script_mut(&mut self) -> &mut Handle {
+ match self {
+ ScriptAttachment::EntityScript(_, script) => script,
+ ScriptAttachment::StaticScript(script) => script,
+ }
+ }
+
+ /// Returns the entity if it exists.
+ pub fn entity(&self) -> Option {
+ match self {
+ ScriptAttachment::EntityScript(entity, _) => Some(*entity),
+ ScriptAttachment::StaticScript(_) => None,
+ }
+ }
+
+ /// Downcasts any script handles into weak handles.
+ pub fn into_weak(self) -> Self {
+ match self {
+ ScriptAttachment::EntityScript(entity, script) => {
+ ScriptAttachment::EntityScript(entity, script.clone_weak())
+ }
+ ScriptAttachment::StaticScript(script) => {
+ ScriptAttachment::StaticScript(script.clone_weak())
+ }
+ }
+ }
+
+ /// Returns true if the attachment is a static script.
+ pub fn is_static(&self) -> bool {
+ matches!(self, ScriptAttachment::StaticScript(_))
+ }
+
+ /// Returns true if the attachment is an entity script.
+ pub fn is_entity_script(&self) -> bool {
+ matches!(self, ScriptAttachment::EntityScript(_, _))
+ }
+}
diff --git a/crates/languages/bevy_mod_scripting_lua/Cargo.toml b/crates/languages/bevy_mod_scripting_lua/Cargo.toml
index e9801676b2..7740b36ac4 100644
--- a/crates/languages/bevy_mod_scripting_lua/Cargo.toml
+++ b/crates/languages/bevy_mod_scripting_lua/Cargo.toml
@@ -46,6 +46,7 @@ bevy_mod_scripting_core = { workspace = true }
bevy_mod_scripting_display = { workspace = true }
bevy_mod_scripting_bindings = { workspace = true }
bevy_mod_scripting_asset = { workspace = true }
+bevy_mod_scripting_script = { workspace = true }
mlua = { workspace = true, features = ["vendored", "send", "macros"] }
profiling = { workspace = true }
diff --git a/crates/languages/bevy_mod_scripting_lua/src/bindings/reference.rs b/crates/languages/bevy_mod_scripting_lua/src/bindings/reference.rs
index 23f1a85643..dc676b48ad 100644
--- a/crates/languages/bevy_mod_scripting_lua/src/bindings/reference.rs
+++ b/crates/languages/bevy_mod_scripting_lua/src/bindings/reference.rs
@@ -1,8 +1,7 @@
use std::any::TypeId;
use bevy_mod_scripting_bindings::{
- ReflectReference, ThreadWorldContainer, WorldContainer, error::InteropError,
- script_value::ScriptValue,
+ ReflectReference, ThreadWorldContainer, error::InteropError, script_value::ScriptValue,
};
use bevy_mod_scripting_display::OrFakeId;
use mlua::{ExternalError, MetaMethod, UserData, UserDataMethods};
@@ -41,8 +40,9 @@ impl UserData for LuaReflectReference {
|_, (self_, key): (LuaReflectReference, LuaScriptValue)| {
profiling::function_scope!("MetaMethod::Index");
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoMluaError::to_lua_error)?;
+ .try_get_context()
+ .map_err(IntoMluaError::to_lua_error)?
+ .world;
let self_: ReflectReference = self_.into();
let type_id = self_
.tail_type_id(world.clone())
@@ -80,8 +80,9 @@ impl UserData for LuaReflectReference {
|_, (self_, key, value): (LuaReflectReference, LuaScriptValue, LuaScriptValue)| {
profiling::function_scope!("MetaMethod::NewIndex");
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoMluaError::to_lua_error)?;
+ .try_get_context()
+ .map_err(IntoMluaError::to_lua_error)?
+ .world;
let self_: ReflectReference = self_.into();
let key: ScriptValue = key.into();
let value: ScriptValue = value.into();
@@ -103,8 +104,9 @@ impl UserData for LuaReflectReference {
|_, (self_, other): (LuaReflectReference, LuaScriptValue)| {
profiling::function_scope!("MetaMethod::Sub");
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoMluaError::to_lua_error)?;
+ .try_get_context()
+ .map_err(IntoMluaError::to_lua_error)?
+ .world;
let self_: ReflectReference = self_.into();
let other: ScriptValue = other.into();
let target_type_id = self_
@@ -124,8 +126,9 @@ impl UserData for LuaReflectReference {
|_, (self_, other): (LuaReflectReference, LuaScriptValue)| {
profiling::function_scope!("MetaMethod::Add");
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoMluaError::to_lua_error)?;
+ .try_get_context()
+ .map_err(IntoMluaError::to_lua_error)?
+ .world;
let self_: ReflectReference = self_.into();
let other: ScriptValue = other.into();
let target_type_id = self_
@@ -145,8 +148,9 @@ impl UserData for LuaReflectReference {
|_, (self_, other): (LuaReflectReference, LuaScriptValue)| {
profiling::function_scope!("MetaMethod::Mul");
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoMluaError::to_lua_error)?;
+ .try_get_context()
+ .map_err(IntoMluaError::to_lua_error)?
+ .world;
let self_: ReflectReference = self_.into();
let other: ScriptValue = other.into();
let target_type_id = self_
@@ -166,8 +170,9 @@ impl UserData for LuaReflectReference {
|_, (self_, other): (LuaReflectReference, LuaScriptValue)| {
profiling::function_scope!("MetaMethod::Div");
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoMluaError::to_lua_error)?;
+ .try_get_context()
+ .map_err(IntoMluaError::to_lua_error)?
+ .world;
let self_: ReflectReference = self_.into();
let other: ScriptValue = other.into();
let target_type_id = self_
@@ -187,8 +192,9 @@ impl UserData for LuaReflectReference {
|_, (self_, other): (LuaReflectReference, LuaScriptValue)| {
profiling::function_scope!("MetaMethod::Mod");
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoMluaError::to_lua_error)?;
+ .try_get_context()
+ .map_err(IntoMluaError::to_lua_error)?
+ .world;
let self_: ReflectReference = self_.into();
let other: ScriptValue = other.into();
let target_type_id = self_
@@ -206,8 +212,9 @@ impl UserData for LuaReflectReference {
m.add_meta_function(MetaMethod::Unm, |_, self_: LuaReflectReference| {
profiling::function_scope!("MetaMethod::Unm");
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoMluaError::to_lua_error)?;
+ .try_get_context()
+ .map_err(IntoMluaError::to_lua_error)?
+ .world;
let self_: ReflectReference = self_.into();
let target_type_id = self_
.tail_type_id(world.clone())
@@ -225,8 +232,9 @@ impl UserData for LuaReflectReference {
|_, (self_, other): (LuaReflectReference, LuaScriptValue)| {
profiling::function_scope!("MetaMethod::Pow");
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoMluaError::to_lua_error)?;
+ .try_get_context()
+ .map_err(IntoMluaError::to_lua_error)?
+ .world;
let self_: ReflectReference = self_.into();
let other: ScriptValue = other.into();
let target_type_id = self_
@@ -246,8 +254,9 @@ impl UserData for LuaReflectReference {
|_, (self_, other): (LuaReflectReference, LuaScriptValue)| {
profiling::function_scope!("MetaMethod::Eq");
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoMluaError::to_lua_error)?;
+ .try_get_context()
+ .map_err(IntoMluaError::to_lua_error)?
+ .world;
let self_: ReflectReference = self_.into();
let other: ScriptValue = other.into();
let target_type_id = self_
@@ -267,8 +276,9 @@ impl UserData for LuaReflectReference {
|_, (self_, other): (LuaReflectReference, LuaScriptValue)| {
profiling::function_scope!("MetaMethod::Lt");
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoMluaError::to_lua_error)?;
+ .try_get_context()
+ .map_err(IntoMluaError::to_lua_error)?
+ .world;
let self_: ReflectReference = self_.into();
let other: ScriptValue = other.into();
let target_type_id = self_
@@ -286,8 +296,9 @@ impl UserData for LuaReflectReference {
m.add_meta_function(MetaMethod::Len, |_lua, self_: LuaScriptValue| {
profiling::function_scope!("MetaMethod::Len");
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoMluaError::to_lua_error)?;
+ .try_get_context()
+ .map_err(IntoMluaError::to_lua_error)?
+ .world;
let script_value: ScriptValue = self_.into();
Ok(match script_value {
ScriptValue::Reference(r) => r.len(world).map_err(IntoMluaError::to_lua_error)?,
@@ -307,8 +318,9 @@ impl UserData for LuaReflectReference {
// let mut iter_func = lookup_dynamic_function_typed::(l, "iter")
// .expect("No iter function registered");
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoMluaError::to_lua_error)?;
+ .try_get_context()
+ .map_err(IntoMluaError::to_lua_error)?
+ .world;
let iter_func = world
.lookup_function([TypeId::of::()], "iter")
@@ -327,8 +339,9 @@ impl UserData for LuaReflectReference {
m.add_meta_function(MetaMethod::ToString, |_, self_: LuaReflectReference| {
profiling::function_scope!("MetaMethod::ToString");
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoMluaError::to_lua_error)?;
+ .try_get_context()
+ .map_err(IntoMluaError::to_lua_error)?
+ .world;
let reflect_reference: ReflectReference = self_.into();
let func = world
@@ -362,8 +375,9 @@ impl UserData for LuaStaticReflectReference {
|_, (self_, key): (LuaStaticReflectReference, LuaScriptValue)| {
profiling::function_scope!("MetaMethod::Index");
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoMluaError::to_lua_error)?;
+ .try_get_context()
+ .map_err(IntoMluaError::to_lua_error)?
+ .world;
let type_id = self_.0;
let key: ScriptValue = key.into();
diff --git a/crates/languages/bevy_mod_scripting_lua/src/lib.rs b/crates/languages/bevy_mod_scripting_lua/src/lib.rs
index f60c605684..39d771f9f4 100644
--- a/crates/languages/bevy_mod_scripting_lua/src/lib.rs
+++ b/crates/languages/bevy_mod_scripting_lua/src/lib.rs
@@ -1,5 +1,8 @@
//! Lua integration for the bevy_mod_scripting system.
-use std::ops::{Deref, DerefMut};
+use std::{
+ ops::{Deref, DerefMut},
+ sync::Arc,
+};
use ::{
bevy_app::Plugin,
@@ -7,27 +10,28 @@ use ::{
bevy_ecs::{entity::Entity, world::World},
};
use bevy_app::App;
-use bevy_ecs::world::WorldId;
+use bevy_ecs::world::{Mut, WorldId};
use bevy_log::trace;
use bevy_mod_scripting_asset::{Language, ScriptAsset};
use bevy_mod_scripting_bindings::{
- InteropError, PartialReflectExt, ThreadWorldContainer, WorldContainer,
- function::namespace::Namespace, globals::AppScriptGlobalsRegistry, script_value::ScriptValue,
+ InteropError, PartialReflectExt, ThreadWorldContainer, function::namespace::Namespace,
+ globals::AppScriptGlobalsRegistry, script_value::ScriptValue,
};
use bevy_mod_scripting_core::{
IntoScriptPluginParams, ScriptingPlugin,
+ callbacks::ScriptCallbacks,
config::{GetPluginThreadConfig, ScriptingPluginConfiguration},
event::CallbackLabel,
- extractors::GetPluginFor,
make_plugin_config_static,
- script::{ContextPolicy, ScriptAttachment},
+ script::ContextPolicy,
};
+use bevy_mod_scripting_script::ScriptAttachment;
use bindings::{
reference::{LuaReflectReference, LuaStaticReflectReference},
script_value::LuaScriptValue,
};
pub use mlua;
-use mlua::{Function, IntoLua, Lua, MultiValue};
+use mlua::{Function, IntoLua, Lua, MultiValue, Variadic};
/// Bindings for lua.
pub mod bindings;
@@ -52,10 +56,6 @@ impl DerefMut for LuaContext {
}
}
-impl GetPluginFor for LuaContext {
- type P = LuaScriptingPlugin;
-}
-
impl IntoScriptPluginParams for LuaScriptingPlugin {
type C = LuaContext;
type R = ();
@@ -89,6 +89,51 @@ pub struct LuaScriptingPlugin {
pub scripting_plugin: ScriptingPlugin,
}
+fn register_plugin_globals(lua: &mut Lua) -> Result<(), mlua::Error> {
+ lua.globals().set(
+ "register_callback",
+ lua.create_function(|_lua: &Lua, (callback, func): (String, Function)| {
+ let thread_ctxt = ThreadWorldContainer
+ .try_get_context()
+ .map_err(mlua::Error::external)?;
+ let world = thread_ctxt.world;
+ let attachment = thread_ctxt.attachment;
+ world
+ .with_resource_mut(|res: Mut>| {
+ let mut callbacks = res.callbacks.write();
+ callbacks.insert(
+ (attachment.clone(), callback),
+ Arc::new(
+ move |args: Vec,
+ lua: &mut LuaContext,
+ world_id: WorldId| {
+ let pre_handling_callbacks =
+ LuaScriptingPlugin::readonly_configuration(world_id)
+ .pre_handling_callbacks;
+
+ pre_handling_callbacks
+ .iter()
+ .try_for_each(|init| init(&attachment, lua))?;
+
+ let args = args
+ .into_iter()
+ .map(LuaScriptValue)
+ .collect::>();
+
+ func.call::(args)
+ .map_err(IntoInteropError::to_bms_error)
+ .map(ScriptValue::from)
+ },
+ ),
+ )
+ })
+ .map_err(mlua::Error::external)?;
+ Ok(())
+ })?,
+ )?;
+ Ok(())
+}
+
impl Default for LuaScriptingPlugin {
fn default() -> Self {
LuaScriptingPlugin {
@@ -98,19 +143,22 @@ impl Default for LuaScriptingPlugin {
context_initializers: vec![
|_script_id, context| {
// set the world global
- context
- .globals()
+ let globals = context.globals();
+
+ globals
.set(
"world",
LuaStaticReflectReference(std::any::TypeId::of::()),
)
.map_err(IntoInteropError::to_bms_error)?;
+ register_plugin_globals(context).map_err(IntoInteropError::to_bms_error)?;
+
Ok(())
},
|_script_id, context| {
// set static globals
- let world = ThreadWorldContainer.try_get_world()?;
+ let world = ThreadWorldContainer.try_get_context()?.world;
let globals_registry =
world.with_resource(|r: &AppScriptGlobalsRegistry| r.clone())?;
let globals_registry = globals_registry.read();
@@ -157,7 +205,7 @@ impl Default for LuaScriptingPlugin {
],
context_pre_handling_initializers: vec![|context_key, context| {
// TODO: convert these to functions
- let world = ThreadWorldContainer.try_get_world()?;
+ let world = ThreadWorldContainer.try_get_context()?.world;
if let Some(entity) = context_key.entity() {
context
.globals()
diff --git a/crates/languages/bevy_mod_scripting_rhai/Cargo.toml b/crates/languages/bevy_mod_scripting_rhai/Cargo.toml
index 5b34fbac5a..d791c59c95 100644
--- a/crates/languages/bevy_mod_scripting_rhai/Cargo.toml
+++ b/crates/languages/bevy_mod_scripting_rhai/Cargo.toml
@@ -26,6 +26,7 @@ bevy_mod_scripting_core = { workspace = true }
bevy_mod_scripting_display = { workspace = true }
bevy_mod_scripting_bindings = { workspace = true }
bevy_mod_scripting_asset = { workspace = true }
+bevy_mod_scripting_script = { workspace = true }
strum = { workspace = true, features = ["derive"] }
parking_lot = { workspace = true }
diff --git a/crates/languages/bevy_mod_scripting_rhai/src/bindings/reference.rs b/crates/languages/bevy_mod_scripting_rhai/src/bindings/reference.rs
index a5799c3427..ecf80ce8f4 100644
--- a/crates/languages/bevy_mod_scripting_rhai/src/bindings/reference.rs
+++ b/crates/languages/bevy_mod_scripting_rhai/src/bindings/reference.rs
@@ -5,7 +5,7 @@ use std::{
use crate::IntoRhaiError;
use bevy_mod_scripting_bindings::{
- ReflectReference, ScriptValue, ThreadWorldContainer, WorldContainer, error::InteropError,
+ ReflectReference, ScriptValue, ThreadWorldContainer, error::InteropError,
function::script_function::DynamicScriptFunctionMut,
};
use bevy_mod_scripting_display::OrFakeId;
@@ -256,7 +256,7 @@ impl IntoIterator for RhaiReflectReference {
fn into_iter(self) -> Self::IntoIter {
let result = (|| {
- let world = ThreadWorldContainer.try_get_world()?;
+ let world = ThreadWorldContainer.try_get_context()?.world;
let iter_func = world
.lookup_function([TypeId::of::()], "iter")
@@ -295,8 +295,9 @@ impl CustomType for RhaiReflectReference {
.with_name(std::any::type_name::())
.with_indexer_get(|self_: &mut Self, index: Dynamic| {
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoRhaiError::into_rhai_error)?;
+ .try_get_context()
+ .map_err(IntoRhaiError::into_rhai_error)?
+ .world;
let self_ = &self_.0;
let type_id = self_
.tail_type_id(world.clone())
@@ -332,8 +333,9 @@ impl CustomType for RhaiReflectReference {
})
.with_indexer_set(|self_: &mut Self, index: Dynamic, value: Dynamic| {
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoRhaiError::into_rhai_error)?;
+ .try_get_context()
+ .map_err(IntoRhaiError::into_rhai_error)?
+ .world;
let self_ = self_.0.clone();
let key = ScriptValue::from_dynamic(index)?;
let value = ScriptValue::from_dynamic(value)?;
@@ -351,8 +353,9 @@ impl CustomType for RhaiReflectReference {
RhaiOperator::Sub.function_name(),
|self_: Self, other: Dynamic| {
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoRhaiError::into_rhai_error)?;
+ .try_get_context()
+ .map_err(IntoRhaiError::into_rhai_error)?
+ .world;
let self_: ReflectReference = self_.0.clone();
let other: ScriptValue = ScriptValue::from_dynamic(other)?;
let target_type_id = self_
@@ -370,8 +373,9 @@ impl CustomType for RhaiReflectReference {
RhaiOperator::Add.function_name(),
|self_: Self, other: Dynamic| {
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoRhaiError::into_rhai_error)?;
+ .try_get_context()
+ .map_err(IntoRhaiError::into_rhai_error)?
+ .world;
let self_: ReflectReference = self_.0.clone();
let other: ScriptValue = ScriptValue::from_dynamic(other)?;
let target_type_id = self_
@@ -389,8 +393,9 @@ impl CustomType for RhaiReflectReference {
RhaiOperator::Mul.function_name(),
|self_: Self, other: Dynamic| {
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoRhaiError::into_rhai_error)?;
+ .try_get_context()
+ .map_err(IntoRhaiError::into_rhai_error)?
+ .world;
let self_: ReflectReference = self_.0.clone();
let other: ScriptValue = ScriptValue::from_dynamic(other)?;
let target_type_id = self_
@@ -408,8 +413,9 @@ impl CustomType for RhaiReflectReference {
RhaiOperator::Div.function_name(),
|self_: Self, other: Dynamic| {
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoRhaiError::into_rhai_error)?;
+ .try_get_context()
+ .map_err(IntoRhaiError::into_rhai_error)?
+ .world;
let self_: ReflectReference = self_.0.clone();
let other: ScriptValue = ScriptValue::from_dynamic(other)?;
let target_type_id = self_
@@ -427,8 +433,9 @@ impl CustomType for RhaiReflectReference {
RhaiOperator::Mod.function_name(),
|self_: Self, other: Dynamic| {
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoRhaiError::into_rhai_error)?;
+ .try_get_context()
+ .map_err(IntoRhaiError::into_rhai_error)?
+ .world;
let self_: ReflectReference = self_.0.clone();
let other: ScriptValue = ScriptValue::from_dynamic(other)?;
let target_type_id = self_
@@ -444,8 +451,9 @@ impl CustomType for RhaiReflectReference {
)
.with_fn(RhaiOperator::Unm.function_name(), |self_: Self| {
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoRhaiError::into_rhai_error)?;
+ .try_get_context()
+ .map_err(IntoRhaiError::into_rhai_error)?
+ .world;
let self_: ReflectReference = self_.0.clone();
let target_type_id = self_
.tail_type_id(world.clone())
@@ -461,8 +469,9 @@ impl CustomType for RhaiReflectReference {
RhaiOperator::Pow.function_name(),
|self_: Self, other: Dynamic| {
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoRhaiError::into_rhai_error)?;
+ .try_get_context()
+ .map_err(IntoRhaiError::into_rhai_error)?
+ .world;
let self_: ReflectReference = self_.0.clone();
let other: ScriptValue = ScriptValue::from_dynamic(other)?;
let target_type_id = self_
@@ -480,8 +489,9 @@ impl CustomType for RhaiReflectReference {
RhaiOperator::Eq.function_name(),
|self_: Self, other: Dynamic| {
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoRhaiError::into_rhai_error)?;
+ .try_get_context()
+ .map_err(IntoRhaiError::into_rhai_error)?
+ .world;
let self_: ReflectReference = self_.0.clone();
let other: ScriptValue = ScriptValue::from_dynamic(other)?;
let target_type_id = self_
@@ -499,8 +509,9 @@ impl CustomType for RhaiReflectReference {
RhaiOperator::Ne.function_name(),
|self_: Self, other: Dynamic| {
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoRhaiError::into_rhai_error)?;
+ .try_get_context()
+ .map_err(IntoRhaiError::into_rhai_error)?
+ .world;
let self_: ReflectReference = self_.0.clone();
let other: ScriptValue = ScriptValue::from_dynamic(other)?;
let target_type_id = self_
@@ -524,8 +535,9 @@ impl CustomType for RhaiReflectReference {
RhaiOperator::Lt.function_name(),
|self_: Self, other: Dynamic| {
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoRhaiError::into_rhai_error)?;
+ .try_get_context()
+ .map_err(IntoRhaiError::into_rhai_error)?
+ .world;
let self_: ReflectReference = self_.0.clone();
let other: ScriptValue = ScriptValue::from_dynamic(other)?;
let target_type_id = self_
@@ -541,7 +553,7 @@ impl CustomType for RhaiReflectReference {
)
.on_debug(|self_| {
let result: Result<_, InteropError> = (|| {
- let world = ThreadWorldContainer.try_get_world()?;
+ let world = ThreadWorldContainer.try_get_context()?.world;
let reflect_reference = self_.0.clone();
let func = world
@@ -571,7 +583,7 @@ impl CustomType for RhaiReflectReference {
})
.on_print(|self_| {
let result: Result<_, InteropError> = (|| {
- let world = ThreadWorldContainer.try_get_world()?;
+ let world = ThreadWorldContainer.try_get_context()?.world;
let reflect_reference = self_.0.clone();
let func = world
@@ -612,8 +624,9 @@ impl CustomType for RhaiStaticReflectReference {
.with_name(std::any::type_name::())
.with_indexer_get(|self_: &mut Self, index: Dynamic| {
let world = ThreadWorldContainer
- .try_get_world()
- .map_err(IntoRhaiError::into_rhai_error)?;
+ .try_get_context()
+ .map_err(IntoRhaiError::into_rhai_error)?
+ .world;
let type_id = self_.0;
let key: ScriptValue = ScriptValue::from_dynamic(index)?;
diff --git a/crates/languages/bevy_mod_scripting_rhai/src/lib.rs b/crates/languages/bevy_mod_scripting_rhai/src/lib.rs
index e6de10e1ff..0db90e9532 100644
--- a/crates/languages/bevy_mod_scripting_rhai/src/lib.rs
+++ b/crates/languages/bevy_mod_scripting_rhai/src/lib.rs
@@ -15,16 +15,17 @@ use bevy_log::trace;
use bevy_mod_scripting_asset::{Language, ScriptAsset};
use bevy_mod_scripting_bindings::{
AppScriptGlobalsRegistry, InteropError, Namespace, PartialReflectExt, ScriptValue,
- ThreadWorldContainer, WorldContainer,
+ ThreadWorldContainer,
};
use bevy_mod_scripting_core::{
IntoScriptPluginParams, ScriptingPlugin,
config::{GetPluginThreadConfig, ScriptingPluginConfiguration},
event::CallbackLabel,
- extractors::GetPluginFor,
make_plugin_config_static,
- script::{ContextPolicy, DisplayProxy, ScriptAttachment},
+ script::ContextPolicy,
};
+use bevy_mod_scripting_display::DisplayProxy;
+use bevy_mod_scripting_script::ScriptAttachment;
use bindings::reference::{ReservedKeyword, RhaiReflectReference, RhaiStaticReflectReference};
use parking_lot::RwLock;
pub use rhai;
@@ -44,10 +45,6 @@ pub struct RhaiScriptContext {
pub scope: Scope<'static>,
}
-impl GetPluginFor for RhaiScriptContext {
- type P = RhaiScriptingPlugin;
-}
-
make_plugin_config_static!(RhaiScriptingPlugin);
impl IntoScriptPluginParams for RhaiScriptingPlugin {
@@ -155,7 +152,7 @@ impl Default for RhaiScriptingPlugin {
},
|_, context| {
// initialize global functions
- let world = ThreadWorldContainer.try_get_world()?;
+ let world = ThreadWorldContainer.try_get_context()?.world;
let globals_registry =
world.with_resource(|r: &AppScriptGlobalsRegistry| r.clone())?;
let globals_registry = globals_registry.read();
@@ -216,7 +213,7 @@ impl Default for RhaiScriptingPlugin {
},
],
context_pre_handling_initializers: vec![|context_key, context| {
- let world = ThreadWorldContainer.try_get_world()?;
+ let world = ThreadWorldContainer.try_get_context()?.world;
if let Some(entity) = context_key.entity() {
context.scope.set_or_push(
diff --git a/crates/testing_crates/script_integration_test_harness/Cargo.toml b/crates/testing_crates/script_integration_test_harness/Cargo.toml
index 7a08a71516..2ccc2e43bc 100644
--- a/crates/testing_crates/script_integration_test_harness/Cargo.toml
+++ b/crates/testing_crates/script_integration_test_harness/Cargo.toml
@@ -26,6 +26,8 @@ bevy_mod_scripting_asset = { workspace = true }
bevy_mod_scripting_functions = { workspace = true, features = [
"core_functions",
] }
+bevy_mod_scripting_display = { workspace = true }
+bevy_mod_scripting_script = { workspace = true }
regex = { workspace = true }
pretty_assertions = { workspace = true }
bevy_mod_scripting_lua = { workspace = true, optional = true }
diff --git a/crates/testing_crates/script_integration_test_harness/src/lib.rs b/crates/testing_crates/script_integration_test_harness/src/lib.rs
index 90596f3ca7..03367008d5 100644
--- a/crates/testing_crates/script_integration_test_harness/src/lib.rs
+++ b/crates/testing_crates/script_integration_test_harness/src/lib.rs
@@ -23,17 +23,19 @@ use ::{
use bevy_asset::Assets;
use bevy_mod_scripting_asset::ScriptAsset;
use bevy_mod_scripting_bindings::{
- CoreScriptGlobalsPlugin, ReflectAccessId, ThreadWorldContainer, WorldAccessGuard,
- WorldContainer, WorldGuard,
+ CoreScriptGlobalsPlugin, ReflectAccessId, ThreadScriptContext, ThreadWorldContainer,
+ WorldAccessGuard, WorldGuard,
};
use bevy_mod_scripting_core::{
BMSScriptingInfrastructurePlugin, IntoScriptPluginParams,
commands::AttachScript,
error::ScriptError,
pipeline::PipelineRun,
- script::{DisplayProxy, ScriptAttachment, ScriptComponent, ScriptContext},
+ script::{ScriptComponent, ScriptContext},
};
+use bevy_mod_scripting_display::DisplayProxy;
use bevy_mod_scripting_functions::ScriptFunctionsPlugin;
+use bevy_mod_scripting_script::ScriptAttachment;
use criterion::{BatchSize, measurement::Measurement};
use rand::{Rng, SeedableRng};
use test_functions::{RNG, register_test_functions};
@@ -328,7 +330,10 @@ where
let _ = WorldAccessGuard::with_existing_static_guard(guard, |guard| {
// Ensure the world is available via ThreadWorldContainer
ThreadWorldContainer
- .set_world(guard.clone())
+ .set_context(ThreadScriptContext {
+ world: guard.clone(),
+ attachment: ScriptAttachment::StaticScript(Handle::Weak(script_id)),
+ })
.map_err(|e| format!("{e:#?}"))?;
// Pass the locked context to the closure for benchmarking its Lua (or generic) part
bench_fn(&mut ctxt_locked, runtime, label, criterion)
diff --git a/crates/testing_crates/script_integration_test_harness/src/parse.rs b/crates/testing_crates/script_integration_test_harness/src/parse.rs
index 0e007d466c..0a4406f323 100644
--- a/crates/testing_crates/script_integration_test_harness/src/parse.rs
+++ b/crates/testing_crates/script_integration_test_harness/src/parse.rs
@@ -9,8 +9,9 @@ use bevy_mod_scripting_core::{
CallbackLabel, OnScriptLoaded, OnScriptReloaded, OnScriptUnloaded, Recipients,
ScriptCallbackEvent,
},
- script::{ContextPolicy, ScriptAttachment},
+ script::ContextPolicy,
};
+use bevy_mod_scripting_script::ScriptAttachment;
use crate::scenario::{SCENARIO_SELF_LANGUAGE_NAME, ScenarioContext, ScenarioStep};
diff --git a/crates/testing_crates/script_integration_test_harness/src/scenario.rs b/crates/testing_crates/script_integration_test_harness/src/scenario.rs
index 79976c2379..8700d6bcac 100644
--- a/crates/testing_crates/script_integration_test_harness/src/scenario.rs
+++ b/crates/testing_crates/script_integration_test_harness/src/scenario.rs
@@ -30,8 +30,9 @@ use bevy_mod_scripting_core::{
ScriptCallbackResponseEvent, ScriptDetachedEvent,
},
handler::event_handler,
- script::{ContextPolicy, ScriptAttachment, ScriptComponent, ScriptContext},
+ script::{ContextPolicy, ScriptComponent, ScriptContext},
};
+use bevy_mod_scripting_script::ScriptAttachment;
use test_utils::test_data::setup_integration_test;
use crate::{install_test_plugin, parse::*};
diff --git a/crates/testing_crates/test_utils/src/test_plugin.rs b/crates/testing_crates/test_utils/src/test_plugin.rs
index d7308a303c..f0c36ea096 100644
--- a/crates/testing_crates/test_utils/src/test_plugin.rs
+++ b/crates/testing_crates/test_utils/src/test_plugin.rs
@@ -20,10 +20,6 @@ macro_rules! make_test_plugin {
$ident::make_plugin_config_static!(TestPlugin);
- impl $ident::extractors::GetPluginFor for TestContext {
- type P = TestPlugin;
- }
-
impl $ident::IntoScriptPluginParams for TestPlugin {
type C = TestContext;
type R = TestRuntime;
diff --git a/examples/game_of_life.rs b/examples/game_of_life.rs
index 7589224ccd..14d82ef684 100644
--- a/examples/game_of_life.rs
+++ b/examples/game_of_life.rs
@@ -17,10 +17,6 @@ use bevy::{
use bevy_console::{AddConsoleCommand, ConsoleCommand, ConsoleOpen, ConsolePlugin, make_layer};
use bevy_mod_scripting::prelude::*;
use bevy_mod_scripting_bindings::AllocatorDiagnosticPlugin;
-use bevy_mod_scripting_core::{
- commands::{AttachScript, DetachScript},
- script::ScriptAttachment,
-};
use clap::Parser;
// CONSOLE SETUP
diff --git a/src/lib.rs b/src/lib.rs
index dd724a1282..51abdb5713 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -16,6 +16,10 @@ pub mod asset {
pub use bevy_mod_scripting_asset::*;
}
+pub mod script {
+ pub use bevy_mod_scripting_script::*;
+}
+
pub mod prelude;
#[cfg(feature = "lua")]
diff --git a/src/prelude.rs b/src/prelude.rs
index 697888ed01..c3c0e6d7b6 100644
--- a/src/prelude.rs
+++ b/src/prelude.rs
@@ -11,8 +11,12 @@ pub use bevy_mod_scripting_bindings::{
script_value::ScriptValue,
};
+pub use bevy_mod_scripting_script::*;
+
pub use bevy_mod_scripting_asset::*;
+pub use bevy_mod_scripting_core::commands::*;
+
#[cfg(feature = "lua")]
pub use bevy_mod_scripting_lua::LuaScriptingPlugin;
#[cfg(feature = "rhai")]