added prototypal "AdaptativeWidget" to automatically resize widget when the window is resized
This commit is contained in:
parent
91a79c7a80
commit
2b4d125b46
10 changed files with 138 additions and 59 deletions
25
main.pyw
25
main.pyw
|
@ -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)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
from .HelloWorldScene import HelloWorldScene
|
from source.gui.scene.test.HelloWorldScene import HelloWorldScene
|
||||||
|
|
30
source/gui/scene/test/ButtonScene.py
Normal file
30
source/gui/scene/test/ButtonScene.py
Normal 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
|
||||||
|
))
|
2
source/gui/scene/test/__init__.py
Normal file
2
source/gui/scene/test/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
from .HelloWorldScene import HelloWorldScene
|
||||||
|
from .ButtonScene import ButtonScene
|
|
@ -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()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
from .Button import Button
|
75
source/gui/widget/base/AdaptativeWidget.py
Normal file
75
source/gui/widget/base/AdaptativeWidget.py
Normal 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
|
|
@ -1 +1,2 @@
|
||||||
from .Widget import Widget
|
from .Widget import Widget
|
||||||
|
from .AdaptativeWidget import AdaptativeWidget
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue