Пример #1
0
class BillboardDisplay(InstructionGroup):
    def __init__(self, pos, texture, size_x=1.0, size_y=1.0, intensity=1.0, Tr=1.0):
        super(BillboardDisplay, self).__init__()
        
        self.intensity = intensity
        self.Tr = Tr

        self.translate = Translate()
        self.rotate_azi = Rotate(origin=(0,0,0), axis=(0,1,0))
        self.rotate_ele = Rotate(origin=(0,0,0), axis=(1,0,0))
        self.scale = Scale()
        self.color_instruction = InstructionGroup()
        self.mesh = Mesh(
            texture=texture,
            vertices=rectangle_nurb.vertices,
            indices=rectangle_nurb.indices,
            fmt=rectangle_nurb.vertex_format,
            mode='triangles'
        )

        self.add(PushMatrix())
        self.add(self.translate)
        self.add(self.rotate_azi)
        self.add(self.rotate_ele)
        self.add(self.scale)
        self.add(self.color_instruction)
        self.add(self.mesh)
        self.add(PopMatrix())

        self.set_color(intensity=intensity, Tr=Tr)
        self.set_size(size_x, size_y)
        self.set_pos(pos)
        self.set_texture(texture)

    def set_texture(self, texture):
        self.texture = texture
        self.mesh.texture = texture

    def set_rotate(self, angles):
        self.rotate_azi.angle = angles[0] * 180/np.pi
        self.rotate_ele.angle = angles[1] * 180/np.pi

    def set_size(self, size_x, size_y):
        self.scale.xyz = (size_x, size_y, 1)

    def set_pos(self, pos):
        self.translate.xyz = pos

    def set_color(self, intensity=1.0, Tr=1.0):
        self.color_instruction.clear()
        self.color_instruction.add(
            ChangeState(
                Kd=(0.6, 0.6, 0.6),
                Ka=(0.8, 0.8, 0.8),
                Ks=(0.9, 0.9, 0.9),
                Tr=Tr,
                Ns=1.0,
                intensity=intensity
            )
        )
Пример #2
0
 def group(self, color):
     rgb = InstructionGroup()
     color = Color(1, 1, 0)
     xyz = color
     rgb.add(xyz)
     rgb.add(Rectangle(pos=self.pos, size=self.size) )
     return rgb
Пример #3
0
 def group(self, color):
     rgb = InstructionGroup()
     color = Color(1, 0, 0)
     xyz = color
     rgb.add(xyz)
     radius = sqrt(sqrt(sum([x*x for x in self.size])))
     rgb.add(Line(circle=(self.pos[0], self.pos[1], radius ) ) )
     return rgb
Пример #4
0
class NurbDisplay(InstructionGroup):
    def __init__(self, nurb, pos, size=1.0, color=(0.0,1.0,0.0), tr=1.0, intensity=1.0):
        super(NurbDisplay, self).__init__()
        
        self.color = color
        self.tr = tr
        self.intensity = intensity

        self.translate = Translate()
        self.scale = Scale()
        self.color_instruction = InstructionGroup()

        self.add(PushMatrix())
        self.add(self.translate)
        self.add(self.scale)
        self.add(self.color_instruction)
        self.add(self.make_mesh(nurb))
        self.add(PopMatrix())

        self.set_color()
        self.set_size(size)
        self.set_pos(pos)

    def make_mesh(self, m):
        return Mesh(
            vertices=m.vertices,
            indices=m.indices,
            fmt=m.vertex_format,
            mode='triangles'
        )

    def set_size(self, size):
        self.scale.xyz = (size, size, size)

    def set_pos(self, pos):
        self.translate.xyz = pos

    def set_color(self, color=None, tr=None, intensity=None):
        if tr is not None:
            self.tr = tr
        if intensity is not None:
            self.intensity = intensity
        if color is not None:
            self.color = color

        self.color_instruction.clear()
        self.color_instruction.add(
            ChangeState(
                Kd=self.color,
                Ka=self.color,
                Ks=(0.3, 0.3, 0.3),
                Tr=self.tr,
                Ns=1.0,
                intensity=self.intensity
            )
        )
Пример #5
0
    def __get_dbg_aabb_gfx(self):
        if self.__dbg_aabb is None:
            c = Color(0.8, 0.8, 0.8, 0.3)
            r = Rectangle()
            group = InstructionGroup()
            for instruction in (c, r):
                group.add(instruction)

            def update_r(_, ((left, bottom), (right, top))):
                r.pos = (left, bottom)
                r.size = (right - left, top - bottom)

            self.bind(aabb=update_r)
            update_r(None, self.aabb)
            self.__dbg_aabb = group
Пример #6
0
    def __get_dbg_viewport_gfx(self):
        if self.__dbg_viewport is None:
            c = Color(1, 1, 1, 0.5)
            r = Rectangle()
            group = InstructionGroup()
            for instruction in (c, r):
                group.add(instruction)

            def update_r(_, __):
                r.pos = self.viewport_pos
                r.size = self.viewport_size

            self.bind(viewport_pos=update_r, viewport_size=update_r)
            update_r(None, None)
            self.__dbg_viewport = group
        return self.__dbg_viewport
Пример #7
0
    def __init__(self, pos, texture, size_x=1.0, size_y=1.0, intensity=1.0, Tr=1.0):
        super(BillboardDisplay, self).__init__()
        
        self.intensity = intensity
        self.Tr = Tr

        self.translate = Translate()
        self.rotate_azi = Rotate(origin=(0,0,0), axis=(0,1,0))
        self.rotate_ele = Rotate(origin=(0,0,0), axis=(1,0,0))
        self.scale = Scale()
        self.color_instruction = InstructionGroup()
        self.mesh = Mesh(
            texture=texture,
            vertices=rectangle_nurb.vertices,
            indices=rectangle_nurb.indices,
            fmt=rectangle_nurb.vertex_format,
            mode='triangles'
        )

        self.add(PushMatrix())
        self.add(self.translate)
        self.add(self.rotate_azi)
        self.add(self.rotate_ele)
        self.add(self.scale)
        self.add(self.color_instruction)
        self.add(self.mesh)
        self.add(PopMatrix())

        self.set_color(intensity=intensity, Tr=Tr)
        self.set_size(size_x, size_y)
        self.set_pos(pos)
        self.set_texture(texture)
Пример #8
0
    def __init__(self, **kwargs):
        super(CanvasWidget, self).__init__(**kwargs)
        self.size = (512, 512)
        self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
        self._keyboard.bind(on_key_down=self._on_keyboard_down)


        self.img = Image.open('test.png')
        self.img = self.img =  self.img.transpose(Image.FLIP_TOP_BOTTOM)
        self.texture = Texture.create(size=(512,512))
        self.texture.mag_filter = 'nearest'
        size = 512*512*3
        buf = []
        for r,g,b,a in self.img.getdata():
            buf.extend([r,g,b,a])
        #buf = [int(x*255/size) for x in range(size)]
        #buf = self._flatten_list(self.pixels)
        self.arr = array('B', buf)
        self.texture.blit_buffer(self.arr, colorfmt='rgba', bufferfmt='ubyte')

        with self.canvas:
            self.test = InstructionGroup()
            #self.test.add(Color(1, 1, 0, mode='rgb'))
            self.test.add(Rectangle(texture=self.texture, pos=self.pos, size=self.size, group='heh'))

        #self.bind(texture=self.on_texture_update)
        self.bind(pos=self.on_texture_update)
        self.bind(size=self.on_texture_update)
Пример #9
0
    def do_layout(self, *args):
        super(Piece, self).do_layout(*args)

        if hasattr(self, 'outline'):
            self.canvas.before.remove(self.outline)

        self.outline = InstructionGroup()
        for child in self.children:
            self.outline.add(Color(.5, .8, 1, .8))
            self.outline.add(Line(
                points=[
                    child.x - 1, child.y - 1,
                    child.right + 1, child.y - 1,
                    child.right + 1, child.top + 1,
                    child.x - 1, child.top + 1
                ],
                close=True,
                width=1.5
            ))

        if self.canvas.before:
            self.canvas.before.add(self.outline)

            if len(self.children) == 0:
                if hasattr(self, 'outline'):
                    self.canvas.before.remove(self.outline)
Пример #10
0
 def food(self,*args):
     self.foodblue = InstructionGroup()
     self.foodblue.add(Color(1, 0, 0, 1))
     x = random.randint(int(self.rangeSnake[0]), int(self.rangeSnake[2]-10))
     y = random.randint(int(self.rangeSnake[1]), int(self.rangeSnake[3]-10))
     self.food = Rectangle(pos=(x,y), size=(10,10))
     self.foodblue.add(self.food)
Пример #11
0
 def __init__(self, **kwargs):
     """Make triggers and bind."""
     kwargs['size_hint'] = (None, None)
     self.translate = Translate(0, 0)
     self.group = InstructionGroup()
     super().__init__(**kwargs)
     self.bind(offxs=self.on_pos, offys=self.on_pos)
Пример #12
0
    def update(self, *args):
        if hasattr(self, 'outline'):
            self.canvas.before.remove(self.outline)

        self.outline = InstructionGroup()
        if self.highlight:
            for child in self.children[:]:
                self.outline.add(Color(1, .2, .2, .8))
                self.outline.add(Line(
                points=[
                    child.x - 1, child.y - 1,
                    child.right + 1, child.y - 1,
                    child.right + 1, child.top + 1,
                    child.x - 1, child.top + 1
                ],
                close=True,
                width=1.5
            ))

            if self.canvas.before:
                self.canvas.before.add(self.outline)

            self.highlight = False
        else:
            self.canvas.before.remove(self.outline)

            self.highlight = True
Пример #13
0
class ErrorPiece(Piece):
    def __init__(self, **kwargs):
        super(ErrorPiece, self).__init__(**kwargs)

        self.highlight = False

    def on_parent(self, *args):
        if self.parent:
            Clock.schedule_interval(self.update, .5)

    def on_keypress(self, keyboard, keycode, text, modifiers):
        return True

    def do_layout(self, *args):
        super(ErrorPiece, self).do_layout(*args)
        self.update()

    def update(self, *args):
        if hasattr(self, 'outline'):
            self.canvas.before.remove(self.outline)

        self.outline = InstructionGroup()
        if self.highlight:
            for child in self.children[:]:
                self.outline.add(Color(1, .2, .2, .8))
                self.outline.add(Line(
                points=[
                    child.x - 1, child.y - 1,
                    child.right + 1, child.y - 1,
                    child.right + 1, child.top + 1,
                    child.x - 1, child.top + 1
                ],
                close=True,
                width=1.5
            ))

            if self.canvas.before:
                self.canvas.before.add(self.outline)

            self.highlight = False
        else:
            self.canvas.before.remove(self.outline)

            self.highlight = True
Пример #14
0
    def __init__(self, **kwargs):
        super(ResizableCursor, self).__init__(**kwargs)
        self.size_hint = (None, None)
        self.pos_hint = (None, None)
        self.source = ''
        self.rect = Rectangle(pos=(-9998,-9998), size=(1, 1))
        self.size = (dp(22), dp(22))
        self.pos = [-9998, -9998]

        # Makes an instruction group with a rectangle and
        # loads an image inside it
        # Binds its properties to mouse positional changes and events triggered
        instr = InstructionGroup()
        instr.add(self.rect)
        self.canvas.after.add(instr)
        self.bind(pos=lambda obj, val: setattr(self.rect, 'pos', val))
        self.bind(source=lambda obj, val: setattr(self.rect, 'source', val))
        self.bind(hidden=lambda obj, val: self.on_mouse_move(Window.mouse_pos))
        Window.bind(mouse_pos=lambda obj, val: self.on_mouse_move(val))
Пример #15
0
    def __get_dbg_origin_gfx(self):
        if self.__dbg_origin is None:
            c1 = Color(1, 0, 0, 0.5)
            r1 = Rectangle()
            c2 = Color(0, 1, 0, 0.5)
            r2 = Rectangle()
            c3 = Color(0, 0, 1, 0.5)
            e = Ellipse()
            group = InstructionGroup()
            for instruction in (c1, r1, c2, r2, c3, e):
                group.add(instruction)

            def update_geom(_, (w, h)):
                r1.size = (w, 0.1 * h)
                r2.size = (0.1 * w, h)
                e.size = (0.5 * w, 0.5 * h)
                e.pos = (0.25 * w, 0.25 * h)

            self.bind(viewport_size=update_geom)
            update_geom(None, self.size)
            self.__dbg_origin = group
Пример #16
0
    def __init__(self, points, **kwargs):
        # calculate some basic information about the data
        self.points = points
        self.points_x = zip(*points)[0]
        self.points_y = zip(*points)[1]

        # if we could figure out how to draw an arbitrary number of ticks in kv, this would be cleaner
        self.ticks = InstructionGroup()
        self.tick_translate = Translate()
        

        super(LinePlot, self).__init__(**kwargs)
        self.canvas.insert(0, self.ticks)
        self.viewport = (min(self.points_x), min(self.points_y), max(self.points_x), max(self.points_y))
Пример #17
0
    def __init__(self, nurb, pos, size=1.0, color=(0.0,1.0,0.0), tr=1.0, intensity=1.0):
        super(NurbDisplay, self).__init__()
        
        self.color = color
        self.tr = tr
        self.intensity = intensity

        self.translate = Translate()
        self.scale = Scale()
        self.color_instruction = InstructionGroup()

        self.add(PushMatrix())
        self.add(self.translate)
        self.add(self.scale)
        self.add(self.color_instruction)
        self.add(self.make_mesh(nurb))
        self.add(PopMatrix())

        self.set_color()
        self.set_size(size)
        self.set_pos(pos)
    def __init__(self, iface, amount, tag, func, serv_addr, bufsize=1024):
        """
            iface: interface to sniff on
            amount: max amount of latest rssis to maintain
            tag: value for tag field, used as sign
            func: function to process rssi list, should takes list of rssis in 
                  and output another list of single output value
            serv_addr: server addr, format as (HOST, PORT)
            bufsize: max size of receive buf, should be big enough
        """
        super(sniffWidget, self).__init__()
        self.iface = iface
        self.amount = amount
        self.tag = tag
        self.rssi_dict = {}
        self.rssi_dict["tag"] = tag
        self.prcs_dict = {}
        self.prcs_dict["tag"] = self.tag

        self.func = func

        # server addr
        self.serv_addr = serv_addr
        self.bufsize = bufsize

        # client socket
        # use ipv4 udp
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        #self.sock.settimeout(3.0)

        # initial communication with server
        self.config()

        # visualize aps
        #self.visual_aps()

        # initial coords
        self.coords = (0, 0)

        # used to record all instructions that draw user-dots
        self.obj = InstructionGroup()
        self.objects = []

        # used to indicate whether update should be down actually
        self.update_flag = 0

        # children widget, 2 buttons
        # define event behavior for those two
        def _on_press1(instance):
            # change the text and flag
            if instance.flag == -1:
                instance.flag = 1
                instance.text = "Pause"
                instance.parent.set_flag()
            elif instance.flag == 0:
                instance.flag = 1
                instance.text = "Pause"
                instance.parent.set_flag()
            elif instance.flag == 1:
                instance.flag = 0
                instance.text = "Resume"
                instance.parent.unset_flag()

        def _on_press2(instance):
            # clear the canvas and re-initial btn1
            instance.parent.clear()
            instance.parent.btn1.reinit()
            instance.parent.unset_flag()

        self.btn1.bind(on_press=_on_press1)
        self.btn2.bind(on_press=_on_press2)
Пример #19
0
    def charting(self, *args):
        """
        繪圖
        """
        self.canvas.clear()

        if self.dataList == None or len(self.dataList) == 0:
            self.drawNoDataGraph()
            return

        self.calcMaxTick()
        self.drawCordFrame()
        
        self.profitPerNumDict.clear()
        self.maxNum = 5
        tmpProfitPer = None
        aNum = None
        for profitPer in self.dataList:
            if profitPer < 0:
                tmpProfitPer = math.floor(profitPer)
                if tmpProfitPer < self.min_tickNum:
                    tmpProfitPer = self.min_tickNum
            else:
                tmpProfitPer = math.ceil(profitPer)
                if tmpProfitPer > self.max_tickNum:
                    tmpProfitPer = self.max_tickNum
                
            tmpProfitPer = int(tmpProfitPer)
            aNum = self.profitPerNumDict.get(str(tmpProfitPer))
            if aNum == None:
                aNum = 0
            aNum += 1
            self.profitPerNumDict[str(tmpProfitPer)] = aNum
            if aNum > self.maxNum:
                self.maxNum = aNum

        self.yscale = (self.height - self.shift_bottom - self.shift_top) / self.maxNum
        
        self.drawCordInfo()
        
        index = None
        shift_xpos = None
        center_pos = int(self.pillarPoint / 2)
        for i in range(self.min_tickNum, self.max_tickNum + 1):
            if i == 0:
                shift_xpos = self.ycordWidth
            elif i > 0:
                shift_xpos = self.ycordWidth * 2
            else:
                shift_xpos = 0
            index = i - self.min_tickNum
            aNum = self.profitPerNumDict.get(str(i))
            if aNum != None:
                lineColor = Color()
                lineColor.rgba = self.GRID_COLOR                
                
                instg = InstructionGroup(group="data")
                instg.add(lineColor)
                
                x1 = int(self.pos[0] + self.shift_left + index * self.pillarSumPoint + shift_xpos)
                y1 = int(self.pos[1] + self.shift_bottom)
                x2 = int(self.pos[0] + self.shift_left + index * self.pillarSumPoint + shift_xpos)
                y2 = int(self.pos[1] + self.shift_bottom + aNum * self.yscale)
                instg.add(Line(points=(x1, y1, x2, y2), width=1))
                self.canvas.add(instg)
                
                instg = InstructionGroup(group="data")
                instg.add(lineColor)
                
                x1 = int(self.pos[0] + self.shift_left + index * self.pillarSumPoint + shift_xpos)
                y1 = int(self.pos[1] + self.shift_bottom + aNum * self.yscale)
                x2 = int(self.pos[0] + self.shift_left + index * self.pillarSumPoint + self.pillarPoint - 1 + shift_xpos)
                y2 = int(self.pos[1] + self.shift_bottom + aNum * self.yscale)
                instg.add(Line(points=(x1, y1, x2, y2), width=1))
                self.canvas.add(instg)
                
                instg = InstructionGroup(group="data")
                instg.add(lineColor)
                
                x1 = int(self.pos[0] + self.shift_left + index * self.pillarSumPoint + self.pillarPoint - 1 + shift_xpos)
                y1 = int(self.pos[1] + self.shift_bottom)
                x2 = int(self.pos[0] + self.shift_left + index * self.pillarSumPoint + self.pillarPoint - 1 + shift_xpos)
                y2 = int(self.pos[1] + self.shift_bottom + aNum * self.yscale)
                instg.add(Line(points=(x1, y1, x2, y2), width=1))
                self.canvas.add(instg)

            x1 = int(self.pos[0] + self.shift_left + index * self.pillarSumPoint + shift_xpos + center_pos)
            self.xcordDict[str(i)] = x1
Пример #20
0
 def move(self,*dt):
     self.canvas.clear()
     self.canvas.add(self.foodblue)
     x,y = self.snake[-1]
     if abs(self.snake[-1][0] -self.food.pos[0])<10 and abs(self.snake[-1][1] -self.food.pos[1])<10:#吃到食物
         x,y = self.snake[-1]
         if self.keyboard.direction == "left":
             for i in range(1,11):
                 x1,y1 = x-i,y
                 self.snake.append((x1,y1))
         elif self.keyboard.direction == "right":
              for i in range(1,11):
                 x1,y1 = x+i,y
                 self.snake.append((x1,y1))
         elif self.keyboard.direction == "up":
             for i in range(1,11):
                 x1,y1 = x,y+i
                 self.snake.append((x1,y1))
         elif self.keyboard.direction == "down":
             for i in range(1,11):
                 x1,y1 = x,y-i
                 self.snake.append((x1,y1))
         self.foods()
     else:
         if self.keyboard.direction == "left":
             x,y = x-1,y
             if x < self.rangeSnake[0] :
                 self.gameover()
             for a,b in self.snake:
                 if x >a and x-a<10 and abs(b-y)<10:
                     self.gameover()
                     break
         elif self.keyboard.direction == "right":
             x,y = x+1,y
             if x+10 > self.rangeSnake[2]:
                 self.gameover()
             for a,b in self.snake:
                 if a>x and a-x < 10 and abs(b-y)< 10:
                     self.gameover()
                     break
         elif self.keyboard.direction == "up":
             x,y = x,y+1
             if y+10 >self.rangeSnake[3]:
                 self.gameover()
             for a,b in self.snake:
                 if b>y and b-y < 10 and abs(x-a)<10:
                     self.gameover()
                     break
         elif self.keyboard.direction == "down":
             x,y = x,y-1
             if y < self.rangeSnake[1]:
                 self.gameover()
             for a,b in self.snake:
                 if y >b and y-b>10 and abs(x-a)<10:
                     self.gameover()
                     break
         self.snake.append((x,y))
         del self.snake[0]
     for i in self.snake:
         snake = InstructionGroup()
         snake.add(Color(0, 0, 1, 1))
         snake.add(Rectangle(pos=i, size=(10,10)))
         self.canvas.add(snake)
Пример #21
0
    def drawCrossLine(self, aIndex):
        """
        """
        dataNum = len(self.dataDict)
        if dataNum == 0:
            return
        if aIndex >= self.dispMax:
            index = self.dispMax - 1
        elif aIndex >= self.dispNum:
            index = self.dispNum - 1
        elif aIndex < 0:
            index = 0
        else:
            index = aIndex
        self.crossLineIndex = index
        if self.infoFunc == None:
            self._showInfo(index)
        else:
            aKey = self.keyList[self.scopeIdx[0] + index]
            aDict = self.dataDict.get(aKey)
            refDict = {}
            for aKey in aDict.keys():
                refDict[aKey] = aDict.get(aKey)
            preIndex = self.scopeIdx[0] + index - 1
            if preIndex < 0:
                refDict["UD"] = 0
            else:
                aKey = self.keyList[preIndex]
                preDict = self.dataDict.get(aKey)
                refDict["UD"] = aDict.get("CP") - preDict.get("CP")
            self.infoFunc(refDict)

        if self.isDrawCrossLine == False:
            return
        groupStr = self.instGroup + "cross_line"
        self.canvas.remove_group(groupStr)

        color = Color()
        color.rgba = self.CROSS_LINE_COLOR

        instg = InstructionGroup(group=groupStr)
        instg.add(color)
        x1 = self.chartPos[0] + (index + 1) * (self.tickWide +
                                               self.tickGap) - self.backGap
        y1 = self.chartPos[1]
        x2 = x1
        y2 = self.chartPos[1] + self.chartSize[1]
        instg.add(Line(points=(x1, y1, x2, y2), width=1))
        self.canvas.add(instg)

        aKey = self.keyList[self.scopeIdx[0] + index]
        aDict = self.dataDict.get(aKey)

        instg = InstructionGroup(group=groupStr)
        instg.add(color)
        x1 = self.chartPos[0]
        y1 = self.chartPos[1] + (aDict.get("CP") -
                                 self.lowestValue) * self.yscale
        x2 = self.chartPos[0] + self.chartSize[0]
        y2 = y1
        instg.add(Line(points=(x1, y1, x2, y2), width=1))
        self.canvas.add(instg)
Пример #22
0
class DialGauge(Widget):
    dial_diameter = NumericProperty(180)
    dial_size = ReferenceListProperty(dial_diameter, dial_diameter)
    scale_max = NumericProperty(100.0)
    scale_min = NumericProperty(0.0)
    scale_increment = NumericProperty(10.0)
    angle_start = NumericProperty(0.0)
    angle_stop = NumericProperty(360.0)
    angle_offset = NumericProperty(0.0)
    tic_frequency = NumericProperty(2.0)
    tic_length = NumericProperty(8)
    tic_width = NumericProperty(2)
    tic_radius = NumericProperty(100)
    tic_color = ListProperty([0, 0, 1])
    dial_color = ListProperty([1, 1, 1])
    needle_color = ListProperty([1, 0, 0])
    hub_color = ListProperty([1, 0, 0])
    needle_length = NumericProperty(100)
    needle_width = NumericProperty(4)
    hub_radius = NumericProperty(20)
    semi_circle = BooleanProperty(False)
    value = NumericProperty(0.0)
    value_offset_pos = ListProperty([0, 0])
    show_value = BooleanProperty(True)
    value_color = ListProperty([0, 0, 1, 1])
    value_font_size = NumericProperty(20)
    scale_font_size = NumericProperty(10)
    annulars = ListProperty()
    annular_thickness = NumericProperty(8)

    setpoint_thickness = NumericProperty(2)
    setpoint_length = NumericProperty(None)
    setpoint_value = NumericProperty(float('nan'))
    setpoint_color = ListProperty([0, 0, 0, 1])

    def __init__(self, **kwargs):
        super(DialGauge, self).__init__(**kwargs)
        self.annular_canvas = None
        self.setpoint_canvas = None

        self.draw_annulars()
        self.draw_ticks()
        self.draw_setpoint()

        self.bind(pos=self._redraw, size=self._redraw)
        self.bind(setpoint_value=self.draw_setpoint)

    def get_dial_center(self):
        x = self.pos[0] + self.dial_diameter / 2.
        y = self.pos[1] + self.dial_diameter / 2.
        if self.semi_circle:
            y += (-self.dial_diameter / 2 + self.hub_radius)

        return [x, y]

    def set_dial_center(self):
        pass

    dial_center = AliasProperty(get_dial_center,
                                set_dial_center,
                                bind=['size', 'pos'])

    def value_to_angle(self, v):
        ''' convert the given value to the angle required for the scale '''
        return -180.0 + self.angle_start + self.angle_offset + (
            (self.angle_stop - self.angle_start) *
            ((float(v) - self.scale_min) / (self.scale_max - self.scale_min)))

    def _redraw(self, instance, value):
        if self.annular_canvas:
            self.canvas.before.remove(self.annular_canvas)
        self.draw_annulars()
        self.canvas.remove(self.ticks)
        self.draw_ticks()
        self.draw_setpoint()

    def draw_annulars(self):
        # draw annulars that are in the annulars list:
        # requires properties annular_thickness, and a list of dicts {color: , start: , stop: }, ...,
        # where start and stop are the values of the scale to start and stop the annular

        if len(self.annulars) == 0:
            return

        awidth = self.annular_thickness
        self.annular_canvas = InstructionGroup()

        if self.semi_circle:
            self.annular_canvas.add(PushMatrix())
            self.annular_canvas.add(
                Translate(0, -self.dial_diameter / 2 + self.hub_radius))

        for a in self.annulars:
            self.annular_canvas.add(Color(*a.get('color', [0, 1, 0, 1])))
            st = self.value_to_angle(a.get('start', self.scale_min))
            en = self.value_to_angle(a.get('stop', self.scale_max))
            self.annular_canvas.add(
                Line(ellipse=(self.pos[0] + awidth, self.pos[1] + awidth,
                              self.dial_diameter - awidth * 2,
                              self.dial_diameter - awidth * 2,
                              st + awidth / 2.0 - self.tic_width,
                              en + awidth / 2.0),
                     width=awidth,
                     cap='none',
                     joint='round'))

        if self.semi_circle:
            self.annular_canvas.add(PopMatrix())

        self.canvas.before.add(self.annular_canvas)

    def draw_ticks(self):
        scangle = self.angle_stop - self.angle_start
        inc = scangle / (
            (self.scale_max - self.scale_min) / self.scale_increment)
        inc /= self.tic_frequency
        cnt = 0

        # create an instruction group so we can remove it and recall draw_ticks to update when pos or size changes
        self.ticks = InstructionGroup()

        self.ticks.add(Color(*self.tic_color))

        labi = self.scale_min
        x = -180.0 + self.angle_start + self.angle_offset  # start
        while x <= self.angle_stop - 180 + self.angle_offset:
            a = x if (x < 0.0) else x + 360.0

            need_label = True
            ticlen = self.tic_length

            if (cnt % self.tic_frequency != 0):
                ticlen = self.tic_length / 2
                need_label = False

            cnt += 1

            self.ticks.add(PushMatrix())
            self.ticks.add(
                Rotate(angle=a,
                       axis=(0, 0, -1),
                       origin=(self.dial_center[0], self.dial_center[1])))
            self.ticks.add(Translate(0, self.tic_radius - ticlen))
            self.ticks.add(
                Line(points=[
                    self.dial_center[0], self.dial_center[1],
                    self.dial_center[0], self.dial_center[1] + ticlen
                ],
                     width=self.tic_width,
                     cap='none',
                     joint='none'))

            if need_label:
                #print("label: " + str(labi))
                #kw['font_size'] = self.tic_length * 2
                label = CoreLabel(text=str(int(round(labi))),
                                  font_size=self.scale_font_size)
                label.refresh()
                texture = label.texture
                self.ticks.add(
                    Translate(-texture.size[0] / 2, -texture.size[1] - 2))
                self.ticks.add(
                    Rectangle(texture=texture,
                              pos=self.dial_center,
                              size=texture.size))
                labi += self.scale_increment

            self.ticks.add(PopMatrix())
            x += inc

        self.canvas.add(self.ticks)

    def draw_setpoint(self, *args):
        # draw a setpoint
        if self.setpoint_canvas:
            self.canvas.after.remove(self.setpoint_canvas)
            self.setpoint_canvas = None

        if math.isnan(self.setpoint_value):
            return

        v = self.value_to_angle(self.setpoint_value)
        length = self.dial_diameter / 2.0 - self.tic_length if not self.setpoint_length else self.setpoint_length
        self.setpoint_canvas = InstructionGroup()

        self.setpoint_canvas.add(PushMatrix())
        self.setpoint_canvas.add(Color(*self.setpoint_color))
        self.setpoint_canvas.add(
            Rotate(angle=v, axis=(0, 0, -1), origin=self.dial_center))
        self.setpoint_canvas.add(
            Translate(self.dial_center[0], self.dial_center[1]))
        self.setpoint_canvas.add(
            Line(points=[0, 0, 0, length],
                 width=self.setpoint_thickness,
                 cap='none'))
        #self.setpoint_canvas.add(SmoothLine(points=[0, 0, 0, length], width=self.setpoint_thickness))
        self.setpoint_canvas.add(PopMatrix())

        self.canvas.after.add(self.setpoint_canvas)
Пример #23
0
class DisplayController(object):
    def __init__(self, width, height, canvas, ac, eye_pos, eye_angle):
        super(DisplayController, self).__init__()
        self.width = width
        self.height = height
        self.canvas = canvas
        self.eye_pos = eye_pos
        self.eye_angle = eye_angle
        self.ac = ac

        self.canvas.shader.source = resource_find('data/simple.glsl')

        self.all_notes = []
        self.future_notes = {}
        self.past_notes = {}
        self.ticks = []

        # self.planes = range(0, 10 * config['PLANE_SPACING'], config['PLANE_SPACING'])
        self.planes = []
        self.lines = []

        self.past_displays = InstructionGroup()
        self.future_displays = InstructionGroup()
        self.plane_displays = InstructionGroup()
        self.line_displays = InstructionGroup()

        self.fixed_x = Translate(0, 0, 0)
        self.fixed_y = Translate(0, 0, 0)
        self.fixed_z = Translate(0, 0, 0)
        self.fixed_azi = Rotate(origin=(0, 0, 0), axis=(0, 1, 0))
        self.fixed_ele = Rotate(origin=(0, 0, 0), axis=(1, 0, 0))

        self.alpha_callback = Callback(self.alpha_sample_callback)
        self.disable_alpha_callback = Callback(self.disable_alpha_sample_callback)
        self.alpha_instruction = InstructionGroup()
        self.alpha_disable_instruction = InstructionGroup()
        self.alpha_sample_enable = False

        self.canvas.add(Callback(self.setup_gl_context))
        self.canvas.add(self.alpha_instruction)
        self.canvas.add(PushMatrix())
        self.canvas.add(UpdateNormalMatrix())

        
        
        self.canvas.add(PushMatrix())
        self.canvas.add(self.fixed_z)
        self.canvas.add(self.line_displays)
        self.canvas.add(PopMatrix())

        self.canvas.add(PushMatrix())
        self.canvas.add(self.past_displays)
        self.canvas.add(self.future_displays)
        self.canvas.add(PopMatrix())

        self.canvas.add(PushMatrix())
        # self.canvas.add(self.fixed_x)
        # self.canvas.add(self.fixed_y)
        self.canvas.add(self.plane_displays)
        self.canvas.add(PopMatrix())

        # self.canvas.add(PushMatrix())
        # self.canvas.add(self.fixed_x)
        # self.canvas.add(self.fixed_y)
        # self.canvas.add(self.fixed_z)
        # self.canvas.add(Plane(-config['SELF_PLANE_DISTANCE'], size=0.1, color=(0x20/255., 0xD8/255., 0xE9/255.), tr=0.2))
        # self.canvas.add(PopMatrix())

        self.canvas.add(PopMatrix())
        self.canvas.add(self.alpha_disable_instruction)
        self.canvas.add(Callback(self.reset_gl_context))

        self.draw_planes()

    def add_notes(self, note_data):
        s = config['LINE_SPACING']
        for nd in note_data:
            if (nd.x, nd.y) not in self.lines and float(nd.x).is_integer() and float(nd.y).is_integer():
                self.line_displays.add(Line(nd.x * s, nd.y * s, color=(0.7, 0.5, 0.0)))
                self.lines.append((nd.x, nd.y))

        self.all_notes.extend(note_data)
        self.all_notes.sort(key=lambda n:n.tick)
        self.ticks = map(lambda n:n.tick, self.all_notes)

    def draw_planes(self):
        for p in self.planes:
            self.plane_displays.add(Plane(p, color=(0xE9/255., 0xD8/255., 0x3C/255.)))

    def setup_gl_context(self, *args):
        gl.glEnable(gl.GL_DEPTH_TEST)

    def toggle_alpha_sample(self):
        if self.alpha_sample_enable:
            self.alpha_instruction.remove(self.alpha_callback)
            self.alpha_disable_instruction.remove(self.disable_alpha_callback)
            self.alpha_sample_enable = False
        else:
            self.alpha_instruction.add(self.alpha_callback)
            self.alpha_disable_instruction.add(self.disable_alpha_callback)
            self.alpha_sample_enable = True

    def alpha_sample_callback(self, *args):
        gl.glEnable(gl.GL_SAMPLE_ALPHA_TO_COVERAGE)

    def reset_gl_context(self, *args):
        gl.glDisable(gl.GL_DEPTH_TEST)

    def disable_alpha_sample_callback(self, *args):
        gl.glDisable(gl.GL_SAMPLE_ALPHA_TO_COVERAGE)

    def get_look_at(self, x, y, z, azi, ele):
        dx = - np.sin(azi) * np.cos(ele)
        dy = np.sin(ele)
        dz = - np.cos(azi) * np.cos(ele)

        # Not sure why up has to just be up...
        upx, upy, upz = (0, 1, 0)

        mat = Matrix()
        mat = mat.look_at(x, y, z,
                          x + dx, y + dy, z + dz,
                          upx, upy, upz)
        return mat

    def update_camera(self, pos, angle):
        self.eye_pos = pos
        self.eye_angle = angle
        x, y, z = pos
        azi, ele = angle
        asp = self.width / float(self.height)
        mat = self.get_look_at(x, y, z, azi, ele)

        proj = Matrix()
        proj.perspective(30, asp, 1, 100)

        self.canvas['projection_mat'] = proj
        self.canvas['modelview_mat'] = mat

        self.fixed_x.x = x
        self.fixed_y.y = y
        self.fixed_z.z = z
        self.fixed_azi.angle = azi * 180/np.pi
        self.fixed_ele.angle = ele * 180/np.pi

    def get_notes_in_range(self, start_tick, end_tick):
      l = bisect.bisect_left(self.ticks, start_tick)
      r = bisect.bisect_left(self.ticks, end_tick)
      if r <= 0:
         return []
      return self.all_notes[l:r]

    def on_update(self, tick):
        self_plane_z = self.eye_pos[2] - config['SELF_PLANE_DISTANCE']

        eye_tick = tick + ( - self.eye_pos[2] / config['UNITS_PER_TICK'])
        dt = kivyClock.frametime

        future_range = self.get_notes_in_range(eye_tick, eye_tick + config['VISIBLE_TICK_RANGE'])
        past_range = self.get_notes_in_range(eye_tick - config['VISIBLE_TICK_RANGE'], eye_tick)

        # COMPLEX LOGIC TO MAINTAIN LISTS OF VISIBLE NOTES ORDERED BY DISTANCE FROM CAMERA
        # far future <-> future
        # future <-> past
        # past <-> far past

        # far future -> future
        fftof = list(x for x in future_range if x not in self.past_notes and x not in self.future_notes)
        # future -> far future
        ftoff = list(x for x in self.future_notes if x not in future_range and x not in past_range)
        # future -> past
        ftop = list(x for x in past_range if x in self.future_notes)
        # past -> future
        ptof = list(x for x in future_range if x in self.past_notes)
        # past -> far past
        ptofp = list(x for x in self.past_notes if x not in future_range and x not in past_range)
        # far past -> past
        fptop = list(x for x in past_range if x not in self.past_notes and x not in self.future_notes)

        # handle ff -> f
        for nd in sorted(fftof, key=lambda n: n.tick):
            ndisp = NoteDisplay(nd, self.planes, self.ac)
            self.future_displays.insert(0, ndisp)
            self.future_notes[nd] = ndisp

        # handle f -> ff
        for nd in ftoff:
            ndisp = self.future_notes[nd]
            self.future_displays.remove(ndisp)
            del self.future_notes[nd]

        # handle f -> p
        for nd in sorted(ftop, key=lambda n: n.tick):
            ndisp = self.future_notes[nd]
            self.future_displays.remove(ndisp)
            self.past_displays.add(ndisp)
            self.past_notes[nd] = ndisp
            del self.future_notes[nd]

        # handle p -> f
        for nd in sorted(ptof, key=lambda n: -n.tick):
            ndisp = self.past_notes[nd]
            self.past_displays.remove(ndisp)
            self.future_displays.add(ndisp)
            self.future_notes[nd] = ndisp
            del self.past_notes[nd]

        # handle p -> fp
        for nd in ptofp:
            ndisp = self.past_notes[nd]
            self.past_displays.remove(ndisp)
            del self.past_notes[nd]

        # handle fp -> p
        for nd in sorted(fptop, key=lambda n: -n.tick):
            ndisp = NoteDisplay(nd, self.planes, self.ac)
            self.past_displays.insert(0, ndisp)
            self.past_notes[nd] = ndisp


        for s in self.future_notes.values() + self.past_notes.values():
            pos = s.pos_from_tick(tick)
            s.set_pos(pos)
            s.on_update(dt, eye_tick, self.eye_angle)

            if s.past_me and pos[2] < self_plane_z - 0.5 * config['SELF_PLANE_DISTANCE']:
                s.past_me = False
            if pos[2] > self_plane_z and not s.past_me:
                s.sound(tick, pos)
                s.past_me = True


        Logger.debug('Number of notes: %s' % (len(self.future_notes) + len(self.past_notes)))
Пример #24
0
class String(FloatLayout):
    open_note_val = NumericProperty(0)
    num_frets = NumericProperty(12)
    fret_positions = ListProperty()
    note_vals = ListProperty()
    mode_filter = NumericProperty(0b101011010101)
    root_note_idx = NumericProperty(0)
    scale_text = StringProperty("")
    notes_to_highlight = StringProperty("")
    notes_or_octaves = StringProperty("")

    animation_prop = NumericProperty(0)
    hit_prop = NumericProperty(0)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.string_shadow = Rectangle()
        self.string_graphic = Rectangle()
        self.note_markers = InstructionGroup()
        self.octave_markers = InstructionGroup()

        self.canvas.add(Color(rgba=[0 / 255, 0 / 255, 0 / 255, 0.25]))
        self.canvas.add(self.string_shadow)
        self.canvas.add(Color(rgba=[169 / 255, 169 / 255, 169 / 255, 1]))
        self.canvas.add(self.string_graphic)
        self._add_markers()
        self.canvas.add(self.note_markers)
        self.canvas.add(self.octave_markers)
        self.bind(size=self.update_canvas, pos=self.update_canvas)

        self.anim = Animation()
        self.hit_anim = Animation()
        self.play_instrs = []

    def _add_markers(self):
        for i in range(25):
            marker = Marker()
            self.note_markers.add(marker)

    def animate_marker(self, index, *args):
        markers = self.note_markers.children
        anim = Animation(animation_prop=1, duration=0.5, t="in_circ")
        anim.bind(on_start=markers[index].initiate_animation)
        anim.bind(on_progress=markers[index].update_animation)
        anim.bind(on_complete=markers[index].end_animation)
        anim.start(self)

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            for i in range(len(self.note_markers.children)):
                self.animate_marker(i)

    def update_canvas(self, *args):
        if self.fret_positions:  # self.fret_positions is empty during instantiation.
            # self.update_octave_markers()
            self.update_string_graphics()
            self.update_note_markers()

    def update_string_graphics(self):
        w, h = self.width, self.height * 0.1
        x, y = self.pos
        cy = y + (self.height / 2)
        string_y = cy - (h / 2)
        shadow_height = 3 * h
        shadow_y = string_y - shadow_height
        # Shadow effect.
        self.string_shadow.size = [w, shadow_height]
        self.string_shadow.pos = [x, cy - shadow_height]
        # String.
        self.string_graphic.size = [w, h]
        self.string_graphic.pos = [x, string_y]

    def update_note_markers(self, *args):
        x, y = self.pos
        r1 = self.height / 2
        r2 = r1 * 0.9
        rdiff = r1 - r2
        for i, (note_val, marker) in enumerate(
                zip(self.note_vals, self.note_markers.children)):
            # Make right edge of circle touch left edge of fret bar (where your finger should go!)
            fret_left = self.fret_positions[i] - (
                self.fretboard.fret_bar_width / 2)
            # Draw 2 concentric circles, c1 and c2.
            # Circles are defined by a square's lower left corner.
            c1x, c1y = (fret_left - 2 * r1) + x, y
            c2x, c2y = c1x + rdiff, c1y + rdiff

            octave, note_idx = divmod(note_val, 12)
            included = int(
                bin(self.mode_filter)[2:][note_idx - self.root_note_idx])
            highlighted = int(
                bin(scale_highlights[self.notes_to_highlight])[2:][
                    note_idx - self.root_note_idx])
            if self.notes_or_octaves == "Notes":
                color_idx = note_idx - self.root_note_idx
                color = rainbow[color_idx]
            else:
                color_idx = octave - 1
                color = octave_colors[color_idx]

            if self.scale_text == "Scale Degrees":
                note_idx -= self.root_note_idx

            note_text = scale_texts[self.scale_text][note_idx]

            marker.update(i, note_text, c1x, c1y, r1, c2x, c2y, r2, included,
                          highlighted, color)

    def update_octave_markers(self):
        self.octave_markers.clear()
        for i, note_val in enumerate(self.note_vals):
            self.update_octave_marker(i, note_val)

    def update_octave_marker(self, i, note_val):
        if self.fret_ranges:
            octave = (note_val - self.fretboard.root_note_idx) // 12
            left, right = self.fret_ranges[i]
            width = right - left
            self.octave_markers.add(octave_colors[octave])
            self.octave_markers.add(
                Rectangle(pos=[left, 0], size=[width, self.height]))

    def on_open_note_val(self, instance, value):
        self.note_vals = [
            val for val in range(self.open_note_val, self.open_note_val + 25)
        ]
        self.update_canvas(instance, value)

    def on_num_frets(self, instance, value):
        self.note_vals = [
            val for val in range(self.open_note_val, self.open_note_val + 25)
        ]
        self.update_canvas(instance, value)

    def on_root_note_idx(self, instance, value):
        self.update_canvas(instance, value)

    def on_mode_filter(self, instance, value):
        self.update_canvas(instance, value)

    def on_scale_text(self, instance, value):
        self.update_note_markers()

    def on_notes_to_highlight(self, instance, value):
        self.update_note_markers()

    def on_notes_or_octaves(self, *args):
        self.update_note_markers()

    ### SONG PLAYING METHODS
    def play_thread(self, lead_in):
        # The GuitarPro songs' tempo are of form BPM where the B(eat) is always a quarter note.
        thread = Thread(target=partial(self._play_thread_animation, lead_in),
                        daemon=True)
        thread.start()

    def _play_thread_animation(self, lead_in):
        self.stopped = False
        markers = self.note_markers.children
        idx = 0
        time.sleep(lead_in)
        start = time.time()
        goal = start
        while not self.stopped:
            if idx == len(self.play_instrs):
                return
            fret_num, seconds = self.play_instrs[idx]
            if fret_num != -1:
                # self._play_fret(fret_num, seconds)

                self.animation_prop = 0
                anim = Animation(animation_prop=1, duration=seconds)
                anim.bind(on_start=markers[fret_num].initiate_animation)
                anim.bind(on_progress=markers[fret_num].update_animation)
                anim.bind(on_complete=markers[fret_num].end_animation)
                self.anim = anim

                self.hit_prop = 0
                hit_anim = Animation(hit_prop=1, duration=min(seconds, 0.1))
                hit_anim.bind(
                    on_start=markers[fret_num].initiate_hit_animation)
                hit_anim.bind(
                    on_progress=markers[fret_num].update_hit_animation)
                hit_anim.bind(on_complete=markers[fret_num].end_hit_animation)
                self.hit_anim = hit_anim

                anim.start(self)
                hit_anim.start(self)
            goal += seconds
            idx += 1
            time.sleep(max(goal - time.time(), 0))

    # def _play_fret(self, fret_num, seconds):
    #     self.anim.stop(self)
    #     self.animation_prop = 0
    #     markers = self.note_markers.children
    #     anim = Animation(animation_prop=1, duration=seconds)
    #     anim.bind(on_start=markers[fret_num].initiate_animation)
    #     anim.bind(on_progress=markers[fret_num].update_animation)
    #     anim.bind(on_complete=markers[fret_num].end_animation)
    #     self.anim = anim
    #     anim.start(self)

    def stop(self):
        self.stopped = True
Пример #25
0
class TextureStack(Widget):
    """Several textures superimposed on one another, and possibly offset
    by some amount.

    In 2D games where characters can wear different clothes or hold
    different equipment, their graphics are often composed of several
    graphics layered on one another. This widget simplifies the
    management of such compositions.

    """
    texs = ListProperty()
    """Texture objects"""
    offxs = ListProperty()
    """x-offsets. The texture at the same index will be moved to the right
    by the number of pixels in this list.

    """
    offys = ListProperty()
    """y-offsets. The texture at the same index will be moved upward by
    the number of pixels in this list.

    """
    def _get_offsets(self):
        return zip(self.offxs, self.offys)

    def _set_offsets(self, offs):
        offxs = []
        offys = []
        for x, y in offs:
            offxs.append(x)
            offys.append(y)
        self.offxs, self.offys = offxs, offys

    offsets = AliasProperty(_get_offsets,
                            _set_offsets,
                            bind=('offxs', 'offys'))
    """List of (x, y) tuples by which to offset the corresponding texture."""
    _texture_rectangles = DictProperty({})
    """Private.

    Rectangle instructions for each of the textures, keyed by the
    texture.

    """

    def __init__(self, **kwargs):
        """Make triggers and bind."""
        kwargs['size_hint'] = (None, None)
        self.translate = Translate(0, 0)
        self.group = InstructionGroup()
        super().__init__(**kwargs)
        self.bind(offxs=self.on_pos, offys=self.on_pos)

    def on_texs(self, *args):
        """Make rectangles for each of the textures and add them to the
        canvas, taking their stacking heights into account.

        """
        if not self.canvas or not self.texs:
            Clock.schedule_once(self.on_texs, 0)
            return
        texlen = len(self.texs)
        # Ensure each property is the same length as my texs, padding
        # with 0 as needed
        for prop in ('offxs', 'offys'):
            proplen = len(getattr(self, prop))
            if proplen > texlen:
                setattr(self, prop, getattr(self, prop)[:proplen - texlen])
            if texlen > proplen:
                propval = list(getattr(self, prop))
                propval += [0] * (texlen - proplen)
                setattr(self, prop, propval)
        self.group.clear()
        self._texture_rectangles = {}
        w = h = 0
        (x, y) = self.pos
        self.translate.x = x
        self.translate.y = y
        self.group.add(PushMatrix())
        self.group.add(self.translate)
        for tex, offx, offy in zip(self.texs, self.offxs, self.offys):
            rect = Rectangle(pos=(offx, offy), size=tex.size, texture=tex)
            self._texture_rectangles[tex] = rect
            self.group.add(rect)
            tw = tex.width + offx
            th = tex.height + offy
            if tw > w:
                w = tw
            if th > h:
                h = th
        self.size = (w, h)
        self.group.add(PopMatrix())
        if self.group not in self.canvas.children:
            self.canvas.add(self.group)

    def on_pos(self, *args):
        """Translate all the rectangles within this widget to reflect the widget's position.

        """
        (x, y) = self.pos
        Logger.debug("TextureStack: repositioning to {}".format((x, y)))
        self.translate.x = x
        self.translate.y = y

    def clear(self):
        """Clear my rectangles, ``texs``, and ``stackhs``."""
        self.group.clear()
        self._texture_rectangles = {}
        self.texs = []
        self.offxs = []
        self.offys = []
        self.size = [1, 1]

    def insert(self, i, tex):
        """Insert the texture into my ``texs``, waiting for the creation of
        the canvas if necessary.

        """
        if not self.canvas:
            Clock.schedule_once(lambda dt: TextureStack.insert(self, i, tex),
                                0)
            return
        self.texs.insert(i, tex)
        self.offxs.insert(i, 0)
        self.offys.insert(i, 0)

    def append(self, tex):
        """``self.insert(len(self.texs), tex)``"""
        self.insert(len(self.texs), tex)

    def __delitem__(self, i):
        """Remove a texture, its rectangle, and its stacking height"""
        tex = self.texs[i]
        try:
            rect = self._texture_rectangles[tex]
            self.canvas.remove(rect)
            del self._texture_rectangles[tex]
        except KeyError:
            pass
        del self.offxs[i]
        del self.offys[i]
        del self.texs[i]

    def __setitem__(self, i, v):
        """First delete at ``i``, then insert there"""
        if len(self.texs) > 0:
            self._no_upd_texs = True
            self.__delitem__(i)
            self._no_upd_texs = False
        self.insert(i, v)

    def pop(self, i=-1):
        """Delete the offsets and texture at ``i``, returning the texture.

        """
        del self.offxs[i]
        del self.offys[i]
        return self.texs.pop(i)
Пример #26
0
 def __init__(self, points=[], **kwargs):
     super(Figure, self).__init__(**kwargs)
     self.line_draw = InstructionGroup()
     self.points_as_added = []
Пример #27
0
    def drawCrossLine(self, key):
        if len(self.profitPerNumDict) == 0:
            return
        
        aNum = self.profitPerNumDict.get(key)
        if aNum == None:
            return
        
        keyInt = int(key)
        
        index = keyInt - self.min_tickNum
        if keyInt == 0:
            shift_xpos = self.ycordWidth
        elif keyInt > 0:
            shift_xpos = self.ycordWidth * 2
        else:
            shift_xpos = 0
        
        color = Color()
        color.rgba = self.CROSS_LINE_COLOR

        self.canvas.remove_group("cross_line")
        
        center_pos = int(self.pillarPoint / 2)
        instg = InstructionGroup(group="cross_line")
        instg.add(color)
        x1 = int(self.pos[0] + self.shift_left + index * self.pillarSumPoint + shift_xpos + center_pos)
        y1 = int(self.pos[1] + self.shift_bottom)
        x2 = int(self.pos[0] + self.shift_left + index * self.pillarSumPoint + shift_xpos + center_pos)
        y2 = int(self.pos[1] + self.shift_bottom + self.maxNum * self.yscale)
        instg.add(Line(points=(x1, y1, x2, y2), width=1))
        self.canvas.add(instg)
                
        instg = InstructionGroup(group="cross_line")
        instg.add(color)
        x1 = self.pos[0] + self.shift_left
        y1 = int(self.pos[1] + self.shift_bottom + aNum * self.yscale)
        x2 = self.pos[0] + self.width - self.shift_right
        y2 = int(self.pos[1] + self.shift_bottom + aNum * self.yscale)
        instg.add(Line(points=(x1, y1, x2, y2), width=1))        
        self.canvas.add(instg)
Пример #28
0
class CanvasWidget(FloatLayout):
    canvas_size = ObjectProperty((512, 512))
    scale = NumericProperty(1)
    texture = ObjectProperty()
    touch_type = 'move'
    current_color = [0,0,0,1]

    @property
    def scaled_size(self):
        w, h = self.canvas_size
        return (w * self.scale, h * self.scale)

    def __init__(self, **kwargs):
        super(CanvasWidget, self).__init__(**kwargs)
        self.size = (512, 512)
        self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
        self._keyboard.bind(on_key_down=self._on_keyboard_down)


        self.img = Image.open('test.png')
        self.img = self.img =  self.img.transpose(Image.FLIP_TOP_BOTTOM)
        self.texture = Texture.create(size=(512,512))
        self.texture.mag_filter = 'nearest'
        size = 512*512*3
        buf = []
        for r,g,b,a in self.img.getdata():
            buf.extend([r,g,b,a])
        #buf = [int(x*255/size) for x in range(size)]
        #buf = self._flatten_list(self.pixels)
        self.arr = array('B', buf)
        self.texture.blit_buffer(self.arr, colorfmt='rgba', bufferfmt='ubyte')

        with self.canvas:
            self.test = InstructionGroup()
            #self.test.add(Color(1, 1, 0, mode='rgb'))
            self.test.add(Rectangle(texture=self.texture, pos=self.pos, size=self.size, group='heh'))

        #self.bind(texture=self.on_texture_update)
        self.bind(pos=self.on_texture_update)
        self.bind(size=self.on_texture_update)

    def on_texture_update(self, instance=None, value=None):
        print('on_texture_update')
        for inst in self.test.get_group('heh'):
            if hasattr(inst, 'pos'):
                inst.pos = self.pos
            if hasattr(inst, 'size'):
                inst.size = self.size

        #self.canvas.clear()
        #with self.canvas:
        #    Color(1, 1, 0, mode='rgb')
        #    #Rectangle(texture=self.texture, pos=self.pos, size=self.size)
        #    Rectangle(pos=self.pos, size=self.size)


    def _keyboard_closed(self):
        self._keyboard.unbind(on_key_down=self._on_keyboard_down)
        self._keyboard = None

    def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
        if keycode[1] == 'q':
            self.touch_type = 'move'
        elif keycode[1] == 'w':
            self.touch_type = 'draw'
        elif keycode[1] == 'e':
            r = random.random()
            g = random.random()
            b = random.random()
            print(self.parent.parent.ids.palette.add_color([r,g,b,1]))

    def on_touch_down(self, touch):
        if touch.button == 'scrolldown':
            print('Zoomin\' in')
            self.set_scale(self.scale * 1.2, touch.pos)
        elif touch.button == 'scrollup':
            print('Zoomin\' out')
            self.set_scale(self.scale / 1.2, touch.pos)
        else:
            if self.touch_type == 'draw':
                x,y = self.project(touch.pos)
                r,g,b,a = self.current_color
                self.update_pixel(int(x), int(y), r, g, b, a)
                self.refresh()
            touch.grab(self)
        return True

    def on_touch_move(self, touch):
        if touch.grab_current == self:
            if self.touch_type == 'move':
                x, y = self.pos
                dx, dy = touch.dpos
                self.pos = (x+dx, y+dy)
            elif self.touch_type == 'draw':
                x,y = self.project(touch.pos)
                px, py = self.project(touch.ppos)
                #self.update_pixel(int(x), int(y), 255, 0, 100, 100)
                r,g,b,a = self.current_color
                self.draw_line(px, py, x, y, r,g,b,a)
                
        return True

    def set_color(self, color):
        self.current_color = color

    def on_touch_up(self, touch):
        if touch.grab_current == self:
            touch.ungrab(self)
        return True

    def update_pixel(self, x, y, r, g, b, a):
        w,h = self.canvas_size
        index = int((y * w * 4) + 4 * x)
        self.arr[index] = int(r*255)
        self.arr[index+1] = int(g*255)
        self.arr[index+2] = int(b*255)
        self.arr[index+3] = int(a*255)
        self.texture.blit_buffer(self.arr, colorfmt='rgba', bufferfmt='ubyte')
        print('PIXEL: %s,%s' % (int(x), int(y)))

    def refresh(self):
        self.canvas.ask_update()

    def draw_line(self, x0, y0, x1, y1, r,g,b,a):
        self.update_pixel(int(x0),int(y0),r,g,b,a)
        self.update_pixel(int(x1),int(y1),r,g,b,a)
        print('LINE: %s, %s -> %s, %s' % (x0,y0,x1,y1))
        x0, y0, x1, y1 = int(x0), int(y0), int(x1), int(y1)
        steep = abs(y1-y0) > abs(x1-x0)
        if steep:
            x0, y0 = y0, x0
            x1, y1 = y1, x1
        if x0 > x1:
            x0, x1 = x1, x0
            y0, y1 = y1, y0
        deltax = x1-x0
        deltay = abs(y1-y0)
        error = int(deltax / 2)
        ystep = 0
        y = y0
        if y0 < y1:
            ystep = 1
        else:
            ystep = -1

        for x in range(x0,x1):
            if steep:
                self.update_pixel(y, x, r,g,b,a)
            else:
                self.update_pixel(x, y, r,g,b,a)
            error -= deltay
            if error < 0:
                y = y + ystep
                error = error + deltax
        self.refresh()

    def redraw_canvas(self):
        arr = array('B', self.buf)
        self.texture.blit_buffer(arr, colorfmt='rgba', bufferfmt='ubyte')

    def is_moveable(self):
        w, h = self.size
        return w > Window.size[0] and h > Window.size[1]

    def set_scale(self, scale, pivot):
        delta_scale = self.scale - scale
        prev_w, prev_h = self.size
        c_w, c_h = self.canvas_size
        self.scale = scale
        w, h = (c_w * self.scale, c_h * self.scale)
        self.size = (w, h)
        dw = w - prev_w
        dh = h - prev_h
        px, py = pivot
        x, y = self.pos
        ratio_x =  abs(px - x) / w
        ratio_y =  abs(py - y) / h
        after_x = dw * ratio_x
        after_y = dh * ratio_y
        print('current', ratio_x, ratio_y)
        #self.center = (x - (ax-px)*scale, y - (ay-py)*scale)
        #if not self.is_moveable():
        #    self.center = Window.center
        #else:
        x,y = self.pos
        self.pos = (x - after_x, y - after_y)

    def project(self, point):
        px,py = point
        x, y = self.pos
        ratio = self.canvas_size[0]/self.size[0]
        return (ratio*(px-x), ratio*(py-y))

    def _flatten_list(self, lst):
        return list(itertools.chain.from_iterable(lst))


    def resize(self):
        print('Resize %s' % self.size)

    def redraw_region(region=None):
        # This will redraw a region of the canvas by iterating over
        # a box of pixels in the pixel map and then drawing a
        # rectangle for each of them. Every time something is drawn
        # the rectangle dimensions containing the shape will be sent
        # through a callback to this function
        pass
Пример #29
0
    def update_board(self):
        self.canvas.after.clear()
        self.players = []
        pos_x = 0.85
        pos_y = 0.11
        self.color_players_list = [[1, 0, 0, 1], [0, 1, 0, 1], [0, 0, 1, 1], [1, 1, 0, 1]]
        self.pos_x_list = []
        self.pos_y_list = []

        for i in range(len(self.dice_holder_list)):
            self.dice_holder_list[i].text = str(self.dice_list[i])
        '''
        for i in range(4):
            if self.game_elem['players'][i].has_get_out_of_jail_chance_card == True:
                self.goo_jail_chance_with_player = "is with " + str(self.game_elem['players'][i].player_name)
                break
            else:
                self.goo_jail_chance_with_player = "Inside the deck"
        
        for i in range(4):
            if self.game_elem['players'][i].has_get_out_of_jail_community_chest_card == True:
                self.goo_jail_cc_with_player = "is with " + str(self.game_elem['players'][i].player_name)
                break
            else:
                self.goo_jail_cc_with_player = "Inside the deck"

        self.goo_jail_list[0].text = "Community Chest Card \nGet out of jail card \n" + self.goo_jail_cc_with_player
        self.goo_jail_list[1].text = "Chance Card \nGet out of jail card \n" + self.goo_jail_chance_with_player
        '''

        for i in range(4):
            text_on_button = " "  + self.game_elem['players'][i].player_name + \
                            "\n Current Cash = " + str(self.game_elem['players'][i].current_cash) + \
                            "\n # of houses = " + str(self.game_elem['players'][i].num_total_houses) + \
                             "\n # of hotels = " + str(self.game_elem['players'][i].num_total_hotels)
            if self.game_elem['players'][i].has_get_out_of_jail_community_chest_card == True:
                text_on_button = text_on_button + "\nGOO_Jail community card"
            if self.game_elem['players'][i].has_get_out_of_jail_chance_card == True:
                text_on_button = text_on_button + "\nGOO_Jail chance card"

            self.player_detail_list[i].text = text_on_button
            self.obj_instr_player = InstructionGroup()
            self.obj_instr_player.add(
                Color(self.color_players_list[i][0], self.color_players_list[i][1], self.color_players_list[i][2],
                      self.color_players_list[i][3]))
            try:
                pos_x_n = self.game_elem['players'][i].current_position / 10
                pos_y_n = self.game_elem['players'][i].current_position % 10
            except:
                pos_x_n = 0
                pos_y_n = 0

            if (pos_x_n == 0):
                pos_x = 0.85 - (pos_y_n * 0.07)
                pos_y = 0.11
            elif (pos_x_n == 2):
                pos_x = 0.85 - (10 * (0.07)) + (pos_y_n * 0.07)
                pos_y = 0.11 + (10 * 0.07)
            elif (pos_x_n == 1):
                pos_x = 0.85 - (10 * (0.07))
                pos_y = 0.11 + (pos_y_n * 0.07)
            elif (pos_x_n == 3):
                pos_x = 0.85
                pos_y = 0.11 + (10 * 0.07) - (pos_y_n * 0.07)

            self.obj_instr_player.add(
                Ellipse(pos=((pos_x + i * 0.01) * Window.width, pos_y * Window.height), size=(10, 10)))
            self.players.append(self.obj_instr_player)
            self.pos_x_list.append(pos_x)
            self.pos_y_list.append(pos_y)
            self.canvas.after.add(self.obj_instr_player)

            count_house = 0
            count_hotel = 0
            if (self.game_elem['players'][i].assets) != None:
                self.player_props = []
                self.player_props_x = []
                self.player_props_y = []

                for k in range(len(list(self.game_elem['players'][i].assets))):
                    prop_name = list(self.game_elem['players'][i].assets)[k].name
                    pos_prop = self.game_elem['location_objects'][prop_name].start_position

                    self.obj_instr = InstructionGroup()
                    self.obj_instr.add(Color(self.color_players_list[i][0], self.color_players_list[i][1],
                                             self.color_players_list[i][2],
                                             self.color_players_list[i][3]))
                    prop_x = pos_prop / 10
                    prop_y = pos_prop % 10
                    pos_x_prop = 0
                    pos_y_prop = 0
                    if (prop_x == 0):
                        pos_x_prop = 0.835 - (prop_y * 0.07)
                        pos_y_prop = 0.14
                    elif (prop_x == 2):
                        pos_x_prop = 0.835 - (10 * (0.07)) + (prop_y * 0.07)
                        pos_y_prop = 0.14 + (10 * 0.07)
                    elif (prop_x == 1):
                        pos_x_prop = 0.835 - (10 * (0.07))
                        pos_y_prop = 0.14 + (prop_y * 0.07)
                    elif (prop_x == 3):
                        pos_x_prop = 0.835
                        pos_y_prop = 0.14 + (10 * 0.07) - (prop_y * 0.07)
                    self.obj_instr.add(Rectangle(pos=(pos_x_prop * Window.width, pos_y_prop * Window.height),
                                                 size=(12, 12)))

                    if list(self.game_elem['players'][i].assets)[k].loc_class=='real_estate':
                        if list(self.game_elem['players'][i].assets)[k].num_houses>0:
                            for m in range(list(self.game_elem['players'][i].assets)[k].num_houses):
                                self.obj_instr.add(Color(1,1,1,1))
                                self.obj_instr.add(Ellipse(pos=((pos_x_prop + (m+1)*0.01) * Window.width, pos_y_prop * Window.height),
                                                             size=(12, 12)))
                                count_house+=list(self.game_elem['players'][i].assets)[k].num_houses

                        if list(self.game_elem['players'][i].assets)[k].num_hotels>0:
                            for m in range(list(self.game_elem['players'][i].assets)[k].num_hotels):
                                self.obj_instr.add(Color(1,0.1,0.5,1))
                                self.obj_instr.add(Ellipse(pos=((pos_x_prop + (m+1)*0.01) * Window.width, pos_y_prop * Window.height),
                                                             size=(12, 12)))
                                count_hotel += list(self.game_elem['players'][i].assets)[k].num_hotels

                    self.player_props.append(self.obj_instr)
                    self.player_props_x.append(pos_x_prop)
                    self.player_props_y.append(pos_y_prop)
                    self.canvas.after.add(self.obj_instr)
                    self.obj_instr_directory.append(self.obj_instr)
            self.bind(pos=self.update_rect, size=self.update_rect)
Пример #30
0
class myLine(GridLayout):
    def __init__(self, **kargs):
        super(myLine, self).__init__(**kargs)

        #to remove the lines
        self.group = InstructionGroup()

        #set 2 col with 100 height
        self.cols = 2
        self.row_force_default = True
        self.row_default_height = 70

        #angle slider
        self.angleSlider = Slider(min=0, max=360, value=30)
        self.add_widget(self.angleSlider)

        #label for angle slider
        self.L1 = Label(text="Angle: " + str(self.angleSlider.value))
        self.add_widget(self.L1)

        #scale slider
        self.scaleSlider = Slider(min=1, max=5, value=3)
        self.add_widget(self.scaleSlider)

        #label for the slider
        self.L2 = Label(text="Scale: " + str(self.scaleSlider.value))
        self.add_widget(self.L2)

        #ratio slider
        self.ratioSlider = Slider(min=.01, max=.8, value=.67)
        self.add_widget(self.ratioSlider)

        #label for the slider
        self.L3 = Label(text="Ratio: " + str(self.ratioSlider.value))
        self.add_widget(self.L3)

        #attach a call back
        self.angleSlider.bind(value=self.on_value1)
        self.scaleSlider.bind(value=self.on_value2)
        self.ratioSlider.bind(value=self.on_value3)

        with self.canvas:
            angle = math.pi / 2
            self.drawLine(origin_x, origin_y, math.pi / 2, 30)

    def on_value1(self, instance, angle):
        self.L1.text = "Angle: " + str(round(angle, 2))

    def on_value2(self, instance, scale):
        self.L2.text = "Length: " + str(round(scale, 2))

    def on_value3(self, instance, ratio):
        self.L3.text = "Ratio: " + str(round(ratio, 2))

    def on_touch_up(self, touch):
        with self.canvas:
            angle = math.pi / 2
            self.canvas.remove_group("test")
            self.drawLine(origin_x, origin_y, angle, 30)


#    def on_touch_move(self, touch):
#        self.on_touch_up(touch)

    def drawLine(self, start_x, start_y, angle, length):

        if length <= 1:
            return

        end_x = length * self.scaleSlider.value * math.cos(angle) + start_x
        end_y = length * self.scaleSlider.value * math.sin(angle) + start_y
        self.group.add(
            Line(points=[start_x, start_y, end_x, end_y], group="test"))

        length *= self.ratioSlider.value
        self.drawLine(end_x, end_y,
                      angle - self.angleSlider.value * math.pi / 180, length)
        self.drawLine(end_x, end_y,
                      angle + self.angleSlider.value * math.pi / 180, length)
Пример #31
0
class CreateBoardWindow(Screen):
    board_id = ObjectProperty(None)
    prop_id = ObjectProperty(None)
    players = []

    def __init__(self, game_elem, **kwargs):
        super().__init__(**kwargs)
        self.game_elem = game_elem
        self.color_dict = {
            "Brown": [0.5859, 0.3, 0, 1],
            "SkyBlue": [0.68, 0.85, 0.90, 1],
            "Orchid": [0.5, 0, 0.5, 1],
            "Red": [1, 0, 0, 1],
            "Orange": [0.99, 0.64, 0, 1],
            "Yellow": [1, 1, 0, 1],
            "Green": [0, 1, 0, 1],
            "Blue": [0, 0, 1, 1],
            'Pink': [1, 0.75, 0.796],
            None: [0.96, 0.96, 0.86, 1]
        }
        self.obj_instr_directory = []
        self.dice_list = []
        self.start_stop_flag = False
        self.create_board()

    def board_layout_caculator(self, num_properties):
        each_side_num_props = (num_properties / 4)
        each_block_width = (1 - 2 * (0.11) - 0.01) / (each_side_num_props + 1)
        return (each_side_num_props, each_block_width)

    def board_layout_total_tiles_caculator(self, location_seq):
        num_property_tiles = 0
        for loc_obj in location_seq:
            num_property_tiles += 1
        return num_property_tiles

    def create_board(self):
        total_num_property_tiles = self.board_layout_total_tiles_caculator(
            self.game_elem['location_sequence'])
        #each_side_number_of_props, each_block_size = self.board_layout_caculator(len(self.game_elem['location_sequence']))
        each_side_number_of_props, each_block_size = self.board_layout_caculator(
            total_num_property_tiles)
        self.num_tiles = each_side_number_of_props
        self.each_tile_size = each_block_size
        each_side_number_of_props = int(each_side_number_of_props)
        Monopoly_center_button = MonopolyButton(
            text="Play", background_color=self.color_dict[None])
        self.board_id.add_widget(Monopoly_center_button)
        Monopoly_center_button.bind(on_release=self.playing_the_game)
        pos_x = 0.9 - each_block_size  ### 0.1 margins left on both sides of the board
        pos_y = 0.1

        for i in range(each_side_number_of_props):
            label = (self.game_elem['location_sequence'][i].name).replace(
                ' ', '\n')
            num_tiles_spanned_by_property = self.game_elem[
                'location_sequence'][i].end_position - self.game_elem[
                    'location_sequence'][i].start_position
            try:
                color_t = self.color_dict[str(
                    self.game_elem['location_sequence'][i].color)]
            except:
                color_t = self.color_dict[self.game_elem['location_sequence']
                                          [i].color]
            for j in range(num_tiles_spanned_by_property):
                property_button = PropertyButton(text=label,
                                                 background_color=color_t,
                                                 pos_hint={
                                                     "x": pos_x,
                                                     "y": pos_y
                                                 },
                                                 size_hint=(each_block_size,
                                                            each_block_size))
                self.board_id.add_widget(property_button)
            pos_x -= each_block_size

        for i in range(each_side_number_of_props,
                       each_side_number_of_props * 2):
            if self.game_elem['location_sequence'][
                    i].name == 'St. James Place':
                label = 'St.James\nPlace'
            elif self.game_elem['location_sequence'][
                    i].name == 'St. Charles Place':
                label = 'St.Charles\nPlace'
            elif self.game_elem['location_sequence'][
                    i].name == 'New York Avenue':
                label = 'NewYork\nAvenue'
            else:
                label = (self.game_elem['location_sequence'][i].name).replace(
                    ' ', '\n')

            num_tiles_spanned_by_property = self.game_elem[
                'location_sequence'][i].end_position - self.game_elem[
                    'location_sequence'][i].start_position
            try:
                color_t = self.color_dict[str(
                    self.game_elem['location_sequence'][i].color)]
            except:
                color_t = self.color_dict[self.game_elem['location_sequence']
                                          [i].color]
            for j in range(num_tiles_spanned_by_property):
                property_button = PropertyButton(text=label,
                                                 background_color=color_t,
                                                 pos_hint={
                                                     "x": pos_x,
                                                     "y": pos_y
                                                 },
                                                 size_hint=(each_block_size,
                                                            each_block_size))
                self.board_id.add_widget(property_button)

            pos_y += each_block_size

        for i in range(each_side_number_of_props * 2,
                       each_side_number_of_props * 3):
            if self.game_elem['location_sequence'][i].name == 'Go to Jail':
                label = 'Goto\nJail'
            else:
                label = (self.game_elem['location_sequence'][i].name).replace(
                    ' ', '\n')

            num_tiles_spanned_by_property = self.game_elem[
                'location_sequence'][i].end_position - self.game_elem[
                    'location_sequence'][i].start_position
            try:
                color_t = self.color_dict[str(
                    self.game_elem['location_sequence'][i].color)]
            except:
                color_t = self.color_dict[self.game_elem['location_sequence']
                                          [i].color]
            for j in range(num_tiles_spanned_by_property):
                property_button = PropertyButton(text=label,
                                                 background_color=color_t,
                                                 pos_hint={
                                                     "x": pos_x,
                                                     "y": pos_y
                                                 },
                                                 size_hint=(each_block_size,
                                                            each_block_size))
                self.board_id.add_widget(property_button)
            pos_x += each_block_size

        for i in range(each_side_number_of_props * 3,
                       each_side_number_of_props * 4):
            label = (self.game_elem['location_sequence'][i].name).replace(
                ' ', '\n')
            num_tiles_spanned_by_property = self.game_elem[
                'location_sequence'][i].end_position - self.game_elem[
                    'location_sequence'][i].start_position
            try:
                color_t = self.color_dict[str(
                    self.game_elem['location_sequence'][i].color)]
            except:
                color_t = self.color_dict[self.game_elem['location_sequence']
                                          [i].color]
            for j in range(num_tiles_spanned_by_property):
                property_button = PropertyButton(text=label,
                                                 background_color=color_t,
                                                 pos_hint={
                                                     "x": pos_x,
                                                     "y": pos_y
                                                 },
                                                 size_hint=(each_block_size,
                                                            each_block_size))
                self.board_id.add_widget(property_button)
            pos_y -= each_block_size

        monopoly_display_button = Button(
            text="MONOPOLY\n PLAY-PAUSE",
            background_color=[0.96, 0.96, 0.86, 1],
            pos_hint={
                "x": 0.48,
                "y": 0.48
            },
            size_hint=(0.07, 0.07))
        self.board_id.add_widget(monopoly_display_button)
        monopoly_display_button.bind(on_release=self.toggle_button_func)

        self.goo_jail_chance_with_player = " "
        self.goo_jail_cc_with_player = " "

        get_out_of_jail_chestcard_button = Button(text="Community Chest Card" + \
                                                       self.goo_jail_cc_with_player,
                                                  background_color=[0.96, 0.96, 0.86, 1],
                                                  pos_hint={"x": 0.3, "top": 0.7},
                                                  size_hint=(0.12, 0.10))
        self.board_id.add_widget(get_out_of_jail_chestcard_button)

        get_out_of_jail_chancecard_button = Button(text="Chance Card" + \
                                                        self.goo_jail_chance_with_player,
                                                   background_color=[0.96, 0.96, 0.86, 1],
                                                   pos_hint={"x": 0.6, "top": 0.35},
                                                   size_hint=(0.12, 0.10))
        self.board_id.add_widget(get_out_of_jail_chancecard_button)

        self.goo_jail_list = []
        self.goo_jail_list.append(get_out_of_jail_chestcard_button)
        self.goo_jail_list.append(get_out_of_jail_chancecard_button)

        self.color_players_list = [[1, 0, 0, 1], [0, 1, 0, 1], [0, 0, 1, 1],
                                   [0.95, 0.95, 0, 1]]
        player_details_button_pos_y = 0.8
        self.player_detail_list = []
        for i in range(4):
            player_detail_button = Button(
                text=" ",
                background_color=self.color_players_list[i],
                pos_hint={
                    "x": 0,
                    "top": player_details_button_pos_y - i * 0.18
                },
                size_hint=(0.11, 0.16))
            self.board_id.add_widget(player_detail_button)
            self.player_detail_list.append(player_detail_button)

        player_details_heading_button = Button(
            text="Player details",
            background_color=[0.96, 0.96, 0.86, 1],
            pos_hint={
                "x": 0,
                "top": 0.87
            },
            size_hint=(0.11, 0.05))
        self.board_id.add_widget(player_details_heading_button)

        die_roll_heading_button = Button(
            text="Dice Roll",
            background_color=[0.96, 0.96, 0.86, 1],
            pos_hint={
                "x": 0.92,
                "top": 0.87
            },
            size_hint=(0.07, 0.05))
        self.board_id.add_widget(die_roll_heading_button)

        self.dice_holder_list = []
        for i in range(len(self.game_elem['die_sequence'])):
            die_roll_num = Button(text=" ",
                                  background_color=[0.96, 0.96, 0.86, 1],
                                  pos_hint={
                                      "x": 0.93,
                                      "top": 0.87 - (i + 1) * 0.10
                                  },
                                  size_hint=(0.05, 0.06))
            self.board_id.add_widget(die_roll_num)
            self.dice_holder_list.append(die_roll_num)

    def playing_the_game(self, *args):
        print("playing")
        self.start_stop_flag = True
        threading.Thread(target=self.simulate_game_instance).start()

    def toggle_button_func(self, *args):
        if self.start_stop_flag == False:
            self.start_stop_flag = True
        elif self.start_stop_flag == True:
            self.start_stop_flag = False
            print('PAUSING THE GAME.... CLICK MONOPOLY BUTTON TO RESUME GAME')

    def simulate_game_instance(self, history_log_file=None, np_seed=838885):
        """
        Simulate a game instance.
        :param game_elements: The dict output by set_up_board
        :param np_seed: The numpy seed to use to control randomness.
        :return: None
        """
        logger.debug("size of board " +
                     str(len(self.game_elem['location_sequence'])))
        np.random.seed(np_seed)
        np.random.shuffle(self.game_elem['players'])
        self.game_elem['seed'] = np_seed
        self.game_elem['card_seed'] = np_seed
        self.game_elem['choice_function'] = np.random.choice

        num_die_rolls = 0
        # game_elements['go_increment'] = 100 # we should not be modifying this here. It is only for testing purposes.
        # One reason to modify go_increment is if your decision agent is not aggressively trying to monopolize. Since go_increment
        # by default is 200 it can lead to runaway cash increases for simple agents like ours.

        logger.debug(
            'players will play in the following order: ' +
            '->'.join([p.player_name for p in self.game_elem['players']]))
        logger.debug('Beginning play. Rolling first die...')
        current_player_index = 0
        num_active_players = 4
        winner = None

        while num_active_players > 1:
            self.disable_history()
            if self.start_stop_flag == True:
                current_player = self.game_elem['players'][
                    current_player_index]
                while current_player.status == 'lost':
                    current_player_index += 1
                    current_player_index = current_player_index % len(
                        self.game_elem['players'])
                    current_player = self.game_elem['players'][
                        current_player_index]
                current_player.status = 'current_move'

                # pre-roll for current player + out-of-turn moves for everybody else,
                # till we get num_active_players skip turns in a row.

                skip_turn = 0
                if current_player.make_pre_roll_moves(
                        self.game_elem) == 2:  #2 is the special skip-turn code
                    skip_turn += 1
                out_of_turn_player_index = current_player_index + 1
                out_of_turn_count = 0
                while skip_turn != num_active_players and out_of_turn_count <= 200:
                    out_of_turn_count += 1
                    # print('checkpoint 1')
                    out_of_turn_player = self.game_elem['players'][
                        out_of_turn_player_index %
                        len(self.game_elem['players'])]
                    if out_of_turn_player.status == 'lost':
                        out_of_turn_player_index += 1
                        continue
                    oot_code = out_of_turn_player.make_out_of_turn_moves(
                        self.game_elem)
                    # add to game history
                    self.game_elem['history']['function'].append(
                        out_of_turn_player.make_out_of_turn_moves)
                    params = dict()
                    params['self'] = out_of_turn_player
                    params['current_gameboard'] = self.game_elem
                    self.game_elem['history']['param'].append(params)
                    self.game_elem['history']['return'].append(oot_code)

                    if oot_code == 2:
                        skip_turn += 1
                    else:
                        skip_turn = 0
                    out_of_turn_player_index += 1

                # now we roll the dice and get into the post_roll phase,
                # but only if we're not in jail.

                r = roll_die(self.game_elem['dies'], np.random.choice)
                self.dice_list = r
                for i in range(len(r)):
                    self.game_elem['die_sequence'][i].append(r[i])
                # add to game history
                self.game_elem['history']['function'].append(roll_die)
                params = dict()
                params['die_objects'] = self.game_elem['dies']
                params['choice'] = np.random.choice
                self.game_elem['history']['param'].append(params)
                self.game_elem['history']['return'].append(r)

                num_die_rolls += 1
                self.game_elem['current_die_total'] = sum(r)
                logger.debug('dies have come up ' + str(r))
                if not current_player.currently_in_jail:
                    check_for_go = True
                    move_player_after_die_roll(current_player, sum(r),
                                               self.game_elem, check_for_go)
                    # add to game history
                    self.game_elem['history']['function'].append(
                        move_player_after_die_roll)
                    params = dict()
                    params['player'] = current_player
                    params['rel_move'] = sum(r)
                    params['current_gameboard'] = self.game_elem
                    params['check_for_go'] = check_for_go
                    self.game_elem['history']['param'].append(params)
                    self.game_elem['history']['return'].append(None)

                    current_player.process_move_consequences(self.game_elem)
                    # add to game history
                    self.game_elem['history']['function'].append(
                        current_player.process_move_consequences)
                    params = dict()
                    params['self'] = current_player
                    params['current_gameboard'] = self.game_elem
                    self.game_elem['history']['param'].append(params)
                    self.game_elem['history']['return'].append(None)

                    # post-roll for current player. No out-of-turn moves allowed at this point.
                    current_player.make_post_roll_moves(self.game_elem)
                    # add to game history
                    self.game_elem['history']['function'].append(
                        current_player.make_post_roll_moves)
                    params = dict()
                    params['self'] = current_player
                    params['current_gameboard'] = self.game_elem
                    self.game_elem['history']['param'].append(params)
                    self.game_elem['history']['return'].append(None)

                else:
                    current_player.currently_in_jail = False  # the player is only allowed to skip one turn (i.e. this one)

                if current_player.current_cash < 0:
                    code = current_player.agent.handle_negative_cash_balance(
                        current_player, self.game_elem)
                    # add to game history
                    self.game_elem['history']['function'].append(
                        current_player.agent.handle_negative_cash_balance)
                    params = dict()
                    params['player'] = current_player
                    params['current_gameboard'] = self.game_elem
                    self.game_elem['history']['param'].append(params)
                    self.game_elem['history']['return'].append(code)
                    if code == -1 or current_player.current_cash < 0:
                        current_player.begin_bankruptcy_proceedings(
                            self.game_elem)
                        # add to game history
                        self.game_elem['history']['function'].append(
                            current_player.begin_bankruptcy_proceedings)
                        params = dict()
                        params['self'] = current_player
                        params['current_gameboard'] = self.game_elem
                        self.game_elem['history']['param'].append(params)
                        self.game_elem['history']['return'].append(None)

                        num_active_players -= 1
                        diagnostics.print_asset_owners(self.game_elem)
                        diagnostics.print_player_cash_balances(self.game_elem)

                        if num_active_players == 1:
                            for p in self.game_elem['players']:
                                if p.status != 'lost':
                                    winner = p
                                    p.status = 'won'
                else:
                    current_player.status = 'waiting_for_move'

                current_player_index = (current_player_index + 1) % len(
                    self.game_elem['players'])
                '''
                The following line determines the speed of your game visualization and game.
                0.1 is the default setting for this package.
                You can reduce it if you want the game to run faster or increase it to slow down the execution.
                '''
                time.sleep(0.05)
                self.update_board()

                if diagnostics.max_cash_balance(
                        self.game_elem
                ) > 300000:  # this is our limit for runaway cash for testing purposes only.
                    # We print some diagnostics and return if any player exceeds this.
                    diagnostics.print_asset_owners(self.game_elem)
                    diagnostics.print_player_cash_balances(self.game_elem)
                    return

        logger.debug('printing final asset owners: ')
        diagnostics.print_asset_owners(self.game_elem)
        logger.debug('number of dice rolls: ' + str(num_die_rolls))
        logger.debug('printing final cash balances: ')
        diagnostics.print_player_cash_balances(self.game_elem)

        if winner:
            logger.debug('We have a winner: ' + winner.player_name)

        return

    def disable_history(self):
        self.game_elem['history'] = dict()
        self.game_elem['history']['function'] = list()
        self.game_elem['history']['param'] = list()
        self.game_elem['history']['return'] = list()

    def update_board(self):
        self.canvas.after.clear()
        self.players = []
        pos_x = 0.9 - self.each_tile_size + 0.01
        pos_y = 0.11
        self.color_players_list = [[1, 0, 0, 1], [0, 1, 0, 1], [0, 0, 1, 1],
                                   [1, 1, 0, 1]]
        self.pos_x_list = []
        self.pos_y_list = []

        for i in range(len(self.dice_holder_list)):
            self.dice_holder_list[i].text = str(self.dice_list[i])

        for i in range(4):
            text_on_button = " "+ self.game_elem['players'][i].player_name + \
                            "\n Current Cash = " + str(self.game_elem['players'][i].current_cash) + \
                            "\n # of houses = " + str(self.game_elem['players'][i].num_total_houses) + \
                             "\n # of hotels = " + str(self.game_elem['players'][i].num_total_hotels)
            if (self.game_elem['players']
                [i].has_get_out_of_jail_community_chest_card == True):
                text_on_button = text_on_button + "\nGOO_Jail community card"
            if (self.game_elem['players'][i].has_get_out_of_jail_chance_card ==
                    True):
                text_on_button = text_on_button + "\nGOO_Jail chance card"

            self.player_detail_list[i].text = text_on_button
            self.obj_instr_player = InstructionGroup()
            self.obj_instr_player.add(
                Color(self.color_players_list[i][0],
                      self.color_players_list[i][1],
                      self.color_players_list[i][2],
                      self.color_players_list[i][3]))
            try:
                pos_x_n = int(self.game_elem['players'][i].current_position /
                              10)
                pos_y_n = int(self.game_elem['players'][i].current_position %
                              10)
            except:
                pos_x_n = 0
                pos_y_n = 0

            if (pos_x_n == 0):
                pos_x = (0.9 - self.each_tile_size +
                         0.01) - (pos_y_n * self.each_tile_size)
                pos_y = 0.11
            elif (pos_x_n == 2):
                pos_x = (0.9 - self.each_tile_size + 0.01) - (
                    self.num_tiles *
                    (self.each_tile_size)) + (pos_y_n * self.each_tile_size)
                pos_y = 0.11 + (self.num_tiles * self.each_tile_size)
            elif (pos_x_n == 1):
                pos_x = (0.9 - self.each_tile_size +
                         0.01) - (self.num_tiles * (self.each_tile_size))
                pos_y = 0.11 + (pos_y_n * self.each_tile_size)
            elif (pos_x_n == 3):
                pos_x = (0.9 - self.each_tile_size + 0.01)
                pos_y = 0.11 + (self.num_tiles * self.each_tile_size) - (
                    pos_y_n * self.each_tile_size)

            self.obj_instr_player.add(
                Ellipse(pos=((pos_x + i * 0.01) * Window.width,
                             pos_y * Window.height),
                        size=(10, 10)))
            self.players.append(self.obj_instr_player)
            self.pos_x_list.append(pos_x)
            self.pos_y_list.append(pos_y)
            self.canvas.after.add(self.obj_instr_player)

            count_house = 0
            count_hotel = 0
            if (self.game_elem['players'][i].assets) != None:
                self.player_props = []
                self.player_props_x = []
                self.player_props_y = []

                for k in range(len(list(self.game_elem['players'][i].assets))):
                    prop_name = list(
                        self.game_elem['players'][i].assets)[k].name
                    pos_prop = self.game_elem['location_objects'][
                        prop_name].start_position

                    self.obj_instr = InstructionGroup()
                    self.obj_instr.add(
                        Color(self.color_players_list[i][0],
                              self.color_players_list[i][1],
                              self.color_players_list[i][2],
                              self.color_players_list[i][3]))

                    each_side_num_tiles = self.num_tiles
                    side = 0
                    if pos_prop >= 0 and pos_prop < each_side_num_tiles:
                        side = 0
                    elif pos_prop >= each_side_num_tiles and pos_prop < 2 * each_side_num_tiles:
                        side = 1
                    elif pos_prop >= 2 * each_side_num_tiles and pos_prop < 3 * each_side_num_tiles:
                        side = 2
                    else:
                        side = 3
                    #prop_x = int(pos_prop / 10)
                    prop_y = pos_prop - side * each_side_num_tiles
                    pos_x_prop = 0
                    pos_y_prop = 0

                    if (side == 0):
                        pos_x_prop = 0.9 - self.each_tile_size + 0.01 - (
                            prop_y * self.each_tile_size)
                        pos_y_prop = 0.14
                    elif (side == 2):
                        pos_x_prop = 0.9 - self.each_tile_size + 0.01 - (
                            self.num_tiles *
                            (self.each_tile_size)) + (prop_y *
                                                      self.each_tile_size)
                        pos_y_prop = 0.14 + (self.num_tiles *
                                             self.each_tile_size)
                    elif (side == 1):
                        pos_x_prop = 0.9 - self.each_tile_size + 0.01 - (
                            self.num_tiles * (self.each_tile_size))
                        pos_y_prop = 0.14 + (prop_y * self.each_tile_size)
                    elif (side == 3):
                        pos_x_prop = 0.9 - self.each_tile_size + 0.01
                        pos_y_prop = 0.14 + (self.num_tiles *
                                             self.each_tile_size) - (
                                                 prop_y * self.each_tile_size)
                    self.obj_instr.add(
                        Rectangle(pos=(pos_x_prop * Window.width,
                                       pos_y_prop * Window.height),
                                  size=(12, 12)))
                    if list(self.game_elem['players']
                            [i].assets)[k].loc_class == 'real_estate':
                        if list(self.game_elem['players']
                                [i].assets)[k].num_houses > 0:
                            for m in range(
                                    list(self.game_elem['players'][i].assets)
                                [k].num_houses):
                                self.obj_instr.add(Color(1, 1, 1, 1))
                                self.obj_instr.add(
                                    Ellipse(
                                        pos=((pos_x_prop +
                                              (m + 1) * 0.01) * Window.width,
                                             pos_y_prop * Window.height),
                                        size=(12, 12)))
                                count_house += list(self.game_elem['players']
                                                    [i].assets)[k].num_houses

                        if list(self.game_elem['players']
                                [i].assets)[k].num_hotels > 0:
                            for m in range(
                                    list(self.game_elem['players'][i].assets)
                                [k].num_hotels):
                                self.obj_instr.add(Color(1, 0.1, 0.5, 1))
                                self.obj_instr.add(
                                    Ellipse(
                                        pos=((pos_x_prop +
                                              (m + 1) * 0.01) * Window.width,
                                             pos_y_prop * Window.height),
                                        size=(12, 12)))
                                count_hotel += list(self.game_elem['players']
                                                    [i].assets)[k].num_hotels

                    self.player_props.append(self.obj_instr)
                    self.player_props_x.append(pos_x_prop)
                    self.player_props_y.append(pos_y_prop)
                    self.canvas.after.add(self.obj_instr)
                    self.obj_instr_directory.append(self.obj_instr)
            self.bind(pos=self.update_rect, size=self.update_rect)

    def update_rect(self, *args):
        self.players[0].pos = (self.pos_x_list[0] * Window.width,
                               self.pos_y_list[0] * Window.height)
        self.players[1].pos = ((self.pos_x_list[1] + 0.01) * Window.width,
                               self.pos_y_list[0] * Window.height)
        self.players[2].pos = ((self.pos_x_list[2] + 0.02) * Window.width,
                               self.pos_y_list[1] * Window.height)
        self.players[3].pos = ((self.pos_x_list[3] + 0.03) * Window.width,
                               self.pos_y_list[3] * Window.height)
        for i in range(len(self.player_props)):
            self.player_props[i].children[2].pos = (self.player_props_x[i] *
                                                    Window.width,
                                                    self.player_props_y[i] *
                                                    Window.height)

    def popup_window(self, property_name):
        show = P()
        property_name_mod = property_name.replace("\n", " ")
        str_prop = "Name of the property: " + property_name_mod

        if self.game_elem['location_objects'][str(
                property_name_mod)].loc_class == 'real_estate':
            str_prop = str_prop + "\nCost: $" + str(self.game_elem['location_objects'][str(property_name_mod)].price) + \
                       "\nRent: $" + str(self.game_elem['location_objects'][str(property_name_mod)].rent) + \
                       "\nRent with 1 house: $" + str(
                self.game_elem['location_objects'][str(property_name_mod)].rent_1_house) + \
                       "\nRent with 2 house: $" + str(
                self.game_elem['location_objects'][str(property_name_mod)].rent_2_houses) + \
                       "\nRent with 3 house: $" + str(
                self.game_elem['location_objects'][str(property_name_mod)].rent_3_houses) + \
                       "\nRent with 4 house: $" + str(
                self.game_elem['location_objects'][str(property_name_mod)].rent_4_houses) + \
                       "\nRent with a hotel: $" + str(
                self.game_elem['location_objects'][str(property_name_mod)].rent_hotel) + \
                       "\nMortgage: $" + str(self.game_elem['location_objects'][str(property_name_mod)].mortgage) + \
                       "\nHouse cost: $" + str(
                self.game_elem['location_objects'][str(property_name_mod)].price_per_house)

        elif self.game_elem['location_objects'][str(
                property_name_mod)].loc_class == 'tax':
            str_prop = str_prop + "Pay as TAX $" + str(
                self.game_elem['location_objects'][str(
                    property_name_mod)].amount_due)

        elif self.game_elem['location_objects'][str(
                property_name_mod)].loc_class == 'railroad':
            str_prop = str_prop + "\nCost: $" + str(self.game_elem['location_objects'][str(property_name_mod)].price) + \
                       "\nMortgage: $" + str(self.game_elem['location_objects'][str(property_name_mod)].mortgage)

        elif self.game_elem['location_objects'][str(
                property_name_mod)].loc_class == 'utility':
            str_prop = str_prop + "\nCost: $" + str(self.game_elem['location_objects'][str(property_name_mod)].price) + \
                       "\nMortgage: $" + str(self.game_elem['location_objects'][str(property_name_mod)].mortgage) + \
                       "\n\nIf one UTILITY is owned, rent is 4 times\n amount shown on dice." + \
                       "\nIf both utilities are owned, rent is 10 times\n amount shown on dice."

        elif self.game_elem['location_objects'][str(
                property_name_mod)].loc_class == 'action':
            str_prop = "Pick a " + property_name_mod + " Card"

        elif self.game_elem['location_objects'][str(
                property_name_mod)].loc_class == 'do_nothing':
            pass

        show.ids.popup_id.text = str_prop
        popup_window = Popup(title=property_name_mod,
                             content=show,
                             size_hint=(None, None),
                             size=(400, 400))
        popup_window.open()
Пример #32
0
class TextureStack(Widget):
    """Several textures superimposed on one another, and possibly offset
    by some amount.

    In 2D games where characters can wear different clothes or hold
    different equipment, their graphics are often composed of several
    graphics layered on one another. This widget simplifies the
    management of such compositions.

    """
    texs = ListProperty()
    """Texture objects"""
    offxs = ListProperty()
    """x-offsets. The texture at the same index will be moved to the right
    by the number of pixels in this list.

    """
    offys = ListProperty()
    """y-offsets. The texture at the same index will be moved upward by
    the number of pixels in this list.

    """
    group = ObjectProperty()
    """My ``InstructionGroup``, suitable for addition to whatever ``canvas``."""

    def _get_offsets(self):
        return zip(self.offxs, self.offys)

    def _set_offsets(self, offs):
        offxs = []
        offys = []
        for x, y in offs:
            offxs.append(x)
            offys.append(y)
        self.offxs, self.offys = offxs, offys

    offsets = AliasProperty(
        _get_offsets,
        _set_offsets,
        bind=('offxs', 'offys')
    )
    """List of (x, y) tuples by which to offset the corresponding texture."""
    _texture_rectangles = DictProperty({})
    """Private.

    Rectangle instructions for each of the textures, keyed by the
    texture.

    """

    def __init__(self, **kwargs):
        """Make triggers and bind."""
        kwargs['size_hint'] = (None, None)
        self.translate = Translate(0, 0)
        self.group = InstructionGroup()
        super().__init__(**kwargs)
        self.bind(offxs=self.on_pos, offys=self.on_pos)

    def on_texs(self, *args):
        """Make rectangles for each of the textures and add them to the canvas."""
        if not self.canvas or not self.texs:
            Clock.schedule_once(self.on_texs, 0)
            return
        texlen = len(self.texs)
        # Ensure each property is the same length as my texs, padding
        # with 0 as needed
        for prop in ('offxs', 'offys'):
            proplen = len(getattr(self, prop))
            if proplen > texlen:
                setattr(self, prop, getattr(self, prop)[:proplen-texlen])
            if texlen > proplen:
                propval = list(getattr(self, prop))
                propval += [0] * (texlen - proplen)
                setattr(self, prop, propval)
        self.group.clear()
        self._texture_rectangles = {}
        w = h = 0
        (x, y) = self.pos
        self.translate.x = x
        self.translate.y = y
        self.group.add(PushMatrix())
        self.group.add(self.translate)
        for tex, offx, offy in zip(self.texs, self.offxs, self.offys):
            rect = Rectangle(
                pos=(offx, offy),
                size=tex.size,
                texture=tex
            )
            self._texture_rectangles[tex] = rect
            self.group.add(rect)
            tw = tex.width + offx
            th = tex.height + offy
            if tw > w:
                w = tw
            if th > h:
                h = th
        self.size = (w, h)
        self.group.add(PopMatrix())
        self.canvas.add(self.group)

    def on_pos(self, *args):
        """Translate all the rectangles within this widget to reflect the widget's position.

        """
        (x, y) = self.pos
        self.translate.x = x
        self.translate.y = y

    def clear(self):
        """Clear my rectangles and ``texs``."""
        self.group.clear()
        self._texture_rectangles = {}
        self.texs = []
        self.size = [1, 1]

    def insert(self, i, tex):
        """Insert the texture into my ``texs``, waiting for the creation of
        the canvas if necessary.

        """
        if not self.canvas:
            Clock.schedule_once(
                lambda dt: self.insert(i, tex), 0)
            return
        self.texs.insert(i, tex)

    def append(self, tex):
        """``self.insert(len(self.texs), tex)``"""
        self.insert(len(self.texs), tex)

    def __delitem__(self, i):
        """Remove a texture and its rectangle"""
        tex = self.texs[i]
        try:
            rect = self._texture_rectangles[tex]
            self.canvas.remove(rect)
            del self._texture_rectangles[tex]
        except KeyError:
            pass
        del self.texs[i]

    def __setitem__(self, i, v):
        """First delete at ``i``, then insert there"""
        if len(self.texs) > 0:
            self._no_upd_texs = True
            self.__delitem__(i)
            self._no_upd_texs = False
        self.insert(i, v)

    def pop(self, i=-1):
        """Delete the texture at ``i``, and return it."""
        return self.texs.pop(i)
Пример #33
0
 def _gl_setup(self):
     self.drip_texture = CoreImage("resources/images/drop.png", mipmap=True).texture
     self.drips_instruction = InstructionGroup()
     self.model_instruction = InstructionGroup()
     print(self.canvas.children)
Пример #34
0
class Display(Widget):
    axis_resolution = NumericProperty(10)
    axis_max_value = NumericProperty(10)
    axis_x_marker_size = (4, 8)
    axis_y_marker_size = (8, 4)
    last_inside = BooleanProperty(False)
    objects = ListProperty([])
    robots = ListProperty([])
    tasks = ListProperty([])
    mu_tasks = ListProperty([])
    selected_object = ObjectProperty(None)
    is_object_selected = BooleanProperty(False)
    dummy_object = DisplayObject('Dummy',name='Dummy',local_pos=(math.inf, math.inf), \
                                                        z_pos = -1,\
                                                        default_size=(0, 0))
    def __init__(self, **kwargs):
        super(Display, self).__init__(**kwargs)
        self.rect_x_ig = InstructionGroup()
        self.rect_x_ig.add(Color(1,1,1))
        self.rect_x = Rectangle(size=(self.width,2), pos=(self.center_x - self.width/2, self.center_y-1))
        self.rect_x_ig.add(self.rect_x)
        self.canvas.add(self.rect_x_ig)

        self.rect_y_ig = InstructionGroup()
        self.rect_y_ig.add(Color(1,1,1))
        self.rect_y = Rectangle(size=(2,self.height), pos=(self.center_x - 1, self.center_y-self.height/2))
        self.rect_y_ig.add(self.rect_y)
        self.canvas.add(self.rect_y_ig)

        values = range(2*self.axis_resolution+1)
        values_x = list(map(lambda x: self._calculate_axis_value(x, self.axis_resolution, self.width), values))
        values_y = list(map(lambda x: self._calculate_axis_value(x, self.axis_resolution, self.height), values))
        self.rects_x = []
        self.rects_y = []
        self.rects_x_ig = []
        self.rects_y_ig = []
        for value_x in values_x:
                self.rects_x += [Rectangle(size=self.axis_x_marker_size, pos=self._calculate_axis_x_marker_pos(value_x, self))]
                self.rects_x_ig += [self.rects_x[-1]]
                self.canvas.add(self.rects_x_ig[-1])
        for value_y in values_y:
                self.rects_y += [Rectangle(size=self.axis_y_marker_size, pos=self._calculate_axis_y_marker_pos(value_y, self))]
                self.rects_y_ig += [self.rects_y[-1]]
                self.canvas.add(self.rects_y_ig[-1])
        self.bind(size=self._update_rect, pos=self._update_rect, axis_resolution=self._update_rect, axis_max_value=self._update_rect)
        Window.bind(mouse_pos=self.on_mouse_pos)
        self.coordinate_label = Label(text='0,0')

    
    def add_robot(self, new_robot):
        name_exists = any([new_robot.name == robot.name for robot in self.objects if robot.obj_type is 'Robot'])
        if not name_exists:
            self.robots.append(new_robot)
            robot_representation = RobotRepresentation(new_robot, \
                                                        name=new_robot.name, \
                                                        local_pos=new_robot.position, \
                                                        z_pos = len(self.objects),\
                                                        default_size=(RobotRepresentation.default_width, RobotRepresentation.default_height))
            self.add_display_object(robot_representation)

    def add_task(self, new_task):
        name_exists = any([new_task.name == task.name for task in self.objects if task.obj_type is 'Task'])
        if not name_exists:
            self.tasks.append(new_task)
            for mu_task in new_task.mu_tasks:
                self.mu_tasks.append(mu_task)
                mu_task_representation = MuTaskRepresentation(name=new_task.name+','+mu_task.name, 
                    task=new_task,
                    mu_task=mu_task,
                    local_pos=mu_task.position,
                    z_pos = len(self.objects),
                    default_size=(MuTaskRepresentation.default_width, MuTaskRepresentation.default_height))
                self.add_display_object(mu_task_representation)
            
    def clear_display(self):
        for obj in self.objects:
            self.remove_widget(obj)
        self.objects = []
        self.robots.clear()
        self.mu_tasks.clear()
        self.tasks.clear()

    def add_display_object(self, new_object):
        self.objects.append(new_object)
        self.add_widget(new_object)
        new_object.pos = new_object.calculate_canvas_position(self.center, self.size, self.axis_max_value)
    
    @staticmethod
    def _calculate_axis_value(original_value, axis_resolution, axis_total_size):
        return ((original_value-axis_resolution)/axis_resolution)*(axis_total_size/2)
    
    def _calculate_axis_x_marker_pos(self, marker_value, reference):
        return reference.center_x+marker_value-(self.axis_x_marker_size[0])/2, reference.center_y-(self.axis_x_marker_size[1])/2

    def _calculate_axis_y_marker_pos(self, marker_value, reference):
        return reference.center_x-(self.axis_y_marker_size[0])/2, reference.center_y+marker_value-(self.axis_y_marker_size[1])/2

    def _update_rect(self, instance, value):
        values = range(2*self.axis_resolution+1)
        values_x = list(map(lambda x: self._calculate_axis_value(x, self.axis_resolution, self.width), values))
        values_y = list(map(lambda x: self._calculate_axis_value(x, self.axis_resolution, self.height), values))
        self.rect_x.size = instance.width, 2
        self.rect_x.pos = instance.center_x - instance.width/2, instance.center_y-1
        self.rect_y.size = 2, self.height
        self.rect_y.pos = self.center_x - 1, self.center_y-self.height/2
        for value_x, rect  in zip(values_x, self.rects_x):
            rect.pos = self._calculate_axis_x_marker_pos(value_x, instance)
            rect.size = self.axis_x_marker_size
        for value_y,rect  in zip(values_y, self.rects_y):
            rect.pos = self._calculate_axis_y_marker_pos(value_y, instance)
            rect.size = self.axis_y_marker_size
        
        if len(self.rects_x) > len(values_x):
            for i in range(len(self.rects_x), len(values_x), -1):
                self.canvas.remove(self.rects_x_ig[i-1])
                self.rects_x.pop()
                self.rects_x_ig.pop()
        elif len(self.rects_x) < len(values_x):
                for i in range(len(self.rects_x), len(values_x)):
                    self.rects_x += [Rectangle(size=self.axis_x_marker_size, pos=self._calculate_axis_x_marker_pos(values_x[i], self))]
                    self.rects_x_ig += [self.rects_x[-1]]
                    self.canvas.add(self.rects_x_ig[-1])
        
        if len(self.rects_y) > len(values_y):
            for i in range(len(self.rects_y), len(values_y), -1):
                self.canvas.remove(self.rects_y_ig[i-1])
                self.rects_y.pop()
                self.rects_y_ig.pop()
        elif len(self.rects_y) < len(values_y):
                for i in range(len(self.rects_y), len(values_y)):
                    self.rects_y += [Rectangle(size=self.axis_y_marker_size, pos=self._calculate_axis_y_marker_pos(values_y[i], self))]
                    self.rects_y_ig += [self.rects_y[-1]]
                    self.canvas.add(self.rects_y_ig[-1])
        for obj in self.objects:
            obj.pos = obj.calculate_canvas_position(instance.center, instance.size, self.axis_max_value)
    
    def on_touch_down(self, value):
        pos = value.pos
        if not self.collide_point(*self.to_widget(*pos)):
            return
        candidates = [ candidate for candidate in self.objects if candidate.collide_point(*self.to_widget(*pos))]
        top_candidate = max(candidates, key=lambda x: x.z_pos, default=None)
        if top_candidate is not None:
            # if not self.is_object_selected or (self.is_object_selected and not top_candidate.collide_widget(self.selected_object)):
            if not self.is_object_selected or (self.is_object_selected and self.selected_object not in candidates):
                self.selected_object = top_candidate
                self.is_object_selected = True
        else:
            if self.is_object_selected:
                self.is_object_selected = False
                self.selected_object = self.dummy_object
        
    def on_touch_move(self, value):
        pos = value.pos
        if not self.collide_point(*self.to_widget(*pos)):
            return
        if self.is_object_selected:
            self.selected_object.move_canvas(value.pos)

    def on_object_menu_selected(self, instance, value):
        if self.is_object_selected:
            if self.selected_object == value:
                return
            else:   
                options = [ obj for obj in self.objects if obj == value]
                if len(options) == 1:
                    self.selected_object = options[0]
                else:
                    self.selected_object = self.dummy_object
                    self.is_object_selected = False
        else:
            options = [ obj for obj in self.objects if obj == value]
            if len(options) == 1:
                self.selected_object = options[0]
                self.is_object_selected = True
            else:
                self.selected_object = self.dummy_object
                self.is_object_selected = False

    def on_mouse_pos(self, *args):
        if not self.get_root_window():
            return
        pos = args[1]
        inside = self.collide_point(*self.to_widget(*pos))
        if inside:
            self.coordinate_label.pos = pos
            local_pos = self._calculate_axis_x_marker_pos(0, self)
            local_pos = round((pos[0] - self.center_x)*(self.axis_max_value)/(self.width/2),2), round((pos[1] - self.center_y)*(self.axis_max_value)/(self.height/2), 2)
            self.coordinate_label.text = str(local_pos)
            self.coordinate_label.size = self.coordinate_label.texture_size
        if self.last_inside != inside:
            if inside:
                self.add_widget(self.coordinate_label)
            else:
                self.remove_widget(self.coordinate_label)
            self.last_inside = inside
Пример #35
0
class PrinterAnimation(RelativeLayout):
    padding = NumericProperty(40)

    printer_actual_dimensions = ListProperty([10, 10, 80])
    printer_current_actual_height = NumericProperty(0.0)

    print_area_height = NumericProperty(1)
    print_area_width = NumericProperty(1)
    print_area_left = NumericProperty(0)
    print_area_bottom = NumericProperty(40)

    container_padding = NumericProperty(0)
    container_left = NumericProperty(0)
    container_width = NumericProperty(0)
    container_bottom = NumericProperty(0)
    container_height = NumericProperty(0)

    laser_size = ListProperty([40, 40])

    resin_height = NumericProperty(20)
    water_height = NumericProperty(20)

    scale = NumericProperty(1.0)

    resin_color = ListProperty([0.0, 0.8, 0.0, 0.6])
    water_color = ListProperty([0.2, 0.2, 1.0, 0.6])
    container_color = ListProperty([1.0, 1.0, 1.0, 1.0])
    laser_color_edge2 = ListProperty([0.0, 0.0, 0.5, 1.0])
    laser_color_edge = ListProperty([0.0, 0.0, 1.0, 1.0])
    laser_color = ListProperty([0.7, 1.0, 1.0, 1.0])

    drip_history = ListProperty()
    laser_points = ListProperty()

    middle_x = NumericProperty(52)

    laser_pos = NumericProperty(60)
    laser_speed = NumericProperty(1)
    refresh_rate = NumericProperty(1.0)

    def __init__(self, **kwargs):
        super(PrinterAnimation, self).__init__(**kwargs)
        self.drip_time_range = 5
        self.waiting_for_drips = True
        self.refresh_rate = App.get_running_app().refresh_rate
        self._gl_setup()
        self.axis_history = []
        self.drips = 0

        self.line_x = []
        self.line_y = []
        self.last_height = 0.0
        self.min_height = 0.0
        self.last_x_min = 0.0
        self.last_x_max = 1.0
        self.is_on_canvas = False

    def on_printer_actual_dimensions(self, instance, value):
        self.min_height = self.printer_actual_dimensions[2] / 400.0
        self.on_size(None)

    def _gl_setup(self):
        self.drip_texture = CoreImage("resources/images/drop.png", mipmap=True).texture
        self.drips_instruction = InstructionGroup()
        self.model_instruction = InstructionGroup()
        print(self.canvas.children)
        # self.canvas.add(self.drips_instruction)
        # self.canvas.add(self.model_instruction)

    def on_size(self, *largs):
        bounds_y = (self.height * 0.7) - self.resin_height
        bounds_x = self.width - (self.padding * 2)
        printer_x = self.printer_actual_dimensions[0]
        printer_y = self.printer_actual_dimensions[2]
        self.laser_pos = self.width / 2

        self.scale = min(bounds_y / printer_y, bounds_x / printer_x)
        Logger.info("Scale: {}".format(self.scale))
        self.print_area_width = printer_x * self.scale
        self.print_area_height = printer_y * self.scale

    def redraw(self, key):
        self._draw_drips()
        self._draw_laser()
        self._draw_model()
        if not self.is_on_canvas:
            self.canvas.insert(4, self.drips_instruction)
            self.canvas.insert(4, self.model_instruction)
            self.is_on_canvas = True

        Clock.unschedule(self.redraw)
        Clock.schedule_once(self.redraw, self.refresh_rate)

    def reset(self):
        self.axis_history = []
        self.line_x = []
        self.line_y = []
        self.last_height = 0
        self.min_height = 0.0
        self.laser_points = []
        self.drip_history = []
        self.waiting_for_drips = True
        self.printer_current_actual_height = 0
        self.redraw('')
        Clock.unschedule(self.redraw)

    def animation_start(self, *args):
        Clock.unschedule(self.redraw)
        self.axis_history = []
        self.line_x = []
        self.line_y = []
        self.last_height = 0
        self.min_height = 0.0
        self.laser_points = []
        self.drip_history = []
        Clock.schedule_once(self.redraw, self.refresh_rate)

    def animation_stop(self):
        Clock.unschedule(self.redraw)
        self.axis_history = []
        self.line_x = []
        self.line_y = []
        self.last_height = 0
        self.min_height = 0.0
        self.laser_points = []
        self.drip_history = []

    def _draw_drips(self):
        self.drips_instruction.clear()
        self.drips_instruction.add(Color(1, 1, 1, 1))
        top = time.time()
        bottom = top - self.drip_time_range
        drips_in_history = len(self.drip_history)
        for (index, drip_time) in zip(range(drips_in_history, 0, -1), self.drip_history):
            if drip_time > bottom:
                time_ago = top - drip_time
                y_pos_percent = (self.drip_time_range - time_ago) / self.drip_time_range
                drip_pos_y = (self.height * y_pos_percent) + self.padding
                xoff = 10 + math.sin((len(self.drip_history) - index) / (2 * math.pi)) * 20
                self.drips_instruction.add(Rectangle(size=[12, 16], pos=[self.print_area_left + xoff, drip_pos_y], texture=self.drip_texture))

    def _draw_laser(self):
        if self.waiting_for_drips:
            self.laser_points = []
        else:
            x_min = self.print_area_left + (self.last_x_min * self.print_area_width)
            x_max = self.print_area_left + (self.last_x_max * self.print_area_width)
            if (self.laser_pos >= x_max):
                self.laser_pos = x_max
                self.laser_speed = abs(self.laser_speed) * -1
            if (self.laser_pos <= x_min):
                self.laser_pos = x_min
                self.laser_speed = abs(self.laser_speed)

            self.laser_pos += self.laser_speed
            laser_x = self.laser_pos
            self.laser_points = [self.middle_x, self.height - self.padding,
                                 laser_x,          self.water_height + self.print_area_bottom + self.resin_height]

    def _draw_model(self):
            if self.axis_history:
                model_height = self.axis_history[-1][2]
                if model_height > (self.last_height + self.min_height) or not self.line_x:
                    x1, y1, x2, y2 = self._get_pixels(self.axis_history[-1])
                    self.last_x_min = x1
                    self.last_x_max = x2

                    self.line_x.insert(0, x1)
                    self.line_x.append(x2)
                    self.line_y.insert(0, y1)
                    self.line_y.append(y2)
                    self.last_height = model_height

                    points = []
                    for idx in range(0, len(self.line_x)):
                        x = int(self.print_area_left + (self.line_x[idx] * self.print_area_width))
                        y = int(self.print_area_bottom + self.resin_height + (self.line_y[idx] * self.print_area_height)) - 2
                        points.append(x)
                        points.append(y)
                    self.model_instruction.clear()
                    self.model_instruction.add(Color(rgba=(1.0, 0.0, 0.0, 1.0)))
                    self.model_instruction.add(Line(points=points, width=2, close=True))
            else:
                self.model_instruction.clear()

    def _get_pixels(self, data):
        pixel_height = data[2] / self.printer_actual_dimensions[2]
        pixel_pos_min = (data[0][0] + (self.printer_actual_dimensions[1] / 2.0)) / self.printer_actual_dimensions[1]
        pixel_pos_max = (data[0][1] + (self.printer_actual_dimensions[1] / 2.0)) / self.printer_actual_dimensions[1]
        return [pixel_pos_min, pixel_height, pixel_pos_max, pixel_height]
Пример #36
0
    def __init__(self, width, height, canvas, ac, eye_pos, eye_angle):
        super(DisplayController, self).__init__()
        self.width = width
        self.height = height
        self.canvas = canvas
        self.eye_pos = eye_pos
        self.eye_angle = eye_angle
        self.ac = ac

        self.canvas.shader.source = resource_find('data/simple.glsl')

        self.all_notes = []
        self.future_notes = {}
        self.past_notes = {}
        self.ticks = []

        # self.planes = range(0, 10 * config['PLANE_SPACING'], config['PLANE_SPACING'])
        self.planes = []
        self.lines = []

        self.past_displays = InstructionGroup()
        self.future_displays = InstructionGroup()
        self.plane_displays = InstructionGroup()
        self.line_displays = InstructionGroup()

        self.fixed_x = Translate(0, 0, 0)
        self.fixed_y = Translate(0, 0, 0)
        self.fixed_z = Translate(0, 0, 0)
        self.fixed_azi = Rotate(origin=(0, 0, 0), axis=(0, 1, 0))
        self.fixed_ele = Rotate(origin=(0, 0, 0), axis=(1, 0, 0))

        self.alpha_callback = Callback(self.alpha_sample_callback)
        self.disable_alpha_callback = Callback(self.disable_alpha_sample_callback)
        self.alpha_instruction = InstructionGroup()
        self.alpha_disable_instruction = InstructionGroup()
        self.alpha_sample_enable = False

        self.canvas.add(Callback(self.setup_gl_context))
        self.canvas.add(self.alpha_instruction)
        self.canvas.add(PushMatrix())
        self.canvas.add(UpdateNormalMatrix())

        
        
        self.canvas.add(PushMatrix())
        self.canvas.add(self.fixed_z)
        self.canvas.add(self.line_displays)
        self.canvas.add(PopMatrix())

        self.canvas.add(PushMatrix())
        self.canvas.add(self.past_displays)
        self.canvas.add(self.future_displays)
        self.canvas.add(PopMatrix())

        self.canvas.add(PushMatrix())
        # self.canvas.add(self.fixed_x)
        # self.canvas.add(self.fixed_y)
        self.canvas.add(self.plane_displays)
        self.canvas.add(PopMatrix())

        # self.canvas.add(PushMatrix())
        # self.canvas.add(self.fixed_x)
        # self.canvas.add(self.fixed_y)
        # self.canvas.add(self.fixed_z)
        # self.canvas.add(Plane(-config['SELF_PLANE_DISTANCE'], size=0.1, color=(0x20/255., 0xD8/255., 0xE9/255.), tr=0.2))
        # self.canvas.add(PopMatrix())

        self.canvas.add(PopMatrix())
        self.canvas.add(self.alpha_disable_instruction)
        self.canvas.add(Callback(self.reset_gl_context))

        self.draw_planes()
Пример #37
0
class LinePlot(Widget):

    viewport = ListProperty(None)
    line_width = NumericProperty(5.)
    line_color = ListProperty([0,.8,1])
    border_width = NumericProperty(5)
    border_color = ListProperty([.3,.3,.3])
    flattened_points = ListProperty(None)
    tick_distance_x = NumericProperty(None)
    tick_distance_y = NumericProperty(None)
    tick_color = ListProperty([.3,.3,.3])
    select_circle = ListProperty([0,0,0])

    def __init__(self, points, **kwargs):
        # calculate some basic information about the data
        self.points = points
        self.points_x = zip(*points)[0]
        self.points_y = zip(*points)[1]

        # if we could figure out how to draw an arbitrary number of ticks in kv, this would be cleaner
        self.ticks = InstructionGroup()
        self.tick_translate = Translate()
        

        super(LinePlot, self).__init__(**kwargs)
        self.canvas.insert(0, self.ticks)
        self.viewport = (min(self.points_x), min(self.points_y), max(self.points_x), max(self.points_y))
    
    # recalculate viewport when size changes
    def on_size(self, instance, value):
        self.on_viewport(None, self.viewport)

    def on_pos(self, instance, value):
        self.tick_translate.xy = self.x, self.y
        
    def on_viewport(self, instance, value):
        if value is None or len(value) != 4: return
        print value
        self.vp_width_convert = float(self.width)/(value[2] - value[0])
        self.vp_height_convert = float(self.height)/(value[3] - value[1])

        # calculate the actual display points based on the viewport and self.size
        self.display_points = [self.to_display_point(*p) for p in self.points if value[0] <= p[0] <= value[2] and value[1] <= p[1] <= value[3]]
        self.flattened_points = [item for sublist in self.display_points for item in sublist]
        self.draw_ticks()

    # it would be real nice if we could figure out how to do this in kv
    def draw_ticks(self):
        self.ticks.clear()
        self.ticks.add(Color(*self.tick_color, mode='rgb'))
        self.ticks.add(PushMatrix())
        self.ticks.add(self.tick_translate)
        if self.tick_distance_x is not None:
            first_x_tick = self.tick_distance_x*(int(self.viewport[0]/self.tick_distance_x) + 1)
            for x in drange(first_x_tick, self.viewport[2], self.tick_distance_x):
                start = self.to_display_point(x, self.viewport[1])
                stop = self.to_display_point(x, self.viewport[3])
                self.ticks.add(Line(points=[start[0], start[1], stop[0], stop[1]]))

        if self.tick_distance_y is not None:
            first_y_tick = self.tick_distance_y*(int(self.viewport[1]/self.tick_distance_y) + 1)
            for y in drange(first_y_tick, self.viewport[3], self.tick_distance_y):
                start = self.to_display_point(self.viewport[0], y)
                stop = self.to_display_point(self.viewport[2], y)
                self.ticks.add(Line(points=[start[0], start[1], stop[0], stop[1]]))
        
        self.ticks.add(PopMatrix())

    def to_display_point(self, x, y):
        return (self.vp_width_convert*(x-self.viewport[0]), self.vp_height_convert*(y-self.viewport[1]))

    def select_point(self, x, y):
        # get point from self.displaypoints that is closest to x
        
        distances = [abs((x - self.x) - d[0]) for d in self.display_points]
        idx = min(xrange(len(distances)),key=distances.__getitem__)
        self.select_circle = [self.display_points[idx][0], self.display_points[idx][1], 20]
        return self.points[idx]




    def to_xy(self, x, y):
        xt = (x - self.x)/self.vp_width_convert+self.viewport[0]
        yt = (y - self.y)/self.vp_height_convert+self.viewport[1]
        return (xt, yt)
Пример #38
0
    def drawCrossLine(self, aIndex):
        """
        繪製十字線
        """
        dataNum = len(self.dataDict)
        if dataNum == 0:
            return
        if aIndex >= self.dispMax:
            index = self.dispMax - 1
        elif aIndex >= self.dispNum:            
            index = self.dispNum - 1
        elif aIndex < 0:
            index = 0
        else:
            index = aIndex
        self.crossLineIndex = index
        if self.infoFunc == None:
            self._showInfo(index)
        else:
            aKey = self.keyList[self.scopeIdx[0] + index]
            aValue = self.dataDict.get(aKey)
            self.infoFunc({"TechType":self.techType, "TD":aKey, "Value":aValue})
        
        if self.isDrawCrossLine == False:
            return
        groupStr = self.instGroup + "cross_line"
        self.canvas.remove_group(groupStr)        

        color = Color()
        color.rgba = self.CROSS_LINE_COLOR
        
        instg = InstructionGroup(group=groupStr)
        instg.add(color)
        x1 = self.chartPos[0] + (index + 1) * (self.tickWide + self.tickGap) - self.backGap
        y1 = self.chartPos[1]
        x2 = x1
        y2 = self.chartPos[1] + self.chartSize[1]
        instg.add(Line(points=(x1, y1, x2, y2), width=1))
        self.canvas.add(instg)
        
        aKey = self.keyList[self.scopeIdx[0] + index]
        aValue = self.dataDict.get(aKey)        
        
        instg = InstructionGroup(group=groupStr)
        instg.add(color)
        x1 = self.chartPos[0]
        y1 = self.chartPos[1] + self.baseYPos + aValue * self.yscale
        x2 = self.chartPos[0] + self.chartSize[0]
        y2 = y1
        instg.add(Line(points=(x1, y1, x2, y2), width=1))
        self.canvas.add(instg)
Пример #39
0
 def drawCordInfo(self):
     
     # 100-Start: 標示y軸資訊 
     
     initStepUp = 1
     if self.maxNum < 8:
         initStepUp = 1
     elif self.maxNum < 10:
         initStepUp = 2
     else:
         initStepUp = int(self.maxNum / 5)
     
     x0 = self.pos[0] + ((self.width - self.shift_left - self.shift_right) / 2) + self.shift_left - 30
     y0 = self.pos[1] + self.height - self.shift_top + 5           
     alabel = SCordLabel(pos=(x0,y0),size_hint=(None,None))
     alabel.width = 60
     alabel.height = 20        
     alabel.text = "(X軸:獲利率,Y軸:交易次數)"
     alabel.color = self.CORD_INFO_COLOR
     self.add_widget(alabel)
         
     frameColor = Color()
     frameColor.rgba = self.FRAME_COLOR
     stepUp = initStepUp
     while(stepUp <= self.maxNum):
         instg = InstructionGroup(group="frame")            
         instg.add(frameColor)            
         x1 = self.center_xpos - 5
         y1 = int(self.pos[1] + self.shift_bottom + stepUp * self.yscale)
         x2 = self.center_xpos
         y2 = int(self.pos[1] + self.shift_bottom + stepUp * self.yscale)
         instg.add(Line(points=(x1, y1, x2, y2), width=1))        
         self.canvas.add(instg)
         
         x0 = self.center_xpos - self.ycordWidth
         y0 = int(self.pos[1] + self.shift_bottom + stepUp * self.yscale) - 10
         alabel = SCordLabel(pos=(x0,y0),size_hint=(None,None))
         alabel.width = 36
         alabel.height = 20
         alabel.text = str(stepUp)
         alabel.color = self.CORD_INFO_COLOR
         self.add_widget(alabel)
         stepUp += initStepUp
     # 100-End.
     
     # 200-Start: 標示x軸資訊 
     center_pos = int(self.pillarPoint / 2)
     remainder = None
     for i in range(self.min_tickNum, self.max_tickNum + 1):
         remainder = i % 10
         if remainder != 0 and i != -1 and i != 0 and i != 1 and i != self.min_tickNum and i != self.max_tickNum:
             continue
         index = i - self.min_tickNum
         if i >= 0:
             tmp = self.max_tickNum - i
             if tmp <= 8 and i != self.max_tickNum:
                 continue
             if i == 0:
                 shift_xpos = self.ycordWidth
             else:
                 shift_xpos = self.ycordWidth * 2
         else:
             if index <= 8 and i != self.min_tickNum:
                 continue
             shift_xpos = 0            
         instg = InstructionGroup(group="frame")            
         instg.add(frameColor)            
         x1 = int(self.pos[0] + self.shift_left + index * self.pillarSumPoint + center_pos + shift_xpos)
         y1 = int(self.pos[1] + self.shift_bottom)
         x2 = int(self.pos[0] + self.shift_left + index * self.pillarSumPoint + center_pos + shift_xpos)
         y2 = int(self.pos[1] + self.shift_bottom - 5)
         instg.add(Line(points=(x1, y1, x2, y2), width=1))        
         self.canvas.add(instg)
         
         x0 = int(self.pos[0] + self.shift_left + index * self.pillarSumPoint + center_pos + shift_xpos - 18)
         y0 = int(self.pos[1] + self.shift_bottom) - 25
         alabel = SCordLabel(pos=(x0,y0),size_hint=(None,None))
         alabel.width = 36
         alabel.height = 20
         if i == self.min_tickNum:
             alabel.text = "<=" + str(i) + "%"
         elif i == self.max_tickNum:
             alabel.text = ">=" + str(i) + "%"
         else:
             alabel.text = str(i) + "%"
         alabel.color = self.CORD_INFO_COLOR
         self.add_widget(alabel)
Пример #40
0
    def _drawLine(self, aDict, dispIdx, isLastFlag):
        """
        
        """
        groupStr = self.instGroup
        if isLastFlag == True:
            groupStr += "_lastData"
        else:
            groupStr += "_curvData"
        instg = InstructionGroup(group=groupStr)
        color = Color()
        color.rgba = self.KLINE_COLOR
        instg.add(color)
        #(self.tickWide + self.tickGap)代表顯示一筆資料,在x軸方向所需的總點數
        x1 = self.chartPos[0] + (dispIdx + 1) * (self.tickWide +
                                                 self.tickGap) - self.backGap
        y1 = self.chartPos[1] + (aDict.get("HP") -
                                 self.lowestValue) * self.yscale
        x2 = x1
        y2 = self.chartPos[1] + (aDict.get("LP") -
                                 self.lowestValue) * self.yscale
        instg.add(Line(points=(x1, y1, x2, y2), width=1))
        self.canvas.add(instg)

        instg = InstructionGroup(group=groupStr)
        color = Color()

        openPrice = aDict.get("OP")
        closePrice = aDict.get("CP")
        if closePrice > openPrice:
            color.rgba = self.SOLID_COLOR
            instg.add(color)
            x1 = self.chartPos[0] + dispIdx * (self.tickWide +
                                               self.tickGap) + self.tickGap
            y1 = self.chartPos[1] + (openPrice -
                                     self.lowestValue) * self.yscale
            instg.add(
                Rectangle(pos=(x1, y1),
                          size=(self.tickWide,
                                (closePrice - openPrice) * self.yscale)))
        elif closePrice < openPrice:
            color.rgba = self.VIRTUAL_COLOR
            instg.add(color)
            x1 = self.chartPos[0] + dispIdx * (self.tickWide +
                                               self.tickGap) + self.tickGap
            y1 = self.chartPos[1] + (closePrice -
                                     self.lowestValue) * self.yscale
            instg.add(
                Rectangle(pos=(x1, y1),
                          size=(self.tickWide,
                                (openPrice - closePrice) * self.yscale)))
        else:
            color.rgba = self.KLINE_COLOR
            instg.add(color)
            x1 = self.chartPos[0] + dispIdx * (self.tickWide +
                                               self.tickGap) + self.tickGap
            y1 = self.chartPos[1] + (closePrice -
                                     self.lowestValue) * self.yscale
            x2 = self.chartPos[0] + (dispIdx + 1) * (self.tickWide +
                                                     self.tickGap)
            y2 = y1
            instg.add(Line(points=(x1, y1, x2, y2), width=1))

        self.canvas.add(instg)
Пример #41
0
 def __init__(self, **kwargs):
     super(BackgroundLabel, self).__init__(**kwargs)
     self.IG = InstructionGroup()
     self.background_color = (0, 0, 0, 1)
     self.color = (1, 1, 1, 1)
Пример #42
0
class Main(FloatLayout):
    snake = ListProperty([(0,0)])
    rangeSnake = ListProperty([0,0,Window.width,Window.height])
    startSpeed = NumericProperty(30)

    def __init__(self, **kwargs):
        super(Main, self).__init__(**kwargs)
        self.keyboard = Controls()
        self.count = 0
        self.bind(size=self.up,pos=self.up)

    def up(self,*args):
        self.rangeSnake[0] = self.pos[0]
        self.rangeSnake[1] = self.pos[1]
        self.rangeSnake[2] = self.pos[0] + self.size[0]
        self.rangeSnake[3] = self.pos[1] + self.size[1]
        self.snake[0] = self.pos

    def start(self,*dt):
        self.canvas.clear()
        Clock.unschedule(self.move)
        self.food()
        Clock.schedule_interval(self.move,1./(self.startSpeed+self.count))

    def restart(self, *dt):
        self.canvas.clear()
        self.clear_widgets()
        Clock.unschedule(self.move)

        self.foods()
        self.snake = [ self.pos]
        self.keyboard.direction = "right"
        Clock.schedule_interval(self.move,1./(self.startSpeed+self.count))

    def stop(self,*dt):
        Clock.unschedule(self.move)

    def continue_move(self):
        Clock.unschedule(self.move)
        Clock.schedule_interval(self.move,1./(self.startSpeed+self.count))

    def food(self,*args):
        self.foodblue = InstructionGroup()
        self.foodblue.add(Color(1, 0, 0, 1))
        x = random.randint(int(self.rangeSnake[0]), int(self.rangeSnake[2]-10))
        y = random.randint(int(self.rangeSnake[1]), int(self.rangeSnake[3]-10))
        self.food = Rectangle(pos=(x,y), size=(10,10))
        self.foodblue.add(self.food)

    def foods(self):
        self.count += 1
        x = random.randint(int(self.rangeSnake[0]), int(self.rangeSnake[2]-10))
        y = random.randint(int(self.rangeSnake[1]), int(self.rangeSnake[3]-10))
        for a,b in self.snake:
            if x > a+10 or y >b+10 or x < a- 10 or y<b-10:
                pass
            else:
                self.foods()
                return
        self.food.pos = (x,y)

    def move(self,*dt):
        self.canvas.clear()
        self.canvas.add(self.foodblue)
        x,y = self.snake[-1]
        if abs(self.snake[-1][0] -self.food.pos[0])<10 and abs(self.snake[-1][1] -self.food.pos[1])<10:#吃到食物
            x,y = self.snake[-1]
            if self.keyboard.direction == "left":
                for i in range(1,11):
                    x1,y1 = x-i,y
                    self.snake.append((x1,y1))
            elif self.keyboard.direction == "right":
                 for i in range(1,11):
                    x1,y1 = x+i,y
                    self.snake.append((x1,y1))
            elif self.keyboard.direction == "up":
                for i in range(1,11):
                    x1,y1 = x,y+i
                    self.snake.append((x1,y1))
            elif self.keyboard.direction == "down":
                for i in range(1,11):
                    x1,y1 = x,y-i
                    self.snake.append((x1,y1))
            self.foods()
        else:
            if self.keyboard.direction == "left":
                x,y = x-1,y
                if x < self.rangeSnake[0] :
                    self.gameover()
                for a,b in self.snake:
                    if x >a and x-a<10 and abs(b-y)<10:
                        self.gameover()
                        break
            elif self.keyboard.direction == "right":
                x,y = x+1,y
                if x+10 > self.rangeSnake[2]:
                    self.gameover()
                for a,b in self.snake:
                    if a>x and a-x < 10 and abs(b-y)< 10:
                        self.gameover()
                        break
            elif self.keyboard.direction == "up":
                x,y = x,y+1
                if y+10 >self.rangeSnake[3]:
                    self.gameover()
                for a,b in self.snake:
                    if b>y and b-y < 10 and abs(x-a)<10:
                        self.gameover()
                        break
            elif self.keyboard.direction == "down":
                x,y = x,y-1
                if y < self.rangeSnake[1]:
                    self.gameover()
                for a,b in self.snake:
                    if y >b and y-b>10 and abs(x-a)<10:
                        self.gameover()
                        break
            self.snake.append((x,y))
            del self.snake[0]
        for i in self.snake:
            snake = InstructionGroup()
            snake.add(Color(0, 0, 1, 1))
            snake.add(Rectangle(pos=i, size=(10,10)))
            self.canvas.add(snake)
    def gameover(self):
        Clock.unschedule(self.move)
        btn = Button(text="Game is over",size_hint=(1,1),pos_hint={"center_x":.5,"center_y":.5})
        self.add_widget(btn)
        btn.bind(on_release=self.restart )
Пример #43
0
 def _gl_setup(self):
     self.drip_texture = CoreImage("resources/images/drop.png", mipmap=True).texture
     self.drips_instruction = InstructionGroup()
     self.model_instruction = InstructionGroup()
     print(self.canvas.children)
class sniffWidget(Widget):

    # two button as property
    btn1 = ObjectProperty(None)
    btn2 = ObjectProperty(None)

    def __init__(self, iface, amount, tag, func, serv_addr, bufsize=1024):
        """
            iface: interface to sniff on
            amount: max amount of latest rssis to maintain
            tag: value for tag field, used as sign
            func: function to process rssi list, should takes list of rssis in 
                  and output another list of single output value
            serv_addr: server addr, format as (HOST, PORT)
            bufsize: max size of receive buf, should be big enough
        """
        super(sniffWidget, self).__init__()
        self.iface = iface
        self.amount = amount
        self.tag = tag
        self.rssi_dict = {}
        self.rssi_dict["tag"] = tag
        self.prcs_dict = {}
        self.prcs_dict["tag"] = self.tag

        self.func = func

        # server addr
        self.serv_addr = serv_addr
        self.bufsize = bufsize

        # client socket
        # use ipv4 udp
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        #self.sock.settimeout(3.0)

        # initial communication with server
        self.config()

        # visualize aps
        #self.visual_aps()

        # initial coords
        self.coords = (0, 0)

        # used to record all instructions that draw user-dots
        self.obj = InstructionGroup()
        self.objects = []

        # used to indicate whether update should be down actually
        self.update_flag = 0

        # children widget, 2 buttons
        # define event behavior for those two
        def _on_press1(instance):
            # change the text and flag
            if instance.flag == -1:
                instance.flag = 1
                instance.text = "Pause"
                instance.parent.set_flag()
            elif instance.flag == 0:
                instance.flag = 1
                instance.text = "Pause"
                instance.parent.set_flag()
            elif instance.flag == 1:
                instance.flag = 0
                instance.text = "Resume"
                instance.parent.unset_flag()

        def _on_press2(instance):
            # clear the canvas and re-initial btn1
            instance.parent.clear()
            instance.parent.btn1.reinit()
            instance.parent.unset_flag()

        self.btn1.bind(on_press=_on_press1)
        self.btn2.bind(on_press=_on_press2)

    def config(self):
        name_dict = {"tag": self.tag}
        # send the tag
        self.sock.sendto(json.dumps(name_dict).encode('utf-8'), self.serv_addr)
        # receive the configuration of APs
        recv_msg, addr = self.sock.recvfrom(self.bufsize)
        recv_msg = str(recv_msg, encoding="utf-8")
        if addr == self.serv_addr:
            self.config_dict = json.loads(recv_msg)
            self.ssids = self.config_dict.keys()
            for ssid in self.ssids:
                self.rssi_dict[ssid] = []
                self.prcs_dict[ssid] = []
            return

        # if fail, then exit
        raise Exception("connect to server {} failed, please \
                         check your network connection and try again".format(
            self.serv_addr))
        sys.exit()

    def visual_aps(self):
        with self.canvas:
            Color(1, 0, 0)
            d = 20.0
            for ssid in self.ssids:
                x, y = self.config_dict[ssid]
                print(x * Window.size[0])
                print(y * Window.size[1])
                Ellipse(pos=(x * Window.size[0], y * Window.size[1]),
                        size=(d, d))

    def sniff(self, dt):
        num = len(self.ssids)
        for ssid in self.ssids:
            data = sniff_rssi(self.iface, ssid, 1, dt)
            #data_dict = sniff_rssi_cmd(self.iface, self.ssids, 1, dt)
            self.rssi_dict[ssid] += data

    def aging(self):
        """
            only keep the latest "amount" rssi values
        """
        for ssid in self.ssids:
            if len(self.rssi_dict[ssid]) > self.amount:
                self.rssi_dict[ssid] = self.rssi_dict[ssid][-1 * self.amount:]

    def process(self):
        """
            process the rssis
        """
        for ssid in self.ssids:
            self.prcs_dict[ssid] = self.func(self.rssi_dict[ssid])

    def sendrecv(self):
        msg = json.dumps(self.prcs_dict)
        # send
        self.sock.sendto(msg.encode("utf-8"), self.serv_addr)
        # recv
        recv_msg, addr = self.sock.recvfrom(self.bufsize)
        recv_msg = str(recv_msg, encoding="utf-8")
        if addr == self.serv_addr:
            recv_dict = json.loads(recv_msg)
            self.coords = (recv_dict["x"], recv_dict["y"])

    def visualize(self):
        self.obj = InstructionGroup()
        d = 20.
        x, y = self.coords
        self.obj.add(Color(0, 1, 0))
        self.obj.add(
            Ellipse(pos=(x * Window.size[0], y * Window.size[1]), size=(d, d)))
        self.canvas.add(self.obj)
        self.objects.append(self.obj)

    def clear(self):
        # clear all user dots
        for obj in self.objects:
            self.canvas.remove(obj)
        self.objects = []

    def set_flag(self):
        self.update_flag = 1

    def unset_flag(self):
        self.update_flag = 0

    def update(self, dt):
        print("in update")
        if self.update_flag:
            # update periodic of interval dt(s)
            # 1.sniff
            self.sniff(dt * 0.08 / len(self.ssids))
            # 2.aging
            self.aging()
            print(self.rssi_dict)
            # 3.process
            self.process()
            # 4.sendrecv
            self.sendrecv()
            # 5.visualize
            self.visualize()
Пример #45
0
class PrinterAnimation(RelativeLayout):
    padding = NumericProperty(40)

    printer_actual_dimensions = ListProperty([10, 10, 80])
    printer_current_actual_height = NumericProperty(0.0)

    print_area_height = NumericProperty(1)
    print_area_width = NumericProperty(1)
    print_area_left = NumericProperty(0)
    print_area_bottom = NumericProperty(40)

    container_padding = NumericProperty(0)
    container_left = NumericProperty(0)
    container_width = NumericProperty(0)
    container_bottom = NumericProperty(0)
    container_height = NumericProperty(0)

    laser_size = ListProperty([40, 40])

    resin_height = NumericProperty(20)
    water_height = NumericProperty(20)

    scale = NumericProperty(1.0)

    resin_color = ListProperty([0.0, 0.8, 0.0, 0.6])
    water_color = ListProperty([0.2, 0.2, 1.0, 0.6])
    container_color = ListProperty([1.0, 1.0, 1.0, 1.0])
    laser_color_edge2 = ListProperty([0.0, 0.0, 0.5, 1.0])
    laser_color_edge = ListProperty([0.0, 0.0, 1.0, 1.0])
    laser_color = ListProperty([0.7, 1.0, 1.0, 1.0])

    drip_history = ListProperty()
    laser_points = ListProperty()

    middle_x = NumericProperty(52)

    laser_pos = NumericProperty(60)
    laser_speed = NumericProperty(1)
    refresh_rate = NumericProperty(1.0)

    def __init__(self, **kwargs):
        super(PrinterAnimation, self).__init__(**kwargs)
        self.drip_time_range = 5
        self.waiting_for_drips = True
        self.refresh_rate = App.get_running_app().refresh_rate
        self._gl_setup()
        self.axis_history = []
        self.drips = 0

        self.line_x = []
        self.line_y = []
        self.last_height = 0.0
        self.min_height = 0.0
        self.last_x_min = 0.0
        self.last_x_max = 1.0
        self.is_on_canvas = False

    def on_printer_actual_dimensions(self, instance, value):
        self.min_height = self.printer_actual_dimensions[2] / 400.0
        self.on_size(None)

    def _gl_setup(self):
        self.drip_texture = CoreImage("resources/images/drop.png", mipmap=True).texture
        self.drips_instruction = InstructionGroup()
        self.model_instruction = InstructionGroup()
        print(self.canvas.children)
        # self.canvas.add(self.drips_instruction)
        # self.canvas.add(self.model_instruction)

    def on_size(self, *largs):
        bounds_y = (self.height * 0.7) - self.resin_height
        bounds_x = self.width - (self.padding * 2)
        printer_x = self.printer_actual_dimensions[0]
        printer_y = self.printer_actual_dimensions[2]
        self.laser_pos = self.width / 2

        self.scale = min(bounds_y / printer_y, bounds_x / printer_x)
        Logger.info("Scale: {}".format(self.scale))
        self.print_area_width = printer_x * self.scale
        self.print_area_height = printer_y * self.scale

    def redraw(self, key):
        self._draw_drips()
        self._draw_laser()
        self._draw_model()
        if not self.is_on_canvas:
            self.canvas.insert(4, self.drips_instruction)
            self.canvas.insert(4, self.model_instruction)
            self.is_on_canvas = True

        Clock.unschedule(self.redraw)
        Clock.schedule_once(self.redraw, self.refresh_rate)

    def animation_start(self, *args):
        Clock.unschedule(self.redraw)
        self.axis_history = []
        self.line_x = []
        self.line_y = []
        self.last_height = 0
        self.min_height = 0.0
        self.laser_points = []
        self.drip_history = []
        Clock.schedule_once(self.redraw, self.refresh_rate)

    def animation_stop(self):
        Clock.unschedule(self.redraw)
        self.axis_history = []
        self.line_x = []
        self.line_y = []
        self.last_height = 0
        self.min_height = 0.0
        self.laser_points = []
        self.drip_history = []

    def _draw_drips(self):
        self.drips_instruction.clear()
        self.drips_instruction.add(Color(1, 1, 1, 1))
        top = time.time()
        bottom = top - self.drip_time_range
        drips_in_history = len(self.drip_history)
        for (index, drip_time) in zip(range(drips_in_history, 0, -1), self.drip_history):
            if drip_time > bottom:
                time_ago = top - drip_time
                y_pos_percent = (self.drip_time_range - time_ago) / self.drip_time_range
                drip_pos_y = (self.height * y_pos_percent) + self.padding
                xoff = 10 + math.sin((len(self.drip_history) - index) / (2 * math.pi)) * 20
                self.drips_instruction.add(Rectangle(size=[12, 16], pos=[self.print_area_left + xoff, drip_pos_y], texture=self.drip_texture))

    def _draw_laser(self):
        if self.waiting_for_drips:
            self.laser_points = []
        else:
            x_min = self.print_area_left + (self.last_x_min * self.print_area_width)
            x_max = self.print_area_left + (self.last_x_max * self.print_area_width)
            if (self.laser_pos >= x_max):
                self.laser_pos = x_max
                self.laser_speed = abs(self.laser_speed) * -1
            if (self.laser_pos <= x_min):
                self.laser_pos = x_min
                self.laser_speed = abs(self.laser_speed)

            self.laser_pos += self.laser_speed
            laser_x = self.laser_pos
            self.laser_points = [self.middle_x, self.height - self.padding,
                                 laser_x,          self.water_height + self.print_area_bottom + self.resin_height]

    def _draw_model(self):
            if self.axis_history:
                model_height = self.axis_history[-1][2]
                if model_height > (self.last_height + self.min_height) or not self.line_x:
                    x1, y1, x2, y2 = self._get_pixels(self.axis_history[-1])
                    self.last_x_min = x1
                    self.last_x_max = x2

                    self.line_x.insert(0, x1)
                    self.line_x.append(x2)
                    self.line_y.insert(0, y1)
                    self.line_y.append(y2)
                    self.last_height = model_height

                    points = []
                    for idx in range(0, len(self.line_x)):
                        x = int(self.print_area_left + (self.line_x[idx] * self.print_area_width))
                        y = int(self.print_area_bottom + self.resin_height + (self.line_y[idx] * self.print_area_height)) - 2
                        points.append(x)
                        points.append(y)
                    self.model_instruction.clear()
                    self.model_instruction.add(Color(rgba=(1.0, 0.0, 0.0, 1.0)))
                    self.model_instruction.add(Line(points=points, width=2, close=True))

    def _get_pixels(self, data):
        pixel_height = data[2] / self.printer_actual_dimensions[2]
        pixel_pos_min = (data[0][0] + (self.printer_actual_dimensions[1] / 2.0)) / self.printer_actual_dimensions[1]
        pixel_pos_max = (data[0][1] + (self.printer_actual_dimensions[1] / 2.0)) / self.printer_actual_dimensions[1]
        return [pixel_pos_min, pixel_height, pixel_pos_max, pixel_height]
Пример #46
0
class TabWidget(Widget):
    open_repeat_opac = NumericProperty(0)
    close_repeat_opac = NumericProperty(0)
    selected_opac = NumericProperty(0)

    timesig_width = NumericProperty(64)
    open_repeat_width = NumericProperty(0)
    close_repeat_width = NumericProperty(0)
    measure_end = NumericProperty(0)

    def get_barline_x(self):
        return self.x + self.timesig_width

    barline_x = AliasProperty(get_barline_x,
                              None,
                              bind=['x', 'timesig_width'],
                              cache=True)

    def get_measure_start(self):
        return self.x + self.timesig_width + self.open_repeat_width

    measure_start = AliasProperty(
        get_measure_start,
        None,
        bind=['x', 'timesig_width', 'open_repeat_width'],
        cache=True)

    def __init__(self, tabbuilder=None, idx=0, total_measures=0, **kwargs):
        self.tabbuilder = tabbuilder
        self.idx = idx
        self.total_measures = total_measures
        self.step_y = 20
        self.measure_width = 512  # width of a 4/4 measure only, sort of a step_x.
        self.starts_with_tie = False
        self.ends_with_slide = False
        self.is_selected = False
        super().__init__(**kwargs)
        self.glyphs = InstructionGroup()
        self.backgrounds = InstructionGroup()
        self.note_glyphs = InstructionGroup()
        self.num_glyphs = InstructionGroup()
        self.tuplet_count = 0
        self.canvas.add(white)
        self.canvas.add(self.backgrounds)
        self.canvas.add(black)
        self.canvas.add(self.glyphs)

    def build_measure(self, gp_measure: guitarpro.models.Measure):
        if self.x == 0:
            self.draw_timesig(gp_measure)
        self.draw_measure_number(gp_measure)
        self.draw_open_repeat(gp_measure)
        self.gp_beats, self.xmids = self.add_staff_glyphs(gp_measure)
        self.draw_note_effects(self.gp_beats, self.xmids)
        gp_beat_groups = self.gp_beat_groupby(self.gp_beats)
        self.add_note_glyphs(gp_beat_groups, self.xmids)
        self.draw_close_repeat(gp_measure)
        self.draw_measure_count()

    def draw_timesig(self, gp_measure: guitarpro.models.Measure):
        num, den = gp_measure.timeSignature.numerator, gp_measure.timeSignature.denominator.value
        num_glyph = CoreLabel(text=str(num),
                              font_size=50,
                              font_name='./fonts/PatuaOne-Regular')
        den_glyph = CoreLabel(text=str(den),
                              font_size=50,
                              font_name='./fonts/PatuaOne-Regular')
        num_glyph.refresh()
        den_glyph.refresh()
        num_x = (self.barline_x / 2) - (num_glyph.texture.width / 2)
        den_x = (self.barline_x / 2) - (den_glyph.texture.width / 2)
        num_instr = Rectangle(pos=(num_x, self.y + self.step_y * 5),
                              size=(num_glyph.texture.size))
        den_instr = Rectangle(pos=(den_x, self.y + self.step_y * 3),
                              size=(den_glyph.texture.size))
        num_instr.texture = num_glyph.texture
        den_instr.texture = den_glyph.texture
        self.glyphs.add(num_instr)
        self.glyphs.add(den_instr)

    def draw_measure_number(self, gp_measure: guitarpro.models.Measure):
        num = gp_measure.header.number
        num_glyph = CoreLabel(text=str(num),
                              font_size=14,
                              font_name='./fonts/Arial')
        num_glyph.refresh()
        num_x = self.barline_x - num_glyph.width
        num_y = self.y + self.step_y * 8
        num_instr = Rectangle(pos=(num_x, num_y), size=num_glyph.texture.size)
        num_instr.texture = num_glyph.texture
        self.glyphs.add(num_instr)

    def draw_measure_count(self):
        # TODO: Once copy/delete buttons are added, update measure counts.
        measure_count = str(self.idx + 1) + ' / ' + str(self.total_measures)
        count_glyph = CoreLabel(text=measure_count,
                                font_size=14,
                                font_name='./fonts/Arial')
        count_glyph.refresh()
        count_x = self.right - (count_glyph.width + 5)
        count_y = self.y
        count_instr = Rectangle(pos=(count_x, count_y), size=count_glyph.size)
        count_instr.texture = count_glyph.texture
        self.glyphs.add(count_instr)

    def draw_open_repeat(self, gp_measure: guitarpro.models.Measure):
        if gp_measure.isRepeatOpen:
            self.open_repeat_opac = 1
            self.open_repeat_width = 25

    def draw_close_repeat(self, gp_measure: guitarpro.models.Measure):
        if gp_measure.repeatClose > 0:
            self.close_repeat_opac = 1
            self.close_repeat_width = 25

    def add_staff_glyphs(self, gp_measure: guitarpro.models.Measure):
        gp_beats, xmids = [], []
        for gp_voice in gp_measure.voices[:-1]:
            xpos = self.measure_start
            for beat_idx, gp_beat in enumerate(gp_voice.beats):
                note_dur = 1 / gp_beat.duration.value
                tuplet_mult = gp_beat.duration.tuplet.times / gp_beat.duration.tuplet.enters
                beat_width = note_dur * tuplet_mult * self.measure_width
                if gp_beat.duration.isDotted:
                    beat_width *= 3 / 2
                elif gp_beat.duration.isDoubleDotted:
                    beat_width *= 7 / 4
                beat_mid = self.add_beat_glyph(gp_beat, xpos)
                xmids += [beat_mid]
                gp_beats += [gp_beat]
                xpos += beat_width
        self.measure_end = xpos
        return gp_beats, xmids

    def add_beat_glyph(self, gp_beat: guitarpro.models.Beat, xpos: float):
        # If notes list is empty, rest for gp_beat.duration.value.
        if not gp_beat.notes:
            self.draw_rest(gp_beat, xpos)
            return xpos
        for gp_note in gp_beat.notes:
            xmid = self.draw_fretnum(gp_note, xpos)
        return xmid

    def draw_fretnum(self, gp_note: guitarpro.models.Note, xpos: float):
        fret_text = str(gp_note.value)
        if gp_note.type.name == 'tie':
            fret_text = '  '
        if gp_note.type.name == 'dead':
            fret_text = 'X'
        if gp_note.effect.isHarmonic:
            fret_text = '<' + fret_text + '>'
        fret_num_glyph = CoreLabel(text=fret_text,
                                   font_size=16,
                                   font_name='./fonts/Arial',
                                   bold=True)
        fret_num_glyph.refresh()
        ypos = self.y + self.step_y * (
            8 - (gp_note.string - 1)) - fret_num_glyph.height / 2
        background = Rectangle(pos=(xpos, ypos),
                               size=fret_num_glyph.texture.size)
        fret_num_instr = Rectangle(pos=(xpos, ypos),
                                   size=fret_num_glyph.texture.size)
        fret_num_instr.texture = fret_num_glyph.texture
        self.backgrounds.add(background)
        self.glyphs.add(fret_num_instr)
        xmid = xpos + (fret_num_glyph.texture.width / 2)
        return xmid

    def gp_beat_groupby(self, gp_beats: List[guitarpro.models.Beat]):
        beat_groups, cur_group = [], []
        prev_dur = None
        i = 0
        while i < len(gp_beats):
            gp_beat = gp_beats[i]
            # Add rests by themselves.
            if not gp_beat.notes:
                if cur_group:
                    beat_groups.append(cur_group[:])
                    cur_group = []
                beat_groups.append([gp_beat])
                prev_dur = None
                i += 1
            # Add notes within a tuplet together.
            elif gp_beat.duration.tuplet.enters != 1:
                if cur_group:
                    beat_groups.append(cur_group[:])
                    cur_group = []
                tuplet_num = gp_beat.duration.tuplet.enters
                beat_groups.append(gp_beats[i:i + tuplet_num])
                prev_dur = None
                i += tuplet_num
            # Group this single note with a previously existing group.
            elif gp_beat.duration.value == prev_dur and not (
                    gp_beat.duration.isDotted
                    or gp_beat.duration.isDoubleDotted
                    or any(gp_note.effect.slides
                           for gp_note in gp_beat.notes)):
                cur_group += [gp_beat]
                i += 1
            # End the previous group and start a new one.
            else:
                if cur_group:
                    beat_groups += [cur_group[:]]
                cur_group = [gp_beat]
                prev_dur = gp_beat.duration.value
                i += 1
        if cur_group:
            beat_groups += [cur_group[:]]
        return beat_groups

    def add_note_glyphs(self, gp_beat_groups: List[guitarpro.models.Beat],
                        xmids: List[float]):
        bg = x = 0
        while bg < len(gp_beat_groups):
            group = gp_beat_groups[bg]
            gp_beat = group[0]
            # Rest or single note.
            if len(group) == 1:
                if gp_beat.notes:
                    self.draw_stem(gp_beat, xmids[x])
                    self.draw_flags(gp_beat, xmids[x])
                x += 1
            # Tuplet.
            elif gp_beat.duration.tuplet.enters != 1:
                num_tuplet = gp_beat.duration.tuplet.enters
                tuplet_mids = xmids[x:x + num_tuplet]
                self.draw_tuplet(gp_beat, tuplet_mids)
                x += num_tuplet
            # Beamed note.
            elif len(group) % 2 == 0:
                num_notes = len(group)
                self.draw_beamed_notes(gp_beat, xmids[x:x + num_notes])
                x += num_notes
            # Mix of beamed note and single note.
            else:
                num_notes = len(group) - 1
                self.draw_beamed_notes(gp_beat, xmids[x:x + num_notes])
                x += num_notes
                self.draw_stem(gp_beat, xmids[x])
                self.draw_flags(gp_beat, xmids[x])
                x += 1
            bg += 1

    def draw_rest(self, gp_beat: guitarpro.models.Beat, xpos: float):
        # The only font I can find for rests doesn't follow the unicode standard.
        step_y = self.step_y
        unicode_rests = {
            1: u'\u1D13B',
            2: u'\u1D13C',
            4: u'\u1D13D',
            8: u'\u1D13E',
            16: u'\u1D13F'
        }
        rests = {
            1: u'\uE102',
            2: u'\uE103',
            4: u'\uE107',
            8: u'\uE109',
            16: u'\uE10A',
            32: u'\uE10B'
        }
        rest_ys = {
            1: step_y * 4,
            2: step_y * 3,
            4: step_y * 2.5,
            8: step_y * 3,
            16: step_y * 3,
            32: step_y * 2.5
        }
        rest, rest_y = rests[gp_beat.duration.value], rest_ys[
            gp_beat.duration.value]
        rest_glyph = CoreLabel(text=rest,
                               font_size=32,
                               font_name='./fonts/mscore-20')
        rest_glyph.refresh()
        rest_instr = Rectangle(pos=(xpos, self.y + rest_y),
                               size=rest_glyph.texture.size)
        rest_instr.texture = rest_glyph.texture
        background = Rectangle(pos=(xpos, self.y + rest_y),
                               size=rest_glyph.texture.size)
        # self.backgrounds.add(background)  # Looks bad because of mscore-20 font.
        self.glyphs.add(rest_instr)
        if gp_beat.duration.isDotted or gp_beat.duration.isDoubleDotted:
            ypos = rest_y + rest_glyph.texture.height * 0.75
            self.draw_dots(gp_beat, xpos, ypos)

    def draw_stem(self, gp_beat: guitarpro.models.Beat, xpos: float):
        lower = (xpos, self.y + self.step_y * 1.5)
        if gp_beat.duration.value == 1:
            return
        if gp_beat.duration.value == 2:
            upper = (xpos, self.y + self.step_y * 2)
        else:
            upper = (xpos, self.y + self.step_y * 2.5)
        stem = Line(points=(*lower, *upper), width=1, cap='square')
        if gp_beat.duration.isDotted or gp_beat.duration.isDoubleDotted:
            xpos, ypos = lower
            ypos += 2
            self.draw_dots(gp_beat, xpos, ypos)
        self.glyphs.add(stem)

    def draw_flags(self, gp_beat: guitarpro.models.Beat, xpos: float):
        # Texture created by mscore-20 font is unnecessarily tall, hard to place exactly.
        flags = {
            1: '',
            2: '',
            4: '',
            8: u'\uE194',
            16: u'\uE197',
            32: u'\uE198'
        }
        flag = flags[gp_beat.duration.value]
        flag_glyph = CoreLabel(text=flag,
                               font_size=32,
                               font_name='./fonts/mscore-20')
        flag_glyph.refresh()
        flag_instr = Rectangle(pos=(xpos, self.y - self.step_y * 1.5),
                               size=flag_glyph.texture.size)
        flag_instr.texture = flag_glyph.texture
        self.glyphs.add(flag_instr)

    def draw_tuplet(self, gp_beat: guitarpro.models.Beat, xmids: List[float]):
        xmin, xmax = xmids[0], xmids[-1]
        for xpos in xmids:
            self.draw_stem(gp_beat, xpos)
        if gp_beat.duration.value == 8:
            self.draw_eightnote_beam(xmin, xmax)
        if gp_beat.duration.value == 16:
            self.draw_eightnote_beam(xmin, xmax)
            self.draw_sixteenthnote_beam(xmin, xmax)

        xmid = (xmin + xmax) / 2
        text_glyph = CoreLabel(text=str(gp_beat.duration.tuplet.enters),
                               font_size=14,
                               font_name='./fonts/Arial')
        text_glyph.refresh()
        text_instr = Rectangle(pos=(xmid - text_glyph.texture.width / 2,
                                    self.y + self.step_y * 0.5),
                               size=text_glyph.texture.size)
        text_instr.texture = text_glyph.texture
        self.glyphs.add(text_instr)

    def draw_beamed_notes(self, gp_beat: guitarpro.models.Beat,
                          xmids: List[float]):
        xmin, xmax = xmids[0], xmids[-1]
        for xpos in xmids:
            self.draw_stem(gp_beat, xpos)
        if gp_beat.duration.value == 8:
            self.draw_eightnote_beam(xmin, xmax)
        if gp_beat.duration.value == 16:
            self.draw_eightnote_beam(xmin, xmax)
            self.draw_sixteenthnote_beam(xmin, xmax)

    def draw_eightnote_beam(self, xmin: float, xmax: float):
        lowbeam = Line(points=(xmin, self.y + self.step_y * 1.5, xmax,
                               self.y + self.step_y * 1.5),
                       width=1.4,
                       cap='square')
        self.glyphs.add(lowbeam)

    def draw_sixteenthnote_beam(self, xmin: float, xmax: float):
        highbeam = Line(points=(xmin, self.y + self.step_y * 1.75, xmax,
                                self.y + self.step_y * 1.75),
                        width=1.1,
                        cap='square')
        self.glyphs.add(highbeam)

    def draw_dots(self, gp_beat: guitarpro.models.Beat, xpos: float,
                  ypos: float):
        xpos += 4
        dot_size = (3, 3)
        if gp_beat.duration.isDotted:
            dot = Ellipse(pos=(xpos, ypos), size=dot_size)
            self.glyphs.add(dot)
        elif gp_beat.duration.isDoubleDotted:
            dot1 = Ellipse(pos=(xpos, ypos), size=dot_size)
            dot2 = Ellipse(pos=(xpos + 4, ypos), size=dot_size)
            self.glyphs.add(dot1)
            self.glyphs.add(dot2)

    def draw_note_effects(self, gp_beats: List[guitarpro.models.Beat],
                          xmids: List[float]):
        for i, (gp_beat, xmid) in enumerate(zip(gp_beats, xmids)):
            for gp_note in gp_beat.notes:
                if gp_note.type.name == "tie":
                    if i != 0:
                        self.draw_tie(gp_note, xmids[i - 1], xmids[i])
                    else:
                        self.starts_with_tie = True
                elif gp_note.effect.slides:
                    if i != len(xmids) - 1:
                        self.draw_slide(gp_note, xmids[i], xmids[i + 1])
                    else:
                        self.ends_with_slide = True

    def draw_tie(self, gp_note: guitarpro.models.Note, start: float,
                 end: float):
        string_y = self.y + self.step_y * (8 - (gp_note.string - 1))
        line_mid = (start + end) / 2
        points = (start, string_y - self.step_y / 3, line_mid,
                  string_y - self.step_y, end, string_y - self.step_y / 3)
        tie_line = Bezier(points=points)
        self.glyphs.add(tie_line)

    def draw_tie_across_measures(self, gp_beat: guitarpro.models.Beat,
                                 start: float, end: float):
        for gp_note in gp_beat.notes:
            if gp_note.type.name == "tie":
                self.draw_tie(gp_note, start, end)

    def draw_slide(self, gp_note: guitarpro.models.Note, start, end):
        # There are 7 guitarpro.models.SlideTypes. So far only shiftSlideto, value == 1.
        string_y = self.y + self.step_y * (8 - (gp_note.string - 1))
        padding = 10
        start += padding
        end -= padding
        points = (start, string_y + self.step_y / 4, end,
                  string_y - self.step_y / 4)
        slide_line = Line(points=points)
        self.glyphs.add(slide_line)

    def on_touch_down(self, touch):
        if self.collide_point(touch.x, touch.y):
            self.tabbuilder.no_tabwidgets_touched = False
            self.tabbuilder.select(self)
            return True
        return super().on_touch_down(touch)

    def select(self):
        self.is_selected = True
        self.selected_opac = 0.5

    def unselect(self):
        self.is_selected = False
        self.selected_opac = 0
Пример #47
0
 def drawCordFrame(self):
     
     # 畫一條橫線
     instg = InstructionGroup(group="frame")
     frameColor = Color()
     frameColor.rgba = self.FRAME_COLOR
     instg.add(frameColor)
     x1 = int(self.pos[0] + self.shift_left)
     y1 = int(self.pos[1] + self.shift_bottom)
     x2 = int(self.pos[0] + self.width - self.shift_right)
     y2 = int(self.pos[1] + self.shift_bottom)
     instg.add(Line(points=(x1, y1, x2, y2), width=1))        
     self.canvas.add(instg)
     
     # 畫一條豎線
     instg = InstructionGroup(group="frame")
     instg.add(frameColor)
     center_pos = int(self.pillarPoint / 2)
     self.center_xpos = int(self.pos[0] + self.shift_left + (self.min_tickNum * -1) * self.pillarSumPoint + self.ycordWidth + center_pos)
     x1 = self.center_xpos
     y1 = int(self.pos[1] + self.shift_bottom)
     x2 = self.center_xpos
     y2 = int(self.pos[1] + self.height - self.shift_top)
     instg.add(Line(points=(x1, y1, x2, y2), width=1))
     self.canvas.add(instg)
Пример #48
0
    def update_board(self):
        self.canvas.after.clear()
        self.players = []
        pos_x = 0.9 - self.each_tile_size + 0.01
        pos_y = 0.11
        self.color_players_list = [[1, 0, 0, 1], [0, 1, 0, 1], [0, 0, 1, 1],
                                   [1, 1, 0, 1]]
        self.pos_x_list = []
        self.pos_y_list = []

        for i in range(len(self.dice_holder_list)):
            self.dice_holder_list[i].text = str(self.dice_list[i])

        for i in range(4):
            text_on_button = " "+ self.game_elem['players'][i].player_name + \
                            "\n Current Cash = " + str(self.game_elem['players'][i].current_cash) + \
                            "\n # of houses = " + str(self.game_elem['players'][i].num_total_houses) + \
                             "\n # of hotels = " + str(self.game_elem['players'][i].num_total_hotels)
            if (self.game_elem['players']
                [i].has_get_out_of_jail_community_chest_card == True):
                text_on_button = text_on_button + "\nGOO_Jail community card"
            if (self.game_elem['players'][i].has_get_out_of_jail_chance_card ==
                    True):
                text_on_button = text_on_button + "\nGOO_Jail chance card"

            self.player_detail_list[i].text = text_on_button
            self.obj_instr_player = InstructionGroup()
            self.obj_instr_player.add(
                Color(self.color_players_list[i][0],
                      self.color_players_list[i][1],
                      self.color_players_list[i][2],
                      self.color_players_list[i][3]))
            try:
                pos_x_n = int(self.game_elem['players'][i].current_position /
                              10)
                pos_y_n = int(self.game_elem['players'][i].current_position %
                              10)
            except:
                pos_x_n = 0
                pos_y_n = 0

            if (pos_x_n == 0):
                pos_x = (0.9 - self.each_tile_size +
                         0.01) - (pos_y_n * self.each_tile_size)
                pos_y = 0.11
            elif (pos_x_n == 2):
                pos_x = (0.9 - self.each_tile_size + 0.01) - (
                    self.num_tiles *
                    (self.each_tile_size)) + (pos_y_n * self.each_tile_size)
                pos_y = 0.11 + (self.num_tiles * self.each_tile_size)
            elif (pos_x_n == 1):
                pos_x = (0.9 - self.each_tile_size +
                         0.01) - (self.num_tiles * (self.each_tile_size))
                pos_y = 0.11 + (pos_y_n * self.each_tile_size)
            elif (pos_x_n == 3):
                pos_x = (0.9 - self.each_tile_size + 0.01)
                pos_y = 0.11 + (self.num_tiles * self.each_tile_size) - (
                    pos_y_n * self.each_tile_size)

            self.obj_instr_player.add(
                Ellipse(pos=((pos_x + i * 0.01) * Window.width,
                             pos_y * Window.height),
                        size=(10, 10)))
            self.players.append(self.obj_instr_player)
            self.pos_x_list.append(pos_x)
            self.pos_y_list.append(pos_y)
            self.canvas.after.add(self.obj_instr_player)

            count_house = 0
            count_hotel = 0
            if (self.game_elem['players'][i].assets) != None:
                self.player_props = []
                self.player_props_x = []
                self.player_props_y = []

                for k in range(len(list(self.game_elem['players'][i].assets))):
                    prop_name = list(
                        self.game_elem['players'][i].assets)[k].name
                    pos_prop = self.game_elem['location_objects'][
                        prop_name].start_position

                    self.obj_instr = InstructionGroup()
                    self.obj_instr.add(
                        Color(self.color_players_list[i][0],
                              self.color_players_list[i][1],
                              self.color_players_list[i][2],
                              self.color_players_list[i][3]))

                    each_side_num_tiles = self.num_tiles
                    side = 0
                    if pos_prop >= 0 and pos_prop < each_side_num_tiles:
                        side = 0
                    elif pos_prop >= each_side_num_tiles and pos_prop < 2 * each_side_num_tiles:
                        side = 1
                    elif pos_prop >= 2 * each_side_num_tiles and pos_prop < 3 * each_side_num_tiles:
                        side = 2
                    else:
                        side = 3
                    #prop_x = int(pos_prop / 10)
                    prop_y = pos_prop - side * each_side_num_tiles
                    pos_x_prop = 0
                    pos_y_prop = 0

                    if (side == 0):
                        pos_x_prop = 0.9 - self.each_tile_size + 0.01 - (
                            prop_y * self.each_tile_size)
                        pos_y_prop = 0.14
                    elif (side == 2):
                        pos_x_prop = 0.9 - self.each_tile_size + 0.01 - (
                            self.num_tiles *
                            (self.each_tile_size)) + (prop_y *
                                                      self.each_tile_size)
                        pos_y_prop = 0.14 + (self.num_tiles *
                                             self.each_tile_size)
                    elif (side == 1):
                        pos_x_prop = 0.9 - self.each_tile_size + 0.01 - (
                            self.num_tiles * (self.each_tile_size))
                        pos_y_prop = 0.14 + (prop_y * self.each_tile_size)
                    elif (side == 3):
                        pos_x_prop = 0.9 - self.each_tile_size + 0.01
                        pos_y_prop = 0.14 + (self.num_tiles *
                                             self.each_tile_size) - (
                                                 prop_y * self.each_tile_size)
                    self.obj_instr.add(
                        Rectangle(pos=(pos_x_prop * Window.width,
                                       pos_y_prop * Window.height),
                                  size=(12, 12)))
                    if list(self.game_elem['players']
                            [i].assets)[k].loc_class == 'real_estate':
                        if list(self.game_elem['players']
                                [i].assets)[k].num_houses > 0:
                            for m in range(
                                    list(self.game_elem['players'][i].assets)
                                [k].num_houses):
                                self.obj_instr.add(Color(1, 1, 1, 1))
                                self.obj_instr.add(
                                    Ellipse(
                                        pos=((pos_x_prop +
                                              (m + 1) * 0.01) * Window.width,
                                             pos_y_prop * Window.height),
                                        size=(12, 12)))
                                count_house += list(self.game_elem['players']
                                                    [i].assets)[k].num_houses

                        if list(self.game_elem['players']
                                [i].assets)[k].num_hotels > 0:
                            for m in range(
                                    list(self.game_elem['players'][i].assets)
                                [k].num_hotels):
                                self.obj_instr.add(Color(1, 0.1, 0.5, 1))
                                self.obj_instr.add(
                                    Ellipse(
                                        pos=((pos_x_prop +
                                              (m + 1) * 0.01) * Window.width,
                                             pos_y_prop * Window.height),
                                        size=(12, 12)))
                                count_hotel += list(self.game_elem['players']
                                                    [i].assets)[k].num_hotels

                    self.player_props.append(self.obj_instr)
                    self.player_props_x.append(pos_x_prop)
                    self.player_props_y.append(pos_y_prop)
                    self.canvas.after.add(self.obj_instr)
                    self.obj_instr_directory.append(self.obj_instr)
            self.bind(pos=self.update_rect, size=self.update_rect)
Пример #49
0
class FrameCanvas(RelativeLayout):
    def __init__(self, app):
        super(FrameCanvas, self).__init__()
        self._app = app
        self.bind(width=app.seek_video)
        self.bind(height=app.seek_video)
        self.touch_points = []

        self._select_event = None
        self._select_center_xy = None
        self._select_radius = None
        self._select_circle = None

    def on_touch_down(self, touch):
        if not self.collide_point(*touch.pos): return False
        if self._app._cap is None: return False
        if self._app._play_pause_btn.text != "Play": return False

        canvas_xy = (touch.pos[0] - self.pos[0], touch.pos[1] - self.pos[1])
        if ((self._select_center_xy is None) or (_sq_distance(
                canvas_xy, self._select_center_xy) >= self._select_radius**2)):
            self._select_center_xy = canvas_xy
            self._select_radius = 0
            if self._select_circle is not None:
                self.canvas.remove(self._select_circle)
                self._select_circle = None

        if self._select_event is not None:
            self._select_event.cancel()
        self._select_event = Clock.schedule_interval(self._inc_selection, 0.01)
        return True

    def _inc_selection(self, *args, **kwargs):
        self._select_radius += 1
        frame_xy1 = self._app._cap.canvas_xy_to_frame_xy(
            self._select_center_xy[0] - self._select_radius,
            self._select_center_xy[1] + self._select_radius)
        frame_xy2 = self._app._cap.canvas_xy_to_frame_xy(
            self._select_center_xy[0] + self._select_radius,
            self._select_center_xy[1] - self._select_radius)
        if frame_xy1 is None or frame_xy2 is None:
            self._select_radius -= 1
            return
        if self._select_circle is not None:
            self.canvas.remove(self._select_circle)
        self._select_circle = InstructionGroup()
        self._select_circle.add(Color(1, 0, 0))
        self._select_circle.add(
            Line(circle=(self._select_center_xy) + (self._select_radius, ),
                 width=dp(3)))
        self.canvas.add(self._select_circle)

    def on_touch_up(self, touch):
        if self._select_event is not None:
            self._select_event.cancel()
            self._select_event = None
        if self._select_center_xy is not None:
            self._app._process_btn.disabled = False

    def clear_selection(self):
        self.on_touch_up(None)
        if self._select_circle is not None:
            self.canvas.remove(self._select_circle)
            self._select_circle = None
        self._select_center_xy = None
        self._select_radius = None
        self._app._process_btn.disabled = True

    def get_selection(self):
        if self._select_center_xy is None:
            return None
        frame_xy1 = self._app._cap.canvas_xy_to_frame_xy(
            self._select_center_xy[0] - self._select_radius,
            self._select_center_xy[1] + self._select_radius)
        frame_xy2 = self._app._cap.canvas_xy_to_frame_xy(
            self._select_center_xy[0] + self._select_radius,
            self._select_center_xy[1] - self._select_radius)
        return (frame_xy1, frame_xy2)
Пример #50
0
class Fretboard(StencilView, FloatLayout):
    strings = ListProperty()
    num_frets = NumericProperty(24)
    tuning = ListProperty([40, 45, 50, 55, 59, 64])
    fret_ranges = ListProperty()
    fret_positions = ListProperty()
    root_note_idx = NumericProperty(0)
    mode_filter = NumericProperty(0b101011010101)
    box_x = NumericProperty(0)
    box_y = NumericProperty(0)
    box_pos = ReferenceListProperty(box_x, box_y)
    scale_text = StringProperty("")
    notes_to_highlight = StringProperty("")
    notes_or_octaves = StringProperty("")

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.fret_bar_width = self.width * (0.1 / 24.75)
        self.relative_fret_positions = self.calc_relative_fret_positions()
        self.fret_positions = self.calc_fret_positions(self)
        self.fret_ranges = self.calc_fret_ranges(self)

        self.fingerboard = Rectangle()
        self.fret_bars = InstructionGroup()
        self.inlays = InstructionGroup()
        self._add_fret_bars()
        self._add_inlays()

        # When launching Fretboard as App, need to use canvas.before..
        self.canvas.before.add(brown)
        self.canvas.before.add(self.fingerboard)
        self.canvas.before.add(black)
        self.canvas.before.add(self.fret_bars)
        self.canvas.before.add(white)
        self.canvas.before.add(self.inlays)

    def _add_fret_bars(self):
        """Add Rectangles to display fret bars.
        Setting maximum to 24 frets (25 with nut) - the most on any common guitar.
        When less frets are chosen, some will be drawn off screen."""
        for fret in range(25):
            self.fret_bars.add(Rectangle())

    def _add_inlays(self):
        """Add Ellipses to display inlays.
        There will be a maximum of 12 for a 24-fret guitar (for a typical Fender style).
        When less frets are chosen, some will be drawn off screen."""
        for inlay in range(12):
            self.inlays.add(Ellipse())

    def calc_relative_fret_positions(self):
        """Calculate relative position of frets on a 24-fret fretboard.
        Each fret position is in the range [0, 1], where 1 is the full length of the fretboard."""
        # Ratio of fret[i]/fret[i+1] for 12-tone equal temperament.
        temperament = 2**(1 / 12)

        # All fret_pos in fret_positions represent % of guitar string; 12th fret_pos == 0.5.
        # All fret_pos in range [0, 0.75] for 24 fret guitar.
        fret_positions = [
            1 - (1 / (temperament**fret_num)) for fret_num in range(25)
        ]

        # Stretch fret_positions to represent % of fretboard instead.
        # All fret_pos now in range [0, 1].
        fret_positions = [
            fret_pos / fret_positions[-1] for fret_pos in fret_positions
        ]

        # Tricky: 0th fret cannot occur at 0; need room to its left to display open note info.
        # Move 0th fret up for nut and scale remaining appropriately.
        # All fret_pos now in range [nut_width_ratio, 1].
        nut_width_ratio = 0.03
        fret_positions = [((1 - nut_width_ratio) * fret_pos) + nut_width_ratio
                          for fret_pos in fret_positions]
        return fret_positions

    def calc_fret_positions(self, box):
        """Calculate position of each fret based on fretboard's current width."""

        # Normalize relative_fret_positions so that we only draw self.num_frets on the screen.
        # Any frets with a normalized_fret_position > 1 will be drawn off screen.
        rightmost = self.relative_fret_positions[self.num_frets]
        normalized_fret_positions = [
            fret_pos / rightmost for fret_pos in self.relative_fret_positions
        ]

        # Calculate the actual x position of each fret.
        self.fret_positions = [
            fret_pos * box.width + box.x
            for fret_pos in normalized_fret_positions
        ]
        return self.fret_positions

    def calc_fret_ranges(self, box):
        """Calculate x positions of fretboard between frets for use in displaying octaves."""
        # Gibson ratio of fret bar width to scale length.
        self.fret_bar_width = box.width * (0.1 / 24.75)
        cur_right = box.x
        fret_ranges = []
        for fret_pos in self.fret_positions:
            next_left = fret_pos - (self.fret_bar_width / 2)
            fret_ranges.append((cur_right, next_left))
            cur_right = (next_left + self.fret_bar_width)
        self.fret_ranges = fret_ranges
        return self.fret_ranges

    def update_canvas(self, *args):
        # With box now resized, recalculate & redraw everything. Having trouble drawing things
        # in order using mixture of python and kv lang. Order is explicit here.
        box = self.ids.box
        self.calc_fret_positions(box)
        self.calc_fret_ranges(box)
        self.update_fingerboard(box)
        self.update_fret_bars(box)
        self.update_inlays(box)

    def update_fingerboard(self, box):
        self.fingerboard.size = box.size
        self.fingerboard.pos = box.pos

    def update_fret_bars(self, box):
        # When adding Rectangle to InstructionGroup, BindTextures are added first.
        self.fret_bar_width = self.width * (0.1 / 24.75)
        rects = [
            obj for obj in self.fret_bars.children
            if isinstance(obj, Rectangle)
        ]
        for fret_pos, rect in zip(self.fret_positions, rects):
            x_pos = fret_pos - (self.fret_bar_width / 2)
            rect.size = [self.fret_bar_width, box.height]
            rect.pos = [x_pos, box.y]

    def update_inlays(self, box):
        inlays = [
            obj for obj in self.inlays.children if isinstance(obj, Ellipse)
        ]
        inlay_num = 0
        d = box.width * 0.01
        for i, fret_range in enumerate(self.fret_ranges):
            # Double circular inlay at fret 12.
            if i != 0 and i % 12 == 0:
                x_pos = (sum(fret_range) / 2)
                y_pos1 = (box.height / 3) + box.y
                y_pos2 = 2 * (box.height / 3) + box.y
                inlay1 = inlays[inlay_num]
                inlay2 = inlays[inlay_num + 1]
                inlay1.size = [d, d]
                inlay2.size = [d, d]
                inlay1.pos = [x_pos - d / 2, y_pos1 - d / 2]
                inlay2.pos = [x_pos - d / 2, y_pos2 - d / 2]
                inlay_num += 2
            # Single circular inlay.
            elif i in [3, 5, 7, 9, 15, 17, 19, 21]:
                x_pos = (sum(fret_range) / 2)
                y_pos = (box.height / 2) + box.y
                inlay = inlays[inlay_num]
                inlay.size = [d, d]
                inlay.pos = [x_pos - d / 2, y_pos - d / 2]
                inlay_num += 1

    def on_size(self, *args):
        """Resize the BoxLayout that holds the fretboard to maintain a guitar neck aspect ratio."""
        target_ratio = 10
        width, height = self.size
        # Check which size is the limiting factor.
        if width / height > target_ratio:
            # Window is "wider" than target, so the limitation is the height.
            self.ids.box.height = height
            self.ids.box.width = height * target_ratio
        else:
            self.ids.box.width = width
            self.ids.box.height = width / target_ratio

    def on_box_pos(self, *args):
        self.update_canvas()

    def on_num_frets(self, *args):
        self.calc_fret_positions(self)
        self.update_canvas()

    ### SONG PLAYING METHODS
    def prep_play(self,
                  flat_song: List[List[guitarpro.models.Measure]],
                  track_num=0,
                  tempo_mult=1):
        flat_track = flat_song[track_num]
        self.build_track_tuning(flat_track)
        self.build_string_play_instr(flat_song[track_num], tempo_mult)

    def build_track_tuning(self, flat_track: List[guitarpro.models.Measure]):
        # GuitarPro song doesn't have the track's guitar tuning?  Dumb.
        track_tuning = [-1] * 6
        for gp_measure in flat_track:
            for gp_voice in gp_measure.voices[:-1]:
                for gp_beat in gp_voice.beats:
                    for gp_note in gp_beat.notes:
                        string_idx = 6 - gp_note.string
                        fret_num = gp_note.value
                        note_val = gp_note.realValue
                        track_tuning[string_idx] = note_val - fret_num
                        if not any(tuning == -1 for tuning in track_tuning):
                            break

        # Possible that some strings weren't played the whole song... just assume its in standard.
        for i in range(6):
            if track_tuning[i] == -1:
                track_tuning[i] = self.tuning[i]
        self.tuning = track_tuning
        print("Fretboard.build_track_tuning ", self.tuning, "\n")

    def build_string_play_instr(self,
                                flat_track: List[guitarpro.models.Measure],
                                tempo_mult: float) -> None:
        # Build list of notes to play length of that beat in seconds.
        string_instrs = [[], [], [], [], [], []]
        for gp_measure in flat_track:
            for gp_voice in gp_measure.voices[:-1]:
                for gp_beat in gp_voice.beats:
                    beat_instr = self.build_beat_instr(gp_beat, tempo_mult)
                    for string_idx, (fret_num,
                                     seconds) in enumerate(beat_instr):
                        string_instrs[string_idx].append((fret_num, seconds))

        # Eliminate faulty ghost notes.
        for string_instr in string_instrs:
            for i, (fret_num, seconds) in enumerate(string_instr):
                if fret_num == -2:
                    string_instr[i] = (string_instr[i - 1][0], seconds)

        for i in range(6):
            self.strings[i].play_instrs = string_instrs[i]
        print("Fretboard.build_string_instr ")

    def build_beat_instr(self, gp_beat: guitarpro.models.Beat,
                         tempo_mult: float):
        tempo = gp_beat.voice.measure.tempo.value
        # results_log = open('./results_log.txt', 'a')
        # results_log.write(str(gp_beat.voice.measure.header.number) + " ")
        # results_log.write(str(gp_beat.voice.measure.tempo.value) + "\n")

        spb = 60 / (tempo * tempo_mult)
        percent_quarter_note = 4 / gp_beat.duration.value
        percent_quarter_note *= (gp_beat.duration.tuplet.times /
                                 gp_beat.duration.tuplet.enters)
        if gp_beat.duration.isDotted:
            percent_quarter_note *= 3 / 2
        elif gp_beat.duration.isDoubleDotted:
            percent_quarter_note *= 7 / 4
        seconds = spb * percent_quarter_note
        fret_nums = [-1] * 6
        for gp_note in gp_beat.notes:
            string_idx = 6 - gp_note.string
            fret_num = gp_note.value
            if gp_note.effect.ghostNote or gp_note.type.name == 'tie':
                fret_num = -2
            fret_nums[string_idx] = fret_num
        beat_instr = [fret_nums, [seconds] * 6]
        return list(zip(*beat_instr))

    def play(self, lead_in):
        for i in range(6):
            self.strings[i].play_thread(lead_in)

    def stop(self):
        for i in range(6):
            self.strings[i].stop()
Пример #51
0
class CustomBoxLayout(BoxLayout):
    def __init__(self, *args, **kwargs):
        if 'color' in kwargs:
            self.background_color = kwargs['color']
            del kwargs['color']
        else:
            self.background_color = hex_color("#333333")

        if 'border_color' in kwargs:
            self.border_color = kwargs['border_color']
            del kwargs['border_color']
        else:
            self.border_color = hex_color("#595959")

        # left, top, right, bottom
        if 'border' in kwargs:
            self.border = kwargs['border']
            if not isinstance(self.border, tuple):
                self.border = tuple([self.border] * 4)
            del kwargs['border']
        else:
            self.border = (0, 0, 0, 0)

        super(CustomBoxLayout, self).__init__(*args, **kwargs)

        self.draw_instructions = None
        self.updateDraw()

        self.bind(size=self._update_rect, pos=self._update_rect)

    def updateDraw(self):
        if self.draw_instructions is not None:
            self.canvas.before.remove(self.draw_instructions)

        self.draw_instructions = InstructionGroup()

        self.draw_instructions.add(Color(*self.border_color))
        self.border_rect = Rectangle(size=self.size, pos=self.pos)
        self.draw_instructions.add(self.border_rect)
        self.draw_instructions.add(Color(*self.background_color))
        p, s = self._get_background_rect(self.pos, self.size)
        self.rect = Rectangle(pos=p, size=s)
        self.draw_instructions.add(self.rect)

        self.canvas.before.add(self.draw_instructions)

    def updateColor(self, color):
        if color is None:
            self.background_color = hex_color("#333333")
        else:
            self.background_color = color

        self.updateDraw()

    def changeBorderColor(self, color):
        if color is None:
            self.border_color = hex_color("#595959")
        else:
            self.border_color = color

        self.updateDraw()

    def _update_rect(self, instance, value):
        self.border_rect.pos = instance.pos
        self.border_rect.size = instance.size

        p, s = self._get_background_rect(instance.pos, instance.size)
        self.rect.pos = p
        self.rect.size = s

    def _get_background_rect(self, pos, size):
        left, top, right, bottom = self.border

        bg_pos = [pos[0], pos[1]]
        bg_size = [size[0], size[1]]

        bg_pos[0] += left
        bg_size[0] -= left
        bg_pos[1] += bottom
        bg_size[1] -= bottom

        bg_size[0] -= right
        bg_size[1] -= top

        return bg_pos, bg_size
Пример #52
0
class MapViewer(ScatterPlane):
    def __init__(self, **kwargs):
        kwargs.setdefault('do_rotation', False)
        kwargs.setdefault('show_border', False)
        kwargs.setdefault('close_on_idle', False)
        kwargs.setdefault('scale_min', 1)
        super(MapViewer, self).__init__(**kwargs)  # init ScatterPlane with above parameters

        self.map = None

        self.tilesize = (0, 0)
        self.tileCache = TileCache()

        self._zoom = 0  # intern var managed by a property
        self.reticule = None
        self.show_arrow = False
        self.arrow = type('DefaultArrow', (), {'azimuth': 0})  # creation a a default object, so azimth can still be set

        self.idle = True  # used by self.update

        # variable contenant la dernière position gps
        self.last_pos = (0, 0)
        self.last_pos_wgs84 = (0, 0)

        self.locked_on_pos = False

        # The path
        self.path = None
        self.path_width = 5.0
        self.tracking_path = False
        self._path_zoom = 0  # intern var to track a zoom change

        # Layers
        self.map_layer = None
        self.path_layer = None

        # Variables relative to layers
        self.map_cleanup_scheduled = False

        # Reposition tasks
        self.reposition_executor = None

        # Finally, as every user action implies a change of x and/or y value,
        # we bind those properties change on the update
        self.bind(x=self.update, y=self.update)

    def view_map(self, _map):
        # Prepare the map
        self._prepare_map(_map)

        # Set the last pos in map coord if possible
        self._init_last_pos(_map)

        # Adding the map layer
        self.map_layer = InstructionGroup()
        self.canvas.add(self.map_layer)

        # Adding the path layer
        self.path_layer = InstructionGroup()
        self.path_layer.add(Color(1, 0, 0, 0.5))
        self.path = Line(width=self.path_width)
        self.path_layer.add(self.path)
        self.canvas.add(self.path_layer)

        # Creation of the reposition task executor
        # Update the reticule and if needed the arrow position
        self.reposition_executor = RepositionExecutor(0.1)
        if self.reticule is not None:
            self.reposition_executor.add_reposition_task(lambda: self.set_reticule_pos(*self.last_pos))
        self.reposition_executor.add_reposition_task(lambda: self.set_arrow_pos())

        # The first time we view a map we have to trigger the first tile drawing and reposition the reticule
        Clock.schedule_once(self.update_map, 0)
        self.reposition_executor.execute()

    def view_map_for_calibration(self, _map):
        # Prepare the map
        self._prepare_map(_map)

        # Adding the map layer
        self.map_layer = InstructionGroup()
        self.canvas.add(self.map_layer)

        # Creation of the reposition task executor
        self.reposition_executor = RepositionExecutor(0.1)

        # The first time we view a map we have to trigger the first tile drawing and reposition the reticule
        Clock.schedule_once(self.update_map, 0)

    def _prepare_map(self, _map):
        # Cleanup the canvas, reinitialize variables
        self.canvas.clear()
        self.idle = True
        self.scale = 1
        self.pos = 0, 0
        self.tileCache.__init__()

        self.map = _map
        self.tilesize = _map.get_tile_size()

        # Here we set the maximum scale of the Scatter, information retrieved from max_zoom in calibration.ini
        self.scale_max = pow(2, _map.get_max_zoom())

        # Save the path of the map's calibration file in application settings
        config.save_last_map_path(_map.calibration_file_path)

    def update(self, obj, value, delay=UPDATE_DELAY):
        """
        To prevent overuse of update_map, each change of position triggers an update of the map after UPDATE_DELAY sec.
        For instance, the position of the reticule has to be updated.
        """
        if self.map is None:
            return

        # Pause the Loader, to prevent ui blocking
        Loader.pause()

        # Reposition widgets that need to be repositioned
        self.reposition_executor.execute()

        # Trigger the map update
        if self.idle:
            self.idle = False
        else:
            Clock.unschedule(self.update_map)
        Clock.schedule_once(self.update_map, delay)

        # Resume the Loader after a short time
        Clock.schedule_once(MapViewer.resume_loading, 0.1)

    def update_map(self, dt):
        # First, we get the current area covered on the ScatterPlane
        area = self.get_covered_area()
        map_area = (0, 0, self.tilesize[0], self.tilesize[1])

        # Then, we make the list of tiles corresponding to that area
        tile_list = self.generate_tile_list(self.zoom, map_area, area)

        # Before drawing the tiles, we may have to perform a cleanup of the map layer
        if self.map_cleanup_scheduled:
            self.map_layer.clear()
            self.tileCache.__init__()
            self.map_cleanup_scheduled = False

        # Tiles drawing
        self.draw_tiles(tile_list)

        # We schedule a cleanup, which will be done if the app is inactive at the time of the callback execution
        Clock.schedule_once(partial(self.cleanup, tile_list), CLEANUP_DELAY)

        self.idle = True
        # logger.debug("container : %s" % self.tileCache.container.values())

        # If we are showing the path, we update its view (adjust the thickness)
        if self.tracking_path:
            self.format_path()

    @staticmethod
    def resume_loading(dt):
        Loader.resume()

    @property
    def zoom(self):
        """Get zoom from current scale"""
        # At each zoom step forward, we cover an area twice as small as the former area
        self._zoom = log(self.scale, 2)
        return self._zoom

    def get_covered_area(self):
        parent = self.parent
        xmin = parent.x
        xmax = parent.x + parent.width
        ymin = parent.y
        ymax = parent.y + parent.height

        # Coordinates in ScatterPlane
        # Here, local and window coordinates are the same because ScatterPlane's origin
        # corresponds to the windows's origin
        xmin, ymin = self.to_local(xmin, ymin)  # (x,y) coord of the bottom left corner
        xmax, ymax = self.to_local(xmax, ymax)  # (x,y) coord of the top right corner

        return xmin, ymin, xmax, ymax

    def out_of_scope(self):
        logger.debug("OUT OF SCOPE")
        return []

    @staticmethod
    def extend_tile_view(tab, maxindex):
        if len(tab):
            if tab[0] > 0:
                tab.insert(0, tab[0] - 1)
            if tab[-1] < maxindex - 1:
                tab.append(tab[-1] + 1)

    def generate_tile_list(self, zoom, map_area, area):
        """ Generates the list of tiles that should be visible for the given zoom level
         and the area visible on the scatterPlane """
        xmin0, ymin0, xmax0, ymax0 = map_area  # area for zoom=0, one unique tile
        xmin, ymin, xmax, ymax = area

        # Overlap test
        if xmax <= xmin0 or xmin >= xmax0 or ymin >= ymax0 or ymax <= ymin0:
            return self.out_of_scope()

        # coordinates of the intersection between map_area and area
        xmin_inter = max(xmin0, xmin)
        xmax_inter = min(xmax0, xmax)
        ymin_inter = max(ymin0, ymin)
        ymax_inter = min(ymax0, ymax)

        # If the current zoom is already an integer, we take its value.
        # Otherwise, we take its superior int value because we want to
        # identify which tiles of the next zoom level have to be displayed
        zoom_int = int(zoom if zoom == int(zoom) else int(zoom) + 1)
        targeted_scale = pow(2, zoom_int)
        tile_width = (xmax0 - xmin0) / float(targeted_scale)

        startx_index = int(xmin_inter / tile_width)
        endx_index = int(xmax_inter / tile_width)

        # Calculation of the indexes on x axis
        x_indexes = []
        append = x_indexes.append
        for x in range(startx_index, endx_index + 1):
            append(x)
        MapViewer.extend_tile_view(x_indexes, targeted_scale)

        starty_index = int(ymin_inter / tile_width)
        endy_index = int(ymax_inter / tile_width)

        # Calculation of the indexes on y axis
        y_indexes = []
        append = y_indexes.append
        for y in range(starty_index, endy_index + 1):
            append(y)
        MapViewer.extend_tile_view(y_indexes, targeted_scale)

        tile_list = []
        append = tile_list.append
        for x in x_indexes:
            for y in y_indexes:
                tile = Tile()
                # tile.canvas = self.canvas
                tile.pos = Vector(x, y) * tile_width
                tile.size = (tile_width, tile_width)
                tile.x = x
                tile.y = y
                tile.zoom = zoom_int
                append(tile)

        return tile_list

    # The good damn right way to do it
    def draw_tile(self, proxy):
        if proxy.image.texture:
            self.map_layer.add(
                Rectangle(pos=proxy.pos, size=proxy.size, texture=proxy.image.texture, group=proxy.zoom))

    def draw_tiles(self, tile_list):
        for tile in tile_list:
            image_id = tile.get_id()
            if self.tileCache.add_tile(tile.zoom, image_id):
                image = self.map.get_tile(tile.zoom, tile.x, tile.y)
                if image is None:
                    continue
                image.create_property("pos", tile.pos)
                image.create_property("size", tile.size)
                image.create_property("zoom", str(int(tile.zoom)))
                image.bind(on_load=self.draw_tile)
                # if image.loaded:    # only useful when Loader actually caches images
                #     image.dispatch("on_load")

    def cleanup(self, tile_list, *largs):
        """
        Cleanup is achieved when the app is considered inactive, ie when self.idle = True.
        """
        if not self.idle:
            return
        zoom = self.zoom
        zoom_int = int(zoom if zoom == int(zoom) else int(zoom) + 1)

        print "debut cleanup, conserve zoom", zoom_int
        for _zoom in TileCache.get_unnecessary_zooms(self.tileCache.container.keys(), zoom_int):
            try:
                print "suppr zoom", _zoom
                self.map_layer.remove_group(str(_zoom))
                self.tileCache.remove_tiles_for_zoom(_zoom)
            except:
                logger.debug("the canvas doesn't contains the zoom %s" % _zoom)

        if self.tileCache.is_tile_overfull(zoom_int):
            self.map_cleanup_scheduled = True

        # logger.debug("cleanup done, container : %s" % self.tileCache.container.values())

    def set_reticule(self, reticule):
        self.reticule = reticule

    def set_reticule_pos(self, x, y):
        """
        :param x: x position on the map in the range [0,tile_width]
        :param y: y position on the map in the range [0,tile_height]
        :return:
        """
        # TODO : remplacer cette méthode par set_movable_widget_pos ? (cf plus bas)
        self.reticule.set_center_x(self.x + x * self.scale)
        self.reticule.set_center_y(self.y + y * self.scale)

    def set_movable_widget_pos(self, widget, x, y):
        """
        Position a widget given the local coordinates of its center.
        :param x: x position on the map in the range [0,tile_width]
        :param y: y position on the map in the range [0,tile_height]
        """
        if widget:
            widget.set_center_x(self.x + x * self.scale)
            widget.set_center_y(self.y + y * self.scale)

    def add_movable_widget(self, widget):
        """Actions done when a movable widget is added to the MapViewer."""

        # Add a reposition task
        self.reposition_executor.add_reposition_task(lambda: self.set_movable_widget_pos(
            widget, *widget.pos_local))

    def set_arrow_pos(self):
        """Must be called after set_reticule_pos"""
        if self.show_arrow:
            self.arrow.set_center_x(self.reticule.get_center_x())
            self.arrow.set_center_y(self.reticule.get_center_y())

    def set_orientation_arrow(self, arrow):
        self.show_arrow = True
        self.arrow = arrow

    def update_azimuth(self, instance, angle):
        self.arrow.azimuth = -angle

    def _init_last_pos(self, _map):
        """Initialize the last position in the _map projection coordinates, given the last known wgs84 position.
        This is used in view_map method.
        """
        if self.last_pos_wgs84 is not None:
            self.last_pos = _map.get_map_coord(*self.last_pos_wgs84)
        else:
            self.last_pos = (0, 0)

    def update_pos(self, instance, value):
        # Remember the position, even if there is no map
        self.last_pos_wgs84 = value

        # If there is no map, no need to go further
        if self.map is None:
            return

        # Conversion from wgs84 coord to map coord
        x, y = self.map.get_map_coord(*value)

        # Remember this position too
        self.last_pos = x, y

        # Update the reticule pos
        self.set_reticule_pos(x, y)

        # Update the orientation arrow pos if necessary
        if self.show_arrow:
            self.set_arrow_pos()

        # Update the path
        if self.tracking_path:
            self.update_path(x, y)

        # If we are locked on pos, we center the view on the last known position
        if self.locked_on_pos:
            self.center_on_last_pos()

    def update_path(self, x, y):
        self.path.points += x, y

    def toggle_tracking_path(self, obj):
        if self.tracking_path:
            self.tracking_path = False
            # Creation of a new path
            self.path = Line(width=self.path_width)
        else:
            self.tracking_path = True

    def format_path(self, *args):
        """This updates the width of the path to be consistent with the scale.
        """
        if self._path_zoom != self.zoom:
            self.path.width = self.path_width / self.scale
            self._path_zoom = self.zoom

    def center_on_last_pos(self, *args):
        scale = self.scale
        new_x = Window.size[0]/2 - self.last_pos[0]*scale
        new_y = Window.size[1]/2 - self.last_pos[1]*scale
        Animation.cancel_all(self)
        anim = Animation(x=new_x, y=new_y, t='in_out_quad', duration=0.5)
        anim.start(self)

    def get_dist_to_center(self):
        """
        :return: The distance in meters between the last known position and the position represented by the middle
        of the screen. If no distance can be calculated, it returns -1.
        """
        if self.map is None:
            return -1
        try:
            merc_x, merc_y = self.map.map_coord_to_map_projection(*self.to_local(Window.size[0]/2, Window.size[1]/2))
        except ZeroDivisionError:
            return -1
        lat, lon = Map.to_geographic(merc_x, merc_y)
        lat_last, lon_last = self.last_pos_wgs84
        dist = Map.distance(lat_last, lon_last, lat, lon)
        return dist

    def transform_with_touch(self, touch):
        if self.locked_on_pos:
            if len(self._touches) == 1:
                return False

            changed = False
            # We have more than one touch... list of last known pos
            points = [Vector(self._last_touch_pos[t]) for t in self._touches
                      if t is not touch]
            # Add current touch last
            points.append(Vector(touch.pos))

            # We only want to transform if the touch is part of the two touches
            # farthest apart! So first we find anchor, the point to transform
            # around as another touch farthest away from current touch's pos
            anchor_ = max(points[:-1], key=lambda p: p.distance(touch.pos))

            # Now we find the touch farthest away from anchor, if its not the
            # same as touch. Touch is not one of the two touches used to transform
            farthest = max(points, key=anchor_.distance)
            if farthest is not points[-1]:
                return changed

            # Ok, so we have touch, and anchor, so we can actually compute the
            # transformation
            old_line = Vector(*touch.ppos) - anchor_
            new_line = Vector(*touch.pos) - anchor_
            if not old_line.length():   # div by zero
                return changed

            # pol : we don't want rotation here
            # angle = radians(new_line.angle(old_line)) * self.do_rotation
            # self.apply_transform(Matrix().rotate(angle, 0, 0, 1), anchor=anchor)

            # pol : trick -> change the origin!!
            anchor = Vector(self.to_parent(*self.last_pos))
            if self.do_scale:
                scale = new_line.length() / old_line.length()
                new_scale = scale * self.scale
                if new_scale < self.scale_min:
                    scale = self.scale_min / self.scale
                elif new_scale > self.scale_max:
                    scale = self.scale_max / self.scale
                self.apply_transform(Matrix().scale(scale, scale, scale),
                                     anchor=anchor)
                changed = True
            return changed

        super(MapViewer, self).transform_with_touch(touch)
Пример #53
0
class ScatterBase(ScatterLayout):
    name = StringProperty()
    _hold_triggered = BooleanProperty(False)
    selected = BooleanProperty(False)
    scale_min = NumericProperty(.2)
    do_rotation = BooleanProperty(False)
    do_scale = BooleanProperty(False)
    do_translation = BooleanProperty(False)
    parent_width = NumericProperty()
    parent_height = NumericProperty()

    # Check if the touch collides with any of the children widgets
    def collide_point(self, x, y):
        local_x,local_y = self.to_local(x, y)
        for child in self.content.walk(restrict=True):
            if child==self.content:
                continue
            if child.collide_point(local_x, local_y):
                return True
        return False

    def get_full_bbox_parent(self, *args):
        all_corners = []
        # Can also iterate through self.content.walk(restrict=True), but takes longer
        for child in self.content.children:
            if child == self.content:
                continue
            all_corners += [child.pos, (child.x, child.top), (child.right, child.y), (child.right, child.top)]
        all_corners_parent = [self.to_parent(*point) for point in all_corners]
        xmin = min([point[0] for point in all_corners_parent])
        ymin = min([point[1] for point in all_corners_parent])
        xmax = max([point[0] for point in all_corners_parent])
        ymax = max([point[1] for point in all_corners_parent])
        return (xmin, ymin), (xmax-xmin, ymax-ymin)
    full_bbox_parent = AliasProperty(get_full_bbox_parent, None)

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            self._hold_triggered = False

            # If this is the "selected widget", treat as a movable scatter
            if self.selected:
                return super(ScatterBase, self).on_touch_down(touch)

            # Only detect on_hold if there is no currently selected widget
            if not self.selected:
                Clock.schedule_once(self.on_hold, .6)

    def on_touch_up(self,touch):

        # Unschedule on_hold for short presses
        if not self._hold_triggered:
            Clock.unschedule(self.on_hold)

        if self.selected:
            super(ScatterBase, self).on_touch_up(touch)

    def on_hold(self, *args):
        app = App.get_running_app()

        # 1. If already selected, do nothing
        if self.selected:
            return

        # 2. If a selected widget already exists, do nothing
        if not app.root.manager.layout_screen.selected_widget:
            self._hold_triggered = True
            app.root.manager.layout_screen.edit_widget(self)

    def on_transform_with_touch(self,*args):
        self.check_widget()

    # When widget is changed, check to make sure it is still in bounds of mirror
    def check_widget(self, *args):
        (bbox_x,bbox_y),(bbox_width,bbox_height) = self.full_bbox_parent

        # 1. Size check
        if bbox_width > self.parent_width:
            widget_to_bbox_ratio = bbox_width/self.parent_width
            self.scale = self.scale/widget_to_bbox_ratio
        if bbox_height > self.parent_height:
            widget_to_bbox_ratio = bbox_height/self.parent_height
            self.scale = self.scale/widget_to_bbox_ratio

        # 2. Translation check - Make sure widget is within mirror
        bbox_right = bbox_x+bbox_width
        bbox_top = bbox_y+bbox_height
        if bbox_x < 0:
            self.x -= bbox_x
        if bbox_right > self.parent_width:
            self.x += self.parent_width - bbox_right
        if bbox_y < 0:
            self.y -= bbox_y
        if bbox_top > self.parent_height:
            self.y += self.parent_height - bbox_top

    def select(self, *args):

        # 0. Set as selected
        self.selected = True

        # 1. Locate outermost bounding box of widget
        all_corners = []
        for widget in self.content.walk(restrict=True):
            if widget == self.content:
                continue
            all_corners += [widget.pos, (widget.x, widget.top), (widget.right, widget.y), (widget.right, widget.top)]
        xmin = min([point[0] for point in all_corners])
        ymin = min([point[1] for point in all_corners])
        xmax = max([point[0] for point in all_corners])
        ymax = max([point[1] for point in all_corners])

        # 2. Draw outline around widget
        self.outline = InstructionGroup()
        self.outline.clear()
        self.outline.add(Color(.67, .816, .95, 1))
        self.outline.add(Line(points=[xmin, ymin, xmax, ymin, xmax, ymax, xmin, ymax],
                              width=2,
                              joint='none',
                              close=True))
        self.canvas.add(self.outline)

        # 3. Bring to front, make movable
        self.do_translation = True
        self.do_scale = True
        if self.rotation != 0:
            self.do_rotation = True
        self.auto_bring_to_front = True

    def unselect(self, *args):

        # 0. Deselect
        self.selected = False

        # 1. Remove outline
        self.canvas.remove(self.outline)

        # 2. Lock widget
        self.do_translation = False
        self.do_scale = False
        self.do_rotation = False
        self.auto_bring_to_front = False
Пример #54
0
    def _drawLine(self, preClose, aDict, dispIdx, isLastFlag):
        """
        
        """
        groupStr = self.instGroup
        if isLastFlag == True:
            groupStr += "_lastData"
        else:
            groupStr += "_curvData"

        instg = InstructionGroup(group=groupStr)
        color = Color()

        volume = aDict.get("VOL")

        closePrice = aDict.get("CP")
        if closePrice > preClose:
            color.rgba = self.UP_COLOR
            instg.add(color)
            x1 = self.chartPos[0] + dispIdx * (self.tickWide +
                                               self.tickGap) + self.tickGap
            y1 = self.chartPos[1]
            instg.add(
                Rectangle(pos=(x1, y1),
                          size=(self.tickWide,
                                (volume - self.lowestValue) * self.yscale)))
        elif closePrice < preClose:
            color.rgba = self.DOWN_COLOR
            instg.add(color)
            x1 = self.chartPos[0] + dispIdx * (self.tickWide +
                                               self.tickGap) + self.tickGap
            y1 = self.chartPos[1]
            instg.add(
                Rectangle(pos=(x1, y1),
                          size=(self.tickWide,
                                (volume - self.lowestValue) * self.yscale)))
        else:
            color.rgba = self.EQUAL_COLOR
            instg.add(color)
            x1 = self.chartPos[0] + dispIdx * (self.tickWide +
                                               self.tickGap) + self.tickGap
            y1 = self.chartPos[1]
            instg.add(
                Rectangle(pos=(x1, y1),
                          size=(self.tickWide,
                                (volume - self.lowestValue) * self.yscale)))

        self.canvas.add(instg)
Пример #55
0
class Piece(SparseGridLayout, TetrisAware):
    map = ListProperty([])

    def __init__(self, color=(1, 1, 1, 1), **kwargs):
        self.color = color

        self.size_hint = (None, None)
        super(SparseGridLayout, self).__init__(**kwargs)

        self.bind(map=self.on_map)

        self.keyboard = App.get_running_app().keyboard
        self.keyboard.bind(
            on_key_down=self.on_keypress,
            on_key_up=self.on_keyrelease
        )

        self.base_delay = self.keyboard.repeat_delay
        self.base_speed = self.keyboard.repeat_speed

        self.vertical = False

        """
        One may wonder, when entering the realms of Piece.update(), "what exactly is delay_lambda?".

        It is what makes a piece remain controllable after having touched the ground, for a static duration (.5).

        It is checked in move() and rotate() - if check_lock notices the Piece isn't right above the ground anymore, it
        triggers "normal" gravity back by calling on_parent. Finally, the lock timeout is necessarily called after the
        static duration (.5), to lock the piece if its height hasn't changed (we discard the false-positive if it has).
        """
        self.delay_lambda = None

    def on_parent(self, *args):
        if self.parent:
            level = self.parent.parent.level
            Clock.schedule_interval(
                self.update,
                .5 * (.75 + (.05 * (4 - (level % 4)))) ** level
            )

    def on_map(self, instance, value):
        current_child = 0
        for y in range(len(self.map)):
            for x in range(len(self.map[y])):
                if self.map[y][x] == 'x':
                    if len(self.children) < sum(line.count('x') for line in self.map):
                        self.add_widget(Block(coords=(x, y), color=self.color))
                    else:
                        self.children[current_child].coords = (x, y)
                        current_child += 1
        self.do_layout()

    def update(self, *args):
        if not self.parent:
            Clock.unschedule(self.update)
            self.keyboard_closed()
            return

        if self.tetris_coords[1] == 0 or self.collide_piece('down'):
            self.do_layout()
            self.remove_children()
            self.keyboard_closed()

            self.parent.check_line()
            self.parent.parent.spawn.new_piece()

            if self.parent:
                self.parent.remove_widget(self)
        else:
            self.tetris_coords[1] -= 1

            self.check_lock(retrigger=True)

    def check_lock(self, retrigger=False):
        if not self.delay_lambda and (self.tetris_coords[1] == 0 or self.collide_piece('down')):
            self.trigger_lock()
        elif self.delay_lambda and (self.tetris_coords[1] > 0 and not self.collide_piece('down')):
            self.reset_lock()
        elif retrigger and self.delay_lambda:
            Clock.unschedule(self.delay_lambda)
            self.trigger_lock()


    def trigger_lock(self):
        Clock.unschedule(self.update)
        y = self.tetris_coords[1]

        self.delay_lambda = lambda *args: self.lock_timeout(y)
        Clock.schedule_once(self.delay_lambda, .5)

    def reset_lock(self):
        self.on_parent()

        Clock.unschedule(self.delay_lambda)
        self.delay_lambda = None

    def lock_timeout(self, y):
        if self.tetris_coords[1] == y:
            self.update()
            self.on_parent()

        self.delay_lambda = None

    def remove_children(self):
        for child in self.children[:]:
            child.pos_hint = {}
            self.remove_widget(child)
            self.parent.add_widget(child)

    def collide_piece(self, direction='down', map=[], coords=[]):
        if self.parent:
            for child in self.parent.children:
                if hasattr(child, 'tetris_coords') and child != self:
                    if direction == 'cw' or direction == 'ccw':
                        for y in range(len(map)):
                            for x in range(len(map[y])):
                                if map[y][x] == 'x':
                                    if coords[0] + x == child.tetris_coords[0]\
                                       and coords[1] + y == child.tetris_coords[1]:
                                            return True
                    else:
                        for own_child in self.children:
                            if direction == 'down':
                                if own_child.tetris_coords[1] - 1 == child.tetris_coords[1]\
                                   and own_child.tetris_coords[0] == child.tetris_coords[0]:
                                    return True
                            if direction == 'left':
                                if own_child.tetris_coords[0] - 1 == child.tetris_coords[0]\
                                   and own_child.tetris_coords[1] == child.tetris_coords[1]:
                                    return True
                            if direction == 'right':
                                if own_child.tetris_coords[0] + 1 == child.tetris_coords[0]\
                                   and own_child.tetris_coords[1] == child.tetris_coords[1]:
                                    return True
                            if direction == 'current':
                                if own_child.tetris_coords[0] == child.tetris_coords[0]\
                                   and own_child.tetris_coords[1] == child.tetris_coords[1]:
                                    return True

        return False

    def on_tetris_coords(self, *args):
        if hasattr(self, 'map') and self.parent:
            if self.tetris_coords[0] < 0:
                self.tetris_coords[0] = 0
            if self.tetris_coords[0] + len(self.map[0]) > self.parent.cols:
                self.tetris_coords[0] = self.parent.cols - len(self.map[0])
            if self.tetris_coords[1] < 0:
                self.tetris_coords[1] = 0
            if self.tetris_coords[1] + len(self.map) > self.parent.rows:
                self.tetris_coords[1] = self.parent.rows - len(self.map)

        if hasattr(self.parent, 'coord_to_pos'):
            self.pos = self.parent.coord_to_pos(*self.tetris_coords)

        for child in self.children:
            child.tetris_coords = [self.tetris_coords[0] + child.col, self.tetris_coords[1] + child.row]

    def do_layout(self, *args):
        super(Piece, self).do_layout(*args)

        if hasattr(self, 'outline'):
            self.canvas.before.remove(self.outline)

        self.outline = InstructionGroup()
        for child in self.children:
            self.outline.add(Color(.5, .8, 1, .8))
            self.outline.add(Line(
                points=[
                    child.x - 1, child.y - 1,
                    child.right + 1, child.y - 1,
                    child.right + 1, child.top + 1,
                    child.x - 1, child.top + 1
                ],
                close=True,
                width=1.5
            ))

        if self.canvas.before:
            self.canvas.before.add(self.outline)

            if len(self.children) == 0:
                if hasattr(self, 'outline'):
                    self.canvas.before.remove(self.outline)

    def move(self, direction):
        if direction == 'left' and not self.collide_piece('left'):
            self.tetris_coords[0] -= 1
        if direction == 'right' and not self.collide_piece('right'):
            self.tetris_coords[0] += 1
        if direction == 'down':
            self.keyboard.repeat_delay = 0
            self.keyboard.repeat_speed /= 4

            self.update()

        self.check_lock()

    def rotate(self, **kwargs):
        direction = 'ccw'
        if 'direction' in kwargs:
            direction = kwargs['direction']

        new_map = self.rotate_map(direction)
        new_coords = self.rotate_coords(new_map)

        if self.collide_piece(direction, new_map, new_coords):
            return

        self.vertical = not self.vertical

        self.map = new_map

        self.tetris_coords = new_coords

        self.check_lock()

    def rotate_map(self, direction):
        new_map = zip(*self.map[::-1])
        if direction == 'cw':
            for i in range(2):
                new_map = zip(*new_map[::-1])

        return new_map

    def rotate_coords(self, new_map):
        map_diff = [
            len(self.map[0]) - len(new_map[0]),
            len(self.map) - len(new_map)
        ]

        for i in range(len(map_diff)):
            if self.vertical:
                map_diff[i] = floor(map_diff[i] / 2.)
            else:
                map_diff[i] = ceil(map_diff[i] / 2.)

        return self.tetris_coords[0] + map_diff[0], self.tetris_coords[1] + map_diff[1]

    def on_keypress(self, keyboard, key, keycode, modifiers):
        self.reset_keyboard_repeat()
        if key == 113: # 'q' on qwerty
            self.rotate(direction='ccw')
        elif key == 101: # 'e'
            self.rotate(direction='cw')
        elif key == 97: # 'a' on qwerty
            self.move('left')
        elif key == 100: # 'd'
            self.move('right')
        elif key == 115: # 's'
            self.move('down')
        elif key == 122: # 'z' on qwerty
            self.rotate(direction='ccw')
        elif key == 120: # 'x'
            self.rotate(direction='cw')
        elif key == 276: # left arrow
            self.move('left')
        elif key == 275: # right arrow
            self.move('right')
        elif key == 273: # up arrow
            self.rotate(direction='ccw')
        elif key == 274: # down arrow
            self.move('down')
        else:
            return True

        return False

    def on_keyrelease(self, keyboard, keycode):
        self.reset_keyboard_repeat()

    def reset_keyboard_repeat(self):
        self.keyboard.repeat_delay = self.base_delay
        self.keyboard.repeat_speed = self.base_speed

    def keyboard_closed(self):
        self.reset_keyboard_repeat()
        self.keyboard.unbind(
            on_key_down=self.on_keypress,
            on_key_up=self.on_keyrelease
        )