L3-Bataille-Navale/source/gui/window/Window.py
2023-03-09 15:00:48 +01:00

107 lines
3.3 KiB
Python

import itertools
from math import inf
from typing import Type, TYPE_CHECKING
import pyglet
from source.gui.event import EventPropagationMixin
if TYPE_CHECKING:
from source.gui.scene.abc import Scene
class Window(pyglet.window.Window, EventPropagationMixin): # NOQA
"""
A window. Based on the pyglet window object.
Scene can be added to the window
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._scenes: list["Scene"] = list()
# Event Propagation
@property
def childs(self):
return self._scenes
# FPS
@staticmethod
def get_fps() -> float:
# on récupère la fonction responsable du rafraichissement de la fenêtre
refresh_func = pyglet.app.event_loop._redraw_windows # NOQA
# on récupère l'événement correspondant dans l'horloge de l'application
refresh_event = next(filter(
lambda item: item.func is refresh_func,
itertools.chain(
pyglet.clock._default._schedule_interval_items, # NOQA
pyglet.clock._default._schedule_items # NOQA
)
))
# renvoie infini s'il n'y avait pas de fréquence, sinon 1 / fréquence pour avoir le nombre de FPS
return inf if isinstance(refresh_event, pyglet.clock._ScheduledItem) else 1 / refresh_event.interval # NOQA
@staticmethod
def set_fps(value: float):
# on récupère la fonction responsable du rafraichissement de la fenêtre
refresh_func = pyglet.app.event_loop._redraw_windows # NOQA
# désactive le rafraichissement de la fenêtre
pyglet.clock.unschedule(refresh_func)
if value == inf:
# si la valeur est infinie, rafraichi dès que possible
pyglet.clock.schedule(refresh_func)
else:
# sinon rafraichi à la fréquence indiquée (1 / FPS)
pyglet.clock.schedule_interval(refresh_func, 1 / value)
# Scene Managing
def set_scene(self, scene_class: Type["Scene"], *scene_args, **scene_kwargs) -> "Scene":
"""
Set the scene of the window.
:scene_class: the class of the scene to add.
:scene_args: args for the creation of the scene object.
:scene_kwargs: kwargs for the creation of the scene object.
:return: the new created scene.
"""
self.clear_scene()
return self.add_scene(scene_class, *scene_args, **scene_kwargs)
def add_scene(self, scene_class: Type["Scene"], priority: int = 0, **scene_kwargs) -> "Scene":
"""
Add a scene of the window.
:scene_class: the class of the scene to add.
:scene_kwargs: kwargs for the creation of the scene object.
:return: the new created scene.
"""
scene: "Scene" = scene_class(window=self, **scene_kwargs)
self._scenes.insert(priority, scene)
return scene
def remove_scene(self, scene: "Scene") -> None:
"""
Remove a scene from the window.
:scene: the scene to remove.
"""
self._scenes.remove(scene)
def clear_scene(self) -> None:
"""
Clear the window from all the scenes.
"""
self._scenes.clear()
# Base Event
def on_draw(self): # NOQA
self.clear()