statecharts ehehehehehe
This commit is contained in:
parent
4d59717b88
commit
6eff1601a9
23 changed files with 895 additions and 2 deletions
88
addons/godot_state_charts/transition.gd
Normal file
88
addons/godot_state_charts/transition.gd
Normal file
|
@ -0,0 +1,88 @@
|
|||
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
|
Loading…
Add table
Add a link
Reference in a new issue