Skip to content

Commit 444f765

Browse files
committed
Update set_timer patch
1 parent bcffe7f commit 444f765

File tree

1 file changed

+63
-6
lines changed

1 file changed

+63
-6
lines changed

platform_wasm/pygame/timer.py

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import asyncio
2+
from typing import Union
3+
import uuid
24

35
# =================================================
46
# do no change import order for *thread*
@@ -27,20 +29,75 @@
2729
# - could be possibly very late
2830
# - delay cannot be less than frametime at device refresh rate.
2931

32+
# Local testing wrap patch_set_timer in a function and
33+
# only apply on emscripten platform, so running pygame vanilla doesn't break
34+
#
35+
# import platform
36+
#
37+
# def patch_timer():
38+
# THREADS = {}
39+
#
40+
# def patch_set_timer(
41+
# event: Union[int, pygame.event.Event], millis: int, loops: int = 0):
42+
# ...
43+
44+
# async def fire_event(thread_uuid):
45+
# ...
46+
#
47+
# pygame.time.set_timer = patch_set_timer
48+
#
49+
# if platform.system().lower() == "emscripten":
50+
# patch_timer()
51+
52+
53+
# Global var to keep track of timer threads
54+
# - key: event type
55+
# - value: thread uuid
56+
THREADS = {}
57+
58+
59+
def patch_set_timer(
60+
event: Union[int, pygame.event.Event], millis: int, loops: int = 0):
61+
"""Patches the pygame.time.set_timer function to use gthreads"""
3062

31-
def patch_set_timer(cust_event_no, millis, loops=0):
3263
dlay = float(millis) / 1000
33-
cevent = pygame.event.Event(cust_event_no)
34-
loop = asyncio.get_event_loop()
64+
cevent = pygame.event.Event(event)
65+
event_loop = asyncio.get_event_loop()
66+
67+
async def fire_event(thread_uuid):
68+
"""The thread's target function to handle the timer
3569
36-
async def fire_event():
70+
Early exit conditions:
71+
- event loop is closed
72+
- event type is no longer in THREADS dictionary
73+
- the thread's uuid is not the latest one
74+
- Max loop iterations if loops param is not zero
75+
"""
76+
loop_counter = 0
3777
while True:
3878
await asyncio.sleep(dlay)
39-
if loop.is_closed():
79+
if (
80+
event_loop.is_closed()
81+
or event not in THREADS
82+
or THREADS[event] != thread_uuid
83+
or (loops and loop_counter >= loops)
84+
):
4085
break
86+
4187
pygame.event.post(cevent)
88+
loop_counter += 1 if loops else 0
89+
90+
if dlay > 0:
91+
# uuid is used to track the latest thread,
92+
# stale threads will be terminated
93+
thread_uuid = uuid.uuid4()
94+
Thread(target=fire_event, args=[thread_uuid]).start()
95+
THREADS[event] = thread_uuid
4296

43-
Thread(target=fire_event).start()
97+
else:
98+
# This cancels the timer for the event
99+
if event in THREADS:
100+
del THREADS[event]
44101

45102

46103
pygame.time.set_timer = patch_set_timer

0 commit comments

Comments
 (0)