Esempio n. 1
0
class Starfield(Widget):
    def __init__(self, **kwargs):
        Widget.__init__(self, **kwargs)
        self.canvas = RenderContext(use_parent_projection=True)
        self.canvas.shader.source = 'starfield.glsl'

        self.vfmt = (
            ('vCenter',     2, 'float'),
            ('vScale',      1, 'float'),
            ('vPosition',   2, 'float'),
            ('vTexCoords0', 2, 'float'),
        )

        self.vsize = sum(attr[1] for attr in self.vfmt)

        self.indices = []
        for i in xrange(0, 4 * NSTARS, 4):
            self.indices.extend((
                i, i + 1, i + 2, i + 2, i + 3, i))

        self.vertices = []
        for i in xrange(NSTARS):
            self.vertices.extend((
                0, 0, 1, -24, -24, 0, 1,
                0, 0, 1,  24, -24, 1, 1,
                0, 0, 1,  24,  24, 1, 0,
                0, 0, 1, -24,  24, 0, 0,
            ))

        self.texture = Image('star.png').texture

        self.stars = [Star(self, i) for i in xrange(NSTARS)]

    def update_glsl(self, nap):
        x0, y0 = self.center
        max_distance = 1.1 * max(x0, y0)

        for i in xrange(NSTARS):
            star = self.stars[i]
            star.distance *= 2 * nap + 1
            star.size += 0.25 * nap

            if (star.distance > max_distance):
                star.reset()
            else:
                star.update(x0, y0)

        self.canvas.clear()

        with self.canvas:
            Mesh(fmt=self.vfmt, mode='triangles',
                 indices=self.indices, vertices=self.vertices,
                 texture=self.texture)
Esempio n. 2
0
File: main.py Progetto: tadachi/kb
class PSWidget(Widget):
    indices = []
    vertices = []
    particles = []

    def __init__(self, **kwargs):
        Widget.__init__(self, **kwargs)
        self.canvas = RenderContext(use_parent_projection=True)
        self.canvas.shader.source = self.glsl

        self.vfmt = (
            ('vCenter', 2, 'float'),
            ('vScale', 1, 'float'),
            ('vPosition', 2, 'float'),
            ('vTexCoords0', 2, 'float'),
        )

        self.vsize = sum(attr[1] for attr in self.vfmt)

        self.texture, self.uvmap = load_atlas(self.atlas)

    def make_particles(self, Cls, num):
        count = len(self.particles)
        uv = self.uvmap[Cls.tex_name]

        for i in xrange(count, count + num):
            j = 4 * i
            self.indices.extend((
                j, j + 1, j + 2, j + 2, j + 3, j))

            self.vertices.extend((
                0, 0, 1, -uv.su, -uv.sv, uv.u0, uv.v1,
                0, 0, 1,  uv.su, -uv.sv, uv.u1, uv.v1,
                0, 0, 1,  uv.su,  uv.sv, uv.u1, uv.v0,
                0, 0, 1, -uv.su,  uv.sv, uv.u0, uv.v0,
            ))

            p = Cls(self, i)
            self.particles.append(p)

    def update_glsl(self, nap):
        for p in self.particles:
            p.advance(nap)
            p.update()

        self.canvas.clear()

        with self.canvas:
            Mesh(fmt=self.vfmt, mode='triangles',
                 indices=self.indices, vertices=self.vertices,
                 texture=self.texture)
