diff --git a/main.pyw b/main.pyw index 4d3f6f8..b55b3ab 100644 --- a/main.pyw +++ b/main.pyw @@ -1,37 +1,18 @@ import pyglet -from source.gui.widget.Button import Button from source.gui.window import Window from source.gui.scene.debug import FPSCounterScene -from source.gui.scene import HelloWorldScene +from source.gui.scene.test import ButtonScene # Créer une fenêtre window = Window(resizable=True, visible=False) -button_normal_image = pyglet.image.load("./assets/test_button_normal.png") -button_hover_image = pyglet.image.load("./assets/test_button_hover.png") -button_click_image = pyglet.image.load("./assets/test_button_clicking.png") - # performance and button test -hello_world_scene = HelloWorldScene() - -for x in range(10): - for y in range(10): - button = Button( - 200 + y * 50, x * 50, 50, 50, - text=f"{x}-{y}", - font_size=10, - on_release=lambda self, *a, **b: setattr(self, "width", self.width + 10), - normal_image=button_normal_image, - hover_image=button_hover_image, - click_image=button_click_image - ) - hello_world_scene.add_widget(button) - +button_scene = ButtonScene() fps_counter_scene = FPSCounterScene() -window.add_scene(hello_world_scene, fps_counter_scene) +window.add_scene(button_scene, fps_counter_scene) # Lance la fenêtre window.set_visible(True) diff --git a/source/gui/scene/__init__.py b/source/gui/scene/__init__.py index 7d9c684..3bcdbb8 100644 --- a/source/gui/scene/__init__.py +++ b/source/gui/scene/__init__.py @@ -1 +1 @@ -from .HelloWorldScene import HelloWorldScene +from source.gui.scene.test.HelloWorldScene import HelloWorldScene diff --git a/source/gui/scene/test/ButtonScene.py b/source/gui/scene/test/ButtonScene.py new file mode 100644 index 0000000..dd23ee8 --- /dev/null +++ b/source/gui/scene/test/ButtonScene.py @@ -0,0 +1,30 @@ +import pyglet + +from source.gui.scene.base import Scene +from source.gui.widget import Button + + +class ButtonScene(Scene): + """ + This is a simple scene to test Button and their adaptable size + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + button_normal_image = pyglet.image.load("./assets/test_button_normal.png") + button_hover_image = pyglet.image.load("./assets/test_button_hover.png") + button_click_image = pyglet.image.load("./assets/test_button_clicking.png") + + for x in range(10): + for y in range(10): + self.add_widget(Button( + x * 0.1, y * 0.1, 0.1, 0.1, + + text=f"{x}-{y}", + font_size=10, + on_release=lambda self, *a, **b: print(self, "clicked !"), + normal_image=button_normal_image, + hover_image=button_hover_image, + click_image=button_click_image + )) diff --git a/source/gui/scene/HelloWorldScene.py b/source/gui/scene/test/HelloWorldScene.py similarity index 100% rename from source/gui/scene/HelloWorldScene.py rename to source/gui/scene/test/HelloWorldScene.py diff --git a/source/gui/scene/test/__init__.py b/source/gui/scene/test/__init__.py new file mode 100644 index 0000000..d2a1e98 --- /dev/null +++ b/source/gui/scene/test/__init__.py @@ -0,0 +1,2 @@ +from .HelloWorldScene import HelloWorldScene +from .ButtonScene import ButtonScene diff --git a/source/gui/widget/Button.py b/source/gui/widget/Button.py index 36c03d4..a0d45ca 100644 --- a/source/gui/widget/Button.py +++ b/source/gui/widget/Button.py @@ -3,8 +3,8 @@ from typing import Callable, Optional, TYPE_CHECKING import pyglet from source.gui.sprite import Sprite -from source.gui.widget.base import Widget -from source.type import BBox +from source.gui.widget.base import AdaptativeWidget +from source.type import Percentage from source.utils import in_bbox if TYPE_CHECKING: @@ -13,12 +13,13 @@ if TYPE_CHECKING: from source.gui.window import Window -class Button(Widget): +class Button(AdaptativeWidget): def __init__(self, - x: int, - y: int, - width: int, - height: int, + + x: int | Percentage, + y: int | Percentage, + width: int | Percentage, + height: int | Percentage, normal_image: pyglet.image.AbstractImage, hover_image: pyglet.image.AbstractImage = None, @@ -30,12 +31,11 @@ class Button(Widget): *args, **kwargs ): + super().__init__(x, y, width, height) + # TODO: use batch ? # TODO: use texture bin and animation to simplify the image handling ? - # TODO: make x, y, width, height, font_size optionally function to allow dynamic sizing - - # initialise the value for the property - self._x, self._y, self._width, self._height = x, y, width, height + # TODO: font_size dynamic sizing too ? # the label used for the text self._label = pyglet.text.Label( @@ -101,42 +101,26 @@ class Button(Widget): else self._normal_image ) - @property - def bbox(self) -> BBox: - 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 + @AdaptativeWidget.x.setter def x(self, x: int): - self._x = x + super().x = x self._update_size() - @property - def y(self) -> int: return self._y - - @y.setter + @AdaptativeWidget.y.setter def y(self, y: int): - self._y = y + super().y = y self._update_size() - @property - def width(self) -> int: return self._width - - @width.setter + @AdaptativeWidget.width.setter def width(self, width: int): - self._width = width + super().width = width self._update_size() - @property - def height(self) -> int: return self._height - - @height.setter + @AdaptativeWidget.height.setter def height(self, height: int): - self._height = height + super().height = height self._update_size() # event @@ -156,7 +140,7 @@ class Button(Widget): if not in_bbox((x, y), self.bbox): return # if this button was the one hovered when the click was pressed - if old_clicking is True and self.on_release is not None: + if old_clicking and self.on_release is not None: self.on_release(self, window, scene, x, y, button, modifiers) def on_mouse_motion(self, window: "Window", scene: "Scene", x: int, y: int, dx: int, dy: int): @@ -165,3 +149,7 @@ class Button(Widget): def on_draw(self, window: "Window", scene: "Scene"): if self._sprite is not None: self._sprite.draw() self._label.draw() + + def on_resize(self, window: "Window", scene: "Scene", width: int, height: int): + super().on_resize(window, scene, width, height) + self._update_size() diff --git a/source/gui/widget/__init__.py b/source/gui/widget/__init__.py index e69de29..631babf 100644 --- a/source/gui/widget/__init__.py +++ b/source/gui/widget/__init__.py @@ -0,0 +1 @@ +from .Button import Button diff --git a/source/gui/widget/base/AdaptativeWidget.py b/source/gui/widget/base/AdaptativeWidget.py new file mode 100644 index 0000000..1429f34 --- /dev/null +++ b/source/gui/widget/base/AdaptativeWidget.py @@ -0,0 +1,75 @@ +from source.gui.widget.base import Widget + +from typing import TYPE_CHECKING + +from source.type import BBox, Percentage + +if TYPE_CHECKING: + from source.gui.window import Window + from source.gui.scene.base import Scene + + +class AdaptativeWidget(Widget): + """ + Similar to a normal Widget + + If the x, y, width or height is a float (representing a percentage), it will change depending on the window size + """ + + def __init__(self, + + x: int | Percentage, + y: int | Percentage, + width: int | Percentage, + height: int | Percentage, + ): + + self._x = x + self._y = y + self._width = width + self._height = height + + self._window_width = 0 + self._window_height = 0 + + # getter / setter + + @property + def x(self) -> int: + return self._x if isinstance(self._x, int) else self._x * self._window_width + + @x.setter + def x(self, x: int | Percentage) -> None: + self._x = x + + @property + def y(self) -> int: + return self._y if isinstance(self._y, int) else self._y * self._window_height + + @y.setter + def y(self, y: int | Percentage) -> None: + self._y = y + + @property + def width(self) -> int: + return self._width if isinstance(self._width, int) else self._width * self._window_width + + @width.setter + def width(self, width: int | Percentage) -> None: + self._width = width + + @property + def height(self) -> int: + return self._height if isinstance(self._height, int) else self._height * self._window_height + + @height.setter + def height(self, height: int | Percentage) -> None: + self._height = height + + @property + def bbox(self) -> BBox: + return self.x, self.y, self.x + self.width, self.y + self.height + + def on_resize(self, window: "Window", scene: "Scene", width: int, height: int): + self._window_width = width + self._window_height = height diff --git a/source/gui/widget/base/__init__.py b/source/gui/widget/base/__init__.py index ab73ff2..7503b5c 100644 --- a/source/gui/widget/base/__init__.py +++ b/source/gui/widget/base/__init__.py @@ -1 +1,2 @@ from .Widget import Widget +from .AdaptativeWidget import AdaptativeWidget diff --git a/source/type.py b/source/type.py index e72d125..71a8148 100644 --- a/source/type.py +++ b/source/type.py @@ -1,2 +1,3 @@ Point2D = tuple[int, int] BBox = tuple[int, int, int, int] +Percentage = float # a percentage is a value between 0 and 1