From d6a65f3548db6c188eadf6eecca35b3a18576be1 Mon Sep 17 00:00:00 2001 From: Faraphel Date: Thu, 5 Jan 2023 10:01:37 +0100 Subject: [PATCH] added an "on_key_hold" event on the Window and Scene --- gui/scene/HelloWorldScene.py | 23 +++++++++++++++-------- gui/scene/Scene.py | 2 +- gui/window/Window.py | 23 ++++++++++++++++++++++- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/gui/scene/HelloWorldScene.py b/gui/scene/HelloWorldScene.py index d9c4b49..1d48600 100644 --- a/gui/scene/HelloWorldScene.py +++ b/gui/scene/HelloWorldScene.py @@ -1,3 +1,5 @@ +from datetime import datetime, timedelta + import pyglet from gui.scene import Scene @@ -13,21 +15,16 @@ class HelloWorldScene(Scene): """ def __init__(self): - self._backspace_hold_frame: int = 0 - self.label = pyglet.text.Label( "Hello World !", anchor_x="center", anchor_y="center" ) - def on_draw(self, window: Window) -> None: - if window.keys[pyglet.window.key.BACKSPACE]: - if self._backspace_hold_frame % 5 == 0: self.label.text = self.label.text[:-1] - self._backspace_hold_frame += 1 - else: - self._backspace_hold_frame = 0 + # remember the cooldown for the backspace button + self._hold_backspace_last_call: datetime = datetime.now() + def on_draw(self, window: Window) -> None: self.label.draw() def on_resize(self, window: Window, width: int, height: int) -> None: @@ -36,3 +33,13 @@ class HelloWorldScene(Scene): def on_text(self, window: Window, char: str): self.label.text += char + + def on_key_held(self, window: Window, dt: float, symbol: int, modifiers: int): + if symbol == pyglet.window.key.BACKSPACE: + + # add a cooldown of 0.1 second on the backspace key + now = datetime.now() + if self._hold_backspace_last_call + timedelta(seconds=0.1) < now: + self._hold_backspace_last_call = now + + self.label.text = self.label.text[:-1] diff --git a/gui/scene/Scene.py b/gui/scene/Scene.py index 8bdbaf0..6e79a1f 100644 --- a/gui/scene/Scene.py +++ b/gui/scene/Scene.py @@ -28,6 +28,7 @@ class Scene(pyglet.event.EventDispatcher): def on_context_state_lost(self, window: Window): pass def on_key_press(self, window: Window, symbol: int, modifiers: int): pass def on_key_release(self, window: Window, symbol: int, modifiers: int): pass + def on_key_held(self, window: Window, dt: float, symbol: int, modifiers: int): pass def on_mouse_enter(self, window: Window, x: int, y: int): pass def on_mouse_leave(self, window: Window, x: int, y: int): pass def on_text_motion(self, window: Window, motion: int): pass @@ -40,4 +41,3 @@ class Scene(pyglet.event.EventDispatcher): - diff --git a/gui/window/Window.py b/gui/window/Window.py index a57954d..0d9bf9a 100644 --- a/gui/window/Window.py +++ b/gui/window/Window.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import Optional, Callable import pyglet.window @@ -22,6 +22,9 @@ class Window(pyglet.window.Window): # NOQA - pycharm think pyglet window is abs self.keys = pyglet.window.key.KeyStateHandler() self.push_handlers(self.keys) + # + self._on_key_held_events: dict[(int, int), Callable] = {} + # scene methods def set_scene(self, scene: Scene) -> None: @@ -104,11 +107,29 @@ class Window(pyglet.window.Window): # NOQA - pycharm think pyglet window is abs def on_key_press(self, symbol: int, modifiers: int): super().on_key_press(symbol, modifiers) # this function is already defined and used + + # this allows the on_key_held event to be called every frame after a press + pyglet.clock.schedule(self.get_on_key_held_function(symbol, modifiers)) + for scene in self._scenes: scene.on_key_press(self, symbol, modifiers) def on_key_release(self, symbol: int, modifiers: int): + # this allows the on_key_held event to stop after the key is released + pyglet.clock.unschedule(self.get_on_key_held_function(symbol, modifiers)) + for scene in self._scenes: scene.on_key_release(self, symbol, modifiers) + def get_on_key_held_function(self, symbol: int, modifiers: int): + key: tuple[int, int] = (symbol, modifiers) + + if key not in self._on_key_held_events: + self._on_key_held_events[key] = lambda dt: self.on_key_held(dt, symbol, modifiers) + + return self._on_key_held_events[key] + + def on_key_held(self, dt: float, symbol: int, modifiers: int): + for scene in self._scenes: scene.on_key_held(self, dt, symbol, modifiers) + def on_mouse_enter(self, x: int, y: int): for scene in self._scenes: scene.on_mouse_enter(self, x, y)