Added add_scripting_api function to AppBuilder (#23)

* Added `add_scripting_api` function to builder
This commit is contained in:
Dennis 2024-07-17 10:36:00 +02:00 committed by GitHub
parent f85dbcffe2
commit be8a80519d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 225 additions and 0 deletions

View file

@ -53,6 +53,10 @@ path = "examples/rhai/function_params.rs"
name = "hello_world_rhai"
path = "examples/rhai/hello_world.rs"
[[example]]
name = "multiple_plugins_rhai"
path = "examples/rhai/multiple_plugins.rs"
[[example]]
name = "non_closure_system_rhai"
path = "examples/rhai/non_closure_system.rs"
@ -93,6 +97,10 @@ path = "examples/lua/function_params.rs"
name = "hello_world_lua"
path = "examples/lua/hello_world.rs"
[[example]]
name = "multiple_plugins_lua"
path = "examples/lua/multiple_plugins.rs"
[[example]]
name = "non_closure_system_lua"
path = "examples/lua/non_closure_system.rs"

View file

@ -0,0 +1 @@
hello_from_plugin_a()

View file

@ -0,0 +1 @@
hello_from_plugin_b_with_parameters("hello", 42)

View file

@ -0,0 +1 @@
hello_from_plugin_a();

View file

@ -0,0 +1 @@
hello_from_plugin_b_with_parameters("hello", 42);

View file

@ -88,6 +88,36 @@ which you can then call in your script like this:
fun_with_string_param("Hello world!")
```
It is also possible to split the definition of your callback functions up over multiple plugins. This enables you to split up your code by subject and keep the main initialization light and clean.
This can be accomplished by using `add_scripting_api`. Be careful though, `add_scripting` has to be called before adding plugins.
```rust
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
struct MyPlugin;
impl Plugin for MyPlugin {
fn build(&self, app: &mut App) {
app.add_scripting_api::<LuaRuntime>(|runtime| {
runtime.add_function(String::from("hello_from_my_plugin"), || {
info!("Hello from MyPlugin");
});
});
}
}
// Main
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_scripting::<LuaRuntime>(|_| {
// nice and clean
})
.add_plugins(MyPlugin)
.run();
}
```
### Usage
Add the following to your `Cargo.toml`:

View file

@ -0,0 +1,67 @@
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::lua::prelude::*;
// Plugin A
struct PluginA;
impl Plugin for PluginA {
fn build(&self, app: &mut App) {
app.add_scripting_api::<LuaRuntime>(|runtime| {
runtime.add_function(String::from("hello_from_plugin_a"), || {
info!("Hello from Plugin A");
});
})
.add_systems(Startup, plugin_a_startup);
}
}
fn plugin_a_startup(mut commands: Commands, assets_server: Res<AssetServer>) {
commands.spawn(Script::<LuaScript>::new(
assets_server.load("examples/lua/multiple_plugins_plugin_a.lua"),
));
}
// Plugin B
struct PluginB;
impl Plugin for PluginB {
fn build(&self, app: &mut App) {
app.add_scripting_api::<LuaRuntime>(|runtime| {
runtime.add_function(
String::from("hello_from_plugin_b_with_parameters"),
hello_from_b,
);
})
.add_systems(Startup, plugin_b_startup);
}
}
fn plugin_b_startup(mut commands: Commands, assets_server: Res<AssetServer>) {
commands.spawn(Script::<LuaScript>::new(
assets_server.load("examples/lua/multiple_plugins_plugin_b.lua"),
));
}
fn hello_from_b(In((text, x)): In<(String, i32)>) {
info!("{} from Plugin B: {}", text, x);
}
// Main
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_scripting::<LuaRuntime>(|runtime| {
runtime.add_function(String::from("hello_bevy"), || {
info!("hello bevy, called from script");
});
})
.add_systems(Startup, main_startup)
.add_plugins(PluginA)
.add_plugins(PluginB)
.run();
}
fn main_startup(mut commands: Commands, assets_server: Res<AssetServer>) {
commands.spawn(Script::<LuaScript>::new(
assets_server.load("examples/lua/hello_world.lua"),
));
}

View file

@ -0,0 +1,68 @@
use bevy::prelude::*;
use bevy_scriptum::prelude::*;
use bevy_scriptum::runtimes::rhai::prelude::*;
use rhai::ImmutableString;
// Plugin A
struct PluginA;
impl Plugin for PluginA {
fn build(&self, app: &mut App) {
app.add_scripting_api::<RhaiRuntime>(|runtime| {
runtime.add_function(String::from("hello_from_plugin_a"), || {
info!("Hello from Plugin A");
});
})
.add_systems(Startup, plugin_a_startup);
}
}
fn plugin_a_startup(mut commands: Commands, assets_server: Res<AssetServer>) {
commands.spawn(Script::<RhaiScript>::new(
assets_server.load("examples/rhai/multiple_plugins_plugin_a.rhai"),
));
}
// Plugin B
struct PluginB;
impl Plugin for PluginB {
fn build(&self, app: &mut App) {
app.add_scripting_api::<RhaiRuntime>(|runtime| {
runtime.add_function(
String::from("hello_from_plugin_b_with_parameters"),
hello_from_b,
);
})
.add_systems(Startup, plugin_b_startup);
}
}
fn plugin_b_startup(mut commands: Commands, assets_server: Res<AssetServer>) {
commands.spawn(Script::<RhaiScript>::new(
assets_server.load("examples/rhai/multiple_plugins_plugin_b.rhai"),
));
}
fn hello_from_b(In((text, x)): In<(ImmutableString, i64)>) {
info!("{} from Plugin B: {}", text, x);
}
// Main
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_scripting::<RhaiRuntime>(|runtime| {
runtime.add_function(String::from("hello_bevy"), || {
info!("hello bevy, called from script");
});
})
.add_systems(Startup, main_startup)
.add_plugins(PluginA)
.add_plugins(PluginB)
.run();
}
fn main_startup(mut commands: Commands, assets_server: Res<AssetServer>) {
commands.spawn(Script::<RhaiScript>::new(
assets_server.load("examples/rhai/hello_world.rhai"),
));
}

View file

@ -82,7 +82,34 @@
//! ```lua
//! fun_with_string_param("Hello world!")
//! ```
//! It is also possible to split the definition of your callback functions up over multiple plugins. This enables you to split up your code by subject and keep the main initialization light and clean.
//! This can be accomplished by using `add_scripting_api`. Be careful though, `add_scripting` has to be called before adding plugins.
//! ```rust
//! use bevy::prelude::*;
//! use bevy_scriptum::prelude::*;
//! use bevy_scriptum::runtimes::lua::prelude::*;
//!
//! struct MyPlugin;
//! impl Plugin for MyPlugin {
//! fn build(&self, app: &mut App) {
//! app.add_scripting_api::<LuaRuntime>(|runtime| {
//! runtime.add_function(String::from("hello_from_my_plugin"), || {
//! info!("Hello from MyPlugin");
//! });
//! });
//! }
//! }
//!
//! App::new()
//! .add_plugins(DefaultPlugins)
//! .add_scripting::<LuaRuntime>(|_| {
//! // nice and clean
//! })
//! .add_plugins(MyPlugin)
//! .run();
//! ```
//!
//!
//! ## Usage
//!
//! Add the following to your `Cargo.toml`:
@ -331,6 +358,12 @@ pub trait BuildScriptingRuntime {
/// Returns a "runtime" type than can be used to setup scripting runtime(
/// add scripting functions etc.).
fn add_scripting<R: Runtime>(&mut self, f: impl Fn(ScriptingRuntimeBuilder<R>)) -> &mut Self;
/// Returns a "runtime" type that can be used to add additional scripting functions from plugins etc.
fn add_scripting_api<R: Runtime>(
&mut self,
f: impl Fn(ScriptingRuntimeBuilder<R>),
) -> &mut Self;
}
pub struct ScriptingRuntimeBuilder<'a, R: Runtime> {
@ -402,6 +435,21 @@ impl BuildScriptingRuntime for App {
self
}
/// Adds a way to add additional accesspoints to the scripting runtime. For example from plugins to add
/// for example additional lua functions to the runtime.
///
/// Be careful with calling this though, make sure that the `add_scripting` call is already called before calling this function.
fn add_scripting_api<R: Runtime>(
&mut self,
f: impl Fn(ScriptingRuntimeBuilder<R>),
) -> &mut Self {
let runtime = ScriptingRuntimeBuilder::<R>::new(self.world_mut());
f(runtime);
self
}
}
/// A resource that stores all the callbacks that were registered using [AddScriptFunctionAppExt::add_function].