@tool class_name CutsceneGenerator extends Object # System for generating executable cutscene actions from graph data # Properties var graph_nodes: Dictionary = {} # Map of node IDs to node data var connections: Array = [] # List of connection data # Generate a cutscene from graph data func generate_cutscene(scene: Node, cutscene_resource: CutsceneResource) -> CutsceneManager: # Clear previous data graph_nodes.clear() connections.clear() # Load graph data for node_data in cutscene_resource.nodes: graph_nodes[node_data["id"]] = node_data connections = cutscene_resource.connections # Create CutsceneManager var cutscene_manager = CutsceneManager.new() # Find entry node var entry_node = _find_entry_node() if not entry_node: printerr("No entry node found in cutscene") return cutscene_manager # Build action sequence starting from entry node _build_action_sequence(scene, entry_node, cutscene_manager) return cutscene_manager # Find the entry node in the graph func _find_entry_node() -> Dictionary: for node_id in graph_nodes: var node_data = graph_nodes[node_id] if node_data["type"] == "entry": return node_data return {} # Build action sequence from graph data func _build_action_sequence(scene: Node, start_node: Dictionary, cutscene_manager: CutsceneManager) -> void: # First pass: Create all actions var action_map = {} # Map of node IDs to action instances for node_id in graph_nodes: var node_data = graph_nodes[node_id] # Skip entry and exit nodes as they don't create actions if node_data["type"] == "entry" or node_data["type"] == "exit": continue # Create action for regular nodes var action = _create_action_from_node(scene, node_data) if action: action_map[node_id] = action # Second pass: Add actions with their dependencies for node_id in action_map: print("setting up", node_id) var action = action_map[node_id] # Get dependencies (incoming connections) var deps = [] var incoming_connections = _get_incoming_connections(node_id) for conn in incoming_connections: # Only add as dependency if the source node creates an action var from_node_data = graph_nodes.get(conn["from_node"], {}) if not from_node_data.is_empty() and from_node_data["type"] != "entry": deps.append(conn["from_node"]) # Add action with dependencies cutscene_manager.add_action(node_id, action, deps) # Create an action instance from node data func _create_action_from_node(scene: Node, node_data: Dictionary): var parameters = node_data["parameters"] match node_data["type"]: "move": var character_path = parameters.get("character", "") var target_x = parameters.get("target_x", 0.0) var target_y = parameters.get("target_y", 0.0) var speed = parameters.get("speed", 100.0) # In a real implementation, we would resolve the character path to an actual node # For now, we'll create a placeholder var character_node = scene.find_child(character_path) # This would be resolved at runtime var target_position = Vector2(target_x, target_y) return MoveAction.new(character_node, target_position, speed) "turn": var character_path = parameters.get("character", "") var target = parameters.get("target", "") var turn_speed = parameters.get("turn_speed", 2.0) # In a real implementation, we would resolve the paths to actual nodes var character_node = scene.find_child(character_path) # This would be resolved at runtime var target_node = scene.find_child(target) # This would be resolved at runtime return TurnAction.new(character_node, target_node, turn_speed) "dialogue": var character_path = parameters.get("character", "") var text = parameters.get("text", "") var duration = parameters.get("duration", 0.0) var character_node = null # This would be resolved at runtime return DialogueAction.new(character_node, text, duration) "animation": var character_path = parameters.get("character", "") var animation_name = parameters.get("animation_name", "") var loop = parameters.get("loop", false) var character_node = null # This would be resolved at runtime return AnimationAction.new(character_node, animation_name, loop) "wait": var duration = parameters.get("duration", 1.0) return WaitAction.new(duration) _: printerr("Unknown node type: %s" % node_data["type"]) return null # Get outgoing connections from a node func _get_outgoing_connections(node_id: String) -> Array: var outgoing = [] for conn in connections: if conn["from_node"] == node_id: outgoing.append(conn) return outgoing # Get incoming connections to a node func _get_incoming_connections(node_id: String) -> Array: var incoming = [] for conn in connections: if conn["to_node"] == node_id: incoming.append(conn) return incoming