Comments (7)
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.
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.
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.
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.
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.
@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.
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)
- Trait bound 'Player: GodotDefault' is not satisfied error during Hello World example HOT 3
- `#[func]` function arguments with invalid types produce weird errors HOT 2
- Deep copies taking into account Rust state (unlike `Node::duplicate()`) HOT 8
- Array<Option<Gd<_>>> Crashes on Null Pointer in Godot's Editor HOT 2
- Inheritance and polymorphism proposals
- Virtual function dispatch for Resources not working HOT 4
- Add mocks for some builtin types for use when Godot isn't running HOT 5
- Missing classes in `engine` module relating to navigation HOT 1
- Recent commit causes "GDExtension initialization function 'gdext_rust_init' returned an error" HOT 1
- Vector3 signed_angle_to is incorrect
- Simple VideoStreamPlayback causes thread panic HOT 4
- It is possible to have a `Base` pointing to a dead object HOT 2
- Issues with string & sse4 support HOT 3
- Problems related to multithreaded access imposed by Godot
- It is tricky to figure out how to properly use `WithBaseField` generically
- commit() failing for SurfaceTool in simple case HOT 6
- godot endlessly prompting to restart HOT 5
- Foreign Classes / Interfaces HOT 1
- Converting Typed Arrays to Variant Arrays Panics HOT 12
- Can't export variable with suffix HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from gdext.