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

Add Node.is_being_edited() as an equivalent of Engine.is_editor_hint() for editor plugins #8216

Closed
ttencate opened this issue Oct 21, 2023 · 4 comments · Fixed by godotengine/godot#85515

Comments

@ttencate
Copy link

ttencate commented Oct 21, 2023

Describe the project you are working on

A bespoke editor plugin for my game.

Describe the problem or limitation you are having in your project

Plugin code needs to be marked with @tool in order to run in the editor.

However, this also causes the code to be run while editing a scene belonging to the plugin. This is often undesirable, because it makes changes to the scene which then get saved in the .tscn file.

For non-plugin scripts, Engine.is_editor_hint() is used to work around this. But in a plugin script, this function always returns true, even while the plugin is running "as a plugin" and is not being edited.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Since the node will be part of the same engine instance and scene tree, whether it's running as a plugin or running in the scene editor, a global function like Engine.is_editor_hint() won't be possible.

Instead, maybe a function on Node could be added, like is_being_edited().

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

is_being_edited() could look at the node's ancestors to find out whether the node is a descendant of the scene editor. I think that would be the CanvasItemEditor class in the current implementation, but this is not exposed in the API.

If this enhancement will not be used often, can it be worked around with a few lines of script?

Yes, I'm currently using something along these lines as a workaround, but it only works for main screen plugins:

    public static bool IsRunningAsPlugin(Node node)
    {
        foreach (var mainScreenChild in EditorInterface.Singleton.GetEditorMainScreen().GetChildren())
        {
            if (mainScreenChild is MyPluginMainPanel && mainScreenChild.IsAncestorOf(node))
            {
                return true;
            }
        }
        return false;
    }

Is there a reason why this should be core and not an add-on in the asset library?

Seems like many plugins that use scenes can benefit from this.

@ttencate
Copy link
Author

ttencate commented Oct 21, 2023

A cleaner workaround to detect whether the node is being edited, thanks to @kleonc:

if get_tree().edited_scene_root != null && get_tree().edited_scene_root in [self, owner]:

If this is deemed robust, it could be added as a helper function to the Node class in core.

@Calinou Calinou changed the title Something like Engine.is_editor_hint(), but for plugins Add Node.is_being_edited() as an equivalent of Engine.is_editor_hint() for editor plugins Oct 21, 2023
@KoBeWi
Copy link
Member

KoBeWi commented Oct 21, 2023

The method exists, it's just not exposed:
https://github.com/godotengine/godot/blob/6543495b49613d20f7e32f2b9d38e4a2f1d06db1/scene/main/node.cpp#L2386-L2389

@ttencate
Copy link
Author

ttencate commented Oct 21, 2023

I did not expect that 😁 It looks functionally equivalent to the above GDScript except it also checks Engine.is_editor_hint() (which seems redundant to me, but can't hurt).

And the name is_part_of_edited_scene is clearer than my suggestion is_being_edited.

It's guarded by #if TOOLS_ENABLED though. Will that be a problem?

@KoBeWi
Copy link
Member

KoBeWi commented Oct 21, 2023

It's guarded by #if TOOLS_ENABLED though. Will that be a problem?

If a script uses this method, it will have parse error after export. This applies to all editor plugins, so usually it's not a problem.
Although if there is a use-case for using such script in non-editor context, the method can be changed to instead always return true in exported project, instead of not existing.

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.

4 participants