diff --git a/Cargo.lock b/Cargo.lock index 63d7377..30e6416 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -321,6 +321,7 @@ dependencies = [ "abi_stable", "cfg-if 1.0.0", "godot", + "godot-rust-script", "godot-rust-script-derive", "hot-lib-reloader", "itertools", diff --git a/README.md b/README.md index f1a90dc..d62b88f 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -godot-rust-script = { git = "https://github.com/TitanNano/godot-rust-script.git", branch = "master" } +godot-rust-script = { git = "https://github.com/TitanNano/godot-rust-script.git", branch = "master", features = ["runtime"] } scripts = { path = "./scripts" } ``` @@ -88,7 +88,7 @@ edition = "2021" crate-type = ["dylib", "rlib"] [dependencies] -godot-rust-script = { git = "https://github.com/TitanNano/godot-rust-script.git", branch = "master" } +godot-rust-script = { git = "https://github.com/TitanNano/godot-rust-script.git", branch = "master", features = ["scripts"] } ``` scripts-lib/src/lib.rs diff --git a/rust-script/Cargo.toml b/rust-script/Cargo.toml index 52afba9..97728a0 100644 --- a/rust-script/Cargo.toml +++ b/rust-script/Cargo.toml @@ -7,19 +7,22 @@ edition.workspace = true [dependencies] godot.workspace = true -itertools.workspace = true abi_stable.workspace = true -rand.workspace = true cfg-if.workspace = true hot-lib-reloader = { workspace = true, optional = true } +itertools = { workspace = true, optional = true } +rand = { workspace = true, optional = true } process_path = { workspace = true, optional = true } -godot-rust-script-derive.workspace = true +godot-rust-script-derive = { workspace = true, optional = true } [dev-dependencies] tests-scripts-lib = { path = "../tests-scripts-lib", features = ["hot-reload"] } +godot-rust-script = { path = "./", features = ["runtime"] } [features] default = ["hot-reload"] -hot-reload = ["dep:process_path", "dep:hot-lib-reloader"] \ No newline at end of file +hot-reload = ["dep:process_path", "dep:hot-lib-reloader"] +runtime = ["dep:itertools", "dep:rand"] +scripts = ["dep:godot-rust-script-derive"] \ No newline at end of file diff --git a/rust-script/src/lib.rs b/rust-script/src/lib.rs index e210226..b5f067d 100644 --- a/rust-script/src/lib.rs +++ b/rust-script/src/lib.rs @@ -1,15 +1,22 @@ mod apply; +mod script_registry; +mod shared; + +#[cfg(feature = "scripts")] mod library; +#[cfg(feature = "runtime")] mod runtime; -mod script_registry; +#[cfg(feature = "scripts")] pub use library::*; +#[cfg(feature = "runtime")] pub use runtime::*; +#[cfg(feature = "scripts")] pub use godot_rust_script_derive::{godot_script_impl, GodotScript}; pub mod private_export { - pub use super::script_registry::RemoteVariantType; + pub use super::{script_registry::RemoteVariantType, shared::BindingInit}; pub use abi_stable::std_types::{RStr, RString, RVec}; pub use godot::sys::{plugin_add, plugin_registry}; diff --git a/rust-script/src/library.rs b/rust-script/src/library.rs index 72b38ee..f1ccf38 100644 --- a/rust-script/src/library.rs +++ b/rust-script/src/library.rs @@ -57,7 +57,7 @@ macro_rules! setup_library { $crate::private_export::plugin_registry!(pub __SCRIPT_REGISTRY: $crate::RegistryItem); #[no_mangle] - pub fn __godot_rust_script_init(binding: Option<$crate::BindingInit>) -> $crate::private_export::RVec<$crate::RemoteScriptMetaData> { + pub fn __godot_rust_script_init(binding: Option<$crate::private_export::BindingInit>) -> $crate::private_export::RVec<$crate::RemoteScriptMetaData> { use $crate::private_export::*; use $crate::godot::obj::EngineEnum; diff --git a/rust-script/src/runtime/hot_reloader.rs b/rust-script/src/runtime/hot_reloader.rs index 3a2180c..68ea08d 100644 --- a/rust-script/src/runtime/hot_reloader.rs +++ b/rust-script/src/runtime/hot_reloader.rs @@ -13,7 +13,7 @@ use hot_lib_reloader::LibReloadObserver; use crate::{ apply::Apply, script_registry::{RemoteGodotScript_TO, RemoteValueRef}, - RustScriptLibInit, + shared::RustScriptLibInit, }; use super::{rust_script::RustScript, HOT_RELOAD_BRIDGE}; diff --git a/rust-script/src/runtime/metadata.rs b/rust-script/src/runtime/metadata.rs new file mode 100644 index 0000000..ab195d5 --- /dev/null +++ b/rust-script/src/runtime/metadata.rs @@ -0,0 +1,93 @@ +use std::rc::Rc; + +use abi_stable::std_types::RBox; +use godot::{ + obj::EngineEnum, + prelude::{ + meta::{ClassName, MethodInfo, PropertyInfo}, + Array, Dictionary, Gd, Object, StringName, ToGodot, + }, +}; + +use crate::{ + apply::Apply, + script_registry::{CreateScriptInstanceData_TO, RemoteGodotScript_TO}, + RemoteScriptMetaData, +}; + +#[derive(Debug)] +pub struct ScriptMetaData { + class_name: ClassName, + base_type_name: StringName, + properties: Rc>, + methods: Rc>, + create_data: CreateScriptInstanceData_TO<'static, RBox<()>>, +} + +impl ScriptMetaData { + pub fn class_name(&self) -> ClassName { + self.class_name + } + + pub fn base_type_name(&self) -> StringName { + self.base_type_name.clone() + } + + pub fn create_data(&self, base: Gd) -> RemoteGodotScript_TO<'static, RBox<()>> { + self.create_data.create(base.to_variant().into()) + } + + pub fn properties(&self) -> Rc> { + self.properties.clone() + } + + pub fn methods(&self) -> Rc> { + self.methods.clone() + } +} + +impl From for ScriptMetaData { + fn from(value: RemoteScriptMetaData) -> Self { + Self { + class_name: ClassName::from_ascii_cstr(value.class_name.as_str().as_bytes()), + base_type_name: StringName::from(value.base_type_name.as_str()), + properties: Rc::new(value.properties.into_iter().map(Into::into).collect()), + methods: Rc::new(value.methods.into_iter().map(Into::into).collect()), + create_data: value.create_data, + } + } +} + +pub(super) trait ToDictionary { + fn to_dict(&self) -> Dictionary; +} + +impl ToDictionary for PropertyInfo { + fn to_dict(&self) -> Dictionary { + let mut dict = Dictionary::new(); + + dict.set("name", self.property_name.clone()); + dict.set("class_name", self.class_name.to_string_name()); + dict.set("type", self.variant_type as i32); + dict.set("hint", self.hint.ord()); + dict.set("hint_string", self.hint_string.clone()); + dict.set("usage", self.usage.ord()); + + dict + } +} + +impl ToDictionary for MethodInfo { + fn to_dict(&self) -> Dictionary { + Dictionary::new().apply(|dict| { + dict.set("name", self.method_name.clone()); + dict.set("flags", self.flags.ord()); + + let args: Array<_> = self.arguments.iter().map(|arg| arg.to_dict()).collect(); + + dict.set("args", args); + + dict.set("return", self.return_type.to_dict()); + }) + } +} diff --git a/rust-script/src/runtime/mod.rs b/rust-script/src/runtime/mod.rs index 554c7d0..ee940e3 100644 --- a/rust-script/src/runtime/mod.rs +++ b/rust-script/src/runtime/mod.rs @@ -1,5 +1,6 @@ #[cfg(all(feature = "hot-reload", debug_assertions))] mod hot_reloader; +mod metadata; mod resource_loader; mod resource_saver; mod rust_script; @@ -8,22 +9,18 @@ mod rust_script_language; use std::{collections::HashMap, rc::Rc, sync::RwLock}; -use abi_stable::std_types::RVec; use cfg_if::cfg_if; use godot::{ engine::{Engine, ResourceLoader, ResourceSaver}, - obj::EngineEnum, - prelude::{ - godot_print, - meta::{MethodInfo, PropertyInfo}, - Array, Dictionary, Gd, - }, + prelude::{godot_print, Gd}, }; use crate::{ - apply::Apply, - runtime::{resource_loader::RustScriptResourceLoader, resource_saver::RustScriptResourceSaver}, - script_registry::{RemoteScriptMetaData, ScriptMetaData}, + runtime::{ + metadata::ScriptMetaData, resource_loader::RustScriptResourceLoader, + resource_saver::RustScriptResourceSaver, + }, + shared::RustScriptLibInit, }; use self::rust_script_language::RustScriptLanguage; @@ -43,7 +40,7 @@ macro_rules! setup { #[hot_functions] extern "Rust" { pub fn __godot_rust_script_init( - binding: Option<$crate::BindingInit>, + binding: Option<$crate::private_export::BindingInit>, ) -> RVec<$crate::RemoteScriptMetaData>; } @@ -79,12 +76,6 @@ thread_local! { static HOT_RELOAD_BRIDGE: std::cell::RefCell>> = std::cell::RefCell::default(); } -pub type BindingInit = godot::sys::GodotBinding; - -pub trait RustScriptLibInit: Fn(Option) -> RVec {} - -impl RustScriptLibInit for F where F: Fn(Option) -> RVec {} - cfg_if! { if #[cfg(all(feature = "hot-reload", debug_assertions))] { type HotReloadSubscribe = fn() -> hot_lib_reloader::LibReloadObserver; @@ -206,37 +197,3 @@ fn load_rust_scripts(lib_init_fn: Rc) { *reg = registry; }); } - -trait ToDictionary { - fn to_dict(&self) -> Dictionary; -} - -impl ToDictionary for PropertyInfo { - fn to_dict(&self) -> Dictionary { - let mut dict = Dictionary::new(); - - dict.set("name", self.property_name.clone()); - dict.set("class_name", self.class_name.to_string_name()); - dict.set("type", self.variant_type as i32); - dict.set("hint", self.hint.ord()); - dict.set("hint_string", self.hint_string.clone()); - dict.set("usage", self.usage.ord()); - - dict - } -} - -impl ToDictionary for MethodInfo { - fn to_dict(&self) -> Dictionary { - Dictionary::new().apply(|dict| { - dict.set("name", self.method_name.clone()); - dict.set("flags", self.flags.ord()); - - let args: Array<_> = self.arguments.iter().map(|arg| arg.to_dict()).collect(); - - dict.set("args", args); - - dict.set("return", self.return_type.to_dict()); - }) - } -} diff --git a/rust-script/src/runtime/rust_script.rs b/rust-script/src/runtime/rust_script.rs index f8307d7..ad5e019 100644 --- a/rust-script/src/runtime/rust_script.rs +++ b/rust-script/src/runtime/rust_script.rs @@ -13,9 +13,10 @@ use RemoteGodotScript_trait::RemoteGodotScript_TO; use crate::script_registry::RemoteGodotScript_trait; use super::{ + metadata::ToDictionary, rust_script_instance::{RustScriptInstance, RustScriptPlaceholder}, rust_script_language::RustScriptLanguage, - ToDictionary, SCRIPT_REGISTRY, + SCRIPT_REGISTRY, }; #[derive(GodotClass)] diff --git a/rust-script/src/script_registry.rs b/rust-script/src/script_registry.rs index 4ebfea9..18af3ad 100644 --- a/rust-script/src/script_registry.rs +++ b/rust-script/src/script_registry.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, fmt::Debug, marker::PhantomData, rc::Rc}; +use std::{collections::HashMap, fmt::Debug, marker::PhantomData}; use abi_stable::{ sabi_trait::TD_CanDowncast, @@ -11,7 +11,7 @@ use godot::{ prelude::{ godot_print, meta::{ClassName, MethodInfo, PropertyInfo}, - Gd, Object, StringName, ToGodot, Variant, + Gd, Object, StringName, Variant, }, sys::VariantType, }; @@ -147,11 +147,11 @@ impl From for MethodInfo { #[derive(Debug, StableAbi)] #[repr(C)] pub struct RemoteScriptMetaData { - class_name: RStr<'static>, - base_type_name: RStr<'static>, - properties: RVec, - methods: RVec, - create_data: CreateScriptInstanceData_TO<'static, RBox<()>>, + pub(crate) class_name: RStr<'static>, + pub(crate) base_type_name: RStr<'static>, + pub(crate) properties: RVec, + pub(crate) methods: RVec, + pub(crate) create_data: CreateScriptInstanceData_TO<'static, RBox<()>>, } impl RemoteScriptMetaData { @@ -175,49 +175,6 @@ impl RemoteScriptMetaData { } } -#[derive(Debug)] -pub struct ScriptMetaData { - class_name: ClassName, - base_type_name: StringName, - properties: Rc>, - methods: Rc>, - create_data: CreateScriptInstanceData_TO<'static, RBox<()>>, -} - -impl ScriptMetaData { - pub fn class_name(&self) -> ClassName { - self.class_name - } - - pub fn base_type_name(&self) -> StringName { - self.base_type_name.clone() - } - - pub fn create_data(&self, base: Gd) -> RemoteGodotScript_TO<'static, RBox<()>> { - self.create_data.create(base.to_variant().into()) - } - - pub fn properties(&self) -> Rc> { - self.properties.clone() - } - - pub fn methods(&self) -> Rc> { - self.methods.clone() - } -} - -impl From for ScriptMetaData { - fn from(value: RemoteScriptMetaData) -> Self { - Self { - class_name: ClassName::from_ascii_cstr(value.class_name.as_str().as_bytes()), - base_type_name: StringName::from(value.base_type_name.as_str()), - properties: Rc::new(value.properties.into_iter().map(Into::into).collect()), - methods: Rc::new(value.methods.into_iter().map(Into::into).collect()), - create_data: value.create_data, - } - } -} - #[abi_stable::sabi_trait] pub trait CreateScriptInstanceData: Debug { fn create(&self, base: RemoteValue) -> RemoteGodotScript_TO<'static, RBox<()>>; diff --git a/rust-script/src/shared.rs b/rust-script/src/shared.rs new file mode 100644 index 0000000..56b8c34 --- /dev/null +++ b/rust-script/src/shared.rs @@ -0,0 +1,9 @@ +use abi_stable::std_types::RVec; + +use crate::RemoteScriptMetaData; + +pub type BindingInit = godot::sys::GodotBinding; + +pub trait RustScriptLibInit: Fn(Option) -> RVec {} + +impl RustScriptLibInit for F where F: Fn(Option) -> RVec {} diff --git a/tests-scripts-lib/Cargo.toml b/tests-scripts-lib/Cargo.toml index 0cf724f..534fa9b 100644 --- a/tests-scripts-lib/Cargo.toml +++ b/tests-scripts-lib/Cargo.toml @@ -7,7 +7,7 @@ edition.workspace = true crate-type = ["dylib", "rlib"] [dependencies] -godot-rust-script = { path = "../rust-script", features = ["hot-reload"] } +godot-rust-script = { path = "../rust-script", features = ["hot-reload", "scripts"] } [features] hot-reload = ["godot-rust-script/hot-reload"]