From 64247042945c4104c9abdd1647bc6300c4a8f25d Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Thu, 9 Nov 2023 11:00:56 +0100 Subject: [PATCH 01/27] dwadwa --- bevy_mod_scripting_core/src/hosts.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/bevy_mod_scripting_core/src/hosts.rs b/bevy_mod_scripting_core/src/hosts.rs index 773de01f..264778b0 100644 --- a/bevy_mod_scripting_core/src/hosts.rs +++ b/bevy_mod_scripting_core/src/hosts.rs @@ -360,22 +360,23 @@ impl Script { event_writer: &mut EventWriter, ) { debug!("reloading script {}", script.id); - // retrieve owning entity - let entity = contexts.script_owner(script.id()).unwrap(); // remove old context contexts.remove_context(script.id()); - // insert new re-loaded context - Self::insert_new_script_context::( - host, - script, - entity, - script_assets, - providers, - contexts, - event_writer, - ); + // retrieve owning entity + if let Some(entity) = contexts.script_owner(script.id()) { + // insert new re-loaded context + Self::insert_new_script_context::( + host, + script, + entity, + script_assets, + providers, + contexts, + event_writer, + ); + } } /// checks if a script has loaded, and if so loads (`ScriptHost::load_script`), From c73fef5e0ee6ccc9068c9d1d98dffa6d941801b0 Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Thu, 9 Nov 2023 11:55:08 +0100 Subject: [PATCH 02/27] debug prints --- bevy_mod_scripting_core/src/hosts.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bevy_mod_scripting_core/src/hosts.rs b/bevy_mod_scripting_core/src/hosts.rs index 264778b0..c549ca82 100644 --- a/bevy_mod_scripting_core/src/hosts.rs +++ b/bevy_mod_scripting_core/src/hosts.rs @@ -366,6 +366,7 @@ impl Script { // retrieve owning entity if let Some(entity) = contexts.script_owner(script.id()) { + println!("Script {} has owner", script.id); // insert new re-loaded context Self::insert_new_script_context::( host, @@ -376,6 +377,8 @@ impl Script { contexts, event_writer, ); + } else { + println!("Script {} has no owner", script.id); } } From 06ff26444cd2b96320de85af52869a63667935ea Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Thu, 9 Nov 2023 11:58:05 +0100 Subject: [PATCH 03/27] we ignore this ever happened --- bevy_mod_scripting_core/src/hosts.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/bevy_mod_scripting_core/src/hosts.rs b/bevy_mod_scripting_core/src/hosts.rs index c549ca82..81fef8bc 100644 --- a/bevy_mod_scripting_core/src/hosts.rs +++ b/bevy_mod_scripting_core/src/hosts.rs @@ -361,12 +361,8 @@ impl Script { ) { debug!("reloading script {}", script.id); - // remove old context - contexts.remove_context(script.id()); - // retrieve owning entity if let Some(entity) = contexts.script_owner(script.id()) { - println!("Script {} has owner", script.id); // insert new re-loaded context Self::insert_new_script_context::( host, @@ -377,9 +373,10 @@ impl Script { contexts, event_writer, ); - } else { - println!("Script {} has no owner", script.id); } + + // remove old context + contexts.remove_context(script.id()); } /// checks if a script has loaded, and if so loads (`ScriptHost::load_script`), From 8879577951ff59ae23a41c1795ad3b3d2e9c2655 Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Thu, 9 Nov 2023 12:01:16 +0100 Subject: [PATCH 04/27] mmmmmmmmmmm i'm still a bit dumb lol --- bevy_mod_scripting_core/src/hosts.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bevy_mod_scripting_core/src/hosts.rs b/bevy_mod_scripting_core/src/hosts.rs index 81fef8bc..9e8ff585 100644 --- a/bevy_mod_scripting_core/src/hosts.rs +++ b/bevy_mod_scripting_core/src/hosts.rs @@ -363,6 +363,8 @@ impl Script { // retrieve owning entity if let Some(entity) = contexts.script_owner(script.id()) { + // remove old context + contexts.remove_context(script.id()); // insert new re-loaded context Self::insert_new_script_context::( host, @@ -373,10 +375,10 @@ impl Script { contexts, event_writer, ); + } else { + // remove old context + contexts.remove_context(script.id()); } - - // remove old context - contexts.remove_context(script.id()); } /// checks if a script has loaded, and if so loads (`ScriptHost::load_script`), From 0c90755142cd32ed588671c2f9f7e3e2f198c2e6 Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Thu, 9 Nov 2023 12:27:44 +0100 Subject: [PATCH 05/27] does this fix the crash? --- bevy_script_api/src/common/std.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/bevy_script_api/src/common/std.rs b/bevy_script_api/src/common/std.rs index b22ea73c..77355ecc 100644 --- a/bevy_script_api/src/common/std.rs +++ b/bevy_script_api/src/common/std.rs @@ -131,10 +131,7 @@ impl IntoIterator for ScriptVec { // TODO?: end used to be an Option, and this check moved into the next method but // I am not sure if this will ever realistically fail, so if you do get this exception happening // hit me with an issue - end: self - .len() - .map(|v| v - 1) - .expect("Could not access length when creating iterator"), + end: self.len().map(|v| v - 1).unwrap_or(0), base: self, } } From dd9005358fefae948272a77617d18b6815033352 Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Thu, 9 Nov 2023 12:41:47 +0100 Subject: [PATCH 06/27] that maybe fixes it --- bevy_script_api/src/common/std.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bevy_script_api/src/common/std.rs b/bevy_script_api/src/common/std.rs index 77355ecc..43297ad0 100644 --- a/bevy_script_api/src/common/std.rs +++ b/bevy_script_api/src/common/std.rs @@ -131,7 +131,11 @@ impl IntoIterator for ScriptVec { // TODO?: end used to be an Option, and this check moved into the next method but // I am not sure if this will ever realistically fail, so if you do get this exception happening // hit me with an issue - end: self.len().map(|v| v - 1).unwrap_or(0), + // if len > 0, subtract 1, otherwise set to 0 + end: self + .len() + .and_then(|len| Ok(if len > 0 { len - 1 } else { 0 })) + .expect("Failed to get length of ScriptVec"), base: self, } } From c19f6b1d757d8563935eb886e3b65765c6a02288 Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Fri, 10 Nov 2023 17:14:24 +0100 Subject: [PATCH 07/27] unncessecary get_children + fixed get_parent --- bevy_script_api/src/rhai/bevy/mod.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/bevy_script_api/src/rhai/bevy/mod.rs b/bevy_script_api/src/rhai/bevy/mod.rs index b75209e7..a696a84b 100644 --- a/bevy_script_api/src/rhai/bevy/mod.rs +++ b/bevy_script_api/src/rhai/bevy/mod.rs @@ -40,13 +40,6 @@ impl CustomType for ScriptWorld { .map(Dynamic::from) .unwrap_or_default() }) - .with_fn("get_children", |self_: ScriptWorld, parent: Entity| { - self_ - .get_children(parent) - .into_iter() - .map(Dynamic::from) - .collect::>() - }) .with_fn( "add_default_component", |self_: ScriptWorld, entity: Entity, type_registration: ScriptTypeRegistration| { @@ -138,15 +131,20 @@ impl CustomType for ScriptWorld { }) }, ) - .with_fn("get_children", |self_: &ScriptWorld, parent: Entity| { + .with_fn("get_parent", |self_: ScriptWorld, entity: Entity| { + if let Some(parent) = self_.get_parent(entity) { + Dynamic::from(parent) + } else { + Dynamic::from(-1) + } + + }) + .with_fn("get_children", |self_: ScriptWorld, parent: Entity| { self_ .get_children(parent) .into_iter() .map(Dynamic::from) - .collect::>() - }) - .with_fn("get_parent", |self_: &ScriptWorld, entity: Entity| { - self_.get_parent(entity) + .collect::>() }) .with_fn( "push_child", From e1dcf0e4b9fadf9f416359ac7cf90b184d9d2c48 Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Fri, 10 Nov 2023 20:49:02 +0100 Subject: [PATCH 08/27] rustfmt --- bevy_script_api/src/rhai/bevy/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/bevy_script_api/src/rhai/bevy/mod.rs b/bevy_script_api/src/rhai/bevy/mod.rs index a696a84b..ee41bd9f 100644 --- a/bevy_script_api/src/rhai/bevy/mod.rs +++ b/bevy_script_api/src/rhai/bevy/mod.rs @@ -137,7 +137,6 @@ impl CustomType for ScriptWorld { } else { Dynamic::from(-1) } - }) .with_fn("get_children", |self_: ScriptWorld, parent: Entity| { self_ From 6a04b27e678393f63a4141cef8e6cf3752f101ca Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Fri, 10 Nov 2023 20:50:37 +0100 Subject: [PATCH 09/27] clippy --- bevy_script_api/src/common/std.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bevy_script_api/src/common/std.rs b/bevy_script_api/src/common/std.rs index 43297ad0..b6f6f01f 100644 --- a/bevy_script_api/src/common/std.rs +++ b/bevy_script_api/src/common/std.rs @@ -134,7 +134,7 @@ impl IntoIterator for ScriptVec { // if len > 0, subtract 1, otherwise set to 0 end: self .len() - .and_then(|len| Ok(if len > 0 { len - 1 } else { 0 })) + .map(|len| if len > 0 { len - 1 } else { 0 }) .expect("Failed to get length of ScriptVec"), base: self, } From 783dbf6785d754d7382f1f1a1634f24a1e398f08 Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Wed, 15 Nov 2023 13:10:53 +0100 Subject: [PATCH 10/27] moved wrappers example into lua and renamed it --- Cargo.toml | 2 +- examples/{wrappers.rs => lua/wrappers_lua.rs} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename examples/{wrappers.rs => lua/wrappers_lua.rs} (100%) diff --git a/Cargo.toml b/Cargo.toml index 948a4ef5..0e330835 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -152,5 +152,5 @@ required-features = ["rhai", "rhai_script_api"] [[example]] name = "wrappers" -path = "examples/wrappers.rs" +path = "examples/lua/wrappers_lua.rs" required-features = ["lua54", "lua_script_api"] diff --git a/examples/wrappers.rs b/examples/lua/wrappers_lua.rs similarity index 100% rename from examples/wrappers.rs rename to examples/lua/wrappers_lua.rs From 5ade1a874ef22443189dbd771d8e8619a2ebf18c Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Wed, 15 Nov 2023 13:11:10 +0100 Subject: [PATCH 11/27] WIP new example for rhai wrapper --- Cargo.toml | 5 +++++ examples/rhai/wrappers_rhai.rs | 39 ++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 examples/rhai/wrappers_rhai.rs diff --git a/Cargo.toml b/Cargo.toml index 0e330835..187bfc4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -154,3 +154,8 @@ required-features = ["rhai", "rhai_script_api"] name = "wrappers" path = "examples/lua/wrappers_lua.rs" required-features = ["lua54", "lua_script_api"] + +[[example]] +name = "wrappers_rhai" +path = "examples/rhai/wrappers_rhai.rs" +required-features = ["rhai", "rhai_script_api"] diff --git a/examples/rhai/wrappers_rhai.rs b/examples/rhai/wrappers_rhai.rs new file mode 100644 index 00000000..4cc62467 --- /dev/null +++ b/examples/rhai/wrappers_rhai.rs @@ -0,0 +1,39 @@ +use bevy::{app::AppExit, prelude::*}; +use bevy_mod_scripting_core::ScriptingPlugin; +use bevy_script_api::rhai::{ReflectRhaiProxyable, std::RhaiCopy}; + +// Step 1. Rust representation +// construct all our types and functionality +// Reflect is neccessary to allow access from scripts +// Clone allows receiving our wrapper as a function parameter (derives FromLua via UserData through mlua's traits) +// We can still use references to NonClone wrappers via AnyUserData in lua methods. +// Even though we are implementing Clone we are still able to reference the original data in script thanks to the script wrapper we are about to implement +// Debug is nice to have, we can forward that implementation to Lua's ToString via our macro +#[derive(Resource, Reflect, Default, Clone, Debug)] +#[reflect(Resource, RhaiProxyable)] +pub struct MyThing { + usize: usize, + string: String, + array: Vec, +} + +impl RhaiCopy for MyThing {} + +impl MyThing { + pub fn do_something_cool(&self) -> String { + self.string.clone() + } +} + +fn main() -> std::io::Result<()> { + let mut app = App::new(); + + app.add_plugins(DefaultPlugins) + .add_plugins(ScriptingPlugin) + .register_type::() + .init_resource::(); + + app.run(); + + Ok(()) +} From eda744c727460e0e17cb0b7a34014552e3ba0d5e Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Wed, 15 Nov 2023 13:15:32 +0100 Subject: [PATCH 12/27] WIP implementing fix mentioned in review https://github.com/makspll/bevy_mod_scripting/pull/87#discussion_r1393773417 --- bevy_script_api/src/common/std.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bevy_script_api/src/common/std.rs b/bevy_script_api/src/common/std.rs index b6f6f01f..fe6d8bb0 100644 --- a/bevy_script_api/src/common/std.rs +++ b/bevy_script_api/src/common/std.rs @@ -102,7 +102,7 @@ impl From> for ScriptRef { pub struct ScriptVecIterator { current: usize, - end: usize, + len: usize, base: ScriptVec, } @@ -110,7 +110,7 @@ impl Iterator for ScriptVecIterator { type Item = ScriptRef; fn next(&mut self) -> Option { - let nxt = (self.current <= self.end).then(|| self.base.index(self.current)); + let nxt = (self.current < self.len).then(|| self.base.index(self.current)); self.current += 1; nxt } @@ -132,7 +132,7 @@ impl IntoIterator for ScriptVec { // I am not sure if this will ever realistically fail, so if you do get this exception happening // hit me with an issue // if len > 0, subtract 1, otherwise set to 0 - end: self + len: self .len() .map(|len| if len > 0 { len - 1 } else { 0 }) .expect("Failed to get length of ScriptVec"), From 5a56ddbbc166e4d2ad94c89ff15654b0ae884a74 Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Wed, 15 Nov 2023 13:44:12 +0100 Subject: [PATCH 13/27] basic one shot works --- examples/rhai/wrappers_rhai.rs | 78 +++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 6 deletions(-) diff --git a/examples/rhai/wrappers_rhai.rs b/examples/rhai/wrappers_rhai.rs index 4cc62467..6adc04f4 100644 --- a/examples/rhai/wrappers_rhai.rs +++ b/examples/rhai/wrappers_rhai.rs @@ -1,6 +1,16 @@ -use bevy::{app::AppExit, prelude::*}; -use bevy_mod_scripting_core::ScriptingPlugin; -use bevy_script_api::rhai::{ReflectRhaiProxyable, std::RhaiCopy}; +use bevy::prelude::*; +use bevy_mod_scripting_core::{ + hosts::{APIProvider, Recipients, ScriptHost}, + AddScriptApiProvider, AddScriptHost, AddScriptHostHandler, ScriptingPlugin, +}; +use bevy_mod_scripting_rhai::{ + docs::RhaiDocFragment, rhai::Engine, RhaiContext, RhaiEvent, RhaiScriptHost, +}; +use bevy_script_api::rhai::{ + bevy::RhaiBevyAPIProvider, + std::{RegisterVecType, RhaiCopy}, + ReflectRhaiProxyable, RegisterForeignRhaiType, +}; // Step 1. Rust representation // construct all our types and functionality @@ -25,15 +35,71 @@ impl MyThing { } } +fn init(mut commands: Commands) { + commands.insert_resource(MyThing { + array: vec![1, 2, 3], + string: "Hello World!".to_owned(), + usize: 42, + }); +} + +fn run_one_shot(world: &mut World) { + world.resource_scope(|world, mut host: Mut>| { + host.run_one_shot( + r#" + fn once() { + print("hello hello"); + } + "# + .as_bytes(), + "script.rhai", + Entity::from_raw(0), + world, + RhaiEvent { + hook_name: "once".to_owned(), + args: (), + recipients: Recipients::All, + }, + ) + .expect("Something went wrong in the script!"); + }); +} + fn main() -> std::io::Result<()> { let mut app = App::new(); - app.add_plugins(DefaultPlugins) - .add_plugins(ScriptingPlugin) + app.add_plugins((DefaultPlugins, ScriptingPlugin)) + .add_script_host::>(PostUpdate) + .add_api_provider::>(Box::new(RhaiBevyAPIProvider)) + .add_api_provider::>(Box::new(WrapperApiProvider)) + .add_script_handler::, 0, 2>(PostUpdate) .register_type::() - .init_resource::(); + .add_systems(Startup, init) + .add_systems(Update, run_one_shot.run_if(run_once())); app.run(); Ok(()) } + +struct WrapperApiProvider; + +impl APIProvider for WrapperApiProvider { + type APITarget = Engine; + + type ScriptContext = RhaiContext; + + type DocTarget = RhaiDocFragment; + + fn register_with_app(&self, app: &mut App) { + app.register_foreign_rhai_type::>(); + } + + fn attach_api( + &mut self, + api: &mut Self::APITarget, + ) -> Result<(), bevy_mod_scripting_core::prelude::ScriptError> { + api.register_vec_functions::(); + Ok(()) + } +} From 59ac5629c7559e82619949ee44ef1cace006541f Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Wed, 15 Nov 2023 14:11:52 +0100 Subject: [PATCH 14/27] accessing variables work --- examples/rhai/wrappers_rhai.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/examples/rhai/wrappers_rhai.rs b/examples/rhai/wrappers_rhai.rs index 6adc04f4..691a1884 100644 --- a/examples/rhai/wrappers_rhai.rs +++ b/examples/rhai/wrappers_rhai.rs @@ -20,15 +20,13 @@ use bevy_script_api::rhai::{ // Even though we are implementing Clone we are still able to reference the original data in script thanks to the script wrapper we are about to implement // Debug is nice to have, we can forward that implementation to Lua's ToString via our macro #[derive(Resource, Reflect, Default, Clone, Debug)] -#[reflect(Resource, RhaiProxyable)] +#[reflect(Resource)] pub struct MyThing { usize: usize, string: String, array: Vec, } -impl RhaiCopy for MyThing {} - impl MyThing { pub fn do_something_cool(&self) -> String { self.string.clone() @@ -48,7 +46,14 @@ fn run_one_shot(world: &mut World) { host.run_one_shot( r#" fn once() { - print("hello hello"); + let my_thing_type = world.get_type_by_name("wrappers_rhai::MyThing"); + print(`MyThing type: ${my_thing_type}`); + let my_thing = world.get_resource(my_thing_type); + print(`MyThing: ${my_thing}`); + print(`MyThing.string: ${my_thing.string}`); + print(`MyThing.usize: ${my_thing.usize}`); + print(`MyThing.array: ${my_thing.array}`); + print(`MyThing.array[0]: ${my_thing.array[0]}`); } "# .as_bytes(), From c282ada927a822eb88750f5e669df53421ebe543 Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Wed, 15 Nov 2023 14:12:06 +0100 Subject: [PATCH 15/27] accessing variables not work --- examples/rhai/wrappers_rhai.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/rhai/wrappers_rhai.rs b/examples/rhai/wrappers_rhai.rs index 691a1884..12f72397 100644 --- a/examples/rhai/wrappers_rhai.rs +++ b/examples/rhai/wrappers_rhai.rs @@ -20,13 +20,15 @@ use bevy_script_api::rhai::{ // Even though we are implementing Clone we are still able to reference the original data in script thanks to the script wrapper we are about to implement // Debug is nice to have, we can forward that implementation to Lua's ToString via our macro #[derive(Resource, Reflect, Default, Clone, Debug)] -#[reflect(Resource)] +#[reflect(Resource, RhaiProxyable)] pub struct MyThing { usize: usize, string: String, array: Vec, } +impl RhaiCopy for MyThing {} + impl MyThing { pub fn do_something_cool(&self) -> String { self.string.clone() From d4afc88810b92138a1c231b1c10090b536f1bc13 Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Wed, 15 Nov 2023 14:14:28 +0100 Subject: [PATCH 16/27] Revert "accessing variables not work" This reverts commit c282ada927a822eb88750f5e669df53421ebe543. --- examples/rhai/wrappers_rhai.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/rhai/wrappers_rhai.rs b/examples/rhai/wrappers_rhai.rs index 12f72397..691a1884 100644 --- a/examples/rhai/wrappers_rhai.rs +++ b/examples/rhai/wrappers_rhai.rs @@ -20,15 +20,13 @@ use bevy_script_api::rhai::{ // Even though we are implementing Clone we are still able to reference the original data in script thanks to the script wrapper we are about to implement // Debug is nice to have, we can forward that implementation to Lua's ToString via our macro #[derive(Resource, Reflect, Default, Clone, Debug)] -#[reflect(Resource, RhaiProxyable)] +#[reflect(Resource)] pub struct MyThing { usize: usize, string: String, array: Vec, } -impl RhaiCopy for MyThing {} - impl MyThing { pub fn do_something_cool(&self) -> String { self.string.clone() From 478e1056293aff29e308722e7190d541c55e124f Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Wed, 15 Nov 2023 14:18:45 +0100 Subject: [PATCH 17/27] empty array --- examples/rhai/wrappers_rhai.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/examples/rhai/wrappers_rhai.rs b/examples/rhai/wrappers_rhai.rs index 691a1884..904e11c5 100644 --- a/examples/rhai/wrappers_rhai.rs +++ b/examples/rhai/wrappers_rhai.rs @@ -7,9 +7,7 @@ use bevy_mod_scripting_rhai::{ docs::RhaiDocFragment, rhai::Engine, RhaiContext, RhaiEvent, RhaiScriptHost, }; use bevy_script_api::rhai::{ - bevy::RhaiBevyAPIProvider, - std::{RegisterVecType, RhaiCopy}, - ReflectRhaiProxyable, RegisterForeignRhaiType, + bevy::RhaiBevyAPIProvider, std::RegisterVecType, RegisterForeignRhaiType, }; // Step 1. Rust representation @@ -25,6 +23,7 @@ pub struct MyThing { usize: usize, string: String, array: Vec, + empty_array: Vec, } impl MyThing { @@ -36,6 +35,7 @@ impl MyThing { fn init(mut commands: Commands) { commands.insert_resource(MyThing { array: vec![1, 2, 3], + empty_array: vec![], string: "Hello World!".to_owned(), usize: 42, }); @@ -54,6 +54,16 @@ fn run_one_shot(world: &mut World) { print(`MyThing.usize: ${my_thing.usize}`); print(`MyThing.array: ${my_thing.array}`); print(`MyThing.array[0]: ${my_thing.array[0]}`); + print(`Looping through MyThing.array:`); + for array_element in my_thing.array { + print(`MyThing.array element: ${array_element}`); + } + print(`MyThing.empty_array: ${my_thing.empty_array}`); + print(`Looping through MyThing.empty_array:`); + for empty_array_element in my_thing.empty_array { + print(`MyThing.empty_array element: ${empty_array_element}`); + } + print(`MyThing.empty_array[0]: ${my_thing.empty_array[0]}`); } "# .as_bytes(), From b88e0c33422bc58bb34fe8082e5dd9d479134931 Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Wed, 15 Nov 2023 14:24:39 +0100 Subject: [PATCH 18/27] go back to <= --- bevy_script_api/src/common/std.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bevy_script_api/src/common/std.rs b/bevy_script_api/src/common/std.rs index fe6d8bb0..99d11a9c 100644 --- a/bevy_script_api/src/common/std.rs +++ b/bevy_script_api/src/common/std.rs @@ -110,7 +110,7 @@ impl Iterator for ScriptVecIterator { type Item = ScriptRef; fn next(&mut self) -> Option { - let nxt = (self.current < self.len).then(|| self.base.index(self.current)); + let nxt = (self.current <= self.len).then(|| self.base.index(self.current)); self.current += 1; nxt } From 263e5f7d6a396562fbcf188a1d0b22655aa5315d Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Wed, 15 Nov 2023 14:33:06 +0100 Subject: [PATCH 19/27] commented out errors, setting values seem to work --- examples/rhai/wrappers_rhai.rs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/examples/rhai/wrappers_rhai.rs b/examples/rhai/wrappers_rhai.rs index 904e11c5..2ce22673 100644 --- a/examples/rhai/wrappers_rhai.rs +++ b/examples/rhai/wrappers_rhai.rs @@ -60,10 +60,24 @@ fn run_one_shot(world: &mut World) { } print(`MyThing.empty_array: ${my_thing.empty_array}`); print(`Looping through MyThing.empty_array:`); - for empty_array_element in my_thing.empty_array { - print(`MyThing.empty_array element: ${empty_array_element}`); - } - print(`MyThing.empty_array[0]: ${my_thing.empty_array[0]}`); + + // this currently returns error: + // ERROR bevy_mod_scripting_rhai: Runtime error in script `script.rhai` Runtime error: Invalid reflection path: `[0]`. No such element (line 20, position 78) in call to function 'once' + //for empty_array_element in my_thing.empty_array { + // print(`MyThing.empty_array element: ${empty_array_element}`); + //} + + // this currently returns error: + // ERROR bevy_mod_scripting_rhai: Runtime error in script `script.rhai` Function not found: do_something_cool (bevy_script_api::script_ref::ReflectedValue) (line 21, position 72) in call to function 'once' + //print(`MyThing.do_something_cool(): ${my_thing.do_something_cool()}`); + + my_thing.usize = 1337; + my_thing.string = "Hello World! 2"; + + let my_thing2 = world.get_resource(my_thing_type); + print(`MyThing2: ${my_thing2}`); + print(`MyThing2.string: ${my_thing2.string}`); + print(`MyThing2.usize: ${my_thing2.usize}`); } "# .as_bytes(), From 2c71be39d5d0f3849b6cec1b44497acb9ec876eb Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Wed, 15 Nov 2023 14:36:07 +0100 Subject: [PATCH 20/27] expanded multiple_events example for parent testing --- assets/scripts/multiple_events_rhai.rhai | 3 +++ examples/rhai/multiple_events_rhai.rs | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/assets/scripts/multiple_events_rhai.rhai b/assets/scripts/multiple_events_rhai.rhai index a544c464..a7308a50 100644 --- a/assets/scripts/multiple_events_rhai.rhai +++ b/assets/scripts/multiple_events_rhai.rhai @@ -1,5 +1,8 @@ fn on_init(name) { print(`Hello World! From "${name}" in Init`); + + let parent = world.get_parent(entity); + print(`Parent: ${type_of(parent)}`); } fn on_update(name, delta) { diff --git a/examples/rhai/multiple_events_rhai.rs b/examples/rhai/multiple_events_rhai.rs index 9ba4beda..6ecf7c55 100644 --- a/examples/rhai/multiple_events_rhai.rs +++ b/examples/rhai/multiple_events_rhai.rs @@ -60,7 +60,20 @@ impl FuncArgs for ScriptArgs { fn setup_entities(mut commands: Commands, asset_server: Res) { let script_path = "scripts/multiple_events_rhai.rhai"; - for i in 0..10 { + commands.spawn_empty().with_children(|parent| { + parent.spawn(( + NewlyAddedEntityCallInit, + Name::from("Test Entity 0"), + ScriptCollection:: { + scripts: vec![Script::new( + script_path.to_owned(), + asset_server.load(script_path), + )], + }, + )); + }); + + for i in 1..10 { let entity_name = format!("Test Entity {}", i); commands.spawn(( NewlyAddedEntityCallInit, From 17f0e8150a1375343be88804cb0336ecba3c10ef Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Wed, 15 Nov 2023 14:41:20 +0100 Subject: [PATCH 21/27] returning UNIT instead of int if parent couldn't be found --- assets/scripts/multiple_events_rhai.rhai | 9 ++++++++- bevy_script_api/src/rhai/bevy/mod.rs | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/assets/scripts/multiple_events_rhai.rhai b/assets/scripts/multiple_events_rhai.rhai index a7308a50..5699d2ba 100644 --- a/assets/scripts/multiple_events_rhai.rhai +++ b/assets/scripts/multiple_events_rhai.rhai @@ -2,7 +2,14 @@ fn on_init(name) { print(`Hello World! From "${name}" in Init`); let parent = world.get_parent(entity); - print(`Parent: ${type_of(parent)}`); + switch type_of(parent) { + "bevy_ecs::entity::Entity" => { + print(`Parent is an Entity`); + }, + "()" => { + print(`Parent doesn't exist`); + }, + } } fn on_update(name, delta) { diff --git a/bevy_script_api/src/rhai/bevy/mod.rs b/bevy_script_api/src/rhai/bevy/mod.rs index ee41bd9f..4ab540e1 100644 --- a/bevy_script_api/src/rhai/bevy/mod.rs +++ b/bevy_script_api/src/rhai/bevy/mod.rs @@ -135,7 +135,7 @@ impl CustomType for ScriptWorld { if let Some(parent) = self_.get_parent(entity) { Dynamic::from(parent) } else { - Dynamic::from(-1) + Dynamic::UNIT } }) .with_fn("get_children", |self_: ScriptWorld, parent: Entity| { From dfa7caf578dcbde1b0a3efaf62029a9547cb3444 Mon Sep 17 00:00:00 2001 From: Tim Irmler <42088586+zwazel@users.noreply.github.com> Date: Fri, 17 Nov 2023 16:59:22 +0100 Subject: [PATCH 22/27] Update bevy_script_api/src/common/std.rs Co-authored-by: Maksymilian Mozolewski --- bevy_script_api/src/common/std.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bevy_script_api/src/common/std.rs b/bevy_script_api/src/common/std.rs index 99d11a9c..fe6d8bb0 100644 --- a/bevy_script_api/src/common/std.rs +++ b/bevy_script_api/src/common/std.rs @@ -110,7 +110,7 @@ impl Iterator for ScriptVecIterator { type Item = ScriptRef; fn next(&mut self) -> Option { - let nxt = (self.current <= self.len).then(|| self.base.index(self.current)); + let nxt = (self.current < self.len).then(|| self.base.index(self.current)); self.current += 1; nxt } From 1de23933add521e17e011f37c1222b190b186f29 Mon Sep 17 00:00:00 2001 From: Tim Irmler <42088586+zwazel@users.noreply.github.com> Date: Fri, 17 Nov 2023 16:59:28 +0100 Subject: [PATCH 23/27] Update bevy_script_api/src/common/std.rs Co-authored-by: Maksymilian Mozolewski --- bevy_script_api/src/common/std.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/bevy_script_api/src/common/std.rs b/bevy_script_api/src/common/std.rs index fe6d8bb0..a4e20980 100644 --- a/bevy_script_api/src/common/std.rs +++ b/bevy_script_api/src/common/std.rs @@ -134,7 +134,6 @@ impl IntoIterator for ScriptVec { // if len > 0, subtract 1, otherwise set to 0 len: self .len() - .map(|len| if len > 0 { len - 1 } else { 0 }) .expect("Failed to get length of ScriptVec"), base: self, } From bde4b3db0fc836a2f05dcba75a512863ecf8643a Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Fri, 17 Nov 2023 17:24:12 +0100 Subject: [PATCH 24/27] no longer problem at looping through empty vec --- examples/rhai/wrappers_rhai.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/rhai/wrappers_rhai.rs b/examples/rhai/wrappers_rhai.rs index 2ce22673..4c343391 100644 --- a/examples/rhai/wrappers_rhai.rs +++ b/examples/rhai/wrappers_rhai.rs @@ -58,14 +58,12 @@ fn run_one_shot(world: &mut World) { for array_element in my_thing.array { print(`MyThing.array element: ${array_element}`); } + print(`MyThing.empty_array: ${my_thing.empty_array}`); print(`Looping through MyThing.empty_array:`); - - // this currently returns error: - // ERROR bevy_mod_scripting_rhai: Runtime error in script `script.rhai` Runtime error: Invalid reflection path: `[0]`. No such element (line 20, position 78) in call to function 'once' - //for empty_array_element in my_thing.empty_array { - // print(`MyThing.empty_array element: ${empty_array_element}`); - //} + for empty_array_element in my_thing.empty_array { + print(`MyThing.empty_array element: ${empty_array_element}`); + } // this currently returns error: // ERROR bevy_mod_scripting_rhai: Runtime error in script `script.rhai` Function not found: do_something_cool (bevy_script_api::script_ref::ReflectedValue) (line 21, position 72) in call to function 'once' From ec31d513ca05e49044d5fc781bb8a8d1675985ea Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Sat, 18 Nov 2023 22:07:56 +0100 Subject: [PATCH 25/27] if/else to check if parent exists --- assets/scripts/multiple_events_rhai.rhai | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/assets/scripts/multiple_events_rhai.rhai b/assets/scripts/multiple_events_rhai.rhai index 5699d2ba..bc7c6680 100644 --- a/assets/scripts/multiple_events_rhai.rhai +++ b/assets/scripts/multiple_events_rhai.rhai @@ -2,13 +2,10 @@ fn on_init(name) { print(`Hello World! From "${name}" in Init`); let parent = world.get_parent(entity); - switch type_of(parent) { - "bevy_ecs::entity::Entity" => { - print(`Parent is an Entity`); - }, - "()" => { - print(`Parent doesn't exist`); - }, + if parent == () { + print(`Parent doesn't exist`); + } else { + print(`Parent exists`); } } From adb18461f44f7d0ffeddcaba50672ccc34c7350b Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Sat, 18 Nov 2023 22:12:11 +0100 Subject: [PATCH 26/27] removed rhai wrapper example, moved normal wrapper example back and renamed --- Cargo.toml | 7 +- examples/rhai/wrappers_rhai.rs | 132 ------------------ examples/{lua/wrappers_lua.rs => wrappers.rs} | 0 3 files changed, 1 insertion(+), 138 deletions(-) delete mode 100644 examples/rhai/wrappers_rhai.rs rename examples/{lua/wrappers_lua.rs => wrappers.rs} (100%) diff --git a/Cargo.toml b/Cargo.toml index 187bfc4f..948a4ef5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -152,10 +152,5 @@ required-features = ["rhai", "rhai_script_api"] [[example]] name = "wrappers" -path = "examples/lua/wrappers_lua.rs" +path = "examples/wrappers.rs" required-features = ["lua54", "lua_script_api"] - -[[example]] -name = "wrappers_rhai" -path = "examples/rhai/wrappers_rhai.rs" -required-features = ["rhai", "rhai_script_api"] diff --git a/examples/rhai/wrappers_rhai.rs b/examples/rhai/wrappers_rhai.rs deleted file mode 100644 index 4c343391..00000000 --- a/examples/rhai/wrappers_rhai.rs +++ /dev/null @@ -1,132 +0,0 @@ -use bevy::prelude::*; -use bevy_mod_scripting_core::{ - hosts::{APIProvider, Recipients, ScriptHost}, - AddScriptApiProvider, AddScriptHost, AddScriptHostHandler, ScriptingPlugin, -}; -use bevy_mod_scripting_rhai::{ - docs::RhaiDocFragment, rhai::Engine, RhaiContext, RhaiEvent, RhaiScriptHost, -}; -use bevy_script_api::rhai::{ - bevy::RhaiBevyAPIProvider, std::RegisterVecType, RegisterForeignRhaiType, -}; - -// Step 1. Rust representation -// construct all our types and functionality -// Reflect is neccessary to allow access from scripts -// Clone allows receiving our wrapper as a function parameter (derives FromLua via UserData through mlua's traits) -// We can still use references to NonClone wrappers via AnyUserData in lua methods. -// Even though we are implementing Clone we are still able to reference the original data in script thanks to the script wrapper we are about to implement -// Debug is nice to have, we can forward that implementation to Lua's ToString via our macro -#[derive(Resource, Reflect, Default, Clone, Debug)] -#[reflect(Resource)] -pub struct MyThing { - usize: usize, - string: String, - array: Vec, - empty_array: Vec, -} - -impl MyThing { - pub fn do_something_cool(&self) -> String { - self.string.clone() - } -} - -fn init(mut commands: Commands) { - commands.insert_resource(MyThing { - array: vec![1, 2, 3], - empty_array: vec![], - string: "Hello World!".to_owned(), - usize: 42, - }); -} - -fn run_one_shot(world: &mut World) { - world.resource_scope(|world, mut host: Mut>| { - host.run_one_shot( - r#" - fn once() { - let my_thing_type = world.get_type_by_name("wrappers_rhai::MyThing"); - print(`MyThing type: ${my_thing_type}`); - let my_thing = world.get_resource(my_thing_type); - print(`MyThing: ${my_thing}`); - print(`MyThing.string: ${my_thing.string}`); - print(`MyThing.usize: ${my_thing.usize}`); - print(`MyThing.array: ${my_thing.array}`); - print(`MyThing.array[0]: ${my_thing.array[0]}`); - print(`Looping through MyThing.array:`); - for array_element in my_thing.array { - print(`MyThing.array element: ${array_element}`); - } - - print(`MyThing.empty_array: ${my_thing.empty_array}`); - print(`Looping through MyThing.empty_array:`); - for empty_array_element in my_thing.empty_array { - print(`MyThing.empty_array element: ${empty_array_element}`); - } - - // this currently returns error: - // ERROR bevy_mod_scripting_rhai: Runtime error in script `script.rhai` Function not found: do_something_cool (bevy_script_api::script_ref::ReflectedValue) (line 21, position 72) in call to function 'once' - //print(`MyThing.do_something_cool(): ${my_thing.do_something_cool()}`); - - my_thing.usize = 1337; - my_thing.string = "Hello World! 2"; - - let my_thing2 = world.get_resource(my_thing_type); - print(`MyThing2: ${my_thing2}`); - print(`MyThing2.string: ${my_thing2.string}`); - print(`MyThing2.usize: ${my_thing2.usize}`); - } - "# - .as_bytes(), - "script.rhai", - Entity::from_raw(0), - world, - RhaiEvent { - hook_name: "once".to_owned(), - args: (), - recipients: Recipients::All, - }, - ) - .expect("Something went wrong in the script!"); - }); -} - -fn main() -> std::io::Result<()> { - let mut app = App::new(); - - app.add_plugins((DefaultPlugins, ScriptingPlugin)) - .add_script_host::>(PostUpdate) - .add_api_provider::>(Box::new(RhaiBevyAPIProvider)) - .add_api_provider::>(Box::new(WrapperApiProvider)) - .add_script_handler::, 0, 2>(PostUpdate) - .register_type::() - .add_systems(Startup, init) - .add_systems(Update, run_one_shot.run_if(run_once())); - - app.run(); - - Ok(()) -} - -struct WrapperApiProvider; - -impl APIProvider for WrapperApiProvider { - type APITarget = Engine; - - type ScriptContext = RhaiContext; - - type DocTarget = RhaiDocFragment; - - fn register_with_app(&self, app: &mut App) { - app.register_foreign_rhai_type::>(); - } - - fn attach_api( - &mut self, - api: &mut Self::APITarget, - ) -> Result<(), bevy_mod_scripting_core::prelude::ScriptError> { - api.register_vec_functions::(); - Ok(()) - } -} diff --git a/examples/lua/wrappers_lua.rs b/examples/wrappers.rs similarity index 100% rename from examples/lua/wrappers_lua.rs rename to examples/wrappers.rs From 3559bd1294dd2141ba68d98385d0dbcce8bed411 Mon Sep 17 00:00:00 2001 From: Tim Irmler Date: Sat, 18 Nov 2023 22:15:48 +0100 Subject: [PATCH 27/27] rust fmt --- bevy_script_api/src/common/std.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bevy_script_api/src/common/std.rs b/bevy_script_api/src/common/std.rs index a4e20980..cbb0abda 100644 --- a/bevy_script_api/src/common/std.rs +++ b/bevy_script_api/src/common/std.rs @@ -132,9 +132,7 @@ impl IntoIterator for ScriptVec { // I am not sure if this will ever realistically fail, so if you do get this exception happening // hit me with an issue // if len > 0, subtract 1, otherwise set to 0 - len: self - .len() - .expect("Failed to get length of ScriptVec"), + len: self.len().expect("Failed to get length of ScriptVec"), base: self, } }