The title, basicaly.

I searched, and found something aboout using the RenderingServer, registering a RID, etc.

Maybe this is not the way.

I just want to use the _draw() class of funcs over the entire godot editor window.

I can get the root node of the editor with:
"EditorInterface.get_editor_viewport_2d().get_tree().root"

but i am laking the know how on how to register a _draw func

If i try to use:
"EditorInterface.get_editor_viewport_2d().get_tree().root.draw_circle(Vector2(100,100),100,Color.BLACK)"

i get "[...] Invalid call. Nonexistent function 'draw_circle' in base 'Window'."

and even more, this is a direct call of a draw function with would normaly return a:
"Drawing is only allowed inside this node's _draw(), functions connected to its draw signal, or when it receives NOTIFICATION_DRAW."

So, i am stuck in the process of the aprouch, how to achieve this?

Thanks for any insights.

  • jonSS and xyz replied to this.
  • PeterPM Ok, you got me there. This is perfectly doable.

    @tool
    extends Node2D
    
    func _ready():
    	var overlay = Control.new()
    	get_tree().get_root().add_child(overlay)
    	overlay.mouse_filter = Control.MOUSE_FILTER_IGNORE
    	overlay.draw.connect(
    		func():
    			overlay.size = get_tree().get_root().size
    			for i in 20:
    				overlay.draw_circle(Vector2(randf()*overlay.size.x, randf()*overlay.size.y), 100, Color.RED)
    	)

    I'll leave the above "skin" a permanent fixture in my editor.

    PeterPM the @tool node will draw on the editor
    Outside of it i think, if you use the editor viewport it will be drawing on top of the other things that are already there, ( like the screen viewRect Box, and the offset crosses )

    You need to do some checks frist on the mouse, for him to draw exacly on the editor, and not the other docks like inspector, scene, etc..

    @tool node (costum_sprite_node.gd)

    
    @tool
    extends Node2D
    
    var Atexture: Texture2D
    
    var mgX: float = 0.0;
    var mgY: float = 0.0;
    var mGpos: Vector2 = Vector2(0, 0);
    
    var viewMouse_position: Vector2 = Vector2(0, 0);
    var mouseInEditor: bool = false;
    
    
    func _notification(what):
    	if what == NOTIFICATION_ENTER_TREE:
    		if ( Atexture == null ):
    			Atexture = load("res://icon.svg");
    			print("enter tree Atexture was null set to: " + str(Atexture))
    			
    
    func _process(_delta):
    	
    	#----------------skips-if-mouse-not-on-the-center-of-editor-window---------------
    	#----------------skips-if-mouse-not-on-the-center-of-editor-window---------------
    	if ( Engine.is_editor_hint() ): 
    		var top_2D = EditorInterface.get_base_control().get_child(0).get_child(0).get_child(2).get_child(0)
    		var viewRect = EditorInterface.get_editor_main_screen().get_child(0).get_child(1).get_child(0).get_child(0).get_child(0).get_rect();
    		viewMouse_position = EditorInterface.get_editor_main_screen().get_child(0).get_child(1).get_local_mouse_position();
    		var mouseArr0w = Input.get_current_cursor_shape();
    		
    		if  Rect2(Vector2(), viewRect.size).has_point( viewMouse_position ) && top_2D.button_pressed == true && mouseArr0w == 0 && layers != null:
    			mouseInEditor = true;
    		else:
    			mouseInEditor = false;
    	
    	#---------------------------------------------------------
    	#---------------------------------------------------------
    	
    	if ( mouseInEditor == false ):
    		return;
    	
    	mgX = snapped(  get_global_mouse_position().x, 128 );
    	mgY = snapped(  get_global_mouse_position().y, 128 );
    	mGpos = Vector2 (mgX, mgY);
    	
    	queue_redraw();
    
    
    
    func _draw():
    	if ( Atexture == null ):
    		return
    	
    	draw_texture(Atexture, mGpos ); 

    Theres the problem when you click on the editor window everything will be deselected.
    you have to set visibility in the @tool node "EditorPlugin" script

    EditorPlugin

    @tool
    extends EditorPlugin
    
    
    const custom_sprite = preload("res://addons/sprite2DplugIN/custom_sprite_node.gd")
    const icon: Texture2D = preload("res://icon.svg")
    var myObj;
    
    func _enter_tree():
    	add_custom_type("CostumSprite2D", "Node2D", custom_sprite, icon );
    	
    
    #-myObj needs to always be visible when the user presses the editor interface
    #-otherwise the node the in plugIN handles gets deSelected, and nothing is selected
    func _forward_canvas_gui_input(event):
    	if (event is InputEventMouseButton ):
    		myObj.visible = true;
    		return true
    	pass;
    
    
    func _handles(object: Object) -> bool:
    	#return object is custom_sprite
    	if ( object is custom_sprite ):
    		myObj = object;
    		return true;
    	return false;
    
    
    func _exit_tree():
    	remove_custom_type("CustomSprite2D")

    PeterPM _draw() is implemented in CanvasItem. You can use it only on nodes that inherit that class. Viewport is not a canvas item. If you meant to draw over the entire editor window including all gui elements, as a one big canvas, I don't think you can do that without an intervention into engine's source code.

    @jonSS Your aprouch is somewhat convoluted, and includes several things not specified, can you please elaborate and make it as a minimal as possible? I just need to draw on the editor.

    @xyz And, yes. This is what i am trying to achieve, the entire editor as a big canvas, and some other sub windows.
    Indeed the Window or the Viewport class does not have a _draw.
    But, one can maybe get the children that is derived from a CanvasItem from the tree.

    print(EditorInterface.get_editor_viewport_2d().get_tree().root.get_child(0).get_children()) returns:

    Click to reveal Click to hide

    [@EditorPropertyNameProcessor@2:<EditorPropertyNameProcessor#24209523966>,
    @EditorFileSystem@3:<EditorFileSystem#25283265838>,
    @EditorExport@5:<EditorExport#25333597488>,
    @EditorResourcePreview@6:<EditorResourcePreview#61438167523>,
    @Panel@13:<Panel#61740157429>,
    @Timer@49:<Timer#63753423469>,
    @Timer@50:<Timer#63770200686>,
    @AudioStreamPreviewGenerator@7669:<AudioStreamPreviewGenerator#588075006539>,
    @DebuggerEditorPlugin@8282:<DebuggerEditorPlugin#588091783754>,
    @AnimationPlayerEditorPlugin@9088:<AnimationPlayerEditorPlugin#619465179447>,
    @AnimationTrackKeyEditEditorPlugin@9089:<AnimationTrackKeyEditEditorPlugin#657683679577>,
    @CanvasItemEditorPlugin@9273:<CanvasItemEditorPlugin#657717234011>,
    @Node3DEditorPlugin@9810:<Node3DEditorPlugin#670367255531>,
    @ScriptEditorPlugin@10561:<ScriptEditorPlugin#717192467488>,
    @AssetLibraryEditorPlugin@10915:<AssetLibraryEditorPlugin#761937305027>,
    @VersionControlEditorPlugin@11351:<VersionControlEditorPlugin#771953303514>,
    @AudioBusesEditorPlugin@11353:<AudioBusesEditorPlugin#792404730957>,
    @AnimationTreeEditorPlugin@12209:<AnimationTreeEditorPlugin#792421508172>,
    @AudioStreamEditorPlugin@12210:<AudioStreamEditorPlugin#829482380432>,
    @AudioStreamRandomizerEditorPlugin@12211:<AudioStreamRandomizerEditorPlugin#829515934866>,
    @BitMapEditorPlugin@12212:<BitMapEditorPlugin#829532712083>,
    @BoneMapEditorPlugin@12213:<BoneMapEditorPlugin#829566266517>,
    @Camera3DEditorPlugin@12214:<Camera3DEditorPlugin#829650152602>,
    @ControlEditorPlugin@12277:<ControlEditorPlugin#829666929819>,
    @CPUParticles3DEditorPlugin@12377:<CPUParticles3DEditorPlugin#832351284539>,
    @CurveEditorPlugin@12378:<CurveEditorPlugin#836780469812>,
    @DebugAdapterServer@12379:<DebugAdapterServer#836830801463>,
    @FontEditorPlugin@12380:<FontEditorPlugin#836914687548>,
    @GPUParticles3DEditorPlugin@12480:<GPUParticles3DEditorPlugin#836981796416>,
    @GPUParticlesCollisionSDF3DEditorPlugin@12626:<GPUParticlesCollisionSDF3DEditorPlugin#841410981689>,
    @GradientEditorPlugin@12627:<GradientEditorPlugin#847752769695>,
    @GradientTexture2DEditorPlugin@12628:<GradientTexture2DEditorPlugin#847786324128>,
    @InputEventEditorPlugin@12629:<InputEventEditorPlugin#847819878562>,
    @LightmapGIEditorPlugin@12774:<LightmapGIEditorPlugin#847853432996>,
    @MaterialEditorPlugin@12775:<MaterialEditorPlugin#854161666568>,
    @MeshEditorPlugin@12776:<MeshEditorPlugin#854228775435>,
    @MeshInstance3DEditorPlugin@12838:<MeshInstance3DEditorPlugin#854262329869>,
    @MeshLibraryEditorPlugin@13009:<MeshLibraryEditorPlugin#857835877060>,
    @MultiMeshEditorPlugin@13121:<MultiMeshEditorPlugin#867717657728>,
    @NavigationObstacle3DEditorPlugin@13127:<NavigationObstacle3DEditorPlugin#872515941781>,
    @OccluderInstance3DEditorPlugin@13272:<OccluderInstance3DEditorPlugin#872801154470>,
    @PackedSceneEditorPlugin@13273:<PackedSceneEditorPlugin#879109388042>,
    @Path3DEditorPlugin@13298:<Path3DEditorPlugin#879142942475>,
    @PhysicalBone3DEditorPlugin@13302:<PhysicalBone3DEditorPlugin#880753555302>,
    @Polygon3DEditorPlugin@13308:<Polygon3DEditorPlugin#880904550254>,
    @ResourcePreloaderEditorPlugin@13483:<ResourcePreloaderEditorPlugin#881189762943>,
    @ShaderEditorPlugin@13705:<ShaderEditorPlugin#888588515624>,
    @ShaderFileEditorPlugin@13721:<ShaderFileEditorPlugin#899292380017>,
    @Skeleton3DEditorPlugin@13722:<Skeleton3DEditorPlugin#899980245913>,
    @SkeletonIK3DEditorPlugin@13725:<SkeletonIK3DEditorPlugin#900215126946>,
    @SpriteFramesEditorPlugin@14171:<SpriteFramesEditorPlugin#900315790247>,
    @StyleBoxEditorPlugin@14172:<StyleBoxEditorPlugin#919928356867>,
    @SubViewportPreviewEditorPlugin@14173:<SubViewportPreviewEditorPlugin#919961911301>,
    @Texture3DEditorPlugin@14174:<Texture3DEditorPlugin#919995465735>,
    @TextureEditorPlugin@14175:<TextureEditorPlugin#920029020169>,
    @TextureLayeredEditorPlugin@14176:<TextureLayeredEditorPlugin#920062574603>,
    @TextureRegionEditorPlugin@14226:<TextureRegionEditorPlugin#920096129037>,
    @ThemeEditorPlugin@15089:<ThemeEditorPlugin#922176503937>,
    @VoxelGIEditorPlugin@15235:<VoxelGIEditorPlugin#962542487802>,
    @CollisionPolygon2DEditorPlugin@15250:<CollisionPolygon2DEditorPlugin#969437923968>,
    @CollisionShape2DEditorPlugin@15252:<CollisionShape2DEditorPlugin#969488255619>,
    @CPUParticles2DEditorPlugin@15424:<CPUParticles2DEditorPlugin#969538587270>,
    @GPUParticles2DEditorPlugin@15610:<GPUParticles2DEditorPlugin#981500742736>,
    @LightOccluder2DEditorPlugin@15625:<LightOccluder2DEditorPlugin#994637303390>,
    @Line2DEditorPlugin@15640:<Line2DEditorPlugin#995241283202>,
    @NavigationLink2DEditorPlugin@15642:<NavigationLink2DEditorPlugin#995291614853>,
    @NavigationObstacle2DEditorPlugin@15657:<NavigationObstacle2DEditorPlugin#995895594665>,
    @NavigationPolygonEditorPlugin@15684:<NavigationPolygonEditorPlugin#996969336553>,
    @ParallaxBackgroundEditorPlugin@15693:<ParallaxBackgroundEditorPlugin#997019668204>,
    @Path2DEditorPlugin@15717:<Path2DEditorPlugin#997455875845>,
    @Polygon2DEditorPlugin@15819:<Polygon2DEditorPlugin#1003361456212>,
    @Cast2DEditorPlugin@15821:<Cast2DEditorPlugin#1003411787863>,
    @Skeleton2DEditorPlugin@15837:<Skeleton2DEditorPlugin#1003462119514>,
    @Sprite2DEditorPlugin@15889:<Sprite2DEditorPlugin#1004317757575>,
    @TileSetEditorPlugin@16278:<TileSetEditorPlugin#1006733676811>,
    @TileMapEditorPlugin@16410:<TileMapEditorPlugin#1024936957184>,
    @EditorPluginCSG@16411:<EditorPluginCSG#1031295522407>,
    @SceneExporterGLTFPlugin@16558:<SceneExporterGLTFPlugin#1031966611078>,
    @GridMapEditorPlugin@16596:<GridMapEditorPlugin#1039432472582>,
    @AudioStreamInteractiveEditorPlugin@16662:<AudioStreamInteractiveEditorPlugin#1043039574190>,
    @MultiplayerEditorPlugin@16790:<MultiplayerEditorPlugin#1046462126443>,
    @NavigationMeshEditorPlugin@16804:<NavigationMeshEditorPlugin#1051730172576>,
    @NoiseEditorPlugin@16805:<NoiseEditorPlugin#1052267043520>,
    @GDScriptLanguageServer@16876:<GDScriptLanguageServer#1056041917336>,
    @EditorImportBlendRunner@16878:<EditorImportBlendRunner#1056243243940>,
    @Timer@16879:<Timer#1056461347761>,
    @Timer@16880:<Timer#1056494902194>,
    JointGizmoUpdateTimer:<Timer#1096626003317>,
    @EditorPlugin@17234:<EditorPlugin#1659820371926>]
    !<

    One of this nodes should contain the engine GUI, and it must be certanly a Control node.

    By getting that control node reference, then we can starting talking about calling _draw() inside it, ergo, on the full canvas of the editor itself.

    I will analise the output that represent the tree and try to find that node, but please, continue pondering about solution and post any here.


    By doing a reverse aprouch:

    EditorInterface.get_editor_viewport_2d().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent()

    gets me to the @Panel@13:<Panel#61740157429>, as doing one more get_parent() gets me to the same node as:
    print(EditorInterface.get_editor_viewport_2d().get_tree().root.get_child(0))
    So, it may be the panel that contains the full editor.


    Indeed it may be.

    var pane = EditorInterface.get_editor_viewport_2d().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent()
    pane.modulate = Color.RED

    tints the full engine editor red:

    But, as speculated, doing a
    pane.draw_circle(Vector2(100,100),100,Color.RED) return a:

    Drawing is only allowed inside this node's _draw(), functions connected to its draw signal, or when it receives NOTIFICATION_DRAW.

    Now, what?

    • xyz replied to this.

      PeterPM One of this nodes should contain the engine GUI

      Nope, I don't think so. Besides, 3D views are not canvas items either. You'll need to go much lower level and the editor itself won't let you go there. You can't go beyond the rendering server, and rendering server has no way of facilitating access to the whole window to draw on, especially not via canvas item class interface or canvas_item_*() calls on the rendering server. You'll need to mess with the source code.

      What's your actual goal with this? Why would you want to do something like this? Some kind of horror thing again, like the one where the engine pretends to delete your files. This is level 2 when the gui gets attacked as well? 😃

      If you want the complete overlay (e.g. Steam overlay) you'll need to do it the way they do it. Hook onto the running application from the outside and do some runtime library injecting. At least that's how it's done with OpenGL. I don't know it's there's a more elegant way with Vulkan but even if there is, it's unlikely you'll be able to pull it off simply by typing some GDScript code.

        xyz Actualy i found the Panel that contains the engine, now i need to register the _draw() funcs on that, because calling directly it is not possible.

        How to do that? Its already proved that its indeed the whole canvas, as the .modulate tinted the whole screen.
        Its something internal, not external, gdscript can be used.
        I think the hard part passed, i now need to know more about how to register the _draw() without pluging a whole script inside the Panel that hosts the editor interface. Or this will be the only way?

        And i need to do that beacuse i am extending the editor, and found what i think is a bug, and i need this to make a test case, that if reproduced, will be posted on github. luckly i am doing something wrong, because i really need the use case, and cant wait for fixages. but lest focus on enabling the _draw() on that suposed Panel that contains the editor. How to, given the context?

        • xyz replied to this.

          PeterPM You can't just take over drawing of built in canvas item classes. The engine is not made to allow that. You can only introduce a new canvas item class and implement custom drawing there by overriding the virtual function _draw(). As I already said, it should either be runtime injection or source code intervention.

            xyz No bro, i did it. 😃

            Click to reveal Click to hide

            @tool
            extends EditorPlugin

            var pane = EditorInterface.get_editor_viewport_2d().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent()
            func enter_tree():
            print(pane.connect("draw", Callable(self, "
            on_draw")))
            func _exit_tree():
            pass
            func _on_draw():
            pane.draw_circle(Vector2(100,100),100,Color.RED)
            func _process(delta):
            pane.modulate = Color.WHITE
            pane.queue_redraw()

            This made this:

            But, because its drawing on the parent node, the child are ocluding it. How to make draw be on top of the childs?

            • xyz replied to this.

              PeterPM But, because its drawing on the parent node, the child are ocluding it. How to make draw be on top of the childs?

              Seems you're the main hacker here. You tell us. 😃

                xyz Hahaha, just a scriptkiddie with acess to gpt. Maybe something with the z-index, but that may cause problens on the other subnodes.

                I tried to add a ColorRect to it, but it does not showd up.
                One thing that would be really cool to have on the engine, would be the "remote" tab when one have a project running, but instead, its the tree of the editor, now that would be very slashy to thinker.

                • xyz replied to this.

                  PeterPM One thing that would be really cool to have on the engine, would be the "remote" tab when one have a project running, but instead, its the tree of the editor, now that would be very slashy to thinker.

                  Make a plugin for that. It's actually quite easy to do.

                    xyz Why not. Will try investigate that latter, it would even help in this case right now.

                    But, its already kinda working, i need to understand if i can use the _draw() to be on top of other nodes, but it seens not.

                    But, thanks anyway, i solved it.

                    This works:

                    Click to reveal Click to hide

                    `@tool
                    extends EditorPlugin

                    var pane = EditorInterface.get_editor_viewport_2d().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent().get_parent()
                    var cc = Control.new()
                    func enter_tree():
                    var rot = pane.get_parent().get_parent()
                    rot.add_child(cc)
                    print(cc.connect("draw", Callable(self, "
                    on_draw")))

                    func _exit_tree():
                    cc.queue_free()
                    pass

                    func _on_draw():
                    var thesize = EditorInterface.get_editor_viewport_2d().get_parent().get_global_rect()
                    cc.draw_rect(thesize,Color.RED,false)

                    func _process(delta):
                    cc.modulate = Color.WHITE

                    cc.queue_redraw()`

                    Its the test case, i need sinc external objets to the the viewport, and it was missbehaving and not aligning, but is seens to be working now, i will go on and run my tests. Thanks. Solved, for now.

                    • xyz replied to this.

                      PeterPM Ok, you got me there. This is perfectly doable.

                      @tool
                      extends Node2D
                      
                      func _ready():
                      	var overlay = Control.new()
                      	get_tree().get_root().add_child(overlay)
                      	overlay.mouse_filter = Control.MOUSE_FILTER_IGNORE
                      	overlay.draw.connect(
                      		func():
                      			overlay.size = get_tree().get_root().size
                      			for i in 20:
                      				overlay.draw_circle(Vector2(randf()*overlay.size.x, randf()*overlay.size.y), 100, Color.RED)
                      	)

                      I'll leave the above "skin" a permanent fixture in my editor.