Skip to content
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

A subclass of an GDExtension subclass of EditorPlugin cannot be used as an editor plugin #85268

Closed
andreymal opened this issue Nov 23, 2023 · 7 comments · Fixed by #85271
Closed

Comments

@andreymal
Copy link

andreymal commented Nov 23, 2023

Godot version

4.1.3

System information

Linux

Issue description

I'm trying to make an editor plugin on Rust:

#[derive(GodotClass)]
#[class(tool, editor_plugin, init, base=EditorPlugin)]
pub struct MyEditorPluginBase {}

But due to some limitations, I still have to use GDScript for some specific things.

So I tried to make a subclass of this Rust class:

@tool
class_name MyEditorPlugin
extends MyEditorPluginBase

This would work if MyEditorPluginBase was a GDScript class, but since it's a GDExtension class in my case, it doesn't work:

Unable to load addon script from path: 'res://addons/my_addon/my_editor_plugin.gd' Base type is not EditorPlugin.

But it obviously IS EditorPlugin!

godot-editorplugin-docs

godot-editorplugin

If I understand correctly, this behavior is caused by this function, which checks some mysterious "instance base type" instead of real inheritance:

godot/editor/editor_node.cpp

Lines 3456 to 3458 in fa4a653

// Plugin init scripts must inherit from EditorPlugin and be tools.
if (String(scr->get_instance_base_type()) != "EditorPlugin") {
show_warning(vformat(TTR("Unable to load addon script from path: '%s' Base type is not EditorPlugin."), script_path));

StringName GDScript::get_instance_base_type() const {
if (native.is_valid()) {
return native->get_name();
}

Since the documentation doesn't say that the script must be a direct subclass of EditorPlugin (and an indirect subclass works fine in GDScript), I interpret this behavior as a Godot bug.

Steps to reproduce

See above

Minimal reproduction project

gdext_editor_plugin_test.zip

@AThousandShips
Copy link
Member

Please provide a minimum project, there may be many different aspects of how you've set this up that might cause this

@andreymal
Copy link
Author

@AThousandShips ok added

@YuriSizov
Copy link
Contributor

YuriSizov commented Nov 23, 2023

get_instance_base_type is used correctly, but the check itself should likely be ClassDB::is_parent_class(instance_base_type, "EditorPlugin");.

Edit: Looks like a few places need to be updated. I'll make a PR.

@dsnopek
Copy link
Contributor

dsnopek commented Nov 30, 2023

FYI, it is also possible to directly register an EditorPlugin from GDExtension, you don't need to make an addon which necessitates the workaround you're using here, where you have a GDScript that extends your GDExtension class.

I don't know the API for how it's done from Rust, but in godot-cpp, you can have code like:

void register_my_extension(ModuleInitializationLevel p_level) {
#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED)
	if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
		GDREGISTER_CLASS(MyEditorPlugin);

		EditorPlugins::add_by_type<MyEditorPlugin>();
	}
#endif
}

This will cause the editor plugin to be registered as soon as the GDExtension is loaded.

There's probably a way to do this from Rust as well!

@andreymal
Copy link
Author

@dsnopek I can't because of a godot-rust bug godot-rust/gdext#494

(which can't be painlessly fixed until godotengine/godot-proposals#2241 is implemented)

@andreymal
Copy link
Author

There is another error in 4.2.1.rc1:

ERROR: Script inherits from native type 'MyEditorPluginBase', so it can't be assigned to an object of type 'EditorPlugin'.
   at: instance_create (modules/gdscript/gdscript.cpp:390)

Should I create a separate issue about this?

@YuriSizov
Copy link
Contributor

YuriSizov commented Dec 11, 2023

@andreymal It may be is just a continuation of this one, but feel free to open a new report. I would also appreciate if you could make an MRP that uses godot-cpp at least. It's unlikely that many contributors, myself included, have a Rust environment set up to reproduce and validate your report as it stands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants