diff --git a/assets/image/input/inputbox.png b/assets/image/input/inputbox.png new file mode 100644 index 0000000..c031d93 Binary files /dev/null and b/assets/image/input/inputbox.png differ diff --git a/main.pyw b/main.pyw index 330234a..c50036c 100644 --- a/main.pyw +++ b/main.pyw @@ -1,13 +1,15 @@ import pyglet -from source.gui.scene.debug import FPSScene -from source.gui.scene.test import HelloWorldScene +from source.gui.scene.debug import FPSAbstractScene +from source.gui.scene.test import TestButtonScene, TestLabelScene from source.gui.window import Window # Create a new window window = Window(resizable=True, vsync=False) -window.add_scene(HelloWorldScene(), FPSScene()) +window.add_scene(TestButtonScene()) +# window.add_scene(TestLabelScene()) +window.add_scene(FPSAbstractScene()) # Start the event loop pyglet.app.run(interval=0) diff --git a/source/gui/README.md b/source/gui/README.md new file mode 100644 index 0000000..139e211 --- /dev/null +++ b/source/gui/README.md @@ -0,0 +1,8 @@ +Ce module est une "surcouche" pour le module pyglet afin d'implémenter quelques éléments qui +ne sont pas déjà disponible nativement dans cette librairie, tel que : + +- Les scènes (attachable à une fenêtre afin de changer rapidement de menu / d'interface) +- Les widgets (attachable à des scènes afin de rajouter des boutons, des textes, ...) + +Ces éléments permettent de plus facilement gérer le redimentionnement de la fenêtre tout en +restant suffisament rapide pour ne pas causer de problème de ralentissement. \ No newline at end of file diff --git a/source/gui/scene/base/BaseScene.py b/source/gui/scene/abc/AbstractScene.py similarity index 86% rename from source/gui/scene/base/BaseScene.py rename to source/gui/scene/abc/AbstractScene.py index 7e4948b..7f4958d 100644 --- a/source/gui/scene/base/BaseScene.py +++ b/source/gui/scene/abc/AbstractScene.py @@ -1,27 +1,29 @@ +from abc import ABC from typing import TYPE_CHECKING, Optional if TYPE_CHECKING: from source.gui.window import Window - from source.gui.widget.base import BaseWidget + from source.gui.widget.abc import AbstractWidget -class BaseScene: +class AbstractScene(ABC): """ - A scene that can be attached to a window + An abstract scene that can be attached to a window. + Can be used to create a menu, an overlay, ... """ def __init__(self): - self._widgets: list["BaseWidget"] = [] - self._window: Optional["Window"] = None + self._widgets: list["AbstractWidget"] = [] # the lists of the widgets in the scene + self._window: Optional["Window"] = None # the window where the scene is attached # widget - def add_widget(self, *widgets: "BaseWidget", priority: int = 0) -> None: + def add_widget(self, *widgets: "AbstractWidget", priority: int = 0) -> None: for widget in widgets: self._widgets.insert(priority, widget) widget.on_scene_added(self) - def remove_widget(self, *widgets: "BaseWidget") -> None: + def remove_widget(self, *widgets: "AbstractWidget") -> None: for widget in widgets: widget.on_scene_removed(self) self._widgets.remove(widget) @@ -44,12 +46,12 @@ class BaseScene: return self._window @window.setter - def window(self, window: "Window"): + def window(self, window: "Window"): # trying to change the window will trigger the event if self._window is not None: self.on_window_removed(self._window) self._window = window if self._window is not None: self.on_window_added(self._window) - # event + # all the events of the window are directly available here or in the widgets def on_draw(self, window: "Window"): for widget in self._widgets: widget.on_draw(window, self) diff --git a/source/gui/scene/abc/__init__.py b/source/gui/scene/abc/__init__.py new file mode 100644 index 0000000..67c0fcc --- /dev/null +++ b/source/gui/scene/abc/__init__.py @@ -0,0 +1 @@ +from .AbstractScene import AbstractScene diff --git a/source/gui/scene/base/__init__.py b/source/gui/scene/base/__init__.py deleted file mode 100644 index ab09621..0000000 --- a/source/gui/scene/base/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .BaseScene import BaseScene diff --git a/source/gui/scene/debug/FPSScene.py b/source/gui/scene/debug/FPSScene.py index 906793c..aed723f 100644 --- a/source/gui/scene/debug/FPSScene.py +++ b/source/gui/scene/debug/FPSScene.py @@ -1,17 +1,21 @@ -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional import pyglet.window -from source.gui.scene.base import BaseScene +from source.gui.scene.abc import AbstractScene if TYPE_CHECKING: from source.gui.window import Window -class FPSScene(BaseScene): +class FPSAbstractScene(AbstractScene): + """ + A base scene that can be used as an overlay to display the FPS + """ + def __init__(self): super().__init__() - self._fps_display = None + self._fps_display: Optional[pyglet.window.FPSDisplay] = None def on_window_added(self, window: "Window"): self._fps_display = pyglet.window.FPSDisplay(window) diff --git a/source/gui/scene/debug/__init__.py b/source/gui/scene/debug/__init__.py index a8d0b54..b5f6215 100644 --- a/source/gui/scene/debug/__init__.py +++ b/source/gui/scene/debug/__init__.py @@ -1 +1 @@ -from .FPSScene import FPSScene +from .FPSScene import FPSAbstractScene diff --git a/source/gui/scene/test/HelloWorldScene.py b/source/gui/scene/test/TestButtonScene.py similarity index 80% rename from source/gui/scene/test/HelloWorldScene.py rename to source/gui/scene/test/TestButtonScene.py index af6c0fb..7029a00 100644 --- a/source/gui/scene/test/HelloWorldScene.py +++ b/source/gui/scene/test/TestButtonScene.py @@ -2,19 +2,23 @@ from typing import TYPE_CHECKING import pyglet -from source.gui.scene.base import BaseScene -from source.gui.widget.Button import Button +from source.gui.scene.abc import AbstractScene +from source.gui.widget import Button if TYPE_CHECKING: from source.gui.window import Window -class HelloWorldScene(BaseScene): +class TestButtonScene(AbstractScene): + """ + A scene used to test the Button widget + """ + def __init__(self): super().__init__() self.button_atlas = None - self.sprite_batch = None + self.background_batch = None self.label_batch = None def on_window_added(self, window: "Window") -> None: @@ -27,7 +31,7 @@ class HelloWorldScene(BaseScene): hover_region = self.button_atlas.add(hover_texture) click_region = self.button_atlas.add(click_texture) - self.sprite_batch = pyglet.graphics.Batch() + self.background_batch = pyglet.graphics.Batch() self.label_batch = pyglet.graphics.Batch() for x in range(10): @@ -43,7 +47,7 @@ class HelloWorldScene(BaseScene): label_multiline=True, label_batch=self.label_batch, - sprite_batch=self.sprite_batch, + background_batch=self.background_batch, )) super().on_window_added(window) @@ -51,5 +55,5 @@ class HelloWorldScene(BaseScene): def on_draw(self, window: "Window"): super().on_draw(window) - self.sprite_batch.draw() + self.background_batch.draw() self.label_batch.draw() diff --git a/source/gui/scene/test/TestLabelScene.py b/source/gui/scene/test/TestLabelScene.py new file mode 100644 index 0000000..6b7ad1b --- /dev/null +++ b/source/gui/scene/test/TestLabelScene.py @@ -0,0 +1,40 @@ +from typing import TYPE_CHECKING + +import pyglet + +from source.gui.scene.abc import AbstractScene +from source.gui.widget import Label + +if TYPE_CHECKING: + from source.gui.window import Window + + +class TestLabelScene(AbstractScene): + """ + A scene used to test the Label widget + """ + + def __init__(self): + super().__init__() + + self.label_batch = None + + def on_window_added(self, window: "Window") -> None: + self.label_batch = pyglet.graphics.Batch() + + for x in range(10): + for y in range(10): + self.add_widget(Label( + x=x*0.1, y=y*0.1, width=0.1, height=0.1, + + text=f"{x}.{y}", + + label_batch=self.label_batch, + )) + + super().on_window_added(window) + + def on_draw(self, window: "Window"): + super().on_draw(window) + + self.label_batch.draw() diff --git a/source/gui/scene/test/__init__.py b/source/gui/scene/test/__init__.py index 7d9c684..eb8343c 100644 --- a/source/gui/scene/test/__init__.py +++ b/source/gui/scene/test/__init__.py @@ -1 +1,3 @@ -from .HelloWorldScene import HelloWorldScene +from .TestButtonScene import TestButtonScene +from .TestLabelScene import TestLabelScene + diff --git a/source/gui/sprite/__init__.py b/source/gui/sprite/__init__.py deleted file mode 100644 index d2ab302..0000000 --- a/source/gui/sprite/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .Sprite import Sprite diff --git a/source/gui/widget/Button.py b/source/gui/widget/Button.py index da11499..45ce227 100644 --- a/source/gui/widget/Button.py +++ b/source/gui/widget/Button.py @@ -1,18 +1,18 @@ -from typing import TYPE_CHECKING, Callable +from typing import TYPE_CHECKING, Callable, Optional import pyglet.image -from source.gui.sprite import Sprite -from source.gui.widget.base import BaseAdaptativeWidget +from source.gui.widget.base import Sprite, Label +from source.gui.widget.abc import AbstractResizableWidget 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 + from source.gui.scene.abc import AbstractScene -class Button(BaseAdaptativeWidget): +class Button(AbstractResizableWidget): def __init__(self, # position @@ -45,11 +45,11 @@ class Button(BaseAdaptativeWidget): # batch label_batch: pyglet.graphics.Batch = None, - sprite_batch: pyglet.graphics.Batch = None, + background_batch: pyglet.graphics.Batch = None, # group label_group: pyglet.graphics.Group = None, - sprite_group: pyglet.graphics.Group = None, + background_group: pyglet.graphics.Group = None, ): super().__init__(x, y, width, height) @@ -61,7 +61,7 @@ class Button(BaseAdaptativeWidget): self.on_press = on_press self.on_release = on_release - self._label = None + self._label: Optional[Label] = None self._label_kwargs = { "text": label_text, "font_name": label_font_name, @@ -79,15 +79,32 @@ class Button(BaseAdaptativeWidget): "group": label_group, } - self._sprite = None - self._sprite_kwargs = { - "batch": sprite_batch, - "group": sprite_group, + self._background: Optional[Sprite] = None + self._background_kwargs = { + "batch": background_batch, + "group": background_group, } self._hover = False self._click = False + def on_window_added(self, window: "Window", scene: "AbstractScene"): + super().on_window_added(window, scene) + + self._label = 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._background = Sprite( + self._normal_texture, + x=self.x, y=self.y, width=self.width, height=self.height, + + **self._background_kwargs + ) + # button update @property @@ -97,7 +114,7 @@ class Button(BaseAdaptativeWidget): @hover.setter def hover(self, hover: bool) -> None: self._hover = hover - self._update_sprite() + self.update_sprite() @property def click(self) -> bool: @@ -106,7 +123,7 @@ class Button(BaseAdaptativeWidget): @click.setter def click(self, click: bool) -> None: self._click = click - self._update_sprite() + self.update_sprite() @property def background_texture(self) -> pyglet.image.AbstractImage: @@ -116,47 +133,19 @@ class Button(BaseAdaptativeWidget): self._normal_texture ) - def _update_sprite(self): - self._sprite.image = self.background_texture + def update_sprite(self): + self._background.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 + self._background.update_size(self.x, self.y, self.width, self.height) + self._label.update_size(self.x + self.width // 2, self.y + self.height // 2, 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): + def on_mouse_motion(self, window: "Window", scene: "AbstractScene", 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): + def on_mouse_press(self, window: "Window", scene: "AbstractScene", x: int, y: int, button: int, modifiers: int): if not in_bbox((x, y), self.bbox): return self.click = True @@ -164,7 +153,7 @@ class Button(BaseAdaptativeWidget): 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): + def on_mouse_release(self, window: "Window", scene: "AbstractScene", x: int, y: int, button: int, modifiers: int): old_click = self.click self.click = False diff --git a/source/gui/widget/Image.py b/source/gui/widget/Image.py new file mode 100644 index 0000000..aa917d7 --- /dev/null +++ b/source/gui/widget/Image.py @@ -0,0 +1,5 @@ +from source.gui.widget.abc import AbstractResizableWidget + + +class Image(AbstractResizableWidget): + ... diff --git a/source/gui/widget/Input.py b/source/gui/widget/Input.py new file mode 100644 index 0000000..34cefa4 --- /dev/null +++ b/source/gui/widget/Input.py @@ -0,0 +1,74 @@ +from typing import TYPE_CHECKING + +import pyglet.text + +from source.gui.widget.abc import AbstractResizableWidget +from source.type import Percentage + +if TYPE_CHECKING: + from source.gui.window import Window + from source.gui.scene.abc import AbstractScene + + +class Input(AbstractResizableWidget): + def __init__(self, + + # position + x: int | Percentage, + y: int | Percentage, + width: int | Percentage, + height: int | Percentage, + + # background + texture: pyglet.image.AbstractImage, + + # 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, + + # batch + label_batch: pyglet.graphics.Batch = None, + background_batch: pyglet.graphics.Batch = None, + + # group + label_group: pyglet.graphics.Group = None, + background_group: pyglet.graphics.Group = None, + ): + + super().__init__(x, y, width, height) + + 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._background_kwargs = { + "img": texture, + "batch": background_batch, + "group": background_group, + } + + def on_window_added(self, window: "Window", scene: "AbstractScene"): + ... diff --git a/source/gui/widget/Label.py b/source/gui/widget/Label.py new file mode 100644 index 0000000..870de6f --- /dev/null +++ b/source/gui/widget/Label.py @@ -0,0 +1,102 @@ +from typing import TYPE_CHECKING + +import pyglet.text + +from source.gui.widget.base import Sprite +from source.gui.widget.abc import AbstractResizableWidget +from source.type import Percentage + +if TYPE_CHECKING: + from source.gui.window import Window + from source.gui.scene.abc import AbstractScene + + +class Label(AbstractResizableWidget): + def __init__(self, + + # position + x: int | Percentage, + y: int | Percentage, + width: int | Percentage = None, + height: int | Percentage = None, + + # label + text: str = "", + font_name: str = None, + font_size: int = None, + bold: bool = False, + italic: bool = False, + stretch: bool = False, + color: tuple[int, int, int, int] = (255, 255, 255, 255), + align: str = "center", + multiline: bool = False, + dpi: int = None, + rotation: int = 0, + + # background + texture: pyglet.image.AbstractImage = None, + + # batch + label_batch: pyglet.graphics.Batch = None, + background_batch: pyglet.graphics.Batch = None, + + # group + label_group: pyglet.graphics.Group = None, + background_group: pyglet.graphics.Group = None + ): + + super().__init__(x, y, width, height) + + self._label = None + self._label_kwargs = { + "text": text, + "font_name": font_name, + "font_size": font_size, + "bold": bold, + "italic": italic, + "stretch": stretch, + "color": color, + "align": align, + "multiline": multiline, + "dpi": dpi, + "rotation": rotation, + + "batch": label_batch, + "group": label_group, + } + + if texture is not None and width is None or height is None: + raise ValueError("You need to set a width and a height to create a Label with a background !") + + self._background = None + self._background_kwargs = { + "img": texture, + "batch": background_batch, + "group": background_group, + } if texture is not None else None + + def on_window_added(self, window: "Window", scene: "AbstractScene"): + super().on_window_added(window, scene) + + self._label = pyglet.text.Label( + x=self.x, y=self.y, width=self.width, height=self.height, + **self._label_kwargs + ) + + if self._background_kwargs is not None: + self._background = Sprite( + x=self.x, y=self.y, width=self.width, height=self.height, + **self._background_kwargs + ) + + def update_size(self): + self._label.x = self.x + self._label.y = self.y + self._label.width = self.width + self._label.height = self.height + + if self._background is not None: + self._background.x = self.x + self._background.y = self.y + self._background.width = self.width + self._background.height = self.height diff --git a/source/gui/widget/__init__.py b/source/gui/widget/__init__.py index e69de29..3c4cb60 100644 --- a/source/gui/widget/__init__.py +++ b/source/gui/widget/__init__.py @@ -0,0 +1,4 @@ +from .Label import Label +from .Input import Input +from .Button import Button +from .Image import Image diff --git a/source/gui/widget/base/BaseBoxWidget.py b/source/gui/widget/abc/AbstractBoxWidget.py similarity index 89% rename from source/gui/widget/base/BaseBoxWidget.py rename to source/gui/widget/abc/AbstractBoxWidget.py index 7441630..37f90cd 100644 --- a/source/gui/widget/base/BaseBoxWidget.py +++ b/source/gui/widget/abc/AbstractBoxWidget.py @@ -1,8 +1,10 @@ -from source.gui.widget.base import BaseWidget +from abc import ABC + +from source.gui.widget.abc import AbstractWidget from source.type import BBox -class BaseBoxWidget(BaseWidget): +class AbstractBoxWidget(AbstractWidget, ABC): def __init__(self, x: int, y: int, width: int, height: int): self._x = x self._y = y diff --git a/source/gui/widget/abc/AbstractResizableWidget.py b/source/gui/widget/abc/AbstractResizableWidget.py new file mode 100644 index 0000000..adbbec9 --- /dev/null +++ b/source/gui/widget/abc/AbstractResizableWidget.py @@ -0,0 +1,50 @@ +from abc import ABC +from typing import Optional, TYPE_CHECKING + +from source.gui.widget.abc import AbstractBoxWidget +from source.type import Percentage + + +if TYPE_CHECKING: + from source.gui.window import Window + from source.gui.scene.abc import AbstractScene + + +class AbstractResizableWidget(AbstractBoxWidget, ABC): + def __init__(self, x: int | Percentage, y: int | Percentage, width: int | Percentage, height: int | Percentage): + super().__init__(x, y, width, height) + + self._window_width: Optional[int] = None + self._window_height: Optional[int] = None + + # getter / setter + + def on_window_added(self, window: "Window", scene: "AbstractScene"): + self._window_width = window.width + self._window_height = window.height + + @property + def x(self) -> int: + return self._x * self._window_width if isinstance(self._x, Percentage) else self._x + + @property + def y(self) -> int: + return self._y * self._window_height if isinstance(self._y, Percentage) else self._y + + @property + def width(self) -> int: + return self._width * self._window_width if isinstance(self._width, Percentage) else self._width + + @property + def height(self) -> int: + return self._height * self._window_height if isinstance(self._height, Percentage) else self._height + + # event + + def update_size(self): pass + + def on_resize(self, window: "Window", scene: "AbstractScene", width: int, height: int): + self._window_width = width + self._window_height = height + + self.update_size() diff --git a/source/gui/widget/abc/AbstractWidget.py b/source/gui/widget/abc/AbstractWidget.py new file mode 100644 index 0000000..29fd6e9 --- /dev/null +++ b/source/gui/widget/abc/AbstractWidget.py @@ -0,0 +1,51 @@ +from abc import ABC +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from source.gui.scene.abc import AbstractScene + from source.gui.window import Window + + +class AbstractWidget(ABC): + """ + 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: "AbstractScene"): pass + def on_scene_removed(self, scene: "AbstractScene"): pass + + # scene event + + def on_window_added(self, window: "Window", scene: "AbstractScene"): pass + def on_window_removed(self, window: "Window", scene: "AbstractScene"): pass + + # global event + + def on_draw(self, window: "Window", scene: "AbstractScene"): pass + def on_resize(self, window: "Window", scene: "AbstractScene", width: int, height: int): pass + def on_hide(self, window: "Window", scene: "AbstractScene"): pass + def on_show(self, window: "Window", scene: "AbstractScene"): pass + def on_close(self, window: "Window", scene: "AbstractScene"): pass + def on_expose(self, window: "Window", scene: "AbstractScene"): pass + def on_activate(self, window: "Window", scene: "AbstractScene"): pass + def on_deactivate(self, window: "Window", scene: "AbstractScene"): pass + def on_text(self, window: "Window", scene: "AbstractScene", char: str): pass + def on_move(self, window: "Window", scene: "AbstractScene", x: int, y: int): pass + def on_context_lost(self, window: "Window", scene: "AbstractScene"): pass + def on_context_state_lost(self, window: "Window", scene: "AbstractScene"): pass + def on_key_press(self, window: "Window", scene: "AbstractScene", symbol: int, modifiers: int): pass + def on_key_release(self, window: "Window", scene: "AbstractScene", symbol: int, modifiers: int): pass + def on_key_held(self, window: "Window", scene: "AbstractScene", dt: float, symbol: int, modifiers: int): pass + def on_mouse_enter(self, window: "Window", scene: "AbstractScene", x: int, y: int): pass + def on_mouse_leave(self, window: "Window", scene: "AbstractScene", x: int, y: int): pass + def on_text_motion(self, window: "Window", scene: "AbstractScene", motion: int): pass + def on_text_motion_select(self, window: "Window", scene: "AbstractScene", motion: int): pass + def on_mouse_motion(self, window: "Window", scene: "AbstractScene", x: int, y: int, dx: int, dy: int): pass + def on_mouse_press(self, window: "Window", scene: "AbstractScene", x: int, y: int, button: int, modifiers: int): pass + def on_mouse_release(self, window: "Window", scene: "AbstractScene", x: int, y: int, button: int, modifiers: int): pass + def on_mouse_drag(self, window: "Window", scene: "AbstractScene", x: int, y: int, dx: int, dy: int, buttons: int, modifiers: int): pass + def on_mouse_scroll(self, window: "Window", scene: "AbstractScene", x: int, y: int, scroll_x: float, scroll_y: float): pass diff --git a/source/gui/widget/abc/__init__.py b/source/gui/widget/abc/__init__.py new file mode 100644 index 0000000..77304a3 --- /dev/null +++ b/source/gui/widget/abc/__init__.py @@ -0,0 +1,3 @@ +from .AbstractWidget import AbstractWidget +from .AbstractBoxWidget import AbstractBoxWidget +from .AbstractResizableWidget import AbstractResizableWidget diff --git a/source/gui/widget/base/BaseAdaptativeWidget.py b/source/gui/widget/base/BaseAdaptativeWidget.py deleted file mode 100644 index fc77a16..0000000 --- a/source/gui/widget/base/BaseAdaptativeWidget.py +++ /dev/null @@ -1,44 +0,0 @@ -from typing import Optional - -from source.gui.widget.base import BaseBoxWidget -from source.type import Percentage - - -class BaseAdaptativeWidget(BaseBoxWidget): - def __init__(self, x: int | Percentage, y: int | Percentage, width: int | Percentage, height: int | Percentage): - super().__init__(x, y, width, height) - - self._window_width: Optional[int] = None - self._window_height: Optional[int] = None - - # getter / setter - - def on_window_added(self, window: "Window", scene: "BaseScene"): - self._window_width = window.width - self._window_height = window.height - - @property - def x(self) -> int: - return self._x if isinstance(self._x, int) else self._x * self._window_width - - @property - def y(self) -> int: - return self._y if isinstance(self._y, int) else self._y * self._window_height - - @property - def width(self) -> int: - return self._width if isinstance(self._width, int) else self._width * self._window_width - - @property - def height(self) -> int: - return self._height if isinstance(self._height, int) else self._height * self._window_height - - # event - - def update_size(self): pass - - def on_resize(self, window: "Window", scene: "BaseScene", width: int, height: int): - self._window_width = width - self._window_height = height - - self.update_size() diff --git a/source/gui/widget/base/BaseWidget.py b/source/gui/widget/base/BaseWidget.py deleted file mode 100644 index 48a9c3f..0000000 --- a/source/gui/widget/base/BaseWidget.py +++ /dev/null @@ -1,50 +0,0 @@ -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - from source.gui.scene.base import BaseScene - from source.gui.window import Window - - -class BaseWidget: - """ - 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: "BaseScene"): pass - def on_scene_removed(self, scene: "BaseScene"): pass - - # scene event - - def on_window_added(self, window: "Window", scene: "BaseScene"): pass - def on_window_removed(self, window: "Window", scene: "BaseScene"): pass - - # global event - - def on_draw(self, window: "Window", scene: "BaseScene"): pass - def on_resize(self, window: "Window", scene: "BaseScene", width: int, height: int): pass - def on_hide(self, window: "Window", scene: "BaseScene"): pass - def on_show(self, window: "Window", scene: "BaseScene"): pass - def on_close(self, window: "Window", scene: "BaseScene"): pass - def on_expose(self, window: "Window", scene: "BaseScene"): pass - def on_activate(self, window: "Window", scene: "BaseScene"): pass - def on_deactivate(self, window: "Window", scene: "BaseScene"): pass - def on_text(self, window: "Window", scene: "BaseScene", char: str): pass - def on_move(self, window: "Window", scene: "BaseScene", x: int, y: int): pass - def on_context_lost(self, window: "Window", scene: "BaseScene"): pass - def on_context_state_lost(self, window: "Window", scene: "BaseScene"): pass - def on_key_press(self, window: "Window", scene: "BaseScene", symbol: int, modifiers: int): pass - def on_key_release(self, window: "Window", scene: "BaseScene", symbol: int, modifiers: int): pass - def on_key_held(self, window: "Window", scene: "BaseScene", dt: float, symbol: int, modifiers: int): pass - def on_mouse_enter(self, window: "Window", scene: "BaseScene", x: int, y: int): pass - def on_mouse_leave(self, window: "Window", scene: "BaseScene", x: int, y: int): pass - def on_text_motion(self, window: "Window", scene: "BaseScene", motion: int): pass - def on_text_motion_select(self, window: "Window", scene: "BaseScene", motion: int): pass - def on_mouse_motion(self, window: "Window", scene: "BaseScene", x: int, y: int, dx: int, dy: int): pass - def on_mouse_press(self, window: "Window", scene: "BaseScene", x: int, y: int, button: int, modifiers: int): pass - def on_mouse_release(self, window: "Window", scene: "BaseScene", x: int, y: int, button: int, modifiers: int): pass - def on_mouse_drag(self, window: "Window", scene: "BaseScene", x: int, y: int, dx: int, dy: int, buttons: int, modifiers: int): pass - def on_mouse_scroll(self, window: "Window", scene: "BaseScene", x: int, y: int, scroll_x: float, scroll_y: float): pass diff --git a/source/gui/widget/base/Label.py b/source/gui/widget/base/Label.py new file mode 100644 index 0000000..d9895e0 --- /dev/null +++ b/source/gui/widget/base/Label.py @@ -0,0 +1,11 @@ +from typing import Optional + +import pyglet.text + + +class Label(pyglet.text.Label): + def update_size(self, x: int, y: int, width: Optional[int] = None, height: Optional[int] = None): + self.x = x + self.y = y + self.width = width + self.height = height diff --git a/source/gui/sprite/Sprite.py b/source/gui/widget/base/Sprite.py similarity index 75% rename from source/gui/sprite/Sprite.py rename to source/gui/widget/base/Sprite.py index 44a4ae1..0990740 100644 --- a/source/gui/sprite/Sprite.py +++ b/source/gui/widget/base/Sprite.py @@ -11,6 +11,8 @@ class Sprite(pyglet.sprite.Sprite): if width is not None: self.width = width if height is not None: self.height = height + # property + @pyglet.sprite.Sprite.width.setter def width(self, width: int): self.scale_x = width / self._orig_width @@ -18,3 +20,11 @@ class Sprite(pyglet.sprite.Sprite): @pyglet.sprite.Sprite.height.setter def height(self, height: int): self.scale_y = height / self._orig_height + + # other event + + def update_size(self, x: int, y: int, width: int, height: int): + self.x = x + self.y = y + self.width = width + self.height = height diff --git a/source/gui/widget/base/__init__.py b/source/gui/widget/base/__init__.py index e3b8a26..70f4050 100644 --- a/source/gui/widget/base/__init__.py +++ b/source/gui/widget/base/__init__.py @@ -1,3 +1,2 @@ -from .BaseWidget import BaseWidget -from .BaseBoxWidget import BaseBoxWidget -from .BaseAdaptativeWidget import BaseAdaptativeWidget +from .Label import Label +from .Sprite import Sprite diff --git a/source/gui/window/Window.py b/source/gui/window/Window.py index f8a134e..5a32fdd 100644 --- a/source/gui/window/Window.py +++ b/source/gui/window/Window.py @@ -3,7 +3,7 @@ from typing import TYPE_CHECKING, Callable import pyglet.window if TYPE_CHECKING: - from source.gui.scene import BaseScene + from source.gui.scene.abc import AbstractScene class Window(pyglet.window.Window): # NOQA @@ -26,16 +26,16 @@ class Window(pyglet.window.Window): # NOQA # scene system - def set_scene(self, *scenes: "BaseScene"): + def set_scene(self, *scenes: "AbstractScene"): self.clear() self.add_scene(*scenes) - def add_scene(self, *scenes: "BaseScene", priority: int = 0): + def add_scene(self, *scenes: "AbstractScene", priority: int = 0): for scene in scenes: self._scenes.insert(priority, scene) scene.on_window_added(self) - def remove_scene(self, *scenes: "BaseScene"): + def remove_scene(self, *scenes: "AbstractScene"): for scene in scenes: scene.on_window_removed(self) self._scenes.remove(scene)