92 lines
3 KiB
Python
92 lines
3 KiB
Python
from typing import TYPE_CHECKING, Callable, Type
|
|
|
|
import pyglet.window
|
|
|
|
if TYPE_CHECKING:
|
|
from source.gui.scene.abc import AbstractScene
|
|
|
|
|
|
class Window(pyglet.window.Window): # NOQA
|
|
"""
|
|
Similaire à la fenêtre de base de pyglet, mais permet d'ajouter des scènes.
|
|
"""
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
|
|
# scene
|
|
self._scenes: list["AbstractScene"] = []
|
|
|
|
# a dictionary linking a key pressed to the corresponding event function
|
|
self._on_key_held_events: dict[tuple[int, int], Callable] = {}
|
|
|
|
# keys event handler
|
|
self.keys_handler = pyglet.window.key.KeyStateHandler()
|
|
self.push_handlers(self.keys_handler)
|
|
|
|
# scene system
|
|
|
|
def set_scene(self, scenes_type: Type["AbstractScene"]) -> "AbstractScene":
|
|
"""
|
|
Clear all the previous scene and add a scene to the window
|
|
:param scenes_type: the class of the scene to add
|
|
:return: the scene
|
|
"""
|
|
self.clear()
|
|
return self.add_scene(scenes_type)
|
|
|
|
def add_scene(self, scene_type: Type["AbstractScene"], priority: int = 0) -> "AbstractScene":
|
|
"""
|
|
Add a scene to the window
|
|
:param scene_type: the class of the scene to add
|
|
:param priority: the priority of the scene in the display
|
|
:return: the scene
|
|
"""
|
|
scene: "AbstractScene" = scene_type(self)
|
|
self._scenes.insert(priority, scene)
|
|
return scene
|
|
|
|
def remove_scene(self, *scenes: "AbstractScene") -> None:
|
|
"""
|
|
Remove scenes from the window
|
|
:param scenes: the scenes to remove
|
|
"""
|
|
for scene in scenes:
|
|
self._scenes.remove(scene)
|
|
|
|
def clear_scene(self) -> None:
|
|
"""
|
|
Remove all the scenes from the window
|
|
"""
|
|
self.remove_scene(*self._scenes)
|
|
|
|
# event
|
|
|
|
def scene_event_wrapper(self, name: str, func: Callable) -> Callable:
|
|
"""
|
|
Un wrapper permettant d'appeler l'événement de toutes les scènes attachées.
|
|
:param name: nom de la fonction à appeler dans la scène.
|
|
:param func: fonction originale à entourer du wrapper
|
|
:return: une fonction appelant l'événement original ainsi que ceux des scènes.
|
|
"""
|
|
|
|
def _func(*args, **kwargs):
|
|
func(*args, **kwargs)
|
|
for scene in self._scenes: getattr(scene, name, lambda *_, **__: "pass")(*args, **kwargs)
|
|
|
|
return _func
|
|
|
|
def __getattribute__(self, item: str):
|
|
"""
|
|
Fonction appelée dès que l'on essaye d'accéder à l'un des attributs de l'objet.
|
|
:param item: nom de l'attribut recherché
|
|
:return: l'attribut de l'objet correspondant.
|
|
"""
|
|
|
|
# print(".", end="")
|
|
|
|
attribute = super().__getattribute__(item)
|
|
|
|
# si l'attribut est un évenement (commence par "on_"), alors renvoie le dans un wrapper
|
|
return self.scene_event_wrapper(item, attribute) if item.startswith("on_") else attribute
|
|
|