Example #1
0
    def __init__(self, parent, uid):
        QtGui.QLabel.__init__(self, parent)
        BackendQuadrant.__init__(self, uid)
        
        self.prnt = parent
        
        self.setMouseTracking(True)
        
        self.bg_image = QtGui.QImage(
            pypentago.data['quad_bg.png']
        )
        
        # 0 1 | With 0 aligned properly, 
        # 2 3 | 1 and 3 need to be mirrored horizontally, 2 and 3 verticaly.
        # While horizontally mirror means "| *" -> "* |", meaning that the
        # mirror axis lies vertically.
        self.bg_image = self.bg_image.mirrored(uid == 1 or uid == 3,
                                               uid == 2 or uid == 3)

        # Clockwise rotation image overlay.
        self.rot_cw = SVGFakePixmap(
            pypentago.data['rot_cw.svg']
        )

        # Counter-clockwise rotation image overlay.
        self.rot_ccw = SVGFakePixmap(
            pypentago.data['rot_ccw.svg']
        )
        

        self.img = [
            QtGui.QImage(
                pypentago.data['ball-empty.png']
                ),
            QtGui.QImage(
                pypentago.data['ball-white.png']
                ),
            QtGui.QImage(
                pypentago.data['ball-black.png']
                ),
        ]
        
        self.stone_background = QtGui.QImage(
                pypentago.data['ball-bg.png']
        )
        
        self.overlay = Overlay(self.repaint)

        self.blink_timer = QtCore.QTimer(self)
        self.preview_stone = None
        self.blink_cw = OverlayBlink(self.overlay, self.repaint)
        self.blink_ccw = OverlayBlink(self.overlay, self.repaint)
        self.blink_stone = StoneBlink(self.repaint)
        self.block_user_control = [self.blink_ccw, self.blink_cw,
                                   self.blink_stone]
