hello,
In a plugIN when getting the editor viewPort image... nothing is showing UP ?

@tool
extends Node2D


var toolCheck: int = 1;
var SelctRect = Rect2(0, 0, 0, 0 );
var SelctImg;
var SelctText;


func _process(delta):

		if ( toolCheck == 1 ):
			var Select_mXG = snapped(  get_local_mouse_position().x, 32 );
			var Select_mYG = snapped(  get_local_mouse_position().y, 32 );
			
			SelctRect = Rect2(Select_mXG, Select_mYG, 100, 100 );
			
			if ( Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) ):
				#SelctImg = EditorInterface.get_editor_viewport_2d().get_texture().get_image().get_region( SelctRect )
				SelctImg = EditorInterface.get_editor_viewport_2d().get_texture().get_image();
				SelctText = ImageTexture.new();
				SelctText.create_from_image(SelctImg)
				
				print( SelctImg )
				print( SelctText )
	




func _draw():

	if ( toolCheck == 1 ):
		draw_rect(SelctRect, Color.YELLOW, false, 2 ); #-- working fine
		
		if ( SelctText != null ):
			
			draw_texture(SelctText, get_local_mouse_position() ); #-- not working
			#print( SelctText ) 

The " draw_rect SelctRect " is drawing fine, but the image texture doesnt show anything..?!?!

heres the print:

<Image#-9223368290619808297>
<ImageTexture#-9223368290586253862>
<Image#-9223368280368929338>
<ImageTexture#-9223368280335374924>

It seems to have a texture inside...
it could be invisible ( blank image )... I cant figure it out ?

