Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions crates/bevy_mod_scripting_core/src/bindings/script_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use crate::{
event::CallbackLabel,
extractors::get_all_access_ids,
handler::ScriptingHandler,
runtime::RuntimeContainer,
script::{ScriptAttachment, ScriptContext},
};
use ::{
Expand Down Expand Up @@ -201,7 +200,6 @@ impl ScriptSystemBuilder {

struct DynamicHandlerContext<'w, P: IntoScriptPluginParams> {
script_context: &'w ScriptContext<P>,
runtime_container: &'w RuntimeContainer<P>,
}

#[profiling::all_functions]
Expand All @@ -213,15 +211,10 @@ impl<'w, P: IntoScriptPluginParams> DynamicHandlerContext<'w, P> {
pub fn init_param(world: &mut World, system: &mut FilteredAccessSet<ComponentId>) {
let mut access = FilteredAccess::<ComponentId>::matches_nothing();

let runtime_container_res_id = world
.resource_id::<RuntimeContainer<P>>()
.expect("RuntimeContainer resource not found");

let script_context_res_id = world
.resource_id::<ScriptContext<P>>()
.expect("Scripts resource not found");

access.add_resource_read(runtime_container_res_id);
access.add_resource_read(script_context_res_id);

system.add(access);
Expand All @@ -235,9 +228,6 @@ impl<'w, P: IntoScriptPluginParams> DynamicHandlerContext<'w, P> {
unsafe {
Self {
script_context: system.get_resource().expect("Scripts resource not found"),
runtime_container: system
.get_resource()
.expect("RuntimeContainer resource not found"),
}
}
}
Expand All @@ -257,7 +247,7 @@ impl<'w, P: IntoScriptPluginParams> DynamicHandlerContext<'w, P> {
};

// call the script
let runtime = &self.runtime_container.runtime;
let runtime = P::readonly_configuration(guard.id()).runtime;

let mut context = context.lock();

Expand Down
29 changes: 5 additions & 24 deletions crates/bevy_mod_scripting_core/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,32 +149,19 @@ impl<P: IntoScriptPluginParams> CreateOrUpdateScript<P> {
content: &[u8],
context: &mut P::C,
guard: WorldGuard,
handler_ctxt: &HandlerContext<P>,
) -> Result<(), ScriptError> {
debug!("{}: reloading context {}", P::LANGUAGE, attachment);
// reload context
P::reload(
attachment,
content,
context,
guard.clone(),
&handler_ctxt.runtime_container.runtime,
)
P::reload(attachment, content, context, guard.clone())
}

fn load_context(
attachment: &ScriptAttachment,
content: &[u8],
guard: WorldGuard,
handler_ctxt: &HandlerContext<P>,
) -> Result<P::C, ScriptError> {
debug!("{}: loading context {}", P::LANGUAGE, attachment);
let context = P::load(
attachment,
content,
guard.clone(),
&handler_ctxt.runtime_container.runtime,
)?;
let context = P::load(attachment, content, guard.clone())?;
Ok(context)
}

Expand Down Expand Up @@ -272,16 +259,10 @@ impl<P: IntoScriptPluginParams> CreateOrUpdateScript<P> {
Some(context) => {
let mut context = context.lock();

Self::reload_context(
&attachment,
content,
&mut context,
guard.clone(),
handler_ctxt,
)
.map(|_| None)
Self::reload_context(&attachment, content, &mut context, guard.clone())
.map(|_| None)
}
None => Self::load_context(&attachment, content, guard.clone(), handler_ctxt).map(Some),
None => Self::load_context(&attachment, content, guard.clone()).map(Some),
};

match result_context_to_insert {
Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_mod_scripting_core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ use crate::{
/// Configs contained here should be
///
/// *global meaning stored in thread-locals, i.e. not annoyingly global, but pretty global.
#[derive(Debug, Default)]
#[derive(Debug)]
pub struct ScriptingPluginConfiguration<P: IntoScriptPluginParams + ?Sized> {
/// callbacks executed before a handler callback is executed every time
pub pre_handling_callbacks: &'static [ContextPreHandlingInitializer<P>],
/// callbacks executed once after creating a context but before executing it for the first time
pub context_initialization_callbacks: &'static [ContextInitializer<P>],
/// Whether to emit responses from the core callbacks like `on_script_loaded`.
pub emit_responses: bool,
/// The configured runtime for the plugin
pub runtime: &'static P::R,
}

impl<P: IntoScriptPluginParams + ?Sized> Clone for ScriptingPluginConfiguration<P> {
Expand Down
8 changes: 2 additions & 6 deletions crates/bevy_mod_scripting_core/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ pub trait ScriptingLoader<P: IntoScriptPluginParams> {
attachment: &ScriptAttachment,
content: &[u8],
world: WorldGuard,
runtime: &P::R,
) -> Result<P::C, ScriptError>;

/// Reloads a script context using the provided reloader function
Expand All @@ -59,7 +58,6 @@ pub trait ScriptingLoader<P: IntoScriptPluginParams> {
content: &[u8],
previous_context: &mut P::C,
world: WorldGuard,
runtime: &P::R,
) -> Result<(), ScriptError>;
}

Expand All @@ -68,7 +66,6 @@ impl<P: IntoScriptPluginParams> ScriptingLoader<P> for P {
attachment: &ScriptAttachment,
content: &[u8],
world: WorldGuard,
runtime: &P::R,
) -> Result<P::C, ScriptError> {
WorldGuard::with_existing_static_guard(world.clone(), |world| {
let world_id = world.id();
Expand All @@ -78,7 +75,7 @@ impl<P: IntoScriptPluginParams> ScriptingLoader<P> for P {
content,
P::readonly_configuration(world_id).context_initialization_callbacks,
P::readonly_configuration(world_id).pre_handling_callbacks,
runtime,
P::readonly_configuration(world_id).runtime,
)
})
}
Expand All @@ -88,7 +85,6 @@ impl<P: IntoScriptPluginParams> ScriptingLoader<P> for P {
content: &[u8],
previous_context: &mut P::C,
world: WorldGuard,
runtime: &P::R,
) -> Result<(), ScriptError> {
WorldGuard::with_existing_static_guard(world, |world| {
let world_id = world.id();
Expand All @@ -99,7 +95,7 @@ impl<P: IntoScriptPluginParams> ScriptingLoader<P> for P {
previous_context,
P::readonly_configuration(world_id).context_initialization_callbacks,
P::readonly_configuration(world_id).pre_handling_callbacks,
runtime,
P::readonly_configuration(world_id).runtime,
)
})
}
Expand Down
20 changes: 1 addition & 19 deletions crates/bevy_mod_scripting_core/src/extractors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use crate::{
error::{InteropError, ScriptError},
event::{CallbackLabel, IntoCallbackLabel},
handler::ScriptingHandler,
runtime::RuntimeContainer,
script::{ScriptAttachment, ScriptContext, StaticScripts},
};

Expand All @@ -48,8 +47,6 @@ pub fn with_handler_system_state<

/// Context for systems which handle events for scripts
pub struct HandlerContext<P: IntoScriptPluginParams> {
/// The runtime container
pub(crate) runtime_container: RuntimeContainer<P>,
/// List of static scripts
pub(crate) static_scripts: StaticScripts,
/// Script context
Expand All @@ -61,7 +58,6 @@ impl<P: IntoScriptPluginParams> HandlerContext<P> {
/// Every call to this function must be paired with a call to [`Self::release`].
pub fn yoink(world: &mut World) -> Self {
Self {
runtime_container: world.remove_resource().unwrap_or_default(),
static_scripts: world.remove_resource().unwrap_or_default(),
script_context: world.remove_resource().unwrap_or_default(),
}
Expand All @@ -71,24 +67,10 @@ impl<P: IntoScriptPluginParams> HandlerContext<P> {
/// Only call this if you have previously yoinked the handler context from the world.
pub fn release(self, world: &mut World) {
// insert the handler context back into the world
world.insert_resource(self.runtime_container);
world.insert_resource(self.static_scripts);
world.insert_resource(self.script_context);
}

/// Splits the handler context into its individual components.
///
/// Useful if you are needing multiple resources from the handler context.
/// Otherwise the borrow checker will prevent you from borrowing the handler context mutably multiple times.
pub fn destructure(&mut self) -> (&mut RuntimeContainer<P>, &mut StaticScripts) {
(&mut self.runtime_container, &mut self.static_scripts)
}

/// Get the runtime container
pub fn runtime_container(&mut self) -> &mut RuntimeContainer<P> {
&mut self.runtime_container
}

/// Get the static scripts
pub fn static_scripts(&mut self) -> &mut StaticScripts {
&mut self.static_scripts
Expand Down Expand Up @@ -122,7 +104,7 @@ impl<P: IntoScriptPluginParams> HandlerContext<P> {
};

// call the script
let runtime = &self.runtime_container.runtime;
let runtime = P::readonly_configuration(guard.id()).runtime;

let mut context = context.lock();

Expand Down
67 changes: 17 additions & 50 deletions crates/bevy_mod_scripting_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ use asset::{
Language, ScriptAsset, ScriptAssetLoader, configure_asset_systems,
configure_asset_systems_for_plugin,
};
use bevy_app::{App, Plugin, PostStartup, PostUpdate};
use bevy_app::{App, Plugin, PostUpdate};
use bevy_asset::{AssetApp, Handle};
use bevy_ecs::schedule::IntoScheduleConfigs;
use bevy_ecs::{
reflect::{AppTypeRegistry, ReflectComponent},
resource::Resource,
schedule::SystemSet,
system::{Command, In},
system::Command,
};
use bevy_ecs::{schedule::IntoScheduleConfigs, system::IntoSystem};
use bevy_log::error;
use bevy_platform::collections::HashMap;
use bindings::{
Expand All @@ -30,10 +30,9 @@ use bindings::{
};
use commands::{AddStaticScript, RemoveStaticScript};
use context::{Context, ContextInitializer, ContextPreHandlingInitializer};
use error::ScriptError;
use event::{ScriptCallbackEvent, ScriptCallbackResponseEvent, ScriptEvent};
use handler::HandlerFn;
use runtime::{Runtime, RuntimeContainer, RuntimeInitializer, RuntimeSettings, initialize_runtime};
use runtime::{Runtime, RuntimeInitializer};
use script::{ContextPolicy, ScriptComponent, ScriptContext, StaticScripts};
use std::ops::{Deref, DerefMut};

Expand Down Expand Up @@ -97,8 +96,8 @@ pub trait IntoScriptPluginParams: 'static + GetPluginThreadConfig<Self> {

/// Bevy plugin enabling scripting within the bevy mod scripting framework
pub struct ScriptingPlugin<P: IntoScriptPluginParams> {
/// Settings for the runtime
pub runtime_settings: RuntimeSettings<P>,
/// Functions configuring the runtime after it is created
pub runtime_initializers: Vec<RuntimeInitializer<P>>,

/// The strategy used to assign contexts to scripts
pub context_policy: ContextPolicy,
Expand Down Expand Up @@ -137,7 +136,7 @@ where
impl<P: IntoScriptPluginParams> Default for ScriptingPlugin<P> {
fn default() -> Self {
Self {
runtime_settings: Default::default(),
runtime_initializers: Default::default(),
context_policy: ContextPolicy::default(),
language: Default::default(),
context_initializers: Default::default(),
Expand All @@ -150,16 +149,20 @@ impl<P: IntoScriptPluginParams> Default for ScriptingPlugin<P> {
#[profiling::all_functions]
impl<P: IntoScriptPluginParams> Plugin for ScriptingPlugin<P> {
fn build(&self, app: &mut App) {
app.insert_resource(self.runtime_settings.clone())
.insert_resource::<RuntimeContainer<P>>(RuntimeContainer {
runtime: P::build_runtime(),
});

// initialize thread local configs

let runtime = P::build_runtime();
for initializer in &self.runtime_initializers {
if let Err(e) = initializer(&runtime) {
error!("Error initializing runtime: {:?}. Continuing.", e);
}
}

let config = ScriptingPluginConfiguration::<P> {
pre_handling_callbacks: Vec::leak(self.context_pre_handling_initializers.clone()),
context_initialization_callbacks: Vec::leak(self.context_initializers.clone()),
emit_responses: self.emit_responses,
runtime: Box::leak(Box::new(runtime)),
};

P::set_thread_config(app.world().id(), config);
Expand Down Expand Up @@ -196,7 +199,7 @@ impl<P: IntoScriptPluginParams> ScriptingPlugin<P> {
///
/// Initializers will be run after the runtime is created, but before any contexts are loaded.
pub fn add_runtime_initializer(&mut self, initializer: RuntimeInitializer<P>) -> &mut Self {
self.runtime_settings.initializers.push(initializer);
self.runtime_initializers.push(initializer);
self
}
}
Expand Down Expand Up @@ -325,16 +328,6 @@ impl Plugin for BMSScriptingInfrastructurePlugin {

/// Systems registered per-language
fn register_script_plugin_systems<P: IntoScriptPluginParams>(app: &mut App) {
app.add_systems(
PostStartup,
(initialize_runtime::<P>.pipe(|e: In<Result<(), ScriptError>>| {
if let Err(e) = e.0 {
error!("Error initializing runtime: {:?}", e);
}
}))
.in_set(ScriptingSystemSet::RuntimeInitialization),
);

app.add_plugins(configure_asset_systems_for_plugin::<P>);
}

Expand All @@ -346,32 +339,6 @@ fn register_types(app: &mut App) {
app.register_type::<ScriptComponent>();
}

/// Trait for adding a runtime initializer to an app
pub trait AddRuntimeInitializer {
/// Adds a runtime initializer to the app
fn add_runtime_initializer<P: IntoScriptPluginParams>(
&mut self,
initializer: RuntimeInitializer<P>,
) -> &mut Self;
}

impl AddRuntimeInitializer for App {
fn add_runtime_initializer<P: IntoScriptPluginParams>(
&mut self,
initializer: RuntimeInitializer<P>,
) -> &mut Self {
if !self.world_mut().contains_resource::<RuntimeSettings<P>>() {
self.world_mut().init_resource::<RuntimeSettings<P>>();
}
self.world_mut()
.resource_mut::<RuntimeSettings<P>>()
.as_mut()
.initializers
.push(initializer);
self
}
}

/// Trait for adding static scripts to an app
pub trait ManageStaticScripts {
/// Registers a script id as a static script.
Expand Down
Loading
Loading