Esempio n. 3
0
class Screen(Widget):
    def __init__(self, **kwargs):
        self.canvas = RenderContext()
        self.pressed_keys = set()

        Window.bind(on_key_down=self.key_down)
        Window.bind(on_key_up=self.key_up)

        super().__init__(**kwargs)

    def key_down(self, _, key, *args):
        self.pressed_keys.add(key)

    def key_up(self, _, key, *args):
        self.pressed_keys.discard(key)

    def render(self, delta):
        """Override this method and render graphics"""

    def update(self, delta):
        """Override this method for updating state"""

    def on_create(self):
        """Called when initialized from screen manager"""

    def on_destroy(self):
        """Called when removed from screen manager"""

    def on_open(self):
        """Called when the screen is opened"""

    def on_close(self):
        """Called when the screen is closed"""

    def on_resize(self, width: int, height: int):
        """Called on window resize"""

    def clear(self):
        self.canvas.clear()

    def set_projection_matrix(self, matrices):
        self.canvas['projection_mat'] = matrices[0]
        self.canvas['modelview_mat'] = matrices[1]

    def render_screen(self, delta):
        """Wrapper method for render, should not be overrided"""
        with self.canvas:
            self.render(delta)
Esempio n. 4
0
File: main.py Progetto: tadachi/kb
class PSWidget(Widget):
    indices = []
    vertices = []
    particles = []

    def __init__(self, **kwargs):
        Widget.__init__(self, **kwargs)
        self.canvas = RenderContext(use_parent_projection=True)
        self.canvas.shader.source = self.glsl

        self.vfmt = (
            ('vCenter', 2, 'float'),
            ('vScale', 1, 'float'),
            ('vPosition', 2, 'float'),
            ('vTexCoords0', 2, 'float'),
        )

        self.vsize = sum(attr[1] for attr in self.vfmt)

        self.texture, self.uvmap = load_atlas(self.atlas)

    def make_particles(self, Cls, num):
        count = len(self.particles)
        uv = self.uvmap[Cls.tex_name]

        for i in xrange(count, count + num):
            j = 4 * i
            self.indices.extend((j, j + 1, j + 2, j + 2, j + 3, j))

            self.vertices.extend((
                0,
                0,
                1,
                -uv.su,
                -uv.sv,
                uv.u0,
                uv.v1,
                0,
                0,
                1,
                uv.su,
                -uv.sv,
                uv.u1,
                uv.v1,
                0,
                0,
                1,
                uv.su,
                uv.sv,
                uv.u1,
                uv.v0,
                0,
                0,
                1,
                -uv.su,
                uv.sv,
                uv.u0,
                uv.v0,
            ))

            p = Cls(self, i)
            self.particles.append(p)

    def update_glsl(self, nap):
        for p in self.particles:
            p.advance(nap)
            p.update()

        self.canvas.clear()

        with self.canvas:
            Mesh(fmt=self.vfmt,
                 mode='triangles',
                 indices=self.indices,
                 vertices=self.vertices,
                 texture=self.texture)
