Problem with draw_primitive and yield

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Oskar

I’m trying to draw points from a grid with pause between each pause.
My script:

func _draw():
	var center = Vector2(200, 200)
	var radius = 80
	var angle_from = 75
	var angle_to = 195
	var color = Color(1.0, 0.0, 0.0)
	draw_points(center, color)
func draw_points(center, color):
	var colorT = PoolColorArray( [Color(1, 1, 1)] ) 
    for index_point in range(NumberOfPoints):
		var point = PoolVector2Array( )
		draw_primitive(point, colorT, PoolVector2Array())
		yield(get_tree().create_timer(0.1), "timeout")

I get an error:

E 0:00:03.601   draw_primitive: Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.

If I remove yield everything is fine. Also yield is working in for loop if I’m not trying to use draw_primitive.
Can’t understand how to do it properly

:bust_in_silhouette: Reply From: avencherus

_draw() is a virtual function that is overridden. It is executed at a very specific time during the frame, because this is right before the rendering takes place.

When using a yield() it returns execution and everything is rendered. Returning anytime after this function happens wouldn’t be meaningful, the frame has already been rendered and moved on.

The backend timing is guarded by that error, which makes the program flow not consistent with what is typical in GDScript.

If you want to manipulate the points being drawn over time you will want to hold the points in an Array/Dictionary elsewhere, and modify them with yield(), timers, processing loops, and later call update() (Which queues _draw() to be called in the script).

The implementation of _draw() should then loop through the points that are available at that particular point in time.

A simple example below of an expected implementation, where a point disappears every second.

extends Node2D # v3.2.4

var pts = []

func _ready():

	for i in 50:
		pts.append(Vector2(randf() * 500.0, randf() * 500.0))

var t = 0.0

func _physics_process(delta: float) -> void:

	t += delta

	if( t >= 1.0):
		t -= 1.0



func _draw() -> void:

	for pt in pts:
		draw_circle(pt, 3.0,

Many thanks!

Oskar | 2020-11-11 09:01