diff --git a/cmu_graphics/cmu_graphics.py b/cmu_graphics/cmu_graphics.py index b94a5e05..00b91f9e 100644 --- a/cmu_graphics/cmu_graphics.py +++ b/cmu_graphics/cmu_graphics.py @@ -1148,7 +1148,8 @@ def run(self): sys.stdout.flush() with DRAWING_LOCK: had_event = False - for event in pygame.event.get(): + all_events = pygame.event.get() + for event in all_events: had_event = True if not self.stopped: if event.type == pygame.MOUSEBUTTONDOWN and event.button <= 3: @@ -1159,17 +1160,6 @@ def run(self): self.callUserFn( 'onMouseRelease', (*event.pos, event.button - 1) ) - elif event.type == pygame.MOUSEMOTION: - if event.buttons == (0, 0, 0): - self.callUserFn('onMouseMove', event.pos) - else: - self.callUserFn( - 'onMouseDrag', - ( - *event.pos, - [i for i in range(3) if event.buttons[i] != 0], - ), - ) elif event.type == pygame.KEYDOWN: self.handleKeyPress(event.key, event.mod) elif event.type == pygame.KEYUP: @@ -1194,6 +1184,31 @@ def run(self): msPassed = pygame.time.get_ticks() - lastTick if 1000 / self.stepsPerSecond - msPassed < 1: lastTick = pygame.time.get_ticks() + mousemotion_events = [ + event + for event in all_events + if event.type == pygame.MOUSEMOTION + ] + if len(mousemotion_events) > 0: + compressed_event = mousemotion_events[-1] + for event in mousemotion_events: + if event.buttons != (0, 0, 0): + compressed_event.buttons = event.buttons + + if compressed_event.buttons == (0, 0, 0): + self.callUserFn('onMouseMove', compressed_event.pos) + else: + self.callUserFn( + 'onMouseDrag', + ( + *compressed_event.pos, + [ + i + for i in range(3) + if compressed_event.buttons[i] != 0 + ], + ), + ) if not (self.paused or self.stopped): self.callUserFn('onStep', ()) if len(self._allKeysDown) > 0: @@ -1282,6 +1297,7 @@ def __setattr__(self, attr, value): return self._app.__setattr__(attr, value) return super().__setattr__(attr, value) + def processRunAppArgs(args, kwargs): # Extract width and height (and their translations) from kwargs width = 400 @@ -1325,6 +1341,7 @@ def processRunAppArgs(args, kwargs): return width, height, remaining_kwargs + def runApp(*args, **kwargs): width, height, remaining_kwargs = processRunAppArgs(args, kwargs) @@ -1359,7 +1376,9 @@ def runApp(*args, **kwargs): # Don't redraw on either of these calls to callUserFn, because we will # instead redraw below - app._app.callUserFn('onAppStart', (), remaining_kwargs, redraw=False, useActiveScreen=False) + app._app.callUserFn( + 'onAppStart', (), remaining_kwargs, redraw=False, useActiveScreen=False + ) if app._app._initialScreen is not None: sortedGlobals = sorted(app._app.userGlobals) @@ -1385,7 +1404,7 @@ def setActiveScreen(screen, fromRunApp=False): ) if (screen in [None, '']) or (not isinstance(screen, str)): raise Exception(f'{repr(screen)} is not a valid screen') - + redrawAllFnNames = ['redrawAll'] redrawAllInCorrectLanguage = 'redrawAll' for language, translations in shape_logic.TRANSLATED_USER_FUNCTION_NAMES.items(): @@ -1395,16 +1414,20 @@ def setActiveScreen(screen, fromRunApp=False): if redrawAllTranslation not in redrawAllFnNames: redrawAllFnNames.append(redrawAllTranslation) if language == shape_logic.cmuGraphicsLanguage: - redrawAllInCorrectLanguage = redrawAllTranslation + redrawAllInCorrectLanguage = redrawAllTranslation - if not any(f'{screen}_{fnName}' in app._app.userGlobals for fnName in redrawAllFnNames): - raise Exception(t( - "Screen '{{screen}}' requires '{{screen}}_{{redrawAllInCorrectLanguage}}()'", - { - 'screen': screen, - 'redrawAllInCorrectLanguage': redrawAllInCorrectLanguage, - } - )) + if not any( + f'{screen}_{fnName}' in app._app.userGlobals for fnName in redrawAllFnNames + ): + raise Exception( + t( + "Screen '{{screen}}' requires '{{screen}}_{{redrawAllInCorrectLanguage}}()'", + { + 'screen': screen, + 'redrawAllInCorrectLanguage': redrawAllInCorrectLanguage, + }, + ) + ) if fromRunApp: app._app.handleSetActiveScreen(screen, redraw=False) else: