commented widgets

This commit is contained in:
Faraphel 2023-03-14 23:09:03 +01:00
parent 89c6b81ba9
commit 51eb35c43c
16 changed files with 206 additions and 132 deletions

View file

@ -6,5 +6,9 @@ path = path_sound / "ambient"
class SoundAmbient(MediaGroup): class SoundAmbient(MediaGroup):
"""
Groupe contenant les sons ambient du jeu.
"""
menu = Sound(path / "menu.wav") menu = Sound(path / "menu.wav")
sea = Sound(path / "sea.wav") sea = Sound(path / "sea.wav")

View file

@ -6,6 +6,10 @@ path = path_sound / "effect"
class SoundEffect(MediaGroup): class SoundEffect(MediaGroup):
"""
Groupe contenant les effets sonores du jeu.
"""
placed = Sound(path / "placed.wav") placed = Sound(path / "placed.wav")
touched = Sound(path / "touched.wav") touched = Sound(path / "touched.wav")
missed = Sound(path / "missed.wav") missed = Sound(path / "missed.wav")

View file

@ -5,7 +5,7 @@ import pyglet
class MediaGroup(ABC): class MediaGroup(ABC):
""" """
This class represent a music group that can be played. Cette classe représente un groupe de musique pouvant être joué.
""" """
player: pyglet.media.Player player: pyglet.media.Player

View file

@ -11,6 +11,10 @@ if TYPE_CHECKING:
class Sound(Media): class Sound(Media):
"""
Représente un son pouvant être joué par le lecteur.
"""
def __init__(self, path: Path): def __init__(self, path: Path):
self.path = path self.path = path

View file

@ -10,10 +10,21 @@ if TYPE_CHECKING:
class Media(ABC): class Media(ABC):
loaded_media: dict[Path, pyglet.media.Source] = {} """
Représente un type de média
"""
loaded_media: dict[Path, pyglet.media.Source] = {} # cache des médias chargés
@classmethod @classmethod
def get_media(cls, path: Path, owner: "MediaGroup") -> pyglet.media.Source: def get_media(cls, path: Path, owner: "MediaGroup") -> pyglet.media.Source:
"""
Renvoie le média correspondant au chemin donné
:param path: le chemin du media
:param owner: la classe qui a appelé la fonction
:return: le média
"""
if (media := cls.loaded_media.get(path)) is None: if (media := cls.loaded_media.get(path)) is None:
# charge le son # charge le son
media = pyglet.media.load(path) media = pyglet.media.load(path)
@ -38,4 +49,10 @@ class Media(ABC):
@abstractmethod @abstractmethod
def __get__(self, instance, owner) -> pyglet.media.Source: def __get__(self, instance, owner) -> pyglet.media.Source:
"""
Renvoie le média correspondant à l'instance donnée
:param instance: instance de la classe qui a appelé la fonction
:param owner: classe ayant appelé la fonction
:return: le media
"""
pass pass

View file

@ -14,8 +14,9 @@ if TYPE_CHECKING:
class Button(BoxWidget): class Button(BoxWidget):
""" """
A button widget with a background texture that change depending on if it is clicked or hovered, and a label. Un bouton avec une texture de fond qui change en fonction de s'il est cliqué ou survolé et un label.
You can pass parameter to the background and label by adding "background_" and "label_" before the parameter. Vous pouvez passer des paramètres pour le background et au label en ajoutant "background_" et "label_"
devant le paramètre.
""" """
def __init__(self, scene: "Scene", def __init__(self, scene: "Scene",
@ -48,17 +49,17 @@ class Button(BoxWidget):
self.add_listener("on_hover_change", lambda *_: self._refresh_background()) self.add_listener("on_hover_change", lambda *_: self._refresh_background())
self.add_listener("on_click_change", lambda *_: self._refresh_background()) self.add_listener("on_click_change", lambda *_: self._refresh_background())
self._refresh_size() # refresh the size and position for the background and label self._refresh_size() # rafraîchit la taille et la position du background et du label
# background # background
@property @property
def background_texture(self) -> pyglet.image.AbstractImage: def background_texture(self) -> pyglet.image.AbstractImage:
""" """
Return the correct texture for the background. Renvoie la bonne texture pour le fond.
The clicking texture per default, if hover the hovered texture (if it exists) Utilise la texture normale par défaut, si survolé la texture de survol (si elle existe)
and if click the clicking texture (if it exists) et la texture de clic (si elle existe) si cliqué
:return: the corresponding texture :return: la texture correspondante
""" """
return ( return (

View file

@ -12,7 +12,7 @@ if TYPE_CHECKING:
class Checkbox(BoxWidget): class Checkbox(BoxWidget):
""" """
A checkbox widget with a background texture that change depending on if it is checked or unchecked. Un widget de checkbox avec une texture d'arrière-plan qui change en fonction de si elle est cochée ou non.
""" """
def __init__(self, scene: "Scene", def __init__(self, scene: "Scene",
@ -43,7 +43,7 @@ class Checkbox(BoxWidget):
self._refresh_size() self._refresh_size()
# refreshing # rafraichissement
@property @property
def tick_texture(self): def tick_texture(self):
@ -56,7 +56,7 @@ class Checkbox(BoxWidget):
self.tick.x, self.tick.y = self.xy self.tick.x, self.tick.y = self.xy
self.tick.width, self.tick.height = self.size self.tick.width, self.tick.height = self.size
# property # propriétés
@property @property
def state(self): def state(self):

View file

@ -19,7 +19,7 @@ if TYPE_CHECKING:
class GameGrid(BoxWidget): class GameGrid(BoxWidget):
""" """
A widget that represent a game grid. Un widget représentant la grille du jeu
""" """
def __init__(self, scene: "Scene", def __init__(self, scene: "Scene",
@ -49,7 +49,7 @@ class GameGrid(BoxWidget):
self.group_cursor = pyglet.graphics.Group(order=1) self.group_cursor = pyglet.graphics.Group(order=1)
self.group_line = pyglet.graphics.Group(order=2) self.group_line = pyglet.graphics.Group(order=2)
# the list of the size of the boats to place # la liste des tailles des bateaux a placé sur la grille
self.boats_length = [] if boats_length is None else sorted(boats_length, reverse=True) self.boats_length = [] if boats_length is None else sorted(boats_length, reverse=True)
# créer la planche du jeu # créer la planche du jeu
@ -104,13 +104,13 @@ class GameGrid(BoxWidget):
int((rel_y-1) / self.cell_height) int((rel_y-1) / self.cell_height)
) )
# refresh # rafraichissement
def _refresh_size(self): def _refresh_size(self):
self.background.x, self.background.y = self.xy self.background.x, self.background.y = self.xy
self.background.width, self.background.height = self.size self.background.width, self.background.height = self.size
# lines # lignes
for column, line in enumerate(self.lines[:self.columns - 1], start=1): for column, line in enumerate(self.lines[:self.columns - 1], start=1):
line.x = self.x + self.cell_width * column line.x = self.x + self.cell_width * column
@ -149,7 +149,7 @@ class GameGrid(BoxWidget):
self.cursor.y = self.y + cell_y * self.height / self.rows self.cursor.y = self.y + cell_y * self.height / self.rows
self.cursor.width, self.cursor.height = self.cell_size self.cursor.width, self.cursor.height = self.cell_size
self.preview_boat((cell_x, cell_y)) # display the preview of the boat on this cell self.preview_boat((cell_x, cell_y)) # affiche la grille du jeu en prévisualisant cette cellule
# function # function
@ -161,7 +161,11 @@ class GameGrid(BoxWidget):
self.display_board(self.board) self.display_board(self.board)
def display_board(self, board: Board, preview: bool = False): def display_board(self, board: Board, preview: bool = False):
# remplacer par l'utilisation de board.boats ? """
Affiche la grille du jeu.
:param board: la grille du jeu à afficher
:param preview: la prévisualisation du dernier bateau est-elle activée ?
"""
matrice = board.boats matrice = board.boats
max_boat: int = np.max(matrice) max_boat: int = np.max(matrice)
@ -220,12 +224,21 @@ class GameGrid(BoxWidget):
self._refresh_size() self._refresh_size()
def swap_orientation(self): def swap_orientation(self):
"""
Inverse l'orientation du bateau en cours de placement.
"""
self.orientation = ( self.orientation = (
Orientation.HORIZONTAL if self.orientation is Orientation.VERTICAL else Orientation.HORIZONTAL if self.orientation is Orientation.VERTICAL else
Orientation.VERTICAL Orientation.VERTICAL
) )
def place_boat(self, cell: Point2D): def place_boat(self, cell: Point2D):
"""
Place un bateau sur la grille du jeu.
:param cell: position sur laquelle placer le bateau
"""
if len(self.boats_length) == 0: return if len(self.boats_length) == 0: return
try: try:
@ -234,10 +247,10 @@ class GameGrid(BoxWidget):
cell cell
) )
except InvalidBoatPosition: except InvalidBoatPosition:
pass # if the boat can't be placed, ignore pass # si le bateau n'a pas pu être placé, ignore
else: # if the boat have been placed else: # si le bateau a bien été placé
self.boats_length.pop(0) # remove the boat from the list of boat to place self.boats_length.pop(0) # retire la taille du bateau de la liste des bateaux à placer
self.trigger_event("on_boat_placed") self.trigger_event("on_boat_placed")
if len(self.boats_length) == 0: if len(self.boats_length) == 0:
@ -246,6 +259,11 @@ class GameGrid(BoxWidget):
self.refresh_board() # rafraichi l'affichage self.refresh_board() # rafraichi l'affichage
def preview_boat(self, cell: Point2D): def preview_boat(self, cell: Point2D):
"""
Prévisualise le prochain bateau à placer.
:param cell: position visualiser le bateau
"""
if len(self.boats_length) == 0: return if len(self.boats_length) == 0: return
try: try:
@ -260,6 +278,13 @@ class GameGrid(BoxWidget):
else: self.display_board(preview_board, preview=True) else: self.display_board(preview_board, preview=True)
def place_bomb(self, cell: Point2D, force_touched: bool = None) -> BombState: def place_bomb(self, cell: Point2D, force_touched: bool = None) -> BombState:
"""
Place une bombe sur la grille du jeu.
:param cell: cellule sur laquelle placer la bombe
:param force_touched: la cellule doit-elle forcer l'affichage comment étant manqué ou touché ?
:return: l'état de la bombe
"""
bomb_state = self.board.bomb(cell) bomb_state = self.board.bomb(cell)
if force_touched is not None: if force_touched is not None:
@ -270,7 +295,10 @@ class GameGrid(BoxWidget):
return bomb_state return bomb_state
def remove_bomb(self, cell: Point2D): def remove_bomb(self, cell: Point2D):
# retire une bombe de la planche """
Retire une bombe de la grille du jeu.
:param cell: cellule de la bombe à retirer
"""
self.board.remove_bomb(cell) self.board.remove_bomb(cell)
self.refresh_board() self.refresh_board()
@ -278,29 +306,27 @@ class GameGrid(BoxWidget):
cell = self.get_cell_from_rel(rel_x, rel_y) cell = self.get_cell_from_rel(rel_x, rel_y)
match button: match button:
# si le joueur fait un clic droit, inverse l'orientation du bateau en cours de placement
case pyglet.window.mouse.RIGHT: case pyglet.window.mouse.RIGHT:
self.swap_orientation() self.swap_orientation()
self.preview_boat(cell) self.preview_boat(cell)
# si le joueur fait un clic gauche, place un bateau ou une bombe
case pyglet.window.mouse.LEFT: case pyglet.window.mouse.LEFT:
self.place_boat(cell) self.place_boat(cell)
self.trigger_event("on_request_place_bomb", cell) self.trigger_event("on_request_place_bomb", cell)
# property # propriétés
@property @property
def cell_width(self) -> float: def cell_width(self) -> float: return self.width / self.columns
return self.width / self.columns
@property @property
def cell_height(self) -> float: def cell_height(self) -> float: return self.height / self.rows
return self.height / self.rows
@property @property
def cell_size(self) -> tuple[float, float]: def cell_size(self) -> tuple[float, float]: return self.cell_width, self.cell_height
return self.cell_width, self.cell_height
# event # événements
def on_resize(self, width: int, height: int): def on_resize(self, width: int, height: int): self._refresh_size()
self._refresh_size()

View file

@ -12,7 +12,7 @@ if TYPE_CHECKING:
class Image(BoxWidget): class Image(BoxWidget):
""" """
An image widget with a texture. Un widget d'image avec une texture.
""" """
def __init__(self, scene: "Scene", def __init__(self, scene: "Scene",

View file

@ -15,7 +15,7 @@ if TYPE_CHECKING:
class Input(BoxWidget): class Input(BoxWidget):
""" """
An input widget with a background texture and a label. A regex pattern can be added to validate the input. Un widget d'entrée avec une texture de fond et un label. Des paternes regex peut être ajouté pour valider l'entrée.
""" """
def __init__(self, scene: "Scene", def __init__(self, scene: "Scene",
@ -64,18 +64,19 @@ class Input(BoxWidget):
@property @property
def background_texture(self) -> pyglet.image.AbstractImage: def background_texture(self) -> pyglet.image.AbstractImage:
""" """
Return the correct texture for the background. Renvoie la texture de fond correspondante.
The clicking texture per default, if hover the hovered texture (if it exists) Si le widget est activé, renvoie la texture active (si elle existe),
and if click the clicking texture (if it exists) la texture de clic (si elle existe) sinon la texture normale
:return: the corresponding texture :return: la texture de fond correspondante
""" """
return ( return (
texture if self.activated and (texture := self.style.get("active")) is not None else # NOQA texture if self.activated and (texture := self.style.get("active")) is not None else # NOQA
texture if not self.valid and (texture := self.style.get("error")) is not None else texture if not self.valid and (texture := self.style.get("error")) is not None else
self.style.get("normal") self.style.get("normal")
) )
# refresh # rafraichissement
def _refresh_background(self) -> None: def _refresh_background(self) -> None:
self.background.image = self.background_texture self.background.image = self.background_texture
@ -94,8 +95,7 @@ class Input(BoxWidget):
# property # property
@property @property
def valid(self): def valid(self): return self._valid
return self._valid
@valid.setter @valid.setter
def valid(self, valid: bool): def valid(self, valid: bool):
@ -103,14 +103,12 @@ class Input(BoxWidget):
self._refresh_background() self._refresh_background()
@property @property
def text(self): def text(self): return self.label.text
return self.label.text
@text.setter @text.setter
def text(self, text: str): def text(self, text: str): self.label.text = text
self.label.text = text
# event # événements
def on_key_press(self, symbol: int, modifiers: int): def on_key_press(self, symbol: int, modifiers: int):
if not self.activated: return # ignore si ce widget est désactivé / non sélectionné if not self.activated: return # ignore si ce widget est désactivé / non sélectionné

View file

@ -12,8 +12,7 @@ if TYPE_CHECKING:
class Scroller(BoxWidget): class Scroller(BoxWidget):
""" """
A scroller widget with a background texture, a scroller and a label. Un widget qui affiche un curseur qui peut être déplacé entre deux valeurs.
The cursor can be moved between the "from" and the "to" value
""" """
def __init__(self, scene: "Scene", def __init__(self, scene: "Scene",
@ -64,7 +63,7 @@ class Scroller(BoxWidget):
self._to = to self._to = to
self.value = value self.value = value
# refresh # rafraichissement
def _refresh(self): def _refresh(self):
# background # background
@ -91,7 +90,7 @@ class Scroller(BoxWidget):
def _refresh_cursor(self, rel_x: int): def _refresh_cursor(self, rel_x: int):
self.value = (rel_x / self.width) * (self.to - self.from_) + self.from_ self.value = (rel_x / self.width) * (self.to - self.from_) + self.from_
# property # propriétés
@property @property
def value(self): def value(self):
@ -122,7 +121,7 @@ class Scroller(BoxWidget):
self._to = to self._to = to
self._refresh() self._refresh()
# event # événements
def on_resize(self, width: int, height: int): def on_resize(self, width: int, height: int):
self._refresh() self._refresh()

View file

@ -11,7 +11,7 @@ if TYPE_CHECKING:
class Text(BoxWidget): class Text(BoxWidget):
""" """
A widget that display a text Un widget qui affiche du texte
""" """
def __init__(self, scene: "Scene", def __init__(self, scene: "Scene",

View file

@ -11,7 +11,7 @@ if TYPE_CHECKING:
class BoxWidget(Widget, ABC): class BoxWidget(Widget, ABC):
""" """
Same as a basic widget, but inside a box Pareil qu'un Widget, mais dans une boîte de collision (bbox)
""" """
def __init__(self, scene: "Scene", def __init__(self, scene: "Scene",
@ -21,23 +21,23 @@ class BoxWidget(Widget, ABC):
height: Distance = None): height: Distance = None):
super().__init__(scene) super().__init__(scene)
# memorize the value with a percent value # Défini les bordures de la boîte de collision. Peut utiliser des nombres ou des unités de distance
self.x = x self.x = x
self.y = y self.y = y
self.width = width self.width = width
self.height = height self.height = height
self.hovering = False # is the button currently hovered ? self.hovering = False # La bbox est-elle actuellement survolée ?
self.clicking = False # is the button currently clicked ? self.clicking = False # La bbox est-elle actuellement cliqué ?
self.activated = False # is the button activated ? (the last click was inside this widget) self.activated = False # La bbox est-il actuellement activé ? (le dernier clic a été à l'intérieur)
# property # propriétés
def _getter_distance(self, raw_distance: Distance) -> int: def _getter_distance(self, raw_distance: Distance) -> int:
""" """
Return the true distance in pixel from a more abstract distance Renvoie la distance en pixel d'une distance abstraite
:param raw_distance: the distance object to convert to pixel :param raw_distance: la distance à convertir en pixel
:return: the true distance in pixel :return: la vrai distance en pixel
""" """
if isinstance(raw_distance, int): return raw_distance if isinstance(raw_distance, int): return raw_distance
@ -47,88 +47,71 @@ class BoxWidget(Widget, ABC):
raise TypeError(f"Invalid type for the distance : {type(raw_distance)}") raise TypeError(f"Invalid type for the distance : {type(raw_distance)}")
@property @property
def x(self) -> int: def x(self) -> int: return self._getter_distance(self._x)
return self._getter_distance(self._x)
@x.setter @x.setter
def x(self, x: Distance): def x(self, x: Distance): self._x = x
self._x = x
@property @property
def y(self) -> int: def y(self) -> int: return self._getter_distance(self._y)
return self._getter_distance(self._y)
@y.setter @y.setter
def y(self, y: Distance): def y(self, y: Distance): self._y = y
self._y = y
@property @property
def xy(self) -> tuple[int, int]: def xy(self) -> tuple[int, int]: return self.x, self.y
return self.x, self.y
@property @property
def x2(self) -> int: def x2(self) -> int: return self.x + self.width
return self.x + self.width
@property @property
def y2(self) -> int: def y2(self) -> int: return self.y + self.height
return self.y + self.height
@property @property
def xy2(self) -> tuple[int, int]: def xy2(self) -> tuple[int, int]: return self.x2, self.y2
return self.x2, self.y2
@property @property
def width(self) -> int: def width(self) -> int: return self._getter_distance(self._width)
return self._getter_distance(self._width)
@width.setter @width.setter
def width(self, width: Optional[Distance]): def width(self, width: Optional[Distance]): self._width = width
self._width = width
@property @property
def height(self) -> int: def height(self) -> int: return self._getter_distance(self._height)
return self._getter_distance(self._height)
@height.setter @height.setter
def height(self, height: Optional[Distance]): def height(self, height: Optional[Distance]): self._height = height
self._height = height
@property @property
def size(self) -> tuple[int, int]: def size(self) -> tuple[int, int]: return self.width, self.height
return self.width, self.height
@property @property
def bbox(self) -> tuple[int, int, int, int]: def bbox(self) -> tuple[int, int, int, int]: return self.x, self.y, self.x2, self.y2
return self.x, self.y, self.x2, self.y2
@property @property
def center_x(self) -> float: def center_x(self) -> float: return self.x + (self.width / 2)
return self.x + (self.width / 2)
@property @property
def center_y(self) -> float: def center_y(self) -> float: return self.y + (self.height / 2)
return self.y + (self.height / 2)
@property @property
def center(self) -> tuple[float, float]: def center(self) -> tuple[float, float]: return self.center_x, self.center_y
return self.center_x, self.center_y
# function # fonctions
def in_bbox(self, point: Point2D) -> bool: def in_bbox(self, point: Point2D) -> bool:
return in_bbox(point, self.bbox) return in_bbox(point, self.bbox)
# event # événements
def on_mouse_motion(self, x: int, y: int, dx: int, dy: int): def on_mouse_motion(self, x: int, y: int, dx: int, dy: int):
""" """
When the mouse is moved, this event is triggered. Lorsque la souris est déplacée, cet événement est déclenché.
Allow the implementation of the on_hover_enter and on_hover_leave events Permet d'implémenter les événements on_hover, on_hover_enter et on_hover_leave
:x: the x position of the mouse :param x: la position x de la souris
:y: the y position of the mouse :param y: la position y de la souris
:dx: the difference of the x mouse axis :param dx: la différence de la position x de la souris
:dy: the difference of the y mouse axis :param dy: la différence de la position y de la souris
""" """
rel_x, rel_y = x - self.x, y - self.y rel_x, rel_y = x - self.x, y - self.y
@ -136,39 +119,59 @@ class BoxWidget(Widget, ABC):
old_hovering = self.hovering old_hovering = self.hovering
self.hovering = self.in_bbox((x, y)) self.hovering = self.in_bbox((x, y))
if old_hovering != self.hovering: # if the hover changed if old_hovering != self.hovering: # si le survole a changé d'état
# call the hover changed event # appelle d'événement on_hover_change
self.trigger_event("on_hover_change", rel_x, rel_y) self.trigger_event("on_hover_change", rel_x, rel_y)
# call the hover enter / leave event # appelle l'événement on_hover_enter ou on_hover_leave selon la valeur
self.trigger_event("on_hover_enter" if self.hovering else "on_hover_leave", rel_x, rel_y) self.trigger_event("on_hover_enter" if self.hovering else "on_hover_leave", rel_x, rel_y)
if self.hovering: # if the mouse motion is inside the collision if self.hovering: # si la souris est dans la bbox actuellement
self.trigger_event("on_hover", rel_x, rel_y) # call the hover event self.trigger_event("on_hover", rel_x, rel_y) # appelle l'événement on_hover
def on_mouse_press(self, x: int, y: int, button: int, modifiers: int): def on_mouse_press(self, x: int, y: int, button: int, modifiers: int):
"""
Lorsque la souris est cliqué, cet événement est déclenché.
:param x: la position x de la souris
:param y: la position y de la souris
:param button: button de la souris cliqué
:param modifiers: modificateur du bouton de la souris
"""
rel_x, rel_y = x - self.x, y - self.y rel_x, rel_y = x - self.x, y - self.y
self.activated = self.in_bbox((x, y)) self.activated = self.in_bbox((x, y))
self.trigger_event("on_activate_change", rel_x, rel_y, button, modifiers) self.trigger_event("on_activate_change", rel_x, rel_y, button, modifiers)
if self.activated: # if the click was inside the widget if self.activated: # si le clic s'est produit dans la bbox
# appel des événements on_activate_enter
self.trigger_event("on_activate_enter", rel_x, rel_y, button, modifiers) self.trigger_event("on_activate_enter", rel_x, rel_y, button, modifiers)
self.clicking = True # the widget is also now clicked self.clicking = True # défini le widget comme étant à présent cliqué
# appel des événements on_click_change et on_click_press
self.trigger_event("on_click_change", rel_x, rel_y, button, modifiers) self.trigger_event("on_click_change", rel_x, rel_y, button, modifiers)
self.trigger_event("on_click_press", rel_x, rel_y, button, modifiers) self.trigger_event("on_click_press", rel_x, rel_y, button, modifiers)
else: else:
# si le clic n'était pas dans la bbox, appel de l'événement on_activate_leave
self.trigger_event("on_activate_leave", rel_x, rel_y, button, modifiers) self.trigger_event("on_activate_leave", rel_x, rel_y, button, modifiers)
def on_mouse_release(self, x: int, y: int, button: int, modifiers: int): def on_mouse_release(self, x: int, y: int, button: int, modifiers: int):
"""
Lorsque le clic de la souris est relâché, cet événement est déclenché.
:param x: la position x de la souris
:param y: la position y de la souris
:param button: button de la souris cliqué
:param modifiers: modificateur du bouton de la souris
"""
rel_x, rel_y = x - self.x, y - self.y rel_x, rel_y = x - self.x, y - self.y
old_click: bool = self.clicking old_click: bool = self.clicking
self.clicking = False # the widget is no longer clicked self.clicking = False # le widget n'est plus cliqué
if not self.in_bbox((x, y)): return # if the release was not in the collision, ignore if not self.in_bbox((x, y)): return # si le clic n'a pas été relâché dans la bbox, ignore
if old_click: # if this button was the one hovered when the click was pressed if old_click: # si ce bouton était celui qui était survolé lorsque le bouton a été cliqué
# déclenche les événements on_click_change et on_click_release
self.trigger_event("on_click_change", rel_x, rel_y, button, modifiers) self.trigger_event("on_click_change", rel_x, rel_y, button, modifiers)
self.trigger_event("on_click_release", rel_x, rel_y, button, modifiers) self.trigger_event("on_click_release", rel_x, rel_y, button, modifiers)

View file

@ -9,9 +9,9 @@ if TYPE_CHECKING:
class Widget(Listener, ABC): class Widget(Listener, ABC):
""" """
A Widget that can be attached to a scene. Un widget pouvant être attaché à une scène.
It can react to any "on_" event from the scene. Il peut réagir à n'importe quel événement "on_" de la scène.
""" """
def __init__(self, scene: "Scene", **kwargs): def __init__(self, scene: "Scene", **kwargs):

View file

@ -9,7 +9,7 @@ from source.type import ColorRGBA
class GameWindow(Window): # NOQA class GameWindow(Window): # NOQA
""" """
Similar to the normal Window, but add small feature useful for a game like a fps counter. Similaire à la classe Window, mais ajoute quelque fonctionnalités pratique pour un jeu. (Option, FPS, etc.)
""" """
def __init__(self, def __init__(self,
@ -34,6 +34,10 @@ class GameWindow(Window): # NOQA
pyglet.clock.schedule_once(lambda *_: self.load_option(), 0) pyglet.clock.schedule_once(lambda *_: self.load_option(), 0)
def load_option(self): def load_option(self):
"""
Charge les options depuis le fichier self.option_path.
"""
try: try:
if self.option_path.exists(): if self.option_path.exists():
self.option = Option.load(self, self.option_path) self.option = Option.load(self, self.option_path)
@ -43,4 +47,5 @@ class GameWindow(Window): # NOQA
if self.option is None: self.option = Option(window=self) if self.option is None: self.option = Option(window=self)
def on_draw_after(self): def on_draw_after(self):
# après que tous les éléments ont été dessinés, dessiner le compteur de FPS s'il est activé.
if self.fps_enable: self._fps_counter.draw() if self.fps_enable: self._fps_counter.draw()

View file

@ -12,8 +12,8 @@ if TYPE_CHECKING:
class Window(pyglet.window.Window, EventPropagationMixin): # NOQA class Window(pyglet.window.Window, EventPropagationMixin): # NOQA
""" """
A window. Based on the pyglet window object. Une fenêtre basée sur l'objet Window de pyglet.
Scene can be added to the window Des scènes peuvent y être placé.
""" """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -24,12 +24,21 @@ class Window(pyglet.window.Window, EventPropagationMixin): # NOQA
@property @property
def childs(self): def childs(self):
"""
Renvoie les scènes de la fenêtre. Utilisé pour la propagation d'événements.
:return: les scènes de la fenêtre.
"""
return self._scenes return self._scenes
# FPS # FPS
@staticmethod @staticmethod
def get_fps() -> float: def get_fps() -> float:
"""
Renvoie le nombre de FPS actuel de la fenêtre.
:return: le nombre de FPS actuel de la fenêtre.
"""
# on récupère la fonction responsable du rafraichissement de la fenêtre # on récupère la fonction responsable du rafraichissement de la fenêtre
refresh_func = pyglet.app.event_loop._redraw_windows # NOQA refresh_func = pyglet.app.event_loop._redraw_windows # NOQA
@ -47,6 +56,11 @@ class Window(pyglet.window.Window, EventPropagationMixin): # NOQA
@staticmethod @staticmethod
def set_fps(value: float): def set_fps(value: float):
"""
Définit le nombre de FPS de la fenêtre.
:param value: nombre de FPS souhaité
"""
# on récupère la fonction responsable du rafraichissement de la fenêtre # on récupère la fonction responsable du rafraichissement de la fenêtre
refresh_func = pyglet.app.event_loop._redraw_windows # NOQA refresh_func = pyglet.app.event_loop._redraw_windows # NOQA
@ -62,24 +76,23 @@ class Window(pyglet.window.Window, EventPropagationMixin): # NOQA
# Scene Managing # Scene Managing
def set_scene(self, scene_class: Type["Scene"], *scene_args, **scene_kwargs) -> "Scene": def set_scene(self, scene_class: Type["Scene"], **scene_kwargs) -> "Scene":
""" """
Set the scene of the window. Défini la scène actuelle pour la fenêtre.
:scene_class: the class of the scene to add. :scene_class: la classe de la scène à ajouter
:scene_args: args for the creation of the scene object. :scene_kwargs: les arguments clés de la scène
:scene_kwargs: kwargs for the creation of the scene object. :return: la nouvelle scène créée
:return: the new created scene.
""" """
self.clear_scene() self.clear_scene()
return self.add_scene(scene_class, *scene_args, **scene_kwargs) return self.add_scene(scene_class, **scene_kwargs)
def add_scene(self, scene_class: Type["Scene"], priority: int = 0, **scene_kwargs) -> "Scene": def add_scene(self, scene_class: Type["Scene"], priority: int = 0, **scene_kwargs) -> "Scene":
""" """
Add a scene of the window. Ajoute une scène à la fenêtre.
:scene_class: the class of the scene to add. :scene_class: la classe de la scène à ajouter
:scene_kwargs: kwargs for the creation of the scene object. :scene_kwargs: les arguments clés de la scène
:return: the new created scene. :return: la nouvelle scène créée
""" """
scene: "Scene" = scene_class(window=self, **scene_kwargs) scene: "Scene" = scene_class(window=self, **scene_kwargs)
@ -88,15 +101,15 @@ class Window(pyglet.window.Window, EventPropagationMixin): # NOQA
def remove_scene(self, scene: "Scene") -> None: def remove_scene(self, scene: "Scene") -> None:
""" """
Remove a scene from the window. Retire une scène spécifique de la fenêtre
:scene: the scene to remove. :scene: la scène à retirer
""" """
self._scenes.remove(scene) self._scenes.remove(scene)
def clear_scene(self) -> None: def clear_scene(self) -> None:
""" """
Clear the window from all the scenes. Retire toutes les scènes de la fenêtre.
""" """
self._scenes.clear() self._scenes.clear()