Giter Club home page Giter Club logo

Comments (7)

Bromeon avatar Bromeon commented on July 21, 2024 1

Indeed, arrays are now supported! TypedArray support is ongoing, but this can be tracked in #33.

@thebigG @tangentstorm regarding confusion, Array and other built-in types are not "classes" in the Godot sense, as such they don't appear in ClassDB.

from gdext.

Bromeon avatar Bromeon commented on July 21, 2024

For now, this unnit business seems to be required. But I'd like to study it more and really understand what it does.

It's mostly equivalent to this C code:

RawArray raw; // the internal representation of an array
method_table->array_construct_default(&raw, nullptr);

But Rust forces you to initialize variables and clearly state which ones are potentially uninitialized, so it's more ceremony. Also, typically we encapsulate this operation with from_sys_init().

From Rust code I'm sticking to the following pattern(not sure if this is the best way of doing this):

let mut points = Array::new();
let v = Vector2Array::from(&points);

There is packed_vector2_array_construct_default method in the global table, so you can construct it directly; no need to go via Array.

But it looks like ClassDB does not have "non-Node" classes such as Arrays? So I can't really just reach out to the engine and have it "append" something for me.

Those classes and methods are also available in the extension_api.json file, under JSON key builtin_classes. It's just that there is no codegen for them implemented yet -- so they're not exposed to Rust at the moment. So maybe omit them for now, this could be added in a later step.

from gdext.

tangentstorm avatar tangentstorm commented on July 21, 2024

I believe the implementation with from_sys_init looks something like this:

#[test]
pub fn test_create_from_sys_init() {
    use godot::prelude::Array;
    use godot::sys;
    use godot::sys::GodotFfi;  // for from_sys_init

    fn new_array() -> Array {
        unsafe {
            Array::from_sys_init(|self_ptr|{
                let ctor = sys::method_table().array_construct_default;
                ctor(self_ptr, std::ptr::null_mut());
            })
        }
    }
    let a = new_array();
    assert!(a.get(0).is_none());
}

(this compiles, but fails as a unit test, as I get "unchecked access to Option::None")

from_sys_init is provided by trait GodotFfi (which is marked as #[doc(hide)])... And generated from impl_builtin_stub and ffi_methods macros in godot-core.

from gdext.

tangentstorm avatar tangentstorm commented on July 21, 2024

Okay, the following code works to implement append. I don't know if it's the "right way" to do things, but it seems to work.

   // i put this in the ready() function of my GodotExt impl:

    use godot::{sys, builtin::StringName};
    use sys::GodotFfi; // for Array.sys()

    let a = Array::new();
    assert!(a.get(0).is_none(), "the array should be empty!"); // (console complains out of bounds)
    let vgpb = sys::interface_fn!(variant_get_ptr_builtin_method);
    let name = StringName::from("append");
    let hash = 3316032543; // hash for 'append' taken from the .json file
    let meth = unsafe { vgpb(sys::VariantType::Array as i32, name.string_sys(), hash).unwrap() };
    godot_print!("append method seems to exist! let's call it.");
    for i in 0..10 {
      let args = [ Variant::from(i) ];
      let args_ptr : sys::GDExtensionConstTypePtr = args.as_ptr().cast();
      let ret_null = std::ptr::null_mut();
      unsafe { meth(a.sys(), &args_ptr, ret_null, args.len() as i32 ); }}
    godot_print!("value after append(s): {}", a.to_variant());  // "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"" !! :)

the only required changes to gdextension are to add the new and default functions and then implement ToVariant for arrays. (Variants want new to be called default):

// godot-core/src/builtin/arrays.rs
impl Array {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn default() -> Self {
        unsafe {
            Self::from_sys_init(|self_ptr| {
                let ctor = sys::builtin_fn!(array_construct_default);
                ctor(self_ptr, std::ptr::null_mut());
            })
        }
    }
}

The implementation of ToVariant is one line in godot-core/src/builtin/variant/impls.rs:

impl_variant_traits!(Array, array_to_variant, array_from_variant, Array);

from gdext.

thebigG avatar thebigG commented on July 21, 2024

let vgpb = sys::interface_fn!(variant_get_ptr_builtin_method);

Interesting...if this does what I think it does(essentially looks up a method inside of a variant?), then this could be very useful for all kinds of methods.

Thanks for sharing @tangentstorm!

from gdext.

tangentstorm avatar tangentstorm commented on July 21, 2024

@thebigG thanks for posting your work-in-progress. I referred to it repeatedly while working this out yesterday!

@Bromeon , @thebigG also seem to be correct about the ClassDB not containing the methods:

    let cdb_gmb = sys::interface_fn!(classdb_get_method_bind);
    let ptrcall = sys::interface_fn!(object_method_bind_ptrcall);
    let meth = unsafe { cdb_gmb(StringName::from("PackedInt32Array").string_sys(),
         StringName::from("append").string_sys(),
         694024632) }; // hash seems to be for each class/method pair, not just method name
    if meth == std::ptr::null_mut() { godot_print!("PackedInt32Array::append not found in ClassDB!") }

It says it's not found... This might kind of make sense because the Array classes don't descend from Object... (?)

As a sanity check, I went looking for ColorRect::set_color and it shows up fine:

    let meth = unsafe { cdb_gmb(StringName::from("ColorRect").string_sys(),
         StringName::from("set_color").string_sys(),
         2920490490) }; // hash seems to be for each class/method pair, not just method name
    if meth == std::ptr::null_mut() { godot_print!("method not found in ClassDB!") }
    else { godot_print!("method found!") }

from gdext.

ttencate avatar ttencate commented on July 21, 2024

Duplicate of #33? Array should now be usable! Note that TypedArray, which you get from several Godot APIs, is not usable... yet.

from gdext.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.