GD-TaskManager/task.gd
2024-12-21 13:41:11 -05:00

88 lines
2.9 KiB
GDScript

## Task
##
## [color=yellow][b]Note:[/b] You probably won't be generating these yourself.
## Primarily intended to be generated and used by [TaskManager][/color].[br]
## A stateful task container, containing a list of functions.
class_name Task extends RefCounted
## Called when this task completes, emitting itself as [param task].
signal on_finished(task:Task)
## Nice name.
var name:String = ""
## List of queued commands.
var commands:Array[Callable] = []
## List of exit conditions. Any set to true will end this process.
var exit_conditions:Array[Callable] = [
func()->bool: return halt
]
## Internal tracker for showing what's running
var current_execution:int = 0
## Are we done yet?
var finished := false
## Are we paused?
var paused := false
## Are we flagged to stop when possible?
var halt := false
## Assign pause state to [param to_pause].
func set_pause(to_pause:bool)->void: paused = to_pause
## Assign pause state to [param to_pause] upon all [param tasks].
static func set_pause_many(tasks:Array[Task], to_pause:bool)->void:
tasks.map(func(t:Task): t.paused = to_pause)
## Initialize.[br]
## [param _name] Nice name.[br]
## [param _commands] List of commands.[br]
## [param exit_conds] List of functions that take 0 args and return boolean.
## if any of these are true when ticked, the task will terminate.
func _init(_name:String, _commands:Array[Callable], exit_conds:Array[Callable])->void:
name = _name
commands = _commands
for p_exit:Callable in exit_conds:
if p_exit.is_valid():
exit_conditions.append(p_exit)
## Execute all [member Task.commands]. Triggers [signal Task.on_finished] when complete.
func execute()->void:
finished = false
var _check_halt_conds := func(p:Callable)->bool: return p.call()
for index:int in commands.size():
if exit_conditions.any(_check_halt_conds):
break
while paused:
await Engine.get_main_loop().root.get_tree().process_frame
if exit_conditions.any(_check_halt_conds):
break
current_execution = index
await commands[index].call()
finished = true
on_finished.emit(self)
## Dump a string of [param task] and all functions in the queue.
static func dump_to_text(task:Task)->String:
var _name_out := "[%s]\n" % "Unnamed tasklist" \
if task.name.is_empty() else task.name
var _commands_out:String = ""
for index:int in task.commands.size():
var cmd := task.commands[index]
var _label_id := "[%s]%s" % [
str(index).pad_zeros(2),
">" if index == task.current_execution else ""]
var _broken := "" if cmd.is_valid() else "<Invalid Callable?>"
var _cmd_out := cmd.get_method() + "("
for arg in cmd.get_bound_arguments():
_cmd_out += str(arg) + ","
_cmd_out = _cmd_out.trim_suffix(",") + ")\n"
_commands_out += _label_id + _broken + _cmd_out
return _name_out + _commands_out
## Dump strings of all given [param tasks].
static func dump_commands(tasks:Array[Task])->Array[String]:
var task_text:Array[String] = []
task_text.assign(tasks.map(dump_to_text))
return task_text