Godot Version
4.2
Question
Hey guys, new here!
I’m having trouble understanding how am i supposed to expose an array of resources (or for what matters an array of Ref wrapped RefCounted instances) in GDExtension.
Here is an (non-working) example of how I would do it:
namespace godot {
class ImageCollection : public Resource {
GDCLASS(ImageCollection, Resource)
private:
Vector<Ref<Image>> m_images;
public:
void set_images(const Vector<Ref<Image>>& p_images)
{
m_images = p_images;
}
Vector<Ref<Image>> get_images() const
{
return m_images;
}
protected:
static void _bind_methods()
{
ClassDB::bind_method(D_METHOD("set_images", "images"), &ImageCollection::set_images);
ClassDB::bind_method(D_METHOD("get_images"), &ImageCollection::get_images);
ClassDB::add_property("ImageCollection",
PropertyInfo(Variant::ARRAY, "images", PROPERTY_HINT_ARRAY_TYPE, "Image"), //
"set_images", //
"get_images"); //
}
};
}
I tried to use both TypedArray<Ref> and Vector<Ref> but the compiler didn’t like any of them. I also tried TypedArray and Vector to no avail.
Any suggestions on what I’m doing wrong?
Thank you! 
Hey man I’m struggle-bussing my way through some GDExtension stuff too - this thread here has lots of good info, maybe it would help you
https://forum.godotengine.org/t/returning-custom-classes-from-c-gdextension/65920
also the Terrain3D project is up on github and a great example of a GDExtension that has a resource it defines that uses an array of images (or textures, anyways). Maybe check that out too.
So… I’ve been experimenting a bit and i finally figured it out.
Here is how to expose and array of Ref<WhateverRefCounted> as a property of a node/resource.
namespace godot {
MAKE_TYPED_ARRAY(Ref<Image>, Variant::OBJECT)
MAKE_TYPED_ARRAY_INFO(Ref<Image>, Variant::OBJECT)
class ImageCollection : public Resource {
GDCLASS(ImageCollection, Resource)
private:
TypedArray<Ref<Image>> m_images;
public:
void set_images(TypedArray<Ref<Image>> p_images)
{
m_images = p_images;
}
TypedArray<Ref<Image>> get_images() const
{
return m_images;
}
protected:
static void _bind_methods()
{
ClassDB::bind_method(D_METHOD("set_images", "images"), &ImageCollection::set_images);
ClassDB::bind_method(D_METHOD("get_images"), &ImageCollection::get_images);
ADD_PROPERTY(
PropertyInfo(
Variant::ARRAY,
"images",
PROPERTY_HINT_TYPE_STRING,
String::num(Variant::OBJECT) + "/" + String::num(PROPERTY_HINT_RESOURCE_TYPE) + "Image"
),
"set_images",
"get_images"
);
}
};
}
- Use the
MAKE_TYPED_ARRAY and MAKE_TYPED_ARRAY_INFO macros with your Ref<Whatever> as first parameter and Variant::OBJECT for the second parameter. To avoid re-declarations I suggest doing this in a separate file since this macros declare new types.
- Use TypedArrays (not Vector like i did in my first example).
- Do not pass values to the setters by reference, only by value.
- When binding your property, in the PropertyInfo use
PROPERTY_HINT_TYPE_STRING as property hint and for the hint string pass String::num(Variant::OBJECT) + "/" + String::num(PROPERTY_HINT_RESOURCE_TYPE) + "Image" with the intended resource type instead of “Image” (source: this post)
I tested this a lil bit and it seems to function as it should, I hope your PC doesn’t explode because of me.
I hope to have been helpfull.