Is there a way to grab the image/texture being drawn in the Editor viewport2D ? ( godot editor main screen ) ??

  • xyz replied to this.
    • [deleted]

    • Best Answerset by jonSS

    jonSS Anyway, this is dragging too long and too wide. Your actual question from the title has been answered. And I additionally suggested several possible approaches for your overall problem. Mark the question answered and if you have another specific problem - start a new thread.

    jonSS Try awaiting for RenderingServer.frame_post_draw before getting the texture.

      xyz thanks... its working

      		if ( toolCheck == 1   ):
      			var Select_mXG = snapped(  get_local_mouse_position().x, 32 );
      			var Select_mYG = snapped(  get_local_mouse_position().y, 32 );
      			
      			SelctRect = Rect2(Select_mXG, Select_mYG, 100, 100 );
      			
      			if ( Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) ):
      				await RenderingServer.frame_post_draw;
      			
      				SelctImg = EditorInterface.get_editor_viewport_2d().get_texture().get_image();
      				SelctText = ImageTexture.create_from_image(SelctImg);
      
      
      func _draw():
      
      	if ( toolCheck == 1 && mouseInEditor == true ):
      		draw_rect(SelctRect, Color.YELLOW, false, 2 );
      		if ( SelctText != null ):
      			draw_texture(SelctText, get_global_mouse_position() );

      but iam not sure the image is supposed to look like this ?
      Its looking like the obs studio screen

      The more times i mouse click on it, the bigger the funil/cone will get... ( 1 normal image, with multiple small images inside )

      • xyz replied to this.

        jonSS Well if you capture the viewport and then draw that capture scaled into the same viewport and repeat this multiple times in succession - you'll end up precisely with what your screenshot shows.

          xyz But i cant clean the image...?
          The 1st mouse click the image is normal... then it starts showing more miniImages has more moouse clicks are added...

          I set it to null but the result is same... i cant clean the image ?

          var toolCheck: int = 0;
          var SelctRect = Rect2(0, 0, 0, 0 );
          var SelctImg;
          var SelctText;
          var SelctPress: bool = true;
          
          
          func _process(delta):
          
          		if ( toolCheck == 1   ):
          			var Select_mXG = snapped(  get_local_mouse_position().x, 32 );
          			var Select_mYG = snapped(  get_local_mouse_position().y, 32 );
          			SelctRect = Rect2(Select_mXG, Select_mYG, 100, 100 );
          			
          			if ( Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) && SelctPress == true ):
          				await RenderingServer.frame_post_draw;
          				
          				if ( SelctImg != null ):
          					SelctImg = null;
          				
          				SelctImg = EditorInterface.get_editor_viewport_2d().get_texture().get_image();
          				SelctText = ImageTexture.create_from_image(SelctImg);
          				SelctPress = false;
          
          			elif ( ! Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) && SelctPress == false ):
          				SelctPress = true;
          
          
          func _draw():
          	if ( toolCheck == 1 && mouseInEditor == true ):
          		draw_rect(SelctRect, Color.YELLOW, false, 2 );
          		if ( SelctText != null ):
          			draw_texture(SelctText, get_global_mouse_position() );

          [ edit ] And i think hes is capturing the wrong viewPort
          When using the draw func with @tool... He draws behind all the strokes and rect boxes in the editor ?
          The captured image shows everything strokes / rect boxes, etc..

          • xyz replied to this.

            jonSS You capture the whole viewport. That includes the image you've drawn on it of the previous capture of the viewport. It's recursive so you end up with the recursive looking result.

              xyz thanks i already got it working... ( managed to set the vars to null ), but had to use 2 awaits or i would get a white square were the prev image used to be...

              			if ( Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) && SelctPress == true ):
              				await RenderingServer.frame_post_draw;
              				SelctImg = null;
              				SelctText = null;
              				await RenderingServer.frame_post_draw;
              				
              				SelctImg = EditorInterface.get_editor_viewport_2d().get_texture().get_image();
              				SelctText = ImageTexture.create_from_image(SelctImg);
              				SelctPress = false;
              
              			elif ( ! Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) && SelctPress == false ):
              				SelctPress = true;

              But is there a way to capture the view of just 1 node ?
              Hes capturing the BORDERS from a camera2D... this is going to be a nightmare, if more nodes with drawings are added to the tree...

              Is there a way to get the entire draw func has one single image ?

              • xyz replied to this.

                xyz its a selection tool, simillar to photoshop selection when copying parts of an image.

                but i got it working... "get_viewport()" seems to work instead of " EditorInterface.get_editor_viewport_2d() "
                this way he no longer captures the other nodes

                		if ( toolCheck == 1  ):
                			var Select_mXG = snapped(  get_local_mouse_position().x, 32 );
                			var Select_mYG = snapped(  get_local_mouse_position().y, 32 );
                			
                			SelctRect = Rect2(Select_mXG, Select_mYG, 100, 100 );
                			
                			if ( Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) && SelctPress == true ):
                				await RenderingServer.frame_post_draw;
                				SelctImg = null;
                				SelctText = null;
                				await RenderingServer.frame_post_draw;
                				
                				#SelctImg = EditorInterface.get_editor_viewport_2d().get_texture().get_image();
                				SelctImg = get_viewport().get_texture().get_image();
                				SelctText = ImageTexture.create_from_image(SelctImg);
                				SelctPress = false;
                
                			elif ( ! Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) && SelctPress == false ):
                				SelctPress = true;
                • xyz replied to this.

                  jonSS Why would you need viewport pixels for a selection tool? What exactly is getting selected there and for what purpose?

                    xyz theres a yellow square on screen ( SelctRect = Rect2(Select_mXG, Select_mYG, 100, 100 ); )
                    I wanted to copy that portion of the image in the editor

                    Iam testing frist with the entire image...
                    But i just notice when he copies the image its smaller or bigger depending on the editor zoom level
                    so this is not going to work

                    • xyz replied to this.

                      jonSS I wanted to copy that portion of the image in the editor

                      Yeah but for what purpose? If you're only selecting tiles you don't need to mess with viewport pixels whatsoever.

                        xyz the tiles are inside a dictionary... Each Lnum corresponds to a layer

                        var layers = {
                        	'Lnum': [ {} ]
                        }

                        Once they are drawn on the editor screen i dont know how to fetch them ?
                        In the plugIN editor window ( right side ) when iam grabbing tiles from the image, iam using this:

                        mouse_tex = ImageTexture.create_from_image(texture.get_image().get_region( absRect ) );

                        Iam copying a region of the image.
                        Then breaking it into pieces once the user presses or moves the mouse

                        	if ( Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) && mouseJustPress == false ):
                        		mouseGroup.Fnum.clear();
                        		
                        		for i in range(0, drawText.get_image().get_size().x,32 ):
                        			for j in range(0,  drawText.get_image().get_size().y, 32):
                        				
                        				mouseGroup.Fnum.append(  { "cords": Vector2(i, j), "img": ImageTexture.create_from_image(drawText.get_image().get_region( Rect2( i, j, 32, 32) ) ) } );
                        		
                        	if ( ! Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) && mouseJustPress == true ):
                        		mouseJustPress = false;
                        		eraseCheck = true;

                        I dont know how to fecth tiles from a dictionary, and i dont think its possible they are all scattered.

                        The mouse icon is the image region, and its the order in witch the tiles must drawn.
                        Once they are drawn in the editor

                        func _draw():
                        	
                        	for p in range(0, layerMax ):
                        		for i in layers.Lnum[p]:
                        			if ( layers.Lnum[p].has(i) ):
                        				draw_texture( layers.Lnum[p][i], i );

                        i can delete them or replace them using the dictionary key.

                        • xyz replied to this.

                          jonSS Looks like you're severely misguided here. What do you hold inside those arrays for each dictionary entry? What are those tiles represented by? They should normally be represented by coordinates and your selection box should be a bounding box. Then you iterate through your tiles and select those whose coordinates fall inside your selection bounding box.

                          Viewport snapshots have no business here.

                            xyz yeah...lol, That looks easy, but i will need another dictionary/array to display those tiles on the mouse icon... This way i only need to display an image... And the problems would start to pile....
                            How would i flip/rotate and entire array of tiles ? An image ( mouse icon ) its less complicated.

                            The final result when running the game the tiles are converted to 1 big image.
                            The tiles in the editor also need to be converted to 1 big image, then broken into pieces:

                            I need that in the editor to add special effects like blur, or pixelatte for far backGrounds and foreGrounds ( Hollow Knight ) its something noONe will ever be able to do in the current 2Dgodot4 tileSet

                            this is basically a drawing program, like photoshop... it just breaks the images into tiles ( pieces ).
                            I know using viewPorts would be easier, but i wanted to get this one working frist before starting to improving on a new one.

                            • xyz replied to this.

                              jonSS You still haven't answered what data you hold in the array/dictionary per each tile.

                              Judging from this question and your previous question that got disrupted by DaveTheCopyPaster's meltdown over my AI remark, it looks like you have some fundamental lack of of understanding of how arrays and dictionaries actually work, and how to effectively utilize them to store, manage and process your data. Both of those questions are actually the infamous XY problem questions where you got stuck in a wrong alley with your attempted solution instead of describing the actual problem you need to solve.

                              Imo you might be getting a little bit ahead of yourself by attempting to write a plugin before having developed some solid intuition on how to aptly juggle arrays and dicts.

                                xyz No... i hate working with dictionaries and arrays in this situation, and i wish i didnt had to do this...
                                the dictionary values ive showed it above... I cant really rebember anymore but i will try...

                                I had to make "Lnum" an array so i could use multiple layers:
                                Lnum[0]: layer 0
                                Lnum[1]: layer 1
                                and so on...

                                "Lnum" adds more values( layers[] ) right at the beginning, This is done in the inpector plugIN, with the itemList

                                	var listSize = itmListLayer.get_item_count();
                                	for n in range( listSize-1 ):
                                		if ( PlugTileDrawNode.layers.Lnum.size() <  listSize  ):
                                			PlugTileDrawNode.layers.Lnum.append( {} ); 

                                it looks like this:
                                var layers = {
                                'Lnum': [ {},{},{} ] # itemList has 3 items
                                }

                                the dictionary inside the array: Holds the vector2 coordinates ( its the key "cords" ) and the value ( "img" ) its a 32x32 image.
                                The dictionary is being filled on 1 go ( 1 mouse click )

                                		for i in range(0, drawText.get_image().get_size().x,32 ):
                                			for j in range(0,  drawText.get_image().get_size().y, 32):
                                				
                                				mouseGroup.Fnum.append(  { "cords": Vector2(i, j), "img": ImageTexture.create_from_image(drawText.get_image().get_region( Rect2( i, j, 32, 32) ) ) } )

                                Its very dificult to understand but that last part "img": its the value inside the dictionary

                                print( layers.Lnum );
                                [{ (128, 96): <ImageTexture#-9223369173520790977>, (128, 128): <ImageTexture#-9223369173470459328>, (128, 160): <ImageTexture#-9223369173420127679>, (128, 192): <ImageTexture#-9223369173369796030>, (128, 224): <ImageTexture#-9223369173319464381>, (160, 96): <ImageTexture#-9223369172816147891>, (160, 128): <ImageTexture#-9223369172765816242>, (160, 160): <ImageTexture#-9223369172715484593>, (160, 192): <ImageTexture#-9223369172665152944>, (160, 224): <ImageTexture#-9223369172614821295>, (192, 96): <ImageTexture#-9223369172111504805>, (192, 128): <ImageTexture#-9223369172061173156>, (192, 160): <ImageTexture#-9223369172010841507>, (192, 192): <ImageTexture#-9223369171960509858>, (192, 224): <ImageTexture#-9223369171910178209>, (224, 96): <ImageTexture#-9223369171406861719>, (224, 128): <ImageTexture#-9223369171356530070>, (224, 160): <ImageTexture#-9223369171306198421>, (224, 192): <ImageTexture#-9223369171255866772>, (224, 224): <ImageTexture#-9223369171205535123>, (128, 256): <ImageTexture#-9223369173269132732>, (128, 288): <ImageTexture#-9223369173218801083>, (128, 320): <ImageTexture#-9223369173168469434>, (160, 256): <ImageTexture#-9223369172564489646>, (160, 288): <ImageTexture#-9223369172514157997>, (160, 320): <ImageTexture#-9223369172463826348>, (192, 256): <ImageTexture#-9223369171859846560>, (192, 288): <ImageTexture#-9223369171809514911>, (192, 320): <ImageTexture#-9223369171759183262>, (224, 256): <ImageTexture#-9223369171155203474>, (224, 288): <ImageTexture#-9223369171104871825>, (224, 320): <ImageTexture#-9223369171054540176>, (64, 96): <ImageTexture#-9223369174930077374>, (64, 128): <ImageTexture#-9223369174879745615>, (64, 160): <ImageTexture#-9223369174829413972>, (64, 192): <ImageTexture#-9223369174779082323>, (64, 224): <ImageTexture#-9223369174728750674>, (64, 256): <ImageTexture#-9223369174678419025>, (64, 288): <ImageTexture#-9223369174628087643>, (64, 320): <ImageTexture#-9223369174577755723>, (64, 352): <ImageTexture#-9223369174527424361>, (64, 384): <ImageTexture#-9223369174477092308>, (64, 416): <ImageTexture#-9223369174426760659>, (64, 448): <ImageTexture#-9223369174376429010>, (64, 480): <ImageTexture#-9223369174326097361>, (64, 512): <ImageTexture#-9223369174275765712>, (96, 96): <ImageTexture#-9223369174225434063>, (96, 128): <ImageTexture#-9223369174175102414>, (96, 160): <ImageTexture#-9223369174124770765>, (96, 192): <ImageTexture#-9223369174074439116>, (96, 224): <ImageTexture#-9223369174024107467>, (96, 256): <ImageTexture#-9223369173973775818>, (96, 288): <ImageTexture#-9223369173923444169>, (96, 320): <ImageTexture#-9223369173873112520>, (96, 352): <ImageTexture#-9223369173822780871>, (96, 384): <ImageTexture#-9223369173772449222>, (96, 416): <ImageTexture#-9223369173722117573>, (96, 448): <ImageTexture#-9223369173671785924>, (96, 480): <ImageTexture#-9223369173621454275>, (96, 512): <ImageTexture#-9223369173571122626>, (128, 352): <ImageTexture#-9223369173118137785>, (128, 384): <ImageTexture#-9223369173067806136>, (128, 416): <ImageTexture#-9223369173017474487>, (128, 448): <ImageTexture#-9223369172967142838>, (128, 480): <ImageTexture#-9223369172916811189>, (128, 512): <ImageTexture#-9223369172866479540>, (160, 352): <ImageTexture#-9223369172413494699>, (160, 384): <ImageTexture#-9223369172363163050>, (160, 416): <ImageTexture#-9223369172312831401>, (160, 448): <ImageTexture#-9223369172262499752>, (160, 480): <ImageTexture#-9223369172212168103>, (160, 512): <ImageTexture#-9223369172161836454>, (192, 352): <ImageTexture#-9223369171708851613>, (192, 384): <ImageTexture#-9223369171658519964>, (192, 416): <ImageTexture#-9223369171608188315>, (192, 448): <ImageTexture#-9223369171557856666>, (192, 480): <ImageTexture#-9223369171507525017>, (192, 512): <ImageTexture#-9223369171457193368>, (224, 352): <ImageTexture#-9223369171004208527>, (224, 384): <ImageTexture#-9223369170953876878>, (224, 416): <ImageTexture#-9223369170903545229>, (224, 448): <ImageTexture#-9223369170853213580>, (224, 480): <ImageTexture#-9223369170802881931>, (224, 512): <ImageTexture#-9223369170752550282>, (256, 96): <ImageTexture#-9223369170702218633>, (256, 128): <ImageTexture#-9223369170651886984>, (256, 160): <ImageTexture#-9223369170601555335>, (256, 192): <ImageTexture#-9223369170551223686>, (256, 224): <ImageTexture#-9223369170500892037>, (256, 256): <ImageTexture#-9223369170450560388>, (256, 288): <ImageTexture#-9223369170400228739>, (256, 320): <ImageTexture#-9223369170349897090>, (256, 352): <ImageTexture#-9223369170299565441>, (256, 384): <ImageTexture#-9223369170249233792>, (256, 416): <ImageTexture#-9223369170198902143>, (256, 448): <ImageTexture#-9223369170148570494>, (256, 480): <ImageTexture#-9223369170098238845>, (256, 512): <ImageTexture#-9223369170047907196>, (288, 96): <ImageTexture#-9223369169997575547>, (288, 128): <ImageTexture#-9223369169947243898>, (288, 160): <ImageTexture#-9223369169896912249>, (288, 192): <ImageTexture#-9223369169846580600>, (288, 224): <ImageTexture#-9223369169796248951>, (288, 256): <ImageTexture#-9223369169745917302>, (288, 288): <ImageTexture#-9223369169695585653>, (288, 320): <ImageTexture#-9223369169645254004>, (288, 352): <ImageTexture#-9223369169594922355>, (288, 384): <ImageTexture#-9223369169544590706>, (288, 416): <ImageTexture#-9223369169494259057>, (288, 448): <ImageTexture#-9223369169443927408>, (288, 480): <ImageTexture#-9223369169393595759>, (288, 512): <ImageTexture#-9223369169343264110>, (320, 96): <ImageTexture#-9223369169292932461>, (320, 128): <ImageTexture#-9223369169242600812>, (320, 160): <ImageTexture#-9223369169192269163>, (320, 192): <ImageTexture#-9223369169141937514>, (320, 224): <ImageTexture#-9223369169091605865>, (320, 256): <ImageTexture#-9223369169041274216>, (320, 288): <ImageTexture#-9223369168990942567>, (320, 320): <ImageTexture#-9223369168940610918>, (320, 352): <ImageTexture#-9223369168890279269>, (320, 384): <ImageTexture#-9223369168839947620>, (320, 416): <ImageTexture#-9223369168789615971>, (320, 448): <ImageTexture#-9223369168739284322>, (320, 480): <ImageTexture#-9223369168688952673>, (320, 512): <ImageTexture#-9223369168638621024> }, **{ }, { }**] layers 1 and 2 are empty i frogot to drawn something on them before making the print

                                I couldnt get this working any other way, by just using tiles i would not be able to add effects like Blur... Its has simple has in photoshop: You blur the image 50%, save it to png, open the image again and select pieces(32x32) of that image, and each piece transforms into a brush.. Then you draw with that brush.

                                • xyz replied to this.

                                  jonSS TileMap should be able to handle this. If you don't want to use it for whatever reason then you need to maintain your own data structure that works like a tile map. When you want to export the whole thing, use that data structure to blit all individual tile images stored in your custom "tile map" onto their proper positions in a big output image.

                                    xyz Iam not sure, do you think blit could group all the " Lnum " textures regions into one image... I cant understand whats writen in manual ( i think noone has ever used the blit functions )

                                    This could be done more easly by using the viewPort in the editor.
                                    I just dont know why in this case he always goes for the camera ? And camera coordinates ?
                                    If i want to take an image region of the editor viewPort. I have to drag the camera to x/y Zero and set the zoom to 100%.

                                    Isnt there a viewPortContainer in the editor, that has a camera that has a child viewPort ?
                                    cause of all the tries:

                                    SelctImg = get_viewport().get_texture().get_image().get_region( SelctRect );
                                    SelctImg = EditorInterface.get_editor_viewport_2d().get_texture().get_image().get_region( SelctRect );

                                    I cant get whats draw in the viewPort without the camera in the way...

                                    • xyz replied to this.

                                      jonSS That's not how things work.

                                      The only thing you can get from the main viewport are the literal pixels you see on the screen. There's no other data stored there. If something is "drawn" out of the screen, it gets clipped away. It doesn't exist for retrieval. If your view is zoomed, you get pixels of the zoomed image, etc... The main viewport is not a "viewport container" for some larger viewport that magically stores everything you draw at its maximal size.

                                      So if you want to reconstruct a full image of all existing tiles in your map, you'll have to maintain your own tilemap-like data structure that holds coordinates of all "drawn" tiles and references to their original image data, and then blit original image pixels into your final exported image. You can't retrieve that from just what's drawn on the screen, except in rare situations where everything you need is contained within the screen and zoomed exactly 1:1.

                                      Since Godot's TileMap maintains precisely such data structure (among other things), it's be best to just use that instead of reinventing the wheel by making your own clunkier version of it. Especially if you're not well versed in using and combining common data structures.