179 lines
5.2 KiB
Python
179 lines
5.2 KiB
Python
from typing import TYPE_CHECKING, Callable
|
|
|
|
import pyglet.image
|
|
|
|
from source.gui.sprite import Sprite
|
|
from source.gui.widget.base import BaseAdaptativeWidget
|
|
from source.type import Percentage
|
|
from source.utils import in_bbox
|
|
|
|
if TYPE_CHECKING:
|
|
from source.gui.window import Window
|
|
from source.gui.scene.base import BaseScene
|
|
|
|
|
|
class Button(BaseAdaptativeWidget):
|
|
def __init__(self,
|
|
|
|
# position
|
|
x: int | Percentage,
|
|
y: int | Percentage,
|
|
width: int | Percentage,
|
|
height: int | Percentage,
|
|
|
|
# background
|
|
normal_texture: pyglet.image.AbstractImage,
|
|
hover_texture: pyglet.image.AbstractImage = None,
|
|
click_texture: pyglet.image.AbstractImage = None,
|
|
|
|
# label
|
|
label_text: str = "",
|
|
label_font_name: str = None,
|
|
label_font_size: int = None,
|
|
label_bold: bool = False,
|
|
label_italic: bool = False,
|
|
label_stretch: bool = False,
|
|
label_color: tuple[int, int, int, int] = (255, 255, 255, 255),
|
|
label_align: str = "center",
|
|
label_multiline: bool = False,
|
|
label_dpi: int = None,
|
|
label_rotation: int = 0,
|
|
|
|
# callback function
|
|
on_press: Callable = None,
|
|
on_release: Callable = None,
|
|
|
|
# batch
|
|
label_batch: pyglet.graphics.Batch = None,
|
|
sprite_batch: pyglet.graphics.Batch = None,
|
|
|
|
# group
|
|
label_group: pyglet.graphics.Group = None,
|
|
sprite_group: pyglet.graphics.Group = None,
|
|
):
|
|
|
|
super().__init__(x, y, width, height)
|
|
|
|
self._normal_texture = normal_texture
|
|
self._hover_texture = hover_texture
|
|
self._click_texture = click_texture
|
|
|
|
self.on_press = on_press
|
|
self.on_release = on_release
|
|
|
|
self._label = None
|
|
self._label_kwargs = {
|
|
"text": label_text,
|
|
"font_name": label_font_name,
|
|
"font_size": label_font_size,
|
|
"bold": label_bold,
|
|
"italic": label_italic,
|
|
"stretch": label_stretch,
|
|
"color": label_color,
|
|
"align": label_align,
|
|
"multiline": label_multiline,
|
|
"dpi": label_dpi,
|
|
"rotation": label_rotation,
|
|
|
|
"batch": label_batch,
|
|
"group": label_group,
|
|
}
|
|
|
|
self._sprite = None
|
|
self._sprite_kwargs = {
|
|
"batch": sprite_batch,
|
|
"group": sprite_group,
|
|
}
|
|
|
|
self._hover = False
|
|
self._click = False
|
|
|
|
# button update
|
|
|
|
@property
|
|
def hover(self) -> bool:
|
|
return self._hover
|
|
|
|
@hover.setter
|
|
def hover(self, hover: bool) -> None:
|
|
self._hover = hover
|
|
self._update_sprite()
|
|
|
|
@property
|
|
def click(self) -> bool:
|
|
return self._click
|
|
|
|
@click.setter
|
|
def click(self, click: bool) -> None:
|
|
self._click = click
|
|
self._update_sprite()
|
|
|
|
@property
|
|
def background_texture(self) -> pyglet.image.AbstractImage:
|
|
return (
|
|
self._click_texture if self._click else
|
|
self._hover_texture if self._hover else
|
|
self._normal_texture
|
|
)
|
|
|
|
def _update_sprite(self):
|
|
self._sprite.image = self.background_texture
|
|
|
|
def update_size(self):
|
|
self._sprite.x = self.x
|
|
self._sprite.y = self.y
|
|
self._sprite.width = self.width
|
|
self._sprite.height = self.height
|
|
|
|
self._label.x = self.x + self.width / 2
|
|
self._label.y = self.y + self.height / 2
|
|
self._label.width = self.width
|
|
|
|
# event
|
|
|
|
def on_window_added(self, window: "Window", scene: "BaseScene"):
|
|
super().on_window_added(window, scene)
|
|
|
|
self._label = pyglet.text.Label(
|
|
x=self.x + self.width / 2,
|
|
y=self.y + self.height / 2,
|
|
|
|
width=self.width,
|
|
anchor_x="center", anchor_y="center",
|
|
|
|
**self._label_kwargs
|
|
)
|
|
|
|
self._sprite = Sprite(
|
|
self._normal_texture,
|
|
|
|
x=self.x, y=self.y,
|
|
width=self.width, height=self.height,
|
|
|
|
**self._sprite_kwargs
|
|
)
|
|
|
|
def on_mouse_motion(self, window: "Window", scene: "BaseScene", x: int, y: int, dx: int, dy: int):
|
|
self.hover = in_bbox((x, y), self.bbox)
|
|
|
|
def on_mouse_press(self, window: "Window", scene: "BaseScene", x: int, y: int, button: int, modifiers: int):
|
|
if not in_bbox((x, y), self.bbox): return
|
|
|
|
self.click = True
|
|
|
|
if self.on_press is not None:
|
|
self.on_press(self, window, scene, x, y, button, modifiers)
|
|
|
|
def on_mouse_release(self, window: "Window", scene: "BaseScene", x: int, y: int, button: int, modifiers: int):
|
|
old_click = self.click
|
|
self.click = False
|
|
|
|
if not in_bbox((x, y), self.bbox): return
|
|
|
|
# if this button was the one hovered when the click was pressed
|
|
if old_click and self.on_release is not None:
|
|
self.on_release(self, window, scene, x, y, button, modifiers)
|
|
|
|
|
|
# TODO: on_resize seem really slow
|
|
# TODO: make the percentage dynamic or non dynamic
|