X-Git-Url: https://scm.cri.ensmp.fr/git/minwii.git/blobdiff_plain/7d014e3dc9f077f1b0402aed8f957146bf317ea7..90331dd4caff60e9517c862101a37d1ae4ee00d1:/src/app/widgets/cursors.py diff --git a/src/app/widgets/cursors.py b/src/app/widgets/cursors.py index b52bfb3..c8df104 100755 --- a/src/app/widgets/cursors.py +++ b/src/app/widgets/cursors.py @@ -8,45 +8,32 @@ $URL$ import pygame import os +from threading import Thread +import time from eventutils import EventHandlerMixin, event_handler from itertools import cycle -from pygame.locals import USEREVENT -TIMEOUT = USEREVENT + 1 -class WarpingCursor(pygame.sprite.Sprite, EventHandlerMixin): +class WarpingCursor(pygame.sprite.DirtySprite, EventHandlerMixin): ''' The class for animating the warping cursor - - duration: - The duration of each image in the animation - centerPosition: - The Position of the center of the cursor - _imagePointer: - A pointer to the current image - _animationOffset: - The time elapsed since when the current image should have been displayed ''' - #screen = None - #images = None - #durations = None - #centerPosition = None - #_imagePointer = None - #_animationOffset = None - + @staticmethod def _get_theme_images(name) : basePath = os.path.abspath(__file__).split(os.path.sep)[:-1] - basePath.append('data') + basePath.extend(['data', 'cursor']) basePath.append(name) basePath = os.path.sep.join(basePath) images = [f for f in os.listdir(basePath) if os.path.splitext(f)[1] == '.png'] return basePath, images - def __init__(self, theme='black', duration=75): - pygame.sprite.Sprite.__init__(self) + def __init__(self, theme='black', duration=50, blinkMode=True): + pygame.sprite.DirtySprite.__init__(self) imagesPath, images = WarpingCursor._get_theme_images(theme) - self.flashImage = images.pop(images.index('flash.png')) + flashImage = images.pop(images.index('flash.png')) + flashImagePath = os.path.sep.join([imagesPath, flashImage]) + self.flashImage = pygame.image.load(flashImagePath).convert_alpha() images.sort(lambda a, b : cmp(*[int(os.path.splitext(f)[0]) for f in [a, b]])) self.images = [] @@ -55,92 +42,89 @@ class WarpingCursor(pygame.sprite.Sprite, EventHandlerMixin): img = pygame.image.load(imagePath).convert_alpha() self.images.append(img) - self._imageLength = len(self.images) # assumes that all images have same dimensions self.width = self.images[0].get_width() self.height = self.images[0].get_height() self.duration = duration self.image = self.images[0] - self.rect = pygame.Rect((0,0), (self.width, self.height)) + # workarround cursor alignement problem + pygame.event.set_blocked(pygame.MOUSEMOTION) + pygame.mouse.set_pos(pygame.mouse.get_pos()) + pygame.event.set_allowed(pygame.MOUSEMOTION) + # --- + x, y = pygame.mouse.get_pos() + left = x - self.width / 2 + top = y - self.height / 2 + self.rect = pygame.Rect((left, top), (self.width, self.height)) - surface = pygame.display.get_surface() - surface.blit(self.image, self.rect) + self.blinkMode = blinkMode self._startBlink() - - #self.flashImagePath = flashImage - #self.durations = durations - #self.centerPosition = initCenterPosition - #self.flashLength = 100 - #self.flashing = False - #self.image = pygame.image.load(self.images[0]).convert_alpha() - #self._imagePointer = 0 - #self._animationOffset = 0 - #self._flashTimer = 0 + + def __del__(self) : + if hasattr(self, 'timer') : + try : self.timer.stop() + except : pass def _startBlink(self) : - pygame.time.set_timer(TIMEOUT, self.duration) - self.iterator = self.iterImages() + if self.blinkMode : + self._blinking = True + self.iterator = self.iterImages() + self.timer = ForeverTimer(self.duration, self.loadNext) + self.timer.start() + def _stopBlink(self) : + if self.blinkMode : + self.timer.stop() + def iterImages(self) : for img in cycle(self.images) : yield img - @event_handler(TIMEOUT) - def loadNext(self, event) : - self.image = self.iterator.next() - surface = pygame.display.get_surface() - surface.blit(self.image, self.rect) - - def update(self) : - print 'cursor update' - -# def update(self, elapsedTime, centerPosition): -# ''' -# Update the cursor's look and position -# -# elapsedTime: -# The time passed since the previous update -# centerPosition: -# the new position of the creep -# ''' -# self._updateImage(elapsedTime) -# self.centerPosition = centerPosition -# if self.flashing : -# self._flashTimer += elapsedTime -# if self._flashTimer > self.flashLength: -# self.flashing = False + def loadNext(self) : + if self._blinking : + self.dirty = 1 + self.image = self.iterator.next() - def _updateImage(self, elapsedTime): - ''' - Update the cursor's image - - elapsedTime: - The time passed since the previous update - ''' - self._animationOffset += elapsedTime - - if self._animationOffset > self.duration : - #New animation offset is computed first, before updating the pointer - self._animationOffset -= self.duration - #point to the next image (restarts from the beginning when it reaches the end) - self._imagePointer = (self._imagePointer + 1) % len(self.images) - - if self.flashing: - self.image = pygame.image.load(self.flashImagePath).convert_alpha() + @event_handler(pygame.MOUSEBUTTONDOWN) + def flashOn(self, event) : + self.dirty = 1 + self._blinking = False + self.image = self.flashImage + + @event_handler(pygame.MOUSEBUTTONUP) + def flashOff(self, event) : + self.dirty = 1 + if self.blinkMode : + self._blinking = True else : - self.image = pygame.image.load(self.images[self._imagePointer]).convert_alpha() + self.image = self.images[0] - def flash(self,flashLength = None): - self._flashTimer = 0 - self.flashing = True - if flashLength: - self.flashlength = flashLength + @event_handler(pygame.MOUSEMOTION) + def move(self, event) : + self.dirty = 1 + self.rect.move_ip(event.rel) - def blit(self,surface): - ''' - Draw the circle on surface - ''' - - newPos = (self.centerPosition[0] - self.image.get_width() / 2, self.centerPosition[1] - self.image.get_height() / 2) - surface.blit(self.image, newPos) + def setPosition(self, pos) : + self.dirty = 1 + x, y = pos + rx, ry = self.rect.centerx, self.rect.centery + self.rect.move_ip(x-rx, y-ry) + + +class ForeverTimer(Thread) : + def __init__(self, duration, func, *args, **kw) : + Thread.__init__(self) + self.duration = duration / 1000. + self.func = func + self.args = args + self.kw = kw + self.running = True + + def run(self) : + while self.running : + self.func(*self.args, **self.kw) + time.sleep(self.duration) + + def stop(self) : + self.running = False \ No newline at end of file