0 votes

Hello
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( )
        point.push_back(GridPoints[index_point])
        draw_primitive(point, colorT, PoolVector2Array())
        yield(get_tree().create_timer(0.1), "timeout")
        point.remove(0)

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

in Engine by (15 points)

1 Answer

0 votes
Best answer

_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

        pts.pop_back()
        update()

        if(pts.empty()):
            set_physics_process(false)



func _draw() -> void:

    for pt in pts:
        draw_circle(pt, 3.0, Color.red)
by (5,192 points)
selected by

Many 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.