class_name StateMachine extends Node #export (NodePath) var starting_state export var debug_state_machine: bool = false # I guess I would declare a number of states here #export (Reference) var states # Doesn't work #var starting_state: State signal state_changed(old_state_name, new_state) signal modifiers_updated(modifier_type, modifier_eventid) var current_state: State var state_modifiers: Array onready var merged_animation_state_modifiers :StateModifierAnimatedActor = StateModifierAnimatedActor.new() export var starting_state_name = 'default' export(Array,Resource) var states var states_index :Dictionary # Initialize the state machine by giving each child state a reference to the # parent object it belongs to and enter the default starting_state. #func _init() -> void: # print ("init state machine.") func _ready(): print ("ready state machine.") for s in states: print ("sname: ", s.name) var this_state = s if this_state is State: print("Adding state ", this_state.name) #check for empty state name if this_state.name != '': #check for unique state name if !(states_index.has(this_state.name)): # call setup this_state.setup() if debug_state_machine: print("Initializing State Node: ", s) this_state.debug_state = true if this_state.state_timeout != null: add_child(this_state.state_timeout) # Add to state index states_index[this_state.name] = this_state else: push_error("Multiple states with same name in: ") else: print("State missing name in: " ) if states_index.has(starting_state_name): change_state(states_index[starting_state_name]) else: push_error("State machine cannot find starting state: " + starting_state_name) func _physics_process(delta): if(state_modifiers.size() > 0): merged_animation_state_modifiers.reset() merged_animation_state_modifiers.animation_name = 'floopy doo,' merge_modifiers() func merge_modifiers(): merged_animation_state_modifiers.reset() for m in state_modifiers: if m is StateModifierAnimatedActor: #print(m.name) if m.is_active: merged_animation_state_modifiers.merge_StateModifierAnimatedActor(m) # Change to the new state by first calling any exit logic on the current state. func change_state(new_state: State) -> void: var current_state_name :String if current_state: current_state.exit() current_state_name = current_state.name current_state = new_state current_state.enter() # Seems like I don't have to do this every state change! # if(state_modifiers.size() > 0): # print("Active Modifiers:") # for mods in state_modifiers: # if mods is StateModifierAnimatedActor: # print(mods.name, " <- asm") emit_signal("state_changed",current_state_name,current_state) func change_to_known_state(new_state_name: String) -> void: if new_state_name.empty() == false: if states_index.has(new_state_name): change_state(states_index[new_state_name]) else: push_warning(get_parent().name + ": Attempt to switch state to unknown: " + new_state_name) change_state(states_index["default"]) func get_state_reference(state_name: String) -> State: print ("what you want? ", state_name) if states_index.has(state_name): return states_index[state_name] return null func push_state_modifier(_state_modifier: StateModifier) -> void: if state_modifiers.has(_state_modifier) == false: state_modifiers.push_front(_state_modifier) _state_modifier.connect("modifier_event",self,"handle_modifier_events") print("Add State Modifier: ", _state_modifier.name, " now size ", state_modifiers.size()) func handle_modifier_events(eventID :int): if eventID == StateModifier.EVENT_ID.ACTIVATED: print ("A mod activated! Which one though?") merge_modifiers() emit_signal("modifiers_updated",merged_animation_state_modifiers.modifier_type, eventID) elif eventID == StateModifier.EVENT_ID.DEACTIVATED: merge_modifiers() emit_signal("modifiers_updated",merged_animation_state_modifiers.modifier_type, eventID) # Disable to test whether actually needed. ## Pass through functions for the Player to call, ## handling state changes as needed. #func process_physics(delta: float) -> void: # change_to_known_state( current_state.process_physics(delta) ) # #func process_input(event: InputEvent) -> void: # var new_state = current_state.process_input(event) # if new_state: # change_state(new_state) # #func process_frame(delta: float) -> void: # var new_state = current_state.process_frame(delta) # if new_state: # change_state(new_state)