@tool class_name UndoRedoManager extends Object # Manager for undo/redo operations # Signals signal undo_redo_state_changed() # Properties var undo_stack: Array = [] # Stack of undo operations var redo_stack: Array = [] # Stack of redo operations var max_history: int = 100 # Maximum number of operations to store var is_processing: bool = false # Flag to prevent recursive processing # Operation types enum OperationType { NODE_ADDED, NODE_REMOVED, NODE_MOVED, NODE_PROPERTY_CHANGED, CONNECTION_CREATED, CONNECTION_REMOVED, GRAPH_CLEARED } # Initialize the undo/redo manager func _init() -> void: pass # Add an operation to the undo stack func add_operation(operation: Dictionary) -> void: if is_processing: return # Add to undo stack undo_stack.push_back(operation) # Limit stack size if undo_stack.size() > max_history: undo_stack.pop_front() # Clear redo stack when new operation is added redo_stack.clear() # Emit signal emit_signal("undo_redo_state_changed") # Perform undo operation func undo() -> void: if undo_stack.is_empty(): return # Set processing flag to prevent recursive calls is_processing = true # Get last operation var operation = undo_stack.pop_back() # Perform reverse operation _perform_reverse_operation(operation) # Add to redo stack redo_stack.push_back(operation) # Limit redo stack size if redo_stack.size() > max_history: redo_stack.pop_front() # Clear processing flag is_processing = false # Emit signal emit_signal("undo_redo_state_changed") # Perform redo operation func redo() -> void: if redo_stack.is_empty(): return # Set processing flag to prevent recursive calls is_processing = true # Get last redo operation var operation = redo_stack.pop_back() # Perform original operation _perform_operation(operation) # Add to undo stack undo_stack.push_back(operation) # Limit undo stack size if undo_stack.size() > max_history: undo_stack.pop_front() # Clear processing flag is_processing = false # Emit signal emit_signal("undo_redo_state_changed") # Check if undo is possible func can_undo() -> bool: return not undo_stack.is_empty() # Check if redo is possible func can_redo() -> bool: return not redo_stack.is_empty() # Clear all history func clear_history() -> void: undo_stack.clear() redo_stack.clear() emit_signal("undo_redo_state_changed") # Perform an operation func _perform_operation(operation: Dictionary) -> void: # This would be implemented in the graph editor pass # Perform the reverse of an operation func _perform_reverse_operation(operation: Dictionary) -> void: match operation["type"]: OperationType.NODE_ADDED: _reverse_node_added(operation) OperationType.NODE_REMOVED: _reverse_node_removed(operation) OperationType.NODE_MOVED: _reverse_node_moved(operation) OperationType.NODE_PROPERTY_CHANGED: _reverse_node_property_changed(operation) OperationType.CONNECTION_CREATED: _reverse_connection_created(operation) OperationType.CONNECTION_REMOVED: _reverse_connection_removed(operation) OperationType.GRAPH_CLEARED: _reverse_graph_cleared(operation) # Create operation for node added func create_node_added_operation(node: BaseGraphNode) -> Dictionary: return { "type": OperationType.NODE_ADDED, "node_name": node.name, "node_type": node.node_type, "position": node.position_offset, "parameters": node.action_parameters.duplicate(true) } # Reverse node added operation func _reverse_node_added(operation: Dictionary) -> void: # This would remove the node in the graph editor pass # Create operation for node removed func create_node_removed_operation(node: BaseGraphNode) -> Dictionary: return { "type": OperationType.NODE_REMOVED, "node_name": node.name, "node_type": node.node_type, "position": node.position_offset, "parameters": node.action_parameters.duplicate(true), "connections": _get_node_connections(node.name) } # Reverse node removed operation func _reverse_node_removed(operation: Dictionary) -> void: # This would add the node back in the graph editor pass # Create operation for node moved func create_node_moved_operation(node_name: String, old_position: Vector2, new_position: Vector2) -> Dictionary: return { "type": OperationType.NODE_MOVED, "node_name": node_name, "old_position": old_position, "new_position": new_position } # Reverse node moved operation func _reverse_node_moved(operation: Dictionary) -> void: # This would move the node back to its old position in the graph editor pass # Create operation for node property changed func create_node_property_changed_operation(node_name: String, property_name: String, old_value, new_value) -> Dictionary: return { "type": OperationType.NODE_PROPERTY_CHANGED, "node_name": node_name, "property_name": property_name, "old_value": old_value, "new_value": new_value } # Reverse node property changed operation func _reverse_node_property_changed(operation: Dictionary) -> void: # This would restore the old property value in the graph editor pass # Create operation for connection created func create_connection_created_operation(from_node: String, from_port: int, to_node: String, to_port: int) -> Dictionary: return { "type": OperationType.CONNECTION_CREATED, "from_node": from_node, "from_port": from_port, "to_node": to_node, "to_port": to_port } # Reverse connection created operation func _reverse_connection_created(operation: Dictionary) -> void: # This would remove the connection in the graph editor pass # Create operation for connection removed func create_connection_removed_operation(from_node: String, from_port: int, to_node: String, to_port: int) -> Dictionary: return { "type": OperationType.CONNECTION_REMOVED, "from_node": from_node, "from_port": from_port, "to_node": to_node, "to_port": to_port } # Reverse connection removed operation func _reverse_connection_removed(operation: Dictionary) -> void: # This would recreate the connection in the graph editor pass # Create operation for graph cleared func create_graph_cleared_operation(nodes: Array, connections: Array) -> Dictionary: return { "type": OperationType.GRAPH_CLEARED, "nodes": nodes.duplicate(true), "connections": connections.duplicate(true) } # Reverse graph cleared operation func _reverse_graph_cleared(operation: Dictionary) -> void: # This would restore all nodes and connections in the graph editor pass # Get connections for a node func _get_node_connections(node_name: String) -> Array: # This would retrieve all connections to/from the node return []