diff --git a/bindings_generator/src/api.rs b/bindings_generator/src/api.rs index 8c8395bbd..12cdc68b7 100644 --- a/bindings_generator/src/api.rs +++ b/bindings_generator/src/api.rs @@ -422,7 +422,7 @@ impl Ty { Ty::Bool => syn::parse_quote! { bool }, Ty::Vector2 => syn::parse_quote! { Vector2 }, Ty::Vector3 => syn::parse_quote! { Vector3 }, - Ty::Vector3Axis => syn::parse_quote! { vector3::Axis }, + Ty::Vector3Axis => syn::parse_quote! { Axis }, Ty::Quat => syn::parse_quote! { Quat }, Ty::Transform => syn::parse_quote! { Transform }, Ty::Transform2D => syn::parse_quote! { Transform2D }, @@ -448,7 +448,7 @@ impl Ty { Ty::VariantOperator => syn::parse_quote! { VariantOperator }, Ty::Enum(path) => syn::parse_quote! { #path }, Ty::Object(path) => { - syn::parse_quote! { Option> } + syn::parse_quote! { Option> } } } } @@ -597,7 +597,7 @@ impl Ty { Ty::Object(ref path) => { quote! { ptr::NonNull::new(ret) - .map(|sys| >::move_from_sys(sys)) + .map(|sys| >::move_from_sys(sys)) } } Ty::Result => { diff --git a/bindings_generator/src/special_methods.rs b/bindings_generator/src/special_methods.rs index c70feab36..a26a8944a 100644 --- a/bindings_generator/src/special_methods.rs +++ b/bindings_generator/src/special_methods.rs @@ -26,7 +26,7 @@ destroying the object) or destroyed manually using `Ref::free`, or preferably quote! { #[doc=#documentation] #[inline] - pub fn new() -> Ref { + pub fn new() -> Ref { unsafe { let gd_api = get_api(); let ctor = #method_table::get(gd_api).class_constructor.unwrap(); @@ -42,17 +42,17 @@ pub fn generate_godot_object_impl(class: &GodotClass) -> TokenStream { let name = &class.name; let class_name = format_ident!("{}", class.name); - let ref_kind = if class.is_refcounted() { - quote! { ref_kind::RefCounted } + let memory = if class.is_refcounted() { + quote! { memory::RefCounted } } else { - quote! { ref_kind::ManuallyManaged } + quote! { memory::ManuallyManaged } }; quote! { impl gdnative_core::private::godot_object::Sealed for #class_name {} unsafe impl GodotObject for #class_name { - type RefKind = #ref_kind; + type RefKind = #memory; #[inline] fn class_name() -> &'static str { @@ -69,7 +69,7 @@ pub fn generate_instantiable_impl(class: &GodotClass) -> TokenStream { quote! { impl Instanciable for #class_name { #[inline] - fn construct() -> Ref { + fn construct() -> Ref { #class_name::new() } } diff --git a/examples/array_export/src/lib.rs b/examples/array_export/src/lib.rs index b17b6d7a3..66631cf4c 100644 --- a/examples/array_export/src/lib.rs +++ b/examples/array_export/src/lib.rs @@ -1,4 +1,4 @@ -use gdnative::nativescript::init::property::hint::{ArrayHint, IntHint, RangeHint}; +use gdnative::nativescript::export::property::hint::{ArrayHint, IntHint, RangeHint}; use gdnative::prelude::*; #[derive(NativeClass)] @@ -6,7 +6,7 @@ use gdnative::prelude::*; #[register_with(Self::register)] struct ExportsArrays; -#[gdnative::methods] +#[methods] impl ExportsArrays { fn new(_owner: &Node) -> Self { ExportsArrays diff --git a/examples/dodge_the_creeps/src/main_scene.rs b/examples/dodge_the_creeps/src/main_scene.rs index 6642ff959..7515aa9c4 100644 --- a/examples/dodge_the_creeps/src/main_scene.rs +++ b/examples/dodge_the_creeps/src/main_scene.rs @@ -140,7 +140,7 @@ impl Main { /// scene as the root. For instance Spatial is used for this example. fn instance_scene(scene: &Ref) -> Ref where - Root: gdnative::GodotObject + SubClass, + Root: gdnative::object::GodotObject + SubClass, { let scene = unsafe { scene.assume_safe() }; diff --git a/examples/hello_world/src/lib.rs b/examples/hello_world/src/lib.rs index c2395aba4..3543e8814 100644 --- a/examples/hello_world/src/lib.rs +++ b/examples/hello_world/src/lib.rs @@ -4,7 +4,7 @@ use gdnative::prelude::*; #[inherit(Node)] struct HelloWorld; -#[gdnative::methods] +#[methods] impl HelloWorld { fn new(_owner: &Node) -> Self { HelloWorld diff --git a/examples/resource/src/lib.rs b/examples/resource/src/lib.rs index 32a8fb017..faeda54e9 100644 --- a/examples/resource/src/lib.rs +++ b/examples/resource/src/lib.rs @@ -8,7 +8,7 @@ struct GreetingResource { name: String, } -#[gdnative::methods] +#[methods] impl GreetingResource { fn new(_owner: &Resource) -> Self { Self { name: "".into() } @@ -29,7 +29,7 @@ struct Greeter { greeting_resource: Option>, } -#[gdnative::methods] +#[methods] impl Greeter { fn new(_owner: &Node) -> Self { Greeter { diff --git a/examples/scene_create/src/lib.rs b/examples/scene_create/src/lib.rs index 7e79be78a..893e8aacc 100644 --- a/examples/scene_create/src/lib.rs +++ b/examples/scene_create/src/lib.rs @@ -6,7 +6,7 @@ pub enum ManageErrs { RootClassNotSpatial(String), } -#[derive(gdnative::NativeClass)] +#[derive(gdnative::derive::NativeClass)] #[inherit(Spatial)] struct SceneCreate { // Store the loaded scene for a very slight performance boost but mostly to show you how. @@ -24,7 +24,7 @@ struct SceneCreate { // Note, the same mechanism which is used to call from panel into spawn_one and remove_one can be // used to call other GDNative classes here in rust. -#[gdnative::methods] +#[gdnative::derive::methods] impl SceneCreate { fn new(_owner: &Spatial) -> Self { SceneCreate { @@ -33,7 +33,7 @@ impl SceneCreate { } } - #[export] + #[gdnative::derive::export] fn _ready(&mut self, _owner: &Spatial) { self.template = load_scene("res://Child_scene.tscn"); match &self.template { @@ -42,7 +42,7 @@ impl SceneCreate { } } - #[export] + #[gdnative::derive::export] fn spawn_one(&mut self, owner: &Spatial, message: GodotString) { godot_print!("Called spawn_one({})", message.to_string()); @@ -77,7 +77,7 @@ impl SceneCreate { update_panel(owner, num_children); } - #[export] + #[gdnative::derive::export] fn remove_one(&mut self, owner: &Spatial, str: GodotString) { godot_print!("Called remove_one({})", str); let num_children = owner.get_child_count(); @@ -116,7 +116,7 @@ pub fn load_scene(path: &str) -> Option> { /// scene as the root. For instance Spatial is used for this example. fn instance_scene(scene: &PackedScene) -> Result, ManageErrs> where - Root: gdnative::GodotObject + SubClass, + Root: gdnative::object::GodotObject + SubClass, { let instance = scene .instance(PackedScene::GEN_EDIT_STATE_DISABLED) diff --git a/examples/spinning_cube/src/lib.rs b/examples/spinning_cube/src/lib.rs index aefa1a579..1bd3f1e35 100644 --- a/examples/spinning_cube/src/lib.rs +++ b/examples/spinning_cube/src/lib.rs @@ -1,9 +1,9 @@ use gdnative::api::MeshInstance; use gdnative::prelude::*; -use gdnative::nativescript::init::property::{EnumHint, IntHint, StringHint}; +use gdnative::nativescript::export::property::{EnumHint, IntHint, StringHint}; -#[derive(gdnative::NativeClass)] +#[derive(gdnative::derive::NativeClass)] #[inherit(MeshInstance)] #[register_with(register_properties)] struct RustTest { @@ -36,7 +36,7 @@ fn register_properties(builder: &ClassBuilder) { .done(); } -#[gdnative::methods] +#[methods] impl RustTest { fn new(_owner: &MeshInstance) -> Self { RustTest { diff --git a/gdnative-bindings/src/generated.rs b/gdnative-bindings/src/generated.rs index 01b9c5389..9820e5eba 100644 --- a/gdnative-bindings/src/generated.rs +++ b/gdnative-bindings/src/generated.rs @@ -8,10 +8,9 @@ use std::sync::Once; use gdnative_core::core_types::*; use gdnative_core::object::*; +use gdnative_core::object::{memory, ownership}; use gdnative_core::private::get_api; use gdnative_core::sys; use gdnative_core::sys::GodotApi; -use gdnative_core::thread_access; -use gdnative_core::{ref_kind, GodotResult}; include!(concat!(env!("OUT_DIR"), "/generated.rs")); diff --git a/gdnative-bindings/src/utils.rs b/gdnative-bindings/src/utils.rs index 16309a941..dc1e7bac8 100644 --- a/gdnative-bindings/src/utils.rs +++ b/gdnative-bindings/src/utils.rs @@ -2,9 +2,8 @@ use super::generated::{Engine, Node, SceneTree}; use gdnative_core::nativescript::{NativeClass, RefInstance}; -use gdnative_core::object::SubClass; -use gdnative_core::thread_access::Shared; -use gdnative_core::TRef; +use gdnative_core::object::ownership::Shared; +use gdnative_core::object::{SubClass, TRef}; /// Convenience method to obtain a reference to an "auto-load" node, that is a child of the root /// node. Returns `None` if the node does not exist or is not of the correct type. diff --git a/gdnative-core/Cargo.toml b/gdnative-core/Cargo.toml index be58edb1c..43e921e71 100644 --- a/gdnative-core/Cargo.toml +++ b/gdnative-core/Cargo.toml @@ -18,16 +18,17 @@ type_tag_fallback = [] [dependencies] gdnative-sys = { path = "../gdnative-sys", version = "0.9.3" } -libc = "0.2.98" +gdnative-impl-proc-macros = { path = "../impl/proc_macros", version = "=0.9.3" } +ahash = "=0.7.4" # TODO use flexible version as soon as https://github.com/tkaitchuck/aHash/issues/99 is fixed approx = "0.5.0" +atomic-take = "1.0.0" +bitflags = { version = "1.2.1", optional = true } glam = "0.18.0" indexmap = "1.7.0" -ahash = "0.7.4" +libc = "0.2.98" once_cell = "1.8.0" +parking_lot = { version = "0.11.1", optional = true } serde = { version = "1", features = ["derive"], optional = true } -gdnative-impl-proc-macros = { path = "../impl/proc_macros", version = "=0.9.3" } - -bitflags = { version = "1.2.1", optional = true } -parking_lot = { version = "0.11.1", optional = true } -atomic-take = "1.0.0" +[dev-dependencies] +gdnative = { path = "../gdnative", version = "0.9.3" } # for doc-tests \ No newline at end of file diff --git a/gdnative-core/src/core_types/access.rs b/gdnative-core/src/core_types/access.rs index c007fcd88..8d04ff633 100644 --- a/gdnative-core/src/core_types/access.rs +++ b/gdnative-core/src/core_types/access.rs @@ -5,21 +5,21 @@ use std::ops::{Deref, DerefMut}; use std::ptr; use std::slice; +/// A pool array access that may be unaligned. #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] -/// An pool array access that may be unaligned. pub struct MaybeUnaligned { guard: G, } +/// A pool array access that is (assumed to be) aligned. #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] -/// An pool array access that is (assumed to be) aligned. pub struct Aligned { guard: G, } -#[derive(Debug)] -/// An pool array write access with an owned aligned copy. The data is written back when this is +/// A pool array write access with an owned aligned copy. The data is written back when this is /// dropped. +#[derive(Debug)] pub struct Owned where G: Guard + WritePtr, diff --git a/gdnative-core/src/core_types/byte_array.rs b/gdnative-core/src/core_types/byte_array.rs index 658c63953..e2fdb73bd 100644 --- a/gdnative-core/src/core_types/byte_array.rs +++ b/gdnative-core/src/core_types/byte_array.rs @@ -1,11 +1,11 @@ -use crate::core_types::typed_array::TypedArray; +use crate::core_types::TypedArray; /// A reference-counted vector of `u8` that uses Godot's pool allocator. pub type ByteArray = TypedArray; godot_test!( test_byte_array_access { - use crate::NewRef as _; + use crate::object::NewRef as _; let arr = (0..8).collect::(); diff --git a/gdnative-core/src/core_types/color_array.rs b/gdnative-core/src/core_types/color_array.rs index 959395927..1ac62f3b9 100644 --- a/gdnative-core/src/core_types/color_array.rs +++ b/gdnative-core/src/core_types/color_array.rs @@ -1,12 +1,12 @@ -use crate::core_types::typed_array::TypedArray; use crate::core_types::Color; +use crate::core_types::TypedArray; /// A reference-counted vector of `Color` that uses Godot's pool allocator. pub type ColorArray = TypedArray; godot_test!( test_color_array_access { - use crate::NewRef as _; + use crate::object::NewRef as _; let arr = ColorArray::from_vec(vec![ Color::from_rgb(1.0, 0.0, 0.0), diff --git a/gdnative-core/src/core_types/dictionary.rs b/gdnative-core/src/core_types/dictionary.rs index 036855d36..98a3503ed 100644 --- a/gdnative-core/src/core_types/dictionary.rs +++ b/gdnative-core/src/core_types/dictionary.rs @@ -12,10 +12,10 @@ use crate::core_types::ToVariant; use crate::core_types::ToVariantEq; use crate::core_types::Variant; use crate::core_types::VariantArray; -use crate::NewRef; +use crate::object::NewRef; use std::fmt; -use crate::thread_access::*; +use crate::object::ownership::*; /// A reference-counted `Dictionary` of `Variant` key-value pairs. /// diff --git a/gdnative-core/src/core_types/error.rs b/gdnative-core/src/core_types/error.rs index d7ade9a44..e2e809b8c 100644 --- a/gdnative-core/src/core_types/error.rs +++ b/gdnative-core/src/core_types/error.rs @@ -82,3 +82,6 @@ impl std::fmt::Display for GodotError { } impl std::error::Error for GodotError {} + +/// Result type with [GodotError] +pub type GodotResult = Result<(), GodotError>; diff --git a/gdnative-core/src/core_types/float32_array.rs b/gdnative-core/src/core_types/float32_array.rs index 9d2461366..fae5f49cc 100644 --- a/gdnative-core/src/core_types/float32_array.rs +++ b/gdnative-core/src/core_types/float32_array.rs @@ -1,11 +1,11 @@ -use crate::core_types::typed_array::TypedArray; +use crate::core_types::TypedArray; /// A reference-counted vector of `f32` that uses Godot's pool allocator. pub type Float32Array = TypedArray; godot_test!( test_float32_array_access { - use crate::NewRef as _; + use crate::object::NewRef as _; let arr = (0..8).map(|i| i as f32).collect::(); diff --git a/gdnative-core/src/core_types/int32_array.rs b/gdnative-core/src/core_types/int32_array.rs index e8088ee7b..9aafd8a09 100644 --- a/gdnative-core/src/core_types/int32_array.rs +++ b/gdnative-core/src/core_types/int32_array.rs @@ -1,11 +1,11 @@ -use crate::core_types::typed_array::TypedArray; +use crate::core_types::TypedArray; /// A reference-counted vector of `i32` that uses Godot's pool allocator. pub type Int32Array = TypedArray; godot_test!( test_int32_array_access { - use crate::NewRef as _; + use crate::object::NewRef as _; let arr = (0..8).collect::(); diff --git a/gdnative-core/src/core_types/mod.rs b/gdnative-core/src/core_types/mod.rs index c610a5633..58958a3be 100644 --- a/gdnative-core/src/core_types/mod.rs +++ b/gdnative-core/src/core_types/mod.rs @@ -1,4 +1,9 @@ -//! Types that represent core-datatypes of Godot. +//! Types that represent core data types of Godot. +//! +//! In contrast to generated Godot class types from the `api` module, the types in here are hand-written in idiomatic Rust and +//! are the counterparts to built-in types in GDScript. +//! +//! godot-rust provides optional serialization support for many core types. Enable the feature `serde` to make use of it. mod geom; @@ -6,6 +11,8 @@ mod access; mod byte_array; mod color; mod color_array; +mod dictionary; +mod error; mod float32_array; mod int32_array; mod node_path; @@ -20,21 +27,17 @@ mod variant; mod variant_array; mod vector2; mod vector2_array; +mod vector3; mod vector3_array; -pub mod dictionary; -pub mod error; -pub mod vector3; - -pub use geom::*; - pub use access::*; pub use byte_array::*; pub use color::*; pub use color_array::*; -pub use dictionary::Dictionary; -pub use error::GodotError; +pub use dictionary::*; +pub use error::{GodotError, GodotResult}; pub use float32_array::*; +pub use geom::*; pub use int32_array::*; pub use node_path::*; pub use quat::*; @@ -43,7 +46,7 @@ pub use rid::*; pub use string::*; pub use string_array::*; pub use transform2d::*; -pub use typed_array::{Element, TypedArray}; +pub use typed_array::*; // TODO rename Element to something more specific pub use variant::*; pub use variant_array::*; pub use vector2::*; diff --git a/gdnative-core/src/core_types/node_path.rs b/gdnative-core/src/core_types/node_path.rs index 0de66669a..4459643e4 100644 --- a/gdnative-core/src/core_types/node_path.rs +++ b/gdnative-core/src/core_types/node_path.rs @@ -1,7 +1,7 @@ use crate::core_types::GodotString; +use crate::object::NewRef; use crate::private::get_api; use crate::sys; -use crate::NewRef; use std::fmt; /// A reference-counted relative or absolute path in a scene tree, for use with `Node.get_node()` and similar diff --git a/gdnative-core/src/core_types/string.rs b/gdnative-core/src/core_types/string.rs index 422625de5..a8b3a0e7c 100644 --- a/gdnative-core/src/core_types/string.rs +++ b/gdnative-core/src/core_types/string.rs @@ -1,6 +1,6 @@ +use crate::object::NewRef; use crate::private::get_api; use crate::sys; -use crate::NewRef; use std::cmp::Ordering; use std::convert::TryFrom; diff --git a/gdnative-core/src/core_types/string_array.rs b/gdnative-core/src/core_types/string_array.rs index 63c7241b3..ac211c1a2 100644 --- a/gdnative-core/src/core_types/string_array.rs +++ b/gdnative-core/src/core_types/string_array.rs @@ -1,12 +1,12 @@ -use crate::core_types::typed_array::TypedArray; use crate::core_types::GodotString; +use crate::core_types::TypedArray; /// A reference-counted vector of `GodotString` that uses Godot's pool allocator. pub type StringArray = TypedArray; godot_test!( test_string_array_access { - use crate::NewRef as _; + use crate::object::NewRef as _; let arr = StringArray::from_vec(vec![ GodotString::from("foo"), diff --git a/gdnative-core/src/core_types/typed_array.rs b/gdnative-core/src/core_types/typed_array.rs index 0f4da8d34..3f56082c8 100644 --- a/gdnative-core/src/core_types/typed_array.rs +++ b/gdnative-core/src/core_types/typed_array.rs @@ -6,8 +6,8 @@ use gdnative_impl_proc_macros as macros; use crate::core_types::access::{Aligned, MaybeUnaligned}; use crate::core_types::{Color, GodotString, VariantArray, Vector2, Vector3}; +use crate::object::NewRef; use crate::private::get_api; -use crate::NewRef; /// A reference-counted CoW typed vector using Godot's pool allocator, generic over possible /// element types. diff --git a/gdnative-core/src/core_types/variant.rs b/gdnative-core/src/core_types/variant.rs index 4d4ec0e66..e3fdefffe 100644 --- a/gdnative-core/src/core_types/variant.rs +++ b/gdnative-core/src/core_types/variant.rs @@ -5,19 +5,24 @@ use std::mem::{forget, transmute}; use std::ptr; use crate::core_types::*; +use crate::object::ownership::*; use crate::object::*; use crate::private::{get_api, ManuallyManagedClassPlaceholder}; -use crate::thread_access::*; #[cfg(feature = "serde")] mod serialize; // TODO: implement Debug, PartialEq, etc. -/// A `Variant` can represent many of godot's core types. +/// A `Variant` can represent all Godot values (core types or `Object` class instances). /// -/// The underlying data can be either stored inline or reference-counted, -/// dependning on the size of the type and whether the it is trivially copyable. +/// The underlying data is either stored inline or reference-counted on the heap, +/// depending on the size of the type and whether the it is trivially copyable. +/// +/// If you compile godot-rust with the `serde` feature enabled, you will have +/// access to serialization/deserialization support: the traits `Serializable` +/// and `Deserializable` will be automatically implemented on [`VariantDispatch`] +/// as well as most of the types in [`core_types`]. pub struct Variant(pub(crate) sys::godot_variant); macro_rules! variant_constructors { diff --git a/gdnative-core/src/core_types/variant_array.rs b/gdnative-core/src/core_types/variant_array.rs index 48870fa02..d0af6a073 100644 --- a/gdnative-core/src/core_types/variant_array.rs +++ b/gdnative-core/src/core_types/variant_array.rs @@ -9,9 +9,9 @@ use crate::sys; use crate::core_types::OwnedToVariant; use crate::core_types::ToVariant; use crate::core_types::Variant; -use crate::NewRef; +use crate::object::NewRef; -use crate::thread_access::*; +use crate::object::ownership::*; use std::fmt; diff --git a/gdnative-core/src/core_types/vector2_array.rs b/gdnative-core/src/core_types/vector2_array.rs index 2cec2aa21..543891073 100644 --- a/gdnative-core/src/core_types/vector2_array.rs +++ b/gdnative-core/src/core_types/vector2_array.rs @@ -1,4 +1,4 @@ -use crate::core_types::typed_array::TypedArray; +use crate::core_types::TypedArray; use crate::core_types::Vector2; /// A reference-counted vector of `Vector2` that uses Godot's pool allocator. @@ -6,7 +6,7 @@ pub type Vector2Array = TypedArray; godot_test!( test_vector2_array_access { - use crate::NewRef as _; + use crate::object::NewRef as _; let arr = Vector2Array::from_vec(vec![ Vector2::new(1.0, 2.0), diff --git a/gdnative-core/src/core_types/vector3_array.rs b/gdnative-core/src/core_types/vector3_array.rs index ad72145ff..c2da709a9 100644 --- a/gdnative-core/src/core_types/vector3_array.rs +++ b/gdnative-core/src/core_types/vector3_array.rs @@ -1,4 +1,4 @@ -use crate::core_types::typed_array::TypedArray; +use crate::core_types::TypedArray; use crate::core_types::Vector3; /// A reference-counted vector of `Vector3` that uses Godot's pool allocator. @@ -6,7 +6,7 @@ pub type Vector3Array = TypedArray; godot_test!( test_vector3_array_access { - use crate::NewRef as _; + use crate::object::NewRef as _; let arr = Vector3Array::from_vec(vec![ Vector3::new(1.0, 2.0, 3.0), diff --git a/gdnative-core/src/init.rs b/gdnative-core/src/init.rs deleted file mode 100644 index 4cd055975..000000000 --- a/gdnative-core/src/init.rs +++ /dev/null @@ -1,93 +0,0 @@ -use crate::core_types::GodotString; - -pub struct TerminateInfo { - in_editor: bool, -} - -impl TerminateInfo { - #[doc(hidden)] - #[inline] - pub unsafe fn new(options: *mut crate::sys::godot_gdnative_terminate_options) -> Self { - assert!(!options.is_null(), "options were NULL"); - - let crate::sys::godot_gdnative_terminate_options { in_editor } = *options; - - Self { in_editor } - } - - /// Returns `true` if the library is loaded in the Godot Editor. - #[inline] - pub fn in_editor(&self) -> bool { - self.in_editor - } -} - -pub struct InitializeInfo { - in_editor: bool, - active_library_path: GodotString, - options: *mut crate::sys::godot_gdnative_init_options, -} - -impl InitializeInfo { - /// Returns true if the library is loaded in the Godot Editor. - #[inline] - pub fn in_editor(&self) -> bool { - self.in_editor - } - - /// Returns a path to the library relative to the project. - /// - /// Example: `res://../../target/debug/libhello_world.dylib` - #[inline] - pub fn active_library_path(&self) -> &GodotString { - &self.active_library_path - } - - /// # Safety - /// - /// Will `panic!()` if options is NULL or invalid. - #[doc(hidden)] - #[inline] - pub unsafe fn new(options: *mut crate::sys::godot_gdnative_init_options) -> Self { - assert!(!options.is_null(), "options were NULL"); - let crate::sys::godot_gdnative_init_options { - in_editor, - active_library_path, - .. - } = *options; - - let active_library_path = - crate::core_types::GodotString::clone_from_sys(*active_library_path); - - Self { - in_editor, - active_library_path, - options, - } - } - - #[inline] - pub fn report_loading_error(&self, message: T) - where - T: std::fmt::Display, - { - let crate::sys::godot_gdnative_init_options { - report_loading_error, - gd_native_library, - .. - } = unsafe { *self.options }; - - if let Some(report_loading_error_fn) = report_loading_error { - // Add the trailing zero and convert Display => String - let message = format!("{}\0", message); - - // Convert to FFI compatible string - let message = std::ffi::CStr::from_bytes_with_nul(message.as_bytes()) - .expect("message should not have a NULL"); - - unsafe { - report_loading_error_fn(gd_native_library, message.as_ptr()); - } - } - } -} diff --git a/gdnative-core/src/lib.rs b/gdnative-core/src/lib.rs index 0277ca96a..53a2b2d37 100644 --- a/gdnative-core/src/lib.rs +++ b/gdnative-core/src/lib.rs @@ -14,7 +14,7 @@ //! //! Since it is easy to expect containers and other types to allocate a copy of their //! content when using the `Clone` trait, some types do not implement `Clone` and instead -//! implement [`NewRef`](./trait.NewRef.html) which provides a `new_ref(&self) -> Self` method +//! implement [`NewRef`](object::NewRef) which provides a `new_ref(&self) -> Self` method //! to create references to the same collection or object. //! //! [thread-safety]: https://docs.godotengine.org/en/stable/tutorials/threads/thread_safe_apis.html @@ -25,6 +25,7 @@ #[doc(hidden)] pub extern crate gdnative_sys as sys; + #[doc(hidden)] pub extern crate libc; @@ -36,27 +37,14 @@ extern crate approx; mod macros; pub mod core_types; -mod init; #[cfg(feature = "nativescript")] pub mod nativescript; +#[doc(hidden)] pub mod log; -mod new_ref; pub mod object; -pub mod ref_kind; -pub mod thread_access; /// Internal low-level API for use by macros and generated bindings. Not a part of the public API. #[doc(hidden)] pub mod private; - -// -// Re-exports -// - -pub use init::{InitializeInfo, TerminateInfo}; -pub use new_ref::NewRef; -pub use object::{GodotObject, Null, Ref, TRef}; - -pub type GodotResult = Result<(), core_types::error::GodotError>; diff --git a/gdnative-core/src/macros.rs b/gdnative-core/src/macros.rs index cac24ce63..68f112421 100644 --- a/gdnative-core/src/macros.rs +++ b/gdnative-core/src/macros.rs @@ -16,11 +16,11 @@ #[macro_export] macro_rules! godot_gdnative_init { () => { - fn godot_gdnative_init_empty(_options: &$crate::InitializeInfo) {} + fn godot_gdnative_init_empty(_options: &$crate::private::InitializeInfo) {} $crate::godot_gdnative_init!(godot_gdnative_init_empty); }; (_ as $fn_name:ident) => { - fn godot_gdnative_init_empty(_options: &$crate::InitializeInfo) {} + fn godot_gdnative_init_empty(_options: &$crate::private::InitializeInfo) {} $crate::godot_gdnative_init!(godot_gdnative_init_empty as $fn_name); }; ($callback:ident) => { @@ -38,7 +38,7 @@ macro_rules! godot_gdnative_init { } let __result = ::std::panic::catch_unwind(|| { - let callback_options = $crate::InitializeInfo::new(options); + let callback_options = $crate::private::InitializeInfo::new(options); $callback(&callback_options) }); if __result.is_err() { @@ -64,14 +64,14 @@ macro_rules! godot_gdnative_init { #[macro_export] macro_rules! godot_gdnative_terminate { () => { - fn godot_gdnative_terminate_empty(_term_info: &$crate::TerminateInfo) {} + fn godot_gdnative_terminate_empty(_term_info: &$crate::private::TerminateInfo) {} $crate::godot_gdnative_terminate!(godot_gdnative_terminate_empty); }; ($callback:ident) => { $crate::godot_gdnative_terminate!($callback as godot_gdnative_terminate); }; (_ as $fn_name:ident) => { - fn godot_gdnative_terminate_empty(_term_info: &$crate::TerminateInfo) {} + fn godot_gdnative_terminate_empty(_term_info: &$crate::private::TerminateInfo) {} $crate::godot_gdnative_terminate!(godot_gdnative_terminate_empty as $fn_name); }; ($callback:ident as $fn_name:ident) => { @@ -86,7 +86,7 @@ macro_rules! godot_gdnative_terminate { } let __result = ::std::panic::catch_unwind(|| { - let term_info = $crate::TerminateInfo::new(options); + let term_info = $crate::private::TerminateInfo::new(options); $callback(&term_info) }); if __result.is_err() { diff --git a/gdnative-core/src/nativescript/class.rs b/gdnative-core/src/nativescript/class.rs index 0811b19a2..0a8cba98f 100644 --- a/gdnative-core/src/nativescript/class.rs +++ b/gdnative-core/src/nativescript/class.rs @@ -3,16 +3,16 @@ use std::ptr::NonNull; use crate::core_types::{ FromVariant, FromVariantError, GodotString, OwnedToVariant, ToVariant, Variant, }; -use crate::nativescript::init::ClassBuilder; -use crate::nativescript::{Map, MapMut, MapOwned, UserData}; -use crate::object::{ - AssumeSafeLifetime, LifetimeConstraint, QueueFree, RawObject, Ref, RefImplBound, SafeAsRaw, - SafeDeref, TRef, +use crate::nativescript::export::ClassBuilder; +use crate::nativescript::user_data::{Map, MapMut, MapOwned, UserData}; +use crate::object::bounds::{ + AssumeSafeLifetime, LifetimeConstraint, RefImplBound, SafeAsRaw, SafeDeref, }; +use crate::object::memory::{ManuallyManaged, RefCounted}; +use crate::object::ownership::{NonUniqueThreadAccess, Shared, ThreadAccess, ThreadLocal, Unique}; use crate::object::{GodotObject, Instanciable}; +use crate::object::{QueueFree, RawObject, Ref, TRef}; use crate::private::{get_api, ReferenceCountedClassPlaceholder}; -use crate::ref_kind::{ManuallyManaged, RefCounted}; -use crate::thread_access::{NonUniqueThreadAccess, Shared, ThreadAccess, ThreadLocal, Unique}; use super::class_registry; use super::emplace; diff --git a/gdnative-core/src/nativescript/init.rs b/gdnative-core/src/nativescript/export.rs similarity index 81% rename from gdnative-core/src/nativescript/init.rs rename to gdnative-core/src/nativescript/export.rs index 20f6eff36..649354488 100644 --- a/gdnative-core/src/nativescript/init.rs +++ b/gdnative-core/src/nativescript/export.rs @@ -1,31 +1,30 @@ -//! Types and functionalities to declare and initialize gdnative classes. +//! Low-level API to register and export GDNative classes, methods and properties. //! -//! ## API endpoints +//! ## Init and exit hooks //! //! Three endpoints are automatically invoked by the engine during startup and shutdown: //! -//! - [`godot_gdnative_init`](macro.godot_gdnative_init.html), -//! - [`godot_nativescript_init`](macro.godot_nativescript_init.html), -//! - [`godot_gdnative_terminate`](macro.godot_gdnative_terminate.html), +//! - [`godot_gdnative_init`], +//! - [`godot_nativescript_init`], +//! - [`godot_gdnative_terminate`], //! //! All three must be present. To quickly define all three endpoints using the default names, -//! use [`godot_init`](macro.godot_init.html). +//! use [`godot_init`]. //! //! ## Registering script classes //! -//! To register script classes, call `InitHandle::add_class` or `InitHandle::add_tool_class` -//! in your `godot_nativescript_init` or `godot_init` callback: +//! [`InitHandle`] is the registry of all your exported symbols. +//! To register script classes, call [`InitHandle::add_class`] or [`InitHandle::add_tool_class`] +//! in your [`godot_nativescript_init`] or [`godot_init`] callback: //! //! ```ignore -//! // - snip - +//! use gdnative::prelude::*; //! -//! fn init(handle: gdnative::init::InitHandle) { +//! fn init(handle: InitHandle) { //! handle.add_class::(); //! } //! //! godot_init!(init); -//! -//! // - snip - //! ``` //! //! For full examples, see [`examples`](https://github.com/godot-rust/godot-rust/tree/master/examples) @@ -41,13 +40,13 @@ use std::marker::PhantomData; use std::ptr; use crate::core_types::{GodotString, Variant}; -use crate::nativescript::NativeClass; -use crate::nativescript::NativeClassMethods; -use crate::nativescript::UserData; +use crate::nativescript::{user_data::UserData, NativeClass, NativeClassMethods}; +use crate::object::{GodotObject, NewRef, TRef}; use crate::private::get_api; use super::class_registry; use super::emplace; + pub mod method; pub mod property; @@ -291,15 +290,39 @@ impl ClassBuilder { /// # Examples /// /// Basic usage: + /// ``` + /// use gdnative::prelude::*; + /// use gdnative::nativescript::export::{RpcMode, Varargs}; + /// + /// #[derive(NativeClass)] + /// #[register_with(Self::my_register)] + /// #[no_constructor] + /// struct MyType {} + /// + /// // Note: no #[methods] required + /// impl MyType { + /// fn my_method(&self) -> i64 { 42 } /// - /// ```ignore - /// // `Bar` is a stateful method implementing `Method` + /// fn my_register(builder: &ClassBuilder) { + /// builder + /// .build_method("my_method", MyMethod) + /// .with_rpc_mode(RpcMode::RemoteSync) + /// .done(); + /// } + /// } /// - /// builder - /// .build_method("foo", Bar { baz: 42 }) - /// .with_rpc_mode(RpcMode::RemoteSync) - /// .done(); + /// // Now, wrap the method (this can do anything and does not need to actually call a method) + /// struct MyMethod; + /// impl Method for MyMethod { + /// fn call(&self, this: RefInstance<'_, MyType, Shared>, _args: Varargs<'_>) -> Variant { + /// this.map(|obj: &MyType, _| { + /// let result = obj.my_method(); + /// Variant::from_i64(result) + /// }).expect("method call succeeds") + /// } + /// } /// ``` + /// #[inline] pub fn build_method<'a, F: Method>( &'a self, @@ -316,14 +339,32 @@ impl ClassBuilder { /// /// Basic usage: /// - /// ```ignore - /// builder - /// .add_property("foo") - /// .with_default(0.0) - /// .with_hint((-10.0..=30.0).into()) - /// .with_getter(MyType::get_foo) - /// .with_setter(MyType::set_foo) - /// .done(); + /// ``` + /// use gdnative::prelude::*; + /// + /// #[derive(NativeClass)] + /// #[inherit(Node)] + /// #[register_with(Self::my_register)] + /// #[no_constructor] + /// struct MyType { + /// foo: i32, + /// } + /// + /// // Note: no #[methods] required + /// impl MyType { + /// pub fn get_foo(&self, _owner: TRef) -> i32 { self.foo } + /// pub fn set_foo(&mut self, _owner: TRef, val: i32) { self.foo = val; } + /// + /// fn my_register(builder: &ClassBuilder) { + /// builder + /// .add_property("foo") + /// .with_default(5) + /// .with_hint((-10..=30).into()) + /// .with_getter(MyType::get_foo) + /// .with_setter(MyType::set_foo) + /// .done(); + /// } + /// } /// ``` #[inline] pub fn add_property<'a, T>(&'a self, name: &'a str) -> PropertyBuilder<'a, C, T> diff --git a/gdnative-core/src/nativescript/init/method.rs b/gdnative-core/src/nativescript/export/method.rs similarity index 99% rename from gdnative-core/src/nativescript/init/method.rs rename to gdnative-core/src/nativescript/export/method.rs index 2c72e03d7..9ad58f5e1 100644 --- a/gdnative-core/src/nativescript/init/method.rs +++ b/gdnative-core/src/nativescript/export/method.rs @@ -10,8 +10,8 @@ use std::marker::PhantomData; use crate::core_types::{FromVariant, FromVariantError, Variant}; use crate::log::Site; use crate::nativescript::class::{NativeClass, RefInstance}; +use crate::object::ownership::Shared; use crate::object::{Ref, TRef}; -use crate::thread_access::Shared; use super::ClassBuilder; diff --git a/gdnative-core/src/nativescript/init/property.rs b/gdnative-core/src/nativescript/export/property.rs similarity index 99% rename from gdnative-core/src/nativescript/init/property.rs rename to gdnative-core/src/nativescript/export/property.rs index c50286025..e00e802ed 100644 --- a/gdnative-core/src/nativescript/init/property.rs +++ b/gdnative-core/src/nativescript/export/property.rs @@ -2,10 +2,10 @@ use crate::core_types::*; use crate::nativescript::{Instance, NativeClass}; +use crate::object::ownership::Shared; use crate::object::GodotObject; use crate::object::Ref; use crate::private::get_api; -use crate::thread_access::Shared; use super::ClassBuilder; diff --git a/gdnative-core/src/nativescript/init/property/accessor.rs b/gdnative-core/src/nativescript/export/property/accessor.rs similarity index 98% rename from gdnative-core/src/nativescript/init/property/accessor.rs rename to gdnative-core/src/nativescript/export/property/accessor.rs index 7162b1018..9583d5ce1 100644 --- a/gdnative-core/src/nativescript/init/property/accessor.rs +++ b/gdnative-core/src/nativescript/export/property/accessor.rs @@ -4,12 +4,9 @@ use std::marker::PhantomData; use std::ptr::NonNull; use crate::core_types::{FromVariant, ToVariant, Variant}; -use crate::nativescript::user_data::UserData; -use crate::nativescript::Map; -use crate::nativescript::MapMut; +use crate::nativescript::user_data::{Map, MapMut, UserData}; use crate::nativescript::NativeClass; -use crate::object::{GodotObject, RawObject}; -use crate::*; +use crate::object::{GodotObject, RawObject, TRef}; mod invalid; diff --git a/gdnative-core/src/nativescript/init/property/accessor/invalid.rs b/gdnative-core/src/nativescript/export/property/accessor/invalid.rs similarity index 100% rename from gdnative-core/src/nativescript/init/property/accessor/invalid.rs rename to gdnative-core/src/nativescript/export/property/accessor/invalid.rs diff --git a/gdnative-core/src/nativescript/init/property/hint.rs b/gdnative-core/src/nativescript/export/property/hint.rs similarity index 98% rename from gdnative-core/src/nativescript/init/property/hint.rs rename to gdnative-core/src/nativescript/export/property/hint.rs index 604db09c3..34f5ca572 100644 --- a/gdnative-core/src/nativescript/init/property/hint.rs +++ b/gdnative-core/src/nativescript/export/property/hint.rs @@ -16,7 +16,7 @@ use super::{Export, ExportInfo}; /// Basic usage: /// /// ```rust -/// use gdnative_core::nativescript::init::property::hint::RangeHint; +/// use gdnative_core::nativescript::export::property::hint::RangeHint; /// /// let hint: RangeHint = RangeHint::new(0.0, 20.0).or_greater(); /// ``` @@ -110,7 +110,7 @@ where /// Basic usage: /// /// ```rust -/// use gdnative_core::nativescript::init::property::hint::EnumHint; +/// use gdnative_core::nativescript::export::property::hint::EnumHint; /// /// let hint = EnumHint::new(vec!["Foo".into(), "Bar".into(), "Baz".into()]); /// ``` diff --git a/gdnative-core/src/nativescript/macros.rs b/gdnative-core/src/nativescript/macros.rs index 485d98f06..50422970c 100644 --- a/gdnative-core/src/nativescript/macros.rs +++ b/gdnative-core/src/nativescript/macros.rs @@ -16,14 +16,14 @@ #[macro_export] macro_rules! godot_nativescript_init { () => { - fn godot_nativescript_init_empty(_init: $crate::nativescript::init::InitHandle) {} + fn godot_nativescript_init_empty(_init: $crate::nativescript::export::InitHandle) {} $crate::godot_nativescript_init!(godot_nativescript_init_empty); }; ($callback:ident) => { $crate::godot_nativescript_init!($callback as godot_nativescript_init); }; (_ as $fn_name:ident) => { - fn godot_nativescript_init_empty(_init: $crate::nativescript::init::InitHandle) {} + fn godot_nativescript_init_empty(_init: $crate::nativescript::export::InitHandle) {} $crate::godot_nativescript_init!(godot_nativescript_init_empty as $fn_name); }; ($callback:ident as $fn_name:ident) => { @@ -36,7 +36,7 @@ macro_rules! godot_nativescript_init { } let __result = ::std::panic::catch_unwind(|| { - $callback($crate::nativescript::init::InitHandle::new(handle)); + $callback($crate::nativescript::export::InitHandle::new(handle)); }); if __result.is_err() { @@ -98,7 +98,7 @@ macro_rules! godot_wrap_method_inner { struct ThisMethod; use $crate::nativescript::{NativeClass, Instance, RefInstance, OwnerArg}; - use ::gdnative::FromVarargs; + use ::gdnative::derive::FromVarargs; #[derive(FromVarargs)] #[allow(clippy::used_underscore_binding)] @@ -108,11 +108,11 @@ macro_rules! godot_wrap_method_inner { } #[allow(unused_variables, unused_assignments, unused_mut)] - impl $crate::nativescript::init::method::StaticArgsMethod<$type_name> for ThisMethod { + impl $crate::nativescript::export::method::StaticArgsMethod<$type_name> for ThisMethod { type Args = Args; fn call( &self, - this: RefInstance<'_, $type_name, $crate::thread_access::Shared>, + this: RefInstance<'_, $type_name, $crate::object::ownership::Shared>, Args { $($pname,)* $($opt_pname,)* }: Args, ) -> $crate::core_types::Variant { this @@ -139,7 +139,7 @@ macro_rules! godot_wrap_method_inner { } } - $crate::nativescript::init::method::StaticArgs::new(ThisMethod) + $crate::nativescript::export::method::StaticArgs::new(ThisMethod) } }; } @@ -321,28 +321,3 @@ macro_rules! godot_wrap_method { ) }; } - -/// Convenience macro to create a profiling signature with a given tag. -/// -/// The expanded code will panic at runtime if the file name or `tag` contains `::` or -/// any NUL-bytes. -/// -/// See `nativescript::profiling::Signature` for more information. -/// -/// # Examples -/// -/// ```rust -/// # fn main() { -/// use gdnative_core::profile_sig; -/// use gdnative_core::nativescript::profiling::profile; -/// -/// let answer = profile(profile_sig!("foo"), || 42); -/// assert_eq!(42, answer); -/// # } -/// ``` -#[macro_export] -macro_rules! profile_sig { - ($tag:expr) => { - $crate::nativescript::profiling::Signature::new(file!(), line!(), $tag) - }; -} diff --git a/gdnative-core/src/nativescript/mod.rs b/gdnative-core/src/nativescript/mod.rs index 2eb426ec5..45c6833df 100644 --- a/gdnative-core/src/nativescript/mod.rs +++ b/gdnative-core/src/nativescript/mod.rs @@ -1,15 +1,23 @@ -//! Types and functions related to the NativeScript extension of GDNative. +//! Functionality for user-defined types exported to the engine (native scripts) +//! +//! NativeScript allows users to have their own scripts in a native language (in this case Rust). +//! It is _not_ the same as GDNative, the native interface to call into Godot. +//! +//! Symbols in this module allow registration, exporting and management of user-defined types +//! which are wrapped in native scripts. +//! +//! If you are looking for how to manage Godot core types or classes (objects), check +//! out the [`core_types`][crate::core_types] and [`object`][crate::object] modules, respectively. -pub(crate) mod class_registry; +mod class; mod emplace; mod macros; -pub mod class; -pub mod init; -pub mod profiling; -pub mod type_tag; +pub(crate) mod class_registry; +pub(crate) mod type_tag; + +pub mod export; +pub mod profiler; pub mod user_data; pub use class::*; -pub use init::*; -pub use user_data::{Map, MapMut, MapOwned, UserData}; diff --git a/gdnative-core/src/nativescript/profiling.rs b/gdnative-core/src/nativescript/profiler.rs similarity index 82% rename from gdnative-core/src/nativescript/profiling.rs rename to gdnative-core/src/nativescript/profiler.rs index 110a745a6..9f35dc47e 100644 --- a/gdnative-core/src/nativescript/profiling.rs +++ b/gdnative-core/src/nativescript/profiler.rs @@ -13,9 +13,9 @@ use crate::private::try_get_api; /// identifier of the code, usually be the name of the method. None of the substrings should /// contain `::`. /// -/// To create a `Signature` in the correct form, see `Signature::new` or `profile_sig!`. To -/// create a `Signature` from an existing `CStr` or `CString`, see `Signature::from_raw` and -/// `Signature::from_raw_owned`. +/// To create a `Signature` in the correct form, see [`Signature::new()`] or [`profile_sig!`]. To +/// create a `Signature` from an existing `CStr` or `CString`, see [`Signature::from_raw()`] and +/// [`Signature::from_raw_owned()`]. #[derive(Clone, Eq, PartialEq, Hash, Debug)] pub struct Signature<'a> { sig: Cow<'a, CStr>, @@ -54,7 +54,7 @@ impl<'a> Signature<'a> { Self::from_raw(sig) } - /// Create a borrowed version of `self` for repeated use with `add_data` or `profile`. + /// Create a borrowed version of `self` for repeated use with [`add_data()`][Self::add_data()] or [`profile()`][Self::add_data()]. #[inline(always)] pub fn borrow(&self) -> Signature<'_> { Signature { @@ -64,7 +64,7 @@ impl<'a> Signature<'a> { /// Add a data point to Godot's built-in profiler using this signature. /// - /// See the free function `gdnative::nativescript::profiling::add_data`. + /// See the free function [`profiler::add_data()`][add_data()]. #[inline] pub fn add_data(&self, time: Duration) { add_data(self.borrow(), time) @@ -73,7 +73,7 @@ impl<'a> Signature<'a> { /// Times a closure and adds the measured time to Godot's built-in profiler with this /// signature, and then returns it's return value. /// - /// See the free function `gdnative::nativescript::profiling::profile`. + /// See the free function [`profiler::profile()`][profile()]. #[inline] pub fn profile(&self, f: F) -> R where @@ -155,3 +155,30 @@ where add_data(signature, Instant::now() - start); ret } + +/// Convenience macro to create a profiling signature with a given tag. +/// +/// The expanded code will panic at runtime if the file name or `tag` contains `::` or +/// any NUL-bytes. +/// +/// See [`Signature`] for more information. +/// +/// # Examples +/// +/// ```rust +/// # fn main() { +/// use gdnative::nativescript::profiler::{profile, profile_sig}; +/// +/// let answer = profile(profile_sig!("foo"), || 42); +/// assert_eq!(answer, 42); +/// # } +/// ``` +#[macro_export] +macro_rules! _profile_sig { + ($tag:expr) => { + $crate::nativescript::profiler::Signature::new(file!(), line!(), $tag) + }; +} + +// Export macro in this module +pub use _profile_sig as profile_sig; diff --git a/gdnative-core/src/object/bounds.rs b/gdnative-core/src/object/bounds.rs new file mode 100644 index 000000000..8d63b4a8f --- /dev/null +++ b/gdnative-core/src/object/bounds.rs @@ -0,0 +1,273 @@ +//! Various traits to verify memory policy, ownership policy or lifetime bounds +//! +//! The symbols defined in this module are internal and used to enhance type safety. +//! You typically will not need to work with them. + +use crate::object::memory::*; +use crate::object::ownership::*; +use crate::object::*; + +// ---------------------------------------------------------------------------------------------------------------------------------------------- +// Implementation for RefKind policy + +/// Specialization trait depending on [`RefKind`]. This is an internal interface. +pub trait RefKindSpec: Sized { + /// Pointer wrapper that may be `Drop` or not. + #[doc(hidden)] + type PtrWrapper: PtrWrapper; + + #[doc(hidden)] + unsafe fn impl_from_maybe_ref_counted>( + ptr: NonNull, + ) -> Option> + where + Self: RefKind; + + #[doc(hidden)] + unsafe fn impl_assume_safe<'a, T: GodotObject>( + this: &Ref, + ) -> TRef<'a, T, Shared> + where + Self: RefKind; + + #[doc(hidden)] + unsafe fn impl_assume_unique>( + this: Ref, + ) -> Ref + where + Self: RefKind; + + #[doc(hidden)] + unsafe fn maybe_add_ref>(raw: &RawObject) + where + Self: RefKind; + + #[doc(hidden)] + unsafe fn maybe_init_ref>(raw: &RawObject) + where + Self: RefKind; +} + +impl RefKindSpec for ManuallyManaged { + type PtrWrapper = Forget; + + #[inline(always)] + unsafe fn impl_from_maybe_ref_counted>( + ptr: NonNull, + ) -> Option> { + if RawObject::::try_from_sys_ref(ptr).is_some() { + drop(Ref::::init_from_sys(ptr)); + None + } else { + let obj = Ref::::init_from_sys(ptr); + + if obj.as_raw().is_class::() { + Some(obj.cast_unchecked()) + } else { + obj.free(); + None + } + } + } + + #[inline(always)] + unsafe fn impl_assume_safe<'a, T: GodotObject>( + this: &Ref, + ) -> TRef<'a, T, Shared> { + debug_assert!( + this.is_instance_sane(), + "assume_safe called on an invalid pointer" + ); + this.assume_safe_unchecked() + } + + #[inline(always)] + unsafe fn impl_assume_unique>( + this: Ref, + ) -> Ref { + debug_assert!( + this.is_instance_sane(), + "assume_unique called on an invalid pointer" + ); + this.cast_access() + } + + #[inline] + unsafe fn maybe_add_ref>(_raw: &RawObject) {} + #[inline] + unsafe fn maybe_init_ref>(_raw: &RawObject) {} +} + +impl RefKindSpec for RefCounted { + type PtrWrapper = UnRef; + + #[inline(always)] + unsafe fn impl_from_maybe_ref_counted>( + ptr: NonNull, + ) -> Option> { + if RawObject::::try_from_sys_ref(ptr).is_some() { + let obj = Ref::::init_from_sys(ptr); + + if obj.as_raw().is_class::() { + Some(obj.cast_unchecked()) + } else { + None + } + } else { + RawObject::::from_sys_ref_unchecked(ptr).free(); + None + } + } + + #[inline(always)] + unsafe fn impl_assume_safe<'a, T: GodotObject>( + this: &Ref, + ) -> TRef<'a, T, Shared> { + this.assume_safe_unchecked() + } + + #[inline(always)] + unsafe fn impl_assume_unique>( + this: Ref, + ) -> Ref { + this.cast_access() + } + + #[inline] + unsafe fn maybe_add_ref>(raw: &RawObject) { + raw.add_ref(); + } + + #[inline] + unsafe fn maybe_init_ref>(raw: &RawObject) { + raw.init_ref_count(); + } +} + +// ---------------------------------------------------------------------------------------------------------------------------------------------- +// Drop strategy + +/// Specialization trait for `Drop` behavior. +pub trait PtrWrapper { + fn new(ptr: NonNull) -> Self; + fn as_non_null(&self) -> NonNull; + + #[inline] + fn as_ptr(&self) -> *mut sys::godot_object { + self.as_non_null().as_ptr() + } +} + +/// Simply releases the held object without deallocating it. +#[derive(Copy, Clone)] +pub struct Forget(NonNull); +impl PtrWrapper for Forget { + #[inline] + fn new(ptr: NonNull) -> Self { + Forget(ptr) + } + + #[inline] + fn as_non_null(&self) -> NonNull { + self.0 + } +} + +/// Decrements the reference count on the held object, deallocating it if it's the last ref. +pub struct UnRef(NonNull); +impl PtrWrapper for UnRef { + #[inline] + fn new(ptr: NonNull) -> Self { + UnRef(ptr) + } + + #[inline] + fn as_non_null(&self) -> NonNull { + self.0 + } +} +impl Drop for UnRef { + #[inline] + fn drop(&mut self) { + unsafe { + let raw = RawObject::::from_sys_ref_unchecked(self.0); + raw.unref_and_free_if_last(); + } + } +} + +// ---------------------------------------------------------------------------------------------------------------------------------------------- +// assume_safe and lifetime bounds + +/// Trait for constraining `assume_safe` lifetimes to the one of `&self` when `T` is +/// reference-counted. This is an internal interface. +pub trait LifetimeConstraint {} + +/// Type used to check lifetime constraint depending on `RefKind`. Internal interface. +#[doc(hidden)] +pub struct AssumeSafeLifetime<'a, 'r> { + _marker: PhantomData<(&'a (), &'r ())>, +} + +impl<'a, 'r> LifetimeConstraint for AssumeSafeLifetime<'a, 'r> {} +impl<'a, 'r: 'a> LifetimeConstraint for AssumeSafeLifetime<'a, 'r> {} + +// ---------------------------------------------------------------------------------------------------------------------------------------------- +// SafeDeref, SafeAsRaw + +/// Trait for combinations of `RefKind` and `ThreadAccess` that can be dereferenced safely. +/// This is an internal interface. +pub unsafe trait SafeDeref { + /// Returns a safe reference to the underlying object. + #[doc(hidden)] + fn impl_as_ref>(this: &Ref) -> TRef<'_, T, Access>; +} + +/// Trait for persistent `Ref`s that point to valid objects. This is an internal interface. +pub unsafe trait SafeAsRaw { + /// Returns a raw reference to the underlying object. + #[doc(hidden)] + fn impl_as_raw>(this: &Ref) -> &RawObject; +} + +// ---------------------------------------------------------------------------------------------------------------------------------------------- +// RefImplBound + +/// Struct to be used for various `Ref` trait bounds. +pub struct RefImplBound { + _private: (), +} + +unsafe impl SafeDeref for RefImplBound { + #[inline] + fn impl_as_ref>( + this: &Ref, + ) -> TRef<'_, T, Unique> { + unsafe { this.assume_safe_unchecked() } + } +} + +unsafe impl SafeDeref for RefImplBound { + #[inline] + fn impl_as_ref>( + this: &Ref, + ) -> TRef<'_, T, Access> { + unsafe { this.assume_safe_unchecked() } + } +} + +unsafe impl SafeAsRaw for RefImplBound { + #[inline] + fn impl_as_raw>( + this: &Ref, + ) -> &RawObject { + unsafe { this.as_raw_unchecked() } + } +} + +unsafe impl SafeAsRaw for RefImplBound { + #[inline] + fn impl_as_raw>(this: &Ref) -> &RawObject { + unsafe { this.as_raw_unchecked() } + } +} diff --git a/gdnative-core/src/ref_kind.rs b/gdnative-core/src/object/memory.rs similarity index 78% rename from gdnative-core/src/ref_kind.rs rename to gdnative-core/src/object/memory.rs index a84840cec..9c8409d8f 100644 --- a/gdnative-core/src/ref_kind.rs +++ b/gdnative-core/src/object/memory.rs @@ -1,6 +1,6 @@ //! Marker types to express the memory management method of Godot types. -use crate::object::RefKindSpec; +use crate::object::bounds::RefKindSpec; /// Marker that indicates that a type is manually managed. #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)] @@ -10,8 +10,7 @@ pub struct ManuallyManaged; #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)] pub struct RefCounted; -/// Trait to parameterize over the memory management markers -/// [`ManuallyManaged`](struct.ManuallyManaged.html) and [`RefCounted`](struct.RefCounted.html). +/// Trait to parameterize over the memory management markers [`ManuallyManaged`] and [`RefCounted`]. /// /// This trait is sealed and has no public members. pub trait RefKind: RefKindSpec + private::Sealed {} @@ -21,7 +20,6 @@ impl private::Sealed for ManuallyManaged {} impl RefKind for RefCounted {} impl private::Sealed for RefCounted {} - mod private { pub trait Sealed {} } diff --git a/gdnative-core/src/object.rs b/gdnative-core/src/object/mod.rs similarity index 83% rename from gdnative-core/src/object.rs rename to gdnative-core/src/object/mod.rs index a6f8ea346..5755ff41a 100644 --- a/gdnative-core/src/object.rs +++ b/gdnative-core/src/object/mod.rs @@ -1,3 +1,11 @@ +//! Provides types to interact with the Godot `Object` class hierarchy +//! +//! This module contains wrappers and helpers to interact with Godot objects. +//! In Godot, classes stand in an inheritance relationship, with the root at `Object`. +//! +//! If you are looking for how to manage user-defined types (native scripts), +//! check out the [`nativescript`][crate::nativescript] module. + use std::borrow::Borrow; use std::ffi::CString; use std::fmt::{self, Debug}; @@ -6,19 +14,25 @@ use std::marker::PhantomData; use std::ops::Deref; use std::ptr::NonNull; -use crate::private::{get_api, ManuallyManagedClassPlaceholder, ReferenceCountedClassPlaceholder}; -use crate::ref_kind::{ManuallyManaged, RefCounted, RefKind}; -use crate::sys; -use crate::thread_access::{ - LocalThreadAccess, NonUniqueThreadAccess, Shared, ThreadAccess, ThreadLocal, Unique, -}; - #[cfg(feature = "nativescript")] use crate::nativescript::{Instance, NativeClass, RefInstance}; -mod raw; +use crate::private::{get_api, ManuallyManagedClassPlaceholder, ReferenceCountedClassPlaceholder}; +use crate::sys; +use bounds::{AssumeSafeLifetime, LifetimeConstraint, PtrWrapper, RefKindSpec}; +use memory::{ManuallyManaged, RefCounted, RefKind}; +use ownership::{NonUniqueThreadAccess, Shared, ThreadAccess, ThreadLocal, Unique}; +pub use self::new_ref::NewRef; pub use self::raw::RawObject; +use crate::object::bounds::{RefImplBound, SafeAsRaw, SafeDeref}; + +pub mod bounds; +pub mod memory; +pub mod ownership; + +mod new_ref; +mod raw; /// Trait for Godot API objects. This trait is sealed, and implemented for generated wrapper /// types. @@ -1095,254 +1109,6 @@ impl<'a, T: GodotObject> AsVariant for &'a Ref { type Target = T; } -/// Trait for combinations of `RefKind` and `ThreadAccess` that can be dereferenced safely. -/// This is an internal interface. -pub unsafe trait SafeDeref { - /// Returns a safe reference to the underlying object. - #[doc(hidden)] - fn impl_as_ref>(this: &Ref) -> TRef<'_, T, Access>; -} - -/// Trait for persistent `Ref`s that point to valid objects. This is an internal interface. -pub unsafe trait SafeAsRaw { - /// Returns a raw reference to the underlying object. - #[doc(hidden)] - fn impl_as_raw>(this: &Ref) -> &RawObject; -} - -/// Struct to be used for various `Ref` trait bounds. -pub struct RefImplBound { - _private: (), -} - -unsafe impl SafeDeref for RefImplBound { - #[inline] - fn impl_as_ref>( - this: &Ref, - ) -> TRef<'_, T, Unique> { - unsafe { this.assume_safe_unchecked() } - } -} - -unsafe impl SafeDeref for RefImplBound { - #[inline] - fn impl_as_ref>( - this: &Ref, - ) -> TRef<'_, T, Access> { - unsafe { this.assume_safe_unchecked() } - } -} - -unsafe impl SafeAsRaw for RefImplBound { - #[inline] - fn impl_as_raw>( - this: &Ref, - ) -> &RawObject { - unsafe { this.as_raw_unchecked() } - } -} - -unsafe impl SafeAsRaw for RefImplBound { - #[inline] - fn impl_as_raw>(this: &Ref) -> &RawObject { - unsafe { this.as_raw_unchecked() } - } -} - -/// Specialization trait depending on `RefKind`. This is an internal interface. -pub trait RefKindSpec: Sized { - /// Pointer wrapper that may be `Drop` or not. - #[doc(hidden)] - type PtrWrapper: PtrWrapper; - - #[doc(hidden)] - unsafe fn impl_from_maybe_ref_counted>( - ptr: NonNull, - ) -> Option> - where - Self: RefKind; - - #[doc(hidden)] - unsafe fn impl_assume_safe<'a, T: GodotObject>( - this: &Ref, - ) -> TRef<'a, T, Shared> - where - Self: RefKind; - - #[doc(hidden)] - unsafe fn impl_assume_unique>( - this: Ref, - ) -> Ref - where - Self: RefKind; - - #[doc(hidden)] - unsafe fn maybe_add_ref>(raw: &RawObject) - where - Self: RefKind; - - #[doc(hidden)] - unsafe fn maybe_init_ref>(raw: &RawObject) - where - Self: RefKind; -} - -impl RefKindSpec for ManuallyManaged { - type PtrWrapper = Forget; - - #[inline(always)] - unsafe fn impl_from_maybe_ref_counted>( - ptr: NonNull, - ) -> Option> { - if RawObject::::try_from_sys_ref(ptr).is_some() { - drop(Ref::::init_from_sys(ptr)); - None - } else { - let obj = Ref::::init_from_sys(ptr); - - if obj.as_raw().is_class::() { - Some(obj.cast_unchecked()) - } else { - obj.free(); - None - } - } - } - - #[inline(always)] - unsafe fn impl_assume_safe<'a, T: GodotObject>( - this: &Ref, - ) -> TRef<'a, T, Shared> { - debug_assert!( - this.is_instance_sane(), - "assume_safe called on an invalid pointer" - ); - this.assume_safe_unchecked() - } - - #[inline(always)] - unsafe fn impl_assume_unique>( - this: Ref, - ) -> Ref { - debug_assert!( - this.is_instance_sane(), - "assume_unique called on an invalid pointer" - ); - this.cast_access() - } - - #[inline] - unsafe fn maybe_add_ref>(_raw: &RawObject) {} - #[inline] - unsafe fn maybe_init_ref>(_raw: &RawObject) {} -} - -impl RefKindSpec for RefCounted { - type PtrWrapper = UnRef; - - #[inline(always)] - unsafe fn impl_from_maybe_ref_counted>( - ptr: NonNull, - ) -> Option> { - if RawObject::::try_from_sys_ref(ptr).is_some() { - let obj = Ref::::init_from_sys(ptr); - - if obj.as_raw().is_class::() { - Some(obj.cast_unchecked()) - } else { - None - } - } else { - RawObject::::from_sys_ref_unchecked(ptr).free(); - None - } - } - - #[inline(always)] - unsafe fn impl_assume_safe<'a, T: GodotObject>( - this: &Ref, - ) -> TRef<'a, T, Shared> { - this.assume_safe_unchecked() - } - - #[inline(always)] - unsafe fn impl_assume_unique>( - this: Ref, - ) -> Ref { - this.cast_access() - } - - #[inline] - unsafe fn maybe_add_ref>(raw: &RawObject) { - raw.add_ref(); - } - - #[inline] - unsafe fn maybe_init_ref>(raw: &RawObject) { - raw.init_ref_count(); - } -} - -/// Specialization trait for `Drop` behavior. -pub trait PtrWrapper { - fn new(ptr: NonNull) -> Self; - fn as_non_null(&self) -> NonNull; - - #[inline] - fn as_ptr(&self) -> *mut sys::godot_object { - self.as_non_null().as_ptr() - } -} - -#[derive(Copy, Clone)] -pub struct Forget(NonNull); -impl PtrWrapper for Forget { - #[inline] - fn new(ptr: NonNull) -> Self { - Forget(ptr) - } - - #[inline] - fn as_non_null(&self) -> NonNull { - self.0 - } -} - -pub struct UnRef(NonNull); -impl PtrWrapper for UnRef { - #[inline] - fn new(ptr: NonNull) -> Self { - UnRef(ptr) - } - - #[inline] - fn as_non_null(&self) -> NonNull { - self.0 - } -} -impl Drop for UnRef { - #[inline] - fn drop(&mut self) { - unsafe { - let raw = RawObject::::from_sys_ref_unchecked(self.0); - raw.unref_and_free_if_last(); - } - } -} - -/// Trait for constraining `assume_safe` lifetimes to the one of `&self` when `T` is -/// reference-counted. This is an internal interface. -pub trait LifetimeConstraint {} - -/// Type used to check lifetime constraint depending on `RefKind`. Internal interface. -#[doc(hidden)] -pub struct AssumeSafeLifetime<'a, 'r> { - _marker: PhantomData<(&'a (), &'r ())>, -} - -impl<'a, 'r> LifetimeConstraint for AssumeSafeLifetime<'a, 'r> {} -impl<'a, 'r: 'a> LifetimeConstraint for AssumeSafeLifetime<'a, 'r> {} - mod private { pub trait Sealed {} } diff --git a/gdnative-core/src/new_ref.rs b/gdnative-core/src/object/new_ref.rs similarity index 100% rename from gdnative-core/src/new_ref.rs rename to gdnative-core/src/object/new_ref.rs diff --git a/gdnative-core/src/thread_access.rs b/gdnative-core/src/object/ownership.rs similarity index 74% rename from gdnative-core/src/thread_access.rs rename to gdnative-core/src/object/ownership.rs index 34d173159..9fd3a13a2 100644 --- a/gdnative-core/src/thread_access.rs +++ b/gdnative-core/src/object/ownership.rs @@ -1,4 +1,4 @@ -//! Typestates to express thread safety of Godot types. +//! Typestates to express ownership and thread safety of Godot types. /// Marker that indicates that a value currently only has a /// single unique reference. @@ -19,18 +19,17 @@ pub struct Shared; #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)] pub struct ThreadLocal(std::marker::PhantomData<*const ()>); -/// Trait to parametrise over the access markers [`Unique`](struct.Unique.html), -/// [`Shared`](struct.Shared.html), and [`ThreadLocal`](struct.ThreadLocal.html). +/// Trait to parametrize over the access markers [`Unique`], [`Shared`] and [`ThreadLocal`]. /// /// This trait is sealed and has no public members. pub trait ThreadAccess: private::Sealed {} -/// Trait to parametrise over the access markers that are local to the current thread: -/// [`Unique`](struct.Unique.html) and [`ThreadLocal`](struct.ThreadLocal.html). +/// Trait to parametrize over the access markers that are local to the current thread: +/// [`Unique`] and [`ThreadLocal`]. pub trait LocalThreadAccess: ThreadAccess {} -/// Trait to parametrise over the access markers that are not unique: -/// [`Shared`](struct.Shared.html) and [`ThreadLocal`](struct.ThreadLocal.html). +/// Trait to parametrize over the access markers that are not unique: +/// [`Shared`] and [`ThreadLocal`]. pub trait NonUniqueThreadAccess: ThreadAccess {} impl ThreadAccess for Unique {} diff --git a/gdnative-core/src/object/raw.rs b/gdnative-core/src/object/raw.rs index 988dfd701..fd34a4bec 100644 --- a/gdnative-core/src/object/raw.rs +++ b/gdnative-core/src/object/raw.rs @@ -3,8 +3,8 @@ use std::marker::PhantomData; use std::ptr::{self, NonNull}; use crate::core_types::GodotString; +use crate::object::memory::RefCounted; use crate::private::get_api; -use crate::ref_kind::RefCounted; use crate::sys; use super::GodotObject; diff --git a/gdnative-core/src/private.rs b/gdnative-core/src/private.rs index 46b36d592..53c186935 100644 --- a/gdnative-core/src/private.rs +++ b/gdnative-core/src/private.rs @@ -1,7 +1,11 @@ use std::ffi::CString; +use crate::core_types::GodotString; use crate::sys; +// ---------------------------------------------------------------------------------------------------------------------------------------------- +// Unsafe helpers for sys + static mut GODOT_API: Option = None; static mut GDNATIVE_LIBRARY_SYS: Option<*mut sys::godot_object> = None; @@ -149,7 +153,7 @@ pub mod godot_object { pub(crate) struct ManuallyManagedClassPlaceholder; unsafe impl crate::object::GodotObject for ManuallyManagedClassPlaceholder { - type RefKind = crate::ref_kind::ManuallyManaged; + type RefKind = crate::object::memory::ManuallyManaged; fn class_name() -> &'static str { "Object" @@ -161,7 +165,7 @@ impl godot_object::Sealed for ManuallyManagedClassPlaceholder {} pub(crate) struct ReferenceCountedClassPlaceholder; unsafe impl crate::object::GodotObject for ReferenceCountedClassPlaceholder { - type RefKind = crate::ref_kind::RefCounted; + type RefKind = crate::object::memory::RefCounted; fn class_name() -> &'static str { "Reference" @@ -229,3 +233,98 @@ make_method_table!(struct NativeScriptMethodTable for NativeScript { set_library, new, }); + +// ---------------------------------------------------------------------------------------------------------------------------------------------- +// Helper structs for init/terminate + +pub struct TerminateInfo { + in_editor: bool, +} + +impl TerminateInfo { + #[inline] + #[doc(hidden)] // avoids clippy warning: unsafe function's docs miss `# Safety` section + pub unsafe fn new(options: *mut crate::sys::godot_gdnative_terminate_options) -> Self { + assert!(!options.is_null(), "options were NULL"); + + let crate::sys::godot_gdnative_terminate_options { in_editor } = *options; + + Self { in_editor } + } + + /// Returns `true` if the library is loaded in the Godot Editor. + #[inline] + pub fn in_editor(&self) -> bool { + self.in_editor + } +} + +pub struct InitializeInfo { + in_editor: bool, + active_library_path: GodotString, + options: *mut crate::sys::godot_gdnative_init_options, +} + +impl InitializeInfo { + /// Returns true if the library is loaded in the Godot Editor. + #[inline] + pub fn in_editor(&self) -> bool { + self.in_editor + } + + /// Returns a path to the library relative to the project. + /// + /// Example: `res://../../target/debug/libhello_world.dylib` + #[inline] + pub fn active_library_path(&self) -> &GodotString { + &self.active_library_path + } + + /// # Safety + /// + /// Will `panic!()` if options is NULL or invalid. + #[inline] + #[doc(hidden)] + pub unsafe fn new(options: *mut crate::sys::godot_gdnative_init_options) -> Self { + assert!(!options.is_null(), "options were NULL"); + let crate::sys::godot_gdnative_init_options { + in_editor, + active_library_path, + .. + } = *options; + + let active_library_path = + crate::core_types::GodotString::clone_from_sys(*active_library_path); + + Self { + in_editor, + active_library_path, + options, + } + } + + #[inline] + pub fn report_loading_error(&self, message: T) + where + T: std::fmt::Display, + { + let crate::sys::godot_gdnative_init_options { + report_loading_error, + gd_native_library, + .. + } = unsafe { *self.options }; + + if let Some(report_loading_error_fn) = report_loading_error { + // Add the trailing zero and convert Display => String + let message = format!("{}\0", message); + + // Convert to FFI compatible string + let message = std::ffi::CStr::from_bytes_with_nul(message.as_bytes()) + .expect("message should not have a NULL"); + + unsafe { + report_loading_error_fn(gd_native_library, message.as_ptr()); + } + } + } +} diff --git a/gdnative-derive/src/lib.rs b/gdnative-derive/src/lib.rs index 1266170f4..8a6e178fe 100644 --- a/gdnative-derive/src/lib.rs +++ b/gdnative-derive/src/lib.rs @@ -49,8 +49,8 @@ mod variant; /// } /// impl gdnative::nativescript::NativeClassMethods for Foo { /// fn register(builder: &ClassBuilder) { -/// use gdnative::nativescript::init::*; -/// builder.build_method("foo", gdnative::godot_wrap_method!(Foo, fn foo(&self, _owner: &Reference, bar: i64) -> i64)) +/// use gdnative::nativescript::export::*; +/// builder.build_method("foo", gdnative::macros::godot_wrap_method!(Foo, fn foo(&self, _owner: &Reference, bar: i64) -> i64)) /// .with_rpc_mode(RpcMode::Disabled) /// .done_stateless(); /// } @@ -63,7 +63,7 @@ mod variant; /// ``` /// **Important**: Only one `impl` block per struct may be attributed with `#[methods]`. /// -/// For more context, please refer to [gdnative::NativeClass](NativeClass). +/// For more context, please refer to [gdnative::derive::NativeClass](NativeClass). #[proc_macro_attribute] pub fn methods(meta: TokenStream, input: TokenStream) -> TokenStream { if syn::parse::(meta.clone()).is_err() { @@ -163,7 +163,7 @@ pub fn profiled(meta: TokenStream, input: TokenStream) -> TokenStream { /// /// ``` /// use gdnative::prelude::*; -/// use gdnative::nativescript::property::{RangeHint, FloatHint}; +/// use gdnative::nativescript::export::property::{RangeHint, FloatHint}; /// /// #[derive(NativeClass)] /// #[inherit(Reference)] diff --git a/gdnative-derive/src/methods.rs b/gdnative-derive/src/methods.rs index fe81477af..115255a25 100644 --- a/gdnative-derive/src/methods.rs +++ b/gdnative-derive/src/methods.rs @@ -128,7 +128,7 @@ pub(crate) fn derive_methods(item_impl: ItemImpl) -> TokenStream2 { quote_spanned!( sig_span=> { - let method = ::gdnative::godot_wrap_method!( + let method = ::gdnative::macros::godot_wrap_method!( #class_name, fn #name ( #( #args )* ) -> #ret_ty ); @@ -146,8 +146,8 @@ pub(crate) fn derive_methods(item_impl: ItemImpl) -> TokenStream2 { #derived impl gdnative::nativescript::NativeClassMethods for #class_name { - fn register(#builder: &::gdnative::nativescript::init::ClassBuilder) { - use gdnative::nativescript::init::*; + fn register(#builder: &::gdnative::nativescript::export::ClassBuilder) { + use gdnative::nativescript::export::*; #(#methods)* } diff --git a/gdnative-derive/src/native_script.rs b/gdnative-derive/src/native_script.rs index 47651d596..c2a1a3b50 100644 --- a/gdnative-derive/src/native_script.rs +++ b/gdnative-derive/src/native_script.rs @@ -29,7 +29,7 @@ pub(crate) fn impl_empty_nativeclass(derive_input: &DeriveInput) -> TokenStream2 fn class_name() -> &'static str { unimplemented!() } - fn init(owner: ::gdnative::TRef<'_, Self::Base, Shared>) -> Self { + fn init(owner: ::gdnative::object::TRef<'_, Self::Base, Shared>) -> Self { unimplemented!() } } @@ -56,7 +56,7 @@ pub(crate) fn derive_native_class(derive_input: &DeriveInput) -> Result Result| { + .with_ref_getter(|this: &#name, _owner: ::gdnative::object::TRef| { #before_get let res = &this.#ident; #after_get res }) - .with_setter(|this: &mut #name, _owner: ::gdnative::TRef, v| { + .with_setter(|this: &mut #name, _owner: ::gdnative::object::TRef, v| { #before_set this.#ident = v; #after_set @@ -105,7 +105,7 @@ pub(crate) fn derive_native_class(derive_input: &DeriveInput) -> Result) -> Self { + fn init(owner: ::gdnative::object::TRef) -> Self { Self::new(::gdnative::nativescript::OwnerArg::from_safe_ref(owner)) } }) @@ -123,7 +123,7 @@ pub(crate) fn derive_native_class(derive_input: &DeriveInput) -> Result) { + fn register_properties(builder: &::gdnative::nativescript::export::ClassBuilder) { #(#properties)*; #register_callback } diff --git a/gdnative-derive/src/profiled.rs b/gdnative-derive/src/profiled.rs index e38414f0d..5f6f9bd99 100644 --- a/gdnative-derive/src/profiled.rs +++ b/gdnative-derive/src/profiled.rs @@ -111,7 +111,8 @@ pub(crate) fn derive_profiled( let stmts = std::mem::take(&mut item_fn.block.stmts); item_fn.block = Box::new(parse_quote!({ - ::gdnative::nativescript::profiling::profile(::gdnative::profile_sig!(#tag), move || { + ::gdnative::nativescript::profiler::profile( + ::gdnative::nativescript::profiler::profile_sig!(#tag), move || { #(#stmts)* }) })); diff --git a/gdnative-derive/src/varargs.rs b/gdnative-derive/src/varargs.rs index 560c90bce..f99c8846e 100644 --- a/gdnative-derive/src/varargs.rs +++ b/gdnative-derive/src/varargs.rs @@ -35,10 +35,10 @@ pub(crate) fn derive_from_varargs(input: DeriveInput) -> Result { return Ok(quote! { #derived - impl #generics ::gdnative::nativescript::init::method::FromVarargs for #ident #generics #where_clause { + impl #generics ::gdnative::nativescript::export::method::FromVarargs for #ident #generics #where_clause { fn read<'a>( - #input_ident: &mut ::gdnative::nativescript::init::method::Varargs<'a>, - ) -> Result>> { + #input_ident: &mut ::gdnative::nativescript::export::method::Varargs<'a>, + ) -> Result>> { Ok(#ident) } } @@ -113,10 +113,10 @@ pub(crate) fn derive_from_varargs(input: DeriveInput) -> Result( - #input_ident: &mut ::gdnative::nativescript::init::method::Varargs<'a>, - ) -> Result>> { + #input_ident: &mut ::gdnative::nativescript::export::method::Varargs<'a>, + ) -> Result>> { let mut __errors = Vec::new(); #( diff --git a/gdnative/src/lib.rs b/gdnative/src/lib.rs index fe70eb8bd..705d4740d 100644 --- a/gdnative/src/lib.rs +++ b/gdnative/src/lib.rs @@ -15,7 +15,7 @@ //! //! Since it is easy to expect containers and other types to allocate a copy of their //! content when using the `Clone` trait, some types do not implement `Clone` and instead -//! implement [`NewRef`](./trait.NewRef.html) which provides a `new_ref(&self) -> Self` method +//! implement [`NewRef`](object::NewRef) which provides a `new_ref(&self) -> Self` method //! to create references to the same collection or object. //! //! ## Generated API types @@ -41,9 +41,12 @@ //! //! ## Feature flags //! -//! ### `bindings` -//! -//! *Enabled* by default. Includes the crates.io version of the bindings in the `api` module. +//! * `bindings` -- *enabled* by default. Includes the crates.io version of the bindings in the +//! `api` module. Disable if you want to use a custom Godot version. +//! * `serde` -- *disabled* by default. Enable for `serde` support. See also +//! [`Variant`](core_types::Variant). +//! * `formatted` -- *disabled* by default. Enable if the generated binding source code should +//! be human-readable. //! //! [thread-safety]: https://docs.godotengine.org/en/stable/tutorials/threads/thread_safe_apis.html //! [custom-version]: https://github.com/godot-rust/godot-rust/#other-versions-or-custom-builds @@ -51,25 +54,33 @@ // TODO: add logo using #![doc(html_logo_url = "https://")] -// Workaround: rustdoc currently shows hidden items in the original crate when they are -// re-exported. Manually re-exporting the public items works around that. +// Workaround (rustdoc 1.55): +// Items, which are #[doc(hidden)] in their original crate and re-exported with a wildcard, lose +// their hidden status. Re-exporting them manually and hiding the wildcard solves this. #[doc(inline)] -pub use gdnative_core::{ - core_types, godot_dbg, godot_error, godot_gdnative_init, godot_gdnative_terminate, godot_init, - godot_nativescript_init, godot_print, godot_warn, godot_wrap_method, nativescript, object, - ref_kind, thread_access, GodotObject, GodotResult, NewRef, Null, Ref, TRef, -}; +pub use gdnative_core::{core_types, nativescript, object}; + +/// Collection of declarative `godot_*` macros, mostly for GDNative registration and output. +pub mod macros { + pub use gdnative_core::{ + godot_dbg, godot_error, godot_gdnative_init, godot_gdnative_terminate, godot_init, + godot_nativescript_init, godot_print, godot_warn, godot_wrap_method, + }; +} +// Implementation details (e.g. used by macros). +// However, do not re-export macros (on crate level), thus no wildcard #[doc(hidden)] -pub use gdnative_core::*; +pub use gdnative_core::{libc, sys}; +/// Derive macros and macro attributes. #[doc(inline)] -pub use gdnative_derive::*; +pub use gdnative_derive as derive; /// Curated re-exports of common items. pub mod prelude; +/// Bindings for the Godot Class API. #[doc(inline)] #[cfg(feature = "bindings")] -/// Bindings for the Godot Class API. pub use gdnative_bindings as api; diff --git a/gdnative/src/prelude.rs b/gdnative/src/prelude.rs index cb3a35fa5..3faebae9b 100644 --- a/gdnative/src/prelude.rs +++ b/gdnative/src/prelude.rs @@ -1,26 +1,28 @@ pub use gdnative_core::core_types::{ - self, error::GodotError, Aabb, Basis, ByteArray, Color, ColorArray, Dictionary, Float32Array, + self, Aabb, Basis, ByteArray, Color, ColorArray, Dictionary, Float32Array, GodotError, GodotString, Int32Array, NodePath, Plane, Quat, Rect2, Rid, StringArray, StringName, Transform, Transform2D, TypedArray, Variant, VariantArray, VariantDispatch, VariantOperator, VariantType, Vector2, Vector2Array, Vector3, Vector3Array, }; + pub use gdnative_core::core_types::{ FromVariant, FromVariantError, OwnedToVariant, ToVariant, ToVariantEq, }; pub use gdnative_core::object::{ - AsArg, GodotObject, Instanciable, Null, QueueFree, Ref, SubClass, TRef, + memory::{ManuallyManaged, RefCounted}, + ownership::{Shared, ThreadLocal, Unique}, + AsArg, GodotObject, Instanciable, NewRef, Null, QueueFree, Ref, SubClass, TRef, }; -pub use gdnative_core::ref_kind::{ManuallyManaged, RefCounted}; -pub use gdnative_core::thread_access::{Shared, ThreadLocal, Unique}; -pub use gdnative_core::NewRef; pub use gdnative_core::nativescript::{ self, - class::{Instance, RefInstance}, - init::{ClassBuilder, InitHandle, Method, MethodBuilder, Signal, SignalArgument}, + export::{ + ClassBuilder, ExportInfo, InitHandle, Method, MethodBuilder, PropertyUsage, Signal, + SignalArgument, + }, user_data::{self, Aether, ArcData, LocalCellData, MutexData, RwLockData}, - ExportInfo, NativeClass, NativeClassMethods, PropertyUsage, + Instance, NativeClass, NativeClassMethods, RefInstance, }; pub use gdnative_core::{ diff --git a/gdnative/tests/ui/derive_fail_methods_missing_new.stderr b/gdnative/tests/ui/derive_fail_methods_missing_new.stderr index 8acdd52b0..9182369d6 100644 --- a/gdnative/tests/ui/derive_fail_methods_missing_new.stderr +++ b/gdnative/tests/ui/derive_fail_methods_missing_new.stderr @@ -10,8 +10,8 @@ error[E0599]: no function or associated item named `new` found for struct `Foo` = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `new`, perhaps you need to implement one of them: candidate #1: `UserData` - candidate #2: `gdnative::GodotObject` - candidate #3: `PtrWrapper` + candidate #2: `PtrWrapper` + candidate #3: `gdnative::prelude::GodotObject` candidate #4: `glam::core::traits::matrix::Matrix2x2` candidate #5: `glam::core::traits::vector::MaskVector2` candidate #6: `glam::core::traits::vector::MaskVector3` diff --git a/gdnative/tests/ui/derive_property_basic.rs b/gdnative/tests/ui/derive_property_basic.rs index 9fba4c110..f75187461 100644 --- a/gdnative/tests/ui/derive_property_basic.rs +++ b/gdnative/tests/ui/derive_property_basic.rs @@ -1,4 +1,4 @@ -use gdnative::nativescript::init::property::*; +use gdnative::nativescript::export::property::*; use gdnative::prelude::*; fn test_hint() -> StringHint { diff --git a/test/src/lib.rs b/test/src/lib.rs index af69adb19..087690756 100644 --- a/test/src/lib.rs +++ b/test/src/lib.rs @@ -21,7 +21,7 @@ pub extern "C" fn run_tests( let mut status = true; status &= gdnative::core_types::test_string(); - status &= gdnative::core_types::dictionary::test_dictionary(); + status &= gdnative::core_types::test_dictionary(); // status &= gdnative::test_dictionary_clone_clear(); status &= gdnative::core_types::test_color(); status &= gdnative::core_types::test_array(); @@ -86,7 +86,7 @@ fn test_underscore_method_binding() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_underscore_method_binding failed"); + godot_error!(" !! Test test_underscore_method_binding failed"); } ok @@ -165,7 +165,7 @@ fn test_rust_class_construction() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_rust_class_construction failed"); + godot_error!(" !! Test test_rust_class_construction failed"); } ok @@ -247,7 +247,7 @@ fn test_from_instance_id() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_from_instance_id failed"); + godot_error!(" !! Test test_from_instance_id failed"); } ok @@ -268,4 +268,4 @@ fn init(handle: InitHandle) { test_vararray_return::register(handle); } -gdnative::godot_init!(init); +godot_init!(init); diff --git a/test/src/test_constructor.rs b/test/src/test_constructor.rs index 158a1a7e0..e49390fad 100644 --- a/test/src/test_constructor.rs +++ b/test/src/test_constructor.rs @@ -62,7 +62,7 @@ fn test_from_class_name() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_from_class_name failed"); + godot_error!(" !! Test test_from_class_name failed"); } ok diff --git a/test/src/test_derive.rs b/test/src/test_derive.rs index 74c314a3b..b296da33a 100644 --- a/test/src/test_derive.rs +++ b/test/src/test_derive.rs @@ -129,7 +129,7 @@ fn test_derive_to_variant() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_derive_to_variant failed"); + godot_error!(" !! Test test_derive_to_variant failed"); } ok @@ -167,13 +167,13 @@ fn test_derive_owned_to_variant() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_derive_owned_to_variant failed"); + godot_error!(" !! Test test_derive_owned_to_variant failed"); } ok } -#[derive(gdnative::NativeClass)] +#[derive(gdnative::derive::NativeClass)] #[inherit(Node)] struct PropertyHooks { #[property( @@ -278,7 +278,7 @@ fn test_derive_nativeclass_with_property_hooks() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_derive_owned_to_variant failed"); + godot_error!(" !! Test test_derive_owned_to_variant failed"); } ok @@ -315,7 +315,7 @@ fn test_derive_nativeclass_without_constructor() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_derive_nativeclass_without_constructor failed"); + godot_error!(" !! Test test_derive_nativeclass_without_constructor failed"); } ok diff --git a/test/src/test_free_ub.rs b/test/src/test_free_ub.rs index 5f04d92d2..ff00f2c2d 100644 --- a/test/src/test_free_ub.rs +++ b/test/src/test_free_ub.rs @@ -75,7 +75,7 @@ fn test_owner_free_ub() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_owner_free_ub failed"); + godot_error!(" !! Test test_owner_free_ub failed"); } ok diff --git a/test/src/test_map_owned.rs b/test/src/test_map_owned.rs index dc6dfe590..cd9c61cb6 100644 --- a/test/src/test_map_owned.rs +++ b/test/src/test_map_owned.rs @@ -62,7 +62,7 @@ fn test_map_owned() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_map_owned failed"); + godot_error!(" !! Test test_map_owned failed"); } ok diff --git a/test/src/test_register.rs b/test/src/test_register.rs index 1e0129106..f230bca52 100644 --- a/test/src/test_register.rs +++ b/test/src/test_register.rs @@ -1,6 +1,6 @@ use std::ops::Add; -use gdnative::nativescript::init::method::{StaticArgs, StaticArgsMethod}; +use gdnative::nativescript::export::method::{StaticArgs, StaticArgsMethod}; use gdnative::prelude::*; pub(crate) fn run_tests() -> bool { @@ -109,7 +109,7 @@ fn test_register_property() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_register_property failed"); + godot_error!(" !! Test test_register_property failed"); } ok @@ -236,7 +236,7 @@ fn test_advanced_methods() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_advanced_methods failed"); + godot_error!(" !! Test test_advanced_methods failed"); } ok diff --git a/test/src/test_return_leak.rs b/test/src/test_return_leak.rs index 335ae5f39..9c8a80c70 100644 --- a/test/src/test_return_leak.rs +++ b/test/src/test_return_leak.rs @@ -83,7 +83,7 @@ fn test_return_leak() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_return_leak failed"); + godot_error!(" !! Test test_return_leak failed"); } ok diff --git a/test/src/test_serde.rs b/test/src/test_serde.rs index fe2a3ca48..c35e4e3c9 100644 --- a/test/src/test_serde.rs +++ b/test/src/test_serde.rs @@ -9,7 +9,7 @@ pub(crate) fn run_tests() -> bool { status &= test_variant_eq(); status &= test_dispatch_eq(); if !status { - gdnative::godot_error!(" !!!! Can't run serde tests, Foo::[to/from]_variant is broken!"); + godot_error!(" !!!! Can't run serde tests, Foo::[to/from]_variant is broken!"); return false; } @@ -126,7 +126,7 @@ fn test_variant_eq() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_variant_eq failed"); + godot_error!(" !! Test test_variant_eq failed"); } ok @@ -145,7 +145,7 @@ fn test_dispatch_eq() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_dispatch_eq failed"); + godot_error!(" !! Test test_dispatch_eq failed"); } ok @@ -174,7 +174,7 @@ fn test_ron() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_ron failed"); + godot_error!(" !! Test test_ron failed"); } ok @@ -201,7 +201,7 @@ fn test_json() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_json failed"); + godot_error!(" !! Test test_json failed"); } ok @@ -226,7 +226,7 @@ fn test_yaml() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_yaml failed"); + godot_error!(" !! Test test_yaml failed"); } ok @@ -252,7 +252,7 @@ fn test_cbor() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_cbor failed"); + godot_error!(" !! Test test_cbor failed"); } ok @@ -280,7 +280,7 @@ fn test_msgpack() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_msgpack failed"); + godot_error!(" !! Test test_msgpack failed"); } ok @@ -307,7 +307,7 @@ fn test_bincode() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_bincode failed"); + godot_error!(" !! Test test_bincode failed"); } ok diff --git a/test/src/test_vararray_return.rs b/test/src/test_vararray_return.rs index 0cbd2cd55..3f97a3505 100644 --- a/test/src/test_vararray_return.rs +++ b/test/src/test_vararray_return.rs @@ -27,7 +27,7 @@ fn test_vararray_return_crash() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_vararray_return_crash failed"); + godot_error!(" !! Test test_vararray_return_crash failed"); } ok diff --git a/test/src/test_variant_call_args.rs b/test/src/test_variant_call_args.rs index 0085f9343..8bdd8957b 100644 --- a/test/src/test_variant_call_args.rs +++ b/test/src/test_variant_call_args.rs @@ -90,7 +90,7 @@ fn test_variant_call_args() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_variant_call_args failed"); + godot_error!(" !! Test test_variant_call_args failed"); } ok diff --git a/test/src/test_variant_ops.rs b/test/src/test_variant_ops.rs index cb3562610..eb080a50a 100644 --- a/test/src/test_variant_ops.rs +++ b/test/src/test_variant_ops.rs @@ -41,7 +41,7 @@ fn test_variant_ops() -> bool { .is_ok(); if !ok { - gdnative::godot_error!(" !! Test test_variant_ops failed"); + godot_error!(" !! Test test_variant_ops failed"); } ok