-
-
Save Bakterija/086eace0003e0bf53ca6244a07e80687 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import division | |
import math | |
from operator import itemgetter | |
import kivy | |
from kivy.app import App | |
from kivy.properties import ReferenceListProperty, ObjectProperty, StringProperty, ListProperty, BooleanProperty, NumericProperty, DictProperty | |
from kivy.uix.floatlayout import FloatLayout | |
from kivy.uix.gridlayout import GridLayout | |
from kivy.uix.scrollview import ScrollView | |
from kivy.core.window import Window | |
from kivy.uix.label import Label | |
from kivy.graphics import Rectangle, Color, Bezier | |
class Scroller(ScrollView): | |
def on_touch_down(self, touch): | |
return super(Scroller, self).on_touch_down(touch) | |
class Curves(FloatLayout): | |
points = ListProperty() | |
current_point = ListProperty() | |
moving = BooleanProperty(False) | |
touch_range = NumericProperty(0.1) | |
scroller = ObjectProperty() | |
def __init__(self, **kwargs): | |
super(Curves, self).__init__(**kwargs) | |
self.bind(pos=self.refresh, size=self.refresh) | |
self.reset() | |
def reset(self): | |
'''Clears the canvas and sets up the default curve''' | |
self.points = [[0,0], [1,1]] | |
self.refresh() | |
def refresh(self, *args): | |
'''Sorts and redraws points on the canvas''' | |
if len(self.points) < 2: | |
self.reset() | |
self.points = sorted(self.points, key=itemgetter(0)) | |
self.points[0][0] = 0 | |
self.points[-1][0] = 1 | |
canvas = self.canvas | |
canvas.clear() | |
canvas.before.add(Color(.3,.3,.3)) | |
canvas.before.add(Rectangle(size=self.size, pos=self.pos)) | |
canvas.add(Color(1,1,1)) | |
for index in range(len(self.points) - 1): | |
current = self.points[index] | |
next = self.points[index+1] | |
self.draw_line(canvas, current, next) | |
self.draw_point(canvas, current) | |
self.draw_point(canvas, self.points[-1]) | |
def relative_to_local(self, point): | |
x = point[0]*self.width + self.pos[0] | |
y = point[1]*self.height + self.pos[1] | |
return [x, y] | |
def local_to_relative(self, point): | |
x = (point[0] - self.pos[0])/self.width | |
y = (point[1] - self.pos[1])/self.height | |
return [x, y] | |
def draw_line(self, canvas, startpoint, endpoint): | |
real_startpoint = self.relative_to_local(startpoint) | |
real_endpoint = self.relative_to_local(endpoint) | |
canvas.add(Bezier(points=(real_startpoint[0],real_startpoint[1],real_endpoint[0],real_endpoint[1]))) | |
def draw_point(self, canvas, point): | |
size = 20 | |
real_point = self.relative_to_local(point) | |
if point == self.current_point: | |
source = 'curve_point_selected.png' | |
else: | |
source = 'curve_point.png' | |
canvas.add(Rectangle(source=source, pos=(real_point[0]-(size/2),real_point[1]-(size/2)), size=(size,size))) | |
def add_point(self, point): | |
'''Adds a new point to the curve''' | |
x = point[0] | |
y = point[1] | |
#dont allow illegal values for x or y | |
if x > 1 or y > 1 or x < 0 or y < 0: | |
return | |
#dont allow point on an x position that already exists | |
for point in self.points: | |
if point[0] == x: | |
return | |
self.points.append([x,y]) | |
self.current_point = [x,y] | |
self.refresh() | |
def remove_point(self): | |
'''Removes the last moved point if it is not the start or end''' | |
if self.current_point: | |
for index, point in enumerate(self.points): | |
if point[0] == self.current_point[0] and point[1] == self.current_point[1]: | |
self.points.pop(index) | |
self.refresh() | |
def generate_curve(self, resolution=256): | |
'''Returns a list of vertical points representing the current curve''' | |
#todo | |
pass | |
def near(self, first, second): | |
if abs(second-first) <= self.touch_range: | |
return True | |
else: | |
return False | |
def on_touch_down(self, touch): | |
## STOP SCROLL HERE | |
global asd | |
asd.scroll_timeout = 0 | |
if self.collide_point(*touch.pos): | |
point = self.local_to_relative(touch.pos) | |
self.moving = True | |
for existing in self.points: | |
if self.near(point[0], existing[0]) and self.near(point[1], existing[1]): | |
self.current_point = existing | |
self.refresh() | |
return | |
self.add_point(point) | |
return True | |
def on_touch_move(self, touch): | |
if self.collide_point(*touch.pos): | |
new_point = self.local_to_relative(touch.pos) | |
if self.moving: | |
for index, point in enumerate(self.points): | |
if point[0] == self.current_point[0]: | |
too_close = False | |
for other_point in self.points: | |
if other_point != point: | |
if self.near(other_point[0], new_point[0]) and self.near(other_point[1], new_point[1]): | |
too_close = True | |
if point[0] == 0: | |
new_point[0] = 0 | |
elif new_point[0] <= 0: | |
too_close = True | |
if point[0] == 1: | |
new_point[0] = 1 | |
elif new_point[0] >= 1: | |
too_close = True | |
if not too_close: | |
self.points[index] = new_point | |
self.current_point = new_point | |
self.refresh() | |
break | |
return True | |
def on_touch_up(self, touch): | |
## START SCROLL HERE | |
global asd | |
asd.scroll_timeout = 100 | |
self.moving = False | |
if self.collide_point(*touch.pos): | |
return True | |
class PhotoManager(App): | |
def build(self): | |
global asd | |
scroller = Scroller() | |
grid = GridLayout(cols=1, height=1000, size_hint_y=None) | |
grid.add_widget(Label(text='scroll here')) | |
grid.add_widget(Curves()) | |
grid.add_widget(Label(text='scroll here')) | |
scroller.add_widget(grid) | |
asd = scroller | |
return scroller | |
if __name__ == '__main__': | |
PhotoManager().run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment