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

EditorPlugin singleton doesn't work #68685

Closed
TokisanGames opened this issue Nov 15, 2022 · 12 comments · Fixed by #75694
Closed

EditorPlugin singleton doesn't work #68685

TokisanGames opened this issue Nov 15, 2022 · 12 comments · Fixed by #75694

Comments

@TokisanGames
Copy link
Contributor

TokisanGames commented Nov 15, 2022

Godot version

Godot 4 Beta 4

System information

Windows 11/64, RTX 3070, Vulkan

Issue description

The EditorPlugin singleton doesn't work. Or the documentation needs to be updated.

The docs say this:

Note: This class shouldn't be instantiated directly. Instead, access the singleton using EditorPlugin.get_editor_interface.

However if I write:

var ei: EditorInterface = EditorPlugin.get_editor_interface()

The editor reports this:

SCRIPT ERROR: Parse Error: Cannot call non-static function "get_editor_interface()" on the class "EditorPlugin" directly. Make an instance instead. at: GDScript::reload (res://node_3d.gd:35)

So I either have to make a class derived from EditorPlugin, which I don't wish to as I just want the editor camera position. Or I have to do what the docs say to not do:

var ei: EditorInterface = EditorPlugin.new().get_editor_interface()

For my terrain system I want it updating based on camera position in the editor. I'm not writing an editor plugin. I just want the position. I wrote this code segment to get the editor cameras outside of an EP:
godotengine/godot-proposals#1302 (comment)

Steps to reproduce

n/a

Minimal reproduction project

No response

@YuriSizov
Copy link
Contributor

YuriSizov commented Nov 15, 2022

The docs say this:

The documentation states that the EditorInterface should not be instanced and that you should instead use a method of EditorPlugin to get an EditorInterface singleton. It doesn't imply or directly tell that there is supposed to be an EditorPlugin singleton. EditorPlugin, in fact, cannot be a singleton. (Though we could make the getter for EditorInterface static).

@TokisanGames
Copy link
Contributor Author

It literally says there is a singleton and how to access it. "Instead, access the singleton using EditorPlugin.get_editor_interface." If there isn't going to be a singleton, the docs need to change.

A static getter would be great. I don't care about the singleton, I just want the editor camera. Instancing a class to get it is unnecessary.

@YuriSizov
Copy link
Contributor

YuriSizov commented Nov 15, 2022

Yes, it literally says how to get an EditorInterface singleton, not an EditorPlugin singleton. It refers to a method of the EditorPlugin class to get the EditorInterface singleton. The EditorInterface has only one instance in the entire runtime, and is internally accessed using a singleton pattern. It is not exposed to the userland API as a named singleton, but it is still one. You just need to get a reference to it using a method of EditorPlugin.

The form ClassName.method_name is a standard way to refer to methods of another class. It doesn't mean that the other class should be used as a singleton.

@TokisanGames
Copy link
Contributor Author

Ah, I understand. You are right. It is confusing because it looks like it is giving a code example of accessing the EP singleton as is done on other classes like the servers.

@TokisanGames
Copy link
Contributor Author

TokisanGames commented Nov 15, 2022

I see in the code, EditorInterface has a singleton available. I attempted to retreive it from the engine
var ei: EditorInterface = Engine.get_singleton("EditorInterface")
However that says, Failed to retrieve non-existent singleton 'EditorInterface'.

I see EditorScript also provides the EditorInterface singleton, which also works and is a smaller class to instantiate.

Why not just expose the EditorInterface singleton directly rather than have two other classes hand it out?

I attempted to make the function in EditorPlugin static, but the engine wouldn't build, giving me problems with class_db.h. Is this an easy fix?

 In file included from ./core/object/ref_counted.h:34,
                 from ./core/io/file_access.h:36,
                 from ./core/io/config_file.h:34,
                 from editor/editor_plugin.h:34,
                 from editor/editor_plugin.cpp:31:
./core/object/class_db.h: In instantiation of 'static MethodBind* ClassDB::bind_method(N, M, VarArgs ...) [with N = MethodDefinition; M = EditorInterface* (*)(); VarArgs = {}]':
editor/editor_plugin.cpp:906:92:   required from here
./core/object/class_db.h:251:40: error: no matching function for call to 'create_method_bind(EditorInterface* (*&)())'
  251 |   MethodBind *bind = create_method_bind(p_method);
      |                      ~~~~~~~~~~~~~~~~~~^~~~~~~~~~
[ 68%] In file included from ./core/object/class_db.h:34,
                 from ./core/object/ref_counted.h:34,
                 from ./core/io/file_access.h:36,
                 from ./core/io/config_file.h:34,
                 from editor/editor_plugin.h:34,
                 from editor/editor_plugin.cpp:31:
./core/object/method_bind.h:341:13: note: candidate: 'template<class T, class ... P> MethodBind* create_method_bind(void (T::*)(P ...))'
  341 | MethodBind *create_method_bind(void (T::*p_method)(P...)) {
      |             ^~~~~~~~~~~~~~~~~~
[ 68%] ./core/object/method_bind.h:341:13: note:   template argument deduction/substitution failed:
[ 68%] In file included from ./core/object/ref_counted.h:34,
                 from ./core/io/file_access.h:36,
                 from ./core/io/config_file.h:34,
                 from editor/editor_plugin.h:34,
                 from editor/editor_plugin.cpp:31:
./core/object/class_db.h:251:40: note:   mismatched types 'void (T::*)(P ...)' and 'EditorInterface* (*)()'
  251 |   MethodBind *bind = create_method_bind(p_method);
      |                      ~~~~~~~~~~~~~~~~~~^~~~~~~~~~
[ 68%] In file included from ./core/object/class_db.h:34,
                 from ./core/object/ref_counted.h:34,
                 from ./core/io/file_access.h:36,
                 from ./core/io/config_file.h:34,
                 from editor/editor_plugin.h:34,
                 from editor/editor_plugin.cpp:31:
./core/object/method_bind.h:409:13: note: candidate: 'template<class T, class ... P> MethodBind* create_method_bind(void (T::*)(P ...) const)'
  409 | MethodBind *create_method_bind(void (T::*p_method)(P...) const) {
      |             ^~~~~~~~~~~~~~~~~~

@YuriSizov
Copy link
Contributor

Why not just expose the EditorInterface singleton directly rather than have two other classes hand it out?

Honestly, not sure why it wasn't exposed like that. I can guess that being an editor-only class having it as a global, named singleton may lead to problems with exported projects that rely on it. But can also be just how it was implemented many years ago for no particular reason.

We also don't really support interacting with the editor UI from tool scripts. It just works because the editor is just a set of controls and other nodes, and GDScript can run in editor. But the way I see the current system is designed, there was never an intention for you to do what you attempt to do without creating an editor plugin and putting your world building tools in there.

I attempted to make the function in EditorPlugin static, but the engine wouldn't build, giving me problems with class_db.h. Is this an easy fix?

The method needs to be bound to the API as static as well. You need to use ClassDB::bind_static_method instead of ClassDB::bind_method, at the very least.

@timothyqiu
Copy link
Member

EditorScript has the method get_editor_interface to get the EditorInterface singleton too.

@TokisanGames
Copy link
Contributor Author

Ok thank you, the bind_static_method helped. I'm currently making a PR to make these two functions static, and to expose the editor viewports, which in turn will provide access to the cameras as requested here godotengine/godot-proposals#1302

@MikeSchulze
Copy link

From the documentation:
image

but fails with Cannot call non-static function "get_editor_settings()" on the class "EditorInterface" directly. Make an instance instead.

@YuriSizov
Copy link
Contributor

Yes, that sample is incorrect.

@Owlmate-Julius
Copy link

It's over a year ago and the "incorrect" example is still there and confuses people like me who are looking to find a way to access the editor settings :(

@akien-mga
Copy link
Member

@Owlmate-Julius The example works as of 4.2 where EditorInterface is exposed as a singleton. Please keep in mind that it's an editor-only class, so it can only be access in the editor (@tool scripts, editor plugins). If it's used at runtime it will throw an error.

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.

6 participants