@tool class_name ParallelGroupNode extends "res://addons/cutscene_editor/editor/nodes/BaseGraphNode.gd" # Node for grouping parallel actions # Special properties for parallel groups var input_connections: int = 3 # Number of input connection points var child_nodes: Array = [] # Child nodes contained within this group var is_container: bool = true # Flag to indicate this is a container node # Visual properties var container_rect: PanelContainer # Visual container for child nodes func _init() -> void: node_type = "parallel" name = "parallel_" + str(randi()) title = "Parallel Group" modulate = Color(1.0, 0.6, 0.2) # Orange # Set up slots for connections _setup_slots() # Set up container for child nodes _setup_container() # Set up connection slots func _setup_slots() -> void: # Multiple input connections for parallel actions for i in range(input_connections): set_slot(i, true, 0, Color(0, 0, 0), false, 0, Color(0, 0, 0, 0)) # Single output connection for sequential continuation var output_slot = input_connections set_slot(output_slot, false, 0, Color(0, 0, 0, 0), true, 0, Color(0, 0, 0)) # Set up visual container for child nodes func _setup_container() -> void: # Create container panel container_rect = PanelContainer.new() container_rect.name = "Container" container_rect.anchor_right = 1 container_rect.anchor_bottom = 1 container_rect.margin_top = 30 # Leave space for title bar container_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE # Set container style var style = StyleBoxFlat.new() style.bg_color = Color(0.9, 0.9, 0.9, 0.3) style.border_color = Color(0.5, 0.5, 0.5, 0.5) style.border_width_left = 1 style.border_width_top = 1 style.border_width_right = 1 style.border_width_bottom = 1 container_rect.add_theme_stylebox_override("panel", style) add_child(container_rect) # Create container for child nodes var child_container = VBoxContainer.new() child_container.name = "ChildContainer" child_container.mouse_filter = Control.MOUSE_FILTER_IGNORE container_rect.add_child(child_container) # Add a child node to this parallel group func add_child_node(child_node: BaseGraphNode) -> void: # Add to child nodes array child_nodes.append(child_node) # Add as child in scene tree if container_rect and container_rect.has_node("ChildContainer"): container_rect.get_node("ChildContainer").add_child(child_node) # Update visual representation _update_container_size() # Remove a child node from this parallel group func remove_child_node(child_node: BaseGraphNode) -> void: # Remove from child nodes array child_nodes.erase(child_node) # Remove from scene tree if child_node.get_parent() == container_rect.get_node("ChildContainer"): container_rect.get_node("ChildContainer").remove_child(child_node) # Update visual representation _update_container_size() # Update container size based on child nodes func _update_container_size() -> void: # Calculate required size based on child nodes var required_height = 20 # Minimum height if container_rect and container_rect.has_node("ChildContainer"): var child_container = container_rect.get_node("ChildContainer") for child in child_container.get_children(): if child is BaseGraphNode: required_height += child.size.y + 5 # Add spacing # Update container size container_rect.custom_minimum_size.y = required_height # Handle node dragging func _on_node_dragged(from: Vector2, to: Vector2) -> void: # Update position position_offset = to # Update child nodes if they're positioned relative to this node for child in child_nodes: # Child nodes should move with the parallel group pass # Add more input connections if needed func add_input_connection() -> void: var slot_index = input_connections set_slot(slot_index, true, 0, Color(0, 0, 0), false, 0, Color(0, 0, 0, 0)) input_connections += 1 # Get the output slot index func get_output_slot_index() -> int: return input_connections # Check if a node can be added as a child func can_add_child_node(node: BaseGraphNode) -> bool: # Can't add entry, exit, or other parallel groups as children return node.node_type != "entry" and node.node_type != "exit" and node.node_type != "parallel"