Esempio n. 5
0
class Console(Widget):
    _vertices = []
    _indices = []
    _vfmt = (
        (b'vCenter', 2, 'float'),
        (b'vPosition', 2, 'float'),
        (b'vTexCoords0', 2, 'float'),
        (b'vColor', 3, 'float'),
        (b'isTexFlag', 1, 'float'),
    )
    _vsize = sum(i[1] for i in _vfmt)
    _fg_color = (1.0, 1.0, 1.0)
    _bg_color = (0.0, 0.0, 0.0)
    _shader = 'console.glsl'
    _font_source = 'terminal8x12_gs_ro.png'
    _font_size = (8, 12)

    def __init__(self, screen_size, font_source=None, font_size=None,
                 fg_color=None, bg_color=None,
                 **kwargs):
        super().__init__(**kwargs)
        self.screen_size = screen_size
        self.fg_color = fg_color or self._fg_color
        self.bg_color = bg_color or self._bg_color
        self.font_source = font_source or self._font_source
        self.font_size = font_size or self._font_size
        self.font_tex, self.font_map = load_font(self.font_source,
                                                 self.font_size)

        self.canvas = RenderContext(use_parent_projection=True)
        self.canvas.shader.source = self._shader
        self.console_bg_color()

    @property
    def max_indice(self):
        return max(self._indices) + 1 if self._indices else 0

    def get_pixel_pos(self, pos, is_bg=False):
        font_w, font_h = self.font_size
        tx, ty = pos
        w, h = font_w * 0.5, font_h * 0.5
        x, y = (tx * font_w) + w, (ty * font_h) + h

        if is_bg:
            x, y = tx * font_w, ty * font_h

        return x, y

    def get_console_pos(self, pos):
        # TODO: Assuming that the pos coords could be referring to any pixel
        #       within the font size, I need to get the relative bottom right
        #       coords and use that for the tx, ty values instead. This will
        #       increase the accuracy of the translation.
        font_w, font_h = self.font_size
        tx, ty = pos
        x, y = tx / font_w, ty / font_h

        return round(x, 0), round(y, 0)

    def console_bg_color(self):
        self.put_rect((0, 0), self.screen_size, self.bg_color)

    def put_char(self, char, pos, color=None):
        x, y = self.get_pixel_pos(pos)

        r, g, b = color or self.fg_color
        idx = self.max_indice
        uv = self.font_map.get(ord(char)) or self.uvmap.get(ord(' '))

        self._vertices.extend((
            x, y, -uv.su, -uv.sv, uv.u0, uv.v1, r, g, b, 1,
            x, y, uv.su, -uv.sv, uv.u1, uv.v1, r, g, b, 1,
            x, y, uv.su, uv.sv, uv.u1, uv.v0, r, g, b, 1,
            x, y, -uv.su, uv.sv, uv.u0, uv.v0, r, g, b, 1,
        ))
        self._indices.extend((
            idx, idx + 1, idx + 2,
            idx + 2, idx + 3, idx
        ))

    def put_bg_color(self, pos, color):
        font_w, font_h = self.font_size
        x, y = self.get_pixel_pos(pos, is_bg=True)

        r, g, b = color
        idx = self.max_indice

        self._vertices.extend((
            x, y, 0, 0, 0, 0, r, g, b, 0,
            x, y, font_w, 0, 0, 0, r, g, b, 0,
            x, y, font_w, font_h, 0, 0, r, g, b, 0,
            x, y, 0, font_h, 0, 0, r, g, b, 0,
        ))
        self._indices.extend((
            idx, idx + 1, idx + 2,
            idx + 2, idx + 3, idx
        ))

    def put_text(self, text, pos, color=None, wrap=None):
        x, y = pos
        start_x = x
        ctr = 0
        for char in iter(text):
            if isinstance(wrap, int) and ctr >= wrap:
                ctr = 0
                x = start_x
                y -= 1

            if not char.strip() and x == start_x:
                continue

            self.put_char(char, pos=(x, y), color=color)
            x += 1
            ctr += 1

    def put_rect(self, pos, size, color):
        font_w, font_h = self.font_size
        w, h = size
        x, y = self.get_pixel_pos(pos, is_bg=True)

        r, g, b = color
        idx = self.max_indice

        self._vertices.extend((
            x, y, 0, 0, 0, 0, r, g, b, 0,
            x, y, w * font_w, 0, 0, 0, r, g, b, 0,
            x, y, w * font_w, h * font_h, 0, 0, r, g, b, 0,
            x, y, 0, h * font_h, 0, 0, r, g, b, 0,
        ))
        self._indices.extend((
            idx, idx + 1, idx + 2,
            idx + 2, idx + 3, idx
        ))

    def flush(self):
        self.canvas.clear()
        with self.canvas:
            Mesh(fmt=self._vfmt, mode='triangles',
                 indices=self._indices, vertices=self._vertices,
                 texture=self.font_tex)
Esempio n. 6
0
 def clear(self, canvas: RenderContext):
     canvas.clear()
