69 lines
1.8 KiB
GDScript
69 lines
1.8 KiB
GDScript
tool
|
|
class_name StateChart, "state_chart.svg"
|
|
extends Node
|
|
|
|
## whether chart should initialize on its own or be done manually
|
|
export var auto_initialize: bool = true
|
|
## whether chart should propagate processing events every frame
|
|
export var idle_frame_event: bool = false
|
|
export var physics_frame_event: bool = false
|
|
|
|
# root state of the state chart
|
|
var _state: State = null
|
|
|
|
# values available to expression guards
|
|
var _guard_properties: Dictionary = {}
|
|
|
|
func _ready() -> void:
|
|
if Engine.editor_hint:
|
|
return
|
|
if auto_initialize:
|
|
initialize()
|
|
|
|
func initialize() -> void:
|
|
# make sure only one child exists
|
|
if get_child_count() != 1:
|
|
push_error("StateChart must have exactly one child")
|
|
return
|
|
|
|
# verify child is a State
|
|
var child = get_child(0)
|
|
if not child is State:
|
|
push_error("StateChart's child must be a State")
|
|
return
|
|
|
|
# initialize states
|
|
_state = child as State
|
|
_state._state_init()
|
|
|
|
# enter root state
|
|
_state._state_enter()
|
|
|
|
## sends an event to be propagated through the states
|
|
func send_event(event: String) -> void:
|
|
if not is_instance_valid(_state):
|
|
push_error("StateChart is not initialized properly")
|
|
return
|
|
|
|
_state._state_event(event)
|
|
|
|
## sets a property available to guard expressions in transitions
|
|
func set_guard_property(property: String, value) -> void:
|
|
_guard_properties[property] = value
|
|
|
|
func _get_configuration_warning() -> String:
|
|
if get_child_count() != 1:
|
|
return "StateChart must have exactly one child"
|
|
if not get_child(0) is State:
|
|
return "StateChart's child must be a State"
|
|
return ""
|
|
|
|
# send frame events that transition can listen to if it should evaluate
|
|
# its guard every frame
|
|
func _process(delta: float) -> void:
|
|
if idle_frame_event:
|
|
send_event("idle_frame")
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
if physics_frame_event:
|
|
send_event("physics_frame")
|