You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
3.8 KiB
131 lines
3.8 KiB
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
|