Esempio n. 7
0
class PSWidget(Widget):
    """ Abstract class to handle all sprite rendering

    An instance of this renderer will only hold a single source of texture.

    """
    indices = []
    vertices = []
    particles = []

    def __init__(self, **kwargs):
        super(PSWidget, self).__init__(**kwargs)
        self.canvas = RenderContext(use_parent_projection=True)
        self.canvas.shader.source = self.glsl

        self.vfmt = (
            (b'vCenter', 2, 'float'),
            (b'vScale', 1, 'float'),
            (b'vPosition', 2, 'float'),
            (b'vTexCoords0', 2, 'float'),
        )

        self.vsize = sum(attr[1] for attr in self.vfmt)

        self.texture, self.uvmap = load_atlas(self.atlas)

    def make_particles(self, Cls, num):
        """ Convenience method to add a large number (`num`) of similar
        particles 


        Parameters
        ----------

        Cls (obj) - Particle class instance. This should implement a `tex_name`
            property to lookup the correct sprite in the UV mapping.

        num (int) - Number of particles to add.

        """
        count = len(self.particles)
        uv = self.uvmap[Cls.tex_name]

        for i in range(count, count + num):
            j = 4 * i
            self.indices.extend((
                j, j + 1, j + 2, j + 2, j + 3, j))
            self.vertices.extend((
                0, 0, 1, -uv.su, -uv.sv, uv.u0, uv.v1,
                0, 0, 1, uv.su, -uv.sv, uv.u1, uv.v1,
                0, 0, 1, uv.su, uv.sv, uv.u1, uv.v0,
                0, 0, 1, -uv.su, uv.sv, uv.u0, uv.v0,
            ))

            p = Cls(self, i)
            self.particles.append(p)

    def update_glsl(self, nap):
        """ Update the canvas.

        NOTES: Take the ff. into consideration when optimization is necessary:

        The particles update loop:
        - This loop should parallelized in full or partially.
        - This could also be run on another thread completely, and not update
            on every frame. This may apply to selected particle sub-classes,
            i.e. stuff in the background that doesn't affect program flow.


        Parameters
        ----------

        nap (float) - TODO

        """
        # Update the state of all particles
        for p in self.particles:
            p.advance(nap)
            p.update()

        # Draw the changes
        self.canvas.clear()
        with self.canvas:
            Mesh(fmt=self.vfmt, mode='triangles', indices=self.indices,
                 vertices=self.vertices, texture=self.texture)
