Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
gottadiveintopython committed Dec 10, 2023
1 parent 222050b commit 5432a99
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 16 deletions.
4 changes: 2 additions & 2 deletions src/asyncpygame/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
'Timer', 'sleep', 'move_on_after',
'anim_with_dt', 'anim_with_dt_et', 'anim_with_dt_et_ratio', 'anim_with_et', 'anim_with_ratio',
'PriorityDispatcher',
'sdl_event',
'sdl_event', 'sdl_event_repeatedly',
'run_in_thread', 'run_in_executor',
# 'PrefilledAPIs',
)
Expand All @@ -15,6 +15,6 @@
anim_with_dt, anim_with_dt_et, anim_with_dt_et_ratio, anim_with_et, anim_with_ratio,
)
from ._priority_dispatcher import PriorityDispatcher
from ._sdl_event import sdl_event
from ._sdl_event import sdl_event, sdl_event_repeatedly
from ._threads import run_in_thread, run_in_executor
# from ._pre_filled_apis import PrefilledAPIs
88 changes: 75 additions & 13 deletions src/asyncpygame/_sdl_event.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,103 @@
import types
from collections.abc import Awaitable
from collections.abc import Awaitable, Callable
from functools import partial

from asyncgui import _current_task, _sleep_forever
from pygame.event import Event

from .constants import DEFAULT_PRIORITY
from ._priority_dispatcher import PriorityDispatcher


def _resume_task(task_step, filter, event: Event):
r = filter(event)
if r:
task_step(event)
return r


@types.coroutine
def sdl_event(dispatcher: PriorityDispatcher, *, priority=DEFAULT_PRIORITY, filter=lambda event: True) -> Awaitable[Event]:
def sdl_event(dispatcher, *, priority=DEFAULT_PRIORITY, filter=lambda event: True) -> Awaitable[Event]:
'''
Waits for a SDL event to occur
Waits for a SDL event to occur.
.. code-block::
e = await sdl_event(dispatcher)
print(f"A {pygame.event.event_name(e.type)} event occurred.")
You usually want to wait for an event of specific type(s).
You probably want to wait for an event of specific type(s).
.. code-block::
e = await sdl_event(dispatcher, filter=lambda e: e.type == pygame.FINGERDOWN)
print("A FINGERDOWN event occurred")
'''
task = (yield _current_task)[0][0]

def _callback(event):
r = filter(event)
if r:
task._step(event)
return r

sub = dispatcher.add_subscriber(_callback, priority)
sub = dispatcher.add_subscriber(partial(_resume_task, task._step, filter), priority)
try:
return (yield _sleep_forever)[0][0]
finally:
sub.cancel()


class sdl_event_repeatedly:
'''
Returns an async context manager that provides an efficient way to repeat waiting for a SDL event to occur.
.. code-block::
async with sdl_event_repeatedly(dispatcher) as sdl_event:
while True:
e = await sdl_event()
print(f"A {pygame.event.event_name(e.type)} event occurred.")
This API is designed to handle SDL events that may frequently occur, such as ``MOUSEMOTION`` or ``FINGERMOTION``:
.. code-block::
def filter(event, allowed_list=(MOUSEMOTION, MOUSEBUTTONUP)):
return event.type in allowed_list
async with sdl_event_repeatedly(dispatcher, filter=filter) as sdl_event:
while True:
e = await sdl_event()
if e.type == MOUSEBUTTONUP:
break
print(f"The mouse cursor is now at ({e.x}, {e.y}).")
**Restriction**
You are not allowed to perform any kind of async operations inside the with-block except ``await sdl_event()``.
.. code-block::
async with sdl_event_repeatedly(dispatcher) as sdl_event:
await sdl_event() # OK
await something_else # NOT ALLOWED
async with async_context_manager: # NOT ALLOWED
...
async for __ in async_iterator: # NOT ALLOWED
...
'''

def __init__(self, dispatcher, *, filter=lambda event: True, priority=DEFAULT_PRIORITY):
self._dispatcher = dispatcher
self._filter = filter
self._priority = priority

@staticmethod
@types.coroutine
def _wait_for_an_event_to_occur(_sleep_forever=_sleep_forever) -> Awaitable[Event]:
return (yield _sleep_forever)[0][0]

@types.coroutine
def __aenter__(self) -> Awaitable[Callable[[], Awaitable[Event]]]:
task = (yield _current_task)[0][0]
self._subscriber = self._dispatcher.add_subscriber(
partial(_resume_task, task._step, self._filter),
self._priority,
)
return self._wait_for_an_event_to_occur

async def __aexit__(self, *args):
self._subscriber.cancel()
2 changes: 1 addition & 1 deletion src/asyncpygame/_timer.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def schedule_interval(self, func, interval) -> TimerEvent:

async def sleep(timer, duration) -> Awaitable:
'''
An async form of :meth:`asyncpygame.Timer.schedule_once`.
Waits for a specified period of time (in milli seconds)
.. code-block::
Expand Down

0 comments on commit 5432a99

Please sign in to comment.