diff --git a/assets/test_button_hover.png b/assets/test_button_hover.png new file mode 100644 index 0000000..89cbda0 Binary files /dev/null and b/assets/test_button_hover.png differ diff --git a/assets/test_button_normal.png b/assets/test_button_normal.png new file mode 100644 index 0000000..706e5f1 Binary files /dev/null and b/assets/test_button_normal.png differ diff --git a/gui/scene/FPSCounterScene.py b/gui/scene/FPSCounterScene.py deleted file mode 100644 index f10c5b4..0000000 --- a/gui/scene/FPSCounterScene.py +++ /dev/null @@ -1,22 +0,0 @@ -from typing import Optional - -import pyglet - -from gui.scene import Scene -from gui.window import Window - - -class FPSCounterScene(Scene): - """ - This scene represent a simple FPS Counter. - """ - - def __init__(self): - self.fps_display: Optional[pyglet.window.FPSDisplay] = None - - def on_window_added(self, window: Window): - # the fps display need to be defined here because it is the moment where the window is first accessible - self.fps_display = pyglet.window.FPSDisplay(window=window) - - def on_draw(self, window: Window) -> None: - self.fps_display.draw() diff --git a/gui/scene/Scene.py b/gui/scene/Scene.py deleted file mode 100644 index 6e79a1f..0000000 --- a/gui/scene/Scene.py +++ /dev/null @@ -1,43 +0,0 @@ -import pyglet.event - -from gui.window import Window - - -class Scene(pyglet.event.EventDispatcher): - """ - This class represent a scene that can be applied to a pyglet window. - - The scene can represent anything like the main menu, the game, the - options' menu, the multiplayer menu, ... - """ - - def on_window_added(self, window: Window): pass # when the Scene is added to a window - def on_window_removed(self, window: Window): pass # when the Scene is removed from a window - - def on_draw(self, window: Window): pass - def on_resize(self, window: Window, width: int, height: int): pass - def on_hide(self, window: Window): pass - def on_show(self, window: Window): pass - def on_close(self, window: Window): pass - def on_expose(self, window: Window): pass - def on_activate(self, window: Window): pass - def on_deactivate(self, window: Window): pass - def on_text(self, window: Window, char: str): pass - def on_move(self, window: Window, x: int, y: int): pass - def on_context_lost(self, window: Window): pass - def on_context_state_lost(self, window: Window): pass - def on_key_press(self, window: Window, symbol: int, modifiers: int): pass - def on_key_release(self, window: Window, symbol: int, modifiers: int): pass - def on_key_held(self, window: Window, dt: float, symbol: int, modifiers: int): pass - def on_mouse_enter(self, window: Window, x: int, y: int): pass - def on_mouse_leave(self, window: Window, x: int, y: int): pass - def on_text_motion(self, window: Window, motion: int): pass - def on_text_motion_select(self, window: Window, motion: int): pass - def on_mouse_motion(self, window: Window, x: int, y: int, dx: int, dy: int): pass - def on_mouse_press(self, window: Window, x: int, y: int, button: int, modifiers: int): pass - def on_mouse_release(self, window: Window, x: int, y: int, button: int, modifiers: int): pass - def on_mouse_drag(self, window: Window, x: int, y: int, dx: int, dy: int, buttons: int, modifiers: int): pass - def on_mouse_scroll(self, window: Window, x: int, y: int, scroll_x: float, scroll_y: float): pass - - - diff --git a/main.pyw b/main.pyw index ad70233..1df1c41 100644 --- a/main.pyw +++ b/main.pyw @@ -1,12 +1,29 @@ import pyglet -from gui.window import Window -from gui.scene import HelloWorldScene, FPSCounterScene +from source.gui.widget.Button import Button +from source.gui.window import Window +from source.gui.scene import HelloWorldScene, FPSCounterScene # Créer une fenêtre window = Window(resizable=True, visible=False) -window.add_scene(HelloWorldScene(), FPSCounterScene()) +button_normal_image = pyglet.image.load("./assets/test_button_normal.png") +button_hover_image = pyglet.image.load("./assets/test_button_hover.png") + +hello_world_scene = HelloWorldScene() + +button = Button( + 50, 50, 300, 100, + text="HELLO", + on_release=lambda *a, **b: print(a, b), + normal_image=button_normal_image, + hover_image=button_hover_image, +) + +hello_world_scene.add_widget(button) +fps_counter_scene = FPSCounterScene() + +window.add_scene(hello_world_scene, fps_counter_scene) # Lance la fenêtre window.set_visible(True) diff --git a/source/__init__.py b/source/__init__.py index d63e215..e69de29 100644 --- a/source/__init__.py +++ b/source/__init__.py @@ -1,2 +0,0 @@ -from .Boat import Boat -from .Board import Board diff --git a/source/Board.py b/source/core/Board.py similarity index 96% rename from source/Board.py rename to source/core/Board.py index 8024dd1..3663822 100644 --- a/source/Board.py +++ b/source/core/Board.py @@ -1,8 +1,8 @@ import numpy as np -from source import Boat -from source.enums import Orientation, BombState -from source.error import InvalidBoatPosition, PositionAlreadyShot +from source.core import Boat +from source.core.enums import Orientation, BombState +from source.core.error import InvalidBoatPosition, PositionAlreadyShot from source.utils import copy_array_offset diff --git a/source/Boat.py b/source/core/Boat.py similarity index 94% rename from source/Boat.py rename to source/core/Boat.py index 52a3cd0..6c815f9 100644 --- a/source/Boat.py +++ b/source/core/Boat.py @@ -1,6 +1,6 @@ import numpy as np -from source.enums import Orientation +from source.core.enums import Orientation class Boat: diff --git a/gui/__init__.py b/source/core/__init__.py similarity index 100% rename from gui/__init__.py rename to source/core/__init__.py diff --git a/source/enums/__init__.py b/source/core/enums/__init__.py similarity index 100% rename from source/enums/__init__.py rename to source/core/enums/__init__.py diff --git a/source/enums/bomb.py b/source/core/enums/bomb.py similarity index 100% rename from source/enums/bomb.py rename to source/core/enums/bomb.py diff --git a/source/enums/orientation.py b/source/core/enums/orientation.py similarity index 100% rename from source/enums/orientation.py rename to source/core/enums/orientation.py diff --git a/source/error/InvalidBoatPosition.py b/source/core/error/InvalidBoatPosition.py similarity index 100% rename from source/error/InvalidBoatPosition.py rename to source/core/error/InvalidBoatPosition.py diff --git a/source/error/PositionAlreadyShot.py b/source/core/error/PositionAlreadyShot.py similarity index 100% rename from source/error/PositionAlreadyShot.py rename to source/core/error/PositionAlreadyShot.py diff --git a/source/error/__init__.py b/source/core/error/__init__.py similarity index 100% rename from source/error/__init__.py rename to source/core/error/__init__.py diff --git a/source/gui/__init__.py b/source/gui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/source/gui/scene/FPSCounterScene.py b/source/gui/scene/FPSCounterScene.py new file mode 100644 index 0000000..728d1c1 --- /dev/null +++ b/source/gui/scene/FPSCounterScene.py @@ -0,0 +1,30 @@ +from typing import Optional, TYPE_CHECKING + +import pyglet + +from source.gui.scene.base import Scene + +if TYPE_CHECKING: + from source.gui.window import Window + + +class FPSCounterScene(Scene): + """ + This scene represent a simple FPS Counter. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.fps_display: Optional[pyglet.window.FPSDisplay] = None + + def on_window_added(self, window: "Window"): + super().on_window_added(window) + + # the fps display need to be defined here because it is the moment where the window is first accessible + self.fps_display = pyglet.window.FPSDisplay(window=window) + + def on_draw(self, window: "Window") -> None: + super().on_draw(window) + + self.fps_display.draw() diff --git a/gui/scene/HelloWorldScene.py b/source/gui/scene/HelloWorldScene.py similarity index 60% rename from gui/scene/HelloWorldScene.py rename to source/gui/scene/HelloWorldScene.py index 1d48600..4dad084 100644 --- a/gui/scene/HelloWorldScene.py +++ b/source/gui/scene/HelloWorldScene.py @@ -2,8 +2,12 @@ from datetime import datetime, timedelta import pyglet -from gui.scene import Scene -from gui.window import Window +from source.gui.scene.base import Scene + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from source.gui.window import Window class HelloWorldScene(Scene): @@ -14,7 +18,9 @@ class HelloWorldScene(Scene): The text is centered on the screen. """ - def __init__(self): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.label = pyglet.text.Label( "Hello World !", anchor_x="center", @@ -24,17 +30,25 @@ class HelloWorldScene(Scene): # remember the cooldown for the backspace button self._hold_backspace_last_call: datetime = datetime.now() - def on_draw(self, window: Window) -> None: + def on_draw(self, window: "Window") -> None: + super().on_draw(window) + self.label.draw() - def on_resize(self, window: Window, width: int, height: int) -> None: + def on_resize(self, window: "Window", width: int, height: int) -> None: + super().on_resize(window, width, height) + self.label.x = width // 2 self.label.y = height // 2 - def on_text(self, window: Window, char: str): + def on_text(self, window: "Window", char: str): + super().on_text(window, char) + self.label.text += char - def on_key_held(self, window: Window, dt: float, symbol: int, modifiers: int): + def on_key_held(self, window: "Window", dt: float, symbol: int, modifiers: int): + super().on_key_held(window, dt, symbol, modifiers) + if symbol == pyglet.window.key.BACKSPACE: # add a cooldown of 0.1 second on the backspace key diff --git a/source/gui/scene/MainMenu.py b/source/gui/scene/MainMenu.py new file mode 100644 index 0000000..b2eba66 --- /dev/null +++ b/source/gui/scene/MainMenu.py @@ -0,0 +1,18 @@ +from source.gui.scene.base import Scene +from source.gui.widget.Button import Button + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from source.gui.window import Window + + +class MainMenuScene(Scene): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.add_widget(Button()) + + def on_draw(self, window: "Window"): + super().on_draw(window) + diff --git a/gui/scene/__init__.py b/source/gui/scene/__init__.py similarity index 78% rename from gui/scene/__init__.py rename to source/gui/scene/__init__.py index 5d2aaee..8fa93cf 100644 --- a/gui/scene/__init__.py +++ b/source/gui/scene/__init__.py @@ -1,3 +1,2 @@ -from .Scene import Scene from .HelloWorldScene import HelloWorldScene from .FPSCounterScene import FPSCounterScene diff --git a/source/gui/scene/base/Scene.py b/source/gui/scene/base/Scene.py new file mode 100644 index 0000000..93dcb03 --- /dev/null +++ b/source/gui/scene/base/Scene.py @@ -0,0 +1,116 @@ +from pyglet.event import EventDispatcher + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from source.gui.widget.base import Widget + from source.gui.window import Window + + +class Scene(EventDispatcher): + """ + This class represent a scene that can be applied to a pyglet window. + + The scene can represent anything like the main menu, the game, the + options' menu, the multiplayer menu, ... + """ + + def __init__(self, widgets: list["Widget"] = None): + self._widgets: list["Widget"] = [] + if widgets is not None: self.add_widget(*widgets) + + def add_widget(self, *widgets: "Widget", priority: int = 0) -> None: + for widget in widgets: + self._widgets.insert(priority, widget) + widget.on_scene_added(self) + + def remove_widget(self, *widgets: "Widget") -> None: + for widget in widgets: + widget.on_scene_removed(self) + self._widgets.remove(widget) + + def clear_widget(self) -> None: + for widget in self._widgets: widget.on_scene_removed(self) + self._widgets.clear() + + # scene event + + def on_window_added(self, window: "Window"): # when the Scene is added to a window + for widget in self._widgets: widget.on_window_added(window, self) + + def on_window_removed(self, window: "Window"): # when the Scene is removed from a window + for widget in self._widgets: widget.on_window_removed(window, self) + + # window event + + def on_draw(self, window: "Window"): + for widget in self._widgets: widget.on_draw(window, self) + + def on_resize(self, window: "Window", width: int, height: int): + for widget in self._widgets: widget.on_resize(window, self, width, height) + + def on_hide(self, window: "Window"): + for widget in self._widgets: widget.on_hide(window, self) + + def on_show(self, window: "Window"): + for widget in self._widgets: widget.on_show(window, self) + + def on_close(self, window: "Window"): + for widget in self._widgets: widget.on_close(window, self) + + def on_expose(self, window: "Window"): + for widget in self._widgets: widget.on_expose(window, self) + + def on_activate(self, window: "Window"): + for widget in self._widgets: widget.on_activate(window, self) + + def on_deactivate(self, window: "Window"): + for widget in self._widgets: widget.on_deactivate(window, self) + + def on_text(self, window: "Window", char: str): + for widget in self._widgets: widget.on_text(window, self, char) + + def on_move(self, window: "Window", x: int, y: int): + for widget in self._widgets: widget.on_move(window, self, x, y) + + def on_context_lost(self, window: "Window"): + for widget in self._widgets: widget.on_context_lost(window, self) + + def on_context_state_lost(self, window: "Window"): + for widget in self._widgets: widget.on_context_state_lost(window, self) + + def on_key_press(self, window: "Window", symbol: int, modifiers: int): + for widget in self._widgets: widget.on_key_press(window, self, symbol, modifiers) + + def on_key_release(self, window: "Window", symbol: int, modifiers: int): + for widget in self._widgets: widget.on_key_release(window, self, symbol, modifiers) + + def on_key_held(self, window: "Window", dt: float, symbol: int, modifiers: int): + for widget in self._widgets: widget.on_key_held(window, self, dt, symbol, modifiers) + + def on_mouse_enter(self, window: "Window", x: int, y: int): + for widget in self._widgets: widget.on_mouse_enter(window, self, x, y) + + def on_mouse_leave(self, window: "Window", x: int, y: int): + for widget in self._widgets: widget.on_mouse_leave(window, self, x, y) + + def on_text_motion(self, window: "Window", motion: int): + for widget in self._widgets: widget.on_text_motion(window, self, motion) + + def on_text_motion_select(self, window: "Window", motion: int): + for widget in self._widgets: widget.on_text_motion_select(window, self, motion) + + def on_mouse_motion(self, window: "Window", x: int, y: int, dx: int, dy: int): + for widget in self._widgets: widget.on_mouse_motion(window, self, x, y, dx, dy) + + def on_mouse_press(self, window: "Window", x: int, y: int, button: int, modifiers: int): + for widget in self._widgets: widget.on_mouse_press(window, self, x, y, button, modifiers) + + def on_mouse_release(self, window: "Window", x: int, y: int, button: int, modifiers: int): + for widget in self._widgets: widget.on_mouse_release(window, self, x, y, button, modifiers) + + def on_mouse_drag(self, window: "Window", x: int, y: int, dx: int, dy: int, buttons: int, modifiers: int): + for widget in self._widgets: widget.on_mouse_drag(window, self, x, y, dx, dy, buttons, modifiers) + + def on_mouse_scroll(self, window: "Window", x: int, y: int, scroll_x: float, scroll_y: float): + for widget in self._widgets: widget.on_mouse_scroll(window, self, x, y, scroll_x, scroll_y) diff --git a/source/gui/scene/base/__init__.py b/source/gui/scene/base/__init__.py new file mode 100644 index 0000000..8abb0fe --- /dev/null +++ b/source/gui/scene/base/__init__.py @@ -0,0 +1 @@ +from .Scene import Scene diff --git a/source/gui/widget/Button.py b/source/gui/widget/Button.py new file mode 100644 index 0000000..c23266a --- /dev/null +++ b/source/gui/widget/Button.py @@ -0,0 +1,123 @@ +from typing import Callable, Optional, TYPE_CHECKING + +import pyglet + +from source.gui.widget.base import Widget +from source.utils import in_bbox + +if TYPE_CHECKING: + from source.gui.scene.base import Scene + from source.gui.window import Window + + +class Button(Widget): + __slots__ = ("_x", "_y", "_width", "_height", "_text", "on_press", "on_release", "_normal_image", "_hover_image", + "_hovering") + + def __init__(self, + x: int, + y: int, + width: int, + height: int, + on_press: Optional[Callable] = None, + on_release: Optional[Callable] = None, + normal_image: pyglet.image.AbstractImage = None, + hover_image: pyglet.image.AbstractImage = None, + *args, **kwargs + ): + + # TODO: use batch + # TODO: make the label centered in the button + # TODO: use texture bin and animation to simplify the image handling ? + + self.label = pyglet.text.Label(*args, **kwargs) + + self._hovering = False + self._normal_sprite = pyglet.sprite.Sprite(normal_image) + self._hover_sprite = pyglet.sprite.Sprite(hover_image) + + self.on_press: Optional[Callable[["Window", "Scene", int, int, int, int], None]] = on_press + self.on_release: Optional[Callable[["Window", "Scene", int, int, int, int], None]] = on_release + + self.x: int = x + self.y: int = y + self.width: int = width + self.height: int = height + + # function + + def _update_sprite_size(self, x: int = None, y: int = None, width: int = None, height: int = None): + for sprite in self._normal_sprite, self._hover_sprite: + sprite.update( + x=x, + y=y, + scale_x=None if width is None else width / sprite.width, + scale_y=None if height is None else height / sprite.height, + ) + + # button getter and setter + + @property + def background_sprite(self) -> Optional[pyglet.sprite.Sprite]: + return self._hover_sprite if self._hovering else self._normal_sprite + + @property + def bbox(self) -> tuple[int, int, int, int]: + return self.x, self.y, self.x + self.width, self.y + self.height + + # label getter and setter + + @property + def x(self) -> int: return self._x + + @x.setter + def x(self, value: int): + self._x = value + self.label.x = value + self._update_sprite_size(x=value) + + @property + def y(self) -> int: return self._y + + @y.setter + def y(self, value: int): + self._y = value + self.label.y = value + self._update_sprite_size(y=value) + + @property + def width(self) -> int: return self._width + + @width.setter + def width(self, value: int): + self._width = value + self.label.width = value + self._update_sprite_size(width=value) + + @property + def height(self) -> int: return self._height + + @height.setter + def height(self, value: int): + self._height = value + self.label.height = value + self._update_sprite_size(height=value) + + # event + + def on_mouse_press(self, window: "Window", scene: "Scene", x: int, y: int, button: int, modifiers: int): + if not in_bbox((x, y), self.bbox): return + if self.on_press is not None: self.on_press(window, scene, x, y, button, modifiers) + + def on_mouse_release(self, window: "Window", scene: "Scene", x: int, y: int, button: int, modifiers: int): + if not in_bbox((x, y), self.bbox): return + if self.on_release is not None: self.on_release(window, scene, x, y, button, modifiers) + + def on_mouse_motion(self, window: "Window", scene: "Scene", x: int, y: int, dx: int, dy: int): + self._hovering = in_bbox((x, y), self.bbox) + + def on_draw(self, window: "Window", scene: "Scene"): + if (bg := self.background_sprite) is not None: + bg.draw() + + self.label.draw() diff --git a/source/gui/widget/__init__.py b/source/gui/widget/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/source/gui/widget/base/Widget.py b/source/gui/widget/base/Widget.py new file mode 100644 index 0000000..8a6f489 --- /dev/null +++ b/source/gui/widget/base/Widget.py @@ -0,0 +1,50 @@ +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from source.gui.scene.base import Scene + from source.gui.window import Window + + +class Widget: + """ + This class represent a widget that can be attached to a Scene. + + It can be used to create a button, a label, ... + """ + + # widget event + + def on_scene_added(self, scene: "Scene"): pass + def on_scene_removed(self, scene: "Scene"): pass + + # scene event + + def on_window_added(self, window: "Window", scene: "Scene"): pass + def on_window_removed(self, window: "Window", scene: "Scene"): pass + + # global event + + def on_draw(self, window: "Window", scene: "Scene"): pass + def on_resize(self, window: "Window", scene: "Scene", width: int, height: int): pass + def on_hide(self, window: "Window", scene: "Scene"): pass + def on_show(self, window: "Window", scene: "Scene"): pass + def on_close(self, window: "Window", scene: "Scene"): pass + def on_expose(self, window: "Window", scene: "Scene"): pass + def on_activate(self, window: "Window", scene: "Scene"): pass + def on_deactivate(self, window: "Window", scene: "Scene"): pass + def on_text(self, window: "Window", scene: "Scene", char: str): pass + def on_move(self, window: "Window", scene: "Scene", x: int, y: int): pass + def on_context_lost(self, window: "Window", scene: "Scene"): pass + def on_context_state_lost(self, window: "Window", scene: "Scene"): pass + def on_key_press(self, window: "Window", scene: "Scene", symbol: int, modifiers: int): pass + def on_key_release(self, window: "Window", scene: "Scene", symbol: int, modifiers: int): pass + def on_key_held(self, window: "Window", scene: "Scene", dt: float, symbol: int, modifiers: int): pass + def on_mouse_enter(self, window: "Window", scene: "Scene", x: int, y: int): pass + def on_mouse_leave(self, window: "Window", scene: "Scene", x: int, y: int): pass + def on_text_motion(self, window: "Window", scene: "Scene", motion: int): pass + def on_text_motion_select(self, window: "Window", scene: "Scene", motion: int): pass + def on_mouse_motion(self, window: "Window", scene: "Scene", x: int, y: int, dx: int, dy: int): pass + def on_mouse_press(self, window: "Window", scene: "Scene", x: int, y: int, button: int, modifiers: int): pass + def on_mouse_release(self, window: "Window", scene: "Scene", x: int, y: int, button: int, modifiers: int): pass + def on_mouse_drag(self, window: "Window", scene: "Scene", x: int, y: int, dx: int, dy: int, buttons: int, modifiers: int): pass + def on_mouse_scroll(self, window: "Window", scene: "Scene", x: int, y: int, scroll_x: float, scroll_y: float): pass diff --git a/source/gui/widget/base/__init__.py b/source/gui/widget/base/__init__.py new file mode 100644 index 0000000..ab73ff2 --- /dev/null +++ b/source/gui/widget/base/__init__.py @@ -0,0 +1 @@ +from .Widget import Widget diff --git a/gui/window/Window.py b/source/gui/window/Window.py similarity index 92% rename from gui/window/Window.py rename to source/gui/window/Window.py index 168c3b5..bdfff5a 100644 --- a/gui/window/Window.py +++ b/source/gui/window/Window.py @@ -1,8 +1,9 @@ -from typing import Optional, Callable +from typing import Optional, Callable, TYPE_CHECKING import pyglet.window -from gui.scene import Scene +if TYPE_CHECKING: + from source.gui.scene import Scene class Window(pyglet.window.Window): # NOQA - pycharm think pyglet window is abstract @@ -14,9 +15,10 @@ class Window(pyglet.window.Window): # NOQA - pycharm think pyglet window is abs putting everything in the window code. """ - def __init__(self, *args, scenes: Optional[Scene] = None, **kwargs): + def __init__(self, scenes: Optional["Scene"] = None, *args, **kwargs): super().__init__(*args, **kwargs) - self._scenes: list[Scene] = [] if scenes is None else scenes + self._scenes: list["Scene"] = [] + if scenes is not None: self.add_scene(*scenes) # add a keys handler to the window self.keys = pyglet.window.key.KeyStateHandler() @@ -27,7 +29,7 @@ class Window(pyglet.window.Window): # NOQA - pycharm think pyglet window is abs # scene methods - def set_scene(self, *scenes: Scene) -> None: + def set_scene(self, *scenes: "Scene") -> None: """ Set the scene(s) of the window :param scenes: the scene(s) to set @@ -42,7 +44,7 @@ class Window(pyglet.window.Window): # NOQA - pycharm think pyglet window is abs for scene in self._scenes: scene.on_window_removed(self) self._scenes.clear() - def add_scene(self, *scenes: Scene, priority: int = 0) -> None: + def add_scene(self, *scenes: "Scene", priority: int = 0) -> None: """ Add a scene to the window :param scenes: the scene to add @@ -52,7 +54,7 @@ class Window(pyglet.window.Window): # NOQA - pycharm think pyglet window is abs self._scenes.insert(priority, scene) scene.on_window_added(self) - def remove_scene(self, *scenes: Scene) -> None: + def remove_scene(self, *scenes: "Scene") -> None: """ Remove a scene from the window :param scenes: the scene to remove diff --git a/gui/window/__init__.py b/source/gui/window/__init__.py similarity index 96% rename from gui/window/__init__.py rename to source/gui/window/__init__.py index 262037f..2391d96 100644 --- a/gui/window/__init__.py +++ b/source/gui/window/__init__.py @@ -1 +1,2 @@ from .Window import Window + diff --git a/source/utils/__init__.py b/source/utils/__init__.py index 22d9bd9..3c0dad2 100644 --- a/source/utils/__init__.py +++ b/source/utils/__init__.py @@ -1 +1,2 @@ from .copy_array_offset import copy_array_offset +from .in_bbox import in_bbox diff --git a/source/utils/in_bbox.py b/source/utils/in_bbox.py new file mode 100644 index 0000000..0f4e4d2 --- /dev/null +++ b/source/utils/in_bbox.py @@ -0,0 +1,14 @@ +def in_bbox(point: tuple[int, int], bbox: tuple[int, int, int, int]) -> bool: + """ + Return true if a point is inside a bounding box + :param point: the point to check + :param bbox: the bbox where to check the point + :return: True if the point is inside the bbox, False otherwise + """ + + point_x, point_y = point + bbox_x1, bbox_y1, bbox_x2, bbox_y2 = bbox + + if not bbox_x1 <= point_x <= bbox_x2: return False + if not bbox_y1 <= point_y <= bbox_y2: return False + return True