Esempio n. 8
0
class Game(Widget):
    '''Game renderer'''

    REPLACE_CURSOR = False

    def __init__(self, **kwargs):
        self.canvas = RenderContext(use_parent_modelview=True,
                                    use_parent_projection=True)
        self.canvas.shader.source = resource_find('game.glsl')

        Widget.__init__(self, **kwargs)

        self.blending_is_broken = blending_is_broken()

        self.tex, self.tex_uv = load_tex_uv('a.atlas')
        update_tex_uv(self.tex_uv)

        self.root_note = NOTES[0]
        self.scale_class = SCALES[0]
        self.scale = self.scale_class(self.root_note)
        self.tuning = TUNING_DEFAULT
        self.build(False)

        from kivy.core.window import Window
        global g_window
        g_window = Window

    def build(self, updating=True):
        fretboard = build_fretboard(self.scale, self.tuning)

        if Game.REPLACE_CURSOR:
            self.begin_cursor = len(fretboard) * VERTEX_SIZE * 4
            fretboard += [Quad(x=0, y=0, size=1, tex='cursor')]

        self.indices = []
        ix = self.indices.extend
        for c in range(0, len(fretboard) << 2, 4):
            ix((c, c + 1, c + 2, c + 2, c + 3, c))

        self.vertices = []
        vx = self.vertices.extend
        self.animate = set()
        for i, o in enumerate(fretboard):
            uv = self.tex_uv[o[3]]
            vx((
                o[0], o[1], o[2], -uv[4], -uv[5], uv[0], uv[1],
                o[0], o[1], o[2],  uv[4], -uv[5], uv[2], uv[1],
                o[0], o[1], o[2],  uv[4],  uv[5], uv[2], uv[3],
                o[0], o[1], o[2], -uv[4],  uv[5], uv[0], uv[3],
            ))
            if o[2] < 1:
                self.animate.add(i)

        if updating:
            self.set_updating()

        self.update_heading()

    def set_updating(self):
        Clock.unschedule(self.update_glsl)
        Clock.schedule_interval(self.update_glsl, 60 ** -1)

    on_start = set_updating

    def update_glsl(self, nap):
        '''
        https://github.com/kivy/kivy/issues/2178

        if Game.REPLACE_CURSOR:
            cur_x, cur_y = g_window.mouse_pos
            cur_x += CURSOR_OFFSET_X
            cur_y += CURSOR_OFFSET_Y

            for c in (self.begin_cursor,
                      self.begin_cursor + VERTEX_SIZE,
                      self.begin_cursor + VERTEX_SIZE * 2,
                      self.begin_cursor + VERTEX_SIZE * 3):

                self.vertices[c] = cur_x
                self.vertices[c + 1] = cur_y
        '''

        if self.animate:
            for i in self.animate.copy():
                idx = i * VERTEX_SIZE * 4 + 2
                val = self.vertices[idx] * (nap * 25 + 1)

                if val >= 1:
                    val = 1
                    self.animate.remove(i)

                for c in (idx,
                          idx + VERTEX_SIZE,
                          idx + VERTEX_SIZE * 2,
                          idx + VERTEX_SIZE * 3):

                    self.vertices[c] = val

        if not self.animate and not Game.REPLACE_CURSOR:
            Clock.unschedule(self.update_glsl)

        self.canvas.clear()

        if self.blending_is_broken:
            self.canvas.before.add(select_blend_func)
            self.canvas.after.add(reset_blend_func)

        self.canvas.add(Mesh(indices=self.indices, vertices=self.vertices,
                             fmt=VERTEX_FORMAT, mode='triangles',
                             texture=self.tex))

    def set_root_note(self, root_note):
        self.root_note = root_note
        self.scale = self.scale_class(self.root_note)
        self.build()

    def set_scale_class(self, scale_class):
        self.scale_class = scale_class
        self.scale = self.scale_class(self.root_note)
        self.build()

    def set_tuning(self, tuning):
        self.tuning = tuning
        self.build()

    _heading = None

    def update_heading(self):
        if self._heading:
            self._heading.text = u'%s \u2013 %s tuning' % (unicode(self.scale),
                                                           self.tuning['name'])

    set_animooted = lambda self, val: set_ani(val)
Esempio n. 9
0
class PSWidget(Widget):  #widget sınıfı oluşturuldu.
    indices = []  #indis listesi
    vertices = []  #köşe listesi
    particles = []  #particles listesi

    def __init__(self, **kwargs):  #Pencere ayarlaması yapıldı.
        Widget.__init__(self, **kwargs)
        self.canvas = RenderContext(use_parent_projection=True)
        self.canvas.shader.source = self.glsl

        self.vfmt = (
            (b'vCenter', 2, 'float'),
            (b'vScale', 1, 'float'),
            (b'vPosition', 2, 'float'),
            (b'vTexCoords0', 2, 'float'),
        )

        self.vsize = sum(attr[1] for attr in self.vfmt)

        self.texture, self.uvmap = load_atlas(self.atlas)

    def make_particles(self, Cls,
                       num):  #Particle oluşturma fonksiyonu tanımlandı.
        count = len(self.particles)
        uv = self.uvmap[Cls.tex_name]

        for i in range(count, count + num):
            j = 4 * i
            self.indices.extend((j, j + 1, j + 2, j + 2, j + 3, j))

            self.vertices.extend((  #particle konumlanması amaçlandı.
                0,
                0,
                1,
                -uv.su,
                -uv.sv,
                uv.u0,
                uv.v1,
                0,
                0,
                1,
                uv.su,
                -uv.sv,
                uv.u1,
                uv.v1,
                0,
                0,
                1,
                uv.su,
                uv.sv,
                uv.u1,
                uv.v0,
                0,
                0,
                1,
                -uv.su,
                uv.sv,
                uv.u0,
                uv.v0,
            ))

            p = Cls(self, i)
            self.particles.append(p)

    def update_glsl(self, nap):  #update fonksiyonu oluşturuldu.
        for p in self.particles:
            p.advance(nap)  #advance fonksiyonu çağırıldı.
            p.update()  #update fonksiyonu çağırıldı.

        self.canvas.clear()  #pencerenin temizlenmesi sağlandı.

        with self.canvas:
            Mesh(fmt=self.vfmt,
                 mode='triangles',
                 indices=self.indices,
                 vertices=self.vertices,
                 texture=self.texture)
