Ejemplo n.º 1
0
class Timer(object):
    """
    Simple profiling timer.
    Output log can be directed to 'console' or to 'textarea'.
    If output is to textarea, may specify log length.
    """

    def __init__(self, log='console', log_length=5):
        self.time = Time()
        self.time_i = self.get_time()
        self.dtime = []
        self.number = 0
        self.log = None
        self.log_list = None
        self.log_num = 0
        self.log_scroll = True
        self.set_log(log, log_length)

    def get_time(self):
        """
        Get current time.
        """
        return self.time.time()

    def set_time(self):
        """
        Set current time.
        """
        self.time_i = self.get_time()

    def lap_time(self, time_i=None, time_f=None, number=100, print_result=True):
        """
        Time lapsed since previous set_time.
        Optional arguments time_i and time_f, number of calls to average, and print_results to output result.
        """
        if time_i is None:
            time_i = self.time_i
        if time_f is None:
            time_f = self.get_time()
        self.dtime.append(time_f-time_i)
        self.number += 1
        if self.number >= number:
            t_ave = ( sum(self.dtime)/number )
            self.dtime = []
            self.number = 0
            if print_result:
                if self.log_type == 'console':
                    self.log_num += 1
                    entry = "Time %d: %s" % (self.log_num, t_ave)
                    print(entry)
                else:
                    self.log_num += 1
                    entry = "Time %d: %s" % (self.log_num, t_ave)
                    self.print_log(entry)
            return t_ave

    def set_log(self, log, log_length=5):
        """
        Set log output.
        Argument log can be 'console' or 'textarea'.
        """
        if log in ('console','textarea'):
            self.log_type = log
            if log == 'textarea':
                if not self.log:
                    size = env.canvas.surface.width-5, 102
                    self.log = env.canvas.surface._display.Textarea(size)
                    self.log.setReadonly(True)
                    self.log.addMouseListener(self)
                    self.onMouseUp = lambda sender,x,y: None
                    self.onMouseMove = lambda sender,x,y: None
                    self.onMouseEnter = lambda sender: None
                    self.log_list = ['' for i in range(log_length)]
                self.log.toggle(True)
            else:
                if self.log:
                    self.log.toggle(False)
                    self.log_list = []

    def onMouseDown(self, sender, x, y):
        self.log_scroll = False

    def onMouseLeave(self, sender):
        self.log_scroll = True

    def print_log(self, text):
        """
        Print text to output.
        """
        if self.log_type == 'console':
            print(text)
        else:
            self.log_list.pop(0)
            self.log_list.append(text+'\n')
            text = ''.join(self.log_list)
            self.log.setText(text)
            if self.log_scroll:
                self.log.setCursorPos(len(text))
Ejemplo n.º 2
0
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()