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

Provide a keyword to differentiate between tool scripts and plugin code #900

Open
YuriSizov opened this issue May 26, 2020 · 3 comments
Open

Comments

@YuriSizov
Copy link
Contributor

YuriSizov commented May 26, 2020

Describe the project you are working on:
Various Editor UI plugins.

Describe the problem or limitation you are having in your project:
Due to the nature of the plugin implementation there is no guaranteed way to separate the code added with a plugin and running within plugin-added nodes from scripts in the tool mode. For a script to be able to execute in the editor environment it must be put in the tool mode. This is used for two distinct cases: to adjust how a scene is visible in the 3D/2D preview panel, and to make UI for editor plugins.

However, issues arise from the fact that the development of said plugins is performed in the same way the regular scenes are developed in: within the same editor and with the same tools. This means that each scene or node created by a plugin has a script attached that is automatically executed in the 3D/2D preview without any intention by developer to do so. There are tricks to guess if the scene is running as a part of a plugin, down to the blunt approach of exposing EditorPlugin instance to the whole added tree. But it's cumbersome and not natural. This also causes unexpected changes to the scenes for inexperienced developers and forces experienced ones to write more code to prevent this from happening in each and every node they implement.

See more reasoning and discussion in the original issue godotengine/godot#17592.
Also related: #520.

Describe the feature / enhancement and how it helps to overcome the problem or limitation:
There may be different ways to solve this problem, if we go deep enough. It is obvious that the issue is related to the way the plugins are implemented internally and a complete reinvention of the system may allow for a smarter and easier approach to solve this.

But as users we can suggest introduction of a new keyword, akin to tool. Let's say it is going to be called plugin. Adding such a word at the top of the script will allow it to be run by the editor within plugin code (or just editor UI in general), but not within the 3D/2D preview. This behavior should not overlap with the tool mode. Both keywords can be combined and used individually to achieve the desired behavior.

It would make sense to introduce an alternative to Engine.editor_hint as well, to allow some logic to happen only when in the editor environment, but not in a scene preview.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:
Since there are unlimited ways to introduce new UI to the editor by plugins (basically, any node can be used with an add_child call, and the editor would be none the wiser), we should probably concentrate on guarding such scripts from interacting with 3D/2D previews.

I'm not sure of any further details, but @RandomShaper was offering to implement his vision of the solution in godotengine/godot#17592, so maybe he can describe it in more detail.

If this enhancement will not be used often, can it be worked around with a few lines of script?:
This is extremely important for plugin developers, but out of our hands at this moment. No way to solve with any scripts, except for mentioned tricks to deduce needed conditions.

Is there a reason why this should be core and not an add-on in the asset library?:
It's a part of the plugin system.

@KoBeWi
Copy link
Member

KoBeWi commented Aug 26, 2023

Since recently, Node has a reliable way to check if it's a part of the edited scene:
https://github.com/godotengine/godot/blob/6da4ad16624484398331f393b503f8b5e2888c51/scene/main/node.cpp#L2367-L2370
It could be exposed as a workaround to the described problem.

@kitbdev
Copy link

kitbdev commented Nov 15, 2023

Here is a GDScript version of that method as a workaround:

func is_part_of_edited_scene():
	return Engine.is_editor_hint() && is_inside_tree() && get_tree().get_edited_scene_root() && (get_tree().get_edited_scene_root() == self || get_tree().get_edited_scene_root().is_ancestor_of(self))

Or as a static function so you don't need to have it in multiple scripts:

static func is_part_of_edited_scene(node: Node):
	return Engine.is_editor_hint() && node.is_inside_tree() && node.get_tree().get_edited_scene_root() && (node.get_tree().get_edited_scene_root() == node || node.get_tree().get_edited_scene_root().is_ancestor_of(node))

@Faless
Copy link

Faless commented Feb 26, 2024

I'm wondering if instead of adding a @plugin annotation it might make more sense to add a new method (or parameter) to PackedScene. Something like PackedScene.instantiate_as_editor_plugin() which will make all scripts in the scene behave as @tool.

The same way a @tool script instantiating another script will make it "inherits" the "@tool trait" (i.e. they get instantiated properly instead of using a placeholder like when going through PackedScene).

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

No branches or pull requests

5 participants