import the woofer
This commit is contained in:
parent
825fee53e2
commit
3e89acfea8
92 changed files with 5783 additions and 0 deletions
116
addons/godot_state_charts/parallel_state.gd
Normal file
116
addons/godot_state_charts/parallel_state.gd
Normal file
|
@ -0,0 +1,116 @@
|
|||
@tool
|
||||
@icon("parallel_state.svg")
|
||||
## A parallel state is a state which can have sub-states, all of which are active
|
||||
## when the parallel state is active.
|
||||
class_name ParallelState
|
||||
extends StateChartState
|
||||
|
||||
# all children of the state
|
||||
var _sub_states:Array[StateChartState] = []
|
||||
|
||||
func _state_init():
|
||||
super._state_init()
|
||||
# find all children of this state which are states
|
||||
for child in get_children():
|
||||
if child is StateChartState:
|
||||
_sub_states.append(child)
|
||||
child._state_init()
|
||||
|
||||
# since there is no state transitions between parallel states, we don't need to
|
||||
# subscribe to events from our children
|
||||
|
||||
|
||||
func _handle_transition(transition:Transition, source:StateChartState):
|
||||
# resolve the target state
|
||||
var target = transition.resolve_target()
|
||||
if not target is StateChartState:
|
||||
push_error("The target state '" + str(transition.to) + "' of the transition from '" + source.name + "' is not a state.")
|
||||
return
|
||||
|
||||
# the target state can be
|
||||
# 0. this state. in this case just activate the state and all its children.
|
||||
# this can happen when a child state transfers back to its parent state.
|
||||
# 1. a direct child of this state. this is the easy case in which
|
||||
# we will do nothing, because our direct children are always active.
|
||||
# 2. a descendant of this state. in this case we find the direct child which
|
||||
# is the ancestor of the target state and then ask it to perform
|
||||
# the transition.
|
||||
# 3. no descendant of this state. in this case, we ask our parent state to
|
||||
# perform the transition
|
||||
|
||||
if target == self:
|
||||
# exit this state
|
||||
_state_exit()
|
||||
# then re-enter it
|
||||
_state_enter(target)
|
||||
return
|
||||
|
||||
if target in get_children():
|
||||
# all good, nothing to do.
|
||||
return
|
||||
|
||||
if self.is_ancestor_of(target):
|
||||
# find the child which is the ancestor of the new target.
|
||||
for child in get_children():
|
||||
if child is StateChartState and child.is_ancestor_of(target):
|
||||
# ask child to handle the transition
|
||||
child._handle_transition(transition, source)
|
||||
return
|
||||
return
|
||||
|
||||
# ask the parent
|
||||
get_parent()._handle_transition(transition, source)
|
||||
|
||||
func _state_enter(transition_target:StateChartState):
|
||||
super._state_enter(transition_target)
|
||||
# enter all children
|
||||
for child in _sub_states:
|
||||
child._state_enter(transition_target)
|
||||
|
||||
func _state_exit():
|
||||
# exit all children
|
||||
for child in _sub_states:
|
||||
child._state_exit()
|
||||
|
||||
super._state_exit()
|
||||
|
||||
func _state_step():
|
||||
super._state_step()
|
||||
for child in _sub_states:
|
||||
child._state_step()
|
||||
|
||||
func _process_transitions(trigger_type:StateChart.TriggerType, event:StringName = "") -> bool:
|
||||
if not active:
|
||||
return false
|
||||
|
||||
# forward to all children
|
||||
var handled := false
|
||||
for child in _sub_states:
|
||||
var child_handled_it = child._process_transitions(trigger_type, event)
|
||||
handled = handled or child_handled_it
|
||||
|
||||
# if any child handled this, we don't touch it anymore
|
||||
if handled:
|
||||
# emit the event_received signal for completeness
|
||||
# if the trigger type is event
|
||||
if trigger_type == StateChart.TriggerType.EVENT:
|
||||
self.event_received.emit(event)
|
||||
return true
|
||||
|
||||
# otherwise handle it ourselves
|
||||
# defer to the base class
|
||||
return super._process_transitions(trigger_type, event)
|
||||
|
||||
func _get_configuration_warnings() -> PackedStringArray:
|
||||
var warnings = super._get_configuration_warnings()
|
||||
|
||||
var child_count = 0
|
||||
for child in get_children():
|
||||
if child is StateChartState:
|
||||
child_count += 1
|
||||
|
||||
if child_count < 2:
|
||||
warnings.append("Parallel states should have at least two child states.")
|
||||
|
||||
|
||||
return warnings
|
Loading…
Add table
Add a link
Reference in a new issue