diff --git a/pydot%2Fcore/node.py b/pydot%2Fcore/node.py new file mode 100644 index 0000000..0d12ec2 --- /dev/null +++ b/pydot%2Fcore/node.py @@ -0,0 +1,130 @@ +import uuid +from typing import Optional, List, Dict, Callable + +from base import Transform2D, Vector2D +from pygame import Surface + + +class Node: + + def __init__(self, name: str = ""): + self._id = str(uuid.uuid4()) + self.name = name or f"Node_{self._id[:8]}" + self.parent: Optional[Node] = None + self.children: List[Node] = [] + self._is_in_tree = False + self._ready_called = False + self._process_enabled = False + self._physics_process_enabled = False + self.signals: Dict[str, List[Callable]] = {} + + def _enter_tree(self): + self.enter_tree() + self._is_in_tree = True + for child in self.children: + child._enter_tree() + + def _exit_tree(self): + self.exit_tree() + self._is_in_tree = False + for child in self.children: + child._exit_tree() + + def _ready(self): + if not self._ready_called: + self._ready_called = True + self.ready() + for child in self.children: + child._ready() + + def _process(self, delta: float): + if not self._process_enabled: + return + self.process(delta) + for child in self.children: + child._process(delta) + + def _physics_process(self, delta: float): + if not self._process_enabled: + return + self.physics_process(delta) + for child in self.children: + child._physics_process(delta) + + def _unhandled_input(self, event):pass + def _unhandled_key_input(self, event):pass + + """ + def _draw(self, surface: Surface): + if self._visible: + self.draw(surface) + for child in self.children: + child._draw(surface) + """ + + def enter_tree(self): pass + def exit_tree(self): pass + def ready(self): pass + def process(self, delta: float): pass + def physics_process(self, delta: float): pass + # def draw(self, surface: Surface): pass + + def add_child(self, node: 'Node'): + if node.parent: + node.parent.remove_child(node) + self.children.append(node) + node.parent = self + + def remove_child(self, node: 'Node'): + if node in self.children: + self.children.remove(node) + node.parent = None + + def get_node(self, path: str) -> Optional['Node']: + if path == ".": + return self + + parts = path.split("/") + current = self + + for part in parts: + if part == "..": + current = current.parent + if not current: + return None + else: + found = False + for child in current.children: + if child.name == part: + current = child + found = True + break + if not found: + return None + return current + + return current + + def connect(self, signal: str, callback: Callable): + if signal not in self.signals: + self.signals[signal] = [] + self.signals[signal].append(callback) + + def emit(self, signal: str, *args): + if signal in self.signals: + for callback in self.signals[signal]: + callback(*args) + + def to_dict(self) -> dict: + return { + "type": self.__class__.__name__, + "name": self.name, + "children": [child.to_dict() for child in self.children], + } + @classmethod + def from_dict(cls, data: dict) -> 'Node': + node = cls(data["name"]) + for child_data in data["children"]: + child = Node.from_dict(child_data) + node.add_child(child) + return node