def create_cursor(size, data, mask): """ Create cursor image from binary data. Arguments cursor size and its binary data and mask. Return surface, can be used with mouse.set_cursor. """ surface = Surface(size, Const.SRCALPHA) black = Color(0, 0, 0, 255) white = Color(255, 255, 255, 255) x = y = 0 rang = range(8) for i in range(len(data)): if data[i] or mask[i]: for j in rang: if data[i] & 0x01 << 7 - j: surface.setFillStyle(black) surface.fillRect(x + j, y, 1, 1) elif mask[i] & 0x01 << 7 - j: surface.setFillStyle(white) surface.fillRect(x + j, y, 1, 1) x += 8 if x >= size[0]: x = 0 y += 1 return surface
def convert_image(self, image): """ Return the image as a Surface. """ if env.canvas._isCanvas: surface = Surface((image.width,image.height)) surface.drawImage(image, 0, 0) else: surface = Surf(image) return surface
def convert_image(self, image): """ Return the image as a Surface. """ if env.canvas._isCanvas: surface = Surface((image.width, image.height)) surface.drawImage(image, 0, 0) else: surface = Surf(image) return surface
def scale(self, surface, size, dest=None): """ Return Surface resized by the given size. An optional destination surface can be provided. """ if not dest: surf = Surface(size) else: surf = dest surf.drawImage(surface.canvas, 0, 0, surface.get_width(), surface.get_height(), 0, 0, size[0], size[1]) return surf
def __init__(self, size, buffered): Surface.__init__(self, size) if isinstance(buffered, bool): self._bufferedimage = buffered else: self._bufferedimage = True try: if self.impl.canvasContext: self._isCanvas = True except: self._isCanvas = False self._bufferedimage = False if self._bufferedimage: self.surface = Surface(size) else: self.surface = self self.images = {} self.image_list = [] self.callback = None self.time = Time() self.event = env.event self.addMouseListener(self) self.addKeyEventListener(self) self.sinkEvents(Event.ONMOUSEDOWN | Event.ONMOUSEUP | Event.ONMOUSEMOVE | Event.ONMOUSEOUT | Event.ONMOUSEWHEEL | Event.ONKEYDOWN | Event.ONKEYPRESS | Event.ONKEYUP) self.onContextMenu = None self.preventContextMenu() self.evt = self.event.eventObj self.modKey = self.event.modKey self.specialKey = self.event.specialKey self.modKeyCode = self.event.modKeyCode self.specialKeyCode = self.event.specialKeyCode self.keyRepeat = self.event.keyRepeat self.keyHeld = self.event.keyHeld self.mouse_entered = True self.event._initiate_touch_listener(self) self._touch_callback = self.event.touchlistener.callback self._rect_list = [] self._rect_len = 0 self._rect_num = 0 self._framerate = 0 self._frametime = 0 self._rendertime = self.time.time() self._pause = False self._canvas_init() self.run = None self.initialized = False
def make_surface(array): """ Generates image pixels from array data. Argument array containing image data. Return Surface generated from array. """ surface = Surface((array._imagedata.width, array._imagedata.height)) blit_array(surface, array) return surface
def __init__(self, size, buffered): Surface.__init__(self, size) MouseWheelHandler.__init__(self, True) if isinstance(buffered, bool): self._bufferedimage = buffered else: self._bufferedimage = True try: if self.impl.canvasContext: self._isCanvas = True except: self._isCanvas = False self._bufferedimage = False if self._bufferedimage: self.surface = Surface(size) else: self.surface = self self.images = {} self.image_list = [] self.callback = None self.time = Time() self.event = pyjsdl.event self.addMouseListener(self) self.addMouseWheelListener(self) self.addKeyboardListener(self) self.sinkEvents(Event.ONMOUSEDOWN | Event.ONMOUSEUP | Event.ONMOUSEMOVE | Event.ONMOUSEOUT | Event.ONMOUSEWHEEL | Event.ONKEYDOWN | Event.ONKEYPRESS | Event.ONKEYUP) self.modKey = pyjsdl.event.modKey self.specialKey = pyjsdl.event.specialKey self.event._initiate_touch_listener(self) self._touch_callback = self.event.touchlistener.callback self._repaint = False self._rect_list = [] self._rect_len = 0 self._rect_num = 0 self._framerate = 0 self._frametime = 0 self._canvas_init() self.initialized = False
def __init__(self, size, buffered): Surface.__init__(self, size) MouseWheelHandler.__init__(self, True) if isinstance(buffered, bool): self._bufferedimage = buffered else: self._bufferedimage = True try: if self.impl.canvasContext: self._isCanvas = True except: self._isCanvas = False self._bufferedimage = False if self._bufferedimage: self.surface = Surface(size) else: self.surface = self self.images = {} self.image_list = [] self.callback = None self.time = Time() self.event = pyjsdl.event self.addMouseListener(self) self.addMouseWheelListener(self) self.addKeyboardListener(self) self.sinkEvents(Event.ONMOUSEDOWN | Event.ONMOUSEUP| Event.ONMOUSEMOVE | Event.ONMOUSEOUT | Event.ONMOUSEWHEEL | Event.ONKEYDOWN | Event.ONKEYPRESS | Event.ONKEYUP) self.modKey = pyjsdl.event.modKey self.specialKey = pyjsdl.event.specialKey self.event._initiate_touch_listener(self) self._touch_callback = self.event.touchlistener.callback self._repaint = False self._rect_list = [] self._rect_len = 0 self._rect_num = 0 self._framerate = 0 self._frametime = 0 self._canvas_init() self.initialized = False
def resize(self, width, height): Surface.resize(self, width, height) if self._bufferedimage: self.surface.resize(width, height) self.surface._display._surface_rect = self.surface.get_rect()
def rotozoom(self, surface, angle, size): """ Return Surface rotated and resized by the given angle and size. """ if not angle: width = int(surface.get_width() * size) height = int(surface.get_height() * size) return self.scale(surface, (width, height)) theta = angle * self.deg_rad width_i = int(surface.get_width() * size) height_i = int(surface.get_height() * size) cos_theta = _fabs(_cos(theta)) sin_theta = _fabs(_sin(theta)) width_f = int(_ceil((width_i * cos_theta) + (height_i * sin_theta))) if width_f % 2: width_f += 1 height_f = int(_ceil((width_i * sin_theta) + (height_i * cos_theta))) if height_f % 2: height_f += 1 surf = Surface((width_f, height_f)) surf.saveContext() surf.translate(width_f / 2.0, height_f / 2.0) surf.rotate(-theta) surf.drawImage(surface.canvas, 0, 0, surface.get_width(), surface.get_height(), -width_i / 2, -height_i / 2, width_i, height_i) surf.restoreContext() return surf
def rotate(self, surface, angle): """ Return Surface rotated by the given angle. """ if not angle: return surface.copy() theta = angle * self.deg_rad width_i = surface.get_width() height_i = surface.get_height() cos_theta = _fabs(_cos(theta)) sin_theta = _fabs(_sin(theta)) width_f = int((width_i * cos_theta) + (height_i * sin_theta)) height_f = int((width_i * sin_theta) + (height_i * cos_theta)) surf = Surface((width_f, height_f)) surf.saveContext() surf.translate(width_f / 2.0, height_f / 2.0) surf.rotate(-theta) surf.drawImage(surface.canvas, -width_i / 2, -height_i / 2) surf.restoreContext() return surf
def flip(self, surface, xbool=True, ybool=False): """ Return Surface that is flipped horizontally, vertically, or both. """ surf = Surface((surface.get_width(), surface.get_height())) surf.saveContext() if xbool and ybool: surf.translate(surface.get_width(), surface.get_height()) surf.scale(-1, -1) elif xbool: surf.translate(surface.get_width(), 0) surf.scale(-1, 1) elif ybool: surf.translate(0, surface.get_height()) surf.scale(1, -1) surf.drawImage(surface.canvas, 0, 0) surf.restoreContext() return surf
def render(self, text, antialias=True, color=(0,0,0), background=None, surface=None): #optional surface for text rendering """ Render text onto surface. Arguments are text to render, and optional antialias, RGB color of text, RGB color of background, and surface for text rendering. """ if not surface: w,h = self.size(text) surf = Surface((w,h)) else: surf = surface w,h = surface.width, surface.height if background: surf.setFillStyle(Color(background)) surf.fillRect(0,0,w,h) surf.setFont('%s %dpx %s' % (self.fontstyle, self.fontsize, self.fontname)) # if antialias: pass surf.setFillStyle(Color(color)) surf.setTextAlign('center') surf.setTextBaseline('middle') surf.fillText(text,w/2,h/2) if self.underline: surf.setLineWidth(self.fontsize/20) surf.setStrokeStyle(Color(color)) surf.beginPath() surf.moveTo(0, h*0.85) surf.lineTo(w, h*0.85) surf.stroke() return surf
def rotate(self, surface, angle): """ Return Surface rotated by the given angle. """ if not angle: return surface.copy() theta = angle*self.deg_rad width_i = surface.get_width() height_i = surface.get_height() cos_theta = _fabs( _cos(theta) ) sin_theta = _fabs( _sin(theta) ) width_f = int( (width_i*cos_theta)+(height_i*sin_theta) ) height_f = int( (width_i*sin_theta)+(height_i*cos_theta) ) surf = Surface((width_f,height_f)) surf.saveContext() surf.translate(width_f/2.0, height_f/2.0) surf.rotate(-theta) surf.drawImage(surface.canvas, -width_i/2, -height_i/2) surf.restoreContext() return surf
def render(self, text, antialias=True, color=(0, 0, 0), background=None, surface=None): #optional surface for text rendering """ Render text onto surface. Arguments are text to render, and optional antialias, RGB color of text, RGB color of background, and surface for text rendering. """ if not surface: w, h = self.size(text) surf = Surface((w, h)) else: surf = surface w, h = surface.width, surface.height if background: surf.setFillStyle(Color(background)) surf.fillRect(0, 0, w, h) surf.setFont('%s %dpx %s' % (self.fontstyle, self.fontsize, self.fontname)) # if antialias: pass surf.setFillStyle(Color(color)) surf.setTextAlign('center') surf.setTextBaseline('middle') surf.fillText(text, w / 2, h / 2) if self.underline: surf.setLineWidth(self.fontsize / 20) surf.setStrokeStyle(Color(color)) surf.beginPath() surf.moveTo(0, h * 0.85) surf.lineTo(w, h * 0.85) surf.stroke() return surf
def rotozoom(self, surface, angle, size): """ Return Surface rotated and resized by the given angle and size. """ if not angle: width = int(surface.get_width()*size) height = int(surface.get_height()*size) return self.scale(surface, (width, height)) theta = angle*self.deg_rad width_i = int(surface.get_width()*size) height_i = int(surface.get_height()*size) cos_theta = _fabs( _cos(theta) ) sin_theta = _fabs( _sin(theta) ) width_f = int( _ceil((width_i*cos_theta)+(height_i*sin_theta)) ) if width_f % 2: width_f += 1 height_f = int( _ceil((width_i*sin_theta)+(height_i*cos_theta)) ) if height_f % 2: height_f += 1 surf = Surface((width_f,height_f)) surf.saveContext() surf.translate(width_f/2.0, height_f/2.0) surf.rotate(-theta) surf.drawImage(surface.canvas, 0, 0, surface.get_width(), surface.get_height(), -width_i/2, -height_i/2, width_i, height_i) surf.restoreContext() return surf
class Canvas(Surface, MouseWheelHandler): def __init__(self, size, buffered): Surface.__init__(self, size) MouseWheelHandler.__init__(self, True) if isinstance(buffered, bool): self._bufferedimage = buffered else: self._bufferedimage = True try: if self.impl.canvasContext: self._isCanvas = True except: self._isCanvas = False self._bufferedimage = False if self._bufferedimage: self.surface = Surface(size) else: self.surface = self self.images = {} self.image_list = [] self.callback = None self.time = Time() self.event = pyjsdl.event self.addMouseListener(self) self.addMouseWheelListener(self) self.addKeyboardListener(self) self.sinkEvents(Event.ONMOUSEDOWN | Event.ONMOUSEUP | Event.ONMOUSEMOVE | Event.ONMOUSEOUT | Event.ONMOUSEWHEEL | Event.ONKEYDOWN | Event.ONKEYPRESS | Event.ONKEYUP) self.modKey = pyjsdl.event.modKey self.specialKey = pyjsdl.event.specialKey self.event._initiate_touch_listener(self) self._touch_callback = self.event.touchlistener.callback self._repaint = False self._rect_list = [] self._rect_len = 0 self._rect_num = 0 self._framerate = 0 self._frametime = 0 self._canvas_init() self.initialized = False def _canvas_init(self): global _canvas, _ctx, _img, _wnd _canvas = self _ctx = self.impl.canvasContext _img = self.surface.canvas _wnd = requestAnimationFrameInit() def onMouseMove(self, sender, x, y): event = DOM.eventGetCurrentEvent() event.pos = (x, y) self.event.mouseMove['x'], self.event.mouseMove['y'] = x, y self.event._updateQueue(event) def onMouseDown(self, sender, x, y): event = DOM.eventGetCurrentEvent() event.pos = (x, y) self.event.mousePress[event.button] = True self.event._updateQueue(event) def onMouseUp(self, sender, x, y): event = DOM.eventGetCurrentEvent() event.pos = (x, y) self.event.mousePress[event.button] = False self.event._updateQueue(event) def onMouseLeave(self, sender): self.event.mousePress[0], self.event.mousePress[ 1], self.event.mousePress[2] = False, False, False self.event.mouseMove['x'], self.event.mouseMove['y'] = -1, -1 self.event.mouseMoveRel['x'], self.event.mouseMoveRel['y'] = None, None for keycode in self.modKey: if self.event.keyPress[keycode]: self.event.keyPress[keycode] = False def onMouseWheel(self, sender, velocity): event = DOM.eventGetCurrentEvent() if event.type == 'mousewheel': #TODO: update for changes in mousewheel implementation if hasattr(event, 'wheelDeltaX'): self.onMouseWheel = self._onMouseWheel self._onMouseWheel(sender, velocity) else: self.onMouseWheel = self._onMouseWheelY DOM.eventGetMouseWheelVelocityY = eventGetMouseWheelVelocityY self._onMouseWheelY(sender, eventGetMouseWheelVelocityY(event)) else: #DOMMouseScroll self.onMouseWheel = self._onMouseScroll self._onMouseScroll(sender, velocity) def _onMouseWheel(self, sender, velocity): event = DOM.eventGetCurrentEvent() if not event.wheelDeltaX: if velocity < 0: button = 4 events = velocity / -3 else: button = 5 events = velocity / 3 else: if velocity < 0: button = 6 events = velocity / -3 else: button = 7 events = velocity / 3 event.btn = button event.pos = (self.event.mouseMove['x'], self.event.mouseMove['y']) for evt in range(events): self.event._updateQueue(event) def _onMouseWheelY(self, sender, velocity): event = DOM.eventGetCurrentEvent() if velocity < 0: button = 4 events = velocity / -3 else: button = 5 events = velocity / 3 event.btn = button event.pos = (self.event.mouseMove['x'], self.event.mouseMove['y']) for evt in range(events): self.event._updateQueue(event) def _onMouseScroll(self, sender, velocity): event = DOM.eventGetCurrentEvent() if velocity > 1 or velocity < -1: if velocity < 0: button = 4 else: button = 5 else: if velocity < 0: button = 6 else: button = 7 event.btn = button event.pos = (self.event.mouseMove['x'], self.event.mouseMove['y']) self.event._updateQueue(event) def onKeyDown(self, sender, keycode, modifiers): if keycode in self.modKey: event = DOM.eventGetCurrentEvent() self.event.keyPress[keycode] = True self.event._updateQueue(event) DOM.eventPreventDefault(event) elif keycode in self.specialKey: event = DOM.eventGetCurrentEvent() self.event._updateQueue(event) DOM.eventPreventDefault(event) def onKeyPress(self, sender, keycode, modifiers): event = DOM.eventGetCurrentEvent() if not (event.keyCode and event.keyCode in self.specialKey): self.event._updateQueue(event) DOM.eventPreventDefault(event) def onKeyUp(self, sender, keycode, modifiers): event = DOM.eventGetCurrentEvent() if keycode in self.modKey: self.event.keyPress[keycode] = False self.event._updateQueue(event) def onTouchInitiate(self, event): self.event.touchlistener.activate() for callback in self._touch_callback: if hasattr(callback, 'onTouchInitiate'): callback.onTouchInitiate(event) self.onTouchStart(event) def onTouchStart(self, event): for callback in self._touch_callback: callback.onTouchStart(event) def onTouchEnd(self, event): for callback in self._touch_callback: callback.onTouchEnd(event) def onTouchMove(self, event): for callback in self._touch_callback: callback.onTouchMove(event) def onTouchCancel(self, event): for callback in self._touch_callback: callback.onTouchCancel(event) def resize(self, width, height): Surface.resize(self, width, height) if self._bufferedimage: self.surface.resize(width, height) self.surface._display._surface_rect = self.surface.get_rect() def set_callback(self, cb): if not hasattr(cb, 'run'): self.callback = Callback(cb) else: self.callback = cb def load_images(self, images): if images: image_list = [] for image in images: if isinstance(image, str): image_list.append(image) self.image_list.append(image) else: name = image[0] if isinstance(image[1], str): data = image[1] else: data = base64.b64encode(image[1].getvalue()) if not data.startswith('data:'): ext = name.strip().split('.')[-1] data = "data:%s;base64,%s" % (ext, data) #data:[<mediatype>][;base64],<data> image_list.append(data) self.image_list.append(name) loadImages(image_list, self) else: self.start() def onImagesLoaded(self, images): for i, image in enumerate(self.image_list): self.images[image] = images[i].getElement() self.start() def start(self): if not self.initialized: self.initialized = True _wnd.requestAnimationFrame(run) self.time.timeout(0, self) def stop(self): global run run = lambda ts: None self.run = lambda: None def _get_rect(self): if self._rect_num < self._rect_len: return self._rect_list[self._rect_num] else: self._rect_list.append(Rect(0, 0, 0, 0)) self._rect_len += 1 return self._rect_list[self._rect_num] def run(self): if not self._repaint: self.callback.run() self._repaint = True self.time.timeout(0, self)
def flip(self, surface, xbool=True, ybool=False): """ Return Surface that is flipped horizontally, vertically, or both. """ surf = Surface((surface.get_width(),surface.get_height())) surf.saveContext() if xbool and ybool: surf.translate(surface.get_width(), surface.get_height()) surf.scale(-1, -1) elif xbool: surf.translate(surface.get_width(), 0) surf.scale(-1, 1) elif ybool: surf.translate(0, surface.get_height()) surf.scale(1, -1) surf.drawImage(surface.canvas, 0, 0) surf.restoreContext() return surf
class Canvas(Surface, MouseWheelHandler): def __init__(self, size, buffered): Surface.__init__(self, size) MouseWheelHandler.__init__(self, True) if isinstance(buffered, bool): self._bufferedimage = buffered else: self._bufferedimage = True try: if self.impl.canvasContext: self._isCanvas = True except: self._isCanvas = False self._bufferedimage = False if self._bufferedimage: self.surface = Surface(size) else: self.surface = self self.images = {} self.image_list = [] self.callback = None self.time = Time() self.event = pyjsdl.event self.addMouseListener(self) self.addMouseWheelListener(self) self.addKeyboardListener(self) self.sinkEvents(Event.ONMOUSEDOWN | Event.ONMOUSEUP| Event.ONMOUSEMOVE | Event.ONMOUSEOUT | Event.ONMOUSEWHEEL | Event.ONKEYDOWN | Event.ONKEYPRESS | Event.ONKEYUP) self.modKey = pyjsdl.event.modKey self.specialKey = pyjsdl.event.specialKey self._repaint = False self._rect_list = [] self._rect_len = 0 self._rect_num = 0 self._framerate = 0 self._frametime = 0 self._canvas_init() self.initialized = False def _canvas_init(self): global _canvas, _ctx, _img, _wnd _canvas = self _ctx = self.impl.canvasContext _img = self.surface.canvas _wnd = requestAnimationFrameInit() def onMouseMove(self, sender, x, y): event = DOM.eventGetCurrentEvent() event.pos = (x, y) self.event.mouseMove['x'], self.event.mouseMove['y'] = x, y self.event._updateQueue(event) def onMouseDown(self, sender, x, y): event = DOM.eventGetCurrentEvent() event.pos = (x, y) self.event.mousePress[event.button] = True self.event._updateQueue(event) def onMouseUp(self, sender, x, y): event = DOM.eventGetCurrentEvent() event.pos = (x, y) self.event.mousePress[event.button] = False self.event._updateQueue(event) def onMouseLeave(self, sender): self.event.mousePress[0], self.event.mousePress[1], self.event.mousePress[2] = False, False, False self.event.mouseMove['x'], self.event.mouseMove['y'] = -1, -1 self.event.mouseMoveRel['x'], self.event.mouseMoveRel['y'] = None, None for keycode in self.modKey: if self.event.keyPress[keycode]: self.event.keyPress[keycode] = False def onMouseWheel(self, sender, velocity): event = DOM.eventGetCurrentEvent() if event.type == 'mousewheel': #TODO: update for changes in mousewheel implementation if hasattr(event, 'wheelDeltaX'): self.onMouseWheel = self._onMouseWheel self._onMouseWheel(sender, velocity) else: self.onMouseWheel = self._onMouseWheelY DOM.eventGetMouseWheelVelocityY = eventGetMouseWheelVelocityY self._onMouseWheelY(sender, eventGetMouseWheelVelocityY(event)) else: #DOMMouseScroll self.onMouseWheel = self._onMouseScroll self._onMouseScroll(sender, velocity) def _onMouseWheel(self, sender, velocity): event = DOM.eventGetCurrentEvent() if not event.wheelDeltaX: if velocity < 0: button = 4 events = velocity / -3 else: button = 5 events = velocity / 3 else: if velocity < 0: button = 6 events = velocity / -3 else: button = 7 events = velocity / 3 event.btn = button event.pos = (self.event.mouseMove['x'], self.event.mouseMove['y']) for evt in range(events): self.event._updateQueue(event) def _onMouseWheelY(self, sender, velocity): event = DOM.eventGetCurrentEvent() if velocity < 0: button = 4 events = velocity / -3 else: button = 5 events = velocity / 3 event.btn = button event.pos = (self.event.mouseMove['x'], self.event.mouseMove['y']) for evt in range(events): self.event._updateQueue(event) def _onMouseScroll(self, sender, velocity): event = DOM.eventGetCurrentEvent() if velocity > 1 or velocity < -1: if velocity < 0: button = 4 else: button = 5 else: if velocity < 0: button = 6 else: button = 7 event.btn = button event.pos = (self.event.mouseMove['x'], self.event.mouseMove['y']) self.event._updateQueue(event) def onKeyDown(self, sender, keycode, modifiers): if keycode in self.modKey: event = DOM.eventGetCurrentEvent() self.event.keyPress[keycode] = True self.event._updateQueue(event) DOM.eventPreventDefault(event) elif keycode in self.specialKey: event = DOM.eventGetCurrentEvent() self.event._updateQueue(event) DOM.eventPreventDefault(event) def onKeyPress(self, sender, keycode, modifiers): event = DOM.eventGetCurrentEvent() if not (event.keyCode and event.keyCode in self.specialKey): self.event._updateQueue(event) DOM.eventPreventDefault(event) def onKeyUp(self, sender, keycode, modifiers): event = DOM.eventGetCurrentEvent() if keycode in self.modKey: self.event.keyPress[keycode] = False self.event._updateQueue(event) def resize(self, width, height): Surface.resize(self, width, height) if self._bufferedimage: self.surface.resize(width, height) self.surface._display._surface_rect = self.surface.get_rect() def set_callback(self, cb): if not hasattr(cb, 'run'): self.callback = Callback(cb) else: self.callback = cb def load_images(self, images): if images: image_list = [] for image in images: if isinstance(image, str): image_list.append(image) self.image_list.append(image) else: name = image[0] if isinstance(image[1], str): data = image[1] else: data = base64.b64encode(image[1].getvalue()) if not data.startswith('data:'): ext = name.strip().split('.')[-1] data = "data:%s;base64,%s" %(ext, data) #data:[<mediatype>][;base64],<data> image_list.append(data) self.image_list.append(name) loadImages(image_list, self) else: self.start() def onImagesLoaded(self, images): for i, image in enumerate(self.image_list): self.images[image] = images[i].getElement() self.start() def start(self): if not self.initialized: self.initialized = True _wnd.requestAnimationFrame(run) self.time.timeout(0, self) def stop(self): global run run = lambda ts: None self.run = lambda: None def _get_rect(self): if self._rect_num < self._rect_len: return self._rect_list[self._rect_num] else: self._rect_list.append(Rect(0,0,0,0)) self._rect_len += 1 return self._rect_list[self._rect_num] def run(self): if not self._repaint: self.callback.run() self._repaint = True self.time.timeout(0, self)
class Canvas(Surface): def __init__(self, size, buffered): Surface.__init__(self, size) if isinstance(buffered, bool): self._bufferedimage = buffered else: self._bufferedimage = True try: if self.impl.canvasContext: self._isCanvas = True except: self._isCanvas = False self._bufferedimage = False if self._bufferedimage: self.surface = Surface(size) else: self.surface = self self.images = {} self.image_list = [] self.callback = None self.time = Time() self.event = env.event self.addMouseListener(self) self.addKeyEventListener(self) self.sinkEvents(Event.ONMOUSEDOWN | Event.ONMOUSEUP | Event.ONMOUSEMOVE | Event.ONMOUSEOUT | Event.ONMOUSEWHEEL | Event.ONKEYDOWN | Event.ONKEYPRESS | Event.ONKEYUP) self.onContextMenu = None self.preventContextMenu() self.evt = self.event.eventObj self.modKey = self.event.modKey self.specialKey = self.event.specialKey self.modKeyCode = self.event.modKeyCode self.specialKeyCode = self.event.specialKeyCode self.keyRepeat = self.event.keyRepeat self.keyHeld = self.event.keyHeld self.mouse_entered = True self.event._initiate_touch_listener(self) self._touch_callback = self.event.touchlistener.callback self._rect_list = [] self._rect_len = 0 self._rect_num = 0 self._framerate = 0 self._frametime = 0 self._rendertime = self.time.time() self._pause = False self._canvas_init() self.initialized = False def _canvas_init(self): global _canvas, _ctx, _img, _wnd _canvas = self _ctx = self.impl.canvasContext _img = self.surface.canvas _wnd = requestAnimationFrameInit() def onMouseMove(self, sender, x, y): event = DOM.eventGetCurrentEvent() if event.type in self.event.events: if not self.mouse_entered: self.event.mouseMovePre['x'] = self.event.mouseMove['x'] self.event.mouseMovePre['y'] = self.event.mouseMove['y'] else: self.event.mouseMovePre['x'] = x self.event.mouseMovePre['y'] = y self.mouse_entered = False self.event._updateQueue(self.evt[event.type](event, x, y)) self.event.mouseMove['x'] = x self.event.mouseMove['y'] = y def onMouseDown(self, sender, x, y): event = DOM.eventGetCurrentEvent() if event.type in self.event.events: self.event._updateQueue(self.evt[event.type](event, x, y)) self.event.mousePress[event.button] = True def onMouseUp(self, sender, x, y): event = DOM.eventGetCurrentEvent() if event.type in self.event.events: self.event._updateQueue(self.evt[event.type](event, x, y)) self.event.mousePress[event.button] = False def onMouseEnter(self, sender): self.mouse_entered = True def onMouseLeave(self, sender): self.event.mousePress[0] = False self.event.mousePress[1] = False self.event.mousePress[2] = False self.event.mouseMove['x'] = -1 self.event.mouseMove['y'] = -1 self.event.mouseMoveRel['x'] = None self.event.mouseMoveRel['y'] = None for keycode in self.modKeyCode: if self.event.keyPress[keycode]: self.event.keyPress[keycode] = False def onMouseWheel(self, event): if event.type in self.event.events: r = self.canvas.getBoundingClientRect() x = event.clientX - round(r.left) y = event.clientY - round(r.top) self.event._updateQueue(self.evt[event.type](event, x, y)) DOM.eventPreventDefault(event) def onKeyEvent(self, event): self.removeKeyEventListener(self) self.addKeyboardListener(self) DOM.currentEvent = event if hasattr(event, 'key') and hasattr(event, 'code'): self.onKeyDown(self, event.key, 0) else: self.event._set_key_event() self.onKeyDown = self._onKeyDown self.onKeyUp = self._onKeyUp self.onKeyPress = self._onKeyPress keycode = event.which or event.keyCode or 0 self._onKeyDown(self, keycode, 0) def onKeyDown(self, sender, keycode, mods): event = DOM.eventGetCurrentEvent() if event.key in self.modKey: self.event.keyPress[self.modKey[event.key]] = True if event.type in self.event.events: if not self._isPaused(event.key): self.event._updateQueue(self.evt[event.type](event)) DOM.eventPreventDefault(event) def onKeyUp(self, sender, keycode, mods): event = DOM.eventGetCurrentEvent() if event.key in self.modKey: self.event.keyPress[self.modKey[event.key]] = False if event.key in self.keyHeld: self.keyHeld[event.key]['pressed'] = False if event.type in self.event.events: self.event._updateQueue(self.evt[event.type](event)) def _onKeyDown(self, sender, keycode, mods): event = DOM.eventGetCurrentEvent() if keycode in self.modKeyCode: self.event.keyPress[keycode] = True if event.type in self.event.events: if not self._isPaused(keycode): self.event.keyCode = keycode if keycode in self.specialKeyCode: self.event._updateQueue(self.evt[event.type](event, keycode)) DOM.eventPreventDefault(event) else: DOM.eventPreventDefault(event) def _onKeyUp(self, sender, keycode, mods): event = DOM.eventGetCurrentEvent() if keycode in self.modKeyCode: self.event.keyPress[keycode] = False if keycode in self.keyHeld: self.keyHeld[keycode]['pressed'] = False if event.type in self.event.events: self.event._updateQueue(self.evt[event.type](event, keycode)) def _onKeyPress(self, sender, keycode, mods): event = DOM.eventGetCurrentEvent() if event.type in self.event.events: self.event.keyPressCode[self.event.keyCode] = keycode self.event._updateQueue(self.evt[event.type](event, keycode)) event.preventDefault() def _isPaused(self, keycode): if keycode not in self.keyHeld: self.keyHeld[keycode] = { 'pressed': False, 'delay': False, 'time': 0 } key = self.keyHeld[keycode] if not key['pressed']: key['pressed'] = True paused = False if self.keyRepeat[0]: key['delay'] = True key['time'] = self.time.time() else: paused = True if self.keyRepeat[0]: time = self.time.time() if key['delay']: if time - key['time'] > self.keyRepeat[0]: key['time'] = time key['delay'] = False paused = False elif time - key['time'] > self.keyRepeat[1]: key['time'] = time paused = False return paused def onTouchInitiate(self, event): self.event.touchlistener.activate() for callback in self._touch_callback: if hasattr(callback, 'onTouchInitiate'): callback.onTouchInitiate(event) self.onTouchStart(event) def onTouchStart(self, event): for callback in self._touch_callback: callback.onTouchStart(event) def onTouchEnd(self, event): for callback in self._touch_callback: callback.onTouchEnd(event) def onTouchMove(self, event): for callback in self._touch_callback: callback.onTouchMove(event) def onTouchCancel(self, event): for callback in self._touch_callback: callback.onTouchCancel(event) def preventContextMenu(self, setting=True): """ Control contextmenu event. Optional bool setting to prevent event, default to True. """ if setting: if self.onContextMenu: return element = self.getElement() self.onContextMenu = lambda event: event.preventDefault() element.addEventListener('contextmenu', self.onContextMenu) else: if not self.onContextMenu: return element = self.getElement() element.removeEventListener('contextmenu', self.onContextMenu) self.onContextMenu = None def resize(self, width, height): Surface.resize(self, width, height) if self._bufferedimage: self.surface.resize(width, height) self.surface._display._surface_rect = self.surface.get_rect() def set_callback(self, cb): if not hasattr(cb, 'run'): self.callback = Callback(cb) else: self.callback = cb def load_images(self, images): if images: image_list = [] for image in images: if isinstance(image, str): image_list.append(image) self.image_list.append(image) else: name = image[0] if isinstance(image[1], str): data = image[1] else: data = base64.b64encode(image[1].getvalue()) if not data.startswith('data:'): ext = name.strip().split('.')[-1] data = "data:%s;base64,%s" % (ext, data) #data:[<mediatype>][;base64],<data> image_list.append(data) self.image_list.append(name) loadImages(image_list, self) else: self.start() def onImagesLoaded(self, images): for i, image in enumerate(self.image_list): self.images[image] = images[i].getElement() self.start() def start(self): if not self.initialized: self.initialized = True _wnd.requestAnimationFrame(run) def stop(self): global run run = lambda ts: None self.run = lambda: None def _get_rect(self): if self._rect_num < self._rect_len: return self._rect_list[self._rect_num] else: self._rect_list.append(Rect(0, 0, 0, 0)) self._rect_len += 1 return self._rect_list[self._rect_num] def update(self, timestamp): if not self._framerate: self._frametime = timestamp - self._rendertime self.run() else: self._frametime += timestamp - self._rendertime if self._frametime > self._framerate: self.run() self._frametime = 0 self._rendertime = timestamp def render(self): while self._rect_num: rect = self._rect_list[self._rect_num - 1] x, y, width, height = rect.x, rect.y, rect.width, rect.height _ctx.drawImage(_img, x, y, width, height, x, y, width, height) self._rect_num -= 1 def run(self): self.callback.run()