Skip to content

feat: Add on_script_reloaded callback. #421

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
40 changes: 37 additions & 3 deletions crates/bevy_mod_scripting_core/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
context::ContextBuilder,
error::{InteropError, ScriptError},
event::{
CallbackLabel, IntoCallbackLabel, OnScriptLoaded, OnScriptUnloaded,
CallbackLabel, IntoCallbackLabel, OnScriptLoaded, OnScriptReloaded, OnScriptUnloaded,
ScriptCallbackResponseEvent,
},
extractors::{with_handler_system_state, HandlerContext},
Expand Down Expand Up @@ -150,6 +150,7 @@ impl<P: IntoScriptPluginParams> CreateOrUpdateScript<P> {
#[profiling::all_functions]
impl<P: IntoScriptPluginParams> Command for CreateOrUpdateScript<P> {
fn apply(self, world: &mut bevy::prelude::World) {
let mut reload_state = None;
let success = with_handler_system_state(
world,
|guard, handler_ctxt: &mut HandlerContext<P>| {
Expand Down Expand Up @@ -194,6 +195,28 @@ impl<P: IntoScriptPluginParams> Command for CreateOrUpdateScript<P> {
// it can potentially be loaded but without a successful script reload but that
// leaves us in an okay state
handler_ctxt.scripts.scripts.insert(self.id.clone(), script);
} else {
match handler_ctxt.call_dynamic_label(
&OnScriptReloaded::into_callback_label(),
&self.id,
Entity::from_raw(0),
vec![ScriptValue::Bool(true)],
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ for languages like rhai, where the arity of the callback is used to actually identify the function in the script, we would probably want to pass in the same number of arguments both times, but instead pass in a None for the missing argument

guard.clone(),
) {
Ok(state) => {
reload_state = Some(state);
}
Err(err) => {
handle_script_errors(
guard.clone(),
vec![err
.with_script(self.id.clone())
.with_context(P::LANGUAGE)
.with_context("saving reload state")]
.into_iter(),
);
}
}
}
bevy::log::debug!("{}: reloading script with id: {}", P::LANGUAGE, self.id);
self.reload_context(guard.clone(), handler_ctxt)
Expand Down Expand Up @@ -235,13 +258,24 @@ impl<P: IntoScriptPluginParams> Command for CreateOrUpdateScript<P> {
// immediately run command for callback, but only if loading went fine
if success {
RunScriptCallback::<P>::new(
self.id,
self.id.clone(),
Entity::from_raw(0),
OnScriptLoaded::into_callback_label(),
vec![],
false,
)
.apply(world)
.apply(world);

if let Some(state) = reload_state {
RunScriptCallback::<P>::new(
self.id,
Entity::from_raw(0),
OnScriptReloaded::into_callback_label(),
vec![ScriptValue::Bool(false), state],
false,
)
.apply(world);
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_mod_scripting_core/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ macro_rules! callback_labels {
callback_labels!(
OnScriptLoaded => "on_script_loaded",
OnScriptUnloaded => "on_script_unloaded",
OnScriptReloaded => "on_script_reloaded",
);

/// A trait for types that can be converted into a callback label
Expand Down
24 changes: 23 additions & 1 deletion docs/src/ScriptingReference/core-callbacks.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

On top of callbacks which are registered by your application, BMS provides a set of core callbacks which are always available.

The two core callbacks are:
The three core callbacks are:
- `on_script_loaded`
- `on_script_unloaded`
- `on_script_reloaded`

## `on_script_loaded`

Expand All @@ -30,3 +31,24 @@ function on_script_unloaded()
print("Goodbye world")
end
```

## `on_script_reloaded`

This will be called twice: right before and after a script is reloaded.

The first parameter `save` informs you whether it is time to save a value or restore it.

Before the reload, it is called with one argument: `true`. After the script is reloaded, it is called with two parameters: the first is `false` and the second is value returned from before.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as of now this seems to be misleading for non-shared contexts, in which case only the second half of the callback would happen


```lua
mode = 1
function on_script_reloaded(save, value)
if save then
print("Before I go, take this.")
return mode
else
print("I'm back. Where was I?")
mode = value
end
end
```
Loading