+1 vote

I'm currently exploring some Addon features (currently only working on GitHub HEAD version of Godot), and what I have in mind is to use a node2D Addon to draw directly on the 2D Edtior Viewport, without actually adding a node to the screen. How can I get the reference to the engine 2D Editor Viewport?

in Engine by (299 points)

2 Answers

+3 votes
Best answer

If you are working in C++, it's simple:

CanvasItemEditor::get_singleton()->get_viewport_control()

However, CanvasItemEditor is not directly accessible from GDScript, but you can use this trick to find it (may stop working in the future):

func find_viewport(node, recursive_level):
    if node.get_type() == "CanvasItemEditor":
        return node.get_child(1).get_child(0).get_child(1).get_child(1)
    else:
        recursive_level += 1
        if recursive_level > 15:
            return null
        for child in node.get_children():
            var result = find_viewport(child, recursive_level)
            if result != null:
                return result

Usage:

var editor_node = get_node("/root/EditorNode")
var viewport = find_viewport(editor_node, 0) # Returns null if not found

I took this method by Marcos Bitetti (which searches for SpatialEditorViewport) as base.

by (488 points)
edited by

That's a crazy workaround :D
Maybe an issue should be opened about exposing CanvasItemEditor to GDScript (at least for the EditorPlugin API)?

Yes, this workaround may stop working if the structure of CanvasItemEditor children changes. I agree some some of the built-in editor plugins should be exposed to GDScript.

It worked! But I guess I formulated my question kinda wrong, haha.
Now I can draw in the canvas 2D, but what I wanted is to create the lines in the world 2D - the idea would be drawing lines 'connecting' two sprites, for example. Is this possible using this workaround?

Thanks anyway, I don't think I would find a function like this without help!

I guess im implementing this addon with a wrong architecture in mind, haha. After trying a couple of times, now I understand why Path and Path2d are nodes. I think if I implement the data as a node like those, I can create an interface to work on it.

In Godot 3.2, this gives the error message:

Invalid call. Nonexistent function 'get_type' in base 'EditorNode'

However, "get_class" works.

0 votes

Maybe you can try this:

get_tree().get_root() # access via scenemainloop
get_node("/root") # access via absolute path

http://docs.godotengine.org/en/latest/tutorials/step_by_step/scene_tree.html#root-viewport

by (153 points)

I have to use "get_node("/root")" on the code too, thanks!

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.