Skip to content

Commit 4d68de3

Browse files
committed
Fix debounce
1 parent f7d3451 commit 4d68de3

1 file changed

Lines changed: 17 additions & 33 deletions

File tree

webgpu/canvas.py

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414

1515
@dataclass
1616
class _DebounceData:
17-
t_last: float | None = None
17+
t_last_frame: float = 0
18+
t_last_call: float = 0
1819
timer: threading.Timer | None = None
19-
running: bool = False
20+
lock: Lock = None
2021

2122

2223
def debounce(arg=None):
@@ -29,54 +30,37 @@ def debounced(obj, *args, **kwargs):
2930

3031
fname = func.__name__
3132
if obj._debounce_data.get(fname, None) is None:
32-
obj._debounce_data[fname] = _DebounceData(None, None)
33+
obj._debounce_data[fname] = _DebounceData(0, 0, None, Lock())
3334

3435
data = obj._debounce_data[fname]
36+
t_call = time.time()
37+
data.t_last_call = t_call
3538

36-
# check if we already have a render scheduled
37-
if platform.is_pyodide:
38-
if data.timer is not None and not data.timer.done():
39-
return
40-
else:
41-
if data.timer is not None or data.running:
42-
return
39+
frame_time = 1.0 / target_fps
4340

4441
def f():
45-
# clear the timer, so we can schedule a new one with the next function call
46-
t = time.time()
47-
data.timer = None
48-
if platform.is_pyodide:
49-
# due to async nature, we need to update t_last before calling func
50-
data.t_last = t
42+
with data.lock:
43+
if t_call != data.t_last_call and t_call - data.t_last_frame < frame_time:
44+
return
45+
46+
data.t_last_frame = time.time()
5147
func(obj, *args, **kwargs)
52-
else:
53-
data.t_last = t
54-
data.running = True
55-
try:
56-
func(obj, *args, **kwargs)
57-
finally:
58-
data.running = False
59-
60-
if data.timer is not None:
61-
return
6248

63-
if data.t_last is None:
64-
# first call -> just call the function immediately
65-
data.t_last = time.time()
49+
t_wait = frame_time - (t_call - data.t_last_frame)
50+
51+
if t_wait <= 0:
6652
f()
6753
return
6854

69-
t_wait = max(1 / target_fps - (time.time() - data.t_last), 0)
7055
if platform.is_pyodide:
7156
import asyncio
7257
async def _runner():
7358
if t_wait > 0:
7459
await asyncio.sleep(t_wait)
7560
f()
76-
data.timer = asyncio.create_task(_runner())
61+
asyncio.create_task(_runner())
7762
else:
78-
data.timer = threading.Timer(t_wait, f)
79-
data.timer.start()
63+
threading.Timer(t_wait, f).start()
8064

8165
debounced._original = func
8266
return debounced

0 commit comments

Comments
 (0)