Example #2
0
class Quadrant(QtGui.QLabel, BackendQuadrant):
    PREVIEW_OPACITY = 0.4
    def __init__(self, parent, uid):
        QtGui.QLabel.__init__(self, parent)
        BackendQuadrant.__init__(self, uid)
        
        self.prnt = parent
        
        self.setMouseTracking(True)
        
        self.bg_image = QtGui.QImage(
            pypentago.data['quad_bg.png']
        )
        
        # 0 1 | With 0 aligned properly, 
        # 2 3 | 1 and 3 need to be mirrored horizontally, 2 and 3 verticaly.
        # While horizontally mirror means "| *" -> "* |", meaning that the
        # mirror axis lies vertically.
        self.bg_image = self.bg_image.mirrored(uid == 1 or uid == 3,
                                               uid == 2 or uid == 3)

        # Clockwise rotation image overlay.
        self.rot_cw = SVGFakePixmap(
            pypentago.data['rot_cw.svg']
        )

        # Counter-clockwise rotation image overlay.
        self.rot_ccw = SVGFakePixmap(
            pypentago.data['rot_ccw.svg']
        )
        

        self.img = [
            QtGui.QImage(
                pypentago.data['ball-empty.png']
                ),
            QtGui.QImage(
                pypentago.data['ball-white.png']
                ),
            QtGui.QImage(
                pypentago.data['ball-black.png']
                ),
        ]
        
        self.stone_background = QtGui.QImage(
                pypentago.data['ball-bg.png']
        )
        
        self.overlay = Overlay(self.repaint)

        self.blink_timer = QtCore.QTimer(self)
        self.preview_stone = None
        self.blink_cw = OverlayBlink(self.overlay, self.repaint)
        self.blink_ccw = OverlayBlink(self.overlay, self.repaint)
        self.blink_stone = StoneBlink(self.repaint)
        self.block_user_control = [self.blink_ccw, self.blink_cw,
                                   self.blink_stone]
    
    def paintEvent(self, event):
        # We might want to change that for performance reasons later on.
        # Either FastTransformation or SmoothTransformation.
        s_mode = QtCore.Qt.SmoothTransformation                
        
        h = self.height()
        w = self.width()
        min_size = min([h, w])
        
        paint = QtGui.QPainter()
        paint.begin(self)
        
        # Resize the background image.
        bg = self.bg_image.scaledToHeight(min_size, s_mode)
        
        paint.drawImage(0, 0, bg)
        
        s_size = min_size - min_size / 6.0
        
        # The space a stone has got is a third of the total space
        # available.
        size = s_size / 3.0
        # The size of one stone is a fourth of either the height or the
        # width of the quadrant, depending which of them is smaller.
        w_size = size / 1.25
        # What we need to add to compensate for the difference of the img
        # and the total size.
        d_size = (size - w_size) / 2.0 + (min_size - s_size) / 2.0
        # Scale all of the images to one fourth of the space we've got.
        # We're assuming to work with squared images!
        imgs = [img.scaledToHeight(w_size, s_mode) for img in self.img]
        
        if self.blink_stone:
            b_col, b_row = self.blink_stone.coord
        else:
            b_col, b_row = None, None
        
        for y_c, row in enumerate(self.field):
            y_p = y_c * size
            for x_c, col in enumerate(row):
                x_p = x_c * size
                if x_c == b_col and y_c == b_row:
                    paint.setOpacity(self.blink_stone.value)
                stone_value = self.field[y_c][x_c]
                paint.drawImage(x_p+d_size, y_p+d_size, self.stone_background)
                paint.drawImage(x_p+d_size, y_p+d_size, imgs[stone_value])
                if x_c == b_col and y_c == b_row:
                    paint.setOpacity(1)
        
        if self.preview_stone is not None:
            x_c, y_c = self.preview_stone
            if 0 <= x_c <= 2 and 0 <= y_c <= 2 and not self.field[y_c][x_c]:
                uid = self.prnt.prnt.local_player.uid
                x_p, y_p = x_c * size, y_c * size
                paint.setOpacity(self.PREVIEW_OPACITY)
                paint.drawImage(x_p+d_size, y_p+d_size, imgs[uid])
                paint.setOpacity(1)
        
        if self.overlay:
            # Display rotation overlay.
            rot_cw = self.rot_cw.scaledToWidth(w / 2.0, s_mode)
            rot_ccw = self.rot_ccw.scaledToWidth(w / 2.0, s_mode)
            cw_y = h / 2.0 - rot_cw.height() / 2.0
            ccw_y = h / 2.0 - rot_ccw.height() / 2.0
            
            cw_o, ccw_o = self.overlay.opacity
            
            paint.setOpacity(cw_o + self.blink_cw.value)
            paint.drawPixmap(0, cw_y, rot_cw)
            if ccw_o != cw_o or self.blink_ccw or self.blink_cw:
                paint.setOpacity(ccw_o + self.blink_ccw.value)
            paint.drawPixmap(w / 2.0, ccw_y, rot_ccw)
            paint.setOpacity(1)
        
        # This was a triumph!
        paint.end()

    def rotate(self, clockwise, user_done=True):
        BackendQuadrant.rotate(self, clockwise)
        
        self.prnt.may_rot = False
        self.overlay.hide()
        self.repaint()
        if user_done:
            self.prnt.do_turn(clockwise and "CW" or "CCW", self.uid)
            
    def show_rot(self, clockwise, callafter=None):
        if clockwise:
            self.blink_cw.run(5000, callafter)
        else:
            self.blink_ccw.run(5000, callafter)
    
    def show_loc(self, col, row, callafter=None):
        self.blink_stone.coord = (col, row)
        self.blink_stone.run(5000, callafter)
    
    def mousePressEvent(self, event):
        if not self.prnt.user_control:
            self.prnt.reclaim_control()
            return
        if self.prnt.may_rot and not self.overlay:
            # This shouldn't actually be happening. Just in case it is.
            warnings.warn('may_rot == True and mousePressEvent but no overlay')
            return
        
        x, y = event.x(), event.y()
        w = self.width()
        h = self.height()
        
        if self.overlay:
            if x < w / 2.0:
                # Clockwise
                self.rotate(True)
            else:
                # Counter-clockwise
                self.rotate(False)
            self.repaint()
            # Update outdated position of preview stone.
            self.mouseMoveEvent(event)
        else:
            # No overlay. Player wants to set a stone.
            size = min([h, w]) / 3.0
            x, y = get_coord(size, x), get_coord(size, y)
            self.set_stone(y, x)
        
    def enterEvent(self, event):
        if self.prnt.may_rot:
            self.overlay.show()
        self.repaint()
    
    def leaveEvent(self, event):
        if not (self.blink_ccw or self.blink_cw):
            self.overlay.hide()
        self.preview_stone = None
        self.repaint()
    
    def mouseMoveEvent(self, event):
        if not self.prnt.user_control:
            return
        
        if not self.overlay:
            x, y = event.x(), event.y()
            size = min([self.height(), self.width()]) / 3.0
            x, y = get_coord(size, x), get_coord(size, y)
            if x > 3 or x < 0 or y > 3 or y < 0:
                warnings.warn("Attempting out-of-range preview stone at "
                              "row %r and col %r" % (y, x))
                self.preview_stone = None
            else:
                self.preview_stone = x, y
            self.repaint()
            return
        else:
            x = event.x()
            if x < self.width() / 2.0:
                self.overlay.highlight_cw()
            else:
                self.overlay.highlight_ccw()
            self.repaint()
    
    def set_stone(self, row, col, player_id=None, may_rot=True):
        if player_id is None:
            player_id = self.prnt.prnt.local_player.uid
        if self.field[row][col]:
            return
        self.field[row][col] = player_id
        self.prnt.may_rot = may_rot
        self.prnt.temp_turn = [self.uid, row, col]
        if may_rot:
            self.overlay.show()
        self.repaint()
    
    @property
    def user_control(self):
        return not any(self.block_user_control)
    
    def reclaim_control(self):
        for elem in self.block_user_control:
            if elem:
                elem.stop()