87 lines
2.6 KiB
GDScript
87 lines
2.6 KiB
GDScript
@tool
|
|
@icon("transition.svg")
|
|
class_name Transition
|
|
extends Node
|
|
|
|
## Fired when this transition is taken. For delayed transitions, this signal
|
|
## will be fired when the transition is actually executed (e.g. when its delay
|
|
## has elapsed and the transition has not been arborted before). The signal will
|
|
## always be fired before the state is exited.
|
|
signal taken()
|
|
|
|
## The target state to which the transition should switch
|
|
@export_node_path("State") var to:NodePath:
|
|
set(value):
|
|
to = value
|
|
update_configuration_warnings()
|
|
|
|
## The event that should trigger this transition, can be empty in which case
|
|
## the transition will immediately be tried when the state is entered
|
|
@export var event:StringName = "":
|
|
set(value):
|
|
event = value
|
|
update_configuration_warnings()
|
|
|
|
## An expression that must evaluate to true for the transition to be taken. Can be
|
|
## empty in which case the transition will always be taken
|
|
@export var guard:Guard:
|
|
set(value):
|
|
guard = value
|
|
update_configuration_warnings()
|
|
|
|
## A delay in seconds before the transition is taken. Can be 0 in which case
|
|
## the transition will be taken immediately. The transition will only be taken
|
|
## if the state is still active when the delay has passed and has never been left.
|
|
@export var delay_seconds:float = 0.0:
|
|
set(value):
|
|
delay_seconds = value
|
|
update_configuration_warnings()
|
|
|
|
|
|
## Read-only property that returns true if the transition has an event specified.
|
|
var has_event:bool:
|
|
get:
|
|
return event != null and event.length() > 0
|
|
|
|
## Evaluates the guard expression and returns true if the transition should be taken.
|
|
## If no guard expression is specified, this function will always return true.
|
|
func evaluate_guard() -> bool:
|
|
if guard == null:
|
|
return true
|
|
|
|
var parent_state = get_parent()
|
|
if parent_state == null or not (parent_state is State):
|
|
push_error("Transitions must be children of states.")
|
|
return false
|
|
|
|
return guard.is_satisfied(self, get_parent())
|
|
|
|
## Resolves the target state and returns it. If the target state is not found,
|
|
## this function will return null.
|
|
func resolve_target() -> State:
|
|
if to == null or to.is_empty():
|
|
return null
|
|
|
|
var result = get_node_or_null(to)
|
|
if result is State:
|
|
return result
|
|
|
|
return null
|
|
|
|
|
|
func _get_configuration_warnings():
|
|
var warnings = []
|
|
if get_child_count() > 0:
|
|
warnings.append("Transitions should not have children")
|
|
|
|
if to == null or to.is_empty():
|
|
warnings.append("The target state is not set")
|
|
elif resolve_target() == null:
|
|
warnings.append("The target state " + str(to) + " could not be found")
|
|
|
|
if not (get_parent() is State):
|
|
warnings.append("Transitions must be children of states.")
|
|
|
|
return warnings
|
|
|