Esempio n. 10
0
class Starfield(Widget):
    def __init__(self, **kwargs):
        super(Starfield, self).__init__(**kwargs)
        self.canvas = RenderContext(use_parent_projection=True)
        self.canvas.shader.source = 'starfield.glsl'

        self.vfmt = (
            (b'vCenter', 2, 'float'),     #  Denotes the star's center point on
                                          #  the screen.

            (b'vScale', 1, 'float'),      #  The star's scale factor. 1 being
                                          #  the original size (48x48 px)

            (b'vPosition', 2, 'float'),   #  Position of each vertex relative
                                          #  to the star's center point.

            (b'vTexCoords0', 2, 'float'), #  Refers to texture coordinates.
        )

        # Note the length of a single vertex in the array of vertices
        self.vsize = sum(attr[1] for attr in self.vfmt)

        self.indices = []
        for i in range(0, 4 * NSTARS, 4):
            self.indices.extend((
                i, i + 1, i + 2, i + 2,
                i + 2, i + 3, i
            ))

        # Essentially, the vertices contain all the data about our stars that
        # we need to retain, however this is not ideal to operate on.
        # So instead, we create a `Star()` class to encapsulate the operations
        # and computations. It will also contain additional properties such as
        # size, angle, distance from center, etc.
        self.vertices = []
        for i in range(NSTARS):
            self.vertices.extend((
                0, 0, 1, -24, -24, 0, 1,
                0, 0, 1, 24, -24, 1, 1,
                0, 0, 1, 24, 24, 1, 0,
                0, 0, 1, -24, 24, 0, 0,
            ))

        self.texture = Image('assets/star.png').texture
        self.stars = [Star(self, i) for i in range(NSTARS)]

    def update_glsl(self, nap):
        """ Implement the starfield motion algorithm.

        """
        # Determine the max distance a star will travel based on the starfield
        # widget's center.
        x0, y0 = self.center
        max_distance = 1.1 * max(x0, y0)

        for star in self.stars:
            # We then move the stars towards the max_distance, enlarging it at
            # the same time. When it reaches the max_distance, we reset it.
            star.distance *= 2 * nap + 1
            star.size += 0.25 * nap

            if star.distance > max_distance:
                star.reset()
            else:
                star.update(x0, y0)

        # Finally we draw them on the canvas
        self.canvas.clear()
        with self.canvas:
            Mesh(fmt=self.vfmt, mode='triangles', indices=self.indices,
                 vertices=self.vertices, texture=self.texture)
