Allow Custom File Extensions for Resources (RES_BASE_EXTENSION macro)
Godot version
4.x
godot-cpp version
master
System information
Windows 10 i7-6800K
Issue description
I am currently porting my terrain system for godot 4 from module to extension and visually having custom resource names inside the editor and the file system without having to write a custom ResourceFormatLoader/Saver helps a lot.
Adding custom file extensions to a resource is not much of an important feature, but it is very useful one to avoid the clutter of .res or .tres names
Steps to reproduce
Create a Custom resource class. There is no method or macro available to set the resource save extension
Minimal reproduction project
not neccesary
Since we can do it in the engine, I think it makes sense that we should be able to do this in godot-cpp as well!
However, I think this will require some changes on the Godot engine side, I'm not sure we can implement this entirely within godot-cpp, but I'll need to do some more investigation to figure that out.
Did a little bit of digging and it looks like it is done in macros in a way that isn't exposed to GDExtension, at least not trivially
I actually did some investigation into this as I wanted to utilize the engine's binary format too and found that the main problem is that the macro RES_BASE_EXTENSION essentially takes the owning class name via get_static_class() and the provided extension and calls ClassDB::add_resource_base_extension.
It may simply be easy enough for the outset to just expose add_resource_base_extension from ClassDB to GDExtension's API and we can just call this directly inside of our shared library init methods or as a part of the _bind_methods() call within a resource class. In essence, all the macro does is wrap the call inside register_custom_data_to_otdb which is a static function called as a part of the sequence of steps when using GDREGISTER_CLASS or any of its derivatives.
@AThousandShips do you think it would be reasonable to simply modify core_bind and expose the ClassDB::add_resource_base_extension method to GDExtension? We could then implement the macro in GDExtension to mimic the behavior from the engine. wdyt?
I don't know, as I said above it's not trivial, I haven't researched it, you look into it and see 🙂
So after looking into this, it is a bit more involved as you mentioned.
The RES_BASE_EXTENSION macro relies not only in injecting the extension into ClassDB using add_resource_base_extension, but it also relies on a virtual method get_base_extension that is defined in the engine's Resource class and the macro overrides. This virtual method is necessary as it is what the resource saver uses to resolve a list of extensions that are applicable for the binary format.
So aside from needing to define our own RES_BASE_EXTENSION macro in godot-cpp, the following are needed:
- Expose
add_resource_base_extensionand I'd probably suggest likely including its sibling methods ofget_resource_base_extensions,get_extensions_for_type, andis_resource_extensionas that would give any godot-cpp tool full visibility into the data set maintained by ClassDB. - Rework with virtual method
get_base_extensionon the engine side to delegate to a virtual override method. - Implement the
RES_BASE_EXTENSIONmacro in godot-cpp, but it would differ slightly in that it would explicitly implement the virtual method override_get_base_extension.