Skip to content

Add support for typed arrays #101

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions godot-codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ const SELECTED_CLASSES: &[&str] = &[
"Control",
"FileAccess",
"HTTPRequest",
"Image",
"ImageTextureLayered",
"Input",
"Label",
"MainLoop",
Expand All @@ -290,6 +292,9 @@ const SELECTED_CLASSES: &[&str] = &[
"SceneTree",
"Sprite2D",
"SpriteFrames",
"Texture",
"Texture2DArray",
"TextureLayered",
"Time",
"Timer",
];
861 changes: 861 additions & 0 deletions godot-core/src/builtin/array.rs

Large diffs are not rendered by default.

639 changes: 0 additions & 639 deletions godot-core/src/builtin/arrays.rs

This file was deleted.

4 changes: 4 additions & 0 deletions godot-core/src/builtin/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,13 @@ macro_rules! impl_builtin_traits_inner {
}
};

// TODO remove; use godot-core/src/builtin/variant/impls.rs instead (this one is only used for Callable)
( FromVariant for $Type:ty => $gd_method:ident ) => {
impl $crate::builtin::variant::FromVariant for $Type {
fn try_from_variant(variant: &$crate::builtin::Variant) -> Result<Self, $crate::builtin::variant::VariantConversionError> {
if variant.get_type() != <Self as $crate::builtin::meta::VariantMetadata>::variant_type() {
return Err($crate::builtin::variant::VariantConversionError)
}
let result = unsafe {
Self::from_sys_init(|self_ptr| {
let converter = sys::builtin_fn!($gd_method);
Expand Down
8 changes: 7 additions & 1 deletion godot-core/src/builtin/meta/class_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub struct ClassName {
}

impl ClassName {
pub fn new<T: GodotClass>() -> Self {
pub fn of<T: GodotClass>() -> Self {
Self {
backing: StringName::from(T::CLASS_NAME),
}
Expand All @@ -36,6 +36,12 @@ impl ClassName {
}
}

impl From<ClassName> for StringName {
fn from(class_name: ClassName) -> Self {
class_name.backing
}
}

impl Display for ClassName {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
self.backing.fmt(f)
Expand Down
6 changes: 5 additions & 1 deletion godot-core/src/builtin/meta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@ use godot_ffi as sys;
pub trait VariantMetadata {
fn variant_type() -> VariantType;

fn class_name() -> ClassName {
ClassName::of::<()>() // FIXME Option or so
}

fn property_info(property_name: &str) -> PropertyInfo {
PropertyInfo::new(
Self::variant_type(),
ClassName::new::<()>(), // FIXME Option or so
Self::class_name(),
StringName::from(property_name),
)
}
Expand Down
7 changes: 4 additions & 3 deletions godot-core/src/builtin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
mod macros;
mod vector_macros;

mod arrays;
mod array;
mod color;
mod dictionary;
mod math;
Expand All @@ -54,9 +54,10 @@ mod vector4i;

pub mod meta;

pub use crate::dict;
// Re-export macros.
pub use crate::{array, dict};

pub use arrays::*;
pub use array::*;
pub use color::*;
pub use dictionary::*;
pub use math::*;
Expand Down
51 changes: 28 additions & 23 deletions godot-core/src/builtin/variant/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ use sys::GodotFfi;
// ----------------------------------------------------------------------------------------------------------------------------------------------
// Macro definitions

macro_rules! impl_variant_metadata {
($T:ty, $variant_type:ident $( ; $($extra:tt)* )?) => {
impl VariantMetadata for $T {
fn variant_type() -> VariantType {
VariantType::$variant_type
}

$($($extra)*)?
}
};
}

macro_rules! impl_variant_traits {
($T:ty, $from_fn:ident, $to_fn:ident, $variant_type:ident) => {
impl_variant_traits!(@@ $T, $from_fn, $to_fn, $variant_type;);
Expand Down Expand Up @@ -62,13 +74,7 @@ macro_rules! impl_variant_traits {
}
}

impl VariantMetadata for $T {
fn variant_type() -> VariantType {
VariantType::$variant_type
}

$($extra)*
}
impl_variant_metadata!($T, $variant_type; $($extra)*);
};
}

Expand Down Expand Up @@ -144,21 +150,19 @@ mod impls {
impl_variant_traits!(GodotString, string_to_variant, string_from_variant, String);
impl_variant_traits!(StringName, string_name_to_variant, string_name_from_variant, StringName);
impl_variant_traits!(NodePath, node_path_to_variant, node_path_from_variant, NodePath);
/* TODO provide those, as soon as `Default` is available. Also consider auto-generating.
impl_variant_traits!(Rect2, rect2_to_variant, rect2_from_variant, Rect2);
impl_variant_traits!(Rect2i, rect2i_to_variant, rect2i_from_variant, Rect2i);
impl_variant_traits!(Plane, plane_to_variant, plane_from_variant, Plane);
impl_variant_traits!(Quaternion, quaternion_to_variant, quaternion_from_variant, Quaternion);
impl_variant_traits!(Aabb, aabb_to_variant, aabb_from_variant, AABB);
impl_variant_traits!(Basis, basis_to_variant, basis_from_variant, Basis);
impl_variant_traits!(Transform2D, transform_2d_to_variant, transform_2d_from_variant, Transform2D);
impl_variant_traits!(Transform3D, transform_3d_to_variant, transform_3d_from_variant, Transform3D);
impl_variant_traits!(Projection, projection_to_variant, projection_from_variant, Projection);
impl_variant_traits!(Rid, rid_to_variant, rid_from_variant, RID);
impl_variant_traits!(Callable, callable_to_variant, callable_from_variant, Callable);
impl_variant_traits!(Signal, signal_to_variant, signal_from_variant, Signal);
*/
impl_variant_traits!(Array, array_to_variant, array_from_variant, Array);
// TODO use impl_variant_traits!, as soon as `Default` is available. Also consider auto-generating.
impl_variant_metadata!(Rect2, /* rect2_to_variant, rect2_from_variant, */ Rect2);
impl_variant_metadata!(Rect2i, /* rect2i_to_variant, rect2i_from_variant, */ Rect2i);
impl_variant_metadata!(Plane, /* plane_to_variant, plane_from_variant, */ Plane);
impl_variant_metadata!(Quaternion, /* quaternion_to_variant, quaternion_from_variant, */ Quaternion);
impl_variant_metadata!(Aabb, /* aabb_to_variant, aabb_from_variant, */ Aabb);
impl_variant_metadata!(Basis, /* basis_to_variant, basis_from_variant, */ Basis);
impl_variant_metadata!(Transform2D, /* transform_2d_to_variant, transform_2d_from_variant, */ Transform2D);
impl_variant_metadata!(Transform3D, /* transform_3d_to_variant, transform_3d_from_variant, */ Transform3D);
impl_variant_metadata!(Projection, /* projection_to_variant, projection_from_variant, */ Projection);
impl_variant_metadata!(Rid, /* rid_to_variant, rid_from_variant, */ Rid);
impl_variant_metadata!(Callable, /* callable_to_variant, callable_from_variant, */ Callable);
impl_variant_metadata!(Signal, /* signal_to_variant, signal_from_variant, */ Signal);
impl_variant_traits!(PackedByteArray, packed_byte_array_to_variant, packed_byte_array_from_variant, PackedByteArray);
impl_variant_traits!(PackedInt32Array, packed_int32_array_to_variant, packed_int32_array_from_variant, PackedInt32Array);
impl_variant_traits!(PackedInt64Array, packed_int64_array_to_variant, packed_int64_array_from_variant, PackedInt64Array);
Expand Down Expand Up @@ -215,7 +219,8 @@ impl FromVariant for Variant {
// Variant itself
impl VariantMetadata for Variant {
fn variant_type() -> VariantType {
VariantType::Nil // FIXME is this correct? what else to use? is this called at all?
// Arrays use the `NIL` type to indicate that they are untyped.
VariantType::Nil
}
}

Expand Down
14 changes: 5 additions & 9 deletions godot-core/src/obj/gd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use godot_ffi::VariantType;
use sys::types::OpaqueObject;
use sys::{ffi_methods, interface_fn, static_assert_eq_size, GodotFfi};

use crate::builtin::meta::{ClassName, PropertyInfo, VariantMetadata};
use crate::builtin::{FromVariant, StringName, ToVariant, Variant, VariantConversionError};
use crate::builtin::meta::{ClassName, VariantMetadata};
use crate::builtin::{FromVariant, ToVariant, Variant, VariantConversionError};
use crate::obj::dom::Domain as _;
use crate::obj::mem::Memory as _;
use crate::obj::{cap, dom, mem, GodotClass, Inherits, Share};
Expand Down Expand Up @@ -332,7 +332,7 @@ impl<T: GodotClass> Gd<T> {
where
U: GodotClass,
{
let class_name = ClassName::new::<U>();
let class_name = ClassName::of::<U>();
let class_tag = interface_fn!(classdb_get_class_tag)(class_name.string_sys());
let cast_object_ptr = interface_fn!(object_cast_to)(self.obj_sys(), class_tag);

Expand Down Expand Up @@ -631,11 +631,7 @@ impl<T: GodotClass> VariantMetadata for Gd<T> {
VariantType::Object
}

fn property_info(property_name: &str) -> PropertyInfo {
PropertyInfo::new(
Self::variant_type(),
ClassName::new::<T>(),
StringName::from(property_name),
)
fn class_name() -> ClassName {
ClassName::of::<T>()
}
}
8 changes: 4 additions & 4 deletions godot-core/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ pub fn register_class<T: GodotExt + cap::GodotInit + cap::ImplementsGodotExt>()
// TODO: provide overloads with only some trait impls

out!("Manually register class {}", std::any::type_name::<T>());
let class_name = ClassName::new::<T>();
let class_name = ClassName::of::<T>();

let godot_params = sys::GDExtensionClassCreationInfo {
to_string_func: Some(callbacks::to_string::<T>),
Expand All @@ -133,7 +133,7 @@ pub fn register_class<T: GodotExt + cap::GodotInit + cap::ImplementsGodotExt>()

register_class_raw(ClassRegistrationInfo {
class_name,
parent_class_name: Some(ClassName::new::<T::Base>()),
parent_class_name: Some(ClassName::of::<T::Base>()),
generated_register_fn: None,
user_register_fn: Some(ErasedRegisterFn {
raw: callbacks::register_class_by_builder::<T>,
Expand Down Expand Up @@ -287,8 +287,8 @@ pub mod callbacks {
T: GodotClass,
F: FnOnce(Base<T::Base>) -> T,
{
let class_name = ClassName::new::<T>();
let base_class_name = ClassName::new::<T::Base>();
let class_name = ClassName::of::<T>();
let base_class_name = ClassName::of::<T::Base>();

//out!("create callback: {}", class_name.backing);

Expand Down
2 changes: 1 addition & 1 deletion godot-macros/src/derive_godot_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ fn make_exports_impl(class_name: &Ident, fields: &Fields) -> TokenStream {
let class_name = ::godot::builtin::StringName::from(#class_name::CLASS_NAME);
let property_info = ::godot::builtin::meta::PropertyInfo::new(
#variant_type,
::godot::builtin::meta::ClassName::new::<#class_name>(),
::godot::builtin::meta::ClassName::of::<#class_name>(),
::godot::builtin::StringName::from(#name),
);
let property_info_sys = property_info.property_sys();
Expand Down
2 changes: 1 addition & 1 deletion godot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ pub use godot_core::private;
/// Often-imported symbols.
pub mod prelude {
pub use super::bind::{godot_api, GodotClass, GodotExt};
pub use super::builtin::dict; // Re-export macros.
pub use super::builtin::*;
pub use super::builtin::{array, dict}; // Re-export macros.
pub use super::engine::{
load, try_load, utilities, AudioStreamPlayer, Camera2D, Camera3D, Input, Node, Node2D,
Node3D, Object, PackedScene, RefCounted, Resource, SceneTree,
Expand Down
20 changes: 20 additions & 0 deletions itest/godot/ManualFfiTests.gd
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,23 @@ func test_export():

obj.free()
node.free()

func test_untyped_array_pass_to_user_func():
var obj = ArrayTest.new()
var array: Array = [42, "answer"]
assert_eq(obj.pass_untyped_array(array), 2)

func test_untyped_array_return_from_user_func():
var obj = ArrayTest.new()
var array: Array = obj.return_untyped_array()
assert_eq(array, [42, "answer"])

func test_typed_array_pass_to_user_func():
var obj = ArrayTest.new()
var array: Array[int] = [1, 2, 3]
assert_eq(obj.pass_typed_array(array), 6)

func test_typed_array_return_from_user_func():
var obj = ArrayTest.new()
var array: Array[int] = obj.return_typed_array(3)
assert_eq(array, [1, 2, 3])
Loading