|
|
|
|
Attention |
Topic was automatically imported from the old Question2Answer platform. |
|
Asked By |
Drewton8 |
I am trying to get a Timer to fire at a set interval, to be used in a progress bar whilst rescaling large images. All the other code works, but the Timer does not seem to fire whilst the CPU is busy processing an image.
As an example, in the sample code below, I was expecting the Timer callback to be executed whilst the for-loops are busy.
extends Node
var time_waster: float
var duration: float = 0.0
var timer: Timer
func _ready():
timer = Timer.new()
timer.set_wait_time(0.1)
timer.autostart = false
add_child(timer)
var _error = timer.connect("timeout", self, "_timeout")
print("Start")
timer.start()
for j in range(1,20):
print("J Loop----------------- ", j)
for i in range(1,2000000):
time_waster = log(i*j) # Waste some time
timer.stop()
print("End")
func _timeout():
duration += timer.wait_time
print("Timer call back: ",duration)
But the output when running the above code is …
Start
J Loop----------------- 1
J Loop----------------- 2
etc. until
End
The Timer does not fire at all whilst the loops are running ?
I do not see what I am doing incorrectly. Any help appreciated.
Thanks
|
|
|
|
Reply From: |
timothybrentwood |
I think because of all the calculation you are doing you’re not hitting an idle frame allowing the timer to increment. From the docs:
enum TimerProcessMode:
TIMER_PROCESS_PHYSICS = 0
Update the timer during the physics step at each frame (fixed framerate processing).
TIMER_PROCESS_IDLE = 1
Update the timer during the idle time at each frame.
For what you’re doing you should probably just use a TextureProgress
node and update it at the top of your for loop.
var progress_bar = TextureProgress.new()
self.add_child(progress_bar)
progress_bar.max_value = num_things_to_load
for i in range(num_things_to_load):
progress_bar.value = i
do_work_here()
Thank you for your answer. I had misunderstood when timers were called, thinking that they were events that ocurred independently of the process load.
I solved my problem by implementing the compute intensive part in a separate thread. The code below works as I originally was expecting, with an output of the form …
Starting thread
Start loop
1
2
Timer: 0.1
Timer: 0.2
…
…
9
Timer: 1.9
Timer: 2
Timer: 2.1
End loop
Timer: 2.2
Thread complete
END
extends Node
var load_time: float
var timer: Timer
var thread: Thread
var compute_complete: bool
signal thread_complete
func _ready():
load_time = 0.0
timer = Timer.new()
timer.set_wait_time(0.1)
add_child(timer)
var _error = timer.connect("timeout", self, "_on_Timer_timeout")
timer.start()
print("Starting thread")
thread = Thread.new()
thread.start(self,"_compute_function")
yield(self,"thread_complete")
print("Thread complete")
timer.stop()
print("END")
func _compute_function(userdata):
compute_complete = false
print("Start loop")
for j in range(1,10):
print(j)
for i in range(1,6000000):
var result = log(i*j)
print("End loop")
compute_complete = true
func _on_Timer_timeout():
load_time += timer.wait_time
print("Timer: ",load_time)
if compute_complete:
thread.wait_to_finish()
emit_signal("thread_complete")
Drewton8 | 2021-05-09 16:24