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

EditorExportPlugin raises error everytime you run the game with F5 because of "abstract native class" #73525

Closed
eh-jogos opened this issue Feb 17, 2023 · 28 comments · Fixed by #93942

Comments

@eh-jogos
Copy link

Godot version

4.0 rc2

System information

Manjaro Linux using i3, Foward+

Issue description

I've added an ExportPlugin to my addon and everytime I run the game in the editor I know get this error:

SCRIPT ERROR: Parse Error: Class "eh_UtilitiesExportPlugin" cannot be constructed as it is based on abstract native class "EditorExportPlugin".

I even tried to guard it with an Engine.is_editor_hint() call but it doesn't work, I still get the same error even though line 54 shouldn't be executing:
image

Weirdly enough, this guard works fine in other parts of the project, but fails here.

Steps to reproduce

Just create a script that extends EditorExportPlugin, and try to create an instance of it in an EditorPlugin script

Minimal reproduction project

See "Steps to Reproduce"

@CodexLambda
Copy link

I've experienced a similar issue with a tool script using EditorScript.new() or EditorPlugin.new().

On running the project (F5), it gives Parser Error: Native class "EditorScript" cannot be constructed as it is abstract.. The same call works in editor.

4.0 rc2, Win x64, Forward+

@PunchablePlushie
Copy link

Can confirm that it happens in 4.0 rc3 as well.
EditorPlugin.new() works fine in the editor itself. But running the project will raise an error.

@baptr
Copy link
Contributor

baptr commented Feb 27, 2023

Still an issue with 4.0rc5.

It looks like #70700 added that check, which happens while analyzing the gdscript, so if guards don't matter there.

I'm still experimenting, hoping I can find an easy fix or workaround...

@baptr
Copy link
Contributor

baptr commented Feb 27, 2023

Ah:

