210 lines
6.0 KiB
GDScript
210 lines
6.0 KiB
GDScript
class_name CutsceneManager
|
|
extends Node
|
|
|
|
# Action queues
|
|
var sequential_actions: Array = [] # Actions that run one after another
|
|
var current_action: Action = null # The action currently being executed
|
|
var action_index: int = 0 # Index of the next sequential action
|
|
|
|
# Parallel actions
|
|
var parallel_groups: Array = [] # Groups of actions running simultaneously
|
|
var active_parallel_groups: Array = [] # Currently running parallel action groups
|
|
|
|
# State management
|
|
enum State {
|
|
IDLE, # Not running any cutscene
|
|
RUNNING, # Currently executing a cutscene
|
|
PAUSED # Cutscene is paused
|
|
}
|
|
|
|
var state: int = State.IDLE
|
|
var is_active: bool = false
|
|
|
|
# Signals
|
|
signal cutscene_started()
|
|
signal cutscene_completed()
|
|
signal cutscene_paused()
|
|
signal cutscene_resumed()
|
|
signal action_started(action)
|
|
signal action_completed(action)
|
|
signal action_failed(action, error_message)
|
|
|
|
# Public methods
|
|
func start() -> void:
|
|
# Start executing the cutscene
|
|
if state != State.IDLE:
|
|
return
|
|
|
|
state = State.RUNNING
|
|
is_active = true
|
|
emit_signal("cutscene_started")
|
|
|
|
# Start first action
|
|
_execute_next_action()
|
|
|
|
func pause() -> void:
|
|
# Pause the current cutscene
|
|
if state == State.RUNNING:
|
|
state = State.PAUSED
|
|
emit_signal("cutscene_paused")
|
|
|
|
func resume() -> void:
|
|
# Resume a paused cutscene
|
|
if state == State.PAUSED:
|
|
state = State.RUNNING
|
|
emit_signal("cutscene_resumed")
|
|
|
|
func stop() -> void:
|
|
# Stop the current cutscene and reset
|
|
if current_action != null:
|
|
current_action.stop()
|
|
current_action = null
|
|
|
|
# Stop all active parallel groups
|
|
for group in active_parallel_groups:
|
|
for action in group["actions"]:
|
|
if action.state == action.State.RUNNING:
|
|
action.stop()
|
|
|
|
_reset()
|
|
|
|
func add_action(action: Action) -> void:
|
|
# Add a single action to the sequential queue
|
|
if state != State.IDLE:
|
|
print("Warning: Cannot add actions while cutscene is running")
|
|
return
|
|
|
|
sequential_actions.append(action)
|
|
|
|
# Internal methods
|
|
func _process(delta: float) -> void:
|
|
# Main update loop
|
|
if state != State.RUNNING:
|
|
return
|
|
|
|
# Update current sequential action
|
|
if current_action != null and current_action.state == current_action.State.RUNNING:
|
|
current_action.update(delta)
|
|
|
|
# Update active parallel groups
|
|
for group in active_parallel_groups:
|
|
for action in group["actions"]:
|
|
if action.state == action.State.RUNNING:
|
|
action.update(delta)
|
|
|
|
func _execute_next_action() -> void:
|
|
# Start executing the next sequential action
|
|
if action_index >= sequential_actions.size():
|
|
# No more actions, cutscene complete
|
|
_on_cutscene_completed()
|
|
return
|
|
|
|
var action_item = sequential_actions[action_index]
|
|
action_index += 1
|
|
print(action_item)
|
|
# Check if this is a parallel group or single action
|
|
if typeof(action_item) == TYPE_DICTIONARY and action_item.has("actions"):
|
|
# This is a parallel group
|
|
_execute_parallel_group(action_item)
|
|
else:
|
|
# This is a single action
|
|
_execute_single_action(action_item)
|
|
|
|
func _execute_single_action(action: Action) -> void:
|
|
# Execute a single action
|
|
current_action = action
|
|
|
|
# Connect to action signals
|
|
if not action.is_connected("completed", _on_action_completed):
|
|
action.connect("completed", _on_action_completed.bind(action))
|
|
if not action.is_connected("failed", _on_action_failed):
|
|
action.connect("failed", _on_action_failed.bind(action))
|
|
if not action.is_connected("started", _on_action_started):
|
|
action.connect("started", _on_action_started.bind(action))
|
|
|
|
# Start the action
|
|
emit_signal("action_started", action)
|
|
action.start()
|
|
|
|
func _execute_parallel_group(group: Dictionary) -> void:
|
|
# Execute a group of parallel actions
|
|
var actions = group["actions"]
|
|
|
|
# Reset completion count
|
|
group["completed_count"] = 0
|
|
|
|
# Add to active parallel groups
|
|
active_parallel_groups.append(group)
|
|
|
|
# Connect to each action's signals
|
|
for action in actions:
|
|
if not action.is_connected("completed", _on_parallel_action_completed):
|
|
action.connect("completed", _on_parallel_action_completed.bind(group, action))
|
|
if not action.is_connected("failed", _on_parallel_action_failed):
|
|
action.connect("failed", _on_parallel_action_failed.bind(group, action))
|
|
if not action.is_connected("started", _on_action_started):
|
|
action.connect("started", _on_action_started.bind(action))
|
|
|
|
# Emit started signal and start action
|
|
emit_signal("action_started", action)
|
|
action.start()
|
|
|
|
func _on_action_started(action: Action) -> void:
|
|
# Handle action started
|
|
emit_signal("action_started", action)
|
|
|
|
func _on_action_completed(action: Action) -> void:
|
|
# Handle action completion
|
|
if action == current_action:
|
|
current_action = null
|
|
emit_signal("action_completed", action)
|
|
# Move to next action
|
|
_execute_next_action()
|
|
|
|
func _on_action_failed(action: Action, error_message: String) -> void:
|
|
# Handle action failure
|
|
if action == current_action:
|
|
current_action = null
|
|
|
|
emit_signal("action_failed", action, error_message)
|
|
print("Action failed: %s - %s" % [action.name, error_message])
|
|
# Stop the cutscene
|
|
stop()
|
|
|
|
func _on_parallel_action_completed(group: Dictionary, action: Action) -> void:
|
|
# Increment completed count
|
|
group["completed_count"] += 1
|
|
|
|
emit_signal("action_completed", action)
|
|
|
|
# Check if all actions in group are completed
|
|
if group["completed_count"] >= group["total_count"]:
|
|
# Remove from active groups
|
|
active_parallel_groups.erase(group)
|
|
|
|
# Continue with next sequential action
|
|
_execute_next_action()
|
|
|
|
func _on_parallel_action_failed(group: Dictionary, action: Action, error_message: String) -> void:
|
|
# Handle parallel action failure
|
|
emit_signal("action_failed", action, error_message)
|
|
print("Parallel action failed: %s - %s" % [action.name, error_message])
|
|
# Stop the cutscene
|
|
stop()
|
|
|
|
func _on_cutscene_completed() -> void:
|
|
# Handle cutscene completion
|
|
state = State.IDLE
|
|
is_active = false
|
|
emit_signal("cutscene_completed")
|
|
|
|
func _reset() -> void:
|
|
# Reset the manager to initial state
|
|
sequential_actions.clear()
|
|
parallel_groups.clear()
|
|
active_parallel_groups.clear()
|
|
current_action = null
|
|
action_index = 0
|
|
state = State.IDLE
|
|
is_active = false
|