initial commit: canny cat basic movement, bouncing, some gridmap tiles for levels
This commit is contained in:
commit
e1b43c8bc5
120 changed files with 5785 additions and 0 deletions
193
addons/godot_state_charts/transition.gd
Normal file
193
addons/godot_state_charts/transition.gd
Normal file
|
@ -0,0 +1,193 @@
|
|||
@tool
|
||||
@icon("transition.svg")
|
||||
class_name Transition
|
||||
extends Node
|
||||
|
||||
const ExpressionUtil = preload("expression_util.gd")
|
||||
const DebugUtil = preload("debug_util.gd")
|
||||
|
||||
## Flag indicating that this transition has been modified and needs to update its caches.
|
||||
var _dirty:bool = true
|
||||
|
||||
## Cached target state of this transition. Will be resolved when [method resolve_target] is called.
|
||||
var _target:StateChartState = null
|
||||
|
||||
## The trigger types that are supported by this transition. This is a bit mask of the supported trigger types.
|
||||
## The trigger types are defined in the [StateChart] class.
|
||||
var _supported_trigger_types:int = 0
|
||||
|
||||
## 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("StateChartState") var to:NodePath:
|
||||
set(value):
|
||||
to = value
|
||||
_dirty = true
|
||||
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
|
||||
_dirty = true
|
||||
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
|
||||
_dirty = true
|
||||
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.
|
||||
## @deprecated: use the new delay_in_seconds property instead
|
||||
var delay_seconds:float = 0.0:
|
||||
set(value):
|
||||
delay_in_seconds = str(value)
|
||||
get:
|
||||
if delay_in_seconds.is_valid_float():
|
||||
return float(delay_in_seconds)
|
||||
return 0.0
|
||||
|
||||
## An expression for the delay in seconds before the transition is taken.
|
||||
## This expression can use all expression properties of the state chart.
|
||||
## If the expression does not evaluate to a valid float or a negative value,
|
||||
## the delay will be 0. When the delay is 0, 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.
|
||||
var delay_in_seconds:String = "0.0":
|
||||
set(value):
|
||||
delay_in_seconds = value
|
||||
update_configuration_warnings()
|
||||
|
||||
|
||||
## Read-only property that returns true if the transition has an event specified.
|
||||
## @deprecated: this property is no longer needed. It will be removed in a future version.
|
||||
var has_event:bool:
|
||||
get:
|
||||
return event != null and event.length() > 0
|
||||
|
||||
|
||||
## Returns true if this transition is potentially triggered by the given trigger type.
|
||||
func is_triggered_by(trigger_type:StateChart.TriggerType) -> bool:
|
||||
if _dirty:
|
||||
_refresh_caches()
|
||||
return (_supported_trigger_types & trigger_type) != 0
|
||||
|
||||
## Takes this transition immediately or with a delay if defined
|
||||
## Note: if there is a delay on this transition and immediately param is true, it forces the transition to be taken without the delay
|
||||
func take(immediately:bool = true) -> void:
|
||||
var parent_state:StateChartState = get_parent() as StateChartState
|
||||
if parent_state == null:
|
||||
push_error("Transitions must be children of states.")
|
||||
return
|
||||
|
||||
parent_state._run_transition(self, immediately)
|
||||
|
||||
## 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:StateChartState = get_parent() as StateChartState
|
||||
if parent_state == null:
|
||||
push_error("Transitions must be children of states.")
|
||||
return false
|
||||
|
||||
return guard.is_satisfied(self, get_parent())
|
||||
|
||||
|
||||
## Evaluates the delay of this transition.
|
||||
func evaluate_delay() -> float:
|
||||
# if the expression just is a single float, skip the evaluation and just
|
||||
# return the float value. This is a performance optimization.
|
||||
if delay_in_seconds.is_valid_float():
|
||||
return float(delay_in_seconds)
|
||||
|
||||
# evaluate the expression
|
||||
var parent_state:StateChartState = get_parent() as StateChartState
|
||||
if parent_state == null:
|
||||
push_error("Transitions must be children of states.")
|
||||
return 0.0
|
||||
|
||||
var result = ExpressionUtil.evaluate_expression("delay of " + DebugUtil.path_of(self), parent_state._chart, delay_in_seconds, 0.0)
|
||||
if typeof(result) != TYPE_FLOAT:
|
||||
push_error("Expression: ", delay_in_seconds ," result: ", result, " is not a float. Returning 0.0.")
|
||||
return 0.0
|
||||
|
||||
return result
|
||||
|
||||
## Resolves the target state and returns it. If the target state is not found,
|
||||
## this function will return null.
|
||||
func resolve_target() -> StateChartState:
|
||||
if _dirty:
|
||||
_refresh_caches()
|
||||
return _target
|
||||
|
||||
func _get_configuration_warnings() -> PackedStringArray:
|
||||
var warnings:Array = []
|
||||
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 StateChartState):
|
||||
warnings.append("Transitions must be children of states.")
|
||||
|
||||
return warnings
|
||||
|
||||
func _get_property_list() -> Array:
|
||||
var properties:Array = []
|
||||
properties.append({
|
||||
"name": "delay_in_seconds",
|
||||
"type": TYPE_STRING,
|
||||
"usage": PROPERTY_USAGE_DEFAULT,
|
||||
"hint": PROPERTY_HINT_EXPRESSION
|
||||
})
|
||||
|
||||
# hide the old delay_seconds property
|
||||
properties.append({
|
||||
"name": "delay_seconds",
|
||||
"type": TYPE_FLOAT,
|
||||
"usage": PROPERTY_USAGE_NONE
|
||||
})
|
||||
|
||||
return properties
|
||||
|
||||
|
||||
func _refresh_caches():
|
||||
_dirty = false
|
||||
var is_automatic:bool = (event == null or event.length() == 0)
|
||||
|
||||
if to != null and not to.is_empty():
|
||||
var result:Node = get_node_or_null(to)
|
||||
if result is StateChartState:
|
||||
_target = result
|
||||
|
||||
_supported_trigger_types = 0
|
||||
if not is_automatic:
|
||||
# non-automatic transitions can only be triggered by events
|
||||
_supported_trigger_types |= StateChart.TriggerType.EVENT
|
||||
else:
|
||||
# automatic transitions can be triggered by multiple conditions.
|
||||
# ALL automatic transitions can be triggered by state enter
|
||||
_supported_trigger_types |= StateChart.TriggerType.STATE_ENTER
|
||||
# ALL automatic transitions remain "in play" until the state is left. While
|
||||
# "in play" they can be triggered by property changes or state changes.
|
||||
# Which changes exactly are supported is determined by the used guard(s).
|
||||
|
||||
# Check the guard for trigger types
|
||||
if guard != null:
|
||||
_supported_trigger_types |= guard.get_supported_trigger_types()
|
Loading…
Add table
Add a link
Reference in a new issue