bool ClassDB::can_instantiate(const StringName &p_class) {
OBJTYPE_RLOCK;
ClassInfo *ti = classes.getptr(p_class);
ERR_FAIL_COND_V_MSG(!ti, false, "Cannot get class '" + String(p_class) + "'.");
#ifdef TOOLS_ENABLED
if (ti->api == API_EDITOR && !Engine::get_singleton()->is_editor_hint()) {
return false;

You can't instantiate any editor code while running.

@eh-jogos
Copy link
Author

eh-jogos commented Feb 27, 2023

I don't know think the problem is not allowing editor or "abstract" code to run while the game is running. I think the problem is considering EditorExportPlugin as an abstract class.

I mean, EditorPlugin works just fine when added as an activated plugin, and I don't get why EditorPlugin.new() would be used, creating an EditorPlugin instance that isn't added as a plugin doesn't make much sense as godot will not know how to use it, so the abstract error makes sense. But why doesn't EditorExportPlugin work?

To customize any exports through plugins I need to:

  • Be inside an existing and activated EditorPlugin
  • Create an instance of a script that extends EditorExportPlugin
  • add said instance using EditorPlugin's add_export_plugin()

The above will ALWAYS make problems with running the game, even though it is the required steps to make it work for filtering exports. This is what makes no sense to me and makes it impossible to use EditorExportPlugin, not the abstract class thing in itself.

In 3.x I could just do the same steps above and run the game just fine. I think this is a regression #73525, and EditorExportPlugin, despite it's name, shouldn't be considered an abstract class, or should be allowed somehow.

@baptr
Copy link
Contributor

baptr commented Feb 27, 2023

See #74025 - the check is trying to use !can_instantiate to infer whether the base class is abstract. But due to the check mentioned above, that fails for EditorExportPlugin (and any other API_EDITOR code).

@eh-jogos
Copy link
Author

So EditorExportPlugin isn't actually an abstract class? it's just being misinterpreted as one?

I had looked at #74025 but I guess I didn't understood what it was doing, so I got confused by how it would fix the problem which led to the comment above.

@baptr
Copy link
Contributor

baptr commented Feb 27, 2023

Right, it's registered as a normal full class:

GDREGISTER_CLASS(EditorExportPlugin);

But the recently added gdscript analyzer check which tries to determine if a parent class is abstract, instead only checks if it can be instantiated right now. The fact that editor types can't be instantiated when running the project leads to the analyzer incorrectly interpreting them as being "abstract".

@eh-jogos
Copy link
Author

Thanks a lot for explaining!

@akien-mga akien-mga added this to the 4.1 milestone Feb 27, 2023
baptr added a commit to baptr/godot that referenced this issue Mar 1, 2023
Editor code is not instantiable outside of the editor
(https://github.com/godotengine/godot/blob/1d14c054a12dacdc193b589e4afb0ef319ee2aae/core/object/class_db.cpp#L369).
This is fine for editor plugins and the like, but the GDScript analyzer
balks at it, causing F5 runs to fail: godotengine#73525.

Instead, we really just want to know if the type is abstract - so add
a new ClassDB method to check that and nothing else.
@Zylann
Copy link
Contributor

Zylann commented Mar 19, 2023

I have this problem too:

static func create_open_file_dialog() -> ConfirmationDialog:
	var d
	if Engine.is_editor_hint():
		d = EditorFileDialog.new()
		d.file_mode = EditorFileDialog.FILE_MODE_OPEN_FILE
		d.access = EditorFileDialog.ACCESS_RESOURCES
	else:
		d = FileDialog.new()
		d.file_mode = FileDialog.FILE_MODE_OPEN_FILE
		d.access = FileDialog.ACCESS_RESOURCES
	d.resizable = true
	return d

I was using this in Godot 3 so I could test my plugin UIs with F5 like regular "game scenes", but now Godot 4 complains of the only presence of EditorFileDialog even if the code never reaches it.

@apples
Copy link
Contributor

apples commented May 6, 2023

Meanwhile, a workaround:

Casting the EditorExportPlugin-derived class to a Variant seems to trick the compiler:

	if Engine.is_editor_hint():
		_exporter = (GitVersionInjector as Variant).new()
		add_export_plugin(_exporter)

Presumably this would also work with other classes that might have this issue.

@ozqf
Copy link

ozqf commented Jun 15, 2023

Casting the EditorExportPlugin-derived class to a Variant seems to trick the compiler:

Ran into this issue extending EditorNode3DGizmoPlugin so can confirm it works with that too.

@chrisb123
Copy link

EditorDebuggerPlugin seems to suffer the same issue and the same workaround

@Zylann
Copy link
Contributor

Zylann commented Jun 25, 2023

@chrisb123 are you trying to run a scene of the plugin? Or just your game? (If the latter it doesn't make any sense)

@chrisb123
Copy link

chrisb123 commented Jun 25, 2023

I'm using the example from the official documentation found here.

I cant find any other information on using the editor debug plugin. I get the same error mentioned above and applying the fix found above does result in the debugger getting a custom debug plugin tab
_exporter = (GitVersionInjector as Variant).new()

@Zylann
Copy link
Contributor

Zylann commented Jun 25, 2023

Oh sorry, I thought you were using the GDScript addon of the same name.

@YuriSizov
Copy link
Contributor

So the issue here is that user scripts end up trying to access Editor-only classes at runtime?

@YuriSizov YuriSizov removed this from the 4.1 milestone Jun 26, 2023
@YuriSizov YuriSizov added this to the 4.2 milestone Jun 26, 2023
@apples
Copy link
Contributor

apples commented Jun 28, 2023

So the issue here is that user scripts end up trying to access Editor-only classes at runtime?

In my project, I'm not actually accessing the Editor-only classes during game runtime. However, my scripts are still loaded/parsed, and the compiler complains about it. The script code is never executed.

At least, this is what I believe to be happening, based on the fact that casting the Editor-only class to a Variant fixes the compile error, and there are no further errors during runtime.

@MikeSchulze
Copy link

If there is a chance to bring the fix in 4.3?

From the documentation, it is not abstract.
This blocks me actually to develop and test the scene and often needs a restart of the Godot editor.
It also blocks me to write unit tests because the scene is loaded via a test API and not instantiated by a plugin.

@AThousandShips
Copy link
Member

If you're able please test the linked PR to help it along:

@MikeSchulze
Copy link

MikeSchulze commented Jul 2, 2024

If you're able please test the linked PR to help it along:

I had never built the Godot binary yet, I need first to setup my environment ...

@AThousandShips I have setup my build env under windows

uses master branch

D:\development\workspace\godot>scoop list
Installed apps:

Name   Version            Source Updated             Info
----   -------            ------ -------             ----
7zip   23.01              main   2024-02-10 09:28:27
dark   3.14               main   2024-07-03 06:42:42
gcc    13.2.0             main   2024-07-03 06:41:37
make   4.4.1              main   2024-07-03 06:41:39
mingw  13.2.0-rt_v11-rev1 main   2024-07-03 06:42:40
nodejs 21.6.1             main   2024-02-10 09:28:37
python 3.12.4             main   2024-07-03 06:43:07
scons  4.7.0              main   2024-07-03 06:43:09

when I run scons platform=windows use_mingw=yes
I get the error

[ 18%] Linking Static Library modules\libmodule_lightmapper_rd.windows.editor.x86_64.a ...
[ 18%] ERROR: C:/Users/mikes/scoop/apps/mingw/13.2.0-rt_v11-rev1/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ranlib.exe: could not create temporary file whilst writing archive: no more archived files

Any ideas?

@AThousandShips
Copy link
Member

Not familiar with that error, are you low on storage space?

@MikeSchulze
Copy link

Not familiar with that error, are you low on storage space?

So after a lot of investigation, I find out it was a local firewall Comodo issue ... what the hell

@MikeSchulze
Copy link

MikeSchulze commented Jul 3, 2024

I build Godot rebased on master and run the example project

EditorSpinSlider.zip

The parse error Parser Error: Native class "EditorSpinSlider" cannot be constructed as it is abstract. is gone but the components still not usable in a testing scene as described in #93854.

It produces errors
image

For my unit testing, this PR unblocks running my tests
image

@MikeSchulze
Copy link

@AThousandShips what would be the next steps to move forward here?

@AThousandShips
Copy link
Member

This specific issue is then resolved by this, the remaining isn't a bug IMO, editor classes are editor only, that should be a proposal instead I'd say, but not relevant for this issue report

@MikeSchulze
Copy link

fine, means this pr can be merged?

@AThousandShips
Copy link
Member

Yes, please comment on it that it solves the problem for you to help it along, it's still waiting for a decision

MikeSchulze pushed a commit to MikeSchulze/godot that referenced this issue Jul 10, 2024
Editor code is not instantiable outside of the editor
(https://github.com/godotengine/godot/blob/1d14c054a12dacdc193b589e4afb0ef319ee2aae/core/object/class_db.cpp#L369).
This is fine for editor plugins and the like, but the GDScript analyzer
balks at it, causing F5 runs to fail: godotengine#73525.

Instead, we really just want to know if the type is abstract - so add
a new ClassDB method to check that and nothing else.

Update core/object/class_db.cpp

Apply code review comments

Co-Authored-By: Bryce <[email protected]>
sorascode pushed a commit to sorascode/godot-soras-version that referenced this issue Jul 22, 2024
Editor code is not instantiable outside of the editor
(https://github.com/godotengine/godot/blob/1d14c054a12dacdc193b589e4afb0ef319ee2aae/core/object/class_db.cpp#L369).
This is fine for editor plugins and the like, but the GDScript analyzer
balks at it, causing F5 runs to fail: godotengine#73525.

Instead, we really just want to know if the type is abstract - so add
a new ClassDB method to check that and nothing else.

Update core/object/class_db.cpp

Apply code review comments

Co-Authored-By: Bryce <[email protected]>
Akeal pushed a commit to Akeal/godot that referenced this issue Jul 24, 2024
Editor code is not instantiable outside of the editor
(https://github.com/godotengine/godot/blob/1d14c054a12dacdc193b589e4afb0ef319ee2aae/core/object/class_db.cpp#L369).
This is fine for editor plugins and the like, but the GDScript analyzer
balks at it, causing F5 runs to fail: godotengine#73525.

Instead, we really just want to know if the type is abstract - so add
a new ClassDB method to check that and nothing else.

Update core/object/class_db.cpp

Apply code review comments

Co-Authored-By: Bryce <[email protected]>
Luis-Wong pushed a commit to Luis-Wong/godot that referenced this issue Jul 26, 2024
Editor code is not instantiable outside of the editor
(https://github.com/godotengine/godot/blob/1d14c054a12dacdc193b589e4afb0ef319ee2aae/core/object/class_db.cpp#L369).
This is fine for editor plugins and the like, but the GDScript analyzer
balks at it, causing F5 runs to fail: godotengine#73525.

Instead, we really just want to know if the type is abstract - so add
a new ClassDB method to check that and nothing else.

Update core/object/class_db.cpp

Apply code review comments

Co-Authored-By: Bryce <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment