tool class_name Transition, "transition.svg" extends Node ## cyclic reference workarounds :/ var _State = load("res://addons/godot_state_charts/state.gd") var _StateChart = load("res://addons/godot_state_charts/state_chart.gd") ## state to transition to export var to: NodePath ## event to react to for transition export var event: String ## delay before taking transition export var delay: float = 0.0 ## expression to determine whether to take transition ## if it returns true the transition will be taken ## expression properties added via the StateChart are available here ## if states are listed in `monitored_states`, they will be available as ## boolean properties named "[state]_active" export (String, MULTILINE) var guard_expression: String ## states to check if active ## they are available in the guard expression as bools named "[state]_active" export (Array, NodePath) var checked_states: Array = [] ## returns true if the transition has an event to react to func has_event() -> bool: return event != null and not event.empty() ## returns the target state func resolve_target(): if to == null or to.is_empty(): return null var target = get_node_or_null(to) if target is _State: return target return null ## returns true if the transition should be taken at this time func evaluate_guard() -> bool: # return true if there is no guard if guard_expression == null or guard_expression.empty(): return true # find root StateChart var root = get_parent() while is_instance_valid(root) and not root is _StateChart: root = root.get_parent() if not is_instance_valid(root): push_error("could not find root StateChart, cannot evaluate expression") return false # combine monitored states with expression properties var properties: Dictionary = root._expression_properties.duplicate() for node in checked_states: var state = get_node_or_null(node) if is_instance_valid(state) and state is _State: properties["in_" + state.name] = state.active # construct expression and set up properties var expression := Expression.new() var input_names = properties.keys() # attempt to parse expression var parse_result = expression.parse(guard_expression, input_names) if parse_result != OK: push_error("error parsing expression: " + expression.get_error_text()) return false # create array of input values var input_values = [] for input_name in input_names: input_values.append(properties[input_name]) # execute expression and validate result var result = expression.execute(input_values) if expression.has_execute_failed(): push_error("failed to execute expression: " + expression.get_error_text()) return false if typeof(result) != TYPE_BOOL: push_error("result is not a boolean value. returning false") return false return result