added prototypal "AdaptativeWidget" to automatically resize widget when the window is resized

This commit is contained in:
Faraphel 2023-01-11 20:26:53 +01:00
parent 91a79c7a80
commit 2b4d125b46
10 changed files with 138 additions and 59 deletions

View file

@ -1,37 +1,18 @@
import pyglet import pyglet
from source.gui.widget.Button import Button
from source.gui.window import Window from source.gui.window import Window
from source.gui.scene.debug import FPSCounterScene 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 # Créer une fenêtre
window = Window(resizable=True, visible=False) 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 # performance and button test
hello_world_scene = HelloWorldScene() button_scene = ButtonScene()
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)
fps_counter_scene = FPSCounterScene() 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 # Lance la fenêtre
window.set_visible(True) window.set_visible(True)

View file

@ -1 +1 @@
from .HelloWorldScene import HelloWorldScene from source.gui.scene.test.HelloWorldScene import HelloWorldScene

View file

@ -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
))

View file

@ -0,0 +1,2 @@
from .HelloWorldScene import HelloWorldScene
from .ButtonScene import ButtonScene

View file

@ -3,8 +3,8 @@ from typing import Callable, Optional, TYPE_CHECKING
import pyglet import pyglet
from source.gui.sprite import Sprite from source.gui.sprite import Sprite
from source.gui.widget.base import Widget from source.gui.widget.base import AdaptativeWidget
from source.type import BBox from source.type import Percentage
from source.utils import in_bbox from source.utils import in_bbox
if TYPE_CHECKING: if TYPE_CHECKING:
@ -13,12 +13,13 @@ if TYPE_CHECKING:
from source.gui.window import Window from source.gui.window import Window
class Button(Widget): class Button(AdaptativeWidget):
def __init__(self, def __init__(self,
x: int,
y: int, x: int | Percentage,
width: int, y: int | Percentage,
height: int, width: int | Percentage,
height: int | Percentage,
normal_image: pyglet.image.AbstractImage, normal_image: pyglet.image.AbstractImage,
hover_image: pyglet.image.AbstractImage = None, hover_image: pyglet.image.AbstractImage = None,
@ -30,12 +31,11 @@ class Button(Widget):
*args, **kwargs *args, **kwargs
): ):
super().__init__(x, y, width, height)
# TODO: use batch ? # TODO: use batch ?
# TODO: use texture bin and animation to simplify the image handling ? # 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 # TODO: font_size dynamic sizing too ?
# initialise the value for the property
self._x, self._y, self._width, self._height = x, y, width, height
# the label used for the text # the label used for the text
self._label = pyglet.text.Label( self._label = pyglet.text.Label(
@ -101,42 +101,26 @@ class Button(Widget):
else self._normal_image 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 # label getter and setter
@property @AdaptativeWidget.x.setter
def x(self) -> int: return self._x
@x.setter
def x(self, x: int): def x(self, x: int):
self._x = x super().x = x
self._update_size() self._update_size()
@property @AdaptativeWidget.y.setter
def y(self) -> int: return self._y
@y.setter
def y(self, y: int): def y(self, y: int):
self._y = y super().y = y
self._update_size() self._update_size()
@property @AdaptativeWidget.width.setter
def width(self) -> int: return self._width
@width.setter
def width(self, width: int): def width(self, width: int):
self._width = width super().width = width
self._update_size() self._update_size()
@property @AdaptativeWidget.height.setter
def height(self) -> int: return self._height
@height.setter
def height(self, height: int): def height(self, height: int):
self._height = height super().height = height
self._update_size() self._update_size()
# event # event
@ -156,7 +140,7 @@ class Button(Widget):
if not in_bbox((x, y), self.bbox): return if not in_bbox((x, y), self.bbox): return
# if this button was the one hovered when the click was pressed # 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) 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): 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"): def on_draw(self, window: "Window", scene: "Scene"):
if self._sprite is not None: self._sprite.draw() if self._sprite is not None: self._sprite.draw()
self._label.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()

View file

@ -0,0 +1 @@
from .Button import Button

View file

@ -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

View file

@ -1 +1,2 @@
from .Widget import Widget from .Widget import Widget
from .AdaptativeWidget import AdaptativeWidget

View file

@ -1,2 +1,3 @@
Point2D = tuple[int, int] Point2D = tuple[int, int]
BBox = tuple[int, int, int, int] BBox = tuple[int, int, int, int]
Percentage = float # a percentage is a value between 0 and 1