L3-Bataille-Navale/source/gui/window/Window.py

140 lines
5.2 KiB
Python

from typing import TYPE_CHECKING, Callable
import pyglet.window
if TYPE_CHECKING:
from source.gui.scene import BaseScene
class Window(pyglet.window.Window): # NOQA
"""
Same as the original pyglet class, but allow to set a scene.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# scene
self._scenes = []
# a dictionary linking a key pressed to the corresponding event function
self._on_key_held_events: dict[(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: "BaseScene"):
self.clear()
self.add_scene(*scenes)
def add_scene(self, *scenes: "BaseScene", priority: int = 0):
for scene in scenes:
self._scenes.insert(priority, scene)
scene.on_window_added(self)
def remove_scene(self, *scenes: "BaseScene"):
for scene in scenes:
scene.on_window_removed(self)
self._scenes.remove(scene)
def clear_scene(self):
self.remove_scene(*self._scenes)
# NOTE: it is too difficult to refactor all the event because :
# - There is no event "on_any_event" or equivalent
# - The list of all the event is not available in the source
# - Some event need special code like on_draw with the clear, on_resize with the super, ...
def on_draw(self): # NOQA
self.clear() # clear the window to reset it
for scene in self._scenes: scene.on_draw(self)
def on_resize(self, width: int, height: int):
super().on_resize(width, height) # this function is already defined and used
for scene in self._scenes: scene.on_resize(self, width, height)
def on_hide(self):
for scene in self._scenes: scene.on_hide(self)
def on_show(self):
for scene in self._scenes: scene.on_show(self)
def on_close(self):
super().close() # this function is already defined and used
for scene in self._scenes: scene.on_close(self)
def on_expose(self):
for scene in self._scenes: scene.on_expose(self)
def on_activate(self):
for scene in self._scenes: scene.on_activate(self)
def on_deactivate(self):
for scene in self._scenes: scene.on_deactivate(self)
def on_text(self, char: str):
for scene in self._scenes: scene.on_text(self, char)
def on_move(self, x: int, y: int):
for scene in self._scenes: scene.on_move(self, x, y)
def on_context_lost(self):
for scene in self._scenes: scene.on_context_lost(self)
def on_context_state_lost(self):
for scene in self._scenes: scene.on_context_state_lost(self)
def on_key_press(self, symbol: int, modifiers: int):
super().on_key_press(symbol, modifiers) # this function is already defined and used
# this allows the on_key_held event to be called every frame after a press
pyglet.clock.schedule(self.get_on_key_held_function(symbol, modifiers))
for scene in self._scenes: scene.on_key_press(self, symbol, modifiers)
def on_key_release(self, symbol: int, modifiers: int):
# this allows the on_key_held event to stop after the key is released
pyglet.clock.unschedule(self.get_on_key_held_function(symbol, modifiers))
for scene in self._scenes: scene.on_key_release(self, symbol, modifiers)
def get_on_key_held_function(self, symbol: int, modifiers: int):
key: tuple[int, int] = (symbol, modifiers)
if key not in self._on_key_held_events:
self._on_key_held_events[key] = lambda dt: self.on_key_held(dt, symbol, modifiers)
return self._on_key_held_events[key]
def on_key_held(self, dt: float, symbol: int, modifiers: int):
for scene in self._scenes: scene.on_key_held(self, dt, symbol, modifiers)
def on_mouse_enter(self, x: int, y: int):
for scene in self._scenes: scene.on_mouse_enter(self, x, y)
def on_mouse_leave(self, x: int, y: int):
for scene in self._scenes: scene.on_mouse_leave(self, x, y)
def on_text_motion(self, motion: int):
for scene in self._scenes: scene.on_text_motion(self, motion)
def on_text_motion_select(self, motion: int):
for scene in self._scenes: scene.on_text_motion_select(self, motion)
def on_mouse_motion(self, x: int, y: int, dx: int, dy: int):
for scene in self._scenes: scene.on_mouse_motion(self, x, y, dx, dy)
def on_mouse_press(self, x: int, y: int, button: int, modifiers: int):
for scene in self._scenes: scene.on_mouse_press(self, x, y, button, modifiers)
def on_mouse_release(self, x: int, y: int, button: int, modifiers: int):
for scene in self._scenes: scene.on_mouse_release(self, x, y, button, modifiers)
def on_mouse_drag(self, x: int, y: int, dx: int, dy: int, buttons: int, modifiers: int):
for scene in self._scenes: scene.on_mouse_drag(self, x, y, dx, dy, buttons, modifiers)
def on_mouse_scroll(self, x: int, y: int, scroll_x: float, scroll_y: float):
for scene in self._scenes: scene.on_mouse_scroll(self, x, y, scroll_x, scroll_y)