150 lines
4.7 KiB
GDScript
Executable File
150 lines
4.7 KiB
GDScript
Executable File
@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 = null # This would be resolved at runtime
|
|
var target_node = null # 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
|