#!/usr/bin/env python
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.slider import Slider
from kivy.graphics import Color, Bezier, Line


class BezierTest(FloatLayout):

    def __init__(self, points=[], loop=False, *args, **kwargs):
        super(BezierTest, self).__init__(*args, **kwargs)
        self.d = 10
        self.points = points
        self.loop = loop
        self.current_point = None

        with self.canvas:
            Color(1.0, 0.0, 0.0)

            self.bezier = Bezier(
                    points=self.points,
                    segments=150,
                    loop=self.loop,
                    dash_length=100,
                    dash_offset=10)

            Color(1.0, 0.0, 1.0)
            self.line = Line(
                    points=self.points+self.points[:2],
                    dash_offset=10,
                    dash_length=100)

        s = Slider(y=0, pos_hint={'x': .3}, size_hint=(.7, None), height=50)
        s.bind(value=self._set_bezier_dash_offset)
        self.add_widget(s)

        s = Slider(y=50, pos_hint={'x': .3}, size_hint=(.7, None), height=50)
        s.bind(value=self._set_line_dash_offset)
        self.add_widget(s)

    def _set_bezier_dash_offset(self, instance, value):
        # effect to reduce length while increase offset
        self.bezier.dash_length = 100 - value
        self.bezier.dash_offset = value

    def _set_line_dash_offset(self, instance, value):
        # effect to reduce length while increase offset
        self.line.dash_length = 100 - value
        self.line.dash_offset = value

    def on_touch_down(self, touch):
        if self.collide_point(touch.pos[0], touch.pos[1]):
            for i, p in enumerate(list(zip(self.points[::2], self.points[1::2]))):
                if (
                        abs(touch.pos[0] - self.pos[0] - p[0]) < self.d and
                        abs(touch.pos[1] - self.pos[1] - p[1]) < self.d):
                    self.current_point = i + 1
                    return True
            return super(BezierTest, self).on_touch_down(touch)

    def on_touch_up(self, touch):
        if self.collide_point(touch.pos[0], touch.pos[1]):
            if self.current_point:
                self.current_point = None
                return True
            return super(BezierTest, self).on_touch_up(touch)

    def on_touch_move(self, touch):
        if self.collide_point(touch.pos[0], touch.pos[1]):
            c = self.current_point
            if c:
                self.points[(c - 1) * 2] = touch.pos[0] - self.pos[0]
                self.points[(c - 1) * 2 + 1] = touch.pos[1] - self.pos[1]
                self.bezier.points = self.points
                self.line.points = self.points + self.points[:2]
                return True
            return super(BezierTest, self).on_touch_move(touch)


class Main(App):

    def build(self):
        from math import cos, sin, radians
        x = y = 150
        l = 100
        # Pacman !
        points = [x, y]
        for i in range(45, 360, 45):
            i = radians(i)
            points.extend([x + cos(i) * l, y + sin(i) * l])
        return BezierTest(points=points, loop=True)

if __name__ == '__main__':
    Main().run()


[((33, 12, 33, 76), 'kivy.uix.slider.Slider', 'Slider', (), '', False, 'from kivy.uix.slider import Slider\n'), ((37, 12, 37, 77), 'kivy.uix.slider.Slider', 'Slider', (), '', False, 'from kivy.uix.slider import Slider\n'), ((18, 12, 18, 32), 'kivy.graphics.Color', 'Color', ({(18, 18, 18, 21): '(1.0)', (18, 23, 18, 26): '(0.0)', (18, 28, 18, 31): '(0.0)'}, {}), '(1.0, 0.0, 0.0)', False, 'from kivy.graphics import Color, Bezier, Line\n'), ((20, 26, 25, 35), 'kivy.graphics.Bezier', 'Bezier', (), '', False, 'from kivy.graphics import Color, Bezier, Line\n'), ((27, 12, 27, 32), 'kivy.graphics.Color', 'Color', ({(27, 18, 27, 21): '(1.0)', (27, 23, 27, 26): '(0.0)', (27, 28, 27, 31): '(1.0)'}, {}), '(1.0, 0.0, 1.0)', False, 'from kivy.graphics import Color, Bezier, Line\n'), ((28, 24, 31, 36), 'kivy.graphics.Line', 'Line', (), '', False, 'from kivy.graphics import Color, Bezier, Line\n'), ((89, 16, 89, 26), 'math.radians', 'radians', ({(89, 24, 89, 25): 'i'}, {}), '(i)', False, 'from math import cos, sin, radians\n'), ((90, 31, 90, 37), 'math.cos', 'cos', ({(90, 35, 90, 36): 'i'}, {}), '(i)', False, 'from math import cos, sin, radians\n'), ((90, 47, 90, 53), 'math.sin', 'sin', ({(90, 51, 90, 52): 'i'}, {}), '(i)', False, 'from math import cos, sin, radians\n')]