godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
87.04k stars 19.54k forks source link

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

Closed eh-jogos closed 1 week ago

eh-jogos commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

Ah: https://github.com/godotengine/godot/blob/1d14c054a12dacdc193b589e4afb0ef319ee2aae/core/object/class_db.cpp#L363-L370

You can't instantiate any editor code while running.

eh-jogos commented 1 year ago

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:

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 commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

Right, it's registered as a normal full class: https://github.com/godotengine/godot/blob/2ec0da1a75a066fe88986fc6ceda22fbabf7eedd/editor/register_editor_types.cpp#L133

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 commented 1 year ago

Thanks a lot for explaining!

Zylann commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

EditorDebuggerPlugin seems to suffer the same issue and the same workaround

Zylann commented 1 year ago

@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 commented 1 year ago

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 commented 1 year ago

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

YuriSizov commented 1 year ago

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

apples commented 1 year ago

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 commented 3 weeks ago

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 commented 3 weeks ago

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

MikeSchulze commented 3 weeks ago

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 commented 2 weeks ago

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

MikeSchulze commented 2 weeks ago

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 commented 2 weeks ago

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 https://github.com/godotengine/godot/issues/93854.

It produces errors image

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

MikeSchulze commented 2 weeks ago

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

AThousandShips commented 2 weeks ago

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 commented 2 weeks ago

fine, means this pr can be merged?

AThousandShips commented 2 weeks ago

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