Esempio n. 11
0
class Game(Widget):
    '''Game renderer'''

    REPLACE_CURSOR = False

    def __init__(self, **kwargs):
        self.canvas = RenderContext(use_parent_modelview=True,
                                    use_parent_projection=True)
        self.canvas.shader.source = resource_find('game.glsl')

        Widget.__init__(self, **kwargs)

        self.blending_is_broken = blending_is_broken()

        self.tex, self.tex_uv = load_tex_uv('a.atlas')
        update_tex_uv(self.tex_uv)

        self.root_note = NOTES[0]
        self.scale_class = SCALES[0]
        self.scale = self.scale_class(self.root_note)
        self.tuning = TUNING_DEFAULT
        self.build(False)

        from kivy.core.window import Window
        global g_window
        g_window = Window

    def build(self, updating=True):
        fretboard = build_fretboard(self.scale, self.tuning)

        if Game.REPLACE_CURSOR:
            self.begin_cursor = len(fretboard) * VERTEX_SIZE * 4
            fretboard += [Quad(x=0, y=0, size=1, tex='cursor')]

        self.indices = []
        ix = self.indices.extend
        for c in range(0, len(fretboard) << 2, 4):
            ix((c, c + 1, c + 2, c + 2, c + 3, c))

        self.vertices = []
        vx = self.vertices.extend
        self.animate = set()
        for i, o in enumerate(fretboard):
            uv = self.tex_uv[o[3]]
            vx((
                o[0],
                o[1],
                o[2],
                -uv[4],
                -uv[5],
                uv[0],
                uv[1],
                o[0],
                o[1],
                o[2],
                uv[4],
                -uv[5],
                uv[2],
                uv[1],
                o[0],
                o[1],
                o[2],
                uv[4],
                uv[5],
                uv[2],
                uv[3],
                o[0],
                o[1],
                o[2],
                -uv[4],
                uv[5],
                uv[0],
                uv[3],
            ))
            if o[2] < 1:
                self.animate.add(i)

        if updating:
            self.set_updating()

        self.update_heading()

    def set_updating(self):
        Clock.unschedule(self.update_glsl)
        Clock.schedule_interval(self.update_glsl, 60**-1)

    on_start = set_updating

    def update_glsl(self, nap):
        '''
        https://github.com/kivy/kivy/issues/2178

        if Game.REPLACE_CURSOR:
            cur_x, cur_y = g_window.mouse_pos
            cur_x += CURSOR_OFFSET_X
            cur_y += CURSOR_OFFSET_Y

            for c in (self.begin_cursor,
                      self.begin_cursor + VERTEX_SIZE,
                      self.begin_cursor + VERTEX_SIZE * 2,
                      self.begin_cursor + VERTEX_SIZE * 3):

                self.vertices[c] = cur_x
                self.vertices[c + 1] = cur_y
        '''

        if self.animate:
            for i in self.animate.copy():
                idx = i * VERTEX_SIZE * 4 + 2
                val = self.vertices[idx] * (nap * 25 + 1)

                if val >= 1:
                    val = 1
                    self.animate.remove(i)

                for c in (idx, idx + VERTEX_SIZE, idx + VERTEX_SIZE * 2,
                          idx + VERTEX_SIZE * 3):

                    self.vertices[c] = val

        if not self.animate and not Game.REPLACE_CURSOR:
            Clock.unschedule(self.update_glsl)

        self.canvas.clear()

        if self.blending_is_broken:
            self.canvas.before.add(select_blend_func)
            self.canvas.after.add(reset_blend_func)

        self.canvas.add(
            Mesh(indices=self.indices,
                 vertices=self.vertices,
                 fmt=VERTEX_FORMAT,
                 mode='triangles',
                 texture=self.tex))

    def set_root_note(self, root_note):
        self.root_note = root_note
        self.scale = self.scale_class(self.root_note)
        self.build()

    def set_scale_class(self, scale_class):
        self.scale_class = scale_class
        self.scale = self.scale_class(self.root_note)
        self.build()

    def set_tuning(self, tuning):
        self.tuning = tuning
        self.build()

    _heading = None

    def update_heading(self):
        if self._heading:
            self._heading.text = u'%s \u2013 %s tuning' % (unicode(
                self.scale), self.tuning['name'])

    set_animooted = lambda self, val: set_ani(val)