diff --git a/freechat-client/readme.md b/freechat-client/readme.md index 5822b91..fb0cfd3 100644 --- a/freechat-client/readme.md +++ b/freechat-client/readme.md @@ -3,3 +3,7 @@ This will be where we keep the code for the web-based-client. This client comms with our server code base found under `/server/` in this repository. +## Client Config Description + +For unix based systems configuration will be found at `$HOME/.config/freechat-client/config.json`. +There a few top levle items that I will describe here. diff --git a/freechat-client/share/kivy-examples/3Drendering/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/3Drendering/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..f64f248 Binary files /dev/null and b/freechat-client/share/kivy-examples/3Drendering/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/3Drendering/__pycache__/objloader.cpython-37.pyc b/freechat-client/share/kivy-examples/3Drendering/__pycache__/objloader.cpython-37.pyc new file mode 100644 index 0000000..070aaf5 Binary files /dev/null and b/freechat-client/share/kivy-examples/3Drendering/__pycache__/objloader.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/3Drendering/main.py b/freechat-client/share/kivy-examples/3Drendering/main.py new file mode 100644 index 0000000..c2ddd5a --- /dev/null +++ b/freechat-client/share/kivy-examples/3Drendering/main.py @@ -0,0 +1,76 @@ +''' +3D Rotating Monkey Head +======================== + +This example demonstrates using OpenGL to display a rotating monkey head. This +includes loading a Blender OBJ file, shaders written in OpenGL's Shading +Language (GLSL), and using scheduled callbacks. + +The monkey.obj file is an OBJ file output from the Blender free 3D creation +software. The file is text, listing vertices and faces and is loaded +using a class in the file objloader.py. The file simple.glsl is +a simple vertex and fragment shader written in GLSL. +''' + +from kivy.app import App +from kivy.clock import Clock +from kivy.core.window import Window +from kivy.uix.widget import Widget +from kivy.resources import resource_find +from kivy.graphics.transformation import Matrix +from kivy.graphics.opengl import * +from kivy.graphics import * +from objloader import ObjFile + + +class Renderer(Widget): + def __init__(self, **kwargs): + self.canvas = RenderContext(compute_normal_mat=True) + self.canvas.shader.source = resource_find('simple.glsl') + self.scene = ObjFile(resource_find("monkey.obj")) + super(Renderer, self).__init__(**kwargs) + with self.canvas: + self.cb = Callback(self.setup_gl_context) + PushMatrix() + self.setup_scene() + PopMatrix() + self.cb = Callback(self.reset_gl_context) + Clock.schedule_interval(self.update_glsl, 1 / 60.) + + def setup_gl_context(self, *args): + glEnable(GL_DEPTH_TEST) + + def reset_gl_context(self, *args): + glDisable(GL_DEPTH_TEST) + + def update_glsl(self, delta): + asp = self.width / float(self.height) + proj = Matrix().view_clip(-asp, asp, -1, 1, 1, 100, 1) + self.canvas['projection_mat'] = proj + self.canvas['diffuse_light'] = (1.0, 1.0, 0.8) + self.canvas['ambient_light'] = (0.1, 0.1, 0.1) + self.rot.angle += delta * 100 + + def setup_scene(self): + Color(1, 1, 1, 1) + PushMatrix() + Translate(0, 0, -3) + self.rot = Rotate(1, 0, 1, 0) + m = list(self.scene.objects.values())[0] + UpdateNormalMatrix() + self.mesh = Mesh( + vertices=m.vertices, + indices=m.indices, + fmt=m.vertex_format, + mode='triangles', + ) + PopMatrix() + + +class RendererApp(App): + def build(self): + return Renderer() + + +if __name__ == "__main__": + RendererApp().run() diff --git a/freechat-client/share/kivy-examples/3Drendering/monkey.obj b/freechat-client/share/kivy-examples/3Drendering/monkey.obj new file mode 100644 index 0000000..1d6d599 --- /dev/null +++ b/freechat-client/share/kivy-examples/3Drendering/monkey.obj @@ -0,0 +1,7966 @@ +# Blender v2.65 (sub 1) OBJ File: '' +# www.blender.org +mtllib monkey.mtl +o Suzanne +v 0.477241 0.205729 0.676920 +v -0.507134 0.205729 0.676920 +v 0.543648 0.178386 0.581217 +v -0.573540 0.178386 0.581217 +v 0.422554 0.059245 0.606607 +v -0.452446 0.059245 0.606607 +v 0.395210 0.125651 0.694498 +v -0.425102 0.125651 0.694498 +v 0.279976 0.125651 0.715982 +v -0.309868 0.125651 0.715982 +v 0.250679 0.059245 0.637857 +v -0.280571 0.059245 0.637857 +v 0.129585 0.178386 0.653482 +v -0.159477 0.178386 0.653482 +v 0.199898 0.205729 0.725748 +v -0.229790 0.205729 0.725748 +v 0.199898 0.320964 0.725748 +v -0.229790 0.320964 0.725748 +v 0.129585 0.348308 0.653482 +v -0.159477 0.348308 0.653482 +v 0.250679 0.469401 0.637857 +v -0.280571 0.469401 0.637857 +v 0.279976 0.402995 0.715982 +v -0.309868 0.402995 0.715982 +v 0.395210 0.402995 0.694498 +v -0.425102 0.402995 0.694498 +v 0.422554 0.469401 0.606607 +v -0.452446 0.469401 0.606607 +v 0.543648 0.348308 0.581217 +v -0.573540 0.348308 0.581217 +v 0.477241 0.320964 0.676920 +v -0.507134 0.320964 0.676920 +v 0.442085 0.307292 0.725748 +v -0.471977 0.307292 0.725748 +v 0.381538 0.369792 0.739420 +v -0.411430 0.369792 0.739420 +v 0.295601 0.369792 0.756998 +v -0.325493 0.369792 0.756998 +v 0.237007 0.307292 0.764810 +v -0.266899 0.307292 0.764810 +v 0.237007 0.221354 0.764810 +v -0.266899 0.221354 0.764810 +v 0.295601 0.162761 0.756998 +v -0.325493 0.162761 0.756998 +v 0.381538 0.162761 0.739420 +v -0.411430 0.162761 0.739420 +v 0.442085 0.221354 0.725748 +v -0.471977 0.221354 0.725748 +v 0.409533 0.233724 0.750488 +v -0.439425 0.233724 0.750488 +v 0.367866 0.192058 0.760904 +v -0.397759 0.192058 0.760904 +v 0.307971 0.192058 0.773925 +v -0.337863 0.192058 0.773925 +v 0.266304 0.233724 0.779133 +v -0.296196 0.233724 0.779133 +v 0.266304 0.293620 0.779133 +v -0.296196 0.293620 0.779133 +v 0.307971 0.337891 0.773925 +v -0.337863 0.337891 0.773925 +v 0.367866 0.337891 0.760904 +v -0.397759 0.337891 0.760904 +v 0.409533 0.293620 0.750488 +v -0.439425 0.293620 0.750488 +v 0.070991 -0.936849 0.557779 +v -0.100884 -0.936849 0.557779 +v 0.211616 -0.919271 0.542154 +v -0.241509 -0.919271 0.542154 +v 0.283882 -0.872396 0.544107 +v -0.313774 -0.872396 0.544107 +v 0.293648 -0.757161 0.569498 +v -0.323540 -0.757161 0.569498 +v 0.266304 -0.550130 0.590982 +v -0.296196 -0.550130 0.590982 +v 0.276070 -0.098958 0.600748 +v -0.305962 -0.098958 0.600748 +v 0.506538 -0.022786 0.548014 +v -0.536430 -0.022786 0.548014 +v 0.686226 0.111979 0.508951 +v -0.716118 0.111979 0.508951 +v 0.774116 0.309245 0.530435 +v -0.804009 0.309245 0.530435 +v 0.735054 0.445964 0.606607 +v -0.764946 0.445964 0.606607 +v 0.567085 0.531901 0.665201 +v -0.596977 0.531901 0.665201 +v 0.375679 0.656901 0.719889 +v -0.405571 0.656901 0.719889 +v 0.233101 0.703776 0.751139 +v -0.262993 0.703776 0.751139 +v 0.115913 0.584636 0.756998 +v -0.145805 0.584636 0.756998 +v 0.026070 0.445964 0.745279 +v -0.055962 0.445964 0.745279 +v 0.164741 0.502604 0.762857 +v -0.194634 0.502604 0.762857 +v 0.258491 0.570964 0.753092 +v -0.288384 0.570964 0.753092 +v 0.362007 0.545573 0.729654 +v -0.391899 0.545573 0.729654 +v 0.524116 0.463542 0.682779 +v -0.554009 0.463542 0.682779 +v 0.653023 0.385417 0.630045 +v -0.682915 0.385417 0.630045 +v 0.668648 0.285808 0.594889 +v -0.698540 0.285808 0.594889 +v 0.600288 0.147136 0.592935 +v -0.630180 0.147136 0.592935 +v 0.455757 0.041667 0.624185 +v -0.485649 0.041667 0.624185 +v 0.260445 0.010417 0.688639 +v -0.290337 0.010417 0.688639 +v 0.108101 0.065104 0.714029 +v -0.137993 0.065104 0.714029 +v 0.082710 0.395183 0.756998 +v -0.112602 0.395183 0.756998 +v 0.049507 0.289714 0.733560 +v -0.079399 0.289714 0.733560 +v 0.059273 0.172526 0.706217 +v -0.089165 0.172526 0.706217 +v 0.041695 -0.891927 0.620279 +v -0.071587 -0.891927 0.620279 +v 0.129585 -0.870442 0.624185 +v -0.159477 -0.870442 0.624185 +v 0.166695 -0.802083 0.641764 +v -0.196587 -0.802083 0.641764 +v 0.149116 -0.550130 0.676920 +v -0.179009 -0.550130 0.676920 +v 0.170601 -0.712239 0.661295 +v -0.200493 -0.712239 0.661295 +v 0.026070 -0.356771 0.702310 +v -0.055962 -0.356771 0.702310 +v 0.033882 -0.544271 0.698404 +v -0.063774 -0.544271 0.698404 +v 0.041695 -0.692708 0.690592 +v -0.071587 -0.692708 0.690592 +v 0.094429 -0.233724 0.723795 +v -0.124321 -0.233724 0.723795 +v 0.102241 -0.163411 0.723795 +v -0.132134 -0.163411 0.723795 +v 0.047554 -0.116536 0.717935 +v -0.077446 -0.116536 0.717935 +v -0.005180 -0.141927 0.723795 +v -0.024712 -0.141927 0.723795 +v 0.029976 -0.282552 0.717935 +v -0.059868 -0.282552 0.717935 +v 0.028023 -0.263021 0.749185 +v -0.057915 -0.263021 0.749185 +v 0.006538 -0.145833 0.760904 +v -0.036430 -0.145833 0.760904 +v 0.057320 -0.120442 0.753092 +v -0.087212 -0.120442 0.753092 +v 0.096382 -0.165364 0.760904 +v -0.126274 -0.165364 0.760904 +v 0.088570 -0.223958 0.758951 +v -0.118462 -0.223958 0.758951 +v 0.047554 -0.163411 0.776529 +v -0.077446 -0.163411 0.776529 +v 0.031929 -0.222005 0.772623 +v -0.061821 -0.222005 0.772623 +v 0.041695 -0.065755 0.712076 +v -0.071587 -0.065755 0.712076 +v 0.113960 -0.159505 0.710123 +v -0.143852 -0.159505 0.710123 +v 0.123726 -0.247396 0.684732 +v -0.153618 -0.247396 0.684732 +v 0.123726 -0.352864 0.684732 +v -0.153618 -0.352864 0.684732 +v 0.225288 -0.356771 0.592935 +v -0.255180 -0.356771 0.592935 +v 0.194038 -0.259114 0.589029 +v -0.223930 -0.259114 0.589029 +v 0.166695 -0.175130 0.616373 +v -0.196587 -0.175130 0.616373 +v 0.035835 -0.729817 0.684732 +v -0.065727 -0.729817 0.684732 +v 0.088570 -0.759114 0.676920 +v -0.118462 -0.759114 0.676920 +v 0.065132 -0.831380 0.657389 +v -0.095024 -0.831380 0.657389 +v 0.012398 -0.858724 0.645670 +v -0.042290 -0.858724 0.645670 +v 0.008491 -0.843099 0.616373 +v -0.038384 -0.843099 0.616373 +v 0.055366 -0.817708 0.624185 +v -0.085259 -0.817708 0.624185 +v 0.078804 -0.761067 0.641764 +v -0.108696 -0.761067 0.641764 +v 0.031929 -0.741536 0.647623 +v -0.061821 -0.741536 0.647623 +v 0.020210 -0.790364 0.602701 +v -0.050102 -0.790364 0.602701 +v 0.063179 -0.784505 0.602050 +v -0.093071 -0.784505 0.602050 +v 0.149116 0.201823 0.721842 +v -0.179009 0.201823 0.721842 +v 0.137398 0.277995 0.727701 +v -0.167290 0.277995 0.727701 +v 0.154976 0.367839 0.731607 +v -0.184868 0.367839 0.731607 +v 0.180366 0.145183 0.717935 +v -0.210259 0.145183 0.717935 +v 0.279976 0.090495 0.698404 +v -0.309868 0.090495 0.698404 +v 0.414741 0.080729 0.665201 +v -0.444634 0.080729 0.665201 +v 0.528023 0.156901 0.635904 +v -0.557915 0.156901 0.635904 +v 0.592476 0.262370 0.622232 +v -0.622368 0.262370 0.622232 +v 0.582710 0.348308 0.630045 +v -0.612602 0.348308 0.630045 +v 0.488960 0.410808 0.669107 +v -0.518852 0.410808 0.669107 +v 0.363960 0.455729 0.704264 +v -0.393852 0.455729 0.704264 +v 0.281929 0.469401 0.714029 +v -0.311821 0.469401 0.714029 +v 0.209663 0.440104 0.727701 +v -0.239555 0.440104 0.727701 +v 0.235054 0.408854 0.725748 +v -0.264946 0.408854 0.725748 +v 0.291695 0.434245 0.717935 +v -0.321587 0.434245 0.717935 +v 0.362007 0.426433 0.714029 +v -0.391899 0.426433 0.714029 +v 0.467476 0.389323 0.680826 +v -0.497368 0.389323 0.680826 +v 0.543648 0.334636 0.639810 +v -0.573540 0.334636 0.639810 +v 0.551460 0.264323 0.633951 +v -0.581352 0.264323 0.633951 +v 0.500679 0.176433 0.649576 +v -0.530571 0.176433 0.649576 +v 0.406929 0.111979 0.678873 +v -0.436821 0.111979 0.678873 +v 0.289741 0.115886 0.708170 +v -0.319634 0.115886 0.708170 +v 0.199898 0.160808 0.721842 +v -0.229790 0.160808 0.721842 +v 0.190132 0.352214 0.725748 +v -0.220024 0.352214 0.725748 +v 0.170601 0.279948 0.723795 +v -0.200493 0.279948 0.723795 +v 0.174507 0.213542 0.719889 +v -0.204399 0.213542 0.719889 +v 0.028023 0.467448 0.631998 +v -0.057915 0.467448 0.631998 +v 0.115913 0.604167 0.639810 +v -0.145805 0.604167 0.639810 +v 0.237007 0.727214 0.631998 +v -0.266899 0.727214 0.631998 +v 0.393257 0.670573 0.598795 +v -0.423149 0.670573 0.598795 +v 0.576851 0.543620 0.546060 +v -0.606743 0.543620 0.546060 +v 0.746773 0.463542 0.499185 +v -0.776665 0.463542 0.499185 +v 0.799507 0.307292 0.424967 +v -0.829399 0.307292 0.424967 +v 0.694038 0.088542 0.399576 +v -0.723930 0.088542 0.399576 +v 0.512398 -0.048177 0.444498 +v -0.542290 -0.048177 0.444498 +v 0.061226 -0.481771 0.260904 +v -0.091118 -0.481771 0.260904 +v 0.051460 -0.647786 0.303873 +v -0.081352 -0.647786 0.303873 +v 0.061226 -0.850911 0.358560 +v -0.091118 -0.850911 0.358560 +v 0.070991 -0.948567 0.464029 +v -0.100884 -0.948567 0.464029 +v 0.235054 -0.923177 0.434732 +v -0.264946 -0.923177 0.434732 +v 0.313179 -0.845052 0.415201 +v -0.343071 -0.845052 0.415201 +v 0.299507 -0.679036 0.424967 +v -0.329399 -0.679036 0.424967 +v 0.186226 -0.606771 0.331217 +v -0.216118 -0.606771 0.331217 +v 0.215523 -0.811849 0.352701 +v -0.245415 -0.811849 0.352701 +v 0.182320 -0.430989 0.309732 +v -0.212212 -0.430989 0.309732 +v 0.272163 -0.475911 0.440592 +v -0.302055 -0.475911 0.440592 +v 0.215523 -0.247396 0.458170 +v -0.245415 -0.247396 0.458170 +v 0.240913 -0.325521 0.446451 +v -0.270805 -0.325521 0.446451 +v 0.197945 -0.188802 0.477701 +v -0.227837 -0.188802 0.477701 +v 0.305366 -0.128255 0.471842 +v -0.335259 -0.128255 0.471842 +v 0.154976 -0.034505 -0.719565 +v -0.184868 -0.034505 -0.719565 +v 0.145210 -0.239583 -0.500815 +v -0.175102 -0.239583 -0.500815 +v 0.112007 -0.366536 -0.110190 +v -0.141899 -0.366536 -0.110190 +v 0.082710 -0.417317 0.178873 +v -0.112602 -0.417317 0.178873 +v 0.195991 -0.339192 0.270670 +v -0.225884 -0.339192 0.270670 +v 0.725288 0.108073 0.184732 +v -0.755180 0.108073 0.184732 +v 0.184273 0.301433 -0.805502 +v -0.214165 0.301433 -0.805502 +v 0.211616 0.936198 0.049967 +v -0.241509 0.936198 0.049967 +v 0.211616 0.940104 -0.313315 +v -0.241509 0.940104 -0.313315 +v 0.213570 0.711589 -0.664877 +v -0.243462 0.711589 -0.664877 +v 0.694038 0.449870 0.348795 +v -0.723930 0.449870 0.348795 +v 0.684273 0.551433 0.155435 +v -0.714165 0.551433 0.155435 +v 0.703804 0.678386 -0.076986 +v -0.733696 0.678386 -0.076986 +v 0.703804 0.666667 -0.323080 +v -0.733696 0.666667 -0.323080 +v 0.692085 0.473308 -0.500815 +v -0.721977 0.473308 -0.500815 +v 0.528023 0.598308 -0.573080 +v -0.557915 0.598308 -0.573080 +v 0.531929 0.826823 -0.317221 +v -0.561821 0.826823 -0.317221 +v 0.531929 0.828776 -0.037924 +v -0.561821 0.828776 -0.037924 +v 0.531929 0.652995 0.206217 +v -0.561821 0.652995 0.206217 +v 0.549507 0.516276 0.395670 +v -0.579399 0.516276 0.395670 +v 0.213570 0.731120 0.337076 +v -0.243462 0.731120 0.337076 +v 0.266304 0.611979 0.549967 +v -0.296196 0.611979 0.549967 +v 0.248726 0.547526 0.497232 +v -0.278618 0.547526 0.497232 +v 0.021512 0.499349 0.549967 +v -0.051404 0.499349 0.549967 +v 0.772163 0.322917 0.262857 +v -0.802055 0.322917 0.262857 +v 0.793648 0.401042 0.073404 +v -0.823540 0.401042 0.073404 +v 0.803413 0.477214 -0.104330 +v -0.833305 0.477214 -0.104330 +v 0.781929 0.457683 -0.323080 +v -0.811821 0.457683 -0.323080 +v 0.320991 -0.247396 -0.084799 +v -0.350884 -0.247396 -0.084799 +v 0.526070 -0.114583 -0.082846 +v -0.555962 -0.114583 -0.082846 +v 0.529976 -0.057942 0.231607 +v -0.559868 -0.057942 0.231607 +v 0.303413 -0.173177 0.335123 +v -0.333305 -0.173177 0.335123 +v 0.263700 -0.261067 0.203613 +v -0.293592 -0.261067 0.203613 +v 0.268908 -0.143880 0.435383 +v -0.298800 -0.143880 0.435383 +v 0.613960 0.172526 -0.543783 +v -0.643852 0.172526 -0.543783 +v 0.459663 0.231120 -0.668783 +v -0.489555 0.231120 -0.668783 +v 0.522163 -0.055989 -0.381674 +v -0.552055 -0.055989 -0.381674 +v 0.373726 -0.138021 -0.434408 +v -0.403618 -0.138021 -0.434408 +v 0.373075 -0.003255 -0.627117 +v -0.402967 -0.003255 -0.627117 +v 0.947945 0.434245 -0.307455 +v -0.977837 0.434245 -0.307455 +v 1.100288 0.479167 -0.397299 +v -1.130180 0.479167 -0.397299 +v 1.244820 0.408855 -0.453940 +v -1.274712 0.408855 -0.453940 +v 1.262398 0.205729 -0.459799 +v -1.292290 0.205729 -0.459799 +v 1.125679 0.018230 -0.410971 +v -1.155571 0.018230 -0.410971 +v 0.903023 -0.067708 -0.266440 +v -0.932915 -0.067708 -0.266440 +v 0.930366 -0.013021 -0.297690 +v -0.960259 -0.013021 -0.297690 +v 1.102242 0.053386 -0.424643 +v -1.132133 0.053386 -0.424643 +v 1.209663 0.197917 -0.469565 +v -1.239555 0.197917 -0.469565 +v 1.199898 0.354167 -0.463705 +v -1.229790 0.354167 -0.463705 +v 1.084663 0.408855 -0.412924 +v -1.114555 0.408855 -0.412924 +v 0.961616 0.375651 -0.332846 +v -0.991509 0.375651 -0.332846 +v 0.678413 -0.028646 -0.127768 +v -0.708305 -0.028646 -0.127768 +v 0.713570 -0.069661 -0.192221 +v -0.743462 -0.069661 -0.192221 +v 0.778023 0.147136 -0.041830 +v -0.807915 0.147136 -0.041830 +v 0.854195 0.365886 -0.260580 +v -0.884087 0.365886 -0.260580 +v 0.795601 -0.013021 -0.241049 +v -0.825493 -0.013021 -0.241049 +v 0.758491 0.024089 -0.270346 +v -0.788384 0.024089 -0.270346 +v 0.770210 0.078776 -0.295736 +v -0.800102 0.078776 -0.295736 +v 0.762398 0.147136 -0.280111 +v -0.792290 0.147136 -0.280111 +v 0.826851 0.246745 -0.284018 +v -0.856743 0.246745 -0.284018 +v 0.885445 0.319011 -0.289877 +v -0.915337 0.319011 -0.289877 +v 0.815132 0.305339 -0.211752 +v -0.845024 0.305339 -0.211752 +v 0.760445 0.160808 -0.172690 +v -0.790337 0.160808 -0.172690 +v 0.706408 0.025391 -0.187012 +v -0.736300 0.025391 -0.187012 +v 0.904976 0.287761 -0.348471 +v -0.934868 0.287761 -0.348471 +v 0.850288 0.225261 -0.338705 +v -0.880180 0.225261 -0.338705 +v 0.785835 0.152995 -0.340658 +v -0.815727 0.152995 -0.340658 +v 0.778023 0.108073 -0.340658 +v -0.807915 0.108073 -0.340658 +v 0.820991 0.069011 -0.340658 +v -0.850884 0.069011 -0.340658 +v 0.815132 0.020183 -0.340658 +v -0.845024 0.020183 -0.340658 +v 0.832710 0.002604 -0.311361 +v -0.862602 0.002604 -0.311361 +v 0.975288 0.336589 -0.395346 +v -1.005180 0.336589 -0.395346 +v 1.090523 0.363933 -0.467611 +v -1.120415 0.363933 -0.467611 +v 1.197945 0.319011 -0.508627 +v -1.227837 0.319011 -0.508627 +v 1.207710 0.188151 -0.510580 +v -1.237602 0.188151 -0.510580 +v 1.106148 0.065104 -0.473471 +v -1.136040 0.065104 -0.473471 +v 0.947945 0.010417 -0.360190 +v -0.977837 0.010417 -0.360190 +v 0.862007 0.086589 -0.369955 +v -0.891899 0.086589 -0.369955 +v 0.932320 0.137370 -0.389486 +v -0.962212 0.137370 -0.389486 +v 0.992866 0.199870 -0.412924 +v -1.022758 0.199870 -0.412924 +v 1.051460 0.246745 -0.428549 +v -1.081352 0.246745 -0.428549 +v 1.008492 0.301433 -0.424643 +v -1.038383 0.301433 -0.424643 +v 0.940132 0.252604 -0.391440 +v -0.970024 0.252604 -0.391440 +v 0.881538 0.192058 -0.373861 +v -0.911430 0.192058 -0.373861 +v 0.817085 0.133464 -0.366049 +v -0.846977 0.133464 -0.366049 +v 0.856148 0.031901 -0.354330 +v -0.886040 0.031901 -0.354330 +v 0.951851 0.063151 -0.391440 +v -0.981743 0.063151 -0.391440 +v 1.063179 0.119792 -0.457846 +v -1.093071 0.119792 -0.457846 +v 1.143257 0.201823 -0.481283 +v -1.173149 0.201823 -0.481283 +v 1.145210 0.287761 -0.483236 +v -1.175102 0.287761 -0.483236 +v 1.089221 0.335287 -0.473471 +v -1.119113 0.335287 -0.473471 +v 0.895210 -0.093099 -0.362143 +v -0.925102 -0.093099 -0.362143 +v 1.153023 0.000651 -0.489096 +v -1.182915 0.000651 -0.489096 +v 1.313179 0.201823 -0.514486 +v -1.343071 0.201823 -0.514486 +v 1.285835 0.418620 -0.516440 +v -1.315727 0.418620 -0.516440 +v 1.117867 0.492839 -0.485190 +v -1.147758 0.492839 -0.485190 +v 0.934273 0.445964 -0.397299 +v -0.964165 0.445964 -0.397299 +v 0.912788 0.172526 -0.465658 +v -0.942680 0.172526 -0.465658 +v 1.141304 0.238933 -0.557455 +v -1.171196 0.238933 -0.557455 +v 1.294950 0.293620 -0.569825 +v -1.324842 0.293620 -0.569825 +v 0.820991 0.365886 -0.358236 +v -0.850884 0.365886 -0.358236 +v 0.750679 0.149089 -0.438315 +v -0.780571 0.149089 -0.438315 +v 0.684273 -0.079427 -0.305502 +v -0.714165 -0.079427 -0.305502 +v 0.448921 0.218425 0.709635 +v 0.445015 0.157390 0.684244 +v 0.513374 0.190104 0.632486 +v 0.488960 0.262858 0.673990 +v -0.474907 0.157390 0.684244 +v -0.478813 0.218425 0.709635 +v -0.518852 0.262858 0.673990 +v -0.543266 0.190104 0.632486 +v 0.495796 0.106608 0.591471 +v 0.570991 0.168620 0.526529 +v 0.561226 0.262858 0.577310 +v -0.525688 0.106608 0.591471 +v -0.591118 0.262858 0.577310 +v -0.600884 0.168620 0.526529 +v 0.409859 0.087565 0.654947 +v 0.336616 0.041667 0.623209 +v 0.434273 0.035808 0.553873 +v -0.366509 0.041667 0.623209 +v -0.439751 0.087565 0.654947 +v -0.464165 0.035808 0.553873 +v 0.383980 0.156413 0.723307 +v 0.337105 0.113933 0.705728 +v -0.366997 0.113933 0.705728 +v -0.413872 0.156413 0.723307 +v 0.292671 0.156413 0.740885 +v 0.231636 0.157390 0.723307 +v 0.263863 0.087565 0.681803 +v -0.261528 0.157390 0.723307 +v -0.322563 0.156413 0.740885 +v -0.293755 0.087565 0.681803 +v 0.177437 0.106608 0.648600 +v 0.238960 0.035808 0.589029 +v -0.207329 0.106608 0.648600 +v -0.268852 0.035808 0.589029 +v 0.160835 0.190104 0.694010 +v 0.112007 0.262858 0.654459 +v 0.102241 0.168620 0.608560 +v -0.141899 0.262858 0.654459 +v -0.190727 0.190104 0.694010 +v -0.132134 0.168620 0.608560 +v 0.230659 0.218425 0.749185 +v 0.188179 0.262858 0.725748 +v -0.218071 0.262858 0.725748 +v -0.260552 0.218425 0.749185 +v 0.230659 0.309733 0.749185 +v 0.231636 0.370769 0.723307 +v 0.160835 0.335612 0.694010 +v -0.261528 0.370769 0.723307 +v -0.260552 0.309733 0.749185 +v -0.190727 0.335612 0.694010 +v 0.177437 0.421550 0.648600 +v 0.102241 0.360026 0.608560 +v -0.207329 0.421550 0.648600 +v -0.132134 0.360026 0.608560 +v 0.263863 0.439128 0.681803 +v 0.336616 0.486979 0.623209 +v 0.238960 0.496745 0.589029 +v -0.366509 0.486979 0.623209 +v -0.293755 0.439128 0.681803 +v -0.268852 0.496745 0.589029 +v 0.292671 0.375163 0.740885 +v 0.337105 0.414714 0.705728 +v -0.366997 0.414714 0.705728 +v -0.322563 0.375163 0.740885 +v 0.383980 0.375163 0.723307 +v 0.445015 0.370769 0.684244 +v 0.409859 0.439128 0.654947 +v -0.474907 0.370769 0.684244 +v -0.413872 0.375163 0.723307 +v -0.439751 0.439128 0.654947 +v 0.495796 0.421550 0.591471 +v 0.434273 0.496745 0.553873 +v -0.525688 0.421550 0.591471 +v -0.464165 0.496745 0.553873 +v 0.513374 0.335612 0.632486 +v 0.570991 0.360026 0.526529 +v -0.543266 0.335612 0.632486 +v -0.600884 0.360026 0.526529 +v 0.448921 0.309733 0.709635 +v -0.478813 0.309733 0.709635 +v 0.419136 0.345378 0.731119 +v 0.435900 0.304851 0.735839 +v 0.449898 0.263347 0.723795 +v -0.449028 0.345378 0.731119 +v -0.479790 0.263347 0.723795 +v -0.465792 0.304851 0.735839 +v 0.337593 0.378581 0.748697 +v 0.379097 0.364746 0.749674 +v -0.367485 0.378581 0.748697 +v -0.408989 0.364746 0.749674 +v 0.260445 0.345378 0.762857 +v 0.297717 0.364746 0.767089 +v -0.290337 0.345378 0.762857 +v -0.327609 0.364746 0.767089 +v 0.228218 0.263347 0.764810 +v 0.241402 0.304851 0.774251 +v -0.258110 0.263347 0.764810 +v -0.271294 0.304851 0.774251 +v 0.260445 0.186198 0.762857 +v 0.241402 0.223470 0.774251 +v -0.290337 0.186198 0.762857 +v -0.271294 0.223470 0.774251 +v 0.337593 0.153972 0.748697 +v 0.297717 0.167155 0.767089 +v -0.367485 0.153972 0.748697 +v -0.327609 0.167155 0.767089 +v 0.419136 0.186198 0.731119 +v 0.379097 0.167155 0.749674 +v -0.449028 0.186198 0.731119 +v -0.408989 0.167155 0.749674 +v 0.435900 0.223470 0.735839 +v -0.465792 0.223470 0.735839 +v 0.386096 0.216146 0.758300 +v 0.404325 0.263021 0.753743 +v -0.415988 0.216146 0.758300 +v -0.434217 0.263021 0.753743 +v 0.337268 0.195964 0.770019 +v -0.367160 0.195964 0.770019 +v 0.290393 0.216146 0.778482 +v -0.320285 0.216146 0.778482 +v 0.270210 0.263021 0.779784 +v -0.300102 0.263021 0.779784 +v 0.290393 0.312500 0.778482 +v -0.320285 0.312500 0.778482 +v 0.337268 0.333334 0.770019 +v -0.367160 0.333334 0.770019 +v 0.386096 0.312500 0.758300 +v -0.415988 0.312500 0.758300 +v 0.149116 -0.928548 0.549967 +v 0.061714 -0.915853 0.590982 +v -0.014946 -0.940755 0.561685 +v 0.072945 -0.949544 0.516764 +v -0.091606 -0.915853 0.590982 +v -0.179009 -0.928548 0.549967 +v -0.102837 -0.949544 0.516764 +v 0.257027 -0.902669 0.538736 +v 0.177437 -0.898274 0.586099 +v 0.231148 -0.929036 0.491861 +v -0.207329 -0.898274 0.586099 +v -0.286919 -0.902669 0.538736 +v -0.261040 -0.929036 0.491861 +v 0.295113 -0.825032 0.555338 +v 0.230171 -0.842122 0.598795 +v 0.315620 -0.878255 0.481607 +v -0.260063 -0.842122 0.598795 +v -0.325005 -0.825032 0.555338 +v -0.345512 -0.878255 0.481607 +v 0.282906 -0.666341 0.582681 +v 0.237495 -0.738118 0.623697 +v 0.320503 -0.745442 0.502115 +v -0.267387 -0.738118 0.623697 +v -0.312798 -0.666341 0.582681 +v -0.350395 -0.745442 0.502115 +v 0.246284 -0.437337 0.594400 +v 0.211616 -0.552083 0.644693 +v 0.293159 -0.529622 0.521158 +v -0.241509 -0.552083 0.644693 +v -0.276177 -0.437337 0.594400 +v -0.323052 -0.529622 0.521158 +v 0.298042 -0.128743 0.519693 +v 0.397163 -0.067220 0.566080 +v 0.257515 -0.049153 0.671549 +v 0.185249 -0.130696 0.626139 +v -0.427055 -0.067220 0.566080 +v -0.327934 -0.128743 0.519693 +v -0.215141 -0.130696 0.626139 +v -0.287407 -0.049153 0.671549 +v 0.514839 -0.052571 0.493814 +v 0.603218 0.036296 0.533365 +v 0.487007 0.016765 0.595377 +v -0.633110 0.036296 0.533365 +v -0.544731 -0.052571 0.493814 +v -0.516899 0.016765 0.595377 +v 0.702827 0.087565 0.451334 +v 0.746284 0.203288 0.499674 +v 0.650093 0.139323 0.560221 +v -0.776177 0.203288 0.499674 +v -0.732719 0.087565 0.451334 +v -0.679985 0.139323 0.560221 +v 0.807808 0.308757 0.476725 +v 0.770210 0.400065 0.574869 +v 0.720406 0.303386 0.573892 +v -0.800102 0.400065 0.574869 +v -0.837700 0.308757 0.476725 +v -0.750298 0.303386 0.573892 +v 0.755562 0.465983 0.559244 +v 0.667671 0.479167 0.633951 +v 0.696968 0.415202 0.632975 +v -0.697563 0.479167 0.633951 +v -0.785454 0.465983 0.559244 +v -0.726860 0.415202 0.632975 +v 0.579292 0.550456 0.609049 +v 0.460640 0.594401 0.695475 +v 0.546577 0.499186 0.695963 +v -0.490532 0.594401 0.695475 +v -0.609184 0.550456 0.609049 +v -0.576469 0.499186 0.695963 +v 0.387886 0.681804 0.663248 +v 0.302925 0.699870 0.738443 +v 0.364448 0.607585 0.748697 +v -0.332817 0.699870 0.738443 +v -0.417778 0.681804 0.663248 +v -0.394341 0.607585 0.748697 +v 0.229195 0.736979 0.696939 +v 0.169624 0.666179 0.757486 +v 0.244331 0.643229 0.776041 +v -0.199516 0.666179 0.757486 +v -0.259087 0.736979 0.696939 +v -0.274223 0.643229 0.776041 +v 0.105171 0.610026 0.704264 +v 0.069038 0.498210 0.752115 +v 0.138863 0.543620 0.781900 +v -0.098930 0.498210 0.752115 +v -0.135063 0.610026 0.704264 +v -0.168755 0.543620 0.781900 +v 0.021675 0.468913 0.695475 +v -0.014946 0.428386 0.741373 +v 0.045113 0.415690 0.769693 +v -0.051567 0.468913 0.695475 +v -0.075005 0.415690 0.769693 +v 0.189644 0.466472 0.733560 +v 0.211616 0.549968 0.759439 +v 0.120796 0.445476 0.762369 +v -0.241509 0.549968 0.759439 +v -0.219536 0.466472 0.733560 +v -0.150688 0.445476 0.762369 +v 0.272163 0.506511 0.719889 +v 0.307808 0.568522 0.743326 +v -0.337700 0.568522 0.743326 +v -0.302055 0.506511 0.719889 +v 0.430855 0.508464 0.710123 +v 0.363472 0.488933 0.701822 +v -0.460747 0.508464 0.710123 +v -0.393364 0.488933 0.701822 +v 0.609077 0.419597 0.653971 +v 0.503609 0.431804 0.661783 +v -0.638969 0.419597 0.653971 +v -0.533501 0.431804 0.661783 +v 0.668648 0.345866 0.610514 +v 0.612007 0.361491 0.621256 +v -0.698540 0.345866 0.610514 +v -0.641899 0.361491 0.621256 +v 0.647652 0.215983 0.587564 +v 0.624214 0.268229 0.606607 +v -0.677544 0.215983 0.587564 +v -0.654106 0.268229 0.606607 +v 0.533882 0.086589 0.606607 +v 0.553902 0.148601 0.615396 +v -0.563774 0.086589 0.606607 +v -0.583794 0.148601 0.615396 +v 0.364937 0.015300 0.650064 +v 0.426948 0.060222 0.644205 +v -0.394829 0.015300 0.650064 +v -0.456841 0.060222 0.644205 +v 0.166695 0.027019 0.717447 +v 0.272163 0.062663 0.686197 +v -0.196587 0.027019 0.717447 +v -0.302055 0.062663 0.686197 +v 0.156441 0.121257 0.709146 +v 0.075386 0.116374 0.702310 +v 0.061226 -0.003743 0.719400 +v -0.105278 0.116374 0.702310 +v -0.186333 0.121257 0.709146 +v -0.091118 -0.003743 0.719400 +v 0.056831 0.345378 0.747232 +v 0.124214 0.380534 0.735025 +v -0.154106 0.380534 0.735025 +v -0.086723 0.345378 0.747232 +v -0.014946 0.295573 0.741373 +v 0.052925 0.231120 0.718912 +v 0.103706 0.280925 0.724283 +v -0.133598 0.280925 0.724283 +v -0.082817 0.231120 0.718912 +v 0.118843 0.191569 0.712076 +v -0.014946 0.160808 0.704264 +v -0.148735 0.191569 0.712076 +v 0.021675 -0.870931 0.640299 +v -0.014946 -0.894856 0.620279 +v 0.091988 -0.883626 0.621256 +v -0.051567 -0.870931 0.640299 +v -0.121880 -0.883626 0.621256 +v 0.086128 -0.845052 0.650064 +v 0.154488 -0.845540 0.630533 +v -0.116020 -0.845052 0.650064 +v -0.184380 -0.845540 0.630533 +v 0.112984 -0.768880 0.669107 +v 0.170601 -0.753255 0.653482 +v -0.142876 -0.768880 0.669107 +v -0.200493 -0.753255 0.653482 +v 0.133003 -0.438314 0.683756 +v 0.087105 -0.546712 0.693033 +v 0.164253 -0.653157 0.668131 +v -0.116997 -0.546712 0.693033 +v -0.162895 -0.438314 0.683756 +v -0.194145 -0.653157 0.668131 +v 0.102241 -0.692708 0.683267 +v -0.132134 -0.692708 0.683267 +v 0.028023 -0.304036 0.704264 +v -0.014946 -0.361653 0.702310 +v 0.027046 -0.437825 0.703287 +v 0.070991 -0.350911 0.697916 +v -0.057915 -0.304036 0.704264 +v -0.100884 -0.350911 0.697916 +v -0.056938 -0.437825 0.703287 +v -0.014946 -0.543294 0.698404 +v 0.040718 -0.640950 0.692545 +v -0.070610 -0.640950 0.692545 +v 0.039253 -0.716634 0.689127 +v -0.014946 -0.697591 0.690592 +v -0.069145 -0.716634 0.689127 +v 0.106148 -0.202474 0.726725 +v 0.094917 -0.229329 0.743326 +v 0.068550 -0.259603 0.719400 +v 0.099800 -0.239095 0.703287 +v -0.124809 -0.229329 0.743326 +v -0.136040 -0.202474 0.726725 +v -0.129692 -0.239095 0.703287 +v -0.098442 -0.259603 0.719400 +v 0.082710 -0.130208 0.719400 +v 0.102730 -0.161946 0.743814 +v 0.103218 -0.164388 0.709635 +v -0.132622 -0.161946 0.743814 +v -0.112602 -0.130208 0.719400 +v -0.133110 -0.164388 0.709635 +v 0.012886 -0.120931 0.719400 +v 0.055855 -0.113606 0.736490 +v 0.040230 -0.107747 0.706705 +v -0.085747 -0.113606 0.736490 +v -0.042778 -0.120931 0.719400 +v -0.070122 -0.107747 0.706705 +v -0.014946 -0.156575 0.726725 +v 0.002632 -0.139974 0.743814 +v -0.014946 -0.144856 0.713053 +v -0.032524 -0.139974 0.743814 +v 0.030464 -0.274739 0.735514 +v -0.014946 -0.293294 0.717935 +v -0.060356 -0.274739 0.735514 +v 0.064644 -0.242513 0.751627 +v 0.027046 -0.245931 0.760904 +v -0.014946 -0.273763 0.749185 +v -0.094536 -0.242513 0.751627 +v -0.056938 -0.245931 0.760904 +v -0.014946 -0.160481 0.764810 +v 0.017769 -0.155110 0.772623 +v 0.029976 -0.124837 0.755045 +v -0.047661 -0.155110 0.772623 +v -0.059868 -0.124837 0.755045 +v 0.053902 -0.137044 0.766764 +v 0.081734 -0.133626 0.755045 +v -0.083794 -0.137044 0.766764 +v -0.111626 -0.133626 0.755045 +v 0.079292 -0.167806 0.772623 +v 0.099312 -0.200521 0.764322 +v -0.109184 -0.167806 0.772623 +v -0.129204 -0.200521 0.764322 +v 0.069527 -0.220540 0.769205 +v -0.099419 -0.220540 0.769205 +v 0.039741 -0.193685 0.779459 +v -0.069634 -0.193685 0.779459 +v -0.014946 -0.223958 0.772623 +v 0.088081 -0.108724 0.722330 +v -0.014946 -0.046224 0.701334 +v -0.117973 -0.108724 0.722330 +v 0.124214 -0.208821 0.692057 +v 0.134956 -0.159505 0.690592 +v -0.154106 -0.208821 0.692057 +v -0.164848 -0.159505 0.690592 +v 0.120796 -0.290364 0.683756 +v 0.157906 -0.255208 0.652017 +v -0.150688 -0.290364 0.683756 +v -0.187798 -0.255208 0.652017 +v 0.177437 -0.356771 0.652994 +v -0.207329 -0.356771 0.652994 +v 0.251656 -0.347981 0.519205 +v 0.206734 -0.300130 0.590006 +v -0.236626 -0.300130 0.590006 +v -0.281548 -0.347981 0.519205 +v 0.217964 -0.257161 0.517252 +v 0.182320 -0.221517 0.595865 +v -0.212212 -0.221517 0.595865 +v -0.247856 -0.257161 0.517252 +v 0.193062 -0.190267 0.530924 +v -0.222954 -0.190267 0.530924 +v -0.014946 -0.739583 0.683756 +v 0.032906 -0.736653 0.672525 +v 0.074409 -0.727376 0.683756 +v -0.104302 -0.727376 0.683756 +v -0.062798 -0.736653 0.672525 +v 0.081245 -0.760579 0.667154 +v 0.083687 -0.801595 0.667154 +v -0.113579 -0.801595 0.667154 +v -0.111137 -0.760579 0.667154 +v 0.057808 -0.824056 0.648111 +v 0.039253 -0.849935 0.649576 +v -0.069145 -0.849935 0.649576 +v -0.087700 -0.824056 0.648111 +v 0.009468 -0.850911 0.637369 +v -0.014946 -0.860677 0.644693 +v -0.039360 -0.850911 0.637369 +v 0.031929 -0.834798 0.618326 +v 0.011421 -0.826009 0.599283 +v -0.014946 -0.845052 0.616373 +v -0.061821 -0.834798 0.618326 +v -0.041313 -0.826009 0.599283 +v 0.072945 -0.792806 0.632486 +v 0.057320 -0.806478 0.603027 +v -0.102837 -0.792806 0.632486 +v -0.087212 -0.806478 0.603027 +v 0.067085 -0.738607 0.648111 +v 0.074898 -0.766927 0.615234 +v -0.096977 -0.738607 0.648111 +v -0.104790 -0.766927 0.615234 +v -0.014946 -0.749349 0.645670 +v 0.028999 -0.755696 0.620767 +v -0.058891 -0.755696 0.620767 +v -0.014946 -0.795247 0.601724 +v 0.048531 -0.784017 0.603515 +v -0.078423 -0.784017 0.603515 +v 0.162788 0.171061 0.718912 +v 0.163277 0.207683 0.727213 +v 0.140327 0.237468 0.725260 +v -0.192680 0.171061 0.718912 +v -0.170219 0.237468 0.725260 +v -0.193169 0.207683 0.727213 +v 0.157417 0.278483 0.731607 +v 0.141792 0.321940 0.729654 +v -0.171684 0.321940 0.729654 +v -0.187309 0.278483 0.731607 +v 0.176460 0.358073 0.733072 +v 0.177437 0.409343 0.731607 +v -0.207329 0.409343 0.731607 +v -0.206352 0.358073 0.733072 +v 0.215034 0.119792 0.713053 +v 0.191109 0.152995 0.726725 +v -0.244927 0.119792 0.713053 +v -0.221001 0.152995 0.726725 +v 0.353706 0.072429 0.680338 +v 0.285347 0.104655 0.710611 +v -0.383598 0.072429 0.680338 +v -0.315239 0.104655 0.710611 +v 0.470406 0.110515 0.651041 +v 0.410835 0.099284 0.679361 +v -0.500298 0.110515 0.651041 +v -0.440727 0.099284 0.679361 +v 0.573433 0.210612 0.624674 +v 0.513374 0.167644 0.649088 +v -0.603325 0.210612 0.624674 +v -0.543266 0.167644 0.649088 +v 0.592964 0.309245 0.625162 +v 0.569527 0.262858 0.633951 +v -0.622856 0.309245 0.625162 +v -0.599419 0.262858 0.633951 +v 0.551460 0.381511 0.642740 +v 0.561226 0.340983 0.641275 +v -0.581352 0.381511 0.642740 +v -0.591118 0.340983 0.641275 +v 0.418648 0.435710 0.694498 +v 0.477730 0.397624 0.682779 +v -0.448540 0.435710 0.694498 +v -0.507622 0.397624 0.682779 +v 0.320015 0.467936 0.707682 +v 0.363472 0.437663 0.715494 +v -0.349907 0.467936 0.707682 +v -0.393364 0.437663 0.715494 +v 0.246284 0.460124 0.721353 +v 0.288277 0.448894 0.718912 +v -0.276177 0.460124 0.721353 +v -0.318169 0.448894 0.718912 +v 0.224800 0.421550 0.730142 +v -0.254692 0.421550 0.730142 +v 0.210152 0.383952 0.725748 +v 0.242866 0.399089 0.717935 +v 0.262886 0.425944 0.723795 +v -0.240044 0.383952 0.725748 +v -0.292778 0.425944 0.723795 +v -0.272759 0.399089 0.717935 +v 0.293648 0.422526 0.714029 +v 0.323921 0.434245 0.713053 +v -0.353813 0.434245 0.713053 +v -0.323540 0.422526 0.714029 +v 0.360054 0.418620 0.706217 +v 0.408882 0.411296 0.707682 +v -0.438774 0.411296 0.707682 +v -0.389946 0.418620 0.706217 +v 0.457710 0.383464 0.671060 +v 0.518745 0.362956 0.652017 +v -0.548637 0.362956 0.652017 +v -0.487602 0.383464 0.671060 +v 0.528023 0.328776 0.631998 +v 0.551460 0.302409 0.636392 +v -0.581352 0.302409 0.636392 +v -0.557915 0.328776 0.631998 +v 0.535835 0.266276 0.628092 +v 0.536812 0.221843 0.636881 +v -0.566704 0.221843 0.636881 +v -0.565727 0.266276 0.628092 +v 0.488960 0.184245 0.643717 +v 0.453804 0.136882 0.665689 +v -0.483696 0.136882 0.665689 +v -0.518852 0.184245 0.643717 +v 0.403023 0.121745 0.671060 +v 0.354195 0.104167 0.692057 +v -0.384087 0.104167 0.692057 +v -0.432915 0.121745 0.671060 +v 0.293648 0.125651 0.698404 +v 0.232124 0.137858 0.720377 +v -0.262016 0.137858 0.720377 +v -0.323540 0.125651 0.698404 +v 0.207710 0.168620 0.710123 +v 0.183784 0.185710 0.719400 +v -0.213677 0.185710 0.719400 +v -0.237602 0.168620 0.710123 +v 0.176460 0.316569 0.725260 +v 0.199898 0.348308 0.714029 +v -0.206352 0.316569 0.725260 +v -0.229790 0.348308 0.714029 +v 0.170601 0.244792 0.721842 +v 0.180366 0.281901 0.710123 +v -0.200493 0.244792 0.721842 +v -0.210259 0.281901 0.710123 +v 0.184273 0.219401 0.706217 +v -0.214165 0.219401 0.706217 +v 0.071480 0.516276 0.635904 +v 0.032254 0.468588 0.576334 +v -0.014946 0.452800 0.630045 +v -0.101372 0.516276 0.635904 +v -0.062147 0.468588 0.576334 +v 0.168648 0.688640 0.639810 +v 0.164253 0.595378 0.582193 +v -0.198540 0.688640 0.639810 +v -0.194145 0.595378 0.582193 +v 0.314156 0.720866 0.617838 +v 0.251167 0.682780 0.576334 +v -0.344048 0.720866 0.617838 +v -0.281059 0.682780 0.576334 +v 0.479195 0.602702 0.574869 +v 0.362495 0.641276 0.552408 +v -0.509087 0.602702 0.574869 +v -0.392387 0.641276 0.552408 +v 0.671089 0.496257 0.518717 +v 0.565132 0.527019 0.475260 +v -0.700981 0.496257 0.518717 +v -0.595024 0.527019 0.475260 +v 0.793159 0.411784 0.472818 +v 0.721870 0.453288 0.428385 +v -0.823052 0.411784 0.472818 +v -0.751762 0.453288 0.428385 +v 0.766304 0.187175 0.389322 +v 0.778023 0.310222 0.359049 +v -0.796196 0.187175 0.389322 +v -0.807915 0.310222 0.359049 +v 0.602730 0.010417 0.427408 +v 0.691109 0.100261 0.321451 +v -0.632622 0.010417 0.427408 +v -0.721001 0.100261 0.321451 +v 0.415718 -0.092610 0.457193 +v 0.512886 -0.039876 0.367838 +v -0.445610 -0.092610 0.457193 +v -0.542778 -0.039876 0.367838 +v -0.014946 -0.494466 0.258951 +v 0.073433 -0.439290 0.222818 +v 0.129585 -0.456380 0.275064 +v 0.051948 -0.549642 0.289224 +v -0.103325 -0.439290 0.222818 +v -0.081841 -0.549642 0.289224 +v -0.159477 -0.456380 0.275064 +v -0.014946 -0.657552 0.296060 +v 0.118355 -0.627767 0.318521 +v 0.055855 -0.755208 0.321451 +v -0.085747 -0.755208 0.321451 +v -0.148247 -0.627767 0.318521 +v -0.014946 -0.860677 0.358560 +v 0.137886 -0.831380 0.357096 +v 0.066597 -0.920247 0.408365 +v -0.096489 -0.920247 0.408365 +v -0.167778 -0.831380 0.357096 +v -0.014946 -0.954427 0.469889 +v 0.154976 -0.936360 0.450846 +v -0.184868 -0.936360 0.450846 +v 0.228218 -0.888509 0.383951 +v 0.293648 -0.896810 0.421060 +v -0.323540 -0.896810 0.421060 +v -0.258110 -0.888509 0.383951 +v 0.278999 -0.810384 0.365396 +v 0.309761 -0.771321 0.416666 +v -0.339653 -0.771321 0.416666 +v -0.308891 -0.810384 0.365396 +v 0.248726 -0.614095 0.360514 +v 0.285835 -0.577474 0.434732 +v -0.315727 -0.577474 0.434732 +v -0.278618 -0.614095 0.360514 +v 0.200386 -0.711751 0.336588 +v 0.178413 -0.509114 0.325846 +v -0.230278 -0.711751 0.336588 +v -0.208305 -0.509114 0.325846 +v 0.227241 -0.429524 0.364908 +v 0.190620 -0.373860 0.289224 +v -0.257134 -0.429524 0.364908 +v -0.220512 -0.373860 0.289224 +v 0.257515 -0.387532 0.444010 +v -0.287407 -0.387532 0.444010 +v 0.225777 -0.281575 0.450357 +v 0.229683 -0.222005 0.401041 +v 0.207222 -0.218099 0.467935 +v -0.259575 -0.222005 0.401041 +v -0.255669 -0.281575 0.450357 +v -0.237114 -0.218099 0.467935 +v 0.215034 -0.314290 0.366373 +v -0.244927 -0.314290 0.366373 +v 0.212756 -0.172688 0.448567 +v 0.219917 -0.159017 0.481119 +v -0.249809 -0.159017 0.481119 +v -0.242648 -0.172688 0.448567 +v 0.296252 -0.124349 0.447102 +v -0.326144 -0.124349 0.447102 +v 0.161323 0.108073 -0.776205 +v 0.294462 -0.022786 -0.659343 +v 0.153511 -0.144368 -0.629721 +v -0.014946 -0.038411 -0.756674 +v -0.324354 -0.022786 -0.659343 +v -0.191216 0.108073 -0.776205 +v -0.183403 -0.144368 -0.629721 +v 0.282417 -0.199544 -0.456869 +v 0.131050 -0.315267 -0.328940 +v -0.014946 -0.254231 -0.528158 +v -0.312309 -0.199544 -0.456869 +v -0.160942 -0.315267 -0.328940 +v 0.227730 -0.319173 -0.096029 +v 0.093941 -0.398763 0.083170 +v -0.014946 -0.384114 -0.118002 +v -0.257622 -0.319173 -0.096029 +v -0.123833 -0.398763 0.083170 +v 0.159859 -0.380208 0.195963 +v -0.014946 -0.434896 0.184732 +v -0.189751 -0.380208 0.195963 +v 0.214872 -0.307942 0.245116 +v -0.244764 -0.307942 0.245116 +v 0.640327 0.010905 0.203287 +v 0.764839 0.120769 0.045084 +v 0.773140 0.217448 0.197428 +v -0.670219 0.010905 0.203287 +v -0.803032 0.217448 0.197428 +v -0.794731 0.120769 0.045084 +v 0.207222 0.513347 -0.778158 +v 0.352730 0.266276 -0.732260 +v -0.014946 0.319011 -0.844565 +v -0.382622 0.266276 -0.732260 +v -0.237114 0.513347 -0.778158 +v 0.212105 0.864421 0.205728 +v 0.404976 0.896647 0.022135 +v 0.211616 0.957683 -0.124838 +v -0.014946 0.948894 0.055826 +v -0.434868 0.896647 0.022135 +v -0.241997 0.864421 0.205728 +v -0.241509 0.957683 -0.124838 +v 0.404976 0.901042 -0.292807 +v 0.212105 0.864421 -0.498861 +v -0.014946 0.950847 -0.334799 +v -0.434868 0.901042 -0.292807 +v -0.241997 0.864421 -0.498861 +v 0.406441 0.663737 -0.602865 +v -0.014946 0.731120 -0.703939 +v -0.436333 0.663737 -0.602865 +v 0.739937 0.406413 0.330240 +v 0.676948 0.475261 0.258463 +v 0.631538 0.478190 0.357584 +v -0.769829 0.406413 0.330240 +v -0.661430 0.478190 0.357584 +v -0.706841 0.475261 0.258463 +v 0.742866 0.490397 0.150553 +v 0.698921 0.633952 0.042643 +v 0.614937 0.600261 0.152506 +v -0.772759 0.490397 0.150553 +v -0.644829 0.600261 0.152506 +v -0.728813 0.633952 0.042643 +v 0.767769 0.593913 -0.065268 +v 0.703804 0.688151 -0.200033 +v 0.621773 0.750163 -0.085775 +v -0.797661 0.593913 -0.065268 +v -0.651665 0.750163 -0.085775 +v -0.733696 0.688151 -0.200033 +v 0.762398 0.580241 -0.302572 +v 0.700874 0.599772 -0.429037 +v 0.621773 0.740886 -0.342123 +v -0.792290 0.580241 -0.302572 +v -0.651665 0.740886 -0.342123 +v -0.730766 0.599772 -0.429037 +v 0.666695 0.319987 -0.538900 +v 0.612007 0.529948 -0.548178 +v 0.753609 0.444011 -0.427084 +v -0.641899 0.529948 -0.548178 +v -0.696587 0.319987 -0.538900 +v -0.783501 0.444011 -0.427084 +v 0.530952 0.753093 -0.451498 +v 0.508980 0.408855 -0.654623 +v -0.560844 0.753093 -0.451498 +v -0.538872 0.408855 -0.654623 +v 0.531929 0.843913 -0.177084 +v -0.561821 0.843913 -0.177084 +v 0.531929 0.769206 0.092447 +v -0.561821 0.769206 0.092447 +v 0.407417 0.699870 0.279947 +v 0.536323 0.546550 0.306314 +v -0.566216 0.546550 0.306314 +v -0.437309 0.699870 0.279947 +v 0.428413 0.545573 0.447428 +v -0.458305 0.545573 0.447428 +v 0.223335 0.603190 0.436685 +v -0.014946 0.742839 0.361490 +v -0.253227 0.603190 0.436685 +v 0.269722 0.553874 0.530924 +v -0.299614 0.553874 0.530924 +v 0.087430 0.529623 0.534830 +v -0.117322 0.529623 0.534830 +v -0.014946 0.503907 0.546060 +v 0.778511 0.351237 0.159830 +v -0.808403 0.351237 0.159830 +v 0.813179 0.285808 -0.012045 +v 0.805855 0.450358 -0.010092 +v -0.835747 0.450358 -0.010092 +v -0.843071 0.285808 -0.012045 +v 0.817085 0.367839 -0.163412 +v 0.793159 0.480144 -0.208822 +v -0.823052 0.480144 -0.208822 +v -0.846977 0.367839 -0.163412 +v 0.791695 0.364421 -0.352377 +v -0.821587 0.364421 -0.352377 +v 0.347847 -0.213216 -0.270834 +v 0.413277 -0.172200 -0.079428 +v 0.292997 -0.257649 0.085937 +v -0.377739 -0.213216 -0.270834 +v -0.322889 -0.257649 0.085937 +v -0.443169 -0.172200 -0.079428 +v 0.541695 -0.087728 0.069986 +v 0.510445 -0.112630 -0.231772 +v 0.625679 -0.068685 -0.097983 +v -0.571587 -0.087728 0.069986 +v -0.655571 -0.068685 -0.097983 +v -0.540337 -0.112630 -0.231772 +v 0.411812 -0.114095 0.274088 +v -0.441704 -0.114095 0.274088 +v 0.297717 -0.149251 0.405110 +v 0.290555 -0.211751 0.257323 +v -0.327609 -0.149251 0.405110 +v -0.320447 -0.211751 0.257323 +v 0.687202 0.154948 -0.484213 +v 0.557808 0.043132 -0.497397 +v 0.536323 0.198894 -0.608236 +v -0.587700 0.043132 -0.497397 +v -0.717094 0.154948 -0.484213 +v -0.566216 0.198894 -0.608236 +v 0.405790 0.086589 -0.648601 +v -0.435682 0.086589 -0.648601 +v 0.445015 -0.081380 -0.415365 +v 0.602730 -0.056966 -0.342123 +v -0.474907 -0.081380 -0.415365 +v -0.632622 -0.056966 -0.342123 +v 0.386258 -0.056478 -0.558757 +v -0.416150 -0.056478 -0.558757 +v 0.941597 0.450847 -0.334799 +v 0.896187 0.401530 -0.277182 +v 0.954292 0.405925 -0.308920 +v 1.014351 0.461101 -0.348471 +v -0.926079 0.401530 -0.277182 +v -0.971489 0.450847 -0.334799 +v -1.044243 0.461101 -0.348471 +v -0.984184 0.405925 -0.308920 +v 1.089546 0.444987 -0.394369 +v 1.184273 0.468425 -0.437826 +v 1.111519 0.499187 -0.426107 +v -1.119438 0.444987 -0.394369 +v -1.141411 0.499187 -0.426107 +v -1.214165 0.468425 -0.437826 +v 1.216988 0.382487 -0.450522 +v 1.273628 0.316081 -0.457358 +v 1.271675 0.423991 -0.475424 +v -1.246880 0.382487 -0.450522 +v -1.301567 0.423991 -0.475424 +v -1.303520 0.316081 -0.457358 +v 1.229683 0.202800 -0.457358 +v 1.212593 0.099284 -0.448568 +v 1.294624 0.205729 -0.478354 +v -1.259575 0.202800 -0.457358 +v -1.324516 0.205729 -0.478354 +v -1.242485 0.099284 -0.448568 +v 1.110054 0.037761 -0.408529 +v 1.017281 -0.037435 -0.349447 +v 1.142281 0.003093 -0.436361 +v -1.139946 0.037761 -0.408529 +v -1.172173 0.003093 -0.436361 +v -1.047173 -0.037435 -0.349447 +v 0.915718 -0.037435 -0.272299 +v 0.797066 -0.076985 -0.201010 +v 0.895210 -0.090657 -0.292318 +v -0.945610 -0.037435 -0.272299 +v -0.925102 -0.090657 -0.292318 +v -0.826958 -0.076985 -0.201010 +v 1.018257 0.010417 -0.370443 +v 0.942573 0.003581 -0.330893 +v 0.851753 -0.019856 -0.242514 +v -0.972466 0.003581 -0.330893 +v -1.048149 0.010417 -0.370443 +v -0.881645 -0.019856 -0.242514 +v 1.170113 0.115886 -0.458334 +v 1.101265 0.063151 -0.449545 +v -1.131157 0.063151 -0.449545 +v -1.200005 0.115886 -0.458334 +v 1.219917 0.282878 -0.468100 +v 1.202339 0.192546 -0.489584 +v -1.232231 0.192546 -0.489584 +v -1.249809 0.282878 -0.468100 +v 1.153511 0.400065 -0.448080 +v 1.193550 0.330730 -0.485678 +v -1.223442 0.330730 -0.485678 +v -1.183403 0.400065 -0.448080 +v 1.013863 0.395671 -0.370443 +v 1.085152 0.379069 -0.441244 +v -1.115044 0.379069 -0.441244 +v -1.043755 0.395671 -0.370443 +v 0.921089 0.349772 -0.304525 +v 0.968941 0.350261 -0.366049 +v -0.950981 0.349772 -0.304525 +v -0.998833 0.350261 -0.366049 +v 0.668648 -0.051595 -0.185873 +v 0.700060 0.003418 -0.161134 +v 0.721870 0.027995 -0.064291 +v -0.698540 -0.051595 -0.185873 +v -0.751762 0.027995 -0.064291 +v -0.729953 0.003418 -0.161134 +v 0.683784 -0.093587 -0.218588 +v 0.756538 -0.034017 -0.206381 +v -0.713677 -0.093587 -0.218588 +v -0.786430 -0.034017 -0.206381 +v 0.773628 0.167155 -0.104818 +v -0.803520 0.167155 -0.104818 +v 0.825874 0.332194 -0.243490 +v 0.868843 0.343425 -0.266928 +v 0.839058 0.376628 -0.285971 +v -0.898735 0.343425 -0.266928 +v -0.855766 0.332194 -0.243490 +v -0.868950 0.376628 -0.285971 +v 0.823433 -0.002278 -0.281088 +v 0.763863 0.003093 -0.261068 +v -0.853325 -0.002278 -0.281088 +v -0.793755 0.003093 -0.261068 +v 0.765327 0.049479 -0.278647 +v 0.718127 0.026368 -0.226075 +v 0.799995 0.021159 -0.311361 +v -0.748019 0.026368 -0.226075 +v -0.795219 0.049479 -0.278647 +v -0.829887 0.021159 -0.311361 +v 0.744820 0.099772 -0.281088 +v 0.806343 0.072429 -0.317709 +v 0.774116 0.101726 -0.317709 +v -0.774712 0.099772 -0.281088 +v -0.804009 0.101726 -0.317709 +v -0.836235 0.072429 -0.317709 +v 0.798042 0.202312 -0.284018 +v 0.752144 0.147624 -0.234701 +v 0.778023 0.151530 -0.313803 +v -0.782036 0.147624 -0.234701 +v -0.827934 0.202312 -0.284018 +v -0.807915 0.151530 -0.313803 +v 0.813179 0.271159 -0.251303 +v 0.843452 0.231608 -0.312338 +v 0.854195 0.284343 -0.284506 +v -0.843071 0.271159 -0.251303 +v -0.884087 0.284343 -0.284506 +v -0.873344 0.231608 -0.312338 +v 0.899116 0.298503 -0.320150 +v -0.929009 0.298503 -0.320150 +v 0.800484 0.257487 -0.182455 +v -0.830376 0.257487 -0.182455 +v 0.720568 0.066407 -0.176270 +v -0.750460 0.066407 -0.176270 +v 0.876656 0.257487 -0.340170 +v 0.914741 0.276042 -0.372885 +v 0.937202 0.314616 -0.366049 +v -0.906548 0.257487 -0.340170 +v -0.967094 0.314616 -0.366049 +v -0.944634 0.276042 -0.372885 +v 0.821480 0.190593 -0.340170 +v 0.859077 0.215983 -0.360190 +v -0.851372 0.190593 -0.340170 +v -0.888969 0.215983 -0.360190 +v 0.764351 0.122233 -0.340658 +v 0.795601 0.148112 -0.358725 +v -0.794243 0.122233 -0.340658 +v -0.825493 0.148112 -0.358725 +v 0.804390 0.095378 -0.340658 +v 0.789741 0.113444 -0.358725 +v -0.834282 0.095378 -0.340658 +v -0.819634 0.113444 -0.358725 +v 0.825386 0.040202 -0.340658 +v 0.833198 0.072429 -0.359701 +v -0.855278 0.040202 -0.340658 +v -0.863091 0.072429 -0.359701 +v 0.810738 0.007976 -0.333334 +v 0.826363 0.023112 -0.355795 +v -0.840630 0.007976 -0.333334 +v -0.856255 0.023112 -0.355795 +v 0.879097 0.003581 -0.308920 +v 0.838570 0.010905 -0.334799 +v -0.908989 0.003581 -0.308920 +v -0.868462 0.010905 -0.334799 +v 0.986519 0.323894 -0.416342 +v 1.024605 0.353190 -0.430990 +v -1.054497 0.353190 -0.430990 +v -1.016411 0.323894 -0.416342 +v 1.094104 0.352865 -0.481772 +v 1.154488 0.356608 -0.496420 +v -1.184380 0.356608 -0.496420 +v -1.123996 0.352865 -0.481772 +v 1.189644 0.308269 -0.513998 +v 1.216988 0.259929 -0.511068 +v -1.246880 0.259929 -0.511068 +v -1.219536 0.308269 -0.513998 +v 1.197456 0.189616 -0.513998 +v 1.170601 0.118327 -0.500326 +v -1.200493 0.118327 -0.500326 +v -1.227348 0.189616 -0.513998 +v 1.099312 0.077800 -0.481283 +v 1.027534 0.028972 -0.427572 +v -1.057426 0.028972 -0.427572 +v -1.129204 0.077800 -0.481283 +v 0.949898 0.024577 -0.381674 +v -0.979790 0.024577 -0.381674 +v 0.869331 0.059245 -0.367025 +v 0.898140 0.109050 -0.377768 +v 0.841988 0.111979 -0.368002 +v -0.899223 0.059245 -0.367025 +v -0.871880 0.111979 -0.368002 +v -0.928032 0.109050 -0.377768 +v 0.947945 0.107097 -0.392904 +v 0.964058 0.168620 -0.402182 +v 0.908882 0.162761 -0.382650 +v -0.977837 0.107097 -0.392904 +v -0.938774 0.162761 -0.382650 +v -0.993950 0.168620 -0.402182 +v 1.020210 0.168132 -0.427084 +v 1.021187 0.227214 -0.421713 +v 0.969917 0.224772 -0.404623 +v -1.050102 0.168132 -0.427084 +v -0.999809 0.224772 -0.404623 +v -1.051079 0.227214 -0.421713 +v 1.082222 0.221843 -0.442709 +v 1.090523 0.264812 -0.445150 +v 1.032906 0.274089 -0.426596 +v -1.112114 0.221843 -0.442709 +v -1.062798 0.274089 -0.426596 +v -1.120415 0.264812 -0.445150 +v 0.971870 0.279460 -0.405600 +v 1.048205 0.319662 -0.447592 +v -1.001762 0.279460 -0.405600 +v -1.078097 0.319662 -0.447592 +v 0.910835 0.222819 -0.381186 +v -0.940727 0.222819 -0.381186 +v 0.850777 0.161784 -0.368979 +v -0.880669 0.161784 -0.368979 +v 0.899605 0.045573 -0.358725 +v -0.929497 0.045573 -0.358725 +v 1.008003 0.087077 -0.431479 +v -1.037895 0.087077 -0.431479 +v 1.110542 0.158854 -0.473471 +v -1.140434 0.158854 -0.473471 +v 1.156441 0.245769 -0.483725 +v -1.186333 0.245769 -0.483725 +v 1.119494 0.320150 -0.479818 +v -1.149386 0.320150 -0.479818 +v 0.778023 -0.099446 -0.302084 +v 0.901558 -0.022786 -0.433920 +v 1.024117 -0.059896 -0.439779 +v -0.807915 -0.099446 -0.302084 +v -1.054008 -0.059896 -0.439779 +v -0.931450 -0.022786 -0.433920 +v 1.153999 0.062175 -0.539389 +v 1.257515 0.088054 -0.513022 +v -1.287407 0.088054 -0.513022 +v -1.183891 0.062175 -0.539389 +v 1.314481 0.221843 -0.550782 +v 1.321968 0.319499 -0.510092 +v -1.351860 0.319499 -0.510092 +v -1.344373 0.221843 -0.550782 +v 1.292020 0.379558 -0.555177 +v 1.214546 0.482097 -0.514486 +v -1.244438 0.482097 -0.514486 +v -1.321912 0.379558 -0.555177 +v 1.125679 0.419597 -0.540365 +v 1.017281 0.473308 -0.441732 +v -1.047173 0.473308 -0.441732 +v -1.155571 0.419597 -0.540365 +v 0.924995 0.369792 -0.454428 +v 0.868843 0.410319 -0.365072 +v -0.898735 0.410319 -0.365072 +v -0.954887 0.369792 -0.454428 +v 1.021675 0.200847 -0.521811 +v 0.820503 0.154948 -0.425619 +v -1.051567 0.200847 -0.521811 +v -0.850395 0.154948 -0.425619 +v 1.242215 0.274089 -0.573243 +v -1.272108 0.274089 -0.573243 +v 0.793648 0.300944 -0.426108 +v -0.823540 0.300944 -0.426108 +v 0.708687 -0.005696 -0.397299 +v -0.738579 -0.005696 -0.397299 +v 0.423897 0.180949 0.715250 +v -0.453789 0.180949 0.715250 +v 0.472359 0.128337 0.641764 +v -0.502251 0.128337 0.641764 +v 0.517281 0.088542 0.537271 +v -0.547173 0.088542 0.537271 +v 0.336616 0.016276 0.572428 +v -0.366509 0.016276 0.572428 +v 0.336739 0.072429 0.669229 +v -0.366631 0.072429 0.669229 +v 0.337471 0.147380 0.732340 +v -0.367363 0.147380 0.732340 +v 0.255196 0.180949 0.747110 +v -0.285088 0.180949 0.747110 +v 0.201729 0.128337 0.690714 +v -0.231621 0.128337 0.690714 +v 0.155952 0.088542 0.601725 +v -0.185844 0.088542 0.601725 +v 0.082710 0.263347 0.610514 +v -0.112602 0.263347 0.610514 +v 0.145698 0.262614 0.694254 +v -0.175591 0.262614 0.694254 +v 0.221626 0.263225 0.749185 +v -0.251518 0.263225 0.749185 +v 0.255196 0.349772 0.747110 +v -0.285088 0.349772 0.747110 +v 0.201729 0.398112 0.690714 +v -0.231621 0.398112 0.690714 +v 0.155952 0.443034 0.601725 +v -0.185844 0.443034 0.601725 +v 0.336616 0.516276 0.572428 +v -0.366509 0.516276 0.572428 +v 0.336739 0.454265 0.669229 +v -0.366631 0.454265 0.669229 +v 0.337471 0.384196 0.732340 +v -0.367363 0.384196 0.732340 +v 0.423897 0.349772 0.715250 +v -0.453789 0.349772 0.715250 +v 0.472359 0.398112 0.641764 +v -0.502251 0.398112 0.641764 +v 0.517281 0.443034 0.537271 +v -0.547173 0.443034 0.537271 +v 0.590523 0.263347 0.522623 +v -0.620415 0.263347 0.522623 +v 0.528511 0.262614 0.628824 +v -0.558403 0.262614 0.628824 +v 0.457710 0.263225 0.707437 +v -0.487602 0.263225 0.707437 +v 0.440458 0.263265 0.735188 +v -0.470350 0.263265 0.735188 +v 0.412585 0.339112 0.742065 +v -0.442477 0.339112 0.742065 +v 0.337512 0.370687 0.759643 +v -0.367404 0.370687 0.759643 +v 0.265978 0.339112 0.772623 +v -0.295871 0.339112 0.772623 +v 0.235298 0.263265 0.774413 +v -0.265190 0.263265 0.774413 +v 0.265978 0.191732 0.772623 +v -0.295871 0.191732 0.772623 +v 0.337023 0.262980 0.778645 +v -0.366915 0.262980 0.778645 +v 0.337512 0.161052 0.759643 +v -0.367404 0.161052 0.759643 +v 0.412585 0.191732 0.742065 +v -0.442477 0.191732 0.742065 +v -0.014946 0.453044 0.693033 +v -0.014946 0.372613 0.765895 +v -0.014946 -0.640950 0.692545 +v -0.014946 -0.285970 0.735514 +v -0.014946 -0.155110 0.747476 +v -0.014946 -0.744954 0.670816 +v -0.014946 0.459229 0.573892 +v -0.014946 0.586734 0.503092 +v -0.014946 0.875896 -0.534506 +v -0.014946 0.538249 -0.816244 +v -0.014946 0.113444 -0.815756 +v -0.014946 -0.332112 -0.348471 +v 0.211983 -0.157064 0.533731 +v -0.241875 -0.157064 0.533731 +v 0.273750 -0.423177 0.521891 +v -0.303642 -0.423177 0.521891 +v 0.309029 -0.644612 0.515177 +v -0.338921 -0.644612 0.515177 +v 0.323921 -0.825521 0.488687 +v -0.353813 -0.825521 0.488687 +v 0.287422 -0.910481 0.482218 +v -0.317314 -0.910481 0.482218 +v 0.156441 -0.940022 0.505167 +v -0.186333 -0.940022 0.505167 +v -0.014946 -0.953938 0.522135 +v 0.412056 -0.096761 0.501993 +v -0.441948 -0.096761 0.501993 +v 0.610420 0.007609 0.481485 +v -0.640312 0.007609 0.481485 +v 0.774483 0.187785 0.438150 +v -0.804375 0.187785 0.438150 +v 0.801826 0.413737 0.529581 +v -0.831719 0.413737 0.529581 +v 0.678291 0.500041 0.580728 +v -0.708183 0.500041 0.580728 +v 0.476509 0.612590 0.638468 +v -0.506401 0.612590 0.638468 +v 0.307442 0.731975 0.682901 +v -0.337334 0.731975 0.682901 +v 0.159615 0.696452 0.704386 +v -0.189507 0.696452 0.704386 +v 0.060860 0.520061 0.700113 +v -0.090752 0.520061 0.700113 +v 0.152046 0.427409 0.736856 +v -0.181938 0.427409 0.736856 +v 0.107613 0.330241 0.730142 +v -0.137505 0.330241 0.730142 +v 0.197823 0.091716 0.704874 +v -0.227715 0.091716 0.704874 +v 0.356270 0.047648 0.662760 +v -0.386162 0.047648 0.662760 +v 0.490669 0.095500 0.628946 +v -0.520561 0.095500 0.628946 +v 0.602974 0.209514 0.606851 +v -0.632866 0.209514 0.606851 +v 0.624824 0.320353 0.612223 +v -0.654717 0.320353 0.612223 +v 0.575142 0.396892 0.636759 +v -0.605034 0.396892 0.636759 +v 0.424141 0.463420 0.686685 +v -0.454033 0.463420 0.686685 +v 0.231514 0.494060 0.727213 +v -0.261406 0.494060 0.727213 +v -0.014946 -0.726155 0.688883 +v 0.097554 -0.717005 0.682623 +v -0.127446 -0.717005 0.682623 +v 0.106758 -0.815267 0.658487 +v -0.136650 -0.815267 0.658487 +v 0.056099 -0.862264 0.643961 +v -0.085991 -0.862264 0.643961 +v -0.014946 -0.873128 0.639078 +v -0.014946 -0.142903 0.724771 +v -0.014946 -0.114258 0.703613 +v 0.081123 -0.128255 0.710123 +v -0.111015 -0.128255 0.710123 +v 0.108711 -0.205037 0.706827 +v -0.138603 -0.205037 0.706827 +v 0.074585 -0.279661 0.700201 +v -0.104477 -0.279661 0.700201 +v 0.378853 -0.023397 0.623941 +v -0.408745 -0.023397 0.623941 +v 0.578560 0.071086 0.577066 +v -0.608452 0.071086 0.577066 +v 0.698433 0.217936 0.555582 +v -0.728325 0.217936 0.555582 +v 0.718941 0.375773 0.603556 +v -0.748833 0.375773 0.603556 +v 0.643257 0.447673 0.663370 +v -0.673149 0.447673 0.663370 +v 0.441963 0.556804 0.725992 +v -0.471855 0.556804 0.725992 +v 0.302437 0.640178 0.765055 +v -0.332329 0.640178 0.765055 +v 0.189888 0.612468 0.781656 +v -0.219780 0.612468 0.781656 +v 0.090767 0.467692 0.777628 +v -0.120659 0.467692 0.777628 +v 0.127469 -0.076117 0.732909 +v -0.157361 -0.076117 0.732909 +v 0.193306 -0.439290 0.651651 +v -0.223198 -0.439290 0.651651 +v 0.227852 -0.662557 0.634561 +v -0.257744 -0.662557 0.634561 +v 0.238838 -0.793172 0.611856 +v -0.268730 -0.793172 0.611856 +v 0.210152 -0.879109 0.588785 +v -0.240044 -0.879109 0.588785 +v 0.128975 -0.907796 0.587808 +v -0.158867 -0.907796 0.587808 +v -0.014946 -0.919515 0.592935 +v -0.014946 0.061741 0.695041 +v -0.014946 0.229655 0.721353 +v 0.315010 0.504558 0.711466 +v -0.344902 0.504558 0.711466 +v 0.134590 0.153728 0.708414 +v -0.164482 0.153728 0.708414 +v 0.108711 0.234172 0.718058 +v -0.138603 0.234172 0.718058 +v 0.099434 -0.644002 0.686441 +v -0.129326 -0.644002 0.686441 +v 0.074531 -0.436971 0.698404 +v -0.104424 -0.436971 0.698404 +v -0.014946 -0.438802 0.703287 +v -0.014946 -0.312825 0.704264 +v 0.069282 -0.252156 0.737467 +v -0.099175 -0.252156 0.737467 +v 0.106392 -0.201009 0.747354 +v -0.136284 -0.201009 0.747354 +v 0.085396 -0.127645 0.738321 +v -0.115288 -0.127645 0.738321 +v 0.024727 -0.118245 0.738321 +v -0.054619 -0.118245 0.738321 +v -0.014946 -0.182183 0.779567 +v 0.032797 -0.137587 0.765245 +v -0.062689 -0.137587 0.765245 +v 0.073162 -0.144965 0.765245 +v -0.103054 -0.144965 0.765245 +v 0.079048 -0.198812 0.775675 +v -0.108940 -0.198812 0.775675 +v 0.055149 -0.236328 0.760687 +v -0.085042 -0.236328 0.760687 +v -0.014946 -0.253987 0.760904 +v 0.231514 -0.295491 0.516519 +v -0.261406 -0.295491 0.516519 +v 0.149727 -0.214192 0.661905 +v -0.179619 -0.214192 0.661905 +v 0.165230 -0.297689 0.652017 +v -0.195122 -0.297689 0.652017 +v 0.206612 -0.224813 0.521891 +v -0.236504 -0.224813 0.521891 +v -0.014946 -0.852864 0.637125 +v 0.033760 -0.842244 0.640299 +v -0.063652 -0.842244 0.640299 +v 0.075630 -0.796712 0.657999 +v -0.105522 -0.796712 0.657999 +v 0.068916 -0.734334 0.672891 +v -0.098808 -0.734334 0.672891 +v -0.014946 -0.762776 0.619058 +v 0.062447 -0.751424 0.621093 +v -0.092339 -0.751424 0.621093 +v 0.069255 -0.789062 0.614999 +v -0.099147 -0.789062 0.614999 +v 0.036079 -0.818440 0.600463 +v -0.065971 -0.818440 0.600463 +v -0.014946 -0.828694 0.599039 +v 0.157661 0.241008 0.730020 +v -0.187553 0.241008 0.730020 +v 0.174385 0.178386 0.725382 +v -0.204277 0.178386 0.725382 +v 0.322945 0.448039 0.714151 +v -0.352837 0.448039 0.714151 +v 0.256538 0.440104 0.725626 +v -0.286430 0.440104 0.725626 +v 0.413765 0.420085 0.709513 +v -0.443657 0.420085 0.709513 +v 0.534004 0.371013 0.653849 +v -0.563896 0.371013 0.653849 +v 0.569649 0.305583 0.637247 +v -0.599541 0.305583 0.637247 +v 0.553291 0.215861 0.636270 +v -0.583183 0.215861 0.636270 +v 0.461861 0.126140 0.665689 +v -0.491753 0.126140 0.665689 +v 0.354073 0.090861 0.693277 +v -0.383965 0.090861 0.693277 +v 0.224434 0.129191 0.724161 +v -0.254326 0.129191 0.724161 +v 0.163399 0.318156 0.732462 +v -0.193291 0.318156 0.732462 +v 0.196846 0.393962 0.732584 +v -0.226738 0.393962 0.732584 +v 0.220406 0.376628 0.715006 +v -0.250298 0.376628 0.715006 +v 0.185249 0.316081 0.713053 +v -0.215141 0.316081 0.713053 +v 0.238960 0.146159 0.709146 +v -0.268852 0.146159 0.709146 +v 0.354195 0.114909 0.683756 +v -0.384087 0.114909 0.683756 +v 0.445991 0.145183 0.658365 +v -0.475884 0.145183 0.658365 +v 0.522163 0.228190 0.631998 +v -0.552055 0.228190 0.631998 +v 0.535835 0.299479 0.629068 +v -0.565727 0.299479 0.629068 +v 0.504585 0.356120 0.643717 +v -0.534477 0.356120 0.643717 +v 0.403999 0.405925 0.697428 +v -0.433891 0.405925 0.697428 +v 0.267281 0.414714 0.718912 +v -0.297173 0.414714 0.718912 +v 0.323921 0.423503 0.708170 +v -0.353813 0.423503 0.708170 +v 0.192085 0.193034 0.707193 +v -0.221977 0.193034 0.707193 +v 0.181343 0.248698 0.707193 +v -0.211235 0.248698 0.707193 +v 0.110575 0.509427 0.569107 +v -0.140467 0.509427 0.569107 +v 0.190783 0.658203 0.596842 +v -0.220675 0.658203 0.596842 +v 0.312745 0.685547 0.578396 +v -0.342637 0.685547 0.578396 +v 0.443179 0.573620 0.513795 +v -0.473071 0.573620 0.513795 +v 0.653145 0.483684 0.445230 +v -0.683037 0.483684 0.445230 +v 0.765449 0.405559 0.405924 +v -0.795342 0.405559 0.405924 +v 0.754829 0.198161 0.320108 +v -0.784721 0.198161 0.320108 +v 0.604561 0.019816 0.343790 +v -0.634453 0.019816 0.343790 +v 0.401721 -0.090599 0.405461 +v -0.431613 -0.090599 0.405461 +v -0.014946 0.876384 0.220133 +v -0.014946 0.970378 -0.129721 +v -0.014946 -0.154866 -0.662436 +v -0.014946 -0.416341 0.085611 +v -0.014946 -0.928060 0.412760 +v -0.014946 -0.765950 0.316568 +v -0.014946 -0.559163 0.281900 +v -0.014946 -0.455647 0.226724 +v 0.799751 0.246257 0.070352 +v -0.829643 0.246257 0.070352 +v 0.821382 0.321120 -0.093627 +v -0.851274 0.321120 -0.093627 +v 0.747867 0.303073 -0.462533 +v -0.777759 0.303073 -0.462533 +v 0.393745 0.462321 -0.709189 +v -0.423637 0.462321 -0.709189 +v 0.685366 -0.012317 0.029029 +v -0.715259 -0.012317 0.029029 +v 0.601148 -0.089349 -0.211752 +v -0.631040 -0.089349 -0.211752 +v 0.634834 0.025310 -0.444296 +v -0.664726 0.025310 -0.444296 +v 0.310575 0.097331 -0.704753 +v -0.340467 0.097331 -0.704753 +v 0.221748 -0.360921 0.365030 +v -0.251640 -0.360921 0.365030 +v 0.146919 -0.406575 0.235514 +v -0.176811 -0.406575 0.235514 +v 0.264595 -0.715657 0.359293 +v -0.294487 -0.715657 0.359293 +v 0.235054 -0.515462 0.364054 +v -0.264946 -0.515462 0.364054 +v 0.271078 -0.866970 0.386555 +v -0.300970 -0.866970 0.386555 +v 0.127388 -0.733602 0.330118 +v -0.157280 -0.733602 0.330118 +v 0.117012 -0.529988 0.305704 +v -0.146904 -0.529988 0.305704 +v 0.147774 -0.904500 0.397867 +v -0.177666 -0.904500 0.397867 +v 0.220887 -0.264583 0.361034 +v -0.250779 -0.264583 0.361034 +v 0.224230 -0.195027 0.430256 +v -0.254122 -0.195027 0.430256 +v 0.238165 -0.151475 0.458025 +v -0.268057 -0.151475 0.458025 +v 0.197684 -0.349114 0.112050 +v -0.227576 -0.349114 0.112050 +v 0.258247 -0.272908 -0.294882 +v -0.288139 -0.272908 -0.294882 +v 0.295926 -0.111897 -0.579265 +v -0.325818 -0.111897 -0.579265 +v 0.405342 0.825114 -0.451376 +v -0.435234 0.825114 -0.451376 +v 0.404976 0.916545 -0.133017 +v -0.434868 0.916545 -0.133017 +v 0.405586 0.828654 0.163004 +v -0.435478 0.828654 0.163004 +v 0.413887 0.581706 0.374308 +v -0.443779 0.581706 0.374308 +v 0.728462 0.429606 0.245279 +v -0.758354 0.429606 0.245279 +v 0.615669 0.507731 0.258951 +v -0.645561 0.507731 0.258951 +v 0.620064 0.699748 0.037760 +v -0.649956 0.699748 0.037760 +v 0.762764 0.556071 0.046793 +v -0.792656 0.556071 0.046793 +v 0.765205 0.602458 -0.182699 +v -0.795097 0.602458 -0.182699 +v 0.621773 0.760783 -0.213827 +v -0.651665 0.760783 -0.213827 +v 0.619331 0.670573 -0.457846 +v -0.649223 0.670573 -0.457846 +v 0.743301 0.544271 -0.387533 +v -0.773193 0.544271 -0.387533 +v 0.588203 0.359294 -0.602011 +v -0.618095 0.359294 -0.602011 +v 0.467059 0.039714 -0.566570 +v -0.496951 0.039714 -0.566570 +v 0.809820 0.367839 -0.249096 +v -0.839712 0.367839 -0.249096 +v 0.390809 -0.161458 0.115019 +v -0.420701 -0.161458 0.115019 +v 0.423897 -0.153890 -0.251547 +v -0.453789 -0.153890 -0.251547 +v 0.883003 0.415690 -0.302572 +v -0.912895 0.415690 -0.302572 +v 0.778389 -0.100911 -0.225302 +v -0.808281 -0.100911 -0.225302 +v 1.020943 -0.057698 -0.376913 +v -1.050835 -0.057698 -0.376913 +v 1.239937 0.091105 -0.470297 +v -1.269829 0.091105 -0.470297 +v 1.305489 0.324260 -0.475180 +v -1.335381 0.324260 -0.475180 +v 1.203560 0.487956 -0.464071 +v -1.233452 0.487956 -0.464071 +v 1.017036 0.479533 -0.377646 +v -1.046928 0.479533 -0.377646 +v 1.012276 0.429362 -0.348105 +v -1.042168 0.429362 -0.348105 +v 1.164864 0.435222 -0.433310 +v -1.194756 0.435222 -0.433310 +v 1.240425 0.300456 -0.455404 +v -1.270317 0.300456 -0.455404 +v 1.185860 0.108806 -0.445395 +v -1.215752 0.108806 -0.445395 +v 1.015572 -0.010823 -0.349814 +v -1.045464 -0.010823 -0.349814 +v 0.824654 -0.044393 -0.212362 +v -0.854546 -0.044393 -0.212362 +v 0.908760 0.376628 -0.280600 +v -0.938652 0.376628 -0.280600 +v 0.931221 0.327067 -0.336996 +v -0.961113 0.327067 -0.336996 +v 0.872017 -0.003743 -0.278891 +v -0.901909 -0.003743 -0.278891 +v 1.023018 0.024333 -0.400107 +v -1.052910 0.024333 -0.400107 +v 1.165108 0.119426 -0.479330 +v -1.195000 0.119426 -0.479330 +v 1.212105 0.267863 -0.488852 +v -1.241997 0.267863 -0.488852 +v 1.150093 0.371135 -0.472372 +v -1.179985 0.371135 -0.472372 +v 1.018257 0.367717 -0.402426 +v -1.048149 0.367717 -0.402426 +v 0.836372 0.307780 -0.259848 +v -0.866264 0.307780 -0.259848 +v 0.813911 0.193767 -0.314169 +v -0.843803 0.193767 -0.314169 +v 0.757515 0.116862 -0.314047 +v -0.787407 0.116862 -0.314047 +v 0.796686 0.091363 -0.325250 +v -0.826578 0.091363 -0.325250 +v 0.808662 0.042766 -0.313437 +v -0.838554 0.042766 -0.313437 +v 0.798775 0.006511 -0.303305 +v -0.828667 0.006511 -0.303305 +v 0.724230 0.052246 -0.122071 +v -0.754122 0.052246 -0.122071 +v 0.712580 -0.007265 -0.212012 +v -0.742472 -0.007265 -0.212012 +v 0.723361 0.068594 -0.235762 +v -0.753253 0.068594 -0.235762 +v 0.788643 0.221721 -0.242514 +v -0.818535 0.221721 -0.242514 +v 0.870552 0.266154 -0.312826 +v -0.900444 0.266154 -0.312826 +v 0.885689 0.246867 -0.363852 +v -0.915581 0.246867 -0.363852 +v 0.822077 0.012587 -0.343262 +v -0.851969 0.012587 -0.343262 +v 0.838081 0.044719 -0.358969 +v -0.867973 0.044719 -0.358969 +v 0.815742 0.098063 -0.359213 +v -0.845635 0.098063 -0.359213 +v 0.779759 0.126736 -0.353896 +v -0.809651 0.126736 -0.353896 +v 0.830513 0.183146 -0.359335 +v -0.860405 0.183146 -0.359335 +v 1.034167 0.340902 -0.448568 +v -1.064059 0.340902 -0.448568 +v 1.149890 0.343832 -0.504233 +v -1.179782 0.343832 -0.504233 +v 1.207466 0.254191 -0.515707 +v -1.237358 0.254191 -0.515707 +v 1.160957 0.126750 -0.504110 +v -1.190849 0.126750 -0.504110 +v 1.024849 0.043498 -0.441733 +v -1.054741 0.043498 -0.441733 +v 0.884468 0.015544 -0.334799 +v -0.914360 0.015544 -0.334799 +v 0.947823 0.302165 -0.389609 +v -0.977715 0.302165 -0.389609 +v 0.875557 0.134440 -0.373617 +v -0.905449 0.134440 -0.373617 +v 0.909248 0.080974 -0.374960 +v -0.939140 0.080974 -0.374960 +v 0.985054 0.136516 -0.412924 +v -1.014946 0.136516 -0.412924 +v 0.940742 0.193889 -0.393515 +v -0.970635 0.193889 -0.393515 +v 0.999580 0.252482 -0.415732 +v -1.029472 0.252482 -0.415732 +v 1.052803 0.197917 -0.436606 +v -1.082695 0.197917 -0.436606 +v 1.108535 0.243707 -0.454808 +v -1.138427 0.243707 -0.454808 +v 1.072131 0.294882 -0.445273 +v -1.102023 0.294882 -0.445273 +v 1.017891 0.395915 -0.502524 +v -1.047783 0.395915 -0.502524 +v 1.224881 0.420817 -0.560426 +v -1.254774 0.420817 -0.560426 +v 1.313324 0.307726 -0.540383 +v -1.343216 0.307726 -0.540383 +v 1.260038 0.134318 -0.554688 +v -1.289930 0.134318 -0.554688 +v 1.024971 0.008708 -0.500570 +v -1.054863 0.008708 -0.500570 +v 0.793037 -0.028768 -0.384482 +v -0.822929 -0.028768 -0.384482 +v 0.849434 0.338908 -0.420736 +v -0.879326 0.338908 -0.420736 +vn 0.702628 -0.228828 0.673727 +vn 0.744530 -0.000946 0.667562 +vn 0.821741 -0.001953 0.569811 +vn 0.776666 -0.263192 0.572283 +vn 0.628681 -0.515580 0.582141 +vn 0.573046 -0.435255 0.694357 +vn 0.618030 -0.502579 0.604480 +vn 0.759575 -0.264351 0.594226 +vn 0.806085 -0.001007 0.591784 +vn -0.702628 -0.228828 0.673727 +vn -0.759575 -0.264351 0.594226 +vn -0.618030 -0.502579 0.604480 +vn -0.573046 -0.435255 0.694357 +vn -0.628681 -0.515580 0.582141 +vn -0.776666 -0.263192 0.572283 +vn -0.821741 -0.001953 0.569811 +vn -0.744530 -0.000946 0.667562 +vn -0.806085 -0.001007 0.591784 +vn 0.813959 -0.298746 0.498154 +vn 0.865261 -0.001373 0.501297 +vn 0.656545 -0.569659 0.494369 +vn 0.678762 -0.572985 0.459304 +vn 0.831935 -0.299051 0.467330 +vn 0.881466 -0.000488 0.472243 +vn -0.813959 -0.298746 0.498154 +vn -0.831935 -0.299051 0.467330 +vn -0.678762 -0.572985 0.459304 +vn -0.656545 -0.569659 0.494369 +vn -0.865261 -0.001373 0.501297 +vn -0.881466 -0.000488 0.472243 +vn 0.406262 -0.770928 0.490493 +vn 0.395215 -0.676229 0.621662 +vn 0.112339 -0.755150 0.645802 +vn 0.086734 -0.861873 0.499588 +vn 0.097751 -0.888424 0.448469 +vn 0.425947 -0.786645 0.446913 +vn -0.406262 -0.770928 0.490493 +vn -0.425947 -0.786645 0.446913 +vn -0.097751 -0.888424 0.448469 +vn -0.086734 -0.861873 0.499588 +vn -0.112339 -0.755150 0.645802 +vn -0.395215 -0.676229 0.621662 +vn 0.375835 -0.578753 0.723685 +vn 0.398541 -0.700583 0.591876 +vn 0.116977 -0.783868 0.609760 +vn 0.136601 -0.641163 0.755120 +vn -0.375835 -0.578753 0.723685 +vn -0.136601 -0.641163 0.755120 +vn -0.116977 -0.783868 0.609760 +vn -0.398541 -0.700583 0.591876 +vn -0.126438 -0.613758 0.779260 +vn -0.199194 -0.751244 0.629231 +vn -0.493759 -0.578539 0.649190 +vn -0.373547 -0.470656 0.799310 +vn -0.460891 -0.548357 0.697745 +vn -0.190802 -0.716514 0.670949 +vn 0.126438 -0.613758 0.779260 +vn 0.190802 -0.716514 0.670949 +vn 0.460891 -0.548357 0.697745 +vn 0.373547 -0.470656 0.799310 +vn 0.493759 -0.578539 0.649190 +vn 0.199194 -0.751244 0.629231 +vn -0.250557 -0.815119 0.522233 +vn -0.544816 -0.626118 0.557756 +vn -0.563097 -0.651204 0.508713 +vn -0.256233 -0.844874 0.469558 +vn 0.250557 -0.815119 0.522233 +vn 0.256233 -0.844874 0.469558 +vn 0.563097 -0.651204 0.508713 +vn 0.544816 -0.626118 0.557756 +vn -0.740043 -0.332652 0.584490 +vn -0.637928 -0.287179 0.714530 +vn -0.693930 -0.001129 0.720023 +vn -0.802972 -0.001556 0.595965 +vn -0.833247 -0.000397 0.552843 +vn -0.767418 -0.346934 0.539140 +vn 0.740043 -0.332652 0.584490 +vn 0.767418 -0.346934 0.539140 +vn 0.833247 -0.000397 0.552843 +vn 0.802972 -0.001556 0.595965 +vn 0.693930 -0.001129 0.720023 +vn 0.637928 -0.287179 0.714530 +vn -0.537706 -0.242714 0.807428 +vn -0.695853 -0.304788 0.650258 +vn -0.761956 -0.002441 0.647603 +vn -0.588061 -0.000977 0.808802 +vn 0.537706 -0.242714 0.807428 +vn 0.588061 -0.000977 0.808802 +vn 0.761956 -0.002441 0.647603 +vn 0.695853 -0.304788 0.650258 +vn -0.546037 0.239967 0.802606 +vn -0.709311 0.295450 0.639973 +vn -0.520798 0.579211 0.627094 +vn -0.391308 0.476699 0.787133 +vn -0.464522 0.542283 0.700064 +vn -0.639332 0.281961 0.715323 +vn 0.546037 0.239967 0.802606 +vn 0.639332 0.281961 0.715323 +vn 0.464522 0.542283 0.700064 +vn 0.391308 0.476699 0.787133 +vn 0.520798 0.579211 0.627094 +vn 0.709311 0.295450 0.639973 +vn -0.736900 0.323862 0.593341 +vn -0.538316 0.609912 0.581530 +vn -0.549242 0.636402 0.541520 +vn -0.761406 0.340892 0.551378 +vn 0.736900 0.323862 0.593341 +vn 0.761406 0.340892 0.551378 +vn 0.549242 0.636402 0.541520 +vn 0.538316 0.609912 0.581530 +vn -0.240150 0.794610 0.557573 +vn -0.191931 0.713370 0.673940 +vn 0.113468 0.752190 0.649068 +vn 0.093722 0.838130 0.537309 +vn 0.105930 0.859462 0.500046 +vn -0.239448 0.820978 0.518296 +vn 0.240150 0.794610 0.557573 +vn 0.239448 0.820978 0.518296 +vn -0.105930 0.859462 0.500046 +vn -0.093722 0.838130 0.537309 +vn -0.113468 0.752190 0.649068 +vn 0.191931 0.713370 0.673940 +vn -0.141057 0.634602 0.759819 +vn -0.220679 0.773247 0.594409 +vn 0.109226 0.813990 0.570452 +vn 0.132633 0.666555 0.733512 +vn 0.141057 0.634602 0.759819 +vn -0.132633 0.666555 0.733512 +vn -0.109226 0.813990 0.570452 +vn 0.220679 0.773247 0.594409 +vn 0.382397 0.598102 0.704276 +vn 0.406446 0.723075 0.558489 +vn 0.646077 0.517411 0.561083 +vn 0.584490 0.440382 0.681448 +vn 0.621296 0.496261 0.606342 +vn 0.397504 0.672292 0.624470 +vn -0.382397 0.598102 0.704276 +vn -0.397504 0.672292 0.624470 +vn -0.621296 0.496261 0.606342 +vn -0.584490 0.440382 0.681448 +vn -0.646077 0.517411 0.561083 +vn -0.406446 0.723075 0.558489 +vn 0.407208 0.748802 0.522904 +vn 0.655599 0.552446 0.514725 +vn 0.673513 0.557360 0.485488 +vn 0.423811 0.761650 0.490127 +vn -0.407208 0.748802 0.522904 +vn -0.423811 0.761650 0.490127 +vn -0.673513 0.557360 0.485488 +vn -0.655599 0.552446 0.514725 +vn 0.812494 0.290292 0.505478 +vn 0.760796 0.259560 0.594775 +vn 0.828669 0.293191 0.476760 +vn -0.812494 0.290292 0.505478 +vn -0.828669 0.293191 0.476760 +vn -0.760796 0.259560 0.594775 +vn 0.708518 0.226173 0.668447 +vn 0.785943 0.255776 0.562883 +vn -0.708518 0.226173 0.668447 +vn -0.785943 0.255776 0.562883 +vn 0.824183 0.271401 0.496994 +vn 0.863857 -0.002106 0.503677 +vn 0.675893 0.563616 0.474837 +vn 0.548784 0.361492 0.753746 +vn 0.645161 0.176244 0.743400 +vn 0.660970 -0.001709 0.750389 +vn -0.824183 0.271401 0.496994 +vn -0.645161 0.176244 0.743400 +vn -0.548784 0.361492 0.753746 +vn -0.675893 0.563616 0.474837 +vn -0.863857 -0.002106 0.503677 +vn -0.660970 -0.001709 0.750389 +vn 0.414014 0.792566 0.447645 +vn 0.078982 0.898923 0.430860 +vn 0.151891 0.613575 0.774865 +vn 0.380291 0.541185 0.749962 +vn -0.414014 0.792566 0.447645 +vn -0.380291 0.541185 0.749962 +vn -0.151891 0.613575 0.774865 +vn -0.078982 0.898923 0.430860 +vn -0.279702 0.845119 0.455519 +vn -0.604297 0.635365 0.480697 +vn -0.356517 0.427961 0.830470 +vn -0.123997 0.589801 0.797937 +vn 0.279702 0.845119 0.455519 +vn 0.123997 0.589801 0.797937 +vn 0.356517 0.427961 0.830470 +vn 0.604297 0.635365 0.480697 +vn -0.813898 0.334635 0.474929 +vn -0.887906 -0.002686 0.459944 +vn -0.581988 -0.002594 0.813166 +vn -0.531388 0.225166 0.816645 +vn 0.813898 0.334635 0.474929 +vn 0.531388 0.225166 0.816645 +vn 0.581988 -0.002594 0.813166 +vn 0.887906 -0.002686 0.459944 +vn -0.807276 -0.349498 0.475509 +vn -0.589953 -0.648976 0.480361 +vn -0.354289 -0.452528 0.818323 +vn -0.532456 -0.242286 0.810999 +vn 0.807276 -0.349498 0.475509 +vn 0.532456 -0.242286 0.810999 +vn 0.354289 -0.452528 0.818323 +vn 0.589953 -0.648976 0.480361 +vn -0.273812 -0.846767 0.456038 +vn 0.080294 -0.897336 0.433943 +vn 0.146611 -0.641591 0.752861 +vn -0.129795 -0.613849 0.778649 +vn 0.273812 -0.846767 0.456038 +vn 0.129795 -0.613849 0.778649 +vn -0.146611 -0.641591 0.752861 +vn -0.080294 -0.897336 0.433943 +vn 0.410382 -0.791955 0.452071 +vn 0.663991 -0.573199 0.480087 +vn 0.546373 -0.385266 0.743645 +vn 0.379864 -0.565935 0.731681 +vn -0.410382 -0.791955 0.452071 +vn -0.379864 -0.565935 0.731681 +vn -0.546373 -0.385266 0.743645 +vn -0.663991 -0.573199 0.480087 +vn 0.818628 -0.283395 0.499466 +vn 0.646107 -0.190893 0.738975 +vn -0.818628 -0.283395 0.499466 +vn -0.646107 -0.190893 0.738975 +vn 0.414655 -0.075259 0.906827 +vn 0.399304 -0.000946 0.916807 +vn 0.190924 -0.002625 0.981567 +vn 0.353343 -0.126255 0.926908 +vn -0.414655 -0.075259 0.906827 +vn -0.399304 -0.000946 0.916807 +vn -0.353343 -0.126255 0.926908 +vn -0.190924 -0.002625 0.981567 +vn 0.302194 -0.207068 0.930448 +vn 0.201788 -0.197821 0.959227 +vn -0.302194 -0.207068 0.930448 +vn -0.201788 -0.197821 0.959227 +vn 0.080477 -0.215522 0.973144 +vn 0.008667 -0.124638 0.992157 +vn -0.080477 -0.215522 0.973144 +vn -0.008667 -0.124638 0.992157 +vn -0.086825 -0.063814 0.994171 +vn -0.067965 -0.000488 0.997681 +vn 0.086825 -0.063814 0.994171 +vn 0.067965 -0.000488 0.997681 +vn -0.086001 0.058077 0.994598 +vn 0.009919 0.117069 0.993042 +vn 0.086001 0.058077 0.994598 +vn -0.009919 0.117069 0.993042 +vn 0.082675 0.203406 0.975585 +vn 0.202460 0.185369 0.961577 +vn -0.082675 0.203406 0.975585 +vn -0.202460 0.185369 0.961577 +vn 0.301309 0.195471 0.933256 +vn 0.352641 0.118686 0.928190 +vn -0.301309 0.195471 0.933256 +vn -0.352641 0.118686 0.928190 +vn 0.414106 0.069247 0.907559 +vn -0.414106 0.069247 0.907559 +vn 0.101260 -0.898770 0.426527 +vn 0.097354 -0.985443 0.139348 +vn 0.148595 -0.983032 0.107456 +vn 0.163762 -0.895932 0.412854 +vn 0.155339 -0.768944 0.620106 +vn 0.091342 -0.788354 0.608386 +vn 0.000000 -0.793664 0.608325 +vn 0.000000 -0.899777 0.436323 +vn 0.000000 -0.987457 0.157811 +vn -0.101260 -0.898770 0.426527 +vn -0.091342 -0.788354 0.608386 +vn -0.155339 -0.768944 0.620106 +vn -0.163762 -0.895932 0.412854 +vn -0.148595 -0.983032 0.107456 +vn -0.097354 -0.985443 0.139348 +vn 0.269112 -0.856258 0.440840 +vn 0.261757 -0.960234 0.096774 +vn 0.596606 -0.794824 0.110782 +vn 0.472793 -0.715720 0.513962 +vn 0.379040 -0.551775 0.742851 +vn 0.249580 -0.701102 0.667928 +vn -0.269112 -0.856258 0.440840 +vn -0.249580 -0.701102 0.667928 +vn -0.379040 -0.551775 0.742851 +vn -0.472793 -0.715720 0.513962 +vn -0.596606 -0.794824 0.110782 +vn -0.261757 -0.960234 0.096774 +vn 0.687613 -0.438643 0.578570 +vn 0.911008 -0.392804 0.125523 +vn 0.988800 -0.070467 0.131535 +vn 0.787652 -0.196081 0.584063 +vn 0.532762 -0.222114 0.816553 +vn 0.473128 -0.367229 0.800775 +vn -0.687613 -0.438643 0.578570 +vn -0.473128 -0.367229 0.800775 +vn -0.532762 -0.222114 0.816553 +vn -0.787652 -0.196081 0.584063 +vn -0.988800 -0.070467 0.131535 +vn -0.911008 -0.392804 0.125523 +vn 0.819910 -0.045137 0.570666 +vn 0.990966 0.060823 0.119358 +vn 0.985717 0.115085 0.122745 +vn 0.822443 0.042573 0.567217 +vn 0.582995 -0.012940 0.812342 +vn 0.569811 -0.100864 0.815546 +vn -0.819910 -0.045137 0.570666 +vn -0.569811 -0.100864 0.815546 +vn -0.582995 -0.012940 0.812342 +vn -0.822443 0.042573 0.567217 +vn -0.985717 0.115085 0.122745 +vn -0.990966 0.060823 0.119358 +vn 0.823603 0.097568 0.558672 +vn 0.981048 0.148167 0.124607 +vn 0.966369 0.215583 0.140049 +vn 0.829035 0.167577 0.533464 +vn 0.612690 0.085604 0.785668 +vn 0.590472 0.034791 0.806299 +vn -0.823603 0.097568 0.558672 +vn -0.590472 0.034791 0.806299 +vn -0.612690 0.085604 0.785668 +vn -0.829035 0.167577 0.533464 +vn -0.966369 0.215583 0.140049 +vn -0.981048 0.148167 0.124607 +vn 0.376049 -0.776391 0.505722 +vn 0.639485 -0.578784 0.505997 +vn 0.631184 -0.731529 0.257729 +vn 0.335704 -0.914762 0.224708 +vn 0.359386 -0.910428 0.204810 +vn 0.369854 -0.755303 0.540971 +vn 0.383312 -0.553758 0.739158 +vn 0.405866 -0.478866 0.778375 +vn 0.222449 -0.201544 0.953856 +vn -0.376049 -0.776391 0.505722 +vn -0.405866 -0.478866 0.778375 +vn -0.383312 -0.553758 0.739158 +vn -0.369854 -0.755303 0.540971 +vn -0.359386 -0.910428 0.204810 +vn -0.335704 -0.914762 0.224708 +vn -0.631184 -0.731529 0.257729 +vn -0.639485 -0.578784 0.505997 +vn -0.222449 -0.201544 0.953856 +vn 0.443587 -0.688955 0.573168 +vn 0.474654 -0.857418 0.198798 +vn 0.609302 -0.770562 0.186926 +vn 0.570544 -0.589099 0.572192 +vn 0.494156 -0.431806 0.754540 +vn 0.414258 -0.524247 0.743980 +vn -0.443587 -0.688955 0.573168 +vn -0.414258 -0.524247 0.743980 +vn -0.494156 -0.431806 0.754540 +vn -0.570544 -0.589099 0.572192 +vn -0.609302 -0.770562 0.186926 +vn -0.474654 -0.857418 0.198798 +vn 0.683340 -0.479904 0.550157 +vn 0.748680 -0.646260 0.147526 +vn 0.895779 -0.427473 0.121677 +vn 0.732322 -0.391614 0.557024 +vn 0.584826 -0.320688 0.745048 +vn 0.569659 -0.354442 0.741508 +vn -0.683340 -0.479904 0.550157 +vn -0.569659 -0.354442 0.741508 +vn -0.584826 -0.320688 0.745048 +vn -0.732322 -0.391614 0.557024 +vn -0.895779 -0.427473 0.121677 +vn -0.748680 -0.646260 0.147526 +vn 0.737266 -0.304788 0.602893 +vn 0.975402 -0.151616 0.159856 +vn 0.934965 0.283181 0.213569 +vn 0.746300 -0.055361 0.663259 +vn 0.487716 -0.293344 0.822199 +vn 0.534257 -0.312326 0.785485 +vn -0.737266 -0.304788 0.602893 +vn -0.534257 -0.312326 0.785485 +vn -0.487716 -0.293344 0.822199 +vn -0.746300 -0.055361 0.663259 +vn -0.934965 0.283181 0.213569 +vn -0.975402 -0.151616 0.159856 +vn 0.639821 0.326090 0.695883 +vn 0.659658 0.715781 0.229041 +vn 0.472213 0.865291 0.168004 +vn 0.527757 0.548540 0.648488 +vn 0.353099 -0.046693 0.934416 +vn 0.438765 -0.154241 0.885250 +vn -0.639821 0.326090 0.695883 +vn -0.438765 -0.154241 0.885250 +vn -0.353099 -0.046693 0.934416 +vn -0.527757 0.548540 0.648488 +vn -0.472213 0.865291 0.168004 +vn -0.659658 0.715781 0.229041 +vn 0.518601 0.602802 0.606311 +vn 0.512772 0.846828 0.141179 +vn 0.588946 0.793542 0.152837 +vn 0.551195 0.563891 0.614948 +vn 0.305002 0.028565 0.951903 +vn 0.308786 0.016785 0.950957 +vn -0.518601 0.602802 0.606311 +vn -0.308786 0.016785 0.950957 +vn -0.305002 0.028565 0.951903 +vn -0.551195 0.563891 0.614948 +vn -0.588946 0.793542 0.152837 +vn -0.512772 0.846828 0.141179 +vn 0.535295 0.554613 0.637013 +vn 0.588519 0.790490 0.169439 +vn 0.314859 0.932188 0.178411 +vn 0.331889 0.642659 0.690512 +vn 0.258614 0.102695 0.960479 +vn 0.308603 0.051515 0.949767 +vn -0.535295 0.554613 0.637013 +vn -0.308603 0.051515 0.949767 +vn -0.258614 0.102695 0.960479 +vn -0.331889 0.642659 0.690512 +vn -0.314859 0.932188 0.178411 +vn -0.588519 0.790490 0.169439 +vn -0.072085 0.670247 0.738609 +vn -0.204352 0.961180 0.185247 +vn -0.669118 0.726371 0.156896 +vn -0.467086 0.521805 0.713767 +vn -0.048372 0.074313 0.996033 +vn 0.107334 0.122379 0.986633 +vn 0.072085 0.670247 0.738609 +vn -0.107334 0.122379 0.986633 +vn 0.048372 0.074313 0.996033 +vn 0.467086 0.521805 0.713767 +vn 0.669118 0.726371 0.156896 +vn 0.204352 0.961180 0.185247 +vn -0.661824 0.379559 0.646443 +vn -0.862850 0.493942 0.107089 +vn -0.842006 0.529923 0.100711 +vn -0.677358 0.403363 0.615162 +vn -0.127689 0.001282 0.991791 +vn -0.103122 0.022492 0.994385 +vn 0.661824 0.379559 0.646443 +vn 0.103122 0.022492 0.994385 +vn 0.127689 0.001282 0.991791 +vn 0.677358 0.403363 0.615162 +vn 0.842006 0.529923 0.100711 +vn 0.862850 0.493942 0.107089 +vn -0.508835 0.551195 0.661214 +vn -0.607227 0.777795 0.162114 +vn 0.000000 0.975646 0.219306 +vn 0.000000 0.666799 0.745232 +vn 0.000000 -0.060488 0.998138 +vn -0.110080 0.026826 0.993530 +vn 0.508835 0.551195 0.661214 +vn 0.110080 0.026826 0.993530 +vn 0.607227 0.777795 0.162114 +vn 0.361126 -0.297250 0.883847 +vn 0.339518 -0.307047 0.889035 +vn 0.302316 -0.228248 0.925443 +vn 0.322275 -0.232215 0.917692 +vn 0.286660 -0.247475 0.925504 +vn 0.304483 -0.303201 0.902951 +vn -0.361126 -0.297250 0.883847 +vn -0.304483 -0.303201 0.902951 +vn -0.286660 -0.247475 0.925504 +vn -0.322275 -0.232215 0.917692 +vn -0.302316 -0.228248 0.925443 +vn -0.339518 -0.307047 0.889035 +vn 0.213721 -0.326029 0.920865 +vn 0.209662 -0.271767 0.939238 +vn 0.122135 -0.268166 0.955565 +vn 0.124485 -0.349864 0.928465 +vn -0.213721 -0.326029 0.920865 +vn -0.124485 -0.349864 0.928465 +vn -0.122135 -0.268166 0.955565 +vn -0.209662 -0.271767 0.939238 +vn 0.064577 -0.372417 0.925779 +vn 0.108188 -0.213935 0.970824 +vn 0.180120 -0.183996 0.966277 +vn 0.055727 -0.407514 0.911466 +vn -0.064577 -0.372417 0.925779 +vn -0.055727 -0.407514 0.911466 +vn -0.180120 -0.183996 0.966277 +vn -0.108188 -0.213935 0.970824 +vn 0.053041 -0.461562 0.885495 +vn 0.192083 -0.271920 0.942930 +vn 0.152776 -0.334452 0.929929 +vn 0.071841 -0.471908 0.878689 +vn -0.053041 -0.461562 0.885495 +vn -0.071841 -0.471908 0.878689 +vn -0.152776 -0.334452 0.929929 +vn -0.192083 -0.271920 0.942930 +vn 0.160405 -0.412763 0.896573 +vn 0.175787 -0.264229 0.948271 +vn 0.276498 -0.159490 0.947661 +vn 0.259651 -0.305307 0.916166 +vn -0.160405 -0.412763 0.896573 +vn -0.259651 -0.305307 0.916166 +vn -0.276498 -0.159490 0.947661 +vn -0.175787 -0.264229 0.948271 +vn 0.370861 -0.236457 0.898068 +vn 0.378155 -0.146825 0.913999 +vn 0.442640 -0.200476 0.873989 +vn 0.447859 -0.234565 0.862758 +vn -0.370861 -0.236457 0.898068 +vn -0.447859 -0.234565 0.862758 +vn -0.442640 -0.200476 0.873989 +vn -0.378155 -0.146825 0.913999 +vn 0.452254 -0.264138 0.851863 +vn 0.459487 -0.281838 0.842250 +vn 0.438124 -0.367443 0.820338 +vn 0.417951 -0.328410 0.847011 +vn -0.452254 -0.264138 0.851863 +vn -0.417951 -0.328410 0.847011 +vn -0.438124 -0.367443 0.820338 +vn -0.459487 -0.281838 0.842250 +vn 0.377239 -0.383160 0.843104 +vn 0.365307 -0.419843 0.830805 +vn 0.275399 -0.364513 0.889523 +vn 0.348949 -0.318552 0.881314 +vn -0.377239 -0.383160 0.843104 +vn -0.348949 -0.318552 0.881314 +vn -0.275399 -0.364513 0.889523 +vn -0.365307 -0.419843 0.830805 +vn 0.338481 -0.136174 0.931059 +vn 0.204169 -0.239418 0.949187 +vn 0.094852 -0.116398 0.988647 +vn 0.177343 0.033418 0.983551 +vn -0.338481 -0.136174 0.931059 +vn -0.177343 0.033418 0.983551 +vn -0.094852 -0.116398 0.988647 +vn -0.204169 -0.239418 0.949187 +vn -0.055269 0.122837 0.990875 +vn -0.074313 -0.043031 0.996277 +vn -0.147954 -0.087100 0.985137 +vn -0.079257 0.017029 0.996704 +vn 0.000000 0.041017 0.999146 +vn -0.158422 0.075228 0.984497 +vn 0.055269 0.122837 0.990875 +vn 0.158422 0.075228 0.984497 +vn 0.079257 0.017029 0.996704 +vn 0.147954 -0.087100 0.985137 +vn 0.074313 -0.043031 0.996277 +vn 0.259468 -0.291025 0.920835 +vn 0.226875 -0.202857 0.952544 +vn 0.186041 -0.259163 0.947722 +vn 0.129154 -0.162084 0.978271 +vn -0.259468 -0.291025 0.920835 +vn -0.186041 -0.259163 0.947722 +vn -0.226875 -0.202857 0.952544 +vn -0.129154 -0.162084 0.978271 +vn 0.115818 -0.236366 0.964721 +vn 0.020539 -0.147801 0.988769 +vn 0.000000 -0.275155 0.961364 +vn 0.000000 -0.246376 0.969146 +vn 0.040773 -0.215949 0.975524 +vn -0.075320 -0.164678 0.983459 +vn -0.115818 -0.236366 0.964721 +vn -0.040773 -0.215949 0.975524 +vn -0.020539 -0.147801 0.988769 +vn 0.075320 -0.164678 0.983459 +vn -0.014710 -0.146702 0.989044 +vn 0.000000 -0.149754 0.988708 +vn -0.126865 -0.161229 0.978698 +vn 0.014710 -0.146702 0.989044 +vn 0.126865 -0.161229 0.978698 +vn 0.070284 -0.702017 0.708640 +vn 0.134465 -0.664174 0.735343 +vn 0.071474 -0.528581 0.845820 +vn 0.026521 -0.547014 0.836665 +vn 0.000000 -0.548997 0.835810 +vn 0.000000 -0.710440 0.703726 +vn -0.070284 -0.702017 0.708640 +vn -0.026521 -0.547014 0.836665 +vn -0.071474 -0.528581 0.845820 +vn -0.134465 -0.664174 0.735343 +vn 0.217627 -0.571978 0.790826 +vn 0.311380 -0.418317 0.853236 +vn 0.229713 -0.334361 0.913999 +vn 0.144993 -0.458571 0.876736 +vn -0.217627 -0.571978 0.790826 +vn -0.144993 -0.458571 0.876736 +vn -0.229713 -0.334361 0.913999 +vn -0.311380 -0.418317 0.853236 +vn 0.353099 -0.284188 0.891354 +vn 0.362377 -0.194220 0.911557 +vn 0.203925 -0.139592 0.968963 +vn 0.262490 -0.223548 0.938658 +vn -0.353099 -0.284188 0.891354 +vn -0.262490 -0.223548 0.938658 +vn -0.203925 -0.139592 0.968963 +vn -0.362377 -0.194220 0.911557 +vn 0.360149 -0.013428 0.932768 +vn 0.362774 0.017914 0.931700 +vn 0.170934 -0.008209 0.985229 +vn 0.175909 -0.038148 0.983642 +vn 0.187933 -0.050172 0.980895 +vn 0.368816 -0.043062 0.928495 +vn -0.360149 -0.013428 0.932768 +vn -0.368816 -0.043062 0.928495 +vn -0.187933 -0.050172 0.980895 +vn -0.175909 -0.038148 0.983642 +vn -0.170934 -0.008209 0.985229 +vn -0.362774 0.017914 0.931700 +vn 0.371868 -0.108249 0.921934 +vn 0.204077 -0.078494 0.975768 +vn -0.371868 -0.108249 0.921934 +vn -0.204077 -0.078494 0.975768 +vn 0.051637 -0.013306 0.998566 +vn 0.181982 -0.007080 0.983245 +vn 0.368725 -0.294595 0.881588 +vn 0.137120 -0.292978 0.946226 +vn 0.000000 -0.278146 0.960509 +vn 0.000000 -0.011170 0.999908 +vn 0.000000 -0.017365 0.999847 +vn 0.048891 -0.015168 0.998688 +vn -0.051637 -0.013306 0.998566 +vn -0.048891 -0.015168 0.998688 +vn -0.137120 -0.292978 0.946226 +vn -0.368725 -0.294595 0.881588 +vn -0.181982 -0.007080 0.983245 +vn 0.049776 -0.049593 0.997497 +vn 0.053468 -0.049196 0.997345 +vn 0.000000 -0.053133 0.998566 +vn 0.000000 -0.048097 0.998840 +vn -0.049776 -0.049593 0.997497 +vn -0.053468 -0.049196 0.997345 +vn 0.060335 -0.050630 0.996887 +vn 0.000000 -0.048982 0.998779 +vn 0.000000 -0.219092 0.975677 +vn 0.061586 -0.160375 0.985107 +vn -0.060335 -0.050630 0.996887 +vn -0.061586 -0.160375 0.985107 +vn 0.810083 -0.520646 0.269478 +vn 0.659139 -0.328501 0.676443 +vn 0.806879 -0.153996 0.570238 +vn 0.989288 -0.119633 0.083438 +vn 0.965361 -0.144719 0.217017 +vn 0.759514 -0.577013 0.300241 +vn 0.506821 -0.753075 0.419477 +vn 0.544420 -0.686453 0.482009 +vn -0.810083 -0.520646 0.269478 +vn -0.544420 -0.686453 0.482009 +vn -0.506821 -0.753075 0.419477 +vn -0.759514 -0.577013 0.300241 +vn -0.965361 -0.144719 0.217017 +vn -0.989288 -0.119633 0.083438 +vn -0.806879 -0.153996 0.570238 +vn -0.659139 -0.328501 0.676443 +vn 0.952116 0.305338 -0.015046 +vn 0.711783 0.053468 0.700308 +vn 0.188299 0.327921 0.925718 +vn 0.689993 0.722953 -0.034791 +vn 0.677145 0.730949 0.084475 +vn 0.940306 0.302744 0.155339 +vn -0.952116 0.305338 -0.015046 +vn -0.940306 0.302744 0.155339 +vn -0.677145 0.730949 0.084475 +vn -0.689993 0.722953 -0.034791 +vn -0.188299 0.327921 0.925718 +vn -0.711783 0.053468 0.700308 +vn 0.151280 0.975982 0.156652 +vn -0.139348 0.337718 0.930845 +vn 0.000000 0.307138 0.951628 +vn -0.381909 0.794244 0.472518 +vn -0.362163 0.904599 0.224769 +vn 0.169103 0.981475 0.089755 +vn -0.151280 0.975982 0.156652 +vn -0.169103 0.981475 0.089755 +vn 0.362163 0.904599 0.224769 +vn 0.381909 0.794244 0.472518 +vn 0.139348 0.337718 0.930845 +vn -0.562883 0.662496 0.494156 +vn 0.000000 0.564135 0.825678 +vn 0.000000 0.759239 0.650777 +vn 0.000000 0.951170 0.308573 +vn 0.000000 0.960356 0.278726 +vn -0.630390 0.724021 0.279916 +vn 0.562883 0.662496 0.494156 +vn 0.630390 0.724021 0.279916 +vn 0.301340 -0.732719 0.610126 +vn 0.000000 -0.752556 0.658498 +vn 0.319376 -0.804498 0.500748 +vn 0.000000 -0.850154 0.526505 +vn -0.301340 -0.732719 0.610126 +vn -0.319376 -0.804498 0.500748 +vn 0.230171 -0.645100 0.728568 +vn 0.000000 -0.657582 0.753349 +vn 0.346294 -0.669454 0.657155 +vn 0.207953 -0.566973 0.797021 +vn 0.134922 -0.503952 0.853114 +vn 0.000000 -0.476363 0.879208 +vn -0.230171 -0.645100 0.728568 +vn -0.134922 -0.503952 0.853114 +vn -0.207953 -0.566973 0.797021 +vn -0.346294 -0.669454 0.657155 +vn -0.430891 0.679769 0.593463 +vn 0.000000 0.728080 0.685476 +vn 0.000000 0.138005 0.990417 +vn -0.149205 0.407788 0.900784 +vn -0.142949 0.526994 0.837733 +vn -0.276009 0.759453 0.589068 +vn 0.430891 0.679769 0.593463 +vn 0.276009 0.759453 0.589068 +vn 0.142949 0.526994 0.837733 +vn 0.149205 0.407788 0.900784 +vn 0.147801 0.804193 0.575640 +vn 0.089755 0.494522 0.864498 +vn 0.316141 0.417035 0.852107 +vn 0.547441 0.603656 0.579516 +vn -0.147801 0.804193 0.575640 +vn -0.547441 0.603656 0.579516 +vn -0.316141 0.417035 0.852107 +vn -0.089755 0.494522 0.864498 +vn 0.738151 0.266640 0.619678 +vn 0.341075 0.213202 0.915525 +vn 0.308206 -0.132298 0.942045 +vn 0.732963 -0.157720 0.661702 +vn -0.738151 0.266640 0.619678 +vn -0.732963 -0.157720 0.661702 +vn -0.308206 -0.132298 0.942045 +vn -0.341075 0.213202 0.915525 +vn 0.541887 -0.547990 0.637165 +vn 0.226051 -0.456496 0.860500 +vn -0.541887 -0.547990 0.637165 +vn -0.226051 -0.456496 0.860500 +vn 0.062929 0.234931 0.969939 +vn 0.043458 -0.059755 0.997253 +vn -0.062929 0.234931 0.969939 +vn -0.043458 -0.059755 0.997253 +vn 0.057711 -0.344737 0.936918 +vn 0.000000 -0.300943 0.953612 +vn -0.057711 -0.344737 0.936918 +vn -0.217780 -0.045137 0.974944 +vn 0.000000 0.003052 0.999969 +vn -0.110630 -0.207984 0.971831 +vn 0.217780 -0.045137 0.974944 +vn 0.110630 -0.207984 0.971831 +vn 0.296396 -0.239326 0.924558 +vn 0.646657 -0.139744 0.749840 +vn 0.829463 0.004578 0.558489 +vn 0.728111 -0.196020 0.656789 +vn -0.296396 -0.239326 0.924558 +vn -0.728111 -0.196020 0.656789 +vn -0.829463 0.004578 0.558489 +vn -0.646657 -0.139744 0.749840 +vn 0.593005 -0.108005 0.797876 +vn 0.470168 -0.018891 0.882351 +vn 0.713187 0.139805 0.686880 +vn 0.784692 0.079257 0.614765 +vn -0.593005 -0.108005 0.797876 +vn -0.784692 0.079257 0.614765 +vn -0.713187 0.139805 0.686880 +vn -0.470168 -0.018891 0.882351 +vn 0.393689 0.037416 0.918455 +vn 0.653523 0.137974 0.744194 +vn -0.393689 0.037416 0.918455 +vn -0.653523 0.137974 0.744194 +vn 0.836787 0.247383 0.488388 +vn 0.940306 0.303110 0.154668 +vn 0.931883 0.327677 0.155492 +vn 0.857723 0.269082 0.438032 +vn -0.836787 0.247383 0.488388 +vn -0.857723 0.269082 0.438032 +vn -0.931883 0.327677 0.155492 +vn -0.940306 0.303110 0.154668 +vn 0.889706 0.228065 0.395398 +vn 0.942228 0.295877 0.156926 +vn 0.945036 0.280862 0.167302 +vn 0.915891 0.182318 0.357555 +vn -0.889706 0.228065 0.395398 +vn -0.915891 0.182318 0.357555 +vn -0.945036 0.280862 0.167302 +vn -0.942228 0.295877 0.156926 +vn 0.903287 -0.131199 0.408429 +vn 0.968047 -0.106754 0.226875 +vn -0.903287 -0.131199 0.408429 +vn -0.968047 -0.106754 0.226875 +vn 0.086398 -0.624805 0.775964 +vn -0.029145 -0.399731 0.916135 +vn 0.000000 -0.701529 0.712607 +vn 0.000000 -0.954924 0.296762 +vn 0.114475 -0.940580 0.319651 +vn -0.385876 -0.804651 0.451216 +vn -0.086398 -0.624805 0.775964 +vn -0.114475 -0.940580 0.319651 +vn 0.029145 -0.399731 0.916135 +vn 0.385876 -0.804651 0.451216 +vn -0.235115 -0.263222 0.935606 +vn -0.268319 -0.152867 0.951109 +vn -0.882229 -0.229377 0.411115 +vn -0.871975 0.194006 0.449385 +vn 0.235115 -0.263222 0.935606 +vn 0.882229 -0.229377 0.411115 +vn 0.268319 -0.152867 0.951109 +vn 0.871975 0.194006 0.449385 +vn -0.278787 -0.087436 0.956359 +vn -0.235023 0.025391 0.971648 +vn -0.710685 0.485427 0.509140 +vn -0.471603 0.701071 0.534806 +vn 0.278787 -0.087436 0.956359 +vn 0.710685 0.485427 0.509140 +vn 0.235023 0.025391 0.971648 +vn 0.471603 0.701071 0.534806 +vn -0.117710 0.118748 0.985900 +vn 0.000000 0.157262 0.987548 +vn -0.203192 0.812983 0.545640 +vn 0.000000 0.837458 0.546464 +vn 0.117710 0.118748 0.985900 +vn 0.203192 0.812983 0.545640 +vn -0.190344 0.835902 0.514786 +vn 0.000000 0.848506 0.529160 +vn -0.441786 0.782098 0.439436 +vn -0.283273 0.403424 0.870022 +vn -0.117740 0.377331 0.918546 +vn 0.000000 0.374004 0.927396 +vn 0.190344 0.835902 0.514786 +vn 0.117740 0.377331 0.918546 +vn 0.283273 0.403424 0.870022 +vn 0.441786 0.782098 0.439436 +vn -0.717185 0.632710 0.292062 +vn -0.926328 0.333995 0.174230 +vn -0.899045 0.302957 0.316019 +vn -0.550249 0.375317 0.745842 +vn 0.717185 0.632710 0.292062 +vn 0.550249 0.375317 0.745842 +vn 0.899045 0.302957 0.316019 +vn 0.926328 0.333995 0.174230 +vn -0.953703 -0.224860 0.199591 +vn -0.436445 -0.853481 0.284646 +vn -0.263375 -0.733696 0.626301 +vn -0.748772 -0.273293 0.603809 +vn 0.953703 -0.224860 0.199591 +vn 0.748772 -0.273293 0.603809 +vn 0.263375 -0.733696 0.626301 +vn 0.436445 -0.853481 0.284646 +vn 0.112491 -0.943907 0.310434 +vn 0.000000 -0.944823 0.327555 +vn 0.000000 -0.694723 0.719230 +vn 0.088046 -0.720023 0.688314 +vn -0.112491 -0.943907 0.310434 +vn -0.088046 -0.720023 0.688314 +vn 0.018799 -0.282723 0.958983 +vn 0.000000 -0.267281 0.963591 +vn 0.001862 -0.297555 0.954680 +vn -0.018799 -0.282723 0.958983 +vn -0.001862 -0.297555 0.954680 +vn -0.465896 -0.095767 0.879604 +vn 0.465896 -0.095767 0.879604 +vn -0.261605 -0.178777 0.948454 +vn -0.217139 -0.122898 0.968352 +vn -0.298502 -0.207038 0.931669 +vn -0.013153 -0.028687 0.999481 +vn 0.092990 -0.056795 0.994018 +vn 0.138279 -0.059999 0.988556 +vn 0.261605 -0.178777 0.948454 +vn -0.092990 -0.056795 0.994018 +vn 0.013153 -0.028687 0.999481 +vn 0.298502 -0.207038 0.931669 +vn 0.217139 -0.122898 0.968352 +vn -0.138279 -0.059999 0.988556 +vn -0.148350 -0.068087 0.986572 +vn -0.067995 -0.045351 0.996643 +vn 0.155950 -0.054353 0.986236 +vn 0.162053 -0.069796 0.984283 +vn 0.148350 -0.068087 0.986572 +vn -0.155950 -0.054353 0.986236 +vn 0.067995 -0.045351 0.996643 +vn -0.162053 -0.069796 0.984283 +vn 0.005524 -0.036653 0.999298 +vn 0.069430 -0.011597 0.997497 +vn 0.153691 -0.082430 0.984649 +vn 0.131748 -0.059999 0.989441 +vn -0.005524 -0.036653 0.999298 +vn -0.153691 -0.082430 0.984649 +vn -0.069430 -0.011597 0.997497 +vn -0.131748 -0.059999 0.989441 +vn -0.253121 -0.301431 0.919248 +vn -0.108188 -0.461409 0.880520 +vn 0.010407 -0.254494 0.967009 +vn -0.081484 -0.125309 0.988739 +vn 0.253121 -0.301431 0.919248 +vn 0.081484 -0.125309 0.988739 +vn -0.010407 -0.254494 0.967009 +vn 0.108188 -0.461409 0.880520 +vn 0.037568 -0.534654 0.844203 +vn 0.186346 -0.554064 0.811335 +vn 0.209449 -0.299264 0.930876 +vn 0.117405 -0.307413 0.944273 +vn -0.037568 -0.534654 0.844203 +vn -0.117405 -0.307413 0.944273 +vn -0.209449 -0.299264 0.930876 +vn -0.186346 -0.554064 0.811335 +vn 0.360393 -0.526597 0.769890 +vn 0.479415 -0.437269 0.760857 +vn 0.365703 -0.161596 0.916562 +vn 0.311472 -0.246803 0.917600 +vn -0.360393 -0.526597 0.769890 +vn -0.311472 -0.246803 0.917600 +vn -0.365703 -0.161596 0.916562 +vn -0.479415 -0.437269 0.760857 +vn 0.509262 -0.320627 0.798639 +vn 0.491165 -0.203009 0.847072 +vn 0.310862 -0.056795 0.948729 +vn 0.357707 -0.085299 0.929899 +vn -0.509262 -0.320627 0.798639 +vn -0.357707 -0.085299 0.929899 +vn -0.310862 -0.056795 0.948729 +vn -0.491165 -0.203009 0.847072 +vn 0.460250 -0.109989 0.880917 +vn 0.425031 -0.052095 0.903653 +vn 0.242164 -0.060823 0.968322 +vn 0.263680 -0.061098 0.962645 +vn -0.460250 -0.109989 0.880917 +vn -0.263680 -0.061098 0.962645 +vn -0.242164 -0.060823 0.968322 +vn -0.425031 -0.052095 0.903653 +vn 0.387738 -0.025880 0.921384 +vn 0.401471 0.034669 0.915189 +vn 0.346110 -0.079379 0.934812 +vn 0.283303 -0.067721 0.956603 +vn -0.387738 -0.025880 0.921384 +vn -0.283303 -0.067721 0.956603 +vn -0.346110 -0.079379 0.934812 +vn -0.401471 0.034669 0.915189 +vn 0.428449 0.203955 0.880215 +vn 0.363475 0.340465 0.867122 +vn 0.298685 0.113559 0.947539 +vn 0.393689 -0.024262 0.918912 +vn -0.428449 0.203955 0.880215 +vn -0.393689 -0.024262 0.918912 +vn -0.298685 0.113559 0.947539 +vn -0.363475 0.340465 0.867122 +vn 0.219398 0.286538 0.932585 +vn 0.153050 0.142674 0.977844 +vn 0.107395 0.172155 0.979186 +vn 0.128117 0.198492 0.971679 +vn -0.219398 0.286538 0.932585 +vn -0.128117 0.198492 0.971679 +vn -0.107395 0.172155 0.979186 +vn -0.153050 0.142674 0.977844 +vn 0.170660 0.080355 0.982025 +vn 0.152257 0.064943 0.986175 +vn 0.137211 0.094607 0.985992 +vn 0.160375 0.141301 0.976867 +vn -0.170660 0.080355 0.982025 +vn -0.160375 0.141301 0.976867 +vn -0.137211 0.094607 0.985992 +vn -0.152257 0.064943 0.986175 +vn 0.113102 0.030427 0.993103 +vn 0.113804 0.006561 0.993469 +vn -0.113102 0.030427 0.993103 +vn -0.113804 0.006561 0.993469 +vn 0.270608 -0.284249 0.919736 +vn 0.226051 -0.191931 0.954985 +vn 0.397351 -0.314310 0.862117 +vn 0.488113 -0.426557 0.761406 +vn 0.330943 -0.419019 0.845485 +vn 0.260292 -0.334666 0.905667 +vn -0.270608 -0.284249 0.919736 +vn -0.330943 -0.419019 0.845485 +vn -0.488113 -0.426557 0.761406 +vn -0.397351 -0.314310 0.862117 +vn -0.226051 -0.191931 0.954985 +vn -0.260292 -0.334666 0.905667 +vn 0.195196 -0.165593 0.966674 +vn 0.042787 -0.259590 0.964751 +vn 0.211554 -0.315836 0.924894 +vn 0.032899 -0.464797 0.884762 +vn -0.195196 -0.165593 0.966674 +vn -0.211554 -0.315836 0.924894 +vn -0.042787 -0.259590 0.964751 +vn -0.032899 -0.464797 0.884762 +vn -0.048921 -0.412000 0.909848 +vn 0.027650 -0.570605 0.820734 +vn -0.111759 -0.677816 0.726646 +vn -0.107700 -0.811182 0.574755 +vn 0.048921 -0.412000 0.909848 +vn 0.111759 -0.677816 0.726646 +vn -0.027650 -0.570605 0.820734 +vn 0.107700 -0.811182 0.574755 +vn 0.084536 -0.644581 0.759819 +vn 0.008942 -0.549821 0.835200 +vn -0.073183 -0.811975 0.579058 +vn -0.133641 -0.676046 0.724601 +vn -0.084536 -0.644581 0.759819 +vn 0.073183 -0.811975 0.579058 +vn -0.008942 -0.549821 0.835200 +vn 0.133641 -0.676046 0.724601 +vn -0.126774 -0.301431 0.945006 +vn -0.197241 -0.108707 0.974273 +vn -0.303690 -0.372570 0.876888 +vn -0.386670 -0.114383 0.915067 +vn 0.126774 -0.301431 0.945006 +vn 0.303690 -0.372570 0.876888 +vn 0.197241 -0.108707 0.974273 +vn 0.386670 -0.114383 0.915067 +vn -0.153111 0.025513 0.987854 +vn -0.060823 0.190924 0.979705 +vn -0.337535 0.070559 0.938627 +vn -0.226417 0.283303 0.931883 +vn 0.153111 0.025513 0.987854 +vn 0.337535 0.070559 0.938627 +vn 0.060823 0.190924 0.979705 +vn 0.226417 0.283303 0.931883 +vn 0.005951 0.304239 0.952574 +vn 0.045167 0.351115 0.935209 +vn -0.160772 0.446089 0.880398 +vn -0.125309 0.555132 0.822230 +vn -0.005951 0.304239 0.952574 +vn 0.160772 0.446089 0.880398 +vn -0.045167 0.351115 0.935209 +vn 0.125309 0.555132 0.822230 +vn 0.127873 0.354625 0.926206 +vn 0.236335 0.345408 0.908170 +vn -0.000763 0.616901 0.787011 +vn 0.192267 0.617420 0.762749 +vn -0.127873 0.354625 0.926206 +vn 0.000763 0.616901 0.787011 +vn -0.236335 0.345408 0.908170 +vn -0.192267 0.617420 0.762749 +vn 0.308939 0.358501 0.880917 +vn 0.335368 0.382122 0.861080 +vn 0.326395 0.601337 0.729270 +vn 0.402081 0.591449 0.698904 +vn -0.308939 0.358501 0.880917 +vn -0.326395 0.601337 0.729270 +vn -0.335368 0.382122 0.861080 +vn -0.402081 0.591449 0.698904 +vn 0.389050 0.384259 0.837214 +vn 0.534898 0.279977 0.797143 +vn 0.515946 0.514359 0.684957 +vn 0.676565 0.330302 0.658132 +vn -0.389050 0.384259 0.837214 +vn -0.515946 0.514359 0.684957 +vn -0.534898 0.279977 0.797143 +vn -0.676565 0.330302 0.658132 +vn 0.527604 -0.273049 0.804376 +vn 0.622272 -0.186132 0.760308 +vn 0.765069 -0.241066 0.597064 +vn 0.648152 -0.360881 0.670522 +vn -0.527604 -0.273049 0.804376 +vn -0.648152 -0.360881 0.670522 +vn -0.765069 -0.241066 0.597064 +vn -0.622272 -0.186132 0.760308 +vn 0.668783 -0.082888 0.738792 +vn 0.676351 0.002106 0.736564 +vn 0.806848 0.011963 0.590625 +vn 0.811151 -0.097079 0.576708 +vn -0.668783 -0.082888 0.738792 +vn -0.811151 -0.097079 0.576708 +vn -0.806848 0.011963 0.590625 +vn -0.676351 0.002106 0.736564 +vn 0.644093 0.114261 0.756340 +vn 0.774621 0.137913 0.617145 +vn -0.644093 0.114261 0.756340 +vn -0.774621 0.137913 0.617145 +vn -0.505081 0.858516 -0.088290 +vn 0.000000 0.999878 0.013855 +vn -0.746269 0.605304 -0.276864 +vn -0.497360 0.863094 -0.087497 +vn -0.351115 0.871151 0.343181 +vn 0.000000 0.878750 0.477218 +vn 0.505081 0.858516 -0.088290 +vn 0.351115 0.871151 0.343181 +vn 0.497360 0.863094 -0.087497 +vn 0.746269 0.605304 -0.276864 +vn -0.791742 0.472396 -0.387219 +vn -0.644093 0.648366 -0.405835 +vn -0.500351 0.452437 -0.738151 +vn -0.511338 0.377941 -0.771783 +vn 0.791742 0.472396 -0.387219 +vn 0.511338 0.377941 -0.771783 +vn 0.500351 0.452437 -0.738151 +vn 0.644093 0.648366 -0.405835 +vn -0.244026 0.879971 -0.407483 +vn 0.232704 0.890439 -0.391064 +vn 0.082522 0.628529 -0.773370 +vn -0.226386 0.551347 -0.802942 +vn 0.244026 0.879971 -0.407483 +vn 0.226386 0.551347 -0.802942 +vn -0.082522 0.628529 -0.773370 +vn -0.232704 0.890439 -0.391064 +vn 0.467757 0.801263 -0.372997 +vn 0.440931 0.839595 -0.317179 +vn 0.155065 0.854091 -0.496445 +vn 0.120731 0.563433 -0.817255 +vn -0.467757 0.801263 -0.372997 +vn -0.120731 0.563433 -0.817255 +vn -0.155065 0.854091 -0.496445 +vn -0.440931 0.839595 -0.317179 +vn 0.391461 0.891324 -0.228614 +vn 0.375439 0.909665 -0.177435 +vn 0.361827 0.909024 -0.206641 +vn 0.303110 0.910794 -0.280221 +vn -0.391461 0.891324 -0.228614 +vn -0.303110 0.910794 -0.280221 +vn -0.361827 0.909024 -0.206641 +vn -0.375439 0.909665 -0.177435 +vn 0.528886 0.825526 -0.196875 +vn 0.853084 0.460738 -0.244728 +vn 0.807184 0.518357 -0.282327 +vn 0.501938 0.828883 -0.246895 +vn -0.528886 0.825526 -0.196875 +vn -0.501938 0.828883 -0.246895 +vn -0.807184 0.518357 -0.282327 +vn -0.853084 0.460738 -0.244728 +vn 0.971374 0.002319 -0.237403 +vn 0.898373 -0.398968 -0.183538 +vn 0.937559 -0.344340 -0.048463 +vn 0.980651 0.075594 -0.180517 +vn -0.971374 0.002319 -0.237403 +vn -0.980651 0.075594 -0.180517 +vn -0.937559 -0.344340 -0.048463 +vn -0.898373 -0.398968 -0.183538 +vn 0.719077 -0.682333 -0.131443 +vn 0.578265 -0.808924 -0.105930 +vn 0.621387 -0.782037 0.047487 +vn 0.778100 -0.627796 0.020264 +vn -0.719077 -0.682333 -0.131443 +vn -0.778100 -0.627796 0.020264 +vn -0.621387 -0.782037 0.047487 +vn -0.578265 -0.808924 -0.105930 +vn 0.459853 -0.882473 -0.098819 +vn 0.342631 -0.934935 -0.091922 +vn 0.422193 -0.904386 0.061525 +vn 0.496261 -0.866848 0.047670 +vn -0.459853 -0.882473 -0.098819 +vn -0.496261 -0.866848 0.047670 +vn -0.422193 -0.904386 0.061525 +vn -0.342631 -0.934935 -0.091922 +vn 0.238777 -0.534837 -0.810480 +vn 0.209296 -0.259468 -0.942778 +vn 0.000000 -0.250649 -0.968047 +vn 0.000000 -0.511399 -0.859310 +vn 0.000000 -0.786798 -0.617176 +vn 0.285134 -0.784204 -0.551073 +vn 0.645039 -0.633320 -0.427473 +vn 0.504624 -0.480880 -0.716971 +vn 0.340556 -0.236152 -0.910062 +vn -0.238777 -0.534837 -0.810480 +vn -0.504624 -0.480880 -0.716971 +vn -0.645039 -0.633320 -0.427473 +vn -0.285134 -0.784204 -0.551073 +vn -0.209296 -0.259468 -0.942778 +vn -0.340556 -0.236152 -0.910062 +vn 0.175726 -0.141453 -0.974212 +vn 0.130833 -0.248421 -0.959746 +vn 0.000000 -0.286630 -0.958007 +vn 0.000000 -0.159459 -0.987182 +vn 0.220435 -0.098758 -0.970367 +vn 0.138737 -0.172582 -0.975158 +vn -0.175726 -0.141453 -0.974212 +vn -0.220435 -0.098758 -0.970367 +vn -0.130833 -0.248421 -0.959746 +vn -0.138737 -0.172582 -0.975158 +vn 0.077181 -0.463210 -0.882839 +vn 0.057894 -0.754051 -0.654225 +vn 0.000000 -0.782281 -0.622883 +vn 0.000000 -0.504929 -0.863155 +vn 0.062502 -0.372387 -0.925962 +vn 0.046327 -0.694968 -0.717521 +vn -0.077181 -0.463210 -0.882839 +vn -0.062502 -0.372387 -0.925962 +vn -0.057894 -0.754051 -0.654225 +vn -0.046327 -0.694968 -0.717521 +vn 0.078799 -0.966521 -0.244118 +vn 0.101199 -0.949919 -0.295541 +vn 0.000000 -0.976318 -0.216254 +vn -0.078799 -0.966521 -0.244118 +vn -0.101199 -0.949919 -0.295541 +vn 0.211432 -0.911527 -0.352702 +vn 0.604419 -0.677328 -0.419385 +vn 0.134678 -0.614338 -0.777429 +vn 0.408521 -0.468001 -0.783593 +vn -0.211432 -0.911527 -0.352702 +vn -0.134678 -0.614338 -0.777429 +vn -0.604419 -0.677328 -0.419385 +vn -0.408521 -0.468001 -0.783593 +vn 0.885556 -0.204413 -0.417066 +vn 0.930631 0.077364 -0.357646 +vn 0.555773 -0.135075 -0.820276 +vn 0.611133 0.051668 -0.789819 +vn -0.885556 -0.204413 -0.417066 +vn -0.555773 -0.135075 -0.820276 +vn -0.930631 0.077364 -0.357646 +vn -0.611133 0.051668 -0.789819 +vn 0.929411 0.136906 -0.342662 +vn 0.932859 0.142796 -0.330668 +vn 0.668264 0.097812 -0.737449 +vn 0.741050 0.065981 -0.668142 +vn -0.929411 0.136906 -0.342662 +vn -0.668264 0.097812 -0.737449 +vn -0.932859 0.142796 -0.330668 +vn -0.741050 0.065981 -0.668142 +vn 0.334391 -0.015107 -0.942289 +vn 0.224799 -0.069185 -0.971923 +vn 0.511826 -0.112339 -0.851680 +vn -0.334391 -0.015107 -0.942289 +vn -0.511826 -0.112339 -0.851680 +vn -0.224799 -0.069185 -0.971923 +vn 0.138066 -0.257668 -0.956298 +vn -0.138066 -0.257668 -0.956298 +vn 0.734458 -0.242225 -0.633931 +vn 0.886502 -0.270272 -0.375500 +vn 0.928983 0.054781 -0.365978 +vn 0.844508 0.023957 -0.534959 +vn -0.734458 -0.242225 -0.633931 +vn -0.844508 0.023957 -0.534959 +vn -0.928983 0.054781 -0.365978 +vn -0.886502 -0.270272 -0.375500 +vn 0.942167 0.143651 -0.302713 +vn 0.951659 0.199347 -0.233558 +vn -0.942167 0.143651 -0.302713 +vn -0.951659 0.199347 -0.233558 +vn 0.983551 0.149571 0.101169 +vn 0.982940 0.180456 -0.034913 +vn 0.941069 -0.327708 0.083407 +vn 0.893460 -0.355846 0.273995 +vn 0.810053 -0.288949 0.510178 +vn 0.957060 0.182775 0.224891 +vn -0.983551 0.149571 0.101169 +vn -0.957060 0.182775 0.224891 +vn -0.810053 -0.288949 0.510178 +vn -0.893460 -0.355846 0.273995 +vn -0.941069 -0.327708 0.083407 +vn -0.982940 0.180456 -0.034913 +vn 0.960540 0.237526 -0.144658 +vn 0.982849 -0.017487 -0.183416 +vn -0.960540 0.237526 -0.144658 +vn -0.982849 -0.017487 -0.183416 +vn 0.963408 -0.150548 0.221656 +vn 0.612262 -0.787164 0.074007 +vn 0.769280 -0.447340 0.456099 +vn 0.488052 -0.863704 0.125614 +vn -0.963408 -0.150548 0.221656 +vn -0.769280 -0.447340 0.456099 +vn -0.612262 -0.787164 0.074007 +vn -0.488052 -0.863704 0.125614 +vn 0.306284 -0.949522 -0.067415 +vn 0.385022 -0.912259 0.139561 +vn -0.306284 -0.949522 -0.067415 +vn -0.385022 -0.912259 0.139561 +vn 0.286752 -0.493240 -0.821253 +vn 0.000000 -0.499283 -0.866421 +vn 0.000000 -0.258156 -0.966094 +vn 0.288797 -0.271310 -0.918119 +vn 0.412061 -0.299722 -0.860439 +vn 0.418378 -0.496597 -0.760460 +vn 0.452223 -0.685965 -0.569994 +vn 0.276925 -0.705466 -0.652364 +vn 0.000000 -0.719779 -0.694174 +vn -0.286752 -0.493240 -0.821253 +vn -0.276925 -0.705466 -0.652364 +vn -0.452223 -0.685965 -0.569994 +vn -0.418378 -0.496597 -0.760460 +vn -0.412061 -0.299722 -0.860439 +vn -0.288797 -0.271310 -0.918119 +vn 0.268380 -0.842799 -0.466475 +vn 0.000000 -0.864620 -0.502396 +vn 0.476150 -0.788720 -0.388745 +vn 0.482253 -0.849330 -0.214545 +vn 0.260842 -0.922483 -0.284463 +vn 0.000000 -0.949736 -0.312998 +vn -0.268380 -0.842799 -0.466475 +vn -0.260842 -0.922483 -0.284463 +vn -0.482253 -0.849330 -0.214545 +vn -0.476150 -0.788720 -0.388745 +vn 0.272622 -0.948973 -0.158330 +vn 0.000000 -0.982391 -0.186682 +vn 0.513932 -0.854030 -0.080386 +vn 0.599872 -0.800073 -0.004547 +vn 0.298746 -0.944731 -0.134770 +vn 0.000000 -0.986053 -0.166265 +vn -0.272622 -0.948973 -0.158330 +vn -0.298746 -0.944731 -0.134770 +vn -0.599872 -0.800073 -0.004547 +vn -0.513932 -0.854030 -0.080386 +vn 0.314982 -0.910886 -0.266549 +vn 0.000000 -0.948271 -0.317423 +vn 0.655751 -0.741020 -0.144444 +vn -0.314982 -0.910886 -0.266549 +vn -0.655751 -0.741020 -0.144444 +vn 0.916898 -0.382458 -0.114078 +vn 0.810053 -0.578295 0.096652 +vn -0.916898 -0.382458 -0.114078 +vn -0.810053 -0.578295 0.096652 +vn 0.837550 -0.514420 0.183905 +vn 0.962828 -0.236457 0.130467 +vn 0.656911 -0.724540 0.208563 +vn 0.692953 -0.705496 0.148350 +vn 0.897031 -0.422987 0.127995 +vn 0.978484 -0.154546 0.136479 +vn -0.837550 -0.514420 0.183905 +vn -0.897031 -0.422987 0.127995 +vn -0.692953 -0.705496 0.148350 +vn -0.656911 -0.724540 0.208563 +vn -0.962828 -0.236457 0.130467 +vn -0.978484 -0.154546 0.136479 +vn 0.288552 -0.043245 -0.956450 +vn 0.000000 -0.011048 -0.999908 +vn 0.000000 0.319987 -0.947417 +vn 0.295999 0.283822 -0.912015 +vn 0.434156 0.214789 -0.874844 +vn 0.420698 -0.107517 -0.900784 +vn -0.288552 -0.043245 -0.956450 +vn -0.420698 -0.107517 -0.900784 +vn -0.434156 0.214789 -0.874844 +vn -0.295999 0.283822 -0.912015 +vn 0.147130 0.950682 0.272958 +vn 0.000000 0.963225 0.268624 +vn 0.000000 0.824610 0.565661 +vn 0.177679 0.804682 0.566454 +vn 0.422620 0.734001 0.531571 +vn 0.387707 0.884182 0.260537 +vn 0.356822 0.933988 0.016968 +vn 0.133305 0.990936 0.015534 +vn 0.000000 0.999939 0.010834 +vn -0.147130 0.950682 0.272958 +vn -0.133305 0.990936 0.015534 +vn -0.356822 0.933988 0.016968 +vn -0.387707 0.884182 0.260537 +vn -0.422620 0.734001 0.531571 +vn -0.177679 0.804682 0.566454 +vn 0.151311 0.959624 -0.237068 +vn 0.000000 0.971221 -0.238044 +vn 0.344554 0.908902 -0.234840 +vn 0.359935 0.767052 -0.531053 +vn 0.211371 0.823267 -0.526780 +vn 0.000000 0.847011 -0.531510 +vn -0.151311 0.959624 -0.237068 +vn -0.211371 0.823267 -0.526780 +vn -0.359935 0.767052 -0.531053 +vn -0.344554 0.908902 -0.234840 +vn 0.273568 0.593371 -0.756981 +vn 0.000000 0.628010 -0.778191 +vn 0.404309 0.527024 -0.747459 +vn -0.273568 0.593371 -0.756981 +vn -0.404309 0.527024 -0.747459 +vn 0.551958 0.832759 -0.042329 +vn 0.435133 0.900021 0.024720 +vn 0.830073 0.553514 -0.067568 +vn 0.827845 0.512711 0.227424 +vn 0.570269 0.749840 0.335337 +vn 0.518967 0.752251 0.405896 +vn -0.551958 0.832759 -0.042329 +vn -0.570269 0.749840 0.335337 +vn -0.827845 0.512711 0.227424 +vn -0.830073 0.553514 -0.067568 +vn -0.435133 0.900021 0.024720 +vn -0.518967 0.752251 0.405896 +vn 0.552629 0.637471 0.536821 +vn 0.569964 0.611957 0.548265 +vn 0.806818 0.427686 0.407514 +vn 0.836085 0.447737 0.316965 +vn 0.629475 0.658742 0.412000 +vn 0.641011 0.653615 0.402264 +vn -0.552629 0.637471 0.536821 +vn -0.629475 0.658742 0.412000 +vn -0.836085 0.447737 0.316965 +vn -0.806818 0.427686 0.407514 +vn -0.569964 0.611957 0.548265 +vn -0.641011 0.653615 0.402264 +vn 0.708090 0.686544 0.164922 +vn 0.670644 0.723197 0.164922 +vn 0.879086 0.464949 0.104831 +vn 0.901608 0.429914 -0.047243 +vn 0.742759 0.668722 -0.032960 +vn 0.671621 0.740074 -0.034059 +vn -0.708090 0.686544 0.164922 +vn -0.742759 0.668722 -0.032960 +vn -0.901608 0.429914 -0.047243 +vn -0.879086 0.464949 0.104831 +vn -0.670644 0.723197 0.164922 +vn -0.671621 0.740074 -0.034059 +vn 0.756340 0.605823 -0.246803 +vn 0.650349 0.706229 -0.279641 +vn 0.909421 0.365398 -0.198462 +vn 0.871395 0.300211 -0.387921 +vn 0.737114 0.439436 -0.513321 +vn 0.599506 0.554643 -0.576983 +vn -0.756340 0.605823 -0.246803 +vn -0.737114 0.439436 -0.513321 +vn -0.871395 0.300211 -0.387921 +vn -0.909421 0.365398 -0.198462 +vn -0.650349 0.706229 -0.279641 +vn -0.599506 0.554643 -0.576983 +vn 0.700430 0.207892 -0.682730 +vn 0.863552 0.163060 -0.477096 +vn 0.686392 0.052278 -0.725333 +vn 0.645894 -0.041200 -0.762261 +vn 0.581469 0.013855 -0.813440 +vn 0.581927 0.305002 -0.753838 +vn -0.700430 0.207892 -0.682730 +vn -0.581927 0.305002 -0.753838 +vn -0.581469 0.013855 -0.813440 +vn -0.645894 -0.041200 -0.762261 +vn -0.686392 0.052278 -0.725333 +vn -0.863552 0.163060 -0.477096 +vn 0.487533 0.429731 -0.760002 +vn 0.514939 0.118656 -0.848933 +vn 0.494400 0.667928 -0.556230 +vn -0.487533 0.429731 -0.760002 +vn -0.494400 0.667928 -0.556230 +vn -0.514939 0.118656 -0.848933 +vn 0.546007 0.797845 -0.255531 +vn 0.587054 0.809503 -0.007202 +vn -0.546007 0.797845 -0.255531 +vn -0.587054 0.809503 -0.007202 +vn 0.617512 0.759880 0.203070 +vn 0.636219 0.635090 0.438002 +vn -0.617512 0.759880 0.203070 +vn -0.636219 0.635090 0.438002 +vn 0.615406 0.552629 0.561998 +vn 0.433485 0.604114 0.668630 +vn 0.370983 0.745781 0.553270 +vn 0.538408 0.729637 0.421552 +vn -0.615406 0.552629 0.561998 +vn -0.538408 0.729637 0.421552 +vn -0.370983 0.745781 0.553270 +vn -0.433485 0.604114 0.668630 +vn 0.376568 0.926267 0.014100 +vn 0.182409 0.981872 0.051424 +vn -0.376568 0.926267 0.014100 +vn -0.182409 0.981872 0.051424 +vn 0.209052 0.657765 0.723594 +vn 0.000000 0.682516 0.730827 +vn 0.000000 0.610889 0.791681 +vn 0.193762 0.700705 0.686605 +vn -0.209052 0.657765 0.723594 +vn -0.193762 0.700705 0.686605 +vn -0.207953 0.341136 -0.916684 +vn -0.198553 0.775750 -0.598926 +vn 0.207953 0.341136 -0.916684 +vn 0.198553 0.775750 -0.598926 +vn 0.028169 0.936552 0.349315 +vn -0.045198 0.741386 0.669515 +vn -0.028169 0.936552 0.349315 +vn 0.045198 0.741386 0.669515 +vn -0.103214 0.565844 0.817988 +vn 0.000000 0.515732 0.856716 +vn 0.103214 0.565844 0.817988 +vn 0.988647 0.143651 0.043428 +vn 0.969390 0.150731 0.193640 +vn -0.988647 0.143651 0.043428 +vn -0.969390 0.150731 0.193640 +vn 0.961150 0.141972 0.236671 +vn 0.991089 -0.112064 0.071688 +vn 0.996094 -0.087863 0.005982 +vn 0.972930 0.178503 0.146702 +vn -0.961150 0.141972 0.236671 +vn -0.972930 0.178503 0.146702 +vn -0.996094 -0.087863 0.005982 +vn -0.991089 -0.112064 0.071688 +vn 0.976745 0.214362 0.000549 +vn 0.997345 0.067721 -0.026521 +vn 0.862911 0.481582 0.152989 +vn 0.974273 0.205939 -0.091464 +vn -0.976745 0.214362 0.000549 +vn -0.974273 0.205939 -0.091464 +vn -0.862911 0.481582 0.152989 +vn -0.997345 0.067721 -0.026521 +vn 0.958953 0.179296 -0.219642 +vn 0.659688 0.631062 -0.408063 +vn -0.958953 0.179296 -0.219642 +vn -0.659688 0.631062 -0.408063 +vn 0.634510 -0.772881 -0.002594 +vn 0.677480 -0.727989 0.104923 +vn 0.611896 -0.775109 -0.157231 +vn 0.552232 -0.817194 -0.164861 +vn 0.554521 -0.831813 0.023713 +vn 0.574145 -0.803827 0.155492 +vn -0.634510 -0.772881 -0.002594 +vn -0.554521 -0.831813 0.023713 +vn -0.552232 -0.817194 -0.164861 +vn -0.611896 -0.775109 -0.157231 +vn -0.677480 -0.727989 0.104923 +vn -0.574145 -0.803827 0.155492 +vn 0.431562 -0.900662 0.050020 +vn 0.514512 -0.853725 0.079958 +vn 0.484573 -0.859371 0.163091 +vn 0.372662 -0.912870 -0.166662 +vn 0.220649 -0.975311 -0.008881 +vn -0.431562 -0.900662 0.050020 +vn -0.372662 -0.912870 -0.166662 +vn -0.484573 -0.859371 0.163091 +vn -0.514512 -0.853725 0.079958 +vn -0.220649 -0.975311 -0.008881 +vn 0.510849 -0.837336 0.194555 +vn 0.517472 -0.832362 0.198401 +vn -0.510849 -0.837336 0.194555 +vn -0.517472 -0.832362 0.198401 +vn 0.636128 -0.723289 0.268624 +vn 0.531968 -0.730094 0.428877 +vn 0.691885 -0.690512 0.210791 +vn -0.636128 -0.723289 0.268624 +vn -0.691885 -0.690512 0.210791 +vn -0.531968 -0.730094 0.428877 +vn 0.719932 -0.671804 0.174139 +vn -0.719932 -0.671804 0.174139 +vn 0.479995 -0.700980 0.527421 +vn -0.479995 -0.700980 0.527421 +vn 0.553697 -0.316263 -0.770287 +vn 0.538865 -0.290139 -0.790796 +vn 0.330943 -0.613880 -0.716636 +vn 0.439894 -0.608448 -0.660482 +vn 0.568682 -0.533830 -0.625782 +vn 0.555193 -0.280313 -0.783044 +vn -0.553697 -0.316263 -0.770287 +vn -0.555193 -0.280313 -0.783044 +vn -0.568682 -0.533830 -0.625782 +vn -0.439894 -0.608448 -0.660482 +vn -0.330943 -0.613880 -0.716636 +vn -0.538865 -0.290139 -0.790796 +vn 0.506241 -0.193304 -0.840419 +vn 0.513321 -0.365490 -0.776452 +vn -0.506241 -0.193304 -0.840419 +vn -0.513321 -0.365490 -0.776452 +vn 0.352092 -0.829249 -0.433973 +vn 0.124088 -0.887814 -0.443129 +vn 0.560656 -0.740715 -0.370067 +vn -0.352092 -0.829249 -0.433973 +vn -0.560656 -0.740715 -0.370067 +vn -0.124088 -0.887814 -0.443129 +vn 0.612964 -0.717734 -0.330302 +vn 0.591662 -0.625507 -0.508560 +vn -0.612964 -0.717734 -0.330302 +vn -0.591662 -0.625507 -0.508560 +vn 0.521714 -0.487045 -0.700400 +vn -0.521714 -0.487045 -0.700400 +vn 0.209479 0.534135 0.818995 +vn 0.309488 0.497574 0.810297 +vn -0.128636 0.958678 0.253670 +vn -0.277871 0.920347 0.275124 +vn -0.451857 0.830683 0.325175 +vn 0.052919 0.487991 0.871212 +vn 0.519364 -0.143529 0.842372 +vn 0.585803 -0.145634 0.797235 +vn 0.565172 -0.212806 0.797021 +vn -0.209479 0.534135 0.818995 +vn -0.585803 -0.145634 0.797235 +vn -0.519364 -0.143529 0.842372 +vn -0.052919 0.487991 0.871212 +vn 0.451857 0.830683 0.325175 +vn 0.277871 0.920347 0.275124 +vn 0.128636 0.958678 0.253670 +vn -0.309488 0.497574 0.810297 +vn -0.565172 -0.212806 0.797021 +vn 0.368633 0.426740 0.825800 +vn 0.088748 0.954375 0.285012 +vn 0.474837 -0.253914 0.842616 +vn 0.286019 -0.227882 0.930692 +vn 0.416242 0.313120 0.853633 +vn 0.432173 0.832484 0.346629 +vn -0.368633 0.426740 0.825800 +vn -0.416242 0.313120 0.853633 +vn -0.286019 -0.227882 0.930692 +vn -0.474837 -0.253914 0.842616 +vn -0.088748 0.954375 0.285012 +vn -0.432173 0.832484 0.346629 +vn 0.384899 0.142399 0.911893 +vn 0.719260 0.472427 0.509323 +vn 0.015687 -0.158208 0.987274 +vn -0.158818 -0.063173 0.985260 +vn 0.330943 0.009430 0.943571 +vn 0.762993 0.105686 0.637684 +vn -0.384899 0.142399 0.911893 +vn -0.330943 0.009430 0.943571 +vn 0.158818 -0.063173 0.985260 +vn -0.015687 -0.158208 0.987274 +vn -0.719260 0.472427 0.509323 +vn -0.762993 0.105686 0.637684 +vn 0.335917 -0.072848 0.939055 +vn 0.735893 -0.192053 0.649251 +vn -0.209998 0.093936 0.973144 +vn -0.082522 0.330973 0.940001 +vn 0.414380 -0.113132 0.903012 +vn 0.699118 -0.451277 0.554582 +vn -0.335917 -0.072848 0.939055 +vn -0.414380 -0.113132 0.903012 +vn 0.082522 0.330973 0.940001 +vn 0.209998 0.093936 0.973144 +vn -0.735893 -0.192053 0.649251 +vn -0.699118 -0.451277 0.554582 +vn 0.520920 -0.197363 0.830439 +vn 0.605914 -0.676687 0.418226 +vn 0.182531 0.440687 0.878872 +vn 0.453230 0.337626 0.824946 +vn 0.592914 -0.341716 0.729148 +vn 0.473220 -0.824915 0.309122 +vn -0.520920 -0.197363 0.830439 +vn -0.592914 -0.341716 0.729148 +vn -0.453230 0.337626 0.824946 +vn -0.182531 0.440687 0.878872 +vn -0.605914 -0.676687 0.418226 +vn -0.473220 -0.824915 0.309122 +vn 0.539781 -0.447951 0.712699 +vn 0.318339 -0.905057 0.281961 +vn 0.548692 0.202307 0.811151 +vn 0.358654 0.326518 0.874477 +vn 0.265175 -0.352886 0.897275 +vn 0.067537 -0.934385 0.349773 +vn -0.539781 -0.447951 0.712699 +vn -0.265175 -0.352886 0.897275 +vn -0.358654 0.326518 0.874477 +vn -0.548692 0.202307 0.811151 +vn -0.318339 -0.905057 0.281961 +vn -0.067537 -0.934385 0.349773 +vn 0.363628 0.683462 0.632923 +vn 0.127232 0.795526 0.592364 +vn -0.150975 0.949828 0.273812 +vn 0.124302 0.922849 0.364483 +vn 0.148930 0.913938 0.377453 +vn 0.288919 0.722434 0.628132 +vn -0.363628 0.683462 0.632923 +vn -0.288919 0.722434 0.628132 +vn -0.148930 0.913938 0.377453 +vn -0.124302 0.922849 0.364483 +vn 0.150975 0.949828 0.273812 +vn -0.127232 0.795526 0.592364 +vn -0.234443 0.799249 0.553362 +vn -0.574297 0.610431 0.545457 +vn -0.779595 0.625935 0.019868 +vn -0.486496 0.860500 0.151006 +vn 0.234443 0.799249 0.553362 +vn 0.486496 0.860500 0.151006 +vn 0.779595 0.625935 0.019868 +vn 0.574297 0.610431 0.545457 +vn -0.769890 0.263863 0.581042 +vn -0.704611 -0.087863 0.704093 +vn -0.990295 -0.073580 0.117740 +vn -0.952635 0.303598 -0.016480 +vn 0.769890 0.263863 0.581042 +vn 0.952635 0.303598 -0.016480 +vn 0.990295 -0.073580 0.117740 +vn 0.704611 -0.087863 0.704093 +vn -0.387768 -0.376843 0.841151 +vn 0.100284 -0.528642 0.842860 +vn -0.094821 -0.757225 0.646168 +vn -0.738731 -0.525468 0.422071 +vn 0.387768 -0.376843 0.841151 +vn 0.738731 -0.525468 0.422071 +vn 0.094821 -0.757225 0.646168 +vn -0.100284 -0.528642 0.842860 +vn 0.422437 -0.542375 0.726157 +vn 0.569414 -0.503067 0.650105 +vn 0.529191 -0.653615 0.541002 +vn 0.346049 -0.718528 0.603259 +vn -0.422437 -0.542375 0.726157 +vn -0.346049 -0.718528 0.603259 +vn -0.529191 -0.653615 0.541002 +vn -0.569414 -0.503067 0.650105 +vn 0.654408 -0.438581 0.615894 +vn 0.652272 -0.404614 0.640919 +vn 0.695608 -0.531571 0.483261 +vn 0.647786 -0.578509 0.495621 +vn -0.654408 -0.438581 0.615894 +vn -0.647786 -0.578509 0.495621 +vn -0.695608 -0.531571 0.483261 +vn -0.652272 -0.404614 0.640919 +vn 0.736076 -0.673910 0.063051 +vn 0.844966 -0.534532 -0.016541 +vn 0.465987 -0.659810 0.589465 +vn 0.719077 0.184545 0.669942 +vn 0.905606 -0.420331 0.056154 +vn 0.906552 -0.403455 -0.123905 +vn -0.736076 -0.673910 0.063051 +vn -0.905606 -0.420331 0.056154 +vn -0.719077 0.184545 0.669942 +vn -0.465987 -0.659810 0.589465 +vn -0.844966 -0.534532 -0.016541 +vn -0.906552 -0.403455 -0.123905 +vn 0.072939 -0.280648 0.957030 +vn -0.086459 -0.935301 0.343089 +vn 0.180700 0.506149 0.843287 +vn -0.072939 -0.280648 0.957030 +vn -0.180700 0.506149 0.843287 +vn 0.086459 -0.935301 0.343089 +vn 0.937071 -0.347606 -0.032167 +vn 0.937071 -0.333140 -0.104312 +vn -0.937071 -0.347606 -0.032167 +vn -0.937071 -0.333140 -0.104312 +vn 0.196753 0.375072 0.905850 +vn -0.321055 0.893460 0.313974 +vn 0.838160 0.062502 0.541795 +vn 0.692587 -0.287454 0.661550 +vn 0.500412 -0.212104 0.839381 +vn -0.196753 0.375072 0.905850 +vn -0.500412 -0.212104 0.839381 +vn -0.692587 -0.287454 0.661550 +vn -0.838160 0.062502 0.541795 +vn 0.321055 0.893460 0.313974 +vn 0.170232 0.840114 0.514969 +vn 0.101382 0.954955 0.278817 +vn 0.516526 0.734611 0.439924 +vn 0.482498 0.642048 0.595752 +vn -0.170232 0.840114 0.514969 +vn -0.482498 0.642048 0.595752 +vn -0.516526 0.734611 0.439924 +vn -0.101382 0.954955 0.278817 +vn 0.701376 0.176153 0.690664 +vn 0.808008 0.000305 0.589129 +vn 0.766289 -0.015839 0.642262 +vn 0.690451 0.137425 0.710166 +vn 0.930479 -0.143223 0.337138 +vn 0.879299 0.032075 0.475112 +vn -0.701376 0.176153 0.690664 +vn -0.879299 0.032075 0.475112 +vn -0.930479 -0.143223 0.337138 +vn -0.690451 0.137425 0.710166 +vn -0.766289 -0.015839 0.642262 +vn -0.808008 0.000305 0.589129 +vn 0.634571 0.390851 0.666707 +vn 0.598041 0.631001 0.494095 +vn 0.923490 0.029298 0.382427 +vn 0.895505 0.003876 0.445021 +vn 0.697745 0.361339 0.618488 +vn 0.567370 0.646229 0.510300 +vn -0.634571 0.390851 0.666707 +vn -0.697745 0.361339 0.618488 +vn -0.895505 0.003876 0.445021 +vn -0.923490 0.029298 0.382427 +vn -0.598041 0.631001 0.494095 +vn -0.567370 0.646229 0.510300 +vn 0.859279 -0.428602 0.279122 +vn 0.799005 -0.537950 0.268654 +vn 0.724265 -0.574358 0.381481 +vn 0.768731 -0.471847 0.431684 +vn 0.885067 -0.408612 0.222755 +vn 0.912687 -0.390545 0.119999 +vn -0.859279 -0.428602 0.279122 +vn -0.912687 -0.390545 0.119999 +vn -0.885067 -0.408612 0.222755 +vn -0.768731 -0.471847 0.431684 +vn -0.724265 -0.574358 0.381481 +vn -0.799005 -0.537950 0.268654 +vn 0.690695 -0.430616 0.580920 +vn 0.618641 -0.408277 0.671194 +vn 0.845790 -0.350261 0.402387 +vn 0.698721 -0.538987 0.470351 +vn 0.689261 -0.521226 0.503159 +vn -0.690695 -0.430616 0.580920 +vn -0.698721 -0.538987 0.470351 +vn -0.845790 -0.350261 0.402387 +vn -0.618641 -0.408277 0.671194 +vn -0.689261 -0.521226 0.503159 +vn 0.607532 -0.405286 0.683096 +vn 0.694205 -0.520005 0.497635 +vn -0.607532 -0.405286 0.683096 +vn -0.694205 -0.520005 0.497635 +vn 0.982055 -0.147588 0.117283 +vn 0.952727 -0.303751 0.002106 +vn -0.982055 -0.147588 0.117283 +vn -0.952727 -0.303751 0.002106 +vn 0.926328 -0.372692 -0.054415 +vn 0.941984 -0.332560 -0.044923 +vn -0.926328 -0.372692 -0.054415 +vn -0.941984 -0.332560 -0.044923 +vn 0.977569 -0.182928 0.104068 +vn -0.977569 -0.182928 0.104068 +vn 0.707999 -0.549516 0.443525 +vn 0.690878 -0.544816 0.475173 +vn 0.714774 -0.555223 0.425184 +vn 0.584887 -0.375927 0.718680 +vn 0.609638 -0.346934 0.712699 +vn 0.619343 -0.281106 0.733055 +vn -0.707999 -0.549516 0.443525 +vn -0.609638 -0.346934 0.712699 +vn -0.584887 -0.375927 0.718680 +vn -0.714774 -0.555223 0.425184 +vn -0.690878 -0.544816 0.475173 +vn -0.619343 -0.281106 0.733055 +vn 0.705802 -0.572039 0.417829 +vn 0.687246 -0.607318 0.398541 +vn 0.475661 -0.408002 0.779260 +vn 0.536027 -0.392132 0.747581 +vn -0.705802 -0.572039 0.417829 +vn -0.536027 -0.392132 0.747581 +vn -0.475661 -0.408002 0.779260 +vn -0.687246 -0.607318 0.398541 +vn 0.730583 -0.570421 0.375225 +vn 0.885372 0.034120 0.463576 +vn 0.619587 -0.055605 0.782922 +vn 0.497299 -0.348430 0.794488 +vn -0.730583 -0.570421 0.375225 +vn -0.497299 -0.348430 0.794488 +vn -0.619587 -0.055605 0.782922 +vn -0.885372 0.034120 0.463576 +vn 0.570269 0.679434 0.461623 +vn 0.590411 0.667165 0.454146 +vn 0.422071 0.390790 0.817988 +vn 0.428846 0.399457 0.810205 +vn -0.570269 0.679434 0.461623 +vn -0.428846 0.399457 0.810205 +vn -0.422071 0.390790 0.817988 +vn -0.590411 0.667165 0.454146 +vn 0.795618 0.299814 0.526353 +vn 0.839259 -0.140477 0.525224 +vn 0.426160 0.141331 0.893521 +vn 0.512314 0.218146 0.830622 +vn -0.795618 0.299814 0.526353 +vn -0.512314 0.218146 0.830622 +vn -0.426160 0.141331 0.893521 +vn -0.839259 -0.140477 0.525224 +vn 0.811670 -0.029969 0.583300 +vn 0.569933 0.671621 0.473312 +vn 0.196142 0.751152 0.630299 +vn 0.401044 0.303232 0.864406 +vn -0.811670 -0.029969 0.583300 +vn -0.401044 0.303232 0.864406 +vn -0.196142 0.751152 0.630299 +vn -0.569933 0.671621 0.473312 +vn 0.020386 0.969848 0.242744 +vn 0.047304 0.951781 0.303079 +vn 0.115604 0.781182 0.613453 +vn -0.127476 0.869442 0.477248 +vn -0.020386 0.969848 0.242744 +vn 0.127476 0.869442 0.477248 +vn -0.115604 0.781182 0.613453 +vn -0.047304 0.951781 0.303079 +vn 0.638417 -0.564226 0.523484 +vn 0.522507 -0.634632 0.569353 +vn 0.593188 -0.200720 0.779626 +vn 0.527177 -0.185858 0.829157 +vn -0.638417 -0.564226 0.523484 +vn -0.593188 -0.200720 0.779626 +vn -0.522507 -0.634632 0.569353 +vn -0.527177 -0.185858 0.829157 +vn 0.311045 -0.738121 0.598621 +vn -0.181371 -0.756493 0.628285 +vn 0.399609 -0.227363 0.888028 +vn 0.221595 -0.208228 0.952635 +vn -0.311045 -0.738121 0.598621 +vn -0.399609 -0.227363 0.888028 +vn 0.181371 -0.756493 0.628285 +vn -0.221595 -0.208228 0.952635 +vn -0.682760 -0.473373 0.556536 +vn -0.892361 -0.070894 0.445692 +vn 0.053926 -0.077456 0.995514 +vn 0.008545 0.006623 0.999939 +vn 0.682760 -0.473373 0.556536 +vn -0.053926 -0.077456 0.995514 +vn 0.892361 -0.070894 0.445692 +vn -0.008545 0.006623 0.999939 +vn -0.846126 0.296640 0.442732 +vn -0.630207 0.621174 0.465773 +vn 0.063662 0.051057 0.996643 +vn 0.142338 0.143925 0.979278 +vn 0.846126 0.296640 0.442732 +vn -0.063662 0.051057 0.996643 +vn 0.630207 0.621174 0.465773 +vn -0.142338 0.143925 0.979278 +vn -0.330302 0.830805 0.447890 +vn -0.041536 0.910733 0.410840 +vn 0.250374 0.260567 0.932401 +vn 0.380749 0.392041 0.837428 +vn 0.330302 0.830805 0.447890 +vn -0.250374 0.260567 0.932401 +vn 0.041536 0.910733 0.410840 +vn -0.380749 0.392041 0.837428 +vn 0.115299 0.922727 0.367718 +vn 0.433882 0.528275 0.729820 +vn -0.115299 0.922727 0.367718 +vn -0.433882 0.528275 0.729820 +vn 0.190069 0.106021 0.976012 +vn 0.184973 0.080081 0.979461 +vn 0.071474 0.275521 0.958617 +vn 0.256203 0.189581 0.947844 +vn 0.223090 0.083560 0.971191 +vn 0.200720 0.009705 0.979583 +vn -0.190069 0.106021 0.976012 +vn -0.223090 0.083560 0.971191 +vn -0.256203 0.189581 0.947844 +vn -0.071474 0.275521 0.958617 +vn -0.184973 0.080081 0.979461 +vn -0.200720 0.009705 0.979583 +vn 0.330729 0.049165 0.942412 +vn 0.287027 0.000153 0.957884 +vn 0.426984 0.070040 0.901517 +vn 0.458724 -0.036988 0.887783 +vn 0.373791 -0.001068 0.927488 +vn 0.342174 -0.009735 0.939573 +vn -0.330729 0.049165 0.942412 +vn -0.373791 -0.001068 0.927488 +vn -0.458724 -0.036988 0.887783 +vn -0.426984 0.070040 0.901517 +vn -0.287027 0.000153 0.957884 +vn -0.342174 -0.009735 0.939573 +vn 0.358135 -0.030854 0.933134 +vn 0.353832 -0.002441 0.935270 +vn 0.421094 -0.110385 0.900235 +vn 0.385754 -0.160710 0.908475 +vn 0.308817 -0.040498 0.950255 +vn 0.319712 0.044679 0.946440 +vn -0.358135 -0.030854 0.933134 +vn -0.308817 -0.040498 0.950255 +vn -0.385754 -0.160710 0.908475 +vn -0.421094 -0.110385 0.900235 +vn -0.353832 -0.002441 0.935270 +vn -0.319712 0.044679 0.946440 +vn 0.319590 0.010529 0.947478 +vn 0.307443 0.165899 0.936979 +vn 0.417768 -0.135441 0.898373 +vn 0.496597 -0.014313 0.867855 +vn 0.432875 0.131718 0.891751 +vn 0.374279 0.302072 0.876705 +vn -0.319590 0.010529 0.947478 +vn -0.432875 0.131718 0.891751 +vn -0.496597 -0.014313 0.867855 +vn -0.417768 -0.135441 0.898373 +vn -0.307443 0.165899 0.936979 +vn -0.374279 0.302072 0.876705 +vn 0.404675 0.175359 0.897458 +vn 0.389996 0.311075 0.866665 +vn 0.435591 0.013337 0.900021 +vn -0.404675 0.175359 0.897458 +vn -0.435591 0.013337 0.900021 +vn -0.389996 0.311075 0.866665 +vn 0.431257 -0.077639 0.898862 +vn 0.386761 -0.107608 0.915860 +vn -0.431257 -0.077639 0.898862 +vn -0.386761 -0.107608 0.915860 +vn 0.310953 -0.111362 0.943846 +vn 0.221564 -0.101260 0.969848 +vn -0.310953 -0.111362 0.943846 +vn -0.221564 -0.101260 0.969848 +vn 0.209540 -0.015351 0.977660 +vn -0.209540 -0.015351 0.977660 +vn -0.088900 0.548936 0.831111 +vn 0.228919 0.393719 0.890255 +vn 0.088900 0.548936 0.831111 +vn -0.228919 0.393719 0.890255 +vn 0.514298 0.133152 0.847194 +vn 0.520341 -0.017182 0.853755 +vn -0.514298 0.133152 0.847194 +vn -0.520341 -0.017182 0.853755 +vn 0.454390 -0.122684 0.882290 +vn 0.441420 -0.177038 0.879635 +vn -0.454390 -0.122684 0.882290 +vn -0.441420 -0.177038 0.879635 +vn 0.484085 -0.142033 0.863399 +vn 0.520737 0.011444 0.853603 +vn -0.484085 -0.142033 0.863399 +vn -0.520737 0.011444 0.853603 +vn 0.492141 0.201575 0.846828 +vn 0.423444 0.324931 0.845637 +vn -0.492141 0.201575 0.846828 +vn -0.423444 0.324931 0.845637 +vn 0.392621 0.359020 0.846706 +vn -0.392621 0.359020 0.846706 +vn -0.026399 -0.935240 -0.352977 +vn 0.137211 -0.908963 -0.393567 +vn -0.098086 -0.943632 -0.316080 +vn -0.183935 -0.532579 -0.826136 +vn -0.344218 -0.434950 -0.832057 +vn -0.224647 -0.413709 -0.882229 +vn 0.026399 -0.935240 -0.352977 +vn 0.344218 -0.434950 -0.832026 +vn 0.183935 -0.532579 -0.826136 +vn 0.098086 -0.943632 -0.316080 +vn -0.137211 -0.908963 -0.393567 +vn 0.224647 -0.413709 -0.882229 +vn 0.424421 -0.837733 -0.343577 +vn 0.734916 -0.653279 -0.181860 +vn 0.031709 -0.412824 -0.910245 +vn 0.423048 -0.386883 -0.819330 +vn -0.424421 -0.837733 -0.343577 +vn -0.031709 -0.412824 -0.910245 +vn -0.734916 -0.653279 -0.181860 +vn -0.423048 -0.386914 -0.819330 +vn 0.952635 -0.293619 0.078890 +vn 0.984252 0.134922 0.114139 +vn 0.760125 -0.172033 -0.626545 +vn 0.931089 0.104984 -0.349315 +vn -0.952635 -0.293619 0.078890 +vn -0.760125 -0.172033 -0.626545 +vn -0.984252 0.134922 0.114139 +vn -0.931089 0.104984 -0.349284 +vn 0.799799 0.574877 -0.172643 +vn 0.294778 0.852626 -0.431379 +vn 0.620319 0.322001 -0.715171 +vn 0.097324 0.416272 -0.903989 +vn -0.799799 0.574877 -0.172643 +vn -0.620319 0.322001 -0.715171 +vn -0.294778 0.852626 -0.431379 +vn -0.097324 0.416272 -0.903989 +vn -0.187536 0.859859 -0.474776 +vn -0.405438 0.807031 -0.429273 +vn -0.277871 0.341594 -0.897824 +vn -0.439253 0.320627 -0.839167 +vn 0.187536 0.859859 -0.474776 +vn 0.277871 0.341594 -0.897824 +vn 0.405438 0.807031 -0.429273 +vn 0.439253 0.320627 -0.839167 +vn -0.505356 0.789941 -0.347209 +vn -0.597308 0.761711 -0.250954 +vn -0.515336 0.340556 -0.786401 +vn -0.456252 0.414350 -0.787469 +vn 0.505356 0.789941 -0.347209 +vn 0.515336 0.340556 -0.786401 +vn 0.597308 0.761711 -0.250954 +vn 0.456252 0.414350 -0.787469 +vn -0.434492 -0.022065 -0.900388 +vn -0.370830 -0.020356 -0.928465 +vn -0.142460 -0.078219 -0.986694 +vn 0.434492 -0.022065 -0.900388 +vn 0.142460 -0.078219 -0.986694 +vn 0.370830 -0.020356 -0.928465 +vn -0.210334 -0.024171 -0.977325 +vn 0.006409 -0.019349 -0.999786 +vn 0.210334 -0.024171 -0.977325 +vn -0.006409 -0.019349 -0.999786 +vn 0.483657 0.054659 -0.873531 +vn -0.483657 0.054659 -0.873531 +vn -0.350017 0.872494 -0.340922 +vn 0.213660 0.358959 -0.908536 +vn 0.350017 0.872494 -0.340922 +vn -0.213660 0.358959 -0.908536 +vn 0.348430 -0.203070 -0.915067 +vn 0.121982 -0.595965 -0.793664 +vn -0.348430 -0.203070 -0.915067 +vn -0.121982 -0.595965 -0.793664 +vn -0.093081 -0.918058 -0.385296 +vn 0.093081 -0.918058 -0.385296 +usemtl None +s 1 +f 1//1 504//2 1552//3 +f 1//1 1552//3 501//4 +f 1//1 501//4 1506//5 +f 1//1 1506//5 502//6 +f 1//1 502//6 1508//7 +f 1//1 1508//7 503//8 +f 1//1 503//8 1550//9 +f 1//1 1550//9 504//2 +f 2//10 508//11 1509//12 +f 2//10 1509//12 505//13 +f 2//10 505//13 1507//14 +f 2//10 1507//14 506//15 +f 2//10 506//15 1553//16 +f 2//10 1553//16 507//17 +f 2//10 507//17 1551//18 +f 2//10 1551//18 508//11 +f 3//19 511//20 1550//9 +f 3//19 1550//9 503//8 +f 3//19 503//8 1508//7 +f 3//19 1508//7 509//21 +f 3//19 509//21 1510//22 +f 3//19 1510//22 510//23 +f 3//19 510//23 1548//24 +f 3//19 1548//24 511//20 +f 4//25 514//26 1511//27 +f 4//25 1511//27 512//28 +f 4//25 512//28 1509//12 +f 4//25 1509//12 508//11 +f 4//25 508//11 1551//18 +f 4//25 1551//18 513//29 +f 4//25 513//29 1549//30 +f 4//25 1549//30 514//26 +f 5//31 509//21 1508//7 +f 5//31 1508//7 515//32 +f 5//31 515//32 1514//33 +f 5//31 1514//33 516//34 +f 5//31 516//34 1512//35 +f 5//31 1512//35 517//36 +f 5//31 517//36 1510//22 +f 5//31 1510//22 509//21 +f 6//37 520//38 1513//39 +f 6//37 1513//39 518//40 +f 6//37 518//40 1515//41 +f 6//37 1515//41 519//42 +f 6//37 519//42 1509//12 +f 6//37 1509//12 512//28 +f 6//37 512//28 1511//27 +f 6//37 1511//27 520//38 +f 7//43 502//6 1506//5 +f 7//43 1506//5 521//44 +f 7//43 521//44 1516//45 +f 7//43 1516//45 522//46 +f 7//43 522//46 1514//33 +f 7//43 1514//33 515//32 +f 7//43 515//32 1508//7 +f 7//43 1508//7 502//6 +f 8//47 519//42 1515//41 +f 8//47 1515//41 523//48 +f 8//47 523//48 1517//49 +f 8//47 1517//49 524//50 +f 8//47 524//50 1507//14 +f 8//47 1507//14 505//13 +f 8//47 505//13 1509//12 +f 8//47 1509//12 519//42 +f 9//51 522//46 1516//45 +f 9//51 1516//45 525//52 +f 9//51 525//52 1518//53 +f 9//51 1518//53 526//54 +f 9//51 526//54 1520//55 +f 9//51 1520//55 527//56 +f 9//51 527//56 1514//33 +f 9//51 1514//33 522//46 +f 10//57 530//58 1521//59 +f 10//57 1521//59 528//60 +f 10//57 528//60 1519//61 +f 10//57 1519//61 529//62 +f 10//57 529//62 1517//49 +f 10//57 1517//49 523//48 +f 10//57 523//48 1515//41 +f 10//57 1515//41 530//58 +f 11//63 516//34 1514//33 +f 11//63 1514//33 527//56 +f 11//63 527//56 1520//55 +f 11//63 1520//55 531//64 +f 11//63 531//64 1522//65 +f 11//63 1522//65 532//66 +f 11//63 532//66 1512//35 +f 11//63 1512//35 516//34 +f 12//67 534//68 1523//69 +f 12//67 1523//69 533//70 +f 12//67 533//70 1521//59 +f 12//67 1521//59 530//58 +f 12//67 530//58 1515//41 +f 12//67 1515//41 518//40 +f 12//67 518//40 1513//39 +f 12//67 1513//39 534//68 +f 13//71 531//64 1520//55 +f 13//71 1520//55 535//72 +f 13//71 535//72 1526//73 +f 13//71 1526//73 536//74 +f 13//71 536//74 1524//75 +f 13//71 1524//75 537//76 +f 13//71 537//76 1522//65 +f 13//71 1522//65 531//64 +f 14//77 540//78 1525//79 +f 14//77 1525//79 538//80 +f 14//77 538//80 1527//81 +f 14//77 1527//81 539//82 +f 14//77 539//82 1521//59 +f 14//77 1521//59 533//70 +f 14//77 533//70 1523//69 +f 14//77 1523//69 540//78 +f 15//83 526//54 1518//53 +f 15//83 1518//53 541//84 +f 15//83 541//84 1528//85 +f 15//83 1528//85 542//86 +f 15//83 542//86 1526//73 +f 15//83 1526//73 535//72 +f 15//83 535//72 1520//55 +f 15//83 1520//55 526//54 +f 16//87 539//82 1527//81 +f 16//87 1527//81 543//88 +f 16//87 543//88 1529//89 +f 16//87 1529//89 544//90 +f 16//87 544//90 1519//61 +f 16//87 1519//61 528//60 +f 16//87 528//60 1521//59 +f 16//87 1521//59 539//82 +f 17//91 542//86 1528//85 +f 17//91 1528//85 545//92 +f 17//91 545//92 1530//93 +f 17//91 1530//93 546//94 +f 17//91 546//94 1532//95 +f 17//91 1532//95 547//96 +f 17//91 547//96 1526//73 +f 17//91 1526//73 542//86 +f 18//97 550//98 1533//99 +f 18//97 1533//99 548//100 +f 18//97 548//100 1531//101 +f 18//97 1531//101 549//102 +f 18//97 549//102 1529//89 +f 18//97 1529//89 543//88 +f 18//97 543//88 1527//81 +f 18//97 1527//81 550//98 +f 19//103 536//74 1526//73 +f 19//103 1526//73 547//96 +f 19//103 547//96 1532//95 +f 19//103 1532//95 551//104 +f 19//103 551//104 1534//105 +f 19//103 1534//105 552//106 +f 19//103 552//106 1524//75 +f 19//103 1524//75 536//74 +f 20//107 554//108 1535//109 +f 20//107 1535//109 553//110 +f 20//107 553//110 1533//99 +f 20//107 1533//99 550//98 +f 20//107 550//98 1527//81 +f 20//107 1527//81 538//80 +f 20//107 538//80 1525//79 +f 20//107 1525//79 554//108 +f 21//111 551//104 1532//95 +f 21//111 1532//95 555//112 +f 21//111 555//112 1538//113 +f 21//111 1538//113 556//114 +f 21//111 556//114 1536//115 +f 21//111 1536//115 557//116 +f 21//111 557//116 1534//105 +f 21//111 1534//105 551//104 +f 22//117 560//118 1537//119 +f 22//117 1537//119 558//120 +f 22//117 558//120 1539//121 +f 22//117 1539//121 559//122 +f 22//117 559//122 1533//99 +f 22//117 1533//99 553//110 +f 22//117 553//110 1535//109 +f 22//117 1535//109 560//118 +f 23//123 546//94 1530//93 +f 23//123 1530//93 561//124 +f 23//123 561//124 1540//125 +f 23//123 1540//125 562//126 +f 23//123 562//126 1538//113 +f 23//123 1538//113 555//112 +f 23//123 555//112 1532//95 +f 23//123 1532//95 546//94 +f 24//127 559//122 1539//121 +f 24//127 1539//121 563//128 +f 24//127 563//128 1541//129 +f 24//127 1541//129 564//130 +f 24//127 564//130 1531//101 +f 24//127 1531//101 548//100 +f 24//127 548//100 1533//99 +f 24//127 1533//99 559//122 +f 25//131 562//126 1540//125 +f 25//131 1540//125 565//132 +f 25//131 565//132 1542//133 +f 25//131 1542//133 566//134 +f 25//131 566//134 1544//135 +f 25//131 1544//135 567//136 +f 25//131 567//136 1538//113 +f 25//131 1538//113 562//126 +f 26//137 570//138 1545//139 +f 26//137 1545//139 568//140 +f 26//137 568//140 1543//141 +f 26//137 1543//141 569//142 +f 26//137 569//142 1541//129 +f 26//137 1541//129 563//128 +f 26//137 563//128 1539//121 +f 26//137 1539//121 570//138 +f 27//143 556//114 1538//113 +f 27//143 1538//113 567//136 +f 27//143 567//136 1544//135 +f 27//143 1544//135 571//144 +f 27//143 571//144 1546//145 +f 27//143 1546//145 572//146 +f 27//143 572//146 1536//115 +f 27//143 1536//115 556//114 +f 28//147 574//148 1547//149 +f 28//147 1547//149 573//150 +f 28//147 573//150 1545//139 +f 28//147 1545//139 570//138 +f 28//147 570//138 1539//121 +f 28//147 1539//121 558//120 +f 28//147 558//120 1537//119 +f 28//147 1537//119 574//148 +f 29//151 571//144 1544//135 +f 29//151 1544//135 575//152 +f 29//151 575//152 1550//9 +f 29//151 1550//9 511//20 +f 29//151 511//20 1548//24 +f 29//151 1548//24 576//153 +f 29//151 576//153 1546//145 +f 29//151 1546//145 571//144 +f 30//154 578//155 1549//30 +f 30//154 1549//30 513//29 +f 30//154 513//29 1551//18 +f 30//154 1551//18 577//156 +f 30//154 577//156 1545//139 +f 30//154 1545//139 573//150 +f 30//154 573//150 1547//149 +f 30//154 1547//149 578//155 +f 31//157 566//134 1542//133 +f 31//157 1542//133 579//158 +f 31//157 579//158 1552//3 +f 31//157 1552//3 504//2 +f 31//157 504//2 1550//9 +f 31//157 1550//9 575//152 +f 31//157 575//152 1544//135 +f 31//157 1544//135 566//134 +f 32//159 577//156 1551//18 +f 32//159 1551//18 507//17 +f 32//159 507//17 1553//16 +f 32//159 1553//16 580//160 +f 32//159 580//160 1543//141 +f 32//159 1543//141 568//140 +f 32//159 568//140 1545//139 +f 32//159 1545//139 577//156 +f 33//161 583//162 1552//3 +f 33//161 1552//3 579//158 +f 33//161 579//158 1542//133 +f 33//161 1542//133 581//163 +f 33//161 581//163 1556//164 +f 33//161 1556//164 582//165 +f 33//161 582//165 1554//166 +f 33//161 1554//166 583//162 +f 34//167 586//168 1557//169 +f 34//167 1557//169 584//170 +f 34//167 584//170 1543//141 +f 34//167 1543//141 580//160 +f 34//167 580//160 1553//16 +f 34//167 1553//16 585//171 +f 34//167 585//171 1555//172 +f 34//167 1555//172 586//168 +f 35//173 581//163 1542//133 +f 35//173 1542//133 565//132 +f 35//173 565//132 1540//125 +f 35//173 1540//125 587//174 +f 35//173 587//174 1558//175 +f 35//173 1558//175 588//176 +f 35//173 588//176 1556//164 +f 35//173 1556//164 581//163 +f 36//177 590//178 1559//179 +f 36//177 1559//179 589//180 +f 36//177 589//180 1541//129 +f 36//177 1541//129 569//142 +f 36//177 569//142 1543//141 +f 36//177 1543//141 584//170 +f 36//177 584//170 1557//169 +f 36//177 1557//169 590//178 +f 37//181 587//174 1540//125 +f 37//181 1540//125 561//124 +f 37//181 561//124 1530//93 +f 37//181 1530//93 591//182 +f 37//181 591//182 1560//183 +f 37//181 1560//183 592//184 +f 37//181 592//184 1558//175 +f 37//181 1558//175 587//174 +f 38//185 594//186 1561//187 +f 38//185 1561//187 593//188 +f 38//185 593//188 1531//101 +f 38//185 1531//101 564//130 +f 38//185 564//130 1541//129 +f 38//185 1541//129 589//180 +f 38//185 589//180 1559//179 +f 38//185 1559//179 594//186 +f 39//189 591//182 1530//93 +f 39//189 1530//93 545//92 +f 39//189 545//92 1528//85 +f 39//189 1528//85 595//190 +f 39//189 595//190 1562//191 +f 39//189 1562//191 596//192 +f 39//189 596//192 1560//183 +f 39//189 1560//183 591//182 +f 40//193 598//194 1563//195 +f 40//193 1563//195 597//196 +f 40//193 597//196 1529//89 +f 40//193 1529//89 549//102 +f 40//193 549//102 1531//101 +f 40//193 1531//101 593//188 +f 40//193 593//188 1561//187 +f 40//193 1561//187 598//194 +f 41//197 595//190 1528//85 +f 41//197 1528//85 541//84 +f 41//197 541//84 1518//53 +f 41//197 1518//53 599//198 +f 41//197 599//198 1564//199 +f 41//197 1564//199 600//200 +f 41//197 600//200 1562//191 +f 41//197 1562//191 595//190 +f 42//201 602//202 1565//203 +f 42//201 1565//203 601//204 +f 42//201 601//204 1519//61 +f 42//201 1519//61 544//90 +f 42//201 544//90 1529//89 +f 42//201 1529//89 597//196 +f 42//201 597//196 1563//195 +f 42//201 1563//195 602//202 +f 43//205 599//198 1518//53 +f 43//205 1518//53 525//52 +f 43//205 525//52 1516//45 +f 43//205 1516//45 603//206 +f 43//205 603//206 1568//207 +f 43//205 1568//207 604//208 +f 43//205 604//208 1564//199 +f 43//205 1564//199 599//198 +f 44//209 606//210 1569//211 +f 44//209 1569//211 605//212 +f 44//209 605//212 1517//49 +f 44//209 1517//49 529//62 +f 44//209 529//62 1519//61 +f 44//209 1519//61 601//204 +f 44//209 601//204 1565//203 +f 44//209 1565//203 606//210 +f 45//213 603//206 1516//45 +f 45//213 1516//45 521//44 +f 45//213 521//44 1506//5 +f 45//213 1506//5 607//214 +f 45//213 607//214 1570//215 +f 45//213 1570//215 608//216 +f 45//213 608//216 1568//207 +f 45//213 1568//207 603//206 +f 46//217 610//218 1571//219 +f 46//217 1571//219 609//220 +f 46//217 609//220 1507//14 +f 46//217 1507//14 524//50 +f 46//217 524//50 1517//49 +f 46//217 1517//49 605//212 +f 46//217 605//212 1569//211 +f 46//217 1569//211 610//218 +f 47//221 607//214 1506//5 +f 47//221 1506//5 501//4 +f 47//221 501//4 1552//3 +f 47//221 1552//3 583//162 +f 47//221 583//162 1554//166 +f 47//221 1554//166 611//222 +f 47//221 611//222 1570//215 +f 47//221 1570//215 607//214 +f 48//223 612//224 1555//172 +f 48//223 1555//172 585//171 +f 48//223 585//171 1553//16 +f 48//223 1553//16 506//15 +f 48//223 506//15 1507//14 +f 48//223 1507//14 609//220 +f 48//223 609//220 1571//219 +f 48//223 1571//219 612//224 +f 49//225 614//226 1566//227 +f 49//225 1566//227 613//228 +f 49//225 613//228 1570//215 +f 49//225 1570//215 611//222 +f 49//225 611//222 1554//166 +f 49//225 1554//166 614//226 +f 50//229 616//230 1555//172 +f 50//229 1555//172 612//224 +f 50//229 612//224 1571//219 +f 50//229 1571//219 615//231 +f 50//229 615//231 1567//232 +f 50//229 1567//232 616//230 +f 51//233 617//234 1568//207 +f 51//233 1568//207 608//216 +f 51//233 608//216 1570//215 +f 51//233 1570//215 613//228 +f 51//233 613//228 1566//227 +f 51//233 1566//227 617//234 +f 52//235 618//236 1567//232 +f 52//235 1567//232 615//231 +f 52//235 615//231 1571//219 +f 52//235 1571//219 610//218 +f 52//235 610//218 1569//211 +f 52//235 1569//211 618//236 +f 53//237 617//234 1566//227 +f 53//237 1566//227 619//238 +f 53//237 619//238 1564//199 +f 53//237 1564//199 604//208 +f 53//237 604//208 1568//207 +f 53//237 1568//207 617//234 +f 54//239 618//236 1569//211 +f 54//239 1569//211 606//210 +f 54//239 606//210 1565//203 +f 54//239 1565//203 620//240 +f 54//239 620//240 1567//232 +f 54//239 1567//232 618//236 +f 55//241 619//238 1566//227 +f 55//241 1566//227 621//242 +f 55//241 621//242 1562//191 +f 55//241 1562//191 600//200 +f 55//241 600//200 1564//199 +f 55//241 1564//199 619//238 +f 56//243 620//240 1565//203 +f 56//243 1565//203 602//202 +f 56//243 602//202 1563//195 +f 56//243 1563//195 622//244 +f 56//243 622//244 1567//232 +f 56//243 1567//232 620//240 +f 57//245 621//242 1566//227 +f 57//245 1566//227 623//246 +f 57//245 623//246 1560//183 +f 57//245 1560//183 596//192 +f 57//245 596//192 1562//191 +f 57//245 1562//191 621//242 +f 58//247 622//244 1563//195 +f 58//247 1563//195 598//194 +f 58//247 598//194 1561//187 +f 58//247 1561//187 624//248 +f 58//247 624//248 1567//232 +f 58//247 1567//232 622//244 +f 59//249 623//246 1566//227 +f 59//249 1566//227 625//250 +f 59//249 625//250 1558//175 +f 59//249 1558//175 592//184 +f 59//249 592//184 1560//183 +f 59//249 1560//183 623//246 +f 60//251 624//248 1561//187 +f 60//251 1561//187 594//186 +f 60//251 594//186 1559//179 +f 60//251 1559//179 626//252 +f 60//251 626//252 1567//232 +f 60//251 1567//232 624//248 +f 61//253 625//250 1566//227 +f 61//253 1566//227 627//254 +f 61//253 627//254 1556//164 +f 61//253 1556//164 588//176 +f 61//253 588//176 1558//175 +f 61//253 1558//175 625//250 +f 62//255 626//252 1559//179 +f 62//255 1559//179 590//178 +f 62//255 590//178 1557//169 +f 62//255 1557//169 628//256 +f 62//255 628//256 1567//232 +f 62//255 1567//232 626//252 +f 63//257 627//254 1566//227 +f 63//257 1566//227 614//226 +f 63//257 614//226 1554//166 +f 63//257 1554//166 582//165 +f 63//257 582//165 1556//164 +f 63//257 1556//164 627//254 +f 64//258 628//256 1557//169 +f 64//258 1557//169 586//168 +f 64//258 586//168 1555//172 +f 64//258 1555//172 616//230 +f 64//258 616//230 1567//232 +f 64//258 1567//232 628//256 +f 65//259 632//260 1594//261 +f 65//259 1594//261 629//262 +f 65//259 629//262 1679//263 +f 65//259 1679//263 630//264 +f 65//259 630//264 1681//265 +f 65//259 1681//265 631//266 +f 65//259 631//266 1596//267 +f 65//259 1596//267 632//260 +f 66//268 631//266 1681//265 +f 66//268 1681//265 633//269 +f 66//268 633//269 1680//270 +f 66//268 1680//270 634//271 +f 66//268 634//271 1595//272 +f 66//268 1595//272 635//273 +f 66//268 635//273 1596//267 +f 66//268 1596//267 631//266 +f 67//274 638//275 1592//276 +f 67//274 1592//276 636//277 +f 67//274 636//277 1677//278 +f 67//274 1677//278 637//279 +f 67//274 637//279 1679//263 +f 67//274 1679//263 629//262 +f 67//274 629//262 1594//261 +f 67//274 1594//261 638//275 +f 68//280 634//271 1680//270 +f 68//280 1680//270 639//281 +f 68//280 639//281 1678//282 +f 68//280 1678//282 640//283 +f 68//280 640//283 1593//284 +f 68//280 1593//284 641//285 +f 68//280 641//285 1595//272 +f 68//280 1595//272 634//271 +f 69//286 644//287 1590//288 +f 69//286 1590//288 642//289 +f 69//286 642//289 1675//290 +f 69//286 1675//290 643//291 +f 69//286 643//291 1677//278 +f 69//286 1677//278 636//277 +f 69//286 636//277 1592//276 +f 69//286 1592//276 644//287 +f 70//292 640//283 1678//282 +f 70//292 1678//282 645//293 +f 70//292 645//293 1676//294 +f 70//292 1676//294 646//295 +f 70//292 646//295 1591//296 +f 70//292 1591//296 647//297 +f 70//292 647//297 1593//284 +f 70//292 1593//284 640//283 +f 71//298 650//299 1588//300 +f 71//298 1588//300 648//301 +f 71//298 648//301 1673//302 +f 71//298 1673//302 649//303 +f 71//298 649//303 1675//290 +f 71//298 1675//290 642//289 +f 71//298 642//289 1590//288 +f 71//298 1590//288 650//299 +f 72//304 646//295 1676//294 +f 72//304 1676//294 651//305 +f 72//304 651//305 1674//306 +f 72//304 1674//306 652//307 +f 72//304 652//307 1589//308 +f 72//304 1589//308 653//309 +f 72//304 653//309 1591//296 +f 72//304 1591//296 646//295 +f 73//310 656//311 1586//312 +f 73//310 1586//312 654//313 +f 73//310 654//313 1671//314 +f 73//310 1671//314 655//315 +f 73//310 655//315 1673//302 +f 73//310 1673//302 648//301 +f 73//310 648//301 1588//300 +f 73//310 1588//300 656//311 +f 74//316 652//307 1674//306 +f 74//316 1674//306 657//317 +f 74//316 657//317 1672//318 +f 74//316 1672//318 658//319 +f 74//316 658//319 1587//320 +f 74//316 1587//320 659//321 +f 74//316 659//321 1589//308 +f 74//316 1589//308 652//307 +f 75//322 663//323 1584//324 +f 75//322 1584//324 660//325 +f 75//322 660//325 1597//326 +f 75//322 1597//326 661//327 +f 75//322 661//327 1651//328 +f 75//322 1651//328 662//329 +f 75//322 662//329 1669//330 +f 75//322 1669//330 663//323 +f 76//331 667//332 1652//333 +f 76//331 1652//333 664//334 +f 76//331 664//334 1598//335 +f 76//331 1598//335 665//336 +f 76//331 665//336 1585//337 +f 76//331 1585//337 666//338 +f 76//331 666//338 1670//339 +f 76//331 1670//339 667//332 +f 77//340 661//327 1597//326 +f 77//340 1597//326 668//341 +f 77//340 668//341 1599//342 +f 77//340 1599//342 669//343 +f 77//340 669//343 1653//344 +f 77//340 1653//344 670//345 +f 77//340 670//345 1651//328 +f 77//340 1651//328 661//327 +f 78//346 673//347 1654//348 +f 78//346 1654//348 671//349 +f 78//346 671//349 1600//350 +f 78//346 1600//350 672//351 +f 78//346 672//351 1598//335 +f 78//346 1598//335 664//334 +f 78//346 664//334 1652//333 +f 78//346 1652//333 673//347 +f 79//352 669//343 1599//342 +f 79//352 1599//342 674//353 +f 79//352 674//353 1601//354 +f 79//352 1601//354 675//355 +f 79//352 675//355 1655//356 +f 79//352 1655//356 676//357 +f 79//352 676//357 1653//344 +f 79//352 1653//344 669//343 +f 80//358 679//359 1656//360 +f 80//358 1656//360 677//361 +f 80//358 677//361 1602//362 +f 80//358 1602//362 678//363 +f 80//358 678//363 1600//350 +f 80//358 1600//350 671//349 +f 80//358 671//349 1654//348 +f 80//358 1654//348 679//359 +f 81//364 675//355 1601//354 +f 81//364 1601//354 680//365 +f 81//364 680//365 1603//366 +f 81//364 1603//366 681//367 +f 81//364 681//367 1657//368 +f 81//364 1657//368 682//369 +f 81//364 682//369 1655//356 +f 81//364 1655//356 675//355 +f 82//370 685//371 1658//372 +f 82//370 1658//372 683//373 +f 82//370 683//373 1604//374 +f 82//370 1604//374 684//375 +f 82//370 684//375 1602//362 +f 82//370 1602//362 677//361 +f 82//370 677//361 1656//360 +f 82//370 1656//360 685//371 +f 83//376 681//367 1603//366 +f 83//376 1603//366 686//377 +f 83//376 686//377 1605//378 +f 83//376 1605//378 687//379 +f 83//376 687//379 1659//380 +f 83//376 1659//380 688//381 +f 83//376 688//381 1657//368 +f 83//376 1657//368 681//367 +f 84//382 691//383 1660//384 +f 84//382 1660//384 689//385 +f 84//382 689//385 1606//386 +f 84//382 1606//386 690//387 +f 84//382 690//387 1604//374 +f 84//382 1604//374 683//373 +f 84//382 683//373 1658//372 +f 84//382 1658//372 691//383 +f 85//388 687//379 1605//378 +f 85//388 1605//378 692//389 +f 85//388 692//389 1607//390 +f 85//388 1607//390 693//391 +f 85//388 693//391 1661//392 +f 85//388 1661//392 694//393 +f 85//388 694//393 1659//380 +f 85//388 1659//380 687//379 +f 86//394 697//395 1662//396 +f 86//394 1662//396 695//397 +f 86//394 695//397 1608//398 +f 86//394 1608//398 696//399 +f 86//394 696//399 1606//386 +f 86//394 1606//386 689//385 +f 86//394 689//385 1660//384 +f 86//394 1660//384 697//395 +f 87//400 693//391 1607//390 +f 87//400 1607//390 698//401 +f 87//400 698//401 1609//402 +f 87//400 1609//402 699//403 +f 87//400 699//403 1663//404 +f 87//400 1663//404 700//405 +f 87//400 700//405 1661//392 +f 87//400 1661//392 693//391 +f 88//406 703//407 1664//408 +f 88//406 1664//408 701//409 +f 88//406 701//409 1610//410 +f 88//406 1610//410 702//411 +f 88//406 702//411 1608//398 +f 88//406 1608//398 695//397 +f 88//406 695//397 1662//396 +f 88//406 1662//396 703//407 +f 89//412 699//403 1609//402 +f 89//412 1609//402 704//413 +f 89//412 704//413 1611//414 +f 89//412 1611//414 705//415 +f 89//412 705//415 1665//416 +f 89//412 1665//416 706//417 +f 89//412 706//417 1663//404 +f 89//412 1663//404 699//403 +f 90//418 709//419 1666//420 +f 90//418 1666//420 707//421 +f 90//418 707//421 1612//422 +f 90//418 1612//422 708//423 +f 90//418 708//423 1610//410 +f 90//418 1610//410 701//409 +f 90//418 701//409 1664//408 +f 90//418 1664//408 709//419 +f 91//424 705//415 1611//414 +f 91//424 1611//414 710//425 +f 91//424 710//425 1613//426 +f 91//424 1613//426 711//427 +f 91//424 711//427 1667//428 +f 91//424 1667//428 712//429 +f 91//424 712//429 1665//416 +f 91//424 1665//416 705//415 +f 92//430 715//431 1668//432 +f 92//430 1668//432 713//433 +f 92//430 713//433 1614//434 +f 92//430 1614//434 714//435 +f 92//430 714//435 1612//422 +f 92//430 1612//422 707//421 +f 92//430 707//421 1666//420 +f 92//430 1666//420 715//431 +f 93//436 711//427 1613//426 +f 93//436 1613//426 716//437 +f 93//436 716//437 1572//438 +f 93//436 1572//438 717//439 +f 93//436 717//439 1573//440 +f 93//436 1573//440 718//441 +f 93//436 718//441 1667//428 +f 93//436 1667//428 711//427 +f 94//442 720//443 1573//440 +f 94//442 1573//440 717//439 +f 94//442 717//439 1572//438 +f 94//442 1572//438 719//444 +f 94//442 719//444 1614//434 +f 94//442 1614//434 713//433 +f 94//442 713//433 1668//432 +f 94//442 1668//432 720//443 +f 95//445 723//446 1615//447 +f 95//445 1615//447 721//448 +f 95//445 721//448 1633//449 +f 95//445 1633//449 722//450 +f 95//445 722//450 1665//416 +f 95//445 1665//416 712//429 +f 95//445 712//429 1667//428 +f 95//445 1667//428 723//446 +f 96//451 715//431 1666//420 +f 96//451 1666//420 724//452 +f 96//451 724//452 1634//453 +f 96//451 1634//453 725//454 +f 96//451 725//454 1616//455 +f 96//451 1616//455 726//456 +f 96//451 726//456 1668//432 +f 96//451 1668//432 715//431 +f 97//457 722//450 1633//449 +f 97//457 1633//449 727//458 +f 97//457 727//458 1684//459 +f 97//457 1684//459 728//460 +f 97//457 728//460 1663//404 +f 97//457 1663//404 706//417 +f 97//457 706//417 1665//416 +f 97//457 1665//416 722//450 +f 98//461 709//419 1664//408 +f 98//461 1664//408 729//462 +f 98//461 729//462 1685//463 +f 98//461 1685//463 730//464 +f 98//461 730//464 1634//453 +f 98//461 1634//453 724//452 +f 98//461 724//452 1666//420 +f 98//461 1666//420 709//419 +f 99//465 732//466 1631//467 +f 99//465 1631//467 731//468 +f 99//465 731//468 1661//392 +f 99//465 1661//392 700//405 +f 99//465 700//405 1663//404 +f 99//465 1663//404 728//460 +f 99//465 728//460 1684//459 +f 99//465 1684//459 732//466 +f 100//469 729//462 1664//408 +f 100//469 1664//408 703//407 +f 100//469 703//407 1662//396 +f 100//469 1662//396 733//470 +f 100//469 733//470 1632//471 +f 100//469 1632//471 734//472 +f 100//469 734//472 1685//463 +f 100//469 1685//463 729//462 +f 101//473 736//474 1629//475 +f 101//473 1629//475 735//476 +f 101//473 735//476 1659//380 +f 101//473 1659//380 694//393 +f 101//473 694//393 1661//392 +f 101//473 1661//392 731//468 +f 101//473 731//468 1631//467 +f 101//473 1631//467 736//474 +f 102//477 733//470 1662//396 +f 102//477 1662//396 697//395 +f 102//477 697//395 1660//384 +f 102//477 1660//384 737//478 +f 102//477 737//478 1630//479 +f 102//477 1630//479 738//480 +f 102//477 738//480 1632//471 +f 102//477 1632//471 733//470 +f 103//481 740//482 1627//483 +f 103//481 1627//483 739//484 +f 103//481 739//484 1657//368 +f 103//481 1657//368 688//381 +f 103//481 688//381 1659//380 +f 103//481 1659//380 735//476 +f 103//481 735//476 1629//475 +f 103//481 1629//475 740//482 +f 104//485 737//478 1660//384 +f 104//485 1660//384 691//383 +f 104//485 691//383 1658//372 +f 104//485 1658//372 741//486 +f 104//485 741//486 1628//487 +f 104//485 1628//487 742//488 +f 104//485 742//488 1630//479 +f 104//485 1630//479 737//478 +f 105//489 744//490 1625//491 +f 105//489 1625//491 743//492 +f 105//489 743//492 1655//356 +f 105//489 1655//356 682//369 +f 105//489 682//369 1657//368 +f 105//489 1657//368 739//484 +f 105//489 739//484 1627//483 +f 105//489 1627//483 744//490 +f 106//493 741//486 1658//372 +f 106//493 1658//372 685//371 +f 106//493 685//371 1656//360 +f 106//493 1656//360 745//494 +f 106//493 745//494 1626//495 +f 106//493 1626//495 746//496 +f 106//493 746//496 1628//487 +f 106//493 1628//487 741//486 +f 107//497 748//498 1623//499 +f 107//497 1623//499 747//500 +f 107//497 747//500 1653//344 +f 107//497 1653//344 676//357 +f 107//497 676//357 1655//356 +f 107//497 1655//356 743//492 +f 107//497 743//492 1625//491 +f 107//497 1625//491 748//498 +f 108//501 745//494 1656//360 +f 108//501 1656//360 679//359 +f 108//501 679//359 1654//348 +f 108//501 1654//348 749//502 +f 108//501 749//502 1624//503 +f 108//501 1624//503 750//504 +f 108//501 750//504 1626//495 +f 108//501 1626//495 745//494 +f 109//505 752//506 1621//507 +f 109//505 1621//507 751//508 +f 109//505 751//508 1651//328 +f 109//505 1651//328 670//345 +f 109//505 670//345 1653//344 +f 109//505 1653//344 747//500 +f 109//505 747//500 1623//499 +f 109//505 1623//499 752//506 +f 110//509 749//502 1654//348 +f 110//509 1654//348 673//347 +f 110//509 673//347 1652//333 +f 110//509 1652//333 753//510 +f 110//509 753//510 1622//511 +f 110//509 1622//511 754//512 +f 110//509 754//512 1624//503 +f 110//509 1624//503 749//502 +f 111//513 756//514 1619//515 +f 111//513 1619//515 755//516 +f 111//513 755//516 1669//330 +f 111//513 1669//330 662//329 +f 111//513 662//329 1651//328 +f 111//513 1651//328 751//508 +f 111//513 751//508 1621//507 +f 111//513 1621//507 756//514 +f 112//517 753//510 1652//333 +f 112//517 1652//333 667//332 +f 112//517 667//332 1670//339 +f 112//517 1670//339 757//518 +f 112//517 757//518 1620//519 +f 112//517 1620//519 758//520 +f 112//517 758//520 1622//511 +f 112//517 1622//511 753//510 +f 113//521 755//516 1619//515 +f 113//521 1619//515 759//522 +f 113//521 759//522 1686//523 +f 113//521 1686//523 760//524 +f 113//521 760//524 1682//525 +f 113//521 1682//525 761//526 +f 113//521 761//526 1669//330 +f 113//521 1669//330 755//516 +f 114//527 764//528 1682//525 +f 114//527 1682//525 762//529 +f 114//527 762//529 1687//530 +f 114//527 1687//530 763//531 +f 114//527 763//531 1620//519 +f 114//527 1620//519 757//518 +f 114//527 757//518 1670//339 +f 114//527 1670//339 764//528 +f 115//532 766//533 1615//447 +f 115//532 1615//447 723//446 +f 115//532 723//446 1667//428 +f 115//532 1667//428 718//441 +f 115//532 718//441 1573//440 +f 115//532 1573//440 765//534 +f 115//532 765//534 1617//535 +f 115//532 1617//535 766//533 +f 116//536 768//537 1573//440 +f 116//536 1573//440 720//443 +f 116//536 720//443 1668//432 +f 116//536 1668//432 726//456 +f 116//536 726//456 1616//455 +f 116//536 1616//455 767//538 +f 116//536 767//538 1618//539 +f 116//536 1618//539 768//537 +f 117//540 771//541 1617//535 +f 117//540 1617//535 765//534 +f 117//540 765//534 1573//440 +f 117//540 1573//440 769//542 +f 117//540 769//542 1683//543 +f 117//540 1683//543 770//544 +f 117//540 770//544 1688//545 +f 117//540 1688//545 771//541 +f 118//546 773//547 1683//543 +f 118//546 1683//543 769//542 +f 118//546 769//542 1573//440 +f 118//546 1573//440 768//537 +f 118//546 768//537 1618//539 +f 118//546 1618//539 772//548 +f 118//546 772//548 1689//549 +f 118//546 1689//549 773//547 +f 119//550 775//551 1682//525 +f 119//550 1682//525 760//524 +f 119//550 760//524 1686//523 +f 119//550 1686//523 774//552 +f 119//550 774//552 1688//545 +f 119//550 1688//545 770//544 +f 119//550 770//544 1683//543 +f 119//550 1683//543 775//551 +f 120//553 773//547 1689//549 +f 120//553 1689//549 776//554 +f 120//553 776//554 1687//530 +f 120//553 1687//530 762//529 +f 120//553 762//529 1682//525 +f 120//553 1682//525 775//551 +f 120//553 775//551 1683//543 +f 120//553 1683//543 773//547 +f 121//555 779//556 1640//557 +f 121//555 1640//557 777//558 +f 121//555 777//558 1642//559 +f 121//555 1642//559 778//560 +f 121//555 778//560 1681//265 +f 121//555 1681//265 630//264 +f 121//555 630//264 1679//263 +f 121//555 1679//263 779//556 +f 122//561 633//269 1681//265 +f 122//561 1681//265 778//560 +f 122//561 778//560 1642//559 +f 122//561 1642//559 780//562 +f 122//561 780//562 1641//563 +f 122//561 1641//563 781//564 +f 122//561 781//564 1680//270 +f 122//561 1680//270 633//269 +f 123//565 783//566 1638//567 +f 123//565 1638//567 782//568 +f 123//565 782//568 1640//557 +f 123//565 1640//557 779//556 +f 123//565 779//556 1679//263 +f 123//565 1679//263 637//279 +f 123//565 637//279 1677//278 +f 123//565 1677//278 783//566 +f 124//569 639//281 1680//270 +f 124//569 1680//270 781//564 +f 124//569 781//564 1641//563 +f 124//569 1641//563 784//570 +f 124//569 784//570 1639//571 +f 124//569 1639//571 785//572 +f 124//569 785//572 1678//282 +f 124//569 1678//282 639//281 +f 125//573 787//574 1636//575 +f 125//573 1636//575 786//576 +f 125//573 786//576 1638//567 +f 125//573 1638//567 783//566 +f 125//573 783//566 1677//278 +f 125//573 1677//278 643//291 +f 125//573 643//291 1675//290 +f 125//573 1675//290 787//574 +f 126//577 645//293 1678//282 +f 126//577 1678//282 785//572 +f 126//577 785//572 1639//571 +f 126//577 1639//571 788//578 +f 126//577 788//578 1637//579 +f 126//577 1637//579 789//580 +f 126//577 789//580 1676//294 +f 126//577 1676//294 645//293 +f 127//581 655//315 1671//314 +f 127//581 1671//314 790//582 +f 127//581 790//582 1692//583 +f 127//581 1692//583 791//584 +f 127//581 791//584 1690//585 +f 127//581 1690//585 792//586 +f 127//581 792//586 1673//302 +f 127//581 1673//302 655//315 +f 128//587 795//588 1691//589 +f 128//587 1691//589 793//590 +f 128//587 793//590 1693//591 +f 128//587 1693//591 794//592 +f 128//587 794//592 1672//318 +f 128//587 1672//318 657//317 +f 128//587 657//317 1674//306 +f 128//587 1674//306 795//588 +f 129//593 796//594 1636//575 +f 129//593 1636//575 787//574 +f 129//593 787//574 1675//290 +f 129//593 1675//290 649//303 +f 129//593 649//303 1673//302 +f 129//593 1673//302 792//586 +f 129//593 792//586 1690//585 +f 129//593 1690//585 796//594 +f 130//595 795//588 1674//306 +f 130//595 1674//306 651//305 +f 130//595 651//305 1676//294 +f 130//595 1676//294 789//580 +f 130//595 789//580 1637//579 +f 130//595 1637//579 797//596 +f 130//595 797//596 1691//589 +f 130//595 1691//589 795//588 +f 131//597 801//598 1649//599 +f 131//597 1649//599 798//600 +f 131//597 798//600 1695//601 +f 131//597 1695//601 799//602 +f 131//597 799//602 1694//603 +f 131//597 1694//603 800//604 +f 131//597 800//604 1692//583 +f 131//597 1692//583 801//598 +f 132//605 804//606 1694//603 +f 132//605 1694//603 799//602 +f 132//605 799//602 1695//601 +f 132//605 1695//601 802//607 +f 132//605 802//607 1650//608 +f 132//605 1650//608 803//609 +f 132//605 803//609 1693//591 +f 132//605 1693//591 804//606 +f 133//610 806//611 1690//585 +f 133//610 1690//585 791//584 +f 133//610 791//584 1692//583 +f 133//610 1692//583 800//604 +f 133//610 800//604 1694//603 +f 133//610 1694//603 805//612 +f 133//610 805//612 1574//613 +f 133//610 1574//613 806//611 +f 134//614 805//612 1694//603 +f 134//614 1694//603 804//606 +f 134//614 804//606 1693//591 +f 134//614 1693//591 793//590 +f 134//614 793//590 1691//589 +f 134//614 1691//589 807//615 +f 134//614 807//615 1574//613 +f 134//614 1574//613 805//612 +f 135//616 809//617 1635//618 +f 135//616 1635//618 808//619 +f 135//616 808//619 1636//575 +f 135//616 1636//575 796//594 +f 135//616 796//594 1690//585 +f 135//616 1690//585 806//611 +f 135//616 806//611 1574//613 +f 135//616 1574//613 809//617 +f 136//620 807//615 1691//589 +f 136//620 1691//589 797//596 +f 136//620 797//596 1637//579 +f 136//620 1637//579 810//621 +f 136//620 810//621 1635//618 +f 136//620 1635//618 809//617 +f 136//620 809//617 1574//613 +f 136//620 1574//613 807//615 +f 137//622 814//623 1647//624 +f 137//622 1647//624 811//625 +f 137//622 811//625 1698//626 +f 137//622 1698//626 812//627 +f 137//622 812//627 1696//628 +f 137//622 1696//628 813//629 +f 137//622 813//629 1649//599 +f 137//622 1649//599 814//623 +f 138//630 818//631 1697//632 +f 138//630 1697//632 815//633 +f 138//630 815//633 1699//634 +f 138//630 1699//634 816//635 +f 138//630 816//635 1648//636 +f 138//630 1648//636 817//637 +f 138//630 817//637 1650//608 +f 138//630 1650//608 818//631 +f 139//638 821//639 1645//640 +f 139//638 1645//640 819//641 +f 139//638 819//641 1700//642 +f 139//638 1700//642 820//643 +f 139//638 820//643 1698//626 +f 139//638 1698//626 811//625 +f 139//638 811//625 1647//624 +f 139//638 1647//624 821//639 +f 140//644 816//635 1699//634 +f 140//644 1699//634 822//645 +f 140//644 822//645 1701//646 +f 140//644 1701//646 823//647 +f 140//644 823//647 1646//648 +f 140//644 1646//648 824//649 +f 140//644 824//649 1648//636 +f 140//644 1648//636 816//635 +f 141//650 827//651 1644//652 +f 141//650 1644//652 825//653 +f 141//650 825//653 1702//654 +f 141//650 1702//654 826//655 +f 141//650 826//655 1700//642 +f 141//650 1700//642 819//641 +f 141//650 819//641 1645//640 +f 141//650 1645//640 827//651 +f 142//656 823//647 1701//646 +f 142//656 1701//646 828//657 +f 142//656 828//657 1703//658 +f 142//656 1703//658 829//659 +f 142//656 829//659 1644//652 +f 142//656 1644//652 830//660 +f 142//656 830//660 1646//648 +f 142//656 1646//648 823//647 +f 143//661 833//662 1643//663 +f 143//661 1643//663 831//664 +f 143//661 831//664 1576//665 +f 143//661 1576//665 832//666 +f 143//661 832//666 1702//654 +f 143//661 1702//654 825//653 +f 143//661 825//653 1644//652 +f 143//661 1644//652 833//662 +f 144//667 829//659 1703//658 +f 144//667 1703//658 834//668 +f 144//667 834//668 1576//665 +f 144//667 1576//665 831//664 +f 144//667 831//664 1643//663 +f 144//667 1643//663 833//662 +f 144//667 833//662 1644//652 +f 144//667 1644//652 829//659 +f 145//669 836//670 1695//601 +f 145//669 1695//601 798//600 +f 145//669 798//600 1649//599 +f 145//669 1649//599 813//629 +f 145//669 813//629 1696//628 +f 145//669 1696//628 835//671 +f 145//669 835//671 1575//672 +f 145//669 1575//672 836//670 +f 146//673 837//674 1697//632 +f 146//673 1697//632 818//631 +f 146//673 818//631 1650//608 +f 146//673 1650//608 802//607 +f 146//673 802//607 1695//601 +f 146//673 1695//601 836//670 +f 146//673 836//670 1575//672 +f 146//673 1575//672 837//674 +f 147//675 840//676 1575//672 +f 147//675 1575//672 835//671 +f 147//675 835//671 1696//628 +f 147//675 1696//628 838//677 +f 147//675 838//677 1711//678 +f 147//675 1711//678 839//679 +f 147//675 839//679 1713//680 +f 147//675 1713//680 840//676 +f 148//681 842//682 1712//683 +f 148//681 1712//683 841//684 +f 148//681 841//684 1697//632 +f 148//681 1697//632 837//674 +f 148//681 837//674 1575//672 +f 148//681 1575//672 840//676 +f 148//681 840//676 1713//680 +f 148//681 1713//680 842//682 +f 149//685 832//666 1576//665 +f 149//685 1576//665 843//686 +f 149//685 843//686 1704//687 +f 149//685 1704//687 844//688 +f 149//685 844//688 1705//689 +f 149//685 1705//689 845//690 +f 149//685 845//690 1702//654 +f 149//685 1702//654 832//666 +f 150//691 847//692 1706//693 +f 150//691 1706//693 846//694 +f 150//691 846//694 1704//687 +f 150//691 1704//687 843//686 +f 150//691 843//686 1576//665 +f 150//691 1576//665 834//668 +f 150//691 834//668 1703//658 +f 150//691 1703//658 847//692 +f 151//695 826//655 1702//654 +f 151//695 1702//654 845//690 +f 151//695 845//690 1705//689 +f 151//695 1705//689 848//696 +f 151//695 848//696 1707//697 +f 151//695 1707//697 849//698 +f 151//695 849//698 1700//642 +f 151//695 1700//642 826//655 +f 152//699 851//700 1708//701 +f 152//699 1708//701 850//702 +f 152//699 850//702 1706//693 +f 152//699 1706//693 847//692 +f 152//699 847//692 1703//658 +f 152//699 1703//658 828//657 +f 152//699 828//657 1701//646 +f 152//699 1701//646 851//700 +f 153//703 820//643 1700//642 +f 153//703 1700//642 849//698 +f 153//703 849//698 1707//697 +f 153//703 1707//697 852//704 +f 153//703 852//704 1709//705 +f 153//703 1709//705 853//706 +f 153//703 853//706 1698//626 +f 153//703 1698//626 820//643 +f 154//707 855//708 1710//709 +f 154//707 1710//709 854//710 +f 154//707 854//710 1708//701 +f 154//707 1708//701 851//700 +f 154//707 851//700 1701//646 +f 154//707 1701//646 822//645 +f 154//707 822//645 1699//634 +f 154//707 1699//634 855//708 +f 155//711 812//627 1698//626 +f 155//711 1698//626 853//706 +f 155//711 853//706 1709//705 +f 155//711 1709//705 856//712 +f 155//711 856//712 1711//678 +f 155//711 1711//678 838//677 +f 155//711 838//677 1696//628 +f 155//711 1696//628 812//627 +f 156//713 841//684 1712//683 +f 156//713 1712//683 857//714 +f 156//713 857//714 1710//709 +f 156//713 1710//709 855//708 +f 156//713 855//708 1699//634 +f 156//713 1699//634 815//633 +f 156//713 815//633 1697//632 +f 156//713 1697//632 841//684 +f 157//715 844//688 1704//687 +f 157//715 1704//687 858//716 +f 157//715 858//716 1709//705 +f 157//715 1709//705 852//704 +f 157//715 852//704 1707//697 +f 157//715 1707//697 848//696 +f 157//715 848//696 1705//689 +f 157//715 1705//689 844//688 +f 158//717 850//702 1708//701 +f 158//717 1708//701 854//710 +f 158//717 854//710 1710//709 +f 158//717 1710//709 859//718 +f 158//717 859//718 1704//687 +f 158//717 1704//687 846//694 +f 158//717 846//694 1706//693 +f 158//717 1706//693 850//702 +f 159//719 858//716 1704//687 +f 159//719 1704//687 860//720 +f 159//719 860//720 1713//680 +f 159//719 1713//680 839//679 +f 159//719 839//679 1711//678 +f 159//719 1711//678 856//712 +f 159//719 856//712 1709//705 +f 159//719 1709//705 858//716 +f 160//721 857//714 1712//683 +f 160//721 1712//683 842//682 +f 160//721 842//682 1713//680 +f 160//721 1713//680 860//720 +f 160//721 860//720 1704//687 +f 160//721 1704//687 859//718 +f 160//721 859//718 1710//709 +f 160//721 1710//709 857//714 +f 161//722 862//723 1644//652 +f 161//722 1644//652 827//651 +f 161//722 827//651 1645//640 +f 161//722 1645//640 861//724 +f 161//722 861//724 1669//330 +f 161//722 1669//330 761//526 +f 161//722 761//526 1682//525 +f 161//722 1682//525 862//723 +f 162//725 764//528 1670//339 +f 162//725 1670//339 863//726 +f 162//725 863//726 1646//648 +f 162//725 1646//648 830//660 +f 162//725 830//660 1644//652 +f 162//725 1644//652 862//723 +f 162//725 862//723 1682//525 +f 162//725 1682//525 764//528 +f 163//727 861//724 1645//640 +f 163//727 1645//640 821//639 +f 163//727 821//639 1647//624 +f 163//727 1647//624 864//728 +f 163//727 864//728 1716//729 +f 163//727 1716//729 865//730 +f 163//727 865//730 1669//330 +f 163//727 1669//330 861//724 +f 164//731 867//732 1717//733 +f 164//731 1717//733 866//734 +f 164//731 866//734 1648//636 +f 164//731 1648//636 824//649 +f 164//731 824//649 1646//648 +f 164//731 1646//648 863//726 +f 164//731 863//726 1670//339 +f 164//731 1670//339 867//732 +f 165//735 864//728 1647//624 +f 165//735 1647//624 814//623 +f 165//735 814//623 1649//599 +f 165//735 1649//599 868//736 +f 165//735 868//736 1718//737 +f 165//735 1718//737 869//738 +f 165//735 869//738 1716//729 +f 165//735 1716//729 864//728 +f 166//739 871//740 1719//741 +f 166//739 1719//741 870//742 +f 166//739 870//742 1650//608 +f 166//739 1650//608 817//637 +f 166//739 817//637 1648//636 +f 166//739 1648//636 866//734 +f 166//739 866//734 1717//733 +f 166//739 1717//733 871//740 +f 167//743 868//736 1649//599 +f 167//743 1649//599 801//598 +f 167//743 801//598 1692//583 +f 167//743 1692//583 790//582 +f 167//743 790//582 1671//314 +f 167//743 1671//314 872//744 +f 167//743 872//744 1718//737 +f 167//743 1718//737 868//736 +f 168//745 873//746 1672//318 +f 168//745 1672//318 794//592 +f 168//745 794//592 1693//591 +f 168//745 1693//591 803//609 +f 168//745 803//609 1650//608 +f 168//745 1650//608 870//742 +f 168//745 870//742 1719//741 +f 168//745 1719//741 873//746 +f 169//747 654//313 1586//312 +f 169//747 1586//312 874//748 +f 169//747 874//748 1714//749 +f 169//747 1714//749 875//750 +f 169//747 875//750 1718//737 +f 169//747 1718//737 872//744 +f 169//747 872//744 1671//314 +f 169//747 1671//314 654//313 +f 170//751 873//746 1719//741 +f 170//751 1719//741 876//752 +f 170//751 876//752 1715//753 +f 170//751 1715//753 877//754 +f 170//751 877//754 1587//320 +f 170//751 1587//320 658//319 +f 170//751 658//319 1672//318 +f 170//751 1672//318 873//746 +f 171//755 875//750 1714//749 +f 171//755 1714//749 878//756 +f 171//755 878//756 1720//757 +f 171//755 1720//757 879//758 +f 171//755 879//758 1716//729 +f 171//755 1716//729 869//738 +f 171//755 869//738 1718//737 +f 171//755 1718//737 875//750 +f 172//759 871//740 1717//733 +f 172//759 1717//733 880//760 +f 172//759 880//760 1721//761 +f 172//759 1721//761 881//762 +f 172//759 881//762 1715//753 +f 172//759 1715//753 876//752 +f 172//759 876//752 1719//741 +f 172//759 1719//741 871//740 +f 173//763 882//764 1584//324 +f 173//763 1584//324 663//323 +f 173//763 663//323 1669//330 +f 173//763 1669//330 865//730 +f 173//763 865//730 1716//729 +f 173//763 1716//729 879//758 +f 173//763 879//758 1720//757 +f 173//763 1720//757 882//764 +f 174//765 880//760 1717//733 +f 174//765 1717//733 867//732 +f 174//765 867//732 1670//339 +f 174//765 1670//339 666//338 +f 174//765 666//338 1585//337 +f 174//765 1585//337 883//766 +f 174//765 883//766 1721//761 +f 174//765 1721//761 880//760 +f 175//767 886//768 1636//575 +f 175//767 1636//575 808//619 +f 175//767 808//619 1635//618 +f 175//767 1635//618 884//769 +f 175//767 884//769 1577//770 +f 175//767 1577//770 885//771 +f 175//767 885//771 1727//772 +f 175//767 1727//772 886//768 +f 176//773 888//774 1577//770 +f 176//773 1577//770 884//769 +f 176//773 884//769 1635//618 +f 176//773 1635//618 810//621 +f 176//773 810//621 1637//579 +f 176//773 1637//579 887//775 +f 176//773 887//775 1728//776 +f 176//773 1728//776 888//774 +f 177//777 890//778 1638//567 +f 177//777 1638//567 786//576 +f 177//777 786//576 1636//575 +f 177//777 1636//575 886//768 +f 177//777 886//768 1727//772 +f 177//777 1727//772 889//779 +f 177//777 889//779 1725//780 +f 177//777 1725//780 890//778 +f 178//781 892//782 1728//776 +f 178//781 1728//776 887//775 +f 178//781 887//775 1637//579 +f 178//781 1637//579 788//578 +f 178//781 788//578 1639//571 +f 178//781 1639//571 891//783 +f 178//781 891//783 1726//784 +f 178//781 1726//784 892//782 +f 179//785 894//786 1640//557 +f 179//785 1640//557 782//568 +f 179//785 782//568 1638//567 +f 179//785 1638//567 890//778 +f 179//785 890//778 1725//780 +f 179//785 1725//780 893//787 +f 179//785 893//787 1723//788 +f 179//785 1723//788 894//786 +f 180//789 896//790 1726//784 +f 180//789 1726//784 891//783 +f 180//789 891//783 1639//571 +f 180//789 1639//571 784//570 +f 180//789 784//570 1641//563 +f 180//789 1641//563 895//791 +f 180//789 895//791 1724//792 +f 180//789 1724//792 896//790 +f 181//793 898//794 1642//559 +f 181//793 1642//559 777//558 +f 181//793 777//558 1640//557 +f 181//793 1640//557 894//786 +f 181//793 894//786 1723//788 +f 181//793 1723//788 897//795 +f 181//793 897//795 1722//796 +f 181//793 1722//796 898//794 +f 182//797 899//798 1724//792 +f 182//797 1724//792 895//791 +f 182//797 895//791 1641//563 +f 182//797 1641//563 780//562 +f 182//797 780//562 1642//559 +f 182//797 1642//559 898//794 +f 182//797 898//794 1722//796 +f 182//797 1722//796 899//798 +f 183//799 902//800 1722//796 +f 183//799 1722//796 897//795 +f 183//799 897//795 1723//788 +f 183//799 1723//788 900//801 +f 183//799 900//801 1734//802 +f 183//799 1734//802 901//803 +f 183//799 901//803 1736//804 +f 183//799 1736//804 902//800 +f 184//805 904//806 1735//807 +f 184//805 1735//807 903//808 +f 184//805 903//808 1724//792 +f 184//805 1724//792 899//798 +f 184//805 899//798 1722//796 +f 184//805 1722//796 902//800 +f 184//805 902//800 1736//804 +f 184//805 1736//804 904//806 +f 185//809 900//801 1723//788 +f 185//809 1723//788 893//787 +f 185//809 893//787 1725//780 +f 185//809 1725//780 905//810 +f 185//809 905//810 1732//811 +f 185//809 1732//811 906//812 +f 185//809 906//812 1734//802 +f 185//809 1734//802 900//801 +f 186//813 908//814 1733//815 +f 186//813 1733//815 907//816 +f 186//813 907//816 1726//784 +f 186//813 1726//784 896//790 +f 186//813 896//790 1724//792 +f 186//813 1724//792 903//808 +f 186//813 903//808 1735//807 +f 186//813 1735//807 908//814 +f 187//817 905//810 1725//780 +f 187//817 1725//780 889//779 +f 187//817 889//779 1727//772 +f 187//817 1727//772 909//818 +f 187//817 909//818 1730//819 +f 187//817 1730//819 910//820 +f 187//817 910//820 1732//811 +f 187//817 1732//811 905//810 +f 188//821 912//822 1731//823 +f 188//821 1731//823 911//824 +f 188//821 911//824 1728//776 +f 188//821 1728//776 892//782 +f 188//821 892//782 1726//784 +f 188//821 1726//784 907//816 +f 188//821 907//816 1733//815 +f 188//821 1733//815 912//822 +f 189//825 909//818 1727//772 +f 189//825 1727//772 885//771 +f 189//825 885//771 1577//770 +f 189//825 1577//770 913//826 +f 189//825 913//826 1729//827 +f 189//825 1729//827 914//828 +f 189//825 914//828 1730//819 +f 189//825 1730//819 909//818 +f 190//829 915//830 1729//827 +f 190//829 1729//827 913//826 +f 190//829 913//826 1577//770 +f 190//829 1577//770 888//774 +f 190//829 888//774 1728//776 +f 190//829 1728//776 911//824 +f 190//829 911//824 1731//823 +f 190//829 1731//823 915//830 +f 191//831 914//828 1729//827 +f 191//831 1729//827 916//832 +f 191//831 916//832 1736//804 +f 191//831 1736//804 901//803 +f 191//831 901//803 1734//802 +f 191//831 1734//802 917//833 +f 191//831 917//833 1730//819 +f 191//831 1730//819 914//828 +f 192//834 918//835 1735//807 +f 192//834 1735//807 904//806 +f 192//834 904//806 1736//804 +f 192//834 1736//804 916//832 +f 192//834 916//832 1729//827 +f 192//834 1729//827 915//830 +f 192//834 915//830 1731//823 +f 192//834 1731//823 918//835 +f 193//836 910//820 1730//819 +f 193//836 1730//819 917//833 +f 193//836 917//833 1734//802 +f 193//836 1734//802 906//812 +f 193//836 906//812 1732//811 +f 193//836 1732//811 910//820 +f 194//837 912//822 1733//815 +f 194//837 1733//815 908//814 +f 194//837 908//814 1735//807 +f 194//837 1735//807 918//835 +f 194//837 918//835 1731//823 +f 194//837 1731//823 912//822 +f 195//838 921//839 1688//545 +f 195//838 1688//545 774//552 +f 195//838 774//552 1686//523 +f 195//838 1686//523 919//840 +f 195//838 919//840 1739//841 +f 195//838 1739//841 920//842 +f 195//838 920//842 1737//843 +f 195//838 1737//843 921//839 +f 196//844 924//845 1740//846 +f 196//844 1740//846 922//847 +f 196//844 922//847 1687//530 +f 196//844 1687//530 776//554 +f 196//844 776//554 1689//549 +f 196//844 1689//549 923//848 +f 196//844 923//848 1738//849 +f 196//844 1738//849 924//845 +f 197//850 926//851 1617//535 +f 197//850 1617//535 771//541 +f 197//850 771//541 1688//545 +f 197//850 1688//545 921//839 +f 197//850 921//839 1737//843 +f 197//850 1737//843 925//852 +f 197//850 925//852 1759//853 +f 197//850 1759//853 926//851 +f 198//854 928//855 1738//849 +f 198//854 1738//849 923//848 +f 198//854 923//848 1689//549 +f 198//854 1689//549 772//548 +f 198//854 772//548 1618//539 +f 198//854 1618//539 927//856 +f 198//854 927//856 1760//857 +f 198//854 1760//857 928//855 +f 199//858 930//859 1615//447 +f 199//858 1615//447 766//533 +f 199//858 766//533 1617//535 +f 199//858 1617//535 926//851 +f 199//858 926//851 1759//853 +f 199//858 1759//853 929//860 +f 199//858 929//860 1761//861 +f 199//858 1761//861 930//859 +f 200//862 932//863 1760//857 +f 200//862 1760//857 927//856 +f 200//862 927//856 1618//539 +f 200//862 1618//539 767//538 +f 200//862 767//538 1616//455 +f 200//862 1616//455 931//864 +f 200//862 931//864 1762//865 +f 200//862 1762//865 932//863 +f 201//866 919//840 1686//523 +f 201//866 1686//523 759//522 +f 201//866 759//522 1619//515 +f 201//866 1619//515 933//867 +f 201//866 933//867 1757//868 +f 201//866 1757//868 934//869 +f 201//866 934//869 1739//841 +f 201//866 1739//841 919//840 +f 202//870 936//871 1758//872 +f 202//870 1758//872 935//873 +f 202//870 935//873 1620//519 +f 202//870 1620//519 763//531 +f 202//870 763//531 1687//530 +f 202//870 1687//530 922//847 +f 202//870 922//847 1740//846 +f 202//870 1740//846 936//871 +f 203//874 933//867 1619//515 +f 203//874 1619//515 756//514 +f 203//874 756//514 1621//507 +f 203//874 1621//507 937//875 +f 203//874 937//875 1755//876 +f 203//874 1755//876 938//877 +f 203//874 938//877 1757//868 +f 203//874 1757//868 933//867 +f 204//878 940//879 1756//880 +f 204//878 1756//880 939//881 +f 204//878 939//881 1622//511 +f 204//878 1622//511 758//520 +f 204//878 758//520 1620//519 +f 204//878 1620//519 935//873 +f 204//878 935//873 1758//872 +f 204//878 1758//872 940//879 +f 205//882 937//875 1621//507 +f 205//882 1621//507 752//506 +f 205//882 752//506 1623//499 +f 205//882 1623//499 941//883 +f 205//882 941//883 1753//884 +f 205//882 1753//884 942//885 +f 205//882 942//885 1755//876 +f 205//882 1755//876 937//875 +f 206//886 944//887 1754//888 +f 206//886 1754//888 943//889 +f 206//886 943//889 1624//503 +f 206//886 1624//503 754//512 +f 206//886 754//512 1622//511 +f 206//886 1622//511 939//881 +f 206//886 939//881 1756//880 +f 206//886 1756//880 944//887 +f 207//890 941//883 1623//499 +f 207//890 1623//499 748//498 +f 207//890 748//498 1625//491 +f 207//890 1625//491 945//891 +f 207//890 945//891 1751//892 +f 207//890 1751//892 946//893 +f 207//890 946//893 1753//884 +f 207//890 1753//884 941//883 +f 208//894 948//895 1752//896 +f 208//894 1752//896 947//897 +f 208//894 947//897 1626//495 +f 208//894 1626//495 750//504 +f 208//894 750//504 1624//503 +f 208//894 1624//503 943//889 +f 208//894 943//889 1754//888 +f 208//894 1754//888 948//895 +f 209//898 945//891 1625//491 +f 209//898 1625//491 744//490 +f 209//898 744//490 1627//483 +f 209//898 1627//483 949//899 +f 209//898 949//899 1749//900 +f 209//898 1749//900 950//901 +f 209//898 950//901 1751//892 +f 209//898 1751//892 945//891 +f 210//902 952//903 1750//904 +f 210//902 1750//904 951//905 +f 210//902 951//905 1628//487 +f 210//902 1628//487 746//496 +f 210//902 746//496 1626//495 +f 210//902 1626//495 947//897 +f 210//902 947//897 1752//896 +f 210//902 1752//896 952//903 +f 211//906 949//899 1627//483 +f 211//906 1627//483 740//482 +f 211//906 740//482 1629//475 +f 211//906 1629//475 953//907 +f 211//906 953//907 1747//908 +f 211//906 1747//908 954//909 +f 211//906 954//909 1749//900 +f 211//906 1749//900 949//899 +f 212//910 956//911 1748//912 +f 212//910 1748//912 955//913 +f 212//910 955//913 1630//479 +f 212//910 1630//479 742//488 +f 212//910 742//488 1628//487 +f 212//910 1628//487 951//905 +f 212//910 951//905 1750//904 +f 212//910 1750//904 956//911 +f 213//914 953//907 1629//475 +f 213//914 1629//475 736//474 +f 213//914 736//474 1631//467 +f 213//914 1631//467 957//915 +f 213//914 957//915 1745//916 +f 213//914 1745//916 958//917 +f 213//914 958//917 1747//908 +f 213//914 1747//908 953//907 +f 214//918 960//919 1746//920 +f 214//918 1746//920 959//921 +f 214//918 959//921 1632//471 +f 214//918 1632//471 738//480 +f 214//918 738//480 1630//479 +f 214//918 1630//479 955//913 +f 214//918 955//913 1748//912 +f 214//918 1748//912 960//919 +f 215//922 957//915 1631//467 +f 215//922 1631//467 732//466 +f 215//922 732//466 1684//459 +f 215//922 1684//459 961//923 +f 215//922 961//923 1741//924 +f 215//922 1741//924 962//925 +f 215//922 962//925 1745//916 +f 215//922 1745//916 957//915 +f 216//926 964//927 1742//928 +f 216//926 1742//928 963//929 +f 216//926 963//929 1685//463 +f 216//926 1685//463 734//472 +f 216//926 734//472 1632//471 +f 216//926 1632//471 959//921 +f 216//926 959//921 1746//920 +f 216//926 1746//920 964//927 +f 217//930 961//923 1684//459 +f 217//930 1684//459 727//458 +f 217//930 727//458 1633//449 +f 217//930 1633//449 965//931 +f 217//930 965//931 1743//932 +f 217//930 1743//932 966//933 +f 217//930 966//933 1741//924 +f 217//930 1741//924 961//923 +f 218//934 968//935 1744//936 +f 218//934 1744//936 967//937 +f 218//934 967//937 1634//453 +f 218//934 1634//453 730//464 +f 218//934 730//464 1685//463 +f 218//934 1685//463 963//929 +f 218//934 963//929 1742//928 +f 218//934 1742//928 968//935 +f 219//938 965//931 1633//449 +f 219//938 1633//449 721//448 +f 219//938 721//448 1615//447 +f 219//938 1615//447 930//859 +f 219//938 930//859 1761//861 +f 219//938 1761//861 969//939 +f 219//938 969//939 1743//932 +f 219//938 1743//932 965//931 +f 220//940 970//941 1762//865 +f 220//940 1762//865 931//864 +f 220//940 931//864 1616//455 +f 220//940 1616//455 725//454 +f 220//940 725//454 1634//453 +f 220//940 1634//453 967//937 +f 220//940 967//937 1744//936 +f 220//940 1744//936 970//941 +f 221//942 973//943 1743//932 +f 221//942 1743//932 969//939 +f 221//942 969//939 1761//861 +f 221//942 1761//861 971//944 +f 221//942 971//944 1763//945 +f 221//942 1763//945 972//946 +f 221//942 972//946 1781//947 +f 221//942 1781//947 973//943 +f 222//948 976//949 1764//950 +f 222//948 1764//950 974//951 +f 222//948 974//951 1762//865 +f 222//948 1762//865 970//941 +f 222//948 970//941 1744//936 +f 222//948 1744//936 975//952 +f 222//948 975//952 1782//953 +f 222//948 1782//953 976//949 +f 223//954 978//955 1741//924 +f 223//954 1741//924 966//933 +f 223//954 966//933 1743//932 +f 223//954 1743//932 973//943 +f 223//954 973//943 1781//947 +f 223//954 1781//947 977//956 +f 223//954 977//956 1783//957 +f 223//954 1783//957 978//955 +f 224//958 980//959 1782//953 +f 224//958 1782//953 975//952 +f 224//958 975//952 1744//936 +f 224//958 1744//936 968//935 +f 224//958 968//935 1742//928 +f 224//958 1742//928 979//960 +f 224//958 979//960 1784//961 +f 224//958 1784//961 980//959 +f 225//962 982//963 1745//916 +f 225//962 1745//916 962//925 +f 225//962 962//925 1741//924 +f 225//962 1741//924 978//955 +f 225//962 978//955 1783//957 +f 225//962 1783//957 981//964 +f 225//962 981//964 1779//965 +f 225//962 1779//965 982//963 +f 226//966 984//967 1784//961 +f 226//966 1784//961 979//960 +f 226//966 979//960 1742//928 +f 226//966 1742//928 964//927 +f 226//966 964//927 1746//920 +f 226//966 1746//920 983//968 +f 226//966 983//968 1780//969 +f 226//966 1780//969 984//967 +f 227//970 986//971 1747//908 +f 227//970 1747//908 958//917 +f 227//970 958//917 1745//916 +f 227//970 1745//916 982//963 +f 227//970 982//963 1779//965 +f 227//970 1779//965 985//972 +f 227//970 985//972 1777//973 +f 227//970 1777//973 986//971 +f 228//974 988//975 1780//969 +f 228//974 1780//969 983//968 +f 228//974 983//968 1746//920 +f 228//974 1746//920 960//919 +f 228//974 960//919 1748//912 +f 228//974 1748//912 987//976 +f 228//974 987//976 1778//977 +f 228//974 1778//977 988//975 +f 229//978 990//979 1749//900 +f 229//978 1749//900 954//909 +f 229//978 954//909 1747//908 +f 229//978 1747//908 986//971 +f 229//978 986//971 1777//973 +f 229//978 1777//973 989//980 +f 229//978 989//980 1775//981 +f 229//978 1775//981 990//979 +f 230//982 992//983 1778//977 +f 230//982 1778//977 987//976 +f 230//982 987//976 1748//912 +f 230//982 1748//912 956//911 +f 230//982 956//911 1750//904 +f 230//982 1750//904 991//984 +f 230//982 991//984 1776//985 +f 230//982 1776//985 992//983 +f 231//986 994//987 1751//892 +f 231//986 1751//892 950//901 +f 231//986 950//901 1749//900 +f 231//986 1749//900 990//979 +f 231//986 990//979 1775//981 +f 231//986 1775//981 993//988 +f 231//986 993//988 1773//989 +f 231//986 1773//989 994//987 +f 232//990 996//991 1776//985 +f 232//990 1776//985 991//984 +f 232//990 991//984 1750//904 +f 232//990 1750//904 952//903 +f 232//990 952//903 1752//896 +f 232//990 1752//896 995//992 +f 232//990 995//992 1774//993 +f 232//990 1774//993 996//991 +f 233//994 998//995 1753//884 +f 233//994 1753//884 946//893 +f 233//994 946//893 1751//892 +f 233//994 1751//892 994//987 +f 233//994 994//987 1773//989 +f 233//994 1773//989 997//996 +f 233//994 997//996 1771//997 +f 233//994 1771//997 998//995 +f 234//998 1000//999 1774//993 +f 234//998 1774//993 995//992 +f 234//998 995//992 1752//896 +f 234//998 1752//896 948//895 +f 234//998 948//895 1754//888 +f 234//998 1754//888 999//1000 +f 234//998 999//1000 1772//1001 +f 234//998 1772//1001 1000//999 +f 235//1002 1002//1003 1755//876 +f 235//1002 1755//876 942//885 +f 235//1002 942//885 1753//884 +f 235//1002 1753//884 998//995 +f 235//1002 998//995 1771//997 +f 235//1002 1771//997 1001//1004 +f 235//1002 1001//1004 1769//1005 +f 235//1002 1769//1005 1002//1003 +f 236//1006 1004//1007 1772//1001 +f 236//1006 1772//1001 999//1000 +f 236//1006 999//1000 1754//888 +f 236//1006 1754//888 944//887 +f 236//1006 944//887 1756//880 +f 236//1006 1756//880 1003//1008 +f 236//1006 1003//1008 1770//1009 +f 236//1006 1770//1009 1004//1007 +f 237//1010 1006//1011 1757//868 +f 237//1010 1757//868 938//877 +f 237//1010 938//877 1755//876 +f 237//1010 1755//876 1002//1003 +f 237//1010 1002//1003 1769//1005 +f 237//1010 1769//1005 1005//1012 +f 237//1010 1005//1012 1767//1013 +f 237//1010 1767//1013 1006//1011 +f 238//1014 1008//1015 1770//1009 +f 238//1014 1770//1009 1003//1008 +f 238//1014 1003//1008 1756//880 +f 238//1014 1756//880 940//879 +f 238//1014 940//879 1758//872 +f 238//1014 1758//872 1007//1016 +f 238//1014 1007//1016 1768//1017 +f 238//1014 1768//1017 1008//1015 +f 239//1018 1010//1019 1739//841 +f 239//1018 1739//841 934//869 +f 239//1018 934//869 1757//868 +f 239//1018 1757//868 1006//1011 +f 239//1018 1006//1011 1767//1013 +f 239//1018 1767//1013 1009//1020 +f 239//1018 1009//1020 1785//1021 +f 239//1018 1785//1021 1010//1019 +f 240//1022 1012//1023 1768//1017 +f 240//1022 1768//1017 1007//1016 +f 240//1022 1007//1016 1758//872 +f 240//1022 1758//872 936//871 +f 240//1022 936//871 1740//846 +f 240//1022 1740//846 1011//1024 +f 240//1022 1011//1024 1786//1025 +f 240//1022 1786//1025 1012//1023 +f 241//1026 971//944 1761//861 +f 241//1026 1761//861 929//860 +f 241//1026 929//860 1759//853 +f 241//1026 1759//853 1013//1027 +f 241//1026 1013//1027 1765//1028 +f 241//1026 1765//1028 1014//1029 +f 241//1026 1014//1029 1763//945 +f 241//1026 1763//945 971//944 +f 242//1030 1016//1031 1766//1032 +f 242//1030 1766//1032 1015//1033 +f 242//1030 1015//1033 1760//857 +f 242//1030 1760//857 932//863 +f 242//1030 932//863 1762//865 +f 242//1030 1762//865 974//951 +f 242//1030 974//951 1764//950 +f 242//1030 1764//950 1016//1031 +f 243//1034 1013//1027 1759//853 +f 243//1034 1759//853 925//852 +f 243//1034 925//852 1737//843 +f 243//1034 1737//843 1017//1035 +f 243//1034 1017//1035 1787//1036 +f 243//1034 1787//1036 1018//1037 +f 243//1034 1018//1037 1765//1028 +f 243//1034 1765//1028 1013//1027 +f 244//1038 1020//1039 1788//1040 +f 244//1038 1788//1040 1019//1041 +f 244//1038 1019//1041 1738//849 +f 244//1038 1738//849 928//855 +f 244//1038 928//855 1760//857 +f 244//1038 1760//857 1015//1033 +f 244//1038 1015//1033 1766//1032 +f 244//1038 1766//1032 1020//1039 +f 245//1042 1017//1035 1737//843 +f 245//1042 1737//843 920//842 +f 245//1042 920//842 1739//841 +f 245//1042 1739//841 1010//1019 +f 245//1042 1010//1019 1785//1021 +f 245//1042 1785//1021 1021//1043 +f 245//1042 1021//1043 1787//1036 +f 245//1042 1787//1036 1017//1035 +f 246//1044 1022//1045 1786//1025 +f 246//1044 1786//1025 1011//1024 +f 246//1044 1011//1024 1740//846 +f 246//1044 1740//846 924//845 +f 246//1044 924//845 1738//849 +f 246//1044 1738//849 1019//1041 +f 246//1044 1019//1041 1788//1040 +f 246//1044 1788//1040 1022//1045 +f 247//1046 1025//1047 1572//438 +f 247//1046 1572//438 716//437 +f 247//1046 716//437 1613//426 +f 247//1046 1613//426 1023//1048 +f 247//1046 1023//1048 1789//1049 +f 247//1046 1789//1049 1024//1050 +f 247//1046 1024//1050 1578//1051 +f 247//1046 1578//1051 1025//1047 +f 248//1052 1027//1053 1790//1054 +f 248//1052 1790//1054 1026//1055 +f 248//1052 1026//1055 1614//434 +f 248//1052 1614//434 719//444 +f 248//1052 719//444 1572//438 +f 248//1052 1572//438 1025//1047 +f 248//1052 1025//1047 1578//1051 +f 248//1052 1578//1051 1027//1053 +f 249//1056 1023//1048 1613//426 +f 249//1056 1613//426 710//425 +f 249//1056 710//425 1611//414 +f 249//1056 1611//414 1028//1057 +f 249//1056 1028//1057 1791//1058 +f 249//1056 1791//1058 1029//1059 +f 249//1056 1029//1059 1789//1049 +f 249//1056 1789//1049 1023//1048 +f 250//1060 1031//1061 1792//1062 +f 250//1060 1792//1062 1030//1063 +f 250//1060 1030//1063 1612//422 +f 250//1060 1612//422 714//435 +f 250//1060 714//435 1614//434 +f 250//1060 1614//434 1026//1055 +f 250//1060 1026//1055 1790//1054 +f 250//1060 1790//1054 1031//1061 +f 251//1064 1028//1057 1611//414 +f 251//1064 1611//414 704//413 +f 251//1064 704//413 1609//402 +f 251//1064 1609//402 1032//1065 +f 251//1064 1032//1065 1793//1066 +f 251//1064 1793//1066 1033//1067 +f 251//1064 1033//1067 1791//1058 +f 251//1064 1791//1058 1028//1057 +f 252//1068 1035//1069 1794//1070 +f 252//1068 1794//1070 1034//1071 +f 252//1068 1034//1071 1610//410 +f 252//1068 1610//410 708//423 +f 252//1068 708//423 1612//422 +f 252//1068 1612//422 1030//1063 +f 252//1068 1030//1063 1792//1062 +f 252//1068 1792//1062 1035//1069 +f 253//1072 1032//1065 1609//402 +f 253//1072 1609//402 698//401 +f 253//1072 698//401 1607//390 +f 253//1072 1607//390 1036//1073 +f 253//1072 1036//1073 1795//1074 +f 253//1072 1795//1074 1037//1075 +f 253//1072 1037//1075 1793//1066 +f 253//1072 1793//1066 1032//1065 +f 254//1076 1039//1077 1796//1078 +f 254//1076 1796//1078 1038//1079 +f 254//1076 1038//1079 1608//398 +f 254//1076 1608//398 702//411 +f 254//1076 702//411 1610//410 +f 254//1076 1610//410 1034//1071 +f 254//1076 1034//1071 1794//1070 +f 254//1076 1794//1070 1039//1077 +f 255//1080 1036//1073 1607//390 +f 255//1080 1607//390 692//389 +f 255//1080 692//389 1605//378 +f 255//1080 1605//378 1040//1081 +f 255//1080 1040//1081 1797//1082 +f 255//1080 1797//1082 1041//1083 +f 255//1080 1041//1083 1795//1074 +f 255//1080 1795//1074 1036//1073 +f 256//1084 1043//1085 1798//1086 +f 256//1084 1798//1086 1042//1087 +f 256//1084 1042//1087 1606//386 +f 256//1084 1606//386 696//399 +f 256//1084 696//399 1608//398 +f 256//1084 1608//398 1038//1079 +f 256//1084 1038//1079 1796//1078 +f 256//1084 1796//1078 1043//1085 +f 257//1088 1040//1081 1605//378 +f 257//1088 1605//378 686//377 +f 257//1088 686//377 1603//366 +f 257//1088 1603//366 1044//1089 +f 257//1088 1044//1089 1799//1090 +f 257//1088 1799//1090 1045//1091 +f 257//1088 1045//1091 1797//1082 +f 257//1088 1797//1082 1040//1081 +f 258//1092 1047//1093 1800//1094 +f 258//1092 1800//1094 1046//1095 +f 258//1092 1046//1095 1604//374 +f 258//1092 1604//374 690//387 +f 258//1092 690//387 1606//386 +f 258//1092 1606//386 1042//1087 +f 258//1092 1042//1087 1798//1086 +f 258//1092 1798//1086 1047//1093 +f 259//1096 1044//1089 1603//366 +f 259//1096 1603//366 680//365 +f 259//1096 680//365 1601//354 +f 259//1096 1601//354 1048//1097 +f 259//1096 1048//1097 1801//1098 +f 259//1096 1801//1098 1049//1099 +f 259//1096 1049//1099 1799//1090 +f 259//1096 1799//1090 1044//1089 +f 260//1100 1051//1101 1802//1102 +f 260//1100 1802//1102 1050//1103 +f 260//1100 1050//1103 1602//362 +f 260//1100 1602//362 684//375 +f 260//1100 684//375 1604//374 +f 260//1100 1604//374 1046//1095 +f 260//1100 1046//1095 1800//1094 +f 260//1100 1800//1094 1051//1101 +f 261//1104 1048//1097 1601//354 +f 261//1104 1601//354 674//353 +f 261//1104 674//353 1599//342 +f 261//1104 1599//342 1052//1105 +f 261//1104 1052//1105 1803//1106 +f 261//1104 1803//1106 1053//1107 +f 261//1104 1053//1107 1801//1098 +f 261//1104 1801//1098 1048//1097 +f 262//1108 1055//1109 1804//1110 +f 262//1108 1804//1110 1054//1111 +f 262//1108 1054//1111 1600//350 +f 262//1108 1600//350 678//363 +f 262//1108 678//363 1602//362 +f 262//1108 1602//362 1050//1103 +f 262//1108 1050//1103 1802//1102 +f 262//1108 1802//1102 1055//1109 +f 263//1112 1052//1105 1599//342 +f 263//1112 1599//342 668//341 +f 263//1112 668//341 1597//326 +f 263//1112 1597//326 1056//1113 +f 263//1112 1056//1113 1805//1114 +f 263//1112 1805//1114 1057//1115 +f 263//1112 1057//1115 1803//1106 +f 263//1112 1803//1106 1052//1105 +f 264//1116 1059//1117 1806//1118 +f 264//1116 1806//1118 1058//1119 +f 264//1116 1058//1119 1598//335 +f 264//1116 1598//335 672//351 +f 264//1116 672//351 1600//350 +f 264//1116 1600//350 1054//1111 +f 264//1116 1054//1111 1804//1110 +f 264//1116 1804//1110 1059//1117 +f 265//1120 1063//1121 1813//1122 +f 265//1120 1813//1122 1060//1123 +f 265//1120 1060//1123 1814//1124 +f 265//1120 1814//1124 1061//1125 +f 265//1120 1061//1125 1833//1126 +f 265//1120 1833//1126 1062//1127 +f 265//1120 1062//1127 1843//1128 +f 265//1120 1843//1128 1063//1121 +f 266//1129 1066//1130 1834//1131 +f 266//1129 1834//1131 1064//1132 +f 266//1129 1064//1132 1814//1124 +f 266//1129 1814//1124 1060//1123 +f 266//1129 1060//1123 1813//1122 +f 266//1129 1813//1122 1065//1133 +f 266//1129 1065//1133 1844//1134 +f 266//1129 1844//1134 1066//1130 +f 267//1135 1069//1136 1812//1137 +f 267//1135 1812//1137 1067//1138 +f 267//1135 1067//1138 1813//1122 +f 267//1135 1813//1122 1063//1121 +f 267//1135 1063//1121 1843//1128 +f 267//1135 1843//1128 1068//1139 +f 267//1135 1068//1139 1841//1140 +f 267//1135 1841//1140 1069//1136 +f 268//1141 1071//1142 1844//1134 +f 268//1141 1844//1134 1065//1133 +f 268//1141 1065//1133 1813//1122 +f 268//1141 1813//1122 1067//1138 +f 268//1141 1067//1138 1812//1137 +f 268//1141 1812//1137 1070//1143 +f 268//1141 1070//1143 1842//1144 +f 268//1141 1842//1144 1071//1142 +f 269//1145 1074//1146 1811//1147 +f 269//1145 1811//1147 1072//1148 +f 269//1145 1072//1148 1812//1137 +f 269//1145 1812//1137 1069//1136 +f 269//1145 1069//1136 1841//1140 +f 269//1145 1841//1140 1073//1149 +f 269//1145 1073//1149 1845//1150 +f 269//1145 1845//1150 1074//1146 +f 270//1151 1076//1152 1842//1144 +f 270//1151 1842//1144 1070//1143 +f 270//1151 1070//1143 1812//1137 +f 270//1151 1812//1137 1072//1148 +f 270//1151 1072//1148 1811//1147 +f 270//1151 1811//1147 1075//1153 +f 270//1151 1075//1153 1846//1154 +f 270//1151 1846//1154 1076//1152 +f 271//1155 1078//1156 1594//261 +f 271//1155 1594//261 632//260 +f 271//1155 632//260 1596//267 +f 271//1155 1596//267 1077//1157 +f 271//1155 1077//1157 1811//1147 +f 271//1155 1811//1147 1074//1146 +f 271//1155 1074//1146 1845//1150 +f 271//1155 1845//1150 1078//1156 +f 272//1158 1075//1153 1811//1147 +f 272//1158 1811//1147 1077//1157 +f 272//1158 1077//1157 1596//267 +f 272//1158 1596//267 635//273 +f 272//1158 635//273 1595//272 +f 272//1158 1595//272 1079//1159 +f 272//1158 1079//1159 1846//1154 +f 272//1158 1846//1154 1075//1153 +f 273//1160 1081//1161 1592//276 +f 273//1160 1592//276 638//275 +f 273//1160 638//275 1594//261 +f 273//1160 1594//261 1078//1156 +f 273//1160 1078//1156 1845//1150 +f 273//1160 1845//1150 1080//1162 +f 273//1160 1080//1162 1839//1163 +f 273//1160 1839//1163 1081//1161 +f 274//1164 1083//1165 1846//1154 +f 274//1164 1846//1154 1079//1159 +f 274//1164 1079//1159 1595//272 +f 274//1164 1595//272 641//285 +f 274//1164 641//285 1593//284 +f 274//1164 1593//284 1082//1166 +f 274//1164 1082//1166 1840//1167 +f 274//1164 1840//1167 1083//1165 +f 275//1168 1085//1169 1590//288 +f 275//1168 1590//288 644//287 +f 275//1168 644//287 1592//276 +f 275//1168 1592//276 1081//1161 +f 275//1168 1081//1161 1839//1163 +f 275//1168 1839//1163 1084//1170 +f 275//1168 1084//1170 1835//1171 +f 275//1168 1835//1171 1085//1169 +f 276//1172 1087//1173 1840//1167 +f 276//1172 1840//1167 1082//1166 +f 276//1172 1082//1166 1593//284 +f 276//1172 1593//284 647//297 +f 276//1172 647//297 1591//296 +f 276//1172 1591//296 1086//1174 +f 276//1172 1086//1174 1836//1175 +f 276//1172 1836//1175 1087//1173 +f 277//1176 1089//1177 1588//300 +f 277//1176 1588//300 650//299 +f 277//1176 650//299 1590//288 +f 277//1176 1590//288 1085//1169 +f 277//1176 1085//1169 1835//1171 +f 277//1176 1835//1171 1088//1178 +f 277//1176 1088//1178 1837//1179 +f 277//1176 1837//1179 1089//1177 +f 278//1180 1091//1181 1836//1175 +f 278//1180 1836//1175 1086//1174 +f 278//1180 1086//1174 1591//296 +f 278//1180 1591//296 653//309 +f 278//1180 653//309 1589//308 +f 278//1180 1589//308 1090//1182 +f 278//1180 1090//1182 1838//1183 +f 278//1180 1838//1183 1091//1181 +f 279//1184 1088//1178 1835//1171 +f 279//1184 1835//1171 1092//1185 +f 279//1184 1092//1185 1841//1140 +f 279//1184 1841//1140 1068//1139 +f 279//1184 1068//1139 1843//1128 +f 279//1184 1843//1128 1093//1186 +f 279//1184 1093//1186 1837//1179 +f 279//1184 1837//1179 1088//1178 +f 280//1187 1095//1188 1844//1134 +f 280//1187 1844//1134 1071//1142 +f 280//1187 1071//1142 1842//1144 +f 280//1187 1842//1144 1094//1189 +f 280//1187 1094//1189 1836//1175 +f 280//1187 1836//1175 1091//1181 +f 280//1187 1091//1181 1838//1183 +f 280//1187 1838//1183 1095//1188 +f 281//1190 1092//1185 1835//1171 +f 281//1190 1835//1171 1084//1170 +f 281//1190 1084//1170 1839//1163 +f 281//1190 1839//1163 1080//1162 +f 281//1190 1080//1162 1845//1150 +f 281//1190 1845//1150 1073//1149 +f 281//1190 1073//1149 1841//1140 +f 281//1190 1841//1140 1092//1185 +f 282//1191 1076//1152 1846//1154 +f 282//1191 1846//1154 1083//1165 +f 282//1191 1083//1165 1840//1167 +f 282//1191 1840//1167 1087//1173 +f 282//1191 1087//1173 1836//1175 +f 282//1191 1836//1175 1094//1189 +f 282//1191 1094//1189 1842//1144 +f 282//1191 1842//1144 1076//1152 +f 283//1192 1097//1193 1831//1194 +f 283//1192 1831//1194 1096//1195 +f 283//1192 1096//1195 1837//1179 +f 283//1192 1837//1179 1093//1186 +f 283//1192 1093//1186 1843//1128 +f 283//1192 1843//1128 1062//1127 +f 283//1192 1062//1127 1833//1126 +f 283//1192 1833//1126 1097//1193 +f 284//1196 1066//1130 1844//1134 +f 284//1196 1844//1134 1095//1188 +f 284//1196 1095//1188 1838//1183 +f 284//1196 1838//1183 1098//1197 +f 284//1196 1098//1197 1832//1198 +f 284//1196 1832//1198 1099//1199 +f 284//1196 1099//1199 1834//1131 +f 284//1196 1834//1131 1066//1130 +f 285//1200 1100//1201 1586//312 +f 285//1200 1586//312 656//311 +f 285//1200 656//311 1588//300 +f 285//1200 1588//300 1089//1177 +f 285//1200 1089//1177 1837//1179 +f 285//1200 1837//1179 1096//1195 +f 285//1200 1096//1195 1831//1194 +f 285//1200 1831//1194 1100//1201 +f 286//1202 1098//1197 1838//1183 +f 286//1202 1838//1183 1090//1182 +f 286//1202 1090//1182 1589//308 +f 286//1202 1589//308 659//321 +f 286//1202 659//321 1587//320 +f 286//1202 1587//320 1101//1203 +f 286//1202 1101//1203 1832//1198 +f 286//1202 1832//1198 1098//1197 +f 287//1204 878//756 1714//749 +f 287//1204 1714//749 1102//1205 +f 287//1204 1102//1205 1847//1206 +f 287//1204 1847//1206 1103//1207 +f 287//1204 1103//1207 1849//1208 +f 287//1204 1849//1208 1104//1209 +f 287//1204 1104//1209 1720//757 +f 287//1204 1720//757 878//756 +f 288//1210 1107//1211 1850//1212 +f 288//1210 1850//1212 1105//1213 +f 288//1210 1105//1213 1848//1214 +f 288//1210 1848//1214 1106//1215 +f 288//1210 1106//1215 1715//753 +f 288//1210 1715//753 881//762 +f 288//1210 881//762 1721//761 +f 288//1210 1721//761 1107//1211 +f 289//1216 874//748 1586//312 +f 289//1216 1586//312 1100//1201 +f 289//1216 1100//1201 1831//1194 +f 289//1216 1831//1194 1108//1217 +f 289//1216 1108//1217 1847//1206 +f 289//1216 1847//1206 1102//1205 +f 289//1216 1102//1205 1714//749 +f 289//1216 1714//749 874//748 +f 290//1218 1106//1215 1848//1214 +f 290//1218 1848//1214 1109//1219 +f 290//1218 1109//1219 1832//1198 +f 290//1218 1832//1198 1101//1203 +f 290//1218 1101//1203 1587//320 +f 290//1218 1587//320 877//754 +f 290//1218 877//754 1715//753 +f 290//1218 1715//753 1106//1215 +f 291//1220 1111//1221 1584//324 +f 291//1220 1584//324 882//764 +f 291//1220 882//764 1720//757 +f 291//1220 1720//757 1104//1209 +f 291//1220 1104//1209 1849//1208 +f 291//1220 1849//1208 1110//1222 +f 291//1220 1110//1222 1851//1223 +f 291//1220 1851//1223 1111//1221 +f 292//1224 1113//1225 1850//1212 +f 292//1224 1850//1212 1107//1211 +f 292//1224 1107//1211 1721//761 +f 292//1224 1721//761 883//766 +f 292//1224 883//766 1585//337 +f 292//1224 1585//337 1112//1226 +f 292//1224 1112//1226 1852//1227 +f 292//1224 1852//1227 1113//1225 +f 293//1228 660//325 1584//324 +f 293//1228 1584//324 1111//1221 +f 293//1228 1111//1221 1851//1223 +f 293//1228 1851//1223 1114//1229 +f 293//1228 1114//1229 1805//1114 +f 293//1228 1805//1114 1056//1113 +f 293//1228 1056//1113 1597//326 +f 293//1228 1597//326 660//325 +f 294//1230 1058//1119 1806//1118 +f 294//1230 1806//1118 1115//1231 +f 294//1230 1115//1231 1852//1227 +f 294//1230 1852//1227 1112//1226 +f 294//1230 1112//1226 1585//337 +f 294//1230 1585//337 665//336 +f 294//1230 665//336 1598//335 +f 294//1230 1598//335 1058//1119 +f 295//1232 1119//1233 1582//1234 +f 295//1232 1582//1234 1116//1235 +f 295//1232 1116//1235 1829//1236 +f 295//1232 1829//1236 1117//1237 +f 295//1232 1117//1237 1857//1238 +f 295//1232 1857//1238 1118//1239 +f 295//1232 1118//1239 1809//1240 +f 295//1232 1809//1240 1119//1233 +f 296//1241 1122//1242 1858//1243 +f 296//1241 1858//1243 1120//1244 +f 296//1241 1120//1244 1830//1245 +f 296//1241 1830//1245 1121//1246 +f 296//1241 1121//1246 1582//1234 +f 296//1241 1582//1234 1119//1233 +f 296//1241 1119//1233 1809//1240 +f 296//1241 1809//1240 1122//1242 +f 297//1247 1125//1248 1809//1240 +f 297//1247 1809//1240 1118//1239 +f 297//1247 1118//1239 1857//1238 +f 297//1247 1857//1238 1123//1249 +f 297//1247 1123//1249 1855//1250 +f 297//1247 1855//1250 1124//1251 +f 297//1247 1124//1251 1583//1252 +f 297//1247 1583//1252 1125//1248 +f 298//1253 1127//1254 1856//1255 +f 298//1253 1856//1255 1126//1256 +f 298//1253 1126//1256 1858//1243 +f 298//1253 1858//1243 1122//1242 +f 298//1253 1122//1242 1809//1240 +f 298//1253 1809//1240 1125//1248 +f 298//1253 1125//1248 1583//1252 +f 298//1253 1583//1252 1127//1254 +f 299//1257 1130//1258 1583//1252 +f 299//1257 1583//1252 1124//1251 +f 299//1257 1124//1251 1855//1250 +f 299//1257 1855//1250 1128//1259 +f 299//1257 1128//1259 1853//1260 +f 299//1257 1853//1260 1129//1261 +f 299//1257 1129//1261 1810//1262 +f 299//1257 1810//1262 1130//1258 +f 300//1263 1132//1264 1854//1265 +f 300//1263 1854//1265 1131//1266 +f 300//1263 1131//1266 1856//1255 +f 300//1263 1856//1255 1127//1254 +f 300//1263 1127//1254 1583//1252 +f 300//1263 1583//1252 1130//1258 +f 300//1263 1130//1258 1810//1262 +f 300//1263 1810//1262 1132//1264 +f 301//1267 1134//1268 1810//1262 +f 301//1267 1810//1262 1129//1261 +f 301//1267 1129//1261 1853//1260 +f 301//1267 1853//1260 1133//1269 +f 301//1267 1133//1269 1833//1126 +f 301//1267 1833//1126 1061//1125 +f 301//1267 1061//1125 1814//1124 +f 301//1267 1814//1124 1134//1268 +f 302//1270 1064//1132 1834//1131 +f 302//1270 1834//1131 1135//1271 +f 302//1270 1135//1271 1854//1265 +f 302//1270 1854//1265 1132//1264 +f 302//1270 1132//1264 1810//1262 +f 302//1270 1810//1262 1134//1268 +f 302//1270 1134//1268 1814//1124 +f 302//1270 1814//1124 1064//1132 +f 303//1272 1108//1217 1831//1194 +f 303//1272 1831//1194 1097//1193 +f 303//1272 1097//1193 1833//1126 +f 303//1272 1833//1126 1133//1269 +f 303//1272 1133//1269 1853//1260 +f 303//1272 1853//1260 1136//1273 +f 303//1272 1136//1273 1847//1206 +f 303//1272 1847//1206 1108//1217 +f 304//1274 1137//1275 1854//1265 +f 304//1274 1854//1265 1135//1271 +f 304//1274 1135//1271 1834//1131 +f 304//1274 1834//1131 1099//1199 +f 304//1274 1099//1199 1832//1198 +f 304//1274 1832//1198 1109//1219 +f 304//1274 1109//1219 1848//1214 +f 304//1274 1848//1214 1137//1275 +f 305//1276 1140//1277 1801//1098 +f 305//1276 1801//1098 1053//1107 +f 305//1276 1053//1107 1803//1106 +f 305//1276 1803//1106 1138//1278 +f 305//1276 1138//1278 1823//1279 +f 305//1276 1823//1279 1139//1280 +f 305//1276 1139//1280 1815//1281 +f 305//1276 1815//1281 1140//1277 +f 306//1282 1143//1283 1824//1284 +f 306//1282 1824//1284 1141//1285 +f 306//1282 1141//1285 1804//1110 +f 306//1282 1804//1110 1055//1109 +f 306//1282 1055//1109 1802//1102 +f 306//1282 1802//1102 1142//1286 +f 306//1282 1142//1286 1816//1287 +f 306//1282 1816//1287 1143//1283 +f 307//1288 1146//1289 1581//1290 +f 307//1288 1581//1290 1144//1291 +f 307//1288 1144//1291 1821//1292 +f 307//1288 1821//1292 1145//1293 +f 307//1288 1145//1293 1829//1236 +f 307//1288 1829//1236 1116//1235 +f 307//1288 1116//1235 1582//1234 +f 307//1288 1582//1234 1146//1289 +f 308//1294 1121//1246 1830//1245 +f 308//1294 1830//1245 1147//1295 +f 308//1294 1147//1295 1822//1296 +f 308//1294 1822//1296 1148//1297 +f 308//1294 1148//1297 1581//1290 +f 308//1294 1581//1290 1146//1289 +f 308//1294 1146//1289 1582//1234 +f 308//1294 1582//1234 1121//1246 +f 309//1298 1152//1299 1807//1300 +f 309//1298 1807//1300 1149//1301 +f 309//1298 1149//1301 1863//1302 +f 309//1298 1863//1302 1150//1303 +f 309//1298 1150//1303 1861//1304 +f 309//1298 1861//1304 1151//1305 +f 309//1298 1151//1305 1808//1306 +f 309//1298 1808//1306 1152//1299 +f 310//1307 1155//1308 1862//1309 +f 310//1307 1862//1309 1153//1310 +f 310//1307 1153//1310 1864//1311 +f 310//1307 1864//1311 1154//1312 +f 310//1307 1154//1312 1807//1300 +f 310//1307 1807//1300 1152//1299 +f 310//1307 1152//1299 1808//1306 +f 310//1307 1808//1306 1155//1308 +f 311//1313 1158//1314 1808//1306 +f 311//1313 1808//1306 1151//1305 +f 311//1313 1151//1305 1861//1304 +f 311//1313 1861//1304 1156//1315 +f 311//1313 1156//1315 1859//1316 +f 311//1313 1859//1316 1157//1317 +f 311//1313 1157//1317 1580//1318 +f 311//1313 1580//1318 1158//1314 +f 312//1319 1160//1320 1860//1321 +f 312//1319 1860//1321 1159//1322 +f 312//1319 1159//1322 1862//1309 +f 312//1319 1862//1309 1155//1308 +f 312//1319 1155//1308 1808//1306 +f 312//1319 1808//1306 1158//1314 +f 312//1319 1158//1314 1580//1318 +f 312//1319 1580//1318 1160//1320 +f 313//1323 1162//1324 1580//1318 +f 313//1323 1580//1318 1157//1317 +f 313//1323 1157//1317 1859//1316 +f 313//1323 1859//1316 1161//1325 +f 313//1323 1161//1325 1821//1292 +f 313//1323 1821//1292 1144//1291 +f 313//1323 1144//1291 1581//1290 +f 313//1323 1581//1290 1162//1324 +f 314//1326 1148//1297 1822//1296 +f 314//1326 1822//1296 1163//1327 +f 314//1326 1163//1327 1860//1321 +f 314//1326 1860//1321 1160//1320 +f 314//1326 1160//1320 1580//1318 +f 314//1326 1580//1318 1162//1324 +f 314//1326 1162//1324 1581//1290 +f 314//1326 1581//1290 1148//1297 +f 315//1328 1166//1329 1797//1082 +f 315//1328 1797//1082 1045//1091 +f 315//1328 1045//1091 1799//1090 +f 315//1328 1799//1090 1164//1330 +f 315//1328 1164//1330 1867//1331 +f 315//1328 1867//1331 1165//1332 +f 315//1328 1165//1332 1869//1333 +f 315//1328 1869//1333 1166//1329 +f 316//1334 1169//1335 1868//1336 +f 316//1334 1868//1336 1167//1337 +f 316//1334 1167//1337 1800//1094 +f 316//1334 1800//1094 1047//1093 +f 316//1334 1047//1093 1798//1086 +f 316//1334 1798//1086 1168//1338 +f 316//1334 1168//1338 1870//1339 +f 316//1334 1870//1339 1169//1335 +f 317//1340 1172//1341 1869//1333 +f 317//1340 1869//1333 1165//1332 +f 317//1340 1165//1332 1867//1331 +f 317//1340 1867//1331 1170//1342 +f 317//1340 1170//1342 1873//1343 +f 317//1340 1873//1343 1171//1344 +f 317//1340 1171//1344 1871//1345 +f 317//1340 1871//1345 1172//1341 +f 318//1346 1175//1347 1874//1348 +f 318//1346 1874//1348 1173//1349 +f 318//1346 1173//1349 1868//1336 +f 318//1346 1868//1336 1169//1335 +f 318//1346 1169//1335 1870//1339 +f 318//1346 1870//1339 1174//1350 +f 318//1346 1174//1350 1872//1351 +f 318//1346 1872//1351 1175//1347 +f 319//1352 1178//1353 1871//1345 +f 319//1352 1871//1345 1171//1344 +f 319//1352 1171//1344 1873//1343 +f 319//1352 1873//1343 1176//1354 +f 319//1352 1176//1354 1875//1355 +f 319//1352 1875//1355 1177//1356 +f 319//1352 1177//1356 1877//1357 +f 319//1352 1877//1357 1178//1353 +f 320//1358 1181//1359 1876//1360 +f 320//1358 1876//1360 1179//1361 +f 320//1358 1179//1361 1874//1348 +f 320//1358 1874//1348 1175//1347 +f 320//1358 1175//1347 1872//1351 +f 320//1358 1872//1351 1180//1362 +f 320//1358 1180//1362 1878//1363 +f 320//1358 1878//1363 1181//1359 +f 321//1364 1184//1365 1877//1357 +f 321//1364 1877//1357 1177//1356 +f 321//1364 1177//1356 1875//1355 +f 321//1364 1875//1355 1182//1366 +f 321//1364 1182//1366 1881//1367 +f 321//1364 1881//1367 1183//1368 +f 321//1364 1183//1368 1879//1369 +f 321//1364 1879//1369 1184//1365 +f 322//1370 1187//1371 1882//1372 +f 322//1370 1882//1372 1185//1373 +f 322//1370 1185//1373 1876//1360 +f 322//1370 1876//1360 1181//1359 +f 322//1370 1181//1359 1878//1363 +f 322//1370 1878//1363 1186//1374 +f 322//1370 1186//1374 1880//1375 +f 322//1370 1880//1375 1187//1371 +f 323//1376 1190//1377 1819//1378 +f 323//1376 1819//1378 1188//1379 +f 323//1376 1188//1379 1883//1380 +f 323//1376 1883//1380 1189//1381 +f 323//1376 1189//1381 1879//1369 +f 323//1376 1879//1369 1183//1368 +f 323//1376 1183//1368 1881//1367 +f 323//1376 1881//1367 1190//1377 +f 324//1382 1187//1371 1880//1375 +f 324//1382 1880//1375 1191//1383 +f 324//1382 1191//1383 1884//1384 +f 324//1382 1884//1384 1192//1385 +f 324//1382 1192//1385 1820//1386 +f 324//1382 1820//1386 1193//1387 +f 324//1382 1193//1387 1882//1372 +f 324//1382 1882//1372 1187//1371 +f 325//1388 1195//1389 1821//1292 +f 325//1388 1821//1292 1161//1325 +f 325//1388 1161//1325 1859//1316 +f 325//1388 1859//1316 1194//1390 +f 325//1388 1194//1390 1879//1369 +f 325//1388 1879//1369 1189//1381 +f 325//1388 1189//1381 1883//1380 +f 325//1388 1883//1380 1195//1389 +f 326//1391 1191//1383 1880//1375 +f 326//1391 1880//1375 1196//1392 +f 326//1391 1196//1392 1860//1321 +f 326//1391 1860//1321 1163//1327 +f 326//1391 1163//1327 1822//1296 +f 326//1391 1822//1296 1197//1393 +f 326//1391 1197//1393 1884//1384 +f 326//1391 1884//1384 1191//1383 +f 327//1394 1194//1390 1859//1316 +f 327//1394 1859//1316 1156//1315 +f 327//1394 1156//1315 1861//1304 +f 327//1394 1861//1304 1198//1395 +f 327//1394 1198//1395 1877//1357 +f 327//1394 1877//1357 1184//1365 +f 327//1394 1184//1365 1879//1369 +f 327//1394 1879//1369 1194//1390 +f 328//1396 1186//1374 1878//1363 +f 328//1396 1878//1363 1199//1397 +f 328//1396 1199//1397 1862//1309 +f 328//1396 1862//1309 1159//1322 +f 328//1396 1159//1322 1860//1321 +f 328//1396 1860//1321 1196//1392 +f 328//1396 1196//1392 1880//1375 +f 328//1396 1880//1375 1186//1374 +f 329//1398 1198//1395 1861//1304 +f 329//1398 1861//1304 1150//1303 +f 329//1398 1150//1303 1863//1302 +f 329//1398 1863//1302 1200//1399 +f 329//1398 1200//1399 1871//1345 +f 329//1398 1871//1345 1178//1353 +f 329//1398 1178//1353 1877//1357 +f 329//1398 1877//1357 1198//1395 +f 330//1400 1180//1362 1872//1351 +f 330//1400 1872//1351 1201//1401 +f 330//1400 1201//1401 1864//1311 +f 330//1400 1864//1311 1153//1310 +f 330//1400 1153//1310 1862//1309 +f 330//1400 1862//1309 1199//1397 +f 330//1400 1199//1397 1878//1363 +f 330//1400 1878//1363 1180//1362 +f 331//1402 1200//1399 1863//1302 +f 331//1402 1863//1302 1202//1403 +f 331//1402 1202//1403 1865//1404 +f 331//1402 1865//1404 1203//1405 +f 331//1402 1203//1405 1869//1333 +f 331//1402 1869//1333 1172//1341 +f 331//1402 1172//1341 1871//1345 +f 331//1402 1871//1345 1200//1399 +f 332//1406 1174//1350 1870//1339 +f 332//1406 1870//1339 1204//1407 +f 332//1406 1204//1407 1866//1408 +f 332//1406 1866//1408 1205//1409 +f 332//1406 1205//1409 1864//1311 +f 332//1406 1864//1311 1201//1401 +f 332//1406 1201//1401 1872//1351 +f 332//1406 1872//1351 1174//1350 +f 333//1410 1206//1411 1795//1074 +f 333//1410 1795//1074 1041//1083 +f 333//1410 1041//1083 1797//1082 +f 333//1410 1797//1082 1166//1329 +f 333//1410 1166//1329 1869//1333 +f 333//1410 1869//1333 1203//1405 +f 333//1410 1203//1405 1865//1404 +f 333//1410 1865//1404 1206//1411 +f 334//1412 1204//1407 1870//1339 +f 334//1412 1870//1339 1168//1338 +f 334//1412 1168//1338 1798//1086 +f 334//1412 1798//1086 1043//1085 +f 334//1412 1043//1085 1796//1078 +f 334//1412 1796//1078 1207//1413 +f 334//1412 1207//1413 1866//1408 +f 334//1412 1866//1408 1204//1407 +f 335//1414 1209//1415 1579//1416 +f 335//1414 1579//1416 1208//1417 +f 335//1414 1208//1417 1865//1404 +f 335//1414 1865//1404 1202//1403 +f 335//1414 1202//1403 1863//1302 +f 335//1414 1863//1302 1149//1301 +f 335//1414 1149//1301 1807//1300 +f 335//1414 1807//1300 1209//1415 +f 336//1418 1154//1312 1864//1311 +f 336//1418 1864//1311 1205//1409 +f 336//1418 1205//1409 1866//1408 +f 336//1418 1866//1408 1210//1419 +f 336//1418 1210//1419 1579//1416 +f 336//1418 1579//1416 1209//1415 +f 336//1418 1209//1415 1807//1300 +f 336//1418 1807//1300 1154//1312 +f 337//1420 1211//1421 1789//1049 +f 337//1420 1789//1049 1029//1059 +f 337//1420 1029//1059 1791//1058 +f 337//1420 1791//1058 1033//1067 +f 337//1420 1033//1067 1793//1066 +f 337//1420 1793//1066 1037//1075 +f 337//1420 1037//1075 1795//1074 +f 337//1420 1795//1074 1211//1421 +f 338//1422 1039//1077 1794//1070 +f 338//1422 1794//1070 1035//1069 +f 338//1422 1035//1069 1792//1062 +f 338//1422 1792//1062 1031//1061 +f 338//1422 1031//1061 1790//1054 +f 338//1422 1790//1054 1212//1423 +f 338//1422 1212//1423 1796//1078 +f 338//1422 1796//1078 1039//1077 +f 339//1424 1213//1425 1789//1049 +f 339//1424 1789//1049 1211//1421 +f 339//1424 1211//1421 1795//1074 +f 339//1424 1795//1074 1206//1411 +f 339//1424 1206//1411 1865//1404 +f 339//1424 1865//1404 1208//1417 +f 339//1424 1208//1417 1579//1416 +f 339//1424 1579//1416 1213//1425 +f 340//1426 1210//1419 1866//1408 +f 340//1426 1866//1408 1207//1413 +f 340//1426 1207//1413 1796//1078 +f 340//1426 1796//1078 1212//1423 +f 340//1426 1212//1423 1790//1054 +f 340//1426 1790//1054 1214//1427 +f 340//1426 1214//1427 1579//1416 +f 340//1426 1579//1416 1210//1419 +f 341//1428 1215//1429 1578//1051 +f 341//1428 1578//1051 1024//1050 +f 341//1428 1024//1050 1789//1049 +f 341//1428 1789//1049 1213//1425 +f 341//1428 1213//1425 1579//1416 +f 341//1428 1579//1416 1215//1429 +f 342//1430 1215//1429 1579//1416 +f 342//1430 1579//1416 1214//1427 +f 342//1430 1214//1427 1790//1054 +f 342//1430 1790//1054 1027//1053 +f 342//1430 1027//1053 1578//1051 +f 342//1430 1578//1051 1215//1429 +f 343//1431 1164//1330 1799//1090 +f 343//1431 1799//1090 1049//1099 +f 343//1431 1049//1099 1801//1098 +f 343//1431 1801//1098 1140//1277 +f 343//1431 1140//1277 1815//1281 +f 343//1431 1815//1281 1216//1432 +f 343//1431 1216//1432 1867//1331 +f 343//1431 1867//1331 1164//1330 +f 344//1433 1217//1434 1816//1287 +f 344//1433 1816//1287 1142//1286 +f 344//1433 1142//1286 1802//1102 +f 344//1433 1802//1102 1051//1101 +f 344//1433 1051//1101 1800//1094 +f 344//1433 1800//1094 1167//1337 +f 344//1433 1167//1337 1868//1336 +f 344//1433 1868//1336 1217//1434 +f 345//1435 1216//1432 1815//1281 +f 345//1435 1815//1281 1218//1436 +f 345//1435 1218//1436 1817//1437 +f 345//1435 1817//1437 1219//1438 +f 345//1435 1219//1438 1873//1343 +f 345//1435 1873//1343 1170//1342 +f 345//1435 1170//1342 1867//1331 +f 345//1435 1867//1331 1216//1432 +f 346//1439 1173//1349 1874//1348 +f 346//1439 1874//1348 1220//1440 +f 346//1439 1220//1440 1818//1441 +f 346//1439 1818//1441 1221//1442 +f 346//1439 1221//1442 1816//1287 +f 346//1439 1816//1287 1217//1434 +f 346//1439 1217//1434 1868//1336 +f 346//1439 1868//1336 1173//1349 +f 347//1443 1219//1438 1817//1437 +f 347//1443 1817//1437 1222//1444 +f 347//1443 1222//1444 1887//1445 +f 347//1443 1887//1445 1223//1446 +f 347//1443 1223//1446 1875//1355 +f 347//1443 1875//1355 1176//1354 +f 347//1443 1176//1354 1873//1343 +f 347//1443 1873//1343 1219//1438 +f 348//1447 1179//1361 1876//1360 +f 348//1447 1876//1360 1224//1448 +f 348//1447 1224//1448 1888//1449 +f 348//1447 1888//1449 1225//1450 +f 348//1447 1225//1450 1818//1441 +f 348//1447 1818//1441 1220//1440 +f 348//1447 1220//1440 1874//1348 +f 348//1447 1874//1348 1179//1361 +f 349//1451 1226//1452 1819//1378 +f 349//1451 1819//1378 1190//1377 +f 349//1451 1190//1377 1881//1367 +f 349//1451 1881//1367 1182//1366 +f 349//1451 1182//1366 1875//1355 +f 349//1451 1875//1355 1223//1446 +f 349//1451 1223//1446 1887//1445 +f 349//1451 1887//1445 1226//1452 +f 350//1453 1224//1448 1876//1360 +f 350//1453 1876//1360 1185//1373 +f 350//1453 1185//1373 1882//1372 +f 350//1453 1882//1372 1193//1387 +f 350//1453 1193//1387 1820//1386 +f 350//1453 1820//1386 1227//1454 +f 350//1453 1227//1454 1888//1449 +f 350//1453 1888//1449 1224//1448 +f 351//1455 1230//1456 1853//1260 +f 351//1455 1853//1260 1128//1259 +f 351//1455 1128//1259 1855//1250 +f 351//1455 1855//1250 1228//1457 +f 351//1455 1228//1457 1891//1458 +f 351//1455 1891//1458 1229//1459 +f 351//1455 1229//1459 1889//1460 +f 351//1455 1889//1460 1230//1456 +f 352//1461 1233//1462 1892//1463 +f 352//1461 1892//1463 1231//1464 +f 352//1461 1231//1464 1856//1255 +f 352//1461 1856//1255 1131//1266 +f 352//1461 1131//1266 1854//1265 +f 352//1461 1854//1265 1232//1465 +f 352//1461 1232//1465 1890//1466 +f 352//1461 1890//1466 1233//1462 +f 353//1467 1236//1468 1823//1279 +f 353//1467 1823//1279 1234//1469 +f 353//1467 1234//1469 1889//1460 +f 353//1467 1889//1460 1229//1459 +f 353//1467 1229//1459 1891//1458 +f 353//1467 1891//1458 1235//1470 +f 353//1467 1235//1470 1825//1471 +f 353//1467 1825//1471 1236//1468 +f 354//1472 1239//1473 1892//1463 +f 354//1472 1892//1463 1233//1462 +f 354//1472 1233//1462 1890//1466 +f 354//1472 1890//1466 1237//1474 +f 354//1472 1237//1474 1824//1284 +f 354//1472 1824//1284 1238//1475 +f 354//1472 1238//1475 1826//1476 +f 354//1472 1826//1476 1239//1473 +f 355//1477 1138//1278 1803//1106 +f 355//1477 1803//1106 1057//1115 +f 355//1477 1057//1115 1805//1114 +f 355//1477 1805//1114 1240//1478 +f 355//1477 1240//1478 1889//1460 +f 355//1477 1889//1460 1234//1469 +f 355//1477 1234//1469 1823//1279 +f 355//1477 1823//1279 1138//1278 +f 356//1479 1237//1474 1890//1466 +f 356//1479 1890//1466 1241//1480 +f 356//1479 1241//1480 1806//1118 +f 356//1479 1806//1118 1059//1117 +f 356//1479 1059//1117 1804//1110 +f 356//1479 1804//1110 1141//1285 +f 356//1479 1141//1285 1824//1284 +f 356//1479 1824//1284 1237//1474 +f 357//1481 1240//1478 1805//1114 +f 357//1481 1805//1114 1242//1482 +f 357//1481 1242//1482 1849//1208 +f 357//1481 1849//1208 1103//1207 +f 357//1481 1103//1207 1847//1206 +f 357//1481 1847//1206 1243//1483 +f 357//1481 1243//1483 1889//1460 +f 357//1481 1889//1460 1240//1478 +f 358//1484 1245//1485 1848//1214 +f 358//1484 1848//1214 1105//1213 +f 358//1484 1105//1213 1850//1212 +f 358//1484 1850//1212 1244//1486 +f 358//1484 1244//1486 1806//1118 +f 358//1484 1806//1118 1241//1480 +f 358//1484 1241//1480 1890//1466 +f 358//1484 1890//1466 1245//1485 +f 359//1487 1243//1483 1847//1206 +f 359//1487 1847//1206 1136//1273 +f 359//1487 1136//1273 1853//1260 +f 359//1487 1853//1260 1230//1456 +f 359//1487 1230//1456 1889//1460 +f 359//1487 1889//1460 1243//1483 +f 360//1488 1245//1485 1890//1466 +f 360//1488 1890//1466 1232//1465 +f 360//1488 1232//1465 1854//1265 +f 360//1488 1854//1265 1137//1275 +f 360//1488 1137//1275 1848//1214 +f 360//1488 1848//1214 1245//1485 +f 361//1489 1242//1482 1805//1114 +f 361//1489 1805//1114 1114//1229 +f 361//1489 1114//1229 1851//1223 +f 361//1489 1851//1223 1110//1222 +f 361//1489 1110//1222 1849//1208 +f 361//1489 1849//1208 1242//1482 +f 362//1490 1244//1486 1850//1212 +f 362//1490 1850//1212 1113//1225 +f 362//1490 1113//1225 1852//1227 +f 362//1490 1852//1227 1115//1231 +f 362//1490 1115//1231 1806//1118 +f 362//1490 1806//1118 1244//1486 +f 363//1491 1188//1379 1819//1378 +f 363//1491 1819//1378 1246//1492 +f 363//1491 1246//1492 1827//1493 +f 363//1491 1827//1493 1247//1494 +f 363//1491 1247//1494 1885//1495 +f 363//1491 1885//1495 1248//1496 +f 363//1491 1248//1496 1883//1380 +f 363//1491 1883//1380 1188//1379 +f 364//1497 1251//1498 1886//1499 +f 364//1497 1886//1499 1249//1500 +f 364//1497 1249//1500 1828//1501 +f 364//1497 1828//1501 1250//1502 +f 364//1497 1250//1502 1820//1386 +f 364//1497 1820//1386 1192//1385 +f 364//1497 1192//1385 1884//1384 +f 364//1497 1884//1384 1251//1498 +f 365//1503 1145//1293 1821//1292 +f 365//1503 1821//1292 1195//1389 +f 365//1503 1195//1389 1883//1380 +f 365//1503 1883//1380 1248//1496 +f 365//1503 1248//1496 1885//1495 +f 365//1503 1885//1495 1252//1504 +f 365//1503 1252//1504 1829//1236 +f 365//1503 1829//1236 1145//1293 +f 366//1505 1253//1506 1886//1499 +f 366//1505 1886//1499 1251//1498 +f 366//1505 1251//1498 1884//1384 +f 366//1505 1884//1384 1197//1393 +f 366//1505 1197//1393 1822//1296 +f 366//1505 1822//1296 1147//1295 +f 366//1505 1147//1295 1830//1245 +f 366//1505 1830//1245 1253//1506 +f 367//1507 1255//1508 1825//1471 +f 367//1507 1825//1471 1235//1470 +f 367//1507 1235//1470 1891//1458 +f 367//1507 1891//1458 1254//1509 +f 367//1507 1254//1509 1885//1495 +f 367//1507 1885//1495 1247//1494 +f 367//1507 1247//1494 1827//1493 +f 367//1507 1827//1493 1255//1508 +f 368//1510 1249//1500 1886//1499 +f 368//1510 1886//1499 1256//1511 +f 368//1510 1256//1511 1892//1463 +f 368//1510 1892//1463 1239//1473 +f 368//1510 1239//1473 1826//1476 +f 368//1510 1826//1476 1257//1512 +f 368//1510 1257//1512 1828//1501 +f 368//1510 1828//1501 1249//1500 +f 369//1513 1228//1457 1855//1250 +f 369//1513 1855//1250 1123//1249 +f 369//1513 1123//1249 1857//1238 +f 369//1513 1857//1238 1258//1514 +f 369//1513 1258//1514 1885//1495 +f 369//1513 1885//1495 1254//1509 +f 369//1513 1254//1509 1891//1458 +f 369//1513 1891//1458 1228//1457 +f 370//1515 1256//1511 1886//1499 +f 370//1515 1886//1499 1259//1516 +f 370//1515 1259//1516 1858//1243 +f 370//1515 1858//1243 1126//1256 +f 370//1515 1126//1256 1856//1255 +f 370//1515 1856//1255 1231//1464 +f 370//1515 1231//1464 1892//1463 +f 370//1515 1892//1463 1256//1511 +f 371//1517 1117//1237 1829//1236 +f 371//1517 1829//1236 1252//1504 +f 371//1517 1252//1504 1885//1495 +f 371//1517 1885//1495 1258//1514 +f 371//1517 1258//1514 1857//1238 +f 371//1517 1857//1238 1117//1237 +f 372//1518 1120//1244 1858//1243 +f 372//1518 1858//1243 1259//1516 +f 372//1518 1259//1516 1886//1499 +f 372//1518 1886//1499 1253//1506 +f 372//1518 1253//1506 1830//1245 +f 372//1518 1830//1245 1120//1244 +f 373//1519 1263//1520 1905//1521 +f 373//1519 1905//1521 1260//1522 +f 373//1519 1260//1522 1893//1523 +f 373//1519 1893//1523 1261//1524 +f 373//1519 1261//1524 1919//1525 +f 373//1519 1919//1525 1262//1526 +f 373//1519 1262//1526 1907//1527 +f 373//1519 1907//1527 1263//1520 +f 374//1528 1267//1529 1920//1530 +f 374//1528 1920//1530 1264//1531 +f 374//1528 1264//1531 1894//1532 +f 374//1528 1894//1532 1265//1533 +f 374//1528 1265//1533 1906//1534 +f 374//1528 1906//1534 1266//1535 +f 374//1528 1266//1535 1908//1536 +f 374//1528 1908//1536 1267//1529 +f 375//1537 1270//1538 1905//1521 +f 375//1537 1905//1521 1263//1520 +f 375//1537 1263//1520 1907//1527 +f 375//1537 1907//1527 1268//1539 +f 375//1537 1268//1539 1909//1540 +f 375//1537 1909//1540 1269//1541 +f 375//1537 1269//1541 1903//1542 +f 375//1537 1903//1542 1270//1538 +f 376//1543 1273//1544 1910//1545 +f 376//1543 1910//1545 1271//1546 +f 376//1543 1271//1546 1908//1536 +f 376//1543 1908//1536 1266//1535 +f 376//1543 1266//1535 1906//1534 +f 376//1543 1906//1534 1272//1547 +f 376//1543 1272//1547 1904//1548 +f 376//1543 1904//1548 1273//1544 +f 377//1549 1276//1550 1903//1542 +f 377//1549 1903//1542 1269//1541 +f 377//1549 1269//1541 1909//1540 +f 377//1549 1909//1540 1274//1551 +f 377//1549 1274//1551 1911//1552 +f 377//1549 1911//1552 1275//1553 +f 377//1549 1275//1553 1901//1554 +f 377//1549 1901//1554 1276//1550 +f 378//1555 1279//1556 1912//1557 +f 378//1555 1912//1557 1277//1558 +f 378//1555 1277//1558 1910//1545 +f 378//1555 1910//1545 1273//1544 +f 378//1555 1273//1544 1904//1548 +f 378//1555 1904//1548 1278//1559 +f 378//1555 1278//1559 1902//1560 +f 378//1555 1902//1560 1279//1556 +f 379//1561 1282//1562 1901//1554 +f 379//1561 1901//1554 1275//1553 +f 379//1561 1275//1553 1911//1552 +f 379//1561 1911//1552 1280//1563 +f 379//1561 1280//1563 1913//1564 +f 379//1561 1913//1564 1281//1565 +f 379//1561 1281//1565 1899//1566 +f 379//1561 1899//1566 1282//1562 +f 380//1567 1285//1568 1914//1569 +f 380//1567 1914//1569 1283//1570 +f 380//1567 1283//1570 1912//1557 +f 380//1567 1912//1557 1279//1556 +f 380//1567 1279//1556 1902//1560 +f 380//1567 1902//1560 1284//1571 +f 380//1567 1284//1571 1900//1572 +f 380//1567 1900//1572 1285//1568 +f 381//1573 1288//1574 1899//1566 +f 381//1573 1899//1566 1281//1565 +f 381//1573 1281//1565 1913//1564 +f 381//1573 1913//1564 1286//1575 +f 381//1573 1286//1575 1915//1576 +f 381//1573 1915//1576 1287//1577 +f 381//1573 1287//1577 1897//1578 +f 381//1573 1897//1578 1288//1574 +f 382//1579 1291//1580 1916//1581 +f 382//1579 1916//1581 1289//1582 +f 382//1579 1289//1582 1914//1569 +f 382//1579 1914//1569 1285//1568 +f 382//1579 1285//1568 1900//1572 +f 382//1579 1900//1572 1290//1583 +f 382//1579 1290//1583 1898//1584 +f 382//1579 1898//1584 1291//1580 +f 383//1585 1294//1586 1897//1578 +f 383//1585 1897//1578 1287//1577 +f 383//1585 1287//1577 1915//1576 +f 383//1585 1915//1576 1292//1587 +f 383//1585 1292//1587 1917//1588 +f 383//1585 1917//1588 1293//1589 +f 383//1585 1293//1589 1895//1590 +f 383//1585 1895//1590 1294//1586 +f 384//1591 1297//1592 1918//1593 +f 384//1591 1918//1593 1295//1594 +f 384//1591 1295//1594 1916//1581 +f 384//1591 1916//1581 1291//1580 +f 384//1591 1291//1580 1898//1584 +f 384//1591 1898//1584 1296//1595 +f 384//1591 1296//1595 1896//1596 +f 384//1591 1896//1596 1297//1592 +f 385//1597 1292//1587 1915//1576 +f 385//1597 1915//1576 1298//1598 +f 385//1597 1298//1598 1925//1599 +f 385//1597 1925//1599 1299//1600 +f 385//1597 1299//1600 1923//1601 +f 385//1597 1923//1601 1300//1602 +f 385//1597 1300//1602 1917//1588 +f 385//1597 1917//1588 1292//1587 +f 386//1603 1303//1604 1924//1605 +f 386//1603 1924//1605 1301//1606 +f 386//1603 1301//1606 1926//1607 +f 386//1603 1926//1607 1302//1608 +f 386//1603 1302//1608 1916//1581 +f 386//1603 1916//1581 1295//1594 +f 386//1603 1295//1594 1918//1593 +f 386//1603 1918//1593 1303//1604 +f 387//1609 1286//1575 1913//1564 +f 387//1609 1913//1564 1304//1610 +f 387//1609 1304//1610 1927//1611 +f 387//1609 1927//1611 1305//1612 +f 387//1609 1305//1612 1925//1599 +f 387//1609 1925//1599 1298//1598 +f 387//1609 1298//1598 1915//1576 +f 387//1609 1915//1576 1286//1575 +f 388//1613 1302//1608 1926//1607 +f 388//1613 1926//1607 1306//1614 +f 388//1613 1306//1614 1928//1615 +f 388//1613 1928//1615 1307//1616 +f 388//1613 1307//1616 1914//1569 +f 388//1613 1914//1569 1289//1582 +f 388//1613 1289//1582 1916//1581 +f 388//1613 1916//1581 1302//1608 +f 389//1617 1280//1563 1911//1552 +f 389//1617 1911//1552 1308//1618 +f 389//1617 1308//1618 1929//1619 +f 389//1617 1929//1619 1309//1620 +f 389//1617 1309//1620 1927//1611 +f 389//1617 1927//1611 1304//1610 +f 389//1617 1304//1610 1913//1564 +f 389//1617 1913//1564 1280//1563 +f 390//1621 1307//1616 1928//1615 +f 390//1621 1928//1615 1310//1622 +f 390//1621 1310//1622 1930//1623 +f 390//1621 1930//1623 1311//1624 +f 390//1621 1311//1624 1912//1557 +f 390//1621 1912//1557 1283//1570 +f 390//1621 1283//1570 1914//1569 +f 390//1621 1914//1569 1307//1616 +f 391//1625 1274//1551 1909//1540 +f 391//1625 1909//1540 1312//1626 +f 391//1625 1312//1626 1931//1627 +f 391//1625 1931//1627 1313//1628 +f 391//1625 1313//1628 1929//1619 +f 391//1625 1929//1619 1308//1618 +f 391//1625 1308//1618 1911//1552 +f 391//1625 1911//1552 1274//1551 +f 392//1629 1311//1624 1930//1623 +f 392//1629 1930//1623 1314//1630 +f 392//1629 1314//1630 1932//1631 +f 392//1629 1932//1631 1315//1632 +f 392//1629 1315//1632 1910//1545 +f 392//1629 1910//1545 1277//1558 +f 392//1629 1277//1558 1912//1557 +f 392//1629 1912//1557 1311//1624 +f 393//1633 1268//1539 1907//1527 +f 393//1633 1907//1527 1316//1634 +f 393//1633 1316//1634 1933//1635 +f 393//1633 1933//1635 1317//1636 +f 393//1633 1317//1636 1931//1627 +f 393//1633 1931//1627 1312//1626 +f 393//1633 1312//1626 1909//1540 +f 393//1633 1909//1540 1268//1539 +f 394//1637 1315//1632 1932//1631 +f 394//1637 1932//1631 1318//1638 +f 394//1637 1318//1638 1934//1639 +f 394//1637 1934//1639 1319//1640 +f 394//1637 1319//1640 1908//1536 +f 394//1637 1908//1536 1271//1546 +f 394//1637 1271//1546 1910//1545 +f 394//1637 1910//1545 1315//1632 +f 395//1641 1316//1634 1907//1527 +f 395//1641 1907//1527 1262//1526 +f 395//1641 1262//1526 1919//1525 +f 395//1641 1919//1525 1320//1642 +f 395//1641 1320//1642 1921//1643 +f 395//1641 1921//1643 1321//1644 +f 395//1641 1321//1644 1933//1635 +f 395//1641 1933//1635 1316//1634 +f 396//1645 1323//1646 1922//1647 +f 396//1645 1922//1647 1322//1648 +f 396//1645 1322//1648 1920//1530 +f 396//1645 1920//1530 1267//1529 +f 396//1645 1267//1529 1908//1536 +f 396//1645 1908//1536 1319//1640 +f 396//1645 1319//1640 1934//1639 +f 396//1645 1934//1639 1323//1646 +f 397//1649 1326//1650 1823//1279 +f 397//1649 1823//1279 1236//1468 +f 397//1649 1236//1468 1825//1471 +f 397//1649 1825//1471 1324//1651 +f 397//1649 1324//1651 1949//1652 +f 397//1649 1949//1652 1325//1653 +f 397//1649 1325//1653 1947//1654 +f 397//1649 1947//1654 1326//1650 +f 398//1655 1329//1656 1950//1657 +f 398//1655 1950//1657 1327//1658 +f 398//1655 1327//1658 1826//1476 +f 398//1655 1826//1476 1238//1475 +f 398//1655 1238//1475 1824//1284 +f 398//1655 1824//1284 1328//1659 +f 398//1655 1328//1659 1948//1660 +f 398//1655 1948//1660 1329//1656 +f 399//1661 1324//1651 1825//1471 +f 399//1661 1825//1471 1330//1662 +f 399//1661 1330//1662 1895//1590 +f 399//1661 1895//1590 1293//1589 +f 399//1661 1293//1589 1917//1588 +f 399//1661 1917//1588 1331//1663 +f 399//1661 1331//1663 1949//1652 +f 399//1661 1949//1652 1324//1651 +f 400//1664 1333//1665 1918//1593 +f 400//1664 1918//1593 1297//1592 +f 400//1664 1297//1592 1896//1596 +f 400//1664 1896//1596 1332//1666 +f 400//1664 1332//1666 1826//1476 +f 400//1664 1826//1476 1327//1658 +f 400//1664 1327//1658 1950//1657 +f 400//1664 1950//1657 1333//1665 +f 401//1667 1218//1436 1815//1281 +f 401//1667 1815//1281 1139//1280 +f 401//1667 1139//1280 1823//1279 +f 401//1667 1823//1279 1326//1650 +f 401//1667 1326//1650 1947//1654 +f 401//1667 1947//1654 1334//1668 +f 401//1667 1334//1668 1817//1437 +f 401//1667 1817//1437 1218//1436 +f 402//1669 1335//1670 1948//1660 +f 402//1669 1948//1660 1328//1659 +f 402//1669 1328//1659 1824//1284 +f 402//1669 1824//1284 1143//1283 +f 402//1669 1143//1283 1816//1287 +f 402//1669 1816//1287 1221//1442 +f 402//1669 1221//1442 1818//1441 +f 402//1669 1818//1441 1335//1670 +f 403//1671 1338//1672 1887//1445 +f 403//1671 1887//1445 1336//1673 +f 403//1671 1336//1673 1935//1674 +f 403//1671 1935//1674 1337//1675 +f 403//1671 1337//1675 1919//1525 +f 403//1671 1919//1525 1261//1524 +f 403//1671 1261//1524 1893//1523 +f 403//1671 1893//1523 1338//1672 +f 404//1676 1264//1531 1920//1530 +f 404//1676 1920//1530 1339//1677 +f 404//1676 1339//1677 1936//1678 +f 404//1676 1936//1678 1340//1679 +f 404//1676 1340//1679 1888//1449 +f 404//1676 1888//1449 1341//1680 +f 404//1676 1341//1680 1894//1532 +f 404//1676 1894//1532 1264//1531 +f 405//1681 1331//1663 1917//1588 +f 405//1681 1917//1588 1300//1602 +f 405//1681 1300//1602 1923//1601 +f 405//1681 1923//1601 1342//1682 +f 405//1681 1342//1682 1945//1683 +f 405//1681 1945//1683 1343//1684 +f 405//1681 1343//1684 1949//1652 +f 405//1681 1949//1652 1331//1663 +f 406//1685 1345//1686 1946//1687 +f 406//1685 1946//1687 1344//1688 +f 406//1685 1344//1688 1924//1605 +f 406//1685 1924//1605 1303//1604 +f 406//1685 1303//1604 1918//1593 +f 406//1685 1918//1593 1333//1665 +f 406//1685 1333//1665 1950//1657 +f 406//1685 1950//1657 1345//1686 +f 407//1689 1348//1690 1943//1691 +f 407//1689 1943//1691 1346//1692 +f 407//1689 1346//1692 1951//1693 +f 407//1689 1951//1693 1347//1694 +f 407//1689 1347//1694 1949//1652 +f 407//1689 1949//1652 1343//1684 +f 407//1689 1343//1684 1945//1683 +f 407//1689 1945//1683 1348//1690 +f 408//1695 1345//1686 1950//1657 +f 408//1695 1950//1657 1349//1696 +f 408//1695 1349//1696 1952//1697 +f 408//1695 1952//1697 1350//1698 +f 408//1695 1350//1698 1944//1699 +f 408//1695 1944//1699 1351//1700 +f 408//1695 1351//1700 1946//1687 +f 408//1695 1946//1687 1345//1686 +f 409//1701 1354//1702 1939//1703 +f 409//1701 1939//1703 1352//1704 +f 409//1701 1352//1704 1951//1693 +f 409//1701 1951//1693 1346//1692 +f 409//1701 1346//1692 1943//1691 +f 409//1701 1943//1691 1353//1705 +f 409//1701 1353//1705 1941//1706 +f 409//1701 1941//1706 1354//1702 +f 410//1707 1357//1708 1944//1699 +f 410//1707 1944//1699 1350//1698 +f 410//1707 1350//1698 1952//1697 +f 410//1707 1952//1697 1355//1709 +f 410//1707 1355//1709 1940//1710 +f 410//1707 1940//1710 1356//1711 +f 410//1707 1356//1711 1942//1712 +f 410//1707 1942//1712 1357//1708 +f 411//1713 1360//1714 1937//1715 +f 411//1713 1937//1715 1358//1716 +f 411//1713 1358//1716 1953//1717 +f 411//1713 1953//1717 1359//1718 +f 411//1713 1359//1718 1951//1693 +f 411//1713 1951//1693 1352//1704 +f 411//1713 1352//1704 1939//1703 +f 411//1713 1939//1703 1360//1714 +f 412//1719 1355//1709 1952//1697 +f 412//1719 1952//1697 1361//1720 +f 412//1719 1361//1720 1954//1721 +f 412//1719 1954//1721 1362//1722 +f 412//1719 1362//1722 1938//1723 +f 412//1719 1938//1723 1363//1724 +f 412//1719 1363//1724 1940//1710 +f 412//1719 1940//1710 1355//1709 +f 413//1725 1366//1726 1935//1674 +f 413//1725 1935//1674 1364//1727 +f 413//1725 1364//1727 1953//1717 +f 413//1725 1953//1717 1358//1716 +f 413//1725 1358//1716 1937//1715 +f 413//1725 1937//1715 1365//1728 +f 413//1725 1365//1728 1955//1729 +f 413//1725 1955//1729 1366//1726 +f 414//1730 1369//1731 1938//1723 +f 414//1730 1938//1723 1362//1722 +f 414//1730 1362//1722 1954//1721 +f 414//1730 1954//1721 1367//1732 +f 414//1730 1367//1732 1936//1678 +f 414//1730 1936//1678 1368//1733 +f 414//1730 1368//1733 1956//1734 +f 414//1730 1956//1734 1369//1731 +f 415//1735 1320//1642 1919//1525 +f 415//1735 1919//1525 1337//1675 +f 415//1735 1337//1675 1935//1674 +f 415//1735 1935//1674 1366//1726 +f 415//1735 1366//1726 1955//1729 +f 415//1735 1955//1729 1370//1736 +f 415//1735 1370//1736 1921//1643 +f 415//1735 1921//1643 1320//1642 +f 416//1737 1371//1738 1956//1734 +f 416//1737 1956//1734 1368//1733 +f 416//1737 1368//1733 1936//1678 +f 416//1737 1936//1678 1339//1677 +f 416//1737 1339//1677 1920//1530 +f 416//1737 1920//1530 1322//1648 +f 416//1737 1322//1648 1922//1647 +f 416//1737 1922//1647 1371//1738 +f 417//1739 1222//1444 1817//1437 +f 417//1739 1817//1437 1372//1740 +f 417//1739 1372//1740 1953//1717 +f 417//1739 1953//1717 1364//1727 +f 417//1739 1364//1727 1935//1674 +f 417//1739 1935//1674 1336//1673 +f 417//1739 1336//1673 1887//1445 +f 417//1739 1887//1445 1222//1444 +f 418//1741 1340//1679 1936//1678 +f 418//1741 1936//1678 1367//1732 +f 418//1741 1367//1732 1954//1721 +f 418//1741 1954//1721 1373//1742 +f 418//1741 1373//1742 1818//1441 +f 418//1741 1818//1441 1225//1450 +f 418//1741 1225//1450 1888//1449 +f 418//1741 1888//1449 1340//1679 +f 419//1743 1372//1740 1817//1437 +f 419//1743 1817//1437 1334//1668 +f 419//1743 1334//1668 1947//1654 +f 419//1743 1947//1654 1374//1744 +f 419//1743 1374//1744 1951//1693 +f 419//1743 1951//1693 1359//1718 +f 419//1743 1359//1718 1953//1717 +f 419//1743 1953//1717 1372//1740 +f 420//1745 1361//1720 1952//1697 +f 420//1745 1952//1697 1375//1746 +f 420//1745 1375//1746 1948//1660 +f 420//1745 1948//1660 1335//1670 +f 420//1745 1335//1670 1818//1441 +f 420//1745 1818//1441 1373//1742 +f 420//1745 1373//1742 1954//1721 +f 420//1745 1954//1721 1361//1720 +f 421//1747 1374//1744 1947//1654 +f 421//1747 1947//1654 1325//1653 +f 421//1747 1325//1653 1949//1652 +f 421//1747 1949//1652 1347//1694 +f 421//1747 1347//1694 1951//1693 +f 421//1747 1951//1693 1374//1744 +f 422//1748 1375//1746 1952//1697 +f 422//1748 1952//1697 1349//1696 +f 422//1748 1349//1696 1950//1657 +f 422//1748 1950//1657 1329//1656 +f 422//1748 1329//1656 1948//1660 +f 422//1748 1948//1660 1375//1746 +f 423//1749 1378//1750 1921//1643 +f 423//1749 1921//1643 1370//1736 +f 423//1749 1370//1736 1955//1729 +f 423//1749 1955//1729 1376//1751 +f 423//1749 1376//1751 1957//1752 +f 423//1749 1957//1752 1377//1753 +f 423//1749 1377//1753 1981//1754 +f 423//1749 1981//1754 1378//1750 +f 424//1755 1381//1756 1958//1757 +f 424//1755 1958//1757 1379//1758 +f 424//1755 1379//1758 1956//1734 +f 424//1755 1956//1734 1371//1738 +f 424//1755 1371//1738 1922//1647 +f 424//1755 1922//1647 1380//1759 +f 424//1755 1380//1759 1982//1760 +f 424//1755 1982//1760 1381//1756 +f 425//1761 1376//1751 1955//1729 +f 425//1761 1955//1729 1365//1728 +f 425//1761 1365//1728 1937//1715 +f 425//1761 1937//1715 1382//1762 +f 425//1761 1382//1762 1967//1763 +f 425//1761 1967//1763 1383//1764 +f 425//1761 1383//1764 1957//1752 +f 425//1761 1957//1752 1376//1751 +f 426//1765 1385//1766 1968//1767 +f 426//1765 1968//1767 1384//1768 +f 426//1765 1384//1768 1938//1723 +f 426//1765 1938//1723 1369//1731 +f 426//1765 1369//1731 1956//1734 +f 426//1765 1956//1734 1379//1758 +f 426//1765 1379//1758 1958//1757 +f 426//1765 1958//1757 1385//1766 +f 427//1769 1382//1762 1937//1715 +f 427//1769 1937//1715 1360//1714 +f 427//1769 1360//1714 1939//1703 +f 427//1769 1939//1703 1386//1770 +f 427//1769 1386//1770 1965//1771 +f 427//1769 1965//1771 1387//1772 +f 427//1769 1387//1772 1967//1763 +f 427//1769 1967//1763 1382//1762 +f 428//1773 1389//1774 1966//1775 +f 428//1773 1966//1775 1388//1776 +f 428//1773 1388//1776 1940//1710 +f 428//1773 1940//1710 1363//1724 +f 428//1773 1363//1724 1938//1723 +f 428//1773 1938//1723 1384//1768 +f 428//1773 1384//1768 1968//1767 +f 428//1773 1968//1767 1389//1774 +f 429//1777 1386//1770 1939//1703 +f 429//1777 1939//1703 1354//1702 +f 429//1777 1354//1702 1941//1706 +f 429//1777 1941//1706 1390//1778 +f 429//1777 1390//1778 1963//1779 +f 429//1777 1963//1779 1391//1780 +f 429//1777 1391//1780 1965//1771 +f 429//1777 1965//1771 1386//1770 +f 430//1781 1393//1782 1964//1783 +f 430//1781 1964//1783 1392//1784 +f 430//1781 1392//1784 1942//1712 +f 430//1781 1942//1712 1356//1711 +f 430//1781 1356//1711 1940//1710 +f 430//1781 1940//1710 1388//1776 +f 430//1781 1388//1776 1966//1775 +f 430//1781 1966//1775 1393//1782 +f 431//1785 1390//1778 1941//1706 +f 431//1785 1941//1706 1353//1705 +f 431//1785 1353//1705 1943//1691 +f 431//1785 1943//1691 1394//1786 +f 431//1785 1394//1786 1961//1787 +f 431//1785 1961//1787 1395//1788 +f 431//1785 1395//1788 1963//1779 +f 431//1785 1963//1779 1390//1778 +f 432//1789 1397//1790 1962//1791 +f 432//1789 1962//1791 1396//1792 +f 432//1789 1396//1792 1944//1699 +f 432//1789 1944//1699 1357//1708 +f 432//1789 1357//1708 1942//1712 +f 432//1789 1942//1712 1392//1784 +f 432//1789 1392//1784 1964//1783 +f 432//1789 1964//1783 1397//1790 +f 433//1793 1394//1786 1943//1691 +f 433//1793 1943//1691 1348//1690 +f 433//1793 1348//1690 1945//1683 +f 433//1793 1945//1683 1398//1794 +f 433//1793 1398//1794 1959//1795 +f 433//1793 1959//1795 1399//1796 +f 433//1793 1399//1796 1961//1787 +f 433//1793 1961//1787 1394//1786 +f 434//1797 1401//1798 1960//1799 +f 434//1797 1960//1799 1400//1800 +f 434//1797 1400//1800 1946//1687 +f 434//1797 1946//1687 1351//1700 +f 434//1797 1351//1700 1944//1699 +f 434//1797 1944//1699 1396//1792 +f 434//1797 1396//1792 1962//1791 +f 434//1797 1962//1791 1401//1798 +f 435//1801 1398//1794 1945//1683 +f 435//1801 1945//1683 1342//1682 +f 435//1801 1342//1682 1923//1601 +f 435//1801 1923//1601 1402//1802 +f 435//1801 1402//1802 1979//1803 +f 435//1801 1979//1803 1403//1804 +f 435//1801 1403//1804 1959//1795 +f 435//1801 1959//1795 1398//1794 +f 436//1805 1405//1806 1980//1807 +f 436//1805 1980//1807 1404//1808 +f 436//1805 1404//1808 1924//1605 +f 436//1805 1924//1605 1344//1688 +f 436//1805 1344//1688 1946//1687 +f 436//1805 1946//1687 1400//1800 +f 436//1805 1400//1800 1960//1799 +f 436//1805 1960//1799 1405//1806 +f 437//1809 1407//1810 1933//1635 +f 437//1809 1933//1635 1321//1644 +f 437//1809 1321//1644 1921//1643 +f 437//1809 1921//1643 1378//1750 +f 437//1809 1378//1750 1981//1754 +f 437//1809 1981//1754 1406//1811 +f 437//1809 1406//1811 1969//1812 +f 437//1809 1969//1812 1407//1810 +f 438//1813 1409//1814 1982//1760 +f 438//1813 1982//1760 1380//1759 +f 438//1813 1380//1759 1922//1647 +f 438//1813 1922//1647 1323//1646 +f 438//1813 1323//1646 1934//1639 +f 438//1813 1934//1639 1408//1815 +f 438//1813 1408//1815 1970//1816 +f 438//1813 1970//1816 1409//1814 +f 439//1817 1411//1818 1931//1627 +f 439//1817 1931//1627 1317//1636 +f 439//1817 1317//1636 1933//1635 +f 439//1817 1933//1635 1407//1810 +f 439//1817 1407//1810 1969//1812 +f 439//1817 1969//1812 1410//1819 +f 439//1817 1410//1819 1971//1820 +f 439//1817 1971//1820 1411//1818 +f 440//1821 1413//1822 1970//1816 +f 440//1821 1970//1816 1408//1815 +f 440//1821 1408//1815 1934//1639 +f 440//1821 1934//1639 1318//1638 +f 440//1821 1318//1638 1932//1631 +f 440//1821 1932//1631 1412//1823 +f 440//1821 1412//1823 1972//1824 +f 440//1821 1972//1824 1413//1822 +f 441//1825 1415//1826 1929//1619 +f 441//1825 1929//1619 1313//1628 +f 441//1825 1313//1628 1931//1627 +f 441//1825 1931//1627 1411//1818 +f 441//1825 1411//1818 1971//1820 +f 441//1825 1971//1820 1414//1827 +f 441//1825 1414//1827 1973//1828 +f 441//1825 1973//1828 1415//1826 +f 442//1829 1417//1830 1972//1824 +f 442//1829 1972//1824 1412//1823 +f 442//1829 1412//1823 1932//1631 +f 442//1829 1932//1631 1314//1630 +f 442//1829 1314//1630 1930//1623 +f 442//1829 1930//1623 1416//1831 +f 442//1829 1416//1831 1974//1832 +f 442//1829 1974//1832 1417//1830 +f 443//1833 1419//1834 1927//1611 +f 443//1833 1927//1611 1309//1620 +f 443//1833 1309//1620 1929//1619 +f 443//1833 1929//1619 1415//1826 +f 443//1833 1415//1826 1973//1828 +f 443//1833 1973//1828 1418//1835 +f 443//1833 1418//1835 1975//1836 +f 443//1833 1975//1836 1419//1834 +f 444//1837 1421//1838 1974//1832 +f 444//1837 1974//1832 1416//1831 +f 444//1837 1416//1831 1930//1623 +f 444//1837 1930//1623 1310//1622 +f 444//1837 1310//1622 1928//1615 +f 444//1837 1928//1615 1420//1839 +f 444//1837 1420//1839 1976//1840 +f 444//1837 1976//1840 1421//1838 +f 445//1841 1423//1842 1925//1599 +f 445//1841 1925//1599 1305//1612 +f 445//1841 1305//1612 1927//1611 +f 445//1841 1927//1611 1419//1834 +f 445//1841 1419//1834 1975//1836 +f 445//1841 1975//1836 1422//1843 +f 445//1841 1422//1843 1977//1844 +f 445//1841 1977//1844 1423//1842 +f 446//1845 1425//1846 1976//1840 +f 446//1845 1976//1840 1420//1839 +f 446//1845 1420//1839 1928//1615 +f 446//1845 1928//1615 1306//1614 +f 446//1845 1306//1614 1926//1607 +f 446//1845 1926//1607 1424//1847 +f 446//1845 1424//1847 1978//1848 +f 446//1845 1978//1848 1425//1846 +f 447//1849 1402//1802 1923//1601 +f 447//1849 1923//1601 1299//1600 +f 447//1849 1299//1600 1925//1599 +f 447//1849 1925//1599 1423//1842 +f 447//1849 1423//1842 1977//1844 +f 447//1849 1977//1844 1426//1850 +f 447//1849 1426//1850 1979//1803 +f 447//1849 1979//1803 1402//1802 +f 448//1851 1427//1852 1978//1848 +f 448//1851 1978//1848 1424//1847 +f 448//1851 1424//1847 1926//1607 +f 448//1851 1926//1607 1301//1606 +f 448//1851 1301//1606 1924//1605 +f 448//1851 1924//1605 1404//1808 +f 448//1851 1404//1808 1980//1807 +f 448//1851 1980//1807 1427//1852 +f 449//1853 1430//1854 1963//1779 +f 449//1853 1963//1779 1395//1788 +f 449//1853 1395//1788 1961//1787 +f 449//1853 1961//1787 1428//1855 +f 449//1853 1428//1855 1985//1856 +f 449//1853 1985//1856 1429//1857 +f 449//1853 1429//1857 1983//1858 +f 449//1853 1983//1858 1430//1854 +f 450//1859 1433//1860 1986//1861 +f 450//1859 1986//1861 1431//1862 +f 450//1859 1431//1862 1962//1791 +f 450//1859 1962//1791 1397//1790 +f 450//1859 1397//1790 1964//1783 +f 450//1859 1964//1783 1432//1863 +f 450//1859 1432//1863 1984//1864 +f 450//1859 1984//1864 1433//1860 +f 451//1865 1436//1866 1983//1858 +f 451//1865 1983//1858 1429//1857 +f 451//1865 1429//1857 1985//1856 +f 451//1865 1985//1856 1434//1867 +f 451//1865 1434//1867 1987//1868 +f 451//1865 1987//1868 1435//1869 +f 451//1865 1435//1869 1989//1870 +f 451//1865 1989//1870 1436//1866 +f 452//1871 1439//1872 1988//1873 +f 452//1871 1988//1873 1437//1874 +f 452//1871 1437//1874 1986//1861 +f 452//1871 1986//1861 1433//1860 +f 452//1871 1433//1860 1984//1864 +f 452//1871 1984//1864 1438//1875 +f 452//1871 1438//1875 1990//1876 +f 452//1871 1990//1876 1439//1872 +f 453//1877 1442//1878 1989//1870 +f 453//1877 1989//1870 1435//1869 +f 453//1877 1435//1869 1987//1868 +f 453//1877 1987//1868 1440//1879 +f 453//1877 1440//1879 1993//1880 +f 453//1877 1993//1880 1441//1881 +f 453//1877 1441//1881 1991//1882 +f 453//1877 1991//1882 1442//1878 +f 454//1883 1445//1884 1994//1885 +f 454//1883 1994//1885 1443//1886 +f 454//1883 1443//1886 1988//1873 +f 454//1883 1988//1873 1439//1872 +f 454//1883 1439//1872 1990//1876 +f 454//1883 1990//1876 1444//1887 +f 454//1883 1444//1887 1992//1888 +f 454//1883 1992//1888 1445//1884 +f 455//1889 1448//1890 1991//1882 +f 455//1889 1991//1882 1441//1881 +f 455//1889 1441//1881 1993//1880 +f 455//1889 1993//1880 1446//1891 +f 455//1889 1446//1891 1995//1892 +f 455//1889 1995//1892 1447//1893 +f 455//1889 1447//1893 1997//1894 +f 455//1889 1997//1894 1448//1890 +f 456//1895 1451//1896 1996//1897 +f 456//1895 1996//1897 1449//1898 +f 456//1895 1449//1898 1994//1885 +f 456//1895 1994//1885 1445//1884 +f 456//1895 1445//1884 1992//1888 +f 456//1895 1992//1888 1450//1899 +f 456//1895 1450//1899 1998//1900 +f 456//1895 1998//1900 1451//1896 +f 457//1901 1453//1902 1969//1812 +f 457//1901 1969//1812 1406//1811 +f 457//1901 1406//1811 1981//1754 +f 457//1901 1981//1754 1452//1903 +f 457//1901 1452//1903 1991//1882 +f 457//1901 1991//1882 1448//1890 +f 457//1901 1448//1890 1997//1894 +f 457//1901 1997//1894 1453//1902 +f 458//1904 1450//1899 1992//1888 +f 458//1904 1992//1888 1454//1905 +f 458//1904 1454//1905 1982//1760 +f 458//1904 1982//1760 1409//1814 +f 458//1904 1409//1814 1970//1816 +f 458//1904 1970//1816 1455//1906 +f 458//1904 1455//1906 1998//1900 +f 458//1904 1998//1900 1450//1899 +f 459//1907 1377//1753 1957//1752 +f 459//1907 1957//1752 1456//1908 +f 459//1907 1456//1908 1989//1870 +f 459//1907 1989//1870 1442//1878 +f 459//1907 1442//1878 1991//1882 +f 459//1907 1991//1882 1452//1903 +f 459//1907 1452//1903 1981//1754 +f 459//1907 1981//1754 1377//1753 +f 460//1909 1454//1905 1992//1888 +f 460//1909 1992//1888 1444//1887 +f 460//1909 1444//1887 1990//1876 +f 460//1909 1990//1876 1457//1910 +f 460//1909 1457//1910 1958//1757 +f 460//1909 1958//1757 1381//1756 +f 460//1909 1381//1756 1982//1760 +f 460//1909 1982//1760 1454//1905 +f 461//1911 1456//1908 1957//1752 +f 461//1911 1957//1752 1383//1764 +f 461//1911 1383//1764 1967//1763 +f 461//1911 1967//1763 1458//1912 +f 461//1911 1458//1912 1983//1858 +f 461//1911 1983//1858 1436//1866 +f 461//1911 1436//1866 1989//1870 +f 461//1911 1989//1870 1456//1908 +f 462//1913 1438//1875 1984//1864 +f 462//1913 1984//1864 1459//1914 +f 462//1913 1459//1914 1968//1767 +f 462//1913 1968//1767 1385//1766 +f 462//1913 1385//1766 1958//1757 +f 462//1913 1958//1757 1457//1910 +f 462//1913 1457//1910 1990//1876 +f 462//1913 1990//1876 1438//1875 +f 463//1915 1391//1780 1963//1779 +f 463//1915 1963//1779 1430//1854 +f 463//1915 1430//1854 1983//1858 +f 463//1915 1983//1858 1458//1912 +f 463//1915 1458//1912 1967//1763 +f 463//1915 1967//1763 1387//1772 +f 463//1915 1387//1772 1965//1771 +f 463//1915 1965//1771 1391//1780 +f 464//1916 1389//1774 1968//1767 +f 464//1916 1968//1767 1459//1914 +f 464//1916 1459//1914 1984//1864 +f 464//1916 1984//1864 1432//1863 +f 464//1916 1432//1863 1964//1783 +f 464//1916 1964//1783 1393//1782 +f 464//1916 1393//1782 1966//1775 +f 464//1916 1966//1775 1389//1774 +f 465//1917 1399//1796 1959//1795 +f 465//1917 1959//1795 1403//1804 +f 465//1917 1403//1804 1979//1803 +f 465//1917 1979//1803 1460//1918 +f 465//1917 1460//1918 1985//1856 +f 465//1917 1985//1856 1428//1855 +f 465//1917 1428//1855 1961//1787 +f 465//1917 1961//1787 1399//1796 +f 466//1919 1431//1862 1986//1861 +f 466//1919 1986//1861 1461//1920 +f 466//1919 1461//1920 1980//1807 +f 466//1919 1980//1807 1405//1806 +f 466//1919 1405//1806 1960//1799 +f 466//1919 1960//1799 1401//1798 +f 466//1919 1401//1798 1962//1791 +f 466//1919 1962//1791 1431//1862 +f 467//1921 1426//1850 1977//1844 +f 467//1921 1977//1844 1462//1922 +f 467//1921 1462//1922 1987//1868 +f 467//1921 1987//1868 1434//1867 +f 467//1921 1434//1867 1985//1856 +f 467//1921 1985//1856 1460//1918 +f 467//1921 1460//1918 1979//1803 +f 467//1921 1979//1803 1426//1850 +f 468//1923 1461//1920 1986//1861 +f 468//1923 1986//1861 1437//1874 +f 468//1923 1437//1874 1988//1873 +f 468//1923 1988//1873 1463//1924 +f 468//1923 1463//1924 1978//1848 +f 468//1923 1978//1848 1427//1852 +f 468//1923 1427//1852 1980//1807 +f 468//1923 1980//1807 1461//1920 +f 469//1925 1422//1843 1975//1836 +f 469//1925 1975//1836 1464//1926 +f 469//1925 1464//1926 1993//1880 +f 469//1925 1993//1880 1440//1879 +f 469//1925 1440//1879 1987//1868 +f 469//1925 1987//1868 1462//1922 +f 469//1925 1462//1922 1977//1844 +f 469//1925 1977//1844 1422//1843 +f 470//1927 1463//1924 1988//1873 +f 470//1927 1988//1873 1443//1886 +f 470//1927 1443//1886 1994//1885 +f 470//1927 1994//1885 1465//1928 +f 470//1927 1465//1928 1976//1840 +f 470//1927 1976//1840 1425//1846 +f 470//1927 1425//1846 1978//1848 +f 470//1927 1978//1848 1463//1924 +f 471//1929 1418//1835 1973//1828 +f 471//1929 1973//1828 1466//1930 +f 471//1929 1466//1930 1995//1892 +f 471//1929 1995//1892 1446//1891 +f 471//1929 1446//1891 1993//1880 +f 471//1929 1993//1880 1464//1926 +f 471//1929 1464//1926 1975//1836 +f 471//1929 1975//1836 1418//1835 +f 472//1931 1465//1928 1994//1885 +f 472//1931 1994//1885 1449//1898 +f 472//1931 1449//1898 1996//1897 +f 472//1931 1996//1897 1467//1932 +f 472//1931 1467//1932 1974//1832 +f 472//1931 1974//1832 1421//1838 +f 472//1931 1421//1838 1976//1840 +f 472//1931 1976//1840 1465//1928 +f 473//1933 1414//1827 1971//1820 +f 473//1933 1971//1820 1468//1934 +f 473//1933 1468//1934 1997//1894 +f 473//1933 1997//1894 1447//1893 +f 473//1933 1447//1893 1995//1892 +f 473//1933 1995//1892 1466//1930 +f 473//1933 1466//1930 1973//1828 +f 473//1933 1973//1828 1414//1827 +f 474//1935 1467//1932 1996//1897 +f 474//1935 1996//1897 1451//1896 +f 474//1935 1451//1896 1998//1900 +f 474//1935 1998//1900 1469//1936 +f 474//1935 1469//1936 1972//1824 +f 474//1935 1972//1824 1417//1830 +f 474//1935 1417//1830 1974//1832 +f 474//1935 1974//1832 1467//1932 +f 475//1937 1410//1819 1969//1812 +f 475//1937 1969//1812 1453//1902 +f 475//1937 1453//1902 1997//1894 +f 475//1937 1997//1894 1468//1934 +f 475//1937 1468//1934 1971//1820 +f 475//1937 1971//1820 1410//1819 +f 476//1938 1413//1822 1972//1824 +f 476//1938 1972//1824 1469//1936 +f 476//1938 1469//1936 1998//1900 +f 476//1938 1998//1900 1455//1906 +f 476//1938 1455//1906 1970//1816 +f 476//1938 1970//1816 1413//1822 +f 477//1939 1472//1940 1897//1578 +f 477//1939 1897//1578 1294//1586 +f 477//1939 1294//1586 1895//1590 +f 477//1939 1895//1590 1470//1941 +f 477//1939 1470//1941 2009//1942 +f 477//1939 2009//1942 1471//1943 +f 477//1939 1471//1943 2007//1944 +f 477//1939 2007//1944 1472//1940 +f 478//1945 1475//1946 2010//1947 +f 478//1945 2010//1947 1473//1948 +f 478//1945 1473//1948 1896//1596 +f 478//1945 1896//1596 1296//1595 +f 478//1945 1296//1595 1898//1584 +f 478//1945 1898//1584 1474//1949 +f 478//1945 1474//1949 2008//1950 +f 478//1945 2008//1950 1475//1946 +f 479//1951 1477//1952 1899//1566 +f 479//1951 1899//1566 1288//1574 +f 479//1951 1288//1574 1897//1578 +f 479//1951 1897//1578 1472//1940 +f 479//1951 1472//1940 2007//1944 +f 479//1951 2007//1944 1476//1953 +f 479//1951 1476//1953 2005//1954 +f 479//1951 2005//1954 1477//1952 +f 480//1955 1479//1956 2008//1950 +f 480//1955 2008//1950 1474//1949 +f 480//1955 1474//1949 1898//1584 +f 480//1955 1898//1584 1290//1583 +f 480//1955 1290//1583 1900//1572 +f 480//1955 1900//1572 1478//1957 +f 480//1955 1478//1957 2006//1958 +f 480//1955 2006//1958 1479//1956 +f 481//1959 1481//1960 1901//1554 +f 481//1959 1901//1554 1282//1562 +f 481//1959 1282//1562 1899//1566 +f 481//1959 1899//1566 1477//1952 +f 481//1959 1477//1952 2005//1954 +f 481//1959 2005//1954 1480//1961 +f 481//1959 1480//1961 2003//1962 +f 481//1959 2003//1962 1481//1960 +f 482//1963 1483//1964 2006//1958 +f 482//1963 2006//1958 1478//1957 +f 482//1963 1478//1957 1900//1572 +f 482//1963 1900//1572 1284//1571 +f 482//1963 1284//1571 1902//1560 +f 482//1963 1902//1560 1482//1965 +f 482//1963 1482//1965 2004//1966 +f 482//1963 2004//1966 1483//1964 +f 483//1967 1485//1968 1903//1542 +f 483//1967 1903//1542 1276//1550 +f 483//1967 1276//1550 1901//1554 +f 483//1967 1901//1554 1481//1960 +f 483//1967 1481//1960 2003//1962 +f 483//1967 2003//1962 1484//1969 +f 483//1967 1484//1969 2001//1970 +f 483//1967 2001//1970 1485//1968 +f 484//1971 1487//1972 2004//1966 +f 484//1971 2004//1966 1482//1965 +f 484//1971 1482//1965 1902//1560 +f 484//1971 1902//1560 1278//1559 +f 484//1971 1278//1559 1904//1548 +f 484//1971 1904//1548 1486//1973 +f 484//1971 1486//1973 2002//1974 +f 484//1971 2002//1974 1487//1972 +f 485//1975 1489//1976 1905//1521 +f 485//1975 1905//1521 1270//1538 +f 485//1975 1270//1538 1903//1542 +f 485//1975 1903//1542 1485//1968 +f 485//1975 1485//1968 2001//1970 +f 485//1975 2001//1970 1488//1977 +f 485//1975 1488//1977 1999//1978 +f 485//1975 1999//1978 1489//1976 +f 486//1979 1491//1980 2002//1974 +f 486//1979 2002//1974 1486//1973 +f 486//1979 1486//1973 1904//1548 +f 486//1979 1904//1548 1272//1547 +f 486//1979 1272//1547 1906//1534 +f 486//1979 1906//1534 1490//1981 +f 486//1979 1490//1981 2000//1982 +f 486//1979 2000//1982 1491//1980 +f 487//1983 1493//1984 1893//1523 +f 487//1983 1893//1523 1260//1522 +f 487//1983 1260//1522 1905//1521 +f 487//1983 1905//1521 1489//1976 +f 487//1983 1489//1976 1999//1978 +f 487//1983 1999//1978 1492//1985 +f 487//1983 1492//1985 2011//1986 +f 487//1983 2011//1986 1493//1984 +f 488//1987 1495//1988 2000//1982 +f 488//1987 2000//1982 1490//1981 +f 488//1987 1490//1981 1906//1534 +f 488//1987 1906//1534 1265//1533 +f 488//1987 1265//1533 1894//1532 +f 488//1987 1894//1532 1494//1989 +f 488//1987 1494//1989 2012//1990 +f 488//1987 2012//1990 1495//1988 +f 489//1991 1492//1985 1999//1978 +f 489//1991 1999//1978 1496//1992 +f 489//1991 1496//1992 2007//1944 +f 489//1991 2007//1944 1471//1943 +f 489//1991 1471//1943 2009//1942 +f 489//1991 2009//1942 1497//1993 +f 489//1991 1497//1993 2011//1986 +f 489//1991 2011//1986 1492//1985 +f 490//1994 1499//1995 2010//1947 +f 490//1994 2010//1947 1475//1946 +f 490//1994 1475//1946 2008//1950 +f 490//1994 2008//1950 1498//1996 +f 490//1994 1498//1996 2000//1982 +f 490//1994 2000//1982 1495//1988 +f 490//1994 1495//1988 2012//1990 +f 490//1994 2012//1990 1499//1995 +f 491//1997 1496//1992 1999//1978 +f 491//1997 1999//1978 1488//1977 +f 491//1997 1488//1977 2001//1970 +f 491//1997 2001//1970 1500//1998 +f 491//1997 1500//1998 2005//1954 +f 491//1997 2005//1954 1476//1953 +f 491//1997 1476//1953 2007//1944 +f 491//1997 2007//1944 1496//1992 +f 492//1999 1479//1956 2006//1958 +f 492//1999 2006//1958 1501//2000 +f 492//1999 1501//2000 2002//1974 +f 492//1999 2002//1974 1491//1980 +f 492//1999 1491//1980 2000//1982 +f 492//1999 2000//1982 1498//1996 +f 492//1999 1498//1996 2008//1950 +f 492//1999 2008//1950 1479//1956 +f 493//2001 1500//1998 2001//1970 +f 493//2001 2001//1970 1484//1969 +f 493//2001 1484//1969 2003//1962 +f 493//2001 2003//1962 1480//1961 +f 493//2001 1480//1961 2005//1954 +f 493//2001 2005//1954 1500//1998 +f 494//2002 1501//2000 2006//1958 +f 494//2002 2006//1958 1483//1964 +f 494//2002 1483//1964 2004//1966 +f 494//2002 2004//1966 1487//1972 +f 494//2002 1487//1972 2002//1974 +f 494//2002 2002//1974 1501//2000 +f 495//2003 1502//2004 1819//1378 +f 495//2003 1819//1378 1226//1452 +f 495//2003 1226//1452 1887//1445 +f 495//2003 1887//1445 1338//1672 +f 495//2003 1338//1672 1893//1523 +f 495//2003 1893//1523 1493//1984 +f 495//2003 1493//1984 2011//1986 +f 495//2003 2011//1986 1502//2004 +f 496//2005 1494//1989 1894//1532 +f 496//2005 1894//1532 1341//1680 +f 496//2005 1341//1680 1888//1449 +f 496//2005 1888//1449 1227//1454 +f 496//2005 1227//1454 1820//1386 +f 496//2005 1820//1386 1503//2006 +f 496//2005 1503//2006 2012//1990 +f 496//2005 2012//1990 1494//1989 +f 497//2007 1246//1492 1819//1378 +f 497//2007 1819//1378 1502//2004 +f 497//2007 1502//2004 2011//1986 +f 497//2007 2011//1986 1497//1993 +f 497//2007 1497//1993 2009//1942 +f 497//2007 2009//1942 1504//2008 +f 497//2007 1504//2008 1827//1493 +f 497//2007 1827//1493 1246//1492 +f 498//2009 1505//2010 2010//1947 +f 498//2009 2010//1947 1499//1995 +f 498//2009 1499//1995 2012//1990 +f 498//2009 2012//1990 1503//2006 +f 498//2009 1503//2006 1820//1386 +f 498//2009 1820//1386 1250//1502 +f 498//2009 1250//1502 1828//1501 +f 498//2009 1828//1501 1505//2010 +f 499//2011 1330//1662 1825//1471 +f 499//2011 1825//1471 1255//1508 +f 499//2011 1255//1508 1827//1493 +f 499//2011 1827//1493 1504//2008 +f 499//2011 1504//2008 2009//1942 +f 499//2011 2009//1942 1470//1941 +f 499//2011 1470//1941 1895//1590 +f 499//2011 1895//1590 1330//1662 +f 500//2012 1473//1948 2010//1947 +f 500//2012 2010//1947 1505//2010 +f 500//2012 1505//2010 1828//1501 +f 500//2012 1828//1501 1257//1512 +f 500//2012 1257//1512 1826//1476 +f 500//2012 1826//1476 1332//1666 +f 500//2012 1332//1666 1896//1596 +f 500//2012 1896//1596 1473//1948 diff --git a/freechat-client/share/kivy-examples/3Drendering/objloader.py b/freechat-client/share/kivy-examples/3Drendering/objloader.py new file mode 100644 index 0000000..c30a0db --- /dev/null +++ b/freechat-client/share/kivy-examples/3Drendering/objloader.py @@ -0,0 +1,147 @@ +class MeshData(object): + def __init__(self, **kwargs): + self.name = kwargs.get("name") + self.vertex_format = [ + (b'v_pos', 3, 'float'), + (b'v_normal', 3, 'float'), + (b'v_tc0', 2, 'float')] + self.vertices = [] + self.indices = [] + + def calculate_normals(self): + for i in range(len(self.indices) / (3)): + fi = i * 3 + v1i = self.indices[fi] + v2i = self.indices[fi + 1] + v3i = self.indices[fi + 2] + + vs = self.vertices + p1 = [vs[v1i + c] for c in range(3)] + p2 = [vs[v2i + c] for c in range(3)] + p3 = [vs[v3i + c] for c in range(3)] + + u, v = [0, 0, 0], [0, 0, 0] + for j in range(3): + v[j] = p2[j] - p1[j] + u[j] = p3[j] - p1[j] + + n = [0, 0, 0] + n[0] = u[1] * v[2] - u[2] * v[1] + n[1] = u[2] * v[0] - u[0] * v[2] + n[2] = u[0] * v[1] - u[1] * v[0] + + for k in range(3): + self.vertices[v1i + 3 + k] = n[k] + self.vertices[v2i + 3 + k] = n[k] + self.vertices[v3i + 3 + k] = n[k] + + +class ObjFile: + def finish_object(self): + if self._current_object is None: + return + + mesh = MeshData() + idx = 0 + for f in self.faces: + verts = f[0] + norms = f[1] + tcs = f[2] + for i in range(3): + # get normal components + n = (0.0, 0.0, 0.0) + if norms[i] != -1: + n = self.normals[norms[i] - 1] + + # get texture coordinate components + t = (0.0, 0.0) + if tcs[i] != -1: + t = self.texcoords[tcs[i] - 1] + + # get vertex components + v = self.vertices[verts[i] - 1] + + data = [v[0], v[1], v[2], n[0], n[1], n[2], t[0], t[1]] + mesh.vertices.extend(data) + + tri = [idx, idx + 1, idx + 2] + mesh.indices.extend(tri) + idx += 3 + + self.objects[self._current_object] = mesh + # mesh.calculate_normals() + self.faces = [] + + def __init__(self, filename, swapyz=False): + """Loads a Wavefront OBJ file. """ + self.objects = {} + self.vertices = [] + self.normals = [] + self.texcoords = [] + self.faces = [] + + self._current_object = None + + material = None + for line in open(filename, "r"): + if line.startswith('#'): + continue + if line.startswith('s'): + continue + values = line.split() + if not values: + continue + if values[0] == 'o': + self.finish_object() + self._current_object = values[1] + # elif values[0] == 'mtllib': + # self.mtl = MTL(values[1]) + # elif values[0] in ('usemtl', 'usemat'): + # material = values[1] + if values[0] == 'v': + v = list(map(float, values[1:4])) + if swapyz: + v = v[0], v[2], v[1] + self.vertices.append(v) + elif values[0] == 'vn': + v = list(map(float, values[1:4])) + if swapyz: + v = v[0], v[2], v[1] + self.normals.append(v) + elif values[0] == 'vt': + self.texcoords.append(map(float, values[1:3])) + elif values[0] == 'f': + face = [] + texcoords = [] + norms = [] + for v in values[1:]: + w = v.split('/') + face.append(int(w[0])) + if len(w) >= 2 and len(w[1]) > 0: + texcoords.append(int(w[1])) + else: + texcoords.append(-1) + if len(w) >= 3 and len(w[2]) > 0: + norms.append(int(w[2])) + else: + norms.append(-1) + self.faces.append((face, norms, texcoords, material)) + self.finish_object() + + +def MTL(filename): + contents = {} + mtl = None + return + for line in open(filename, "r"): + if line.startswith('#'): + continue + values = line.split() + if not values: + continue + if values[0] == 'newmtl': + mtl = contents[values[1]] = {} + elif mtl is None: + raise ValueError("mtl file doesn't start with newmtl stmt") + mtl[values[0]] = values[1:] + return contents diff --git a/freechat-client/share/kivy-examples/3Drendering/simple.glsl b/freechat-client/share/kivy-examples/3Drendering/simple.glsl new file mode 100644 index 0000000..b95c116 --- /dev/null +++ b/freechat-client/share/kivy-examples/3Drendering/simple.glsl @@ -0,0 +1,47 @@ +/* simple.glsl + +simple diffuse lighting based on laberts cosine law; see e.g.: + http://en.wikipedia.org/wiki/Lambertian_reflectance + http://en.wikipedia.org/wiki/Lambert%27s_cosine_law +*/ +---VERTEX SHADER------------------------------------------------------- +#ifdef GL_ES + precision highp float; +#endif + +attribute vec3 v_pos; +attribute vec3 v_normal; + +uniform mat4 modelview_mat; +uniform mat4 projection_mat; + +varying vec4 normal_vec; +varying vec4 vertex_pos; + +void main (void) { + //compute vertex position in eye_space and normalize normal vector + vec4 pos = modelview_mat * vec4(v_pos,1.0); + vertex_pos = pos; + normal_vec = vec4(v_normal,0.0); + gl_Position = projection_mat * pos; +} + + +---FRAGMENT SHADER----------------------------------------------------- +#ifdef GL_ES + precision highp float; +#endif + +varying vec4 normal_vec; +varying vec4 vertex_pos; + +uniform mat4 normal_mat; + +void main (void){ + //correct normal, and compute light vector (assume light at the eye) + vec4 v_normal = normalize( normal_mat * normal_vec ) ; + vec4 v_light = normalize( vec4(0,0,0,1) - vertex_pos ); + //reflectance based on lamberts law of cosine + float theta = clamp(dot(v_normal, v_light), 0.0, 1.0); + gl_FragColor = vec4(theta, theta, theta, 1.0); +} diff --git a/freechat-client/share/kivy-examples/RST_Editor/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/RST_Editor/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..e422fb2 Binary files /dev/null and b/freechat-client/share/kivy-examples/RST_Editor/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/RST_Editor/editor.kv b/freechat-client/share/kivy-examples/RST_Editor/editor.kv new file mode 100644 index 0000000..feeaa5c --- /dev/null +++ b/freechat-client/share/kivy-examples/RST_Editor/editor.kv @@ -0,0 +1,72 @@ +#:kivy 1.1.0 + +Root: + text_input: text_input + + BoxLayout: + orientation: 'vertical' + BoxLayout: + size_hint_y: None + height: 30 + Button: + text: 'Load' + on_release: root.show_load() + Button: + text: 'Save' + on_release: root.show_save() + + BoxLayout: + TextInput: + id: text_input + text: '' + + RstDocument: + text: text_input.text + show_errors: True + +: + BoxLayout: + size: root.size + pos: root.pos + orientation: "vertical" + FileChooserListView: + id: filechooser + + BoxLayout: + size_hint_y: None + height: 30 + Button: + text: "Cancel" + on_release: root.cancel() + + Button: + text: "Load" + on_release: root.load(filechooser.path, filechooser.selection) + +: + text_input: text_input + BoxLayout: + size: root.size + pos: root.pos + orientation: "vertical" + FileChooserListView: + id: filechooser + on_selection: text_input.text = self.selection and self.selection[0] or '' + + TextInput: + id: text_input + size_hint_y: None + height: 30 + multiline: False + + BoxLayout: + size_hint_y: None + height: 30 + Button: + text: "Cancel" + on_release: root.cancel() + + Button: + text: "Save" + on_release: root.save(filechooser.path, text_input.text) + diff --git a/freechat-client/share/kivy-examples/RST_Editor/main.py b/freechat-client/share/kivy-examples/RST_Editor/main.py new file mode 100644 index 0000000..2423ed0 --- /dev/null +++ b/freechat-client/share/kivy-examples/RST_Editor/main.py @@ -0,0 +1,64 @@ +from kivy.app import App +from kivy.uix.floatlayout import FloatLayout +from kivy.factory import Factory +from kivy.properties import ObjectProperty +from kivy.uix.popup import Popup + +import os + + +class LoadDialog(FloatLayout): + load = ObjectProperty(None) + cancel = ObjectProperty(None) + + +class SaveDialog(FloatLayout): + save = ObjectProperty(None) + text_input = ObjectProperty(None) + cancel = ObjectProperty(None) + + +class Root(FloatLayout): + loadfile = ObjectProperty(None) + savefile = ObjectProperty(None) + text_input = ObjectProperty(None) + + def dismiss_popup(self): + self._popup.dismiss() + + def show_load(self): + content = LoadDialog(load=self.load, cancel=self.dismiss_popup) + self._popup = Popup(title="Load file", content=content, + size_hint=(0.9, 0.9)) + self._popup.open() + + def show_save(self): + content = SaveDialog(save=self.save, cancel=self.dismiss_popup) + self._popup = Popup(title="Save file", content=content, + size_hint=(0.9, 0.9)) + self._popup.open() + + def load(self, path, filename): + with open(os.path.join(path, filename[0])) as stream: + self.text_input.text = stream.read() + + self.dismiss_popup() + + def save(self, path, filename): + with open(os.path.join(path, filename), 'w') as stream: + stream.write(self.text_input.text) + + self.dismiss_popup() + + +class Editor(App): + pass + + +Factory.register('Root', cls=Root) +Factory.register('LoadDialog', cls=LoadDialog) +Factory.register('SaveDialog', cls=SaveDialog) + + +if __name__ == '__main__': + Editor().run() diff --git a/freechat-client/share/kivy-examples/android/compass/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/android/compass/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..887bb19 Binary files /dev/null and b/freechat-client/share/kivy-examples/android/compass/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/android/compass/android.txt b/freechat-client/share/kivy-examples/android/compass/android.txt new file mode 100644 index 0000000..813307f --- /dev/null +++ b/freechat-client/share/kivy-examples/android/compass/android.txt @@ -0,0 +1,3 @@ +title=Compass +author=Nik Klever +orientation=portrait diff --git a/freechat-client/share/kivy-examples/android/compass/compass.kv b/freechat-client/share/kivy-examples/android/compass/compass.kv new file mode 100644 index 0000000..05eedde --- /dev/null +++ b/freechat-client/share/kivy-examples/android/compass/compass.kv @@ -0,0 +1,25 @@ +#:kivy 1.7.0 + +FloatLayout: + + canvas: + Color: + rgb: .98, .98, .98 + Rectangle: + size: self.size + + Image: + source: 'rose.png' + + Image: + source: 'needle.png' + + canvas.before: + PushMatrix + Rotate: + angle: app.needle_angle + axis: 0, 0, 1 + origin: self.center + + canvas.after: + PopMatrix diff --git a/freechat-client/share/kivy-examples/android/compass/main.py b/freechat-client/share/kivy-examples/android/compass/main.py new file mode 100644 index 0000000..06163ad --- /dev/null +++ b/freechat-client/share/kivy-examples/android/compass/main.py @@ -0,0 +1,77 @@ +''' +Compass example +=============== + +This example is a demonstration of Hardware class usage. +But it has severals drawbacks, like using only the magnetic sensor, and +extrapolating values to get the orientation. The compass is absolutely not +accurate. + +The right way would be to get the accelerometer + magnetic, and computer +everything according to the phone orientation. This is not the purpose of this +example right now. + +You can compile it with:: + + ./build.py --package org.test.compass --name compass \ + --private ~/code/kivy/examples/android/compass \ + --window --version 1.0 debug installd +''' + + +import kivy +kivy.require('1.7.0') + +from jnius import autoclass +from math import floor +from kivy.app import App +from kivy.properties import NumericProperty +from kivy.clock import Clock +from kivy.vector import Vector +from kivy.animation import Animation + +Hardware = autoclass('org.renpy.android.Hardware') + + +class CompassApp(App): + + needle_angle = NumericProperty(0) + + def build(self): + self._anim = None + Hardware.magneticFieldSensorEnable(True) + Clock.schedule_interval(self.update_compass, 1 / 10.) + + def update_compass(self, *args): + # read the magnetic sensor from the Hardware class + (x, y, z) = Hardware.magneticFieldSensorReading() + + # calculate the angle + needle_angle = Vector(x, y).angle((0, 1)) + 90. + + # fix animation transition around the unit circle + if (self.needle_angle % 360) - needle_angle > 180: + needle_angle += 360 + elif (self.needle_angle % 360) - needle_angle < -180: + needle_angle -= 360 + # add the number of revolutions to the result + needle_angle += 360 * floor(self.needle_angle / 360.) + + # animate the needle + if self._anim: + self._anim.stop(self) + self._anim = Animation(needle_angle=needle_angle, d=.2, t='out_quad') + self._anim.start(self) + + def on_pause(self): + # when you are going on pause, don't forget to stop the sensor + Hardware.magneticFieldSensorEnable(False) + return True + + def on_resume(self): + # reactivate the sensor when you are back to the app + Hardware.magneticFieldSensorEnable(True) + + +if __name__ == '__main__': + CompassApp().run() diff --git a/freechat-client/share/kivy-examples/android/compass/needle.png b/freechat-client/share/kivy-examples/android/compass/needle.png new file mode 100644 index 0000000..ba74a19 Binary files /dev/null and b/freechat-client/share/kivy-examples/android/compass/needle.png differ diff --git a/freechat-client/share/kivy-examples/android/compass/rose.png b/freechat-client/share/kivy-examples/android/compass/rose.png new file mode 100644 index 0000000..e400a72 Binary files /dev/null and b/freechat-client/share/kivy-examples/android/compass/rose.png differ diff --git a/freechat-client/share/kivy-examples/android/takepicture/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/android/takepicture/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..10ea795 Binary files /dev/null and b/freechat-client/share/kivy-examples/android/takepicture/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/android/takepicture/android.txt b/freechat-client/share/kivy-examples/android/takepicture/android.txt new file mode 100644 index 0000000..998b899 --- /dev/null +++ b/freechat-client/share/kivy-examples/android/takepicture/android.txt @@ -0,0 +1,3 @@ +title=TakePicture +author=Mathieu Virbel +orientation=portrait diff --git a/freechat-client/share/kivy-examples/android/takepicture/main.py b/freechat-client/share/kivy-examples/android/takepicture/main.py new file mode 100644 index 0000000..43f9756 --- /dev/null +++ b/freechat-client/share/kivy-examples/android/takepicture/main.py @@ -0,0 +1,80 @@ +''' +Take picture +============ + +.. author:: Mathieu Virbel + +Little example to demonstrate how to start an Intent, and get the result. +When you use the Android.startActivityForResult(), the result will be +dispatched into onActivityResult. You can catch the event with the +android.activity API from python-for-android project. + +If you want to compile it, don't forget to add the CAMERA permission:: + + ./build.py --name 'TakePicture' --package org.test.takepicture \ + --permission CAMERA --version 1 \ + --private ~/code/kivy/examples/android/takepicture \ + debug installd + +''' + +__version__ = '0.1' + +from kivy.app import App +from os.path import exists +from jnius import autoclass, cast +from android import activity, mActivity +from functools import partial +from kivy.clock import Clock +from kivy.uix.scatter import Scatter +from kivy.properties import StringProperty + +from PIL import Image + +Intent = autoclass('android.content.Intent') +MediaStore = autoclass('android.provider.MediaStore') +Uri = autoclass('android.net.Uri') +Environment = autoclass('android.os.Environment') + + +class Picture(Scatter): + source = StringProperty(None) + + +class TakePictureApp(App): + def build(self): + self.index = 0 + activity.bind(on_activity_result=self.on_activity_result) + + def get_filename(self): + while True: + self.index += 1 + fn = (Environment.getExternalStorageDirectory().getPath() + + '/takepicture{}.jpg'.format(self.index)) + if not exists(fn): + return fn + + def take_picture(self): + intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) + self.last_fn = self.get_filename() + self.uri = Uri.parse('file://' + self.last_fn) + self.uri = cast('android.os.Parcelable', self.uri) + intent.putExtra(MediaStore.EXTRA_OUTPUT, self.uri) + mActivity.startActivityForResult(intent, 0x123) + + def on_activity_result(self, requestCode, resultCode, intent): + if requestCode == 0x123: + Clock.schedule_once(partial(self.add_picture, self.last_fn), 0) + + def add_picture(self, fn, *args): + im = Image.open(fn) + width, height = im.size + im.thumbnail((width / 4, height / 4), Image.ANTIALIAS) + im.save(fn, quality=95) + self.root.add_widget(Picture(source=fn, center=self.root.center)) + + def on_pause(self): + return True + + +TakePictureApp().run() diff --git a/freechat-client/share/kivy-examples/android/takepicture/shadow32.png b/freechat-client/share/kivy-examples/android/takepicture/shadow32.png new file mode 100644 index 0000000..f5e9f45 Binary files /dev/null and b/freechat-client/share/kivy-examples/android/takepicture/shadow32.png differ diff --git a/freechat-client/share/kivy-examples/android/takepicture/takepicture.kv b/freechat-client/share/kivy-examples/android/takepicture/takepicture.kv new file mode 100644 index 0000000..a8f06c1 --- /dev/null +++ b/freechat-client/share/kivy-examples/android/takepicture/takepicture.kv @@ -0,0 +1,40 @@ +#:kivy 1.0 +#:import win kivy.core.window + +Widget: + canvas: + Color: + rgb: .85, .87, .88 + Rectangle: + size: self.size + + Button: + text: 'Take a picture' + width: self.texture_size[0] + dp(40) + height: '48dp' + on_release: app.take_picture() + +: + on_size: self.center = win.Window.center + size: image.size + size_hint: None, None + + Image: + id: image + source: root.source + + # create initial image to be 400 pixels width + size: 400, 400 + + # add shadow background + canvas.before: + Color: + rgba: 1, 1, 1, 1 + BorderImage: + source: 'shadow32.png' + border: (36, 36, 36, 36) + size:(self.width + 72, self.height + 72) + pos: (-36, -36) + + + diff --git a/freechat-client/share/kivy-examples/animation/__pycache__/animate.cpython-37.pyc b/freechat-client/share/kivy-examples/animation/__pycache__/animate.cpython-37.pyc new file mode 100644 index 0000000..5819937 Binary files /dev/null and b/freechat-client/share/kivy-examples/animation/__pycache__/animate.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/animation/animate.py b/freechat-client/share/kivy-examples/animation/animate.py new file mode 100644 index 0000000..8c9bb30 --- /dev/null +++ b/freechat-client/share/kivy-examples/animation/animate.py @@ -0,0 +1,42 @@ +''' +Widget animation +================ + +This example demonstrates creating and applying a multi-part animation to +a button widget. You should see a button labelled 'plop' that will move with +an animation when clicked. +''' + +import kivy +kivy.require('1.0.7') + +from kivy.animation import Animation +from kivy.app import App +from kivy.uix.button import Button + + +class TestApp(App): + + def animate(self, instance): + # create an animation object. This object could be stored + # and reused each call or reused across different widgets. + # += is a sequential step, while &= is in parallel + animation = Animation(pos=(100, 100), t='out_bounce') + animation += Animation(pos=(200, 100), t='out_bounce') + animation &= Animation(size=(500, 500)) + animation += Animation(size=(100, 50)) + + # apply the animation on the button, passed in the "instance" argument + # Notice that default 'click' animation (changing the button + # color while the mouse is down) is unchanged. + animation.start(instance) + + def build(self): + # create a button, and attach animate() method as a on_press handler + button = Button(size_hint=(None, None), text='plop', + on_press=self.animate) + return button + + +if __name__ == '__main__': + TestApp().run() diff --git a/freechat-client/share/kivy-examples/application/__pycache__/app_suite.cpython-37.pyc b/freechat-client/share/kivy-examples/application/__pycache__/app_suite.cpython-37.pyc new file mode 100644 index 0000000..1766f94 Binary files /dev/null and b/freechat-client/share/kivy-examples/application/__pycache__/app_suite.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/application/__pycache__/app_with_build.cpython-37.pyc b/freechat-client/share/kivy-examples/application/__pycache__/app_with_build.cpython-37.pyc new file mode 100644 index 0000000..f1a7389 Binary files /dev/null and b/freechat-client/share/kivy-examples/application/__pycache__/app_with_build.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/application/__pycache__/app_with_config.cpython-37.pyc b/freechat-client/share/kivy-examples/application/__pycache__/app_with_config.cpython-37.pyc new file mode 100644 index 0000000..b32ddf1 Binary files /dev/null and b/freechat-client/share/kivy-examples/application/__pycache__/app_with_config.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/application/__pycache__/app_with_kv.cpython-37.pyc b/freechat-client/share/kivy-examples/application/__pycache__/app_with_kv.cpython-37.pyc new file mode 100644 index 0000000..a420a73 Binary files /dev/null and b/freechat-client/share/kivy-examples/application/__pycache__/app_with_kv.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/application/__pycache__/app_with_kv_in_template1.cpython-37.pyc b/freechat-client/share/kivy-examples/application/__pycache__/app_with_kv_in_template1.cpython-37.pyc new file mode 100644 index 0000000..e5181b3 Binary files /dev/null and b/freechat-client/share/kivy-examples/application/__pycache__/app_with_kv_in_template1.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/application/app_suite.py b/freechat-client/share/kivy-examples/application/app_suite.py new file mode 100644 index 0000000..09b0ed6 --- /dev/null +++ b/freechat-client/share/kivy-examples/application/app_suite.py @@ -0,0 +1,152 @@ +''' +Suite of Application Builders +============================= + +This explores different methods of starting an application. If you run +this without a command line parameter, you should see a menu in your terminal. +You can also run this with a 'r' parameter to pick a random method. +There are lots of logging options to make this easier to debug: the execution +order may not be obvious. Each time you run the command, only one kivy +application is created. + +This uses the file testkvfile.kv and the file app_suite_data/testkvdir.kv. + +''' + +from __future__ import print_function +import sys +import re +from random import choice + +import kivy +kivy.require('1.8.0') # 1.8 is when kv_directory became part of app. +from kivy.app import App +from kivy.uix.button import Button +from kivy.lang import Builder + +from kivy.uix.floatlayout import FloatLayout +# Note that importing FloatLayout causes Kivy to execute, including +# starting up the Logger and some other messages. +print("** In main program, done with imports") + + +class TestBuildApp(App): + """ Use build() function to return a widget. """ + def build(self): + """ Build called by kivy when an App is started. + Called after trying to load a .kv file. + Returns a new Button as a root widget. + """ + print("** inside build()") + return Button(text='hello from TestBuildApp') + + +class TestKVFileApp(App): + """ + Empty class, but name used to find .kv file. The filename is the lowercase + version of the class, i.e. 'testkvfileapp.kv'. If not found, it strips + off the final 'app', i.e. 'testkvfile.kv'. If not file is found, and no + other method sets the self.root, the program will run with an empty screen. + """ + pass + + +class TestKVDirApp(App): + """ + Empty class except for setting class variable kv_directory. + This directory sets the directory in which to search for the .kv file. + The name of the kv file is still governed by the class name and the .kv + file should still have one root widget. + """ + kv_directory = 'app_suite_data' + + +class TestKVStringApp(App): + """ + Use a build() function and use the kivy.lang.Builder function to parse up a + Kivy language string. + """ + def build(self): + """ Called by kivy run(). """ + print("** inside build()") + widget = Builder.load_string( + "Button:\n text: 'hello from TestKVStringApp'") + print("** widget built") + return widget + + +class TestPrebuiltApp(App): + """ Use the Builder to create a top level widget at the beginning + of the Python program, then use a dummy class for that widget. + This costs a bit more in start-up time. """ + kv = "\n Button:\n text:'hello from TestPrebuiltApp'" + Builder.load_string(kv) + print("** in TestPrebuiltApp, class initialization built ") + + class Prebuilt(FloatLayout): + """ Empty class to cause setting root to tag and + set inheritence """ + pass + + def build(self): + """ called, returns instance matching tag . """ + return self.Prebuilt() + + +def print_class(class_name): + """ Read this file and print the section with the class name specified.)""" + filename = sys.argv[0] + with open(filename) as f: + data = f.read() + regex = "^(class " + class_name + "\\b.*?)^\\S" + match = re.search(regex, data, flags=re.MULTILINE | re.DOTALL) + if match: + print(match.group(1)) + + +# the __name__ idiom executes when run from command line but not from import. +if __name__ == '__main__': + dash = "-" * 40 + + arg = sys.argv[1][0].lower() if len(sys.argv) > 1 else "h" + print(dash) + + if arg == 'r': + arg = choice('bfds') + + if arg == 'b': + print_class("TestBuildApp") + TestBuildApp().run() + elif arg == 'f': + print_class("TestKVFileApp") + TestKVFileApp().run() + elif arg == 'd': + print_class("TestKVDirApp") + TestKVDirApp().run() + elif arg == 's': + print_class("TestKVStringApp") + TestKVStringApp().run() + elif arg == 'p': + print_class("TestPrebuiltApp") + TestPrebuiltApp().run() + else: # help + print(""" +This demo runs different application windows based on a command line argument. + +Try using one of these: + b - Use build() method to return a widget + d - Use a kv file from a different directory + f - Use a kv file with the widget object + p - Use prebuilt widget inside a layout + s - Use a kivy language string to create the widget + r - pick one of the options at random. + + h - show this help message. + + After closing the application window, this program will exit. + While the run() method does return, kivy cannot run another + application window after one has been closed. + """) + + print(dash) + print("This program is gratified to be of use.") diff --git a/freechat-client/share/kivy-examples/application/app_suite_data/testkvdir.kv b/freechat-client/share/kivy-examples/application/app_suite_data/testkvdir.kv new file mode 100644 index 0000000..e1f864c --- /dev/null +++ b/freechat-client/share/kivy-examples/application/app_suite_data/testkvdir.kv @@ -0,0 +1,4 @@ +#:kivy 1.0 + +Button: + text: 'Hello from app_suite_data/testkvdir.kv' diff --git a/freechat-client/share/kivy-examples/application/app_with_build.py b/freechat-client/share/kivy-examples/application/app_with_build.py new file mode 100644 index 0000000..05d6012 --- /dev/null +++ b/freechat-client/share/kivy-examples/application/app_with_build.py @@ -0,0 +1,24 @@ +''' +Application example using build() + return +========================================== + +An application can be built if you return a widget on build(), or if you set +self.root. +''' + +import kivy +kivy.require('1.0.7') + +from kivy.app import App +from kivy.uix.button import Button + + +class TestApp(App): + + def build(self): + # return a Button() as a root widget + return Button(text='hello world') + + +if __name__ == '__main__': + TestApp().run() diff --git a/freechat-client/share/kivy-examples/application/app_with_config.py b/freechat-client/share/kivy-examples/application/app_with_config.py new file mode 100644 index 0000000..be2d17e --- /dev/null +++ b/freechat-client/share/kivy-examples/application/app_with_config.py @@ -0,0 +1,49 @@ +from kivy.app import App +from kivy.lang import Builder +from kivy.properties import ConfigParserProperty + +KV = ''' +FloatLayout: + BoxLayout: + size_hint: .5, .5 + pos_hint: {'center': (.5, .5)} + + orientation: 'vertical' + + TextInput: + text: app.text + on_text: app.text = self.text + + Slider: + min: 0 + max: 100 + value: app.number + on_value: app.number = self.value +''' + + +class ConfigApp(App): + number = ConfigParserProperty( + 0, 'general', 'number', + 'app', val_type=float + ) + text = ConfigParserProperty( + '', 'general', 'text', + 'app', val_type=str + ) + + def build_config(self, config): + config.setdefaults( + 'general', + { + 'number': 0, + 'text': 'test' + } + ) + + def build(self): + return Builder.load_string(KV) + + +if __name__ == '__main__': + ConfigApp().run() diff --git a/freechat-client/share/kivy-examples/application/app_with_kv.py b/freechat-client/share/kivy-examples/application/app_with_kv.py new file mode 100644 index 0000000..ea35f8f --- /dev/null +++ b/freechat-client/share/kivy-examples/application/app_with_kv.py @@ -0,0 +1,25 @@ +''' +Application built from a .kv file +================================== + +This shows how to implicitly use a .kv file for your application. You +should see a full screen button labelled "Hello from test.kv". + +After Kivy instantiates a subclass of App, it implicitly searches for a .kv +file. The file test.kv is selected because the name of the subclass of App is +TestApp, which implies that kivy should try to load "test.kv". That file +contains a root Widget. +''' + +import kivy +kivy.require('1.0.7') + +from kivy.app import App + + +class TestApp(App): + pass + + +if __name__ == '__main__': + TestApp().run() diff --git a/freechat-client/share/kivy-examples/application/app_with_kv_in_template1.py b/freechat-client/share/kivy-examples/application/app_with_kv_in_template1.py new file mode 100644 index 0000000..9f5650c --- /dev/null +++ b/freechat-client/share/kivy-examples/application/app_with_kv_in_template1.py @@ -0,0 +1,27 @@ +''' +Application from a .kv in a Template Directory +============================================== + +This example shows how you can change the directory for the .kv file. You +should see "Hello from template1/test.ky" as a button. + +As kivy instantiates the TestApp subclass of App, the variable kv_directory +is set. Kivy then implicitly searches for a .kv file matching the name +of the subclass in that directory, finding the file template1/test.kv. That +file contains the root widget. + + +''' + +import kivy +kivy.require('1.0.7') + +from kivy.app import App + + +class TestApp(App): + kv_directory = 'template1' + + +if __name__ == '__main__': + TestApp().run() diff --git a/freechat-client/share/kivy-examples/application/template1/test.kv b/freechat-client/share/kivy-examples/application/template1/test.kv new file mode 100644 index 0000000..22ff9fe --- /dev/null +++ b/freechat-client/share/kivy-examples/application/template1/test.kv @@ -0,0 +1,4 @@ +#:kivy 1.0 + +Button: + text: 'Hello from template1/test.kv' diff --git a/freechat-client/share/kivy-examples/application/test.kv b/freechat-client/share/kivy-examples/application/test.kv new file mode 100644 index 0000000..b24f2a5 --- /dev/null +++ b/freechat-client/share/kivy-examples/application/test.kv @@ -0,0 +1,4 @@ +#:kivy 1.0 + +Button: + text: 'Hello from test.kv' diff --git a/freechat-client/share/kivy-examples/application/testkvfile.kv b/freechat-client/share/kivy-examples/application/testkvfile.kv new file mode 100644 index 0000000..3939781 --- /dev/null +++ b/freechat-client/share/kivy-examples/application/testkvfile.kv @@ -0,0 +1,4 @@ +#:kivy 1.0 + +Button: + text: 'Hello from testkvfile.kv' diff --git a/freechat-client/share/kivy-examples/audio/12908_sweet_trip_mm_clap_hi.wav b/freechat-client/share/kivy-examples/audio/12908_sweet_trip_mm_clap_hi.wav new file mode 100644 index 0000000..b1e4819 Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12908_sweet_trip_mm_clap_hi.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12909_sweet_trip_mm_clap_lo.wav b/freechat-client/share/kivy-examples/audio/12909_sweet_trip_mm_clap_lo.wav new file mode 100644 index 0000000..5b03cd0 Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12909_sweet_trip_mm_clap_lo.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12910_sweet_trip_mm_clap_mid.wav b/freechat-client/share/kivy-examples/audio/12910_sweet_trip_mm_clap_mid.wav new file mode 100644 index 0000000..170544d Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12910_sweet_trip_mm_clap_mid.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12911_sweet_trip_mm_hat_cl.wav b/freechat-client/share/kivy-examples/audio/12911_sweet_trip_mm_hat_cl.wav new file mode 100644 index 0000000..74a342f Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12911_sweet_trip_mm_hat_cl.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12913_sweet_trip_mm_kick_hi.wav b/freechat-client/share/kivy-examples/audio/12913_sweet_trip_mm_kick_hi.wav new file mode 100644 index 0000000..cd1050f Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12913_sweet_trip_mm_kick_hi.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12914_sweet_trip_mm_kick_lo.wav b/freechat-client/share/kivy-examples/audio/12914_sweet_trip_mm_kick_lo.wav new file mode 100644 index 0000000..c9ab8d0 Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12914_sweet_trip_mm_kick_lo.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12915_sweet_trip_mm_kick_mid.wav b/freechat-client/share/kivy-examples/audio/12915_sweet_trip_mm_kick_mid.wav new file mode 100644 index 0000000..4caaecc Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12915_sweet_trip_mm_kick_mid.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12916_sweet_trip_mm_kwik_mod_01.wav b/freechat-client/share/kivy-examples/audio/12916_sweet_trip_mm_kwik_mod_01.wav new file mode 100644 index 0000000..38f35e4 Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12916_sweet_trip_mm_kwik_mod_01.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12917_sweet_trip_mm_kwik_mod_02.wav b/freechat-client/share/kivy-examples/audio/12917_sweet_trip_mm_kwik_mod_02.wav new file mode 100644 index 0000000..a782ef9 Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12917_sweet_trip_mm_kwik_mod_02.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12918_sweet_trip_mm_kwik_mod_03.wav b/freechat-client/share/kivy-examples/audio/12918_sweet_trip_mm_kwik_mod_03.wav new file mode 100644 index 0000000..f240707 Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12918_sweet_trip_mm_kwik_mod_03.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12919_sweet_trip_mm_kwik_mod_04.wav b/freechat-client/share/kivy-examples/audio/12919_sweet_trip_mm_kwik_mod_04.wav new file mode 100644 index 0000000..10ffc3b Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12919_sweet_trip_mm_kwik_mod_04.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12920_sweet_trip_mm_kwik_mod_05.wav b/freechat-client/share/kivy-examples/audio/12920_sweet_trip_mm_kwik_mod_05.wav new file mode 100644 index 0000000..04dc583 Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12920_sweet_trip_mm_kwik_mod_05.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12921_sweet_trip_mm_kwik_mod_06.wav b/freechat-client/share/kivy-examples/audio/12921_sweet_trip_mm_kwik_mod_06.wav new file mode 100644 index 0000000..662d067 Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12921_sweet_trip_mm_kwik_mod_06.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12922_sweet_trip_mm_kwik_mod_07.wav b/freechat-client/share/kivy-examples/audio/12922_sweet_trip_mm_kwik_mod_07.wav new file mode 100644 index 0000000..66a5af4 Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12922_sweet_trip_mm_kwik_mod_07.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12923_sweet_trip_mm_metal_clave.wav b/freechat-client/share/kivy-examples/audio/12923_sweet_trip_mm_metal_clave.wav new file mode 100644 index 0000000..7e21ad5 Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12923_sweet_trip_mm_metal_clave.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12925_sweet_trip_mm_sweep_x.wav b/freechat-client/share/kivy-examples/audio/12925_sweet_trip_mm_sweep_x.wav new file mode 100644 index 0000000..6679d26 Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12925_sweet_trip_mm_sweep_x.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12926_sweet_trip_mm_sweep_y.wav b/freechat-client/share/kivy-examples/audio/12926_sweet_trip_mm_sweep_y.wav new file mode 100644 index 0000000..f3ab96c Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12926_sweet_trip_mm_sweep_y.wav differ diff --git a/freechat-client/share/kivy-examples/audio/12927_sweet_trip_mm_sweep_z.wav b/freechat-client/share/kivy-examples/audio/12927_sweet_trip_mm_sweep_z.wav new file mode 100644 index 0000000..8121511 Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/12927_sweet_trip_mm_sweep_z.wav differ diff --git a/freechat-client/share/kivy-examples/audio/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/audio/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..2e42e3f Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/audio/__pycache__/pitch.cpython-37.pyc b/freechat-client/share/kivy-examples/audio/__pycache__/pitch.cpython-37.pyc new file mode 100644 index 0000000..f4af56c Binary files /dev/null and b/freechat-client/share/kivy-examples/audio/__pycache__/pitch.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/audio/audio.kv b/freechat-client/share/kivy-examples/audio/audio.kv new file mode 100644 index 0000000..3aa9539 --- /dev/null +++ b/freechat-client/share/kivy-examples/audio/audio.kv @@ -0,0 +1,59 @@ +#:kivy 1.0 +#:import kivy kivy + +: + orientation: 'vertical' + canvas: + Color: + rgb: 1, 1, 1 + Rectangle: + source: 'data/images/background.jpg' + size: self.size + + BoxLayout: + padding: 10 + spacing: 10 + size_hint: 1, None + pos_hint: {'top': 1} + height: 44 + Image: + size_hint: None, None + size: 24, 24 + source: 'data/logo/kivy-icon-24.png' + Label: + height: 24 + text_size: self.size + color: (1, 1, 1, .8) + text: 'Kivy %s - Audio sample' % kivy.__version__ + valign: 'middle' + + Label: + text: 'Audio example' + font_size: 32 + size_hint_y: None + + BoxLayout: + Slider: + min: 0.0 + max: 1.0 + value: 1.0 + on_value: app.set_volume(self.value) + orientation: "vertical" + size_hint_x: None + width: "48dp" + + StackLayout: + id: sl + + Button: + text: 'Stop and release all audio' + size_hint_y: None + height: '50sp' + on_press: app.release_audio() + +: + size_hint: None,0.333 + width: self.height + text_size: self.size + font_size: '12sp' + valign: 'middle' diff --git a/freechat-client/share/kivy-examples/audio/main.py b/freechat-client/share/kivy-examples/audio/main.py new file mode 100644 index 0000000..b6b043d --- /dev/null +++ b/freechat-client/share/kivy-examples/audio/main.py @@ -0,0 +1,81 @@ +''' +Audio example +============= + +This example plays sounds of different formats. You should see a grid of +buttons labelled with filenames. Clicking on the buttons will play, or +restart, each sound. Not all sound formats will play on all platforms. + +All the sounds are from the http://woolyss.com/chipmusic-samples.php +"THE FREESOUND PROJECT", Under Creative Commons Sampling Plus 1.0 License. + +''' + +import kivy +kivy.require('1.0.8') + +from kivy.app import App +from kivy.uix.button import Button +from kivy.uix.boxlayout import BoxLayout +from kivy.core.audio import SoundLoader +from kivy.properties import StringProperty, ObjectProperty, NumericProperty +from glob import glob +from os.path import dirname, join, basename + + +class AudioButton(Button): + + filename = StringProperty(None) + sound = ObjectProperty(None, allownone=True) + volume = NumericProperty(1.0) + + def on_press(self): + if self.sound is None: + self.sound = SoundLoader.load(self.filename) + # stop the sound if it's currently playing + if self.sound.status != 'stop': + self.sound.stop() + self.sound.volume = self.volume + self.sound.play() + + def release_audio(self): + if self.sound: + self.sound.stop() + self.sound.unload() + self.sound = None + + def set_volume(self, volume): + self.volume = volume + if self.sound: + self.sound.volume = volume + + +class AudioBackground(BoxLayout): + pass + + +class AudioApp(App): + + def build(self): + + root = AudioBackground(spacing=5) + for fn in glob(join(dirname(__file__), '*.wav')): + btn = AudioButton( + text=basename(fn[:-4]).replace('_', ' '), filename=fn, + size_hint=(None, None), halign='center', + size=(128, 128), text_size=(118, None)) + root.ids.sl.add_widget(btn) + + return root + + def release_audio(self): + for audiobutton in self.root.ids.sl.children: + audiobutton.release_audio() + + def set_volume(self, value): + for audiobutton in self.root.ids.sl.children: + audiobutton.set_volume(value) + + +if __name__ == '__main__': + AudioApp().run() diff --git a/freechat-client/share/kivy-examples/audio/pitch.py b/freechat-client/share/kivy-examples/audio/pitch.py new file mode 100644 index 0000000..2a142ff --- /dev/null +++ b/freechat-client/share/kivy-examples/audio/pitch.py @@ -0,0 +1,42 @@ +# encoding: utf8 + +from kivy.app import App +from kivy.core.audio import SoundLoader +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.button import Button + +from sys import version_info + + +NOTES = ( + ('Do', 1), + ('Ré', 9 / 8.), + ('Mi', 5 / 4.), + ('Fa', 4 / 3.), + ('Sol', 3 / 2.), + ('La', 5 / 3.), + ('Si', 15 / 8.), +) + + +class Test(App): + def build(self): + self.sound = SoundLoader.load( + '/usr/lib64/python{}.{}/test/audiodata/pluck-pcm32.wav' + .format(*version_info[0:2]) + ) + root = BoxLayout() + for octave in range(-2, 3): + for note, pitch in NOTES: + button = Button(text=note) + button.pitch = pitch * 2 ** octave + button.bind(on_release=self.play_note) + root.add_widget(button) + return root + + def play_note(self, button): + self.sound.pitch = button.pitch + self.sound.play() + + +Test().run() diff --git a/freechat-client/share/kivy-examples/camera/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/camera/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..3699194 Binary files /dev/null and b/freechat-client/share/kivy-examples/camera/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/camera/main.py b/freechat-client/share/kivy-examples/camera/main.py new file mode 100644 index 0000000..05770f7 --- /dev/null +++ b/freechat-client/share/kivy-examples/camera/main.py @@ -0,0 +1,59 @@ +''' +Camera Example +============== + +This example demonstrates a simple use of the camera. It shows a window with +a buttoned labelled 'play' to turn the camera on and off. Note that +not finding a camera, perhaps because gstreamer is not installed, will +throw an exception during the kv language processing. + +''' + +# Uncomment these lines to see all the messages +# from kivy.logger import Logger +# import logging +# Logger.setLevel(logging.TRACE) + +from kivy.app import App +from kivy.lang import Builder +from kivy.uix.boxlayout import BoxLayout +import time +Builder.load_string(''' +: + orientation: 'vertical' + Camera: + id: camera + resolution: (640, 480) + play: False + ToggleButton: + text: 'Play' + on_press: camera.play = not camera.play + size_hint_y: None + height: '48dp' + Button: + text: 'Capture' + size_hint_y: None + height: '48dp' + on_press: root.capture() +''') + + +class CameraClick(BoxLayout): + def capture(self): + ''' + Function to capture the images and give them the names + according to their captured time and date. + ''' + camera = self.ids['camera'] + timestr = time.strftime("%Y%m%d_%H%M%S") + camera.export_to_png("IMG_{}.png".format(timestr)) + print("Captured") + + +class TestCamera(App): + + def build(self): + return CameraClick() + + +TestCamera().run() diff --git a/freechat-client/share/kivy-examples/canvas/__pycache__/bezier.cpython-37.pyc b/freechat-client/share/kivy-examples/canvas/__pycache__/bezier.cpython-37.pyc new file mode 100644 index 0000000..033a4ae Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/__pycache__/bezier.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/canvas/__pycache__/canvas_stress.cpython-37.pyc b/freechat-client/share/kivy-examples/canvas/__pycache__/canvas_stress.cpython-37.pyc new file mode 100644 index 0000000..a828d5f Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/__pycache__/canvas_stress.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/canvas/__pycache__/circle.cpython-37.pyc b/freechat-client/share/kivy-examples/canvas/__pycache__/circle.cpython-37.pyc new file mode 100644 index 0000000..e358730 Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/__pycache__/circle.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/canvas/__pycache__/fbo_canvas.cpython-37.pyc b/freechat-client/share/kivy-examples/canvas/__pycache__/fbo_canvas.cpython-37.pyc new file mode 100644 index 0000000..6c4c9ed Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/__pycache__/fbo_canvas.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/canvas/__pycache__/lines.cpython-37.pyc b/freechat-client/share/kivy-examples/canvas/__pycache__/lines.cpython-37.pyc new file mode 100644 index 0000000..acf5925 Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/__pycache__/lines.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/canvas/__pycache__/lines_extended.cpython-37.pyc b/freechat-client/share/kivy-examples/canvas/__pycache__/lines_extended.cpython-37.pyc new file mode 100644 index 0000000..e1a5ab3 Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/__pycache__/lines_extended.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/canvas/__pycache__/mesh.cpython-37.pyc b/freechat-client/share/kivy-examples/canvas/__pycache__/mesh.cpython-37.pyc new file mode 100644 index 0000000..b26d2ed Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/__pycache__/mesh.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/canvas/__pycache__/mesh_manipulation.cpython-37.pyc b/freechat-client/share/kivy-examples/canvas/__pycache__/mesh_manipulation.cpython-37.pyc new file mode 100644 index 0000000..2ac757b Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/__pycache__/mesh_manipulation.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/canvas/__pycache__/multitexture.cpython-37.pyc b/freechat-client/share/kivy-examples/canvas/__pycache__/multitexture.cpython-37.pyc new file mode 100644 index 0000000..6e9660a Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/__pycache__/multitexture.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/canvas/__pycache__/repeat_texture.cpython-37.pyc b/freechat-client/share/kivy-examples/canvas/__pycache__/repeat_texture.cpython-37.pyc new file mode 100644 index 0000000..667c740 Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/__pycache__/repeat_texture.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/canvas/__pycache__/rotation.cpython-37.pyc b/freechat-client/share/kivy-examples/canvas/__pycache__/rotation.cpython-37.pyc new file mode 100644 index 0000000..4117a0b Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/__pycache__/rotation.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/canvas/__pycache__/rounded_rectangle.cpython-37.pyc b/freechat-client/share/kivy-examples/canvas/__pycache__/rounded_rectangle.cpython-37.pyc new file mode 100644 index 0000000..e695aa5 Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/__pycache__/rounded_rectangle.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/canvas/__pycache__/scale.cpython-37.pyc b/freechat-client/share/kivy-examples/canvas/__pycache__/scale.cpython-37.pyc new file mode 100644 index 0000000..27a0d17 Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/__pycache__/scale.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/canvas/__pycache__/stencil_canvas.cpython-37.pyc b/freechat-client/share/kivy-examples/canvas/__pycache__/stencil_canvas.cpython-37.pyc new file mode 100644 index 0000000..1e6c2cc Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/__pycache__/stencil_canvas.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/canvas/__pycache__/tesselate.cpython-37.pyc b/freechat-client/share/kivy-examples/canvas/__pycache__/tesselate.cpython-37.pyc new file mode 100644 index 0000000..99313f4 Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/__pycache__/tesselate.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/canvas/__pycache__/texture.cpython-37.pyc b/freechat-client/share/kivy-examples/canvas/__pycache__/texture.cpython-37.pyc new file mode 100644 index 0000000..d827c74 Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/__pycache__/texture.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/canvas/bezier.py b/freechat-client/share/kivy-examples/canvas/bezier.py new file mode 100644 index 0000000..f9ae226 --- /dev/null +++ b/freechat-client/share/kivy-examples/canvas/bezier.py @@ -0,0 +1,105 @@ +''' +Bezier Example +============== + +This example shows a closed Bezier curve computed from a polygon. You +should see a purple polygon, a red bezier curve computed from the polygon, +and two sliders. You can drag points on the polygon to recompute the curve. +The two sliders control the dash length of the dashed lines making up the two +shapes. + +''' +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 # pixel tolerance when clicking on a point + self.points = points + self.loop = loop + self.current_point = None # index of point being dragged + + 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 + z = 100 + # Pacman ! + points = [x, y] + for i in range(45, 360, 45): + i = radians(i) + points.extend([x + cos(i) * z, y + sin(i) * z]) + return BezierTest(points=points, loop=True) + + +if __name__ == '__main__': + Main().run() diff --git a/freechat-client/share/kivy-examples/canvas/canvas_stress.py b/freechat-client/share/kivy-examples/canvas/canvas_stress.py new file mode 100644 index 0000000..ce0d1ba --- /dev/null +++ b/freechat-client/share/kivy-examples/canvas/canvas_stress.py @@ -0,0 +1,72 @@ +''' +Canvas stress +============= + +This example tests the performance of our Graphics engine by drawing large +numbers of small squares. You should see a black canvas with buttons and a +label at the bottom. Pressing the buttons adds small colored squares to the +canvas. + +''' + +from kivy.uix.button import Button +from kivy.uix.widget import Widget +from kivy.uix.label import Label +from kivy.uix.boxlayout import BoxLayout +from kivy.app import App +from kivy.graphics import Color, Rectangle +from random import random as r +from functools import partial + + +class StressCanvasApp(App): + + def add_rects(self, label, wid, count, *largs): + label.text = str(int(label.text) + count) + with wid.canvas: + for x in range(count): + Color(r(), 1, 1, mode='hsv') + Rectangle(pos=(r() * wid.width + wid.x, + r() * wid.height + wid.y), size=(20, 20)) + + def double_rects(self, label, wid, *largs): + count = int(label.text) + self.add_rects(label, wid, count, *largs) + + def reset_rects(self, label, wid, *largs): + label.text = '0' + wid.canvas.clear() + + def build(self): + wid = Widget() + + label = Label(text='0') + + btn_add100 = Button(text='+ 100 rects', + on_press=partial(self.add_rects, label, wid, 100)) + + btn_add500 = Button(text='+ 500 rects', + on_press=partial(self.add_rects, label, wid, 500)) + + btn_double = Button(text='x 2', + on_press=partial(self.double_rects, label, wid)) + + btn_reset = Button(text='Reset', + on_press=partial(self.reset_rects, label, wid)) + + layout = BoxLayout(size_hint=(1, None), height=50) + layout.add_widget(btn_add100) + layout.add_widget(btn_add500) + layout.add_widget(btn_double) + layout.add_widget(btn_reset) + layout.add_widget(label) + + root = BoxLayout(orientation='vertical') + root.add_widget(wid) + root.add_widget(layout) + + return root + + +if __name__ == '__main__': + StressCanvasApp().run() diff --git a/freechat-client/share/kivy-examples/canvas/circle.py b/freechat-client/share/kivy-examples/canvas/circle.py new file mode 100644 index 0000000..4a810af --- /dev/null +++ b/freechat-client/share/kivy-examples/canvas/circle.py @@ -0,0 +1,84 @@ +''' +Circle Example +============== + +This example exercises circle (ellipse) drawing. You should see sliders at the +top of the screen with the Kivy logo below it. The sliders control the +angle start and stop and the height and width scales. There is a button +to reset the sliders. The logo used for the circle's background image is +from the kivy/data directory. The entire example is coded in the +kv language description. +''' + +from kivy.app import App +from kivy.lang import Builder + +kv = ''' +BoxLayout: + orientation: 'vertical' + BoxLayout: + size_hint_y: None + height: sp(100) + BoxLayout: + orientation: 'vertical' + Slider: + id: e1 + min: -360. + max: 360. + Label: + text: 'angle_start = {}'.format(e1.value) + BoxLayout: + orientation: 'vertical' + Slider: + id: e2 + min: -360. + max: 360. + value: 360 + Label: + text: 'angle_end = {}'.format(e2.value) + + BoxLayout: + size_hint_y: None + height: sp(100) + BoxLayout: + orientation: 'vertical' + Slider: + id: wm + min: 0 + max: 2 + value: 1 + Label: + text: 'Width mult. = {}'.format(wm.value) + BoxLayout: + orientation: 'vertical' + Slider: + id: hm + min: 0 + max: 2 + value: 1 + Label: + text: 'Height mult. = {}'.format(hm.value) + Button: + text: 'Reset ratios' + on_press: wm.value = 1; hm.value = 1 + + FloatLayout: + canvas: + Color: + rgb: 1, 1, 1 + Ellipse: + pos: 100, 100 + size: 200 * wm.value, 201 * hm.value + source: 'data/logo/kivy-icon-512.png' + angle_start: e1.value + angle_end: e2.value + +''' + + +class CircleApp(App): + def build(self): + return Builder.load_string(kv) + + +CircleApp().run() diff --git a/freechat-client/share/kivy-examples/canvas/fbo_canvas.py b/freechat-client/share/kivy-examples/canvas/fbo_canvas.py new file mode 100644 index 0000000..b18f4b0 --- /dev/null +++ b/freechat-client/share/kivy-examples/canvas/fbo_canvas.py @@ -0,0 +1,91 @@ +''' +FBO Canvas +========== + +This demonstrates a layout using an FBO (Frame Buffer Off-screen) +instead of a plain canvas. You should see a black canvas with a +button labelled 'FBO' in the bottom left corner. Clicking it +animates the button moving right to left. +''' + +__all__ = ('FboFloatLayout', ) + +from kivy.graphics import Color, Rectangle, Canvas, ClearBuffers, ClearColor +from kivy.graphics.fbo import Fbo +from kivy.uix.floatlayout import FloatLayout +from kivy.properties import ObjectProperty, NumericProperty +from kivy.app import App +from kivy.core.window import Window +from kivy.animation import Animation +from kivy.factory import Factory + + +class FboFloatLayout(FloatLayout): + + texture = ObjectProperty(None, allownone=True) + + alpha = NumericProperty(1) + + def __init__(self, **kwargs): + self.canvas = Canvas() + with self.canvas: + self.fbo = Fbo(size=self.size) + self.fbo_color = Color(1, 1, 1, 1) + self.fbo_rect = Rectangle() + + with self.fbo: + ClearColor(0, 0, 0, 0) + ClearBuffers() + + # wait that all the instructions are in the canvas to set texture + self.texture = self.fbo.texture + super(FboFloatLayout, self).__init__(**kwargs) + + def add_widget(self, *largs): + # trick to attach graphics instruction to fbo instead of canvas + canvas = self.canvas + self.canvas = self.fbo + ret = super(FboFloatLayout, self).add_widget(*largs) + self.canvas = canvas + return ret + + def remove_widget(self, *largs): + canvas = self.canvas + self.canvas = self.fbo + super(FboFloatLayout, self).remove_widget(*largs) + self.canvas = canvas + + def on_size(self, instance, value): + self.fbo.size = value + self.texture = self.fbo.texture + self.fbo_rect.size = value + + def on_pos(self, instance, value): + self.fbo_rect.pos = value + + def on_texture(self, instance, value): + self.fbo_rect.texture = value + + def on_alpha(self, instance, value): + self.fbo_color.rgba = (1, 1, 1, value) + + +class ScreenLayerApp(App): + def build(self): + + f = FboFloatLayout() + b = Factory.Button(text="FBO", size_hint=(None, None)) + f.add_widget(b) + + def anim_btn(*args): + if b.pos[0] == 0: + Animation(x=f.width - b.width).start(b) + else: + Animation(x=0).start(b) + b.bind(on_press=anim_btn) + + return f + + +if __name__ == "__main__": + ScreenLayerApp().run() diff --git a/freechat-client/share/kivy-examples/canvas/kiwi.jpg b/freechat-client/share/kivy-examples/canvas/kiwi.jpg new file mode 100644 index 0000000..019cc59 Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/kiwi.jpg differ diff --git a/freechat-client/share/kivy-examples/canvas/lines.py b/freechat-client/share/kivy-examples/canvas/lines.py new file mode 100644 index 0000000..7f4dcea --- /dev/null +++ b/freechat-client/share/kivy-examples/canvas/lines.py @@ -0,0 +1,296 @@ +''' +Line (SmoothLine) Experiment +============================ + +This demonstrates the experimental and unfinished SmoothLine feature +for fast line drawing. You should see a multi-segment +path at the top of the screen, and sliders and buttons along the bottom. +You can click to add new points to the segment, change the transparency +and width of the line, or hit 'Animate' to see a set of sine and cosine +animations. The Cap and Joint buttons don't work: SmoothLine has not +implemented these features yet. +''' + +from kivy.app import App +from kivy.properties import OptionProperty, NumericProperty, ListProperty, \ + BooleanProperty +from kivy.uix.floatlayout import FloatLayout +from kivy.lang import Builder +from kivy.clock import Clock +from math import cos, sin + +Builder.load_string(''' +: + canvas: + Color: + rgba: .4, .4, 1, root.alpha + Line: + points: self.points + joint: self.joint + cap: self.cap + width: self.linewidth + close: self.close + dash_length: self.dash_length + dash_offset: self.dash_offset + dashes: self.dashes + Color: + rgba: .8, .8, .8, root.alpha_controlline + Line: + points: self.points + close: self.close + dash_length: self.dash_length + dash_offset: self.dash_offset + dashes: self.dashes + Color: + rgba: 1, .4, .4, root.alpha + Line: + points: self.points2 + joint: self.joint + cap: self.cap + width: self.linewidth + close: self.close + dash_length: self.dash_length + dash_offset: self.dash_offset + dashes: self.dashes + + GridLayout: + cols: 2 + size_hint: 1, None + height: 44 * 5 + + GridLayout: + cols: 2 + + Label: + text: 'Alpha' + Slider: + value: root.alpha + on_value: root.alpha = float(args[1]) + min: 0. + max: 1. + Label: + text: 'Alpha Control Line' + Slider: + value: root.alpha_controlline + on_value: root.alpha_controlline = float(args[1]) + min: 0. + max: 1. + Label: + text: 'Width' + Slider: + value: root.linewidth + on_value: root.linewidth = args[1] + min: 1 + max: 40 + Label: + text: 'Cap' + GridLayout: + rows: 1 + ToggleButton: + group: 'cap' + text: 'none' + on_press: root.cap = self.text + ToggleButton: + group: 'cap' + text: 'round' + on_press: root.cap = self.text + ToggleButton: + group: 'cap' + text: 'square' + on_press: root.cap = self.text + Label: + text: 'Joint' + GridLayout: + rows: 1 + ToggleButton: + group: 'joint' + text: 'none' + on_press: root.joint = self.text + ToggleButton: + group: 'joint' + text: 'round' + on_press: root.joint = self.text + ToggleButton: + group: 'joint' + text: 'miter' + on_press: root.joint = self.text + ToggleButton: + group: 'joint' + text: 'bevel' + on_press: root.joint = self.text + + Label: + text: 'Close' + ToggleButton: + text: 'Close line' + on_press: root.close = self.state == 'down' + + Label: + text: 'Dashes' + GridLayout: + rows: 1 + ToggleButton: + group: 'dashes' + text: 'none' + state: 'down' + allow_no_selection: False + size_hint_x: None + width: self.texture_size[0] + padding_x: '5dp' + on_state: + if self.state == 'down': root.dashes = [] + if self.state == 'down': root.dash_length = 1 + if self.state == 'down': root.dash_offset = 0 + ToggleButton: + id: constant + group: 'dashes' + text: 'Constant: ' + allow_no_selection: False + size_hint_x: None + width: self.texture_size[0] + padding_x: '5dp' + on_state: + if self.state == 'down': root.dashes = [] + if self.state == 'down': root.dash_length = \ + int(dash_len.text or 1) + if self.state == 'down': root.dash_offset = \ + int(dash_offset.text or 0) + Label: + text: 'len' + size_hint_x: None + width: self.texture_size[0] + padding_x: '5dp' + TextInput: + id: dash_len + size_hint_x: None + width: '30dp' + input_filter: 'int' + multiline: False + text: '1' + on_text: if constant.state == 'down': \ + root.dash_length = int(self.text or 1) + Label: + text: 'offset' + size_hint_x: None + width: self.texture_size[0] + padding_x: '5dp' + TextInput: + id: dash_offset + size_hint_x: None + width: '30dp' + input_filter: 'int' + multiline: False + text: '0' + on_text: if constant.state == 'down': \ + root.dash_offset = int(self.text or 0) + ToggleButton: + id: dash_list + group: 'dashes' + text: 'List: ' + allow_no_selection: False + size_hint_x: None + width: self.texture_size[0] + padding_x: '5dp' + on_state: + if self.state == 'down': root.dashes = list(map(lambda\ + x: int(x or 0), dash_list_in.text.split(','))) + if self.state == 'down': root.dash_length = 1 + if self.state == 'down': root.dash_offset = 0 + TextInput: + id: dash_list_in + size_hint_x: None + width: '180dp' + multiline: False + text: '4,3,10,15' + on_text: if dash_list.state == 'down': root.dashes = \ + list(map(lambda x: int(x or 0), self.text.split(','))) + + AnchorLayout: + GridLayout: + cols: 1 + size_hint: None, None + size: self.minimum_size + ToggleButton: + size_hint: None, None + size: 100, 44 + text: 'Animate' + on_state: root.animate(self.state == 'down') + Button: + size_hint: None, None + size: 100, 44 + text: 'Clear' + on_press: root.points = root.points2 = [] + +''') + + +class LinePlayground(FloatLayout): + + alpha_controlline = NumericProperty(1.0) + alpha = NumericProperty(0.5) + close = BooleanProperty(False) + points = ListProperty([(500, 500), + [300, 300, 500, 300], + [500, 400, 600, 400]]) + points2 = ListProperty([]) + joint = OptionProperty('none', options=('round', 'miter', 'bevel', 'none')) + cap = OptionProperty('none', options=('round', 'square', 'none')) + linewidth = NumericProperty(10.0) + dt = NumericProperty(0) + dash_length = NumericProperty(1) + dash_offset = NumericProperty(0) + dashes = ListProperty([]) + + _update_points_animation_ev = None + + def on_touch_down(self, touch): + if super(LinePlayground, self).on_touch_down(touch): + return True + touch.grab(self) + self.points.append(touch.pos) + return True + + def on_touch_move(self, touch): + if touch.grab_current is self: + self.points[-1] = touch.pos + return True + return super(LinePlayground, self).on_touch_move(touch) + + def on_touch_up(self, touch): + if touch.grab_current is self: + touch.ungrab(self) + return True + return super(LinePlayground, self).on_touch_up(touch) + + def animate(self, do_animation): + if do_animation: + self._update_points_animation_ev = Clock.schedule_interval( + self.update_points_animation, 0) + elif self._update_points_animation_ev is not None: + self._update_points_animation_ev.cancel() + + def update_points_animation(self, dt): + cy = self.height * 0.6 + cx = self.width * 0.1 + w = self.width * 0.8 + step = 20 + points = [] + points2 = [] + self.dt += dt + for i in range(int(w / step)): + x = i * step + points.append(cx + x) + points.append(cy + cos(x / w * 8. + self.dt) * self.height * 0.2) + points2.append(cx + x) + points2.append(cy + sin(x / w * 8. + self.dt) * self.height * 0.2) + self.points = points + self.points2 = points2 + + +class TestLineApp(App): + def build(self): + return LinePlayground() + + +if __name__ == '__main__': + TestLineApp().run() diff --git a/freechat-client/share/kivy-examples/canvas/lines_extended.py b/freechat-client/share/kivy-examples/canvas/lines_extended.py new file mode 100644 index 0000000..df2a48e --- /dev/null +++ b/freechat-client/share/kivy-examples/canvas/lines_extended.py @@ -0,0 +1,183 @@ +''' +Lines Extended Demo +=================== + +This demonstrates how to use the extended line drawing routines such +as circles, ellipses, and rectangles. You should see a static image of +labelled shapes on the screen. +''' + +from kivy.app import App +from kivy.uix.gridlayout import GridLayout +from kivy.uix.widget import Widget +from kivy.lang import Builder + +Builder.load_string(''' +: + canvas: + Color: + rgba: 1, .1, .1, .9 + Line: + width: 2. + ellipse: (self.x, self.y, self.width, self.height) + Label: + center: root.center + text: 'Ellipse' + +: + canvas: + Color: + rgba: 1, .1, .1, .9 + Line: + width: 2. + ellipse: (self.x, self.y, self.width, self.height, 90, 180) + Label: + center: root.center + text: 'Ellipse from 90 to 180' + +# fun result with low segments! +: + canvas: + Color: + rgba: 1, .1, .1, .9 + Line: + width: 2. + ellipse: (self.x, self.y, self.width, self.height, 90, 720, 10) + Label: + center: root.center + text: 'Ellipse from 90 to 720\\n10 segments' + halign: 'center' + +: + canvas: + Color: + rgba: .1, 1, .1, .9 + Line: + width: 2. + circle: + (self.center_x, self.center_y, min(self.width, self.height) + / 2) + Label: + center: root.center + text: 'Circle' + +: + canvas: + Color: + rgba: .1, 1, .1, .9 + Line: + width: 2. + circle: + (self.center_x, self.center_y, min(self.width, self.height) + / 2, 90, 180) + Label: + center: root.center + text: 'Circle from 90 to 180' + +: + canvas: + Color: + rgba: .1, 1, .1, .9 + Line: + width: 2. + circle: + (self.center_x, self.center_y, min(self.width, self.height) + / 2, 90, 180, 10) + Label: + center: root.center + text: 'Circle from 90 to 180\\n10 segments' + halign: 'center' + +: + canvas: + Color: + rgba: .1, 1, .1, .9 + Line: + width: 2. + circle: + (self.center_x, self.center_y, min(self.width, self.height) + / 2, 0, 360) + Label: + center: root.center + text: 'Circle from 0 to 360' + halign: 'center' + +: + canvas: + Color: + rgba: .1, .1, 1, .9 + Line: + width: 2. + rectangle: (self.x, self.y, self.width, self.height) + Label: + center: root.center + text: 'Rectangle' + +: + canvas: + Color: + rgba: .1, .1, 1, .9 + Line: + width: 2. + bezier: + (self.x, self.y, self.center_x - 40, self.y + 100, + self.center_x + 40, self.y - 100, self.right, self.y) + Label: + center: root.center + text: 'Bezier' +''') + + +class LineEllipse1(Widget): + pass + + +class LineEllipse2(Widget): + pass + + +class LineEllipse3(Widget): + pass + + +class LineCircle1(Widget): + pass + + +class LineCircle2(Widget): + pass + + +class LineCircle3(Widget): + pass + + +class LineCircle4(Widget): + pass + + +class LineRectangle(Widget): + pass + + +class LineBezier(Widget): + pass + + +class LineExtendedApp(App): + def build(self): + root = GridLayout(cols=2, padding=50, spacing=50) + root.add_widget(LineEllipse1()) + root.add_widget(LineEllipse2()) + root.add_widget(LineEllipse3()) + root.add_widget(LineCircle1()) + root.add_widget(LineCircle2()) + root.add_widget(LineCircle3()) + root.add_widget(LineCircle4()) + root.add_widget(LineRectangle()) + root.add_widget(LineBezier()) + return root + + +if __name__ == '__main__': + LineExtendedApp().run() diff --git a/freechat-client/share/kivy-examples/canvas/mesh.py b/freechat-client/share/kivy-examples/canvas/mesh.py new file mode 100644 index 0000000..9add8ce --- /dev/null +++ b/freechat-client/share/kivy-examples/canvas/mesh.py @@ -0,0 +1,57 @@ +''' +Mesh test +========= + +This demonstrates the use of a mesh mode to distort an image. You should see +a line of buttons across the bottom of a canvas. Pressing them displays +the mesh, a small circle of points, with different mesh.mode settings. +''' + +from kivy.uix.button import Button +from kivy.uix.widget import Widget +from kivy.uix.boxlayout import BoxLayout +from kivy.app import App +from kivy.graphics import Mesh +from functools import partial +from math import cos, sin, pi + + +class MeshTestApp(App): + + def change_mode(self, mode, *largs): + self.mesh.mode = mode + + def build_mesh(self): + """ returns a Mesh of a rough circle. """ + vertices = [] + indices = [] + step = 10 + istep = (pi * 2) / float(step) + for i in range(step): + x = 300 + cos(istep * i) * 100 + y = 300 + sin(istep * i) * 100 + vertices.extend([x, y, 0, 0]) + indices.append(i) + return Mesh(vertices=vertices, indices=indices) + + def build(self): + wid = Widget() + with wid.canvas: + self.mesh = self.build_mesh() + + layout = BoxLayout(size_hint=(1, None), height=50) + for mode in ('points', 'line_strip', 'line_loop', 'lines', + 'triangle_strip', 'triangle_fan'): + button = Button(text=mode) + button.bind(on_release=partial(self.change_mode, mode)) + layout.add_widget(button) + + root = BoxLayout(orientation='vertical') + root.add_widget(wid) + root.add_widget(layout) + + return root + + +if __name__ == '__main__': + MeshTestApp().run() diff --git a/freechat-client/share/kivy-examples/canvas/mesh_manipulation.py b/freechat-client/share/kivy-examples/canvas/mesh_manipulation.py new file mode 100644 index 0000000..a78f531 --- /dev/null +++ b/freechat-client/share/kivy-examples/canvas/mesh_manipulation.py @@ -0,0 +1,101 @@ +''' +Mesh Manipulation Example +========================= + +This demonstrates creating a mesh and using it to deform the texture (the +kivy log). You should see the kivy logo with a five sliders to right. +The sliders change the mesh points' x and y offsets, radius, and a +'wobble' deformation's magnitude and speed. + +This example is developed in gabriel's blog post at +http://kivy.org/planet/2014/01/kivy-image-manipulations-with-mesh-and-textures/ +''' + +from kivy.app import App +from kivy.lang import Builder +from kivy.core.image import Image as CoreImage +from kivy.properties import ListProperty, ObjectProperty, NumericProperty +from kivy.clock import Clock +from kivy.core.window import Window +from math import sin, cos, pi + + +kv = ''' +BoxLayout: + Widget: + canvas: + Color: + rgba: 1, 1, 1, 1 + Mesh: + vertices: app.mesh_points + indices: range(len(app.mesh_points) // 4) + texture: app.mesh_texture + mode: 'triangle_fan' + BoxLayout: + orientation: 'vertical' + size_hint_x: None + width: 100 + Slider: + value: app.offset_x + on_value: app.offset_x = args[1] + min: -1 + max: 1 + Slider: + value: app.offset_y + on_value: app.offset_y = args[1] + min: -1 + max: 1 + Slider: + value: app.radius + on_value: app.radius = args[1] + min: 10 + max: 1000 + Slider: + value: app.sin_wobble + on_value: app.sin_wobble = args[1] + min: -50 + max: 50 + Slider: + value: app.sin_wobble_speed + on_value: app.sin_wobble_speed = args[1] + min: 0 + max: 50 + step: 1 +''' + + +class MeshBallApp(App): + mesh_points = ListProperty([]) + mesh_texture = ObjectProperty(None) + radius = NumericProperty(500) + offset_x = NumericProperty(.5) + offset_y = NumericProperty(.5) + sin_wobble = NumericProperty(0) + sin_wobble_speed = NumericProperty(0) + + def build(self): + self.mesh_texture = CoreImage('data/logo/kivy-icon-512.png').texture + Clock.schedule_interval(self.update_points, 0) + return Builder.load_string(kv) + + def update_points(self, *args): + """ replace self.mesh_points based on current slider positions. + Called continuously by a timer because this only sample code. + """ + points = [Window.width / 2, Window.height / 2, .5, .5] + i = 0 + while i < 2 * pi: + i += 0.01 * pi + points.extend([ + Window.width / 2 + cos(i) * (self.radius + self.sin_wobble * + sin(i * self.sin_wobble_speed)), + Window.height / 2 + sin(i) * (self.radius + self.sin_wobble * + sin(i * self.sin_wobble_speed)), + self.offset_x + sin(i), + self.offset_y + cos(i)]) + + self.mesh_points = points + + +if __name__ == '__main__': + MeshBallApp().run() diff --git a/freechat-client/share/kivy-examples/canvas/mtexture1.png b/freechat-client/share/kivy-examples/canvas/mtexture1.png new file mode 100644 index 0000000..18218f8 Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/mtexture1.png differ diff --git a/freechat-client/share/kivy-examples/canvas/mtexture2.png b/freechat-client/share/kivy-examples/canvas/mtexture2.png new file mode 100644 index 0000000..48eb86a Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/mtexture2.png differ diff --git a/freechat-client/share/kivy-examples/canvas/multitexture.py b/freechat-client/share/kivy-examples/canvas/multitexture.py new file mode 100644 index 0000000..673ea03 --- /dev/null +++ b/freechat-client/share/kivy-examples/canvas/multitexture.py @@ -0,0 +1,110 @@ +''' +Multitexture Example +==================== + +This example blends two textures: the image mtexture1.png of the letter K +and the image mtexture2.png of an orange circle. You should see an orange +K clipped to a circle. It uses a custom shader, written in glsl +(OpenGL Shading Language), stored in a local string. + +Note the image mtexture1.png is a white 'K' on a transparent background, which +makes it hard to see. +''' + +from kivy.clock import Clock +from kivy.app import App +from kivy.uix.widget import Widget +from kivy.uix.floatlayout import FloatLayout +from kivy.lang import Builder +from kivy.core.window import Window +from kivy.graphics import RenderContext, Color, Rectangle, BindTexture + + +fs_multitexture = ''' +$HEADER$ + +// New uniform that will receive texture at index 1 +uniform sampler2D texture1; + +void main(void) { + + // multiple current color with both texture (0 and 1). + // currently, both will use exactly the same texture coordinates. + gl_FragColor = frag_color * \ + texture2D(texture0, tex_coord0) * \ + texture2D(texture1, tex_coord0); +} +''' + + +kv = """ +: + + Image: + source: "mtexture1.png" + size_hint: .3,.3 + id: 1 + pos: 0,200 + Image: + source: "mtexture2.png" + size_hint: .3,.3 + id: 2 + pos: 200,200 + + MultitextureWidget: + +""" + +Builder.load_string(kv) + + +class MultitextureWidget(Widget): + + def __init__(self, **kwargs): + self.canvas = RenderContext() + # setting shader.fs to new source code automatically compiles it. + self.canvas.shader.fs = fs_multitexture + with self.canvas: + Color(1, 1, 1) + + # here, we are binding a custom texture at index 1 + # this will be used as texture1 in shader. + # The filenames are misleading: they do not correspond to the + # index here or in the shader. + BindTexture(source='mtexture2.png', index=1) + + # create a rectangle with texture (will be at index 0) + Rectangle(size=(150, 150), source='mtexture1.png', pos=(500, 200)) + + # set the texture1 to use texture index 1 + self.canvas['texture1'] = 1 + + # call the constructor of parent + # if they are any graphics objects, they will be added on our new + # canvas + super(MultitextureWidget, self).__init__(**kwargs) + + # We'll update our glsl variables in a clock + Clock.schedule_interval(self.update_glsl, 0) + + def update_glsl(self, *largs): + # This is needed for the default vertex shader. + self.canvas['projection_mat'] = Window.render_context['projection_mat'] + self.canvas['modelview_mat'] = Window.render_context['modelview_mat'] + + +class MultitextureLayout(FloatLayout): + + def __init__(self, **kwargs): + self.size = kwargs['size'] + super(MultitextureLayout, self).__init__(**kwargs) + + +class MultitextureApp(App): + + def build(self): + return MultitextureLayout(size=(600, 600)) + + +if __name__ == '__main__': + MultitextureApp().run() diff --git a/freechat-client/share/kivy-examples/canvas/repeat_texture.py b/freechat-client/share/kivy-examples/canvas/repeat_texture.py new file mode 100644 index 0000000..145f063 --- /dev/null +++ b/freechat-client/share/kivy-examples/canvas/repeat_texture.py @@ -0,0 +1,65 @@ +''' +Repeat Texture on Resize +======================== + +This examples repeats the letter 'K' (mtexture1.png) 64 times in a window. +You should see 8 rows and 8 columns of white K letters, along a label +showing the current size. As you resize the window, it stays an 8x8. +This example includes a label with a colored background. + +Note the image mtexture1.png is a white 'K' on a transparent background, which +makes it hard to see. +''' + +from kivy.app import App +from kivy.uix.image import Image +from kivy.uix.label import Label +from kivy.properties import ObjectProperty, ListProperty +from kivy.lang import Builder + +kv = ''' +: + canvas.before: + Color: + rgb: self.background + Rectangle: + pos: self.pos + size: self.size + +FloatLayout: + canvas.before: + Color: + rgb: 1, 1, 1 + Rectangle: + pos: self.pos + size: self.size + texture: app.texture + + LabelOnBackground: + text: '{} (try to resize the window)'.format(root.size) + color: (0.4, 1, 1, 1) + background: (.3, .3, .3) + pos_hint: {'center_x': .5, 'center_y': .5 } + size_hint: None, None + height: 30 + width: 250 + +''' + + +class LabelOnBackground(Label): + background = ListProperty((0.2, 0.2, 0.2)) + + +class RepeatTexture(App): + + texture = ObjectProperty() + + def build(self): + self.texture = Image(source='mtexture1.png').texture + self.texture.wrap = 'repeat' + self.texture.uvsize = (8, 8) + return Builder.load_string(kv) + + +RepeatTexture().run() diff --git a/freechat-client/share/kivy-examples/canvas/rotation.py b/freechat-client/share/kivy-examples/canvas/rotation.py new file mode 100644 index 0000000..68bf0fb --- /dev/null +++ b/freechat-client/share/kivy-examples/canvas/rotation.py @@ -0,0 +1,35 @@ +''' +Rotation Example +================ + +This example rotates a button using PushMatrix and PopMatrix. You should see +a static button with the words 'hello world' rotated at a 45 degree angle. +''' + + +from kivy.app import App +from kivy.lang import Builder + +kv = ''' +FloatLayout: + + Button: + text: 'hello world' + size_hint: None, None + pos_hint: {'center_x': .5, 'center_y': .5} + canvas.before: + PushMatrix + Rotate: + angle: 45 + origin: self.center + canvas.after: + PopMatrix +''' + + +class RotationApp(App): + def build(self): + return Builder.load_string(kv) + + +RotationApp().run() diff --git a/freechat-client/share/kivy-examples/canvas/rounded_rectangle.py b/freechat-client/share/kivy-examples/canvas/rounded_rectangle.py new file mode 100644 index 0000000..ef51930 --- /dev/null +++ b/freechat-client/share/kivy-examples/canvas/rounded_rectangle.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +from kivy.app import App +from kivy.uix.widget import Widget +from kivy.graphics import Color, Ellipse, Rectangle, RoundedRectangle +from kivy.lang import Builder + +TEXTURE = 'kiwi.jpg' +YELLOW = (1, .7, 0) +ORANGE = (1, .45, 0) +RED = (1, 0, 0) +WHITE = (1, 1, 1) + + +class RoundedRectangleWidget(Widget): + def prepare(self): + with self.canvas: + Color(*WHITE) + + # Rectangle of default size 100x100 + Rectangle(pos=(50, 400)) + + # RoundedRectangles of default size 100x100: + + # Textured: + RoundedRectangle( + pos=(175, 400), radius=[0, 50, 0, 50], source=TEXTURE) + + # Colored: + Color(*YELLOW) + RoundedRectangle(pos=(300, 400), radius=[0, 50, 0, 50]) + + # Textured + Colored + # Color(.3,.3,.3, 1) + RoundedRectangle( + pos=(425, 400), radius=[0, 50, 0, 50], source=TEXTURE) + + # Possible radius arguments: + # 1) Same value for each corner + Color(*ORANGE) + + # With same radius 20x20 + RoundedRectangle(pos=(50, 275), radius=[20]) + + # With same radius dimensions 20x40 + RoundedRectangle(pos=(175, 275), radius=[(20, 40)]) + + # 2) Different values for each corner + Color(*RED) + + # With different radiuses NxN: + RoundedRectangle(pos=(300, 275), radius=[10, 20, 30, 40]) + + # With different radiuses: + RoundedRectangle( + pos=(425, 275), + radius=[(10, 20), (20, 30), (30, 40), (40, 50)]) + + # Default ellipses + Color(*WHITE) + Ellipse(pos=(50, 150)) + Ellipse(pos=(175, 150)) + Ellipse(pos=(300, 150)) + Ellipse(pos=(425, 150)) + + # Radius dimensions can't be bigger than half of the figure side + RoundedRectangle(pos=(175, 150), radius=[9000], source=TEXTURE) + + # Segments parameter defines how many segments each corner has. + # More segments - more roundness + Color(*RED) + RoundedRectangle(pos=(300, 150), radius=[9000]) + RoundedRectangle(pos=(425, 150), radius=[9000], segments=15) + + Color(*ORANGE) + RoundedRectangle(pos=(425, 150), radius=[9000], segments=2) + + Color(*YELLOW) + RoundedRectangle(pos=(425, 150), radius=[9000], segments=1) + + # Various sizes + # You can cut corners by setting segments to 1. + # You can set different segment count to corners, + # by using a list useful for lowering vertex count + # by using small amount on small corners, while using + # bigger amount on bigger corners. + RoundedRectangle( + pos=(50, 25), + radius=[40], + segments=[1, 1, 10, 10], + size=(125, 100)) + + # If radius dimension is 0, then the corner will be sharp + # (90 degrees). It is also possible to mix tuple values + # with numeric + Color(*ORANGE) + RoundedRectangle( + pos=(200, 25), + radius=[(40, 20), + 45.5, 45.5, 0], + segments=[2, 3, 3, 1], size=(125, 100)) + + Color(*RED) + RoundedRectangle( + pos=(350, 25), + radius=[(40, 40), (40, 40), (20, 20), (20, 20)], + segments=[2, 3, 3, 2], + size=(150, 100)) + + +class DrawRoundedRectanglesApp(App): + def build(self): + kv = ''' +Widget: + canvas: + Color: + rgba: 1, 1,1, 1 + + RoundedRectangle: + pos: 575, 400 + size: 100, 100 + radius: [0, 50, 0, 50] + source: 'kiwi.jpg' + + Color: + rgba: 0, 0.8, 0.8, 1 + + RoundedRectangle: + pos: 575, 275 + size: 100, 100 + radius: [(10, 20), (20, 30), (30, 40), (40, 50)] + + RoundedRectangle: + pos: 575, 150 + size: 100, 100 + radius: [9000] + segments: 15 + + RoundedRectangle: + pos: 550, 25 + size: 150, 100 + segments: [1, 2, 1, 3] + radius: [30, 40, 30, 40] + +''' + widget = RoundedRectangleWidget() + widget.prepare() + kvrect = Builder.load_string(kv) + widget.add_widget(kvrect) + return widget + + +if __name__ == '__main__': + DrawRoundedRectanglesApp().run() diff --git a/freechat-client/share/kivy-examples/canvas/scale.py b/freechat-client/share/kivy-examples/canvas/scale.py new file mode 100644 index 0000000..55358dc --- /dev/null +++ b/freechat-client/share/kivy-examples/canvas/scale.py @@ -0,0 +1,37 @@ +''' +Scaling Example +================ + +This example scales a button using PushMatrix and PopMatrix. It shows +a static button with the words 'hello world', stretched about its centre by +a factor of 1.5 horizontally and 5 vertically. +''' + + +from kivy.app import App +from kivy.lang import Builder + +kv = ''' +FloatLayout: + + Button: + text: 'hello world' + size_hint: None, None + pos_hint: {'center_x': .5, 'center_y': .5} + canvas.before: + PushMatrix + Scale: + x: 1.5 + y: 5 + origin: self.center + canvas.after: + PopMatrix +''' + + +class ScalingApp(App): + def build(self): + return Builder.load_string(kv) + + +ScalingApp().run() diff --git a/freechat-client/share/kivy-examples/canvas/stencil_canvas.py b/freechat-client/share/kivy-examples/canvas/stencil_canvas.py new file mode 100644 index 0000000..8467cd4 --- /dev/null +++ b/freechat-client/share/kivy-examples/canvas/stencil_canvas.py @@ -0,0 +1,85 @@ +''' +Stencil demo +============ + +This is a test of the stencil graphics instruction inside the stencil view +widget. When you use a stencil, nothing will be drawn outside the bounding +box. All the graphics will draw only in the stencil view. + +You can "draw" a stencil view by touch & draw. The touch down will set the +position, and the drag will set the size. +''' + +from kivy.app import App +from kivy.core.window import Window +from kivy.graphics import Color, Rectangle +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.floatlayout import FloatLayout +from kivy.uix.button import Button +from kivy.uix.label import Label +from kivy.uix.stencilview import StencilView +from random import random as r +from functools import partial + + +class StencilTestWidget(StencilView): + '''Drag to define stencil area + ''' + + def on_touch_down(self, touch): + self.pos = touch.pos + self.size = (1, 1) + + def on_touch_move(self, touch): + self.size = (touch.x - touch.ox, touch.y - touch.oy) + + +class StencilCanvasApp(App): + + def add_rects(self, label, wid, count, *largs): + label.text = str(int(label.text) + count) + with wid.canvas: + for x in range(count): + Color(r(), 1, 1, mode='hsv') + Rectangle(pos=(r() * wid.width + wid.x, + r() * wid.height + wid.y), size=(10, 10)) + + def reset_stencil(self, wid, *largs): + wid.pos = (0, 0) + wid.size = Window.size + + def reset_rects(self, label, wid, *largs): + label.text = '0' + wid.canvas.clear() + + def build(self): + wid = StencilTestWidget(size_hint=(None, None), size=Window.size) + + label = Label(text='0') + + btn_add500 = Button(text='+ 200 rects') + btn_add500.bind(on_press=partial(self.add_rects, label, wid, 200)) + + btn_reset = Button(text='Reset Rectangles') + btn_reset.bind(on_press=partial(self.reset_rects, label, wid)) + + btn_stencil = Button(text='Reset Stencil') + btn_stencil.bind(on_press=partial(self.reset_stencil, wid)) + + layout = BoxLayout(size_hint=(1, None), height=50) + layout.add_widget(btn_add500) + layout.add_widget(btn_reset) + layout.add_widget(btn_stencil) + layout.add_widget(label) + + root = BoxLayout(orientation='vertical') + rfl = FloatLayout() + rfl.add_widget(wid) + root.add_widget(rfl) + root.add_widget(layout) + + return root + + +if __name__ == '__main__': + StencilCanvasApp().run() diff --git a/freechat-client/share/kivy-examples/canvas/tesselate.py b/freechat-client/share/kivy-examples/canvas/tesselate.py new file mode 100644 index 0000000..c5a4b3d --- /dev/null +++ b/freechat-client/share/kivy-examples/canvas/tesselate.py @@ -0,0 +1,146 @@ +''' +Tesselate Demonstration +======================= + +This demonstrates the experimental library for tesselating polygons. You +should see a hollow square with some buttons below it. You can click and +drag to create additional shapes, watching the number of vertexes and elements +at the top of the screen. The 'debug' button toggles showing the mesh in +different colors. +''' + + +from kivy.app import App +from kivy.graphics import Mesh, Color +from kivy.graphics.tesselator import Tesselator, WINDING_ODD, TYPE_POLYGONS +from kivy.uix.floatlayout import FloatLayout +from kivy.lang import Builder +from kivy.logger import Logger + +Builder.load_string(""" +: + BoxLayout: + size_hint_y: None + height: "48dp" + spacing: "2dp" + padding: "2dp" + + ToggleButton: + text: "Debug" + id: debug + on_release: root.build() + Button: + text: "New shape" + on_release: root.push_shape() + Button: + text: "Build" + on_release: root.build() + Button: + text: "Reset" + on_release: root.reset() + + BoxLayout: + size_hint_y: None + height: "48dp" + top: root.top + spacing: "2dp" + padding: "2dp" + Label: + id: status + text: "Status" +""") + + +class ShapeBuilder(FloatLayout): + def __init__(self, **kwargs): + super(ShapeBuilder, self).__init__(**kwargs) + self.shapes = [ + [100, 100, 300, 100, 300, 300, 100, 300], + [150, 150, 250, 150, 250, 250, 150, 250] + ] # the 'hollow square' shape + self.shape = [] + self.build() + + def on_touch_down(self, touch): + if super(ShapeBuilder, self).on_touch_down(touch): + return True + Logger.info('tesselate: on_touch_down (%5.2f, %5.2f)' % touch.pos) + self.shape.extend(touch.pos) + self.build() + return True + + def on_touch_move(self, touch): + if super(ShapeBuilder, self).on_touch_move(touch): + return True + Logger.info('tesselate: on_touch_move (%5.2f, %5.2f)' % touch.pos) + self.shape.extend(touch.pos) + self.build() + return True + + def on_touch_up(self, touch): + if super(ShapeBuilder, self).on_touch_up(touch): + return True + Logger.info('tesselate: on_touch_up (%5.2f, %5.2f)' % touch.pos) + self.push_shape() + self.build() + + def push_shape(self): + self.shapes.append(self.shape) + self.shape = [] + + def build(self): + tess = Tesselator() + count = 0 + for shape in self.shapes: + if len(shape) >= 3: + tess.add_contour(shape) + count += 1 + if self.shape and len(self.shape) >= 3: + tess.add_contour(self.shape) + count += 1 + if not count: + return + ret = tess.tesselate(WINDING_ODD, TYPE_POLYGONS) + Logger.info('tesselate: build: tess.tesselate returns {}'.format(ret)) + self.canvas.after.clear() + + debug = self.ids.debug.state == "down" + if debug: + with self.canvas.after: + c = 0 + for vertices, indices in tess.meshes: + Color(c, 1, 1, mode="hsv") + c += 0.3 + indices = [0] + for i in range(1, len(vertices) // 4): + if i > 0: + indices.append(i) + indices.append(i) + indices.append(0) + indices.append(i) + indices.pop(-1) + Mesh(vertices=vertices, indices=indices, mode="lines") + else: + with self.canvas.after: + Color(1, 1, 1, 1) + for vertices, indices in tess.meshes: + Mesh(vertices=vertices, indices=indices, + mode="triangle_fan") + + self.ids.status.text = "Shapes: {} - Vertex: {} - Elements: {}".format( + count, tess.vertex_count, tess.element_count) + + def reset(self): + self.shapes = [] + self.shape = [] + self.ids.status.text = "Shapes: {} - Vertex: {} - Elements: {}".format( + 0, 0, 0) + self.canvas.after.clear() + + +class TessApp(App): + def build(self): + return ShapeBuilder() + + +TessApp().run() diff --git a/freechat-client/share/kivy-examples/canvas/texture.py b/freechat-client/share/kivy-examples/canvas/texture.py new file mode 100644 index 0000000..c12d842 --- /dev/null +++ b/freechat-client/share/kivy-examples/canvas/texture.py @@ -0,0 +1,143 @@ +''' +Texture Wrapping and Coordinates Example +======================================== + +This example changes texture properties and the properties +of its containing rectangle. You should see some a multicolored +texture with sliders to the left and below and buttons at the +bottom of the screen. The image texture_example_image.png is +rendered into the rectangle. Sliders change the number of copies of the +texture (the tex_coords), the size of enclosing rectangle (the taw_height +and taw_width) while the buttons change how the texture is rendered when more +than one copy is in the rectangle (the +texture_wrap). + +''' + + +from kivy.uix.widget import Widget +from kivy.properties import ObjectProperty, ListProperty, StringProperty +from kivy.lang import Builder +from kivy.clock import Clock +from kivy.base import runTouchApp + + +class TextureAccessibleWidget(Widget): + texture = ObjectProperty(None) + tex_coords = ListProperty([0, 0, 1, 0, 1, 1, 0, 1]) + texture_wrap = StringProperty('clamp_to_edge') + + def __init__(self, **kwargs): + super(TextureAccessibleWidget, self).__init__(**kwargs) + Clock.schedule_once(self.texture_init, 0) + + def texture_init(self, *args): + self.texture = self.canvas.children[-1].texture + + def on_texture_wrap(self, instance, value): + self.texture.wrap = value + + +root = Builder.load_string(''' +: + canvas: + Rectangle: + pos: self.pos + size: self.size + source: 'texture_example_image.png' + tex_coords: root.tex_coords + +: + min: 0.0 + max: 1.0 + value: slider.value + Slider: + id: slider + orientation: root.orientation + min: root.min + max: root.max + value: 1.0 + Label: + size_hint: None, None + size: min(root.size), min(root.size) + text: str(slider.value)[:4] + +BoxLayout: + orientation: 'vertical' + BoxLayout: + SliderWithValue: + orientation: 'vertical' + size_hint_x: None + width: dp(40) + min: 0 + max: 5 + value: 1 + on_value: taw.tex_coords[5] = self.value + on_value: taw.tex_coords[7] = self.value + SliderWithValue: + orientation: 'vertical' + size_hint_x: None + width: dp(40) + min: 0 + max: taw_container.height + value: 0.5*taw_container.height + on_value: taw.height = self.value + AnchorLayout: + id: taw_container + anchor_x: 'left' + anchor_y: 'bottom' + TextureAccessibleWidget: + id: taw + size_hint: None, None + BoxLayout: + size_hint_y: None + height: dp(80) + BoxLayout: + orientation: 'vertical' + size_hint_x: None + width: dp(80) + Label: + text: 'size' + text_size: self.size + halign: 'right' + valign: 'middle' + Label: + text: 'tex_coords' + text_size: self.size + halign: 'left' + valign: 'middle' + BoxLayout: + orientation: 'vertical' + SliderWithValue: + min: 0 + max: taw_container.width + value: 0.5*taw_container.width + on_value: taw.width = self.value + SliderWithValue: + min: 0. + max: 5. + value: 1. + on_value: taw.tex_coords[2] = self.value + on_value: taw.tex_coords[4] = self.value + + BoxLayout: + size_hint_y: None + height: dp(50) + Label: + text: 'texture wrap:' + text_size: self.size + valign: 'middle' + halign: 'center' + Button: + text: 'clamp_to_edge' + on_press: taw.texture_wrap = 'clamp_to_edge' + Button: + text: 'repeat' + on_press: taw.texture_wrap = 'repeat' + Button: + text: 'mirrored_repeat' + on_press: taw.texture_wrap = 'mirrored_repeat' +''') + + +runTouchApp(root) diff --git a/freechat-client/share/kivy-examples/canvas/texture_example_image.png b/freechat-client/share/kivy-examples/canvas/texture_example_image.png new file mode 100644 index 0000000..c0e54c5 Binary files /dev/null and b/freechat-client/share/kivy-examples/canvas/texture_example_image.png differ diff --git a/freechat-client/share/kivy-examples/container/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/container/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..06f7f5d Binary files /dev/null and b/freechat-client/share/kivy-examples/container/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/container/kv/1.kv b/freechat-client/share/kivy-examples/container/kv/1.kv new file mode 100644 index 0000000..19634eb --- /dev/null +++ b/freechat-client/share/kivy-examples/container/kv/1.kv @@ -0,0 +1,28 @@ +#:kivy 1.8.0 +#:import datetime datetime + +RootWidget: + # import container + container: container + + # fill the container + BoxLayout: + id: container + orientation: 'vertical' + padding: 0 + spacing: 3 + + Label: + text: 'screen-1' + + BoxLayout: + orientation: 'horizontal' + padding: 0 + spacing: 1 + size_hint: 1, 0.1 + + # weiter button + Button: + size_hint: 0.2, 1 + text: 'next' + on_release: app.next_screen('2') diff --git a/freechat-client/share/kivy-examples/container/kv/2.kv b/freechat-client/share/kivy-examples/container/kv/2.kv new file mode 100644 index 0000000..4a88ee7 --- /dev/null +++ b/freechat-client/share/kivy-examples/container/kv/2.kv @@ -0,0 +1,28 @@ +#:kivy 1.8.0 +#:import datetime datetime + +RootWidget: + # import container + container: container + + # fill the container + BoxLayout: + id: container + orientation: 'vertical' + padding: 0 + spacing: 3 + + Label: + text: 'screen-2' + + BoxLayout: + orientation: 'horizontal' + padding: 0 + spacing: 1 + size_hint: 1, 0.1 + + # weiter button + Button: + size_hint: 0.2, 1 + text: 'next' + on_release: app.next_screen('3') diff --git a/freechat-client/share/kivy-examples/container/kv/3.kv b/freechat-client/share/kivy-examples/container/kv/3.kv new file mode 100644 index 0000000..c4a7a2e --- /dev/null +++ b/freechat-client/share/kivy-examples/container/kv/3.kv @@ -0,0 +1,28 @@ +#:kivy 1.8.0 +#:import datetime datetime + +RootWidget: + # import container + container: container + + # fill the container + BoxLayout: + id: container + orientation: 'vertical' + padding: 0 + spacing: 3 + + Label: + text: 'screen-3' + + BoxLayout: + orientation: 'horizontal' + padding: 0 + spacing: 1 + size_hint: 1, 0.1 + + # weiter button + Button: + size_hint: 0.2, 1 + text: 'next' + on_release: app.next_screen('1') diff --git a/freechat-client/share/kivy-examples/container/kv/root.kv b/freechat-client/share/kivy-examples/container/kv/root.kv new file mode 100644 index 0000000..b927522 --- /dev/null +++ b/freechat-client/share/kivy-examples/container/kv/root.kv @@ -0,0 +1,32 @@ +#:kivy 1.8.0 + +RootWidget: + # import container + container: container + + BoxLayout: + orientation: 'vertical' + padding: 0 + spacing: 6 + + # bottom-left part: + BoxLayout: + orientation: 'horizontal' + padding: 0 + spacing: 6 + + # bottom-left + BoxLayout: + size_hint: 0.12, 0.12 + orientation: 'vertical' + padding: 0 + spacing: 6 + + # option calibrate + Button: + text: 'Start' + on_release: app.next_screen('1') + + # create container (bottom-right) + BoxLayout: + id: container diff --git a/freechat-client/share/kivy-examples/container/main.py b/freechat-client/share/kivy-examples/container/main.py new file mode 100644 index 0000000..adaa182 --- /dev/null +++ b/freechat-client/share/kivy-examples/container/main.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +''' +Container Example +============== + +This example shows how to add a container to our screen. +A container is simply an empty place on the screen which +could be filled with any other content from a .kv file. +''' +from kivy.app import App +from kivy.lang import Builder +from kivy.uix.boxlayout import BoxLayout +from kivy.properties import ObjectProperty + +import kivy +kivy.require('1.8.0') + + +class RootWidget(BoxLayout): + '''Create a controller that receives a custom widget from the kv lang file. + Add an action to be called from a kv file. + ''' + + container = ObjectProperty(None) + + +class EzsApp(App): + + '''This is the app itself''' + + def build(self): + '''This method loads the root.kv file automatically + + :rtype: none + ''' + # loading the content of root.kv + self.root = Builder.load_file('kv/root.kv') + + def next_screen(self, screen): + '''Clear container and load the given screen object from file in kv + folder. + + :param screen: name of the screen object made from the loaded .kv file + :type screen: str + :rtype: none + ''' + + filename = screen + '.kv' + # unload the content of the .kv file + # reason: it could have data from previous calls + Builder.unload_file('kv/' + filename) + # clear the container + self.root.container.clear_widgets() + # load the content of the .kv file + screen = Builder.load_file('kv/' + filename) + # add the content of the .kv file to the container + self.root.container.add_widget(screen) + + +if __name__ == '__main__': + '''Start the application''' + + EzsApp().run() diff --git a/freechat-client/share/kivy-examples/cover/__pycache__/cover_image.cpython-37.pyc b/freechat-client/share/kivy-examples/cover/__pycache__/cover_image.cpython-37.pyc new file mode 100644 index 0000000..fa86882 Binary files /dev/null and b/freechat-client/share/kivy-examples/cover/__pycache__/cover_image.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/cover/__pycache__/cover_video.cpython-37.pyc b/freechat-client/share/kivy-examples/cover/__pycache__/cover_video.cpython-37.pyc new file mode 100644 index 0000000..f1b8f64 Binary files /dev/null and b/freechat-client/share/kivy-examples/cover/__pycache__/cover_video.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/cover/cover_image.py b/freechat-client/share/kivy-examples/cover/cover_image.py new file mode 100644 index 0000000..60585d9 --- /dev/null +++ b/freechat-client/share/kivy-examples/cover/cover_image.py @@ -0,0 +1,25 @@ +import kivy +from kivy.app import App +from kivy.uix.behaviors import CoverBehavior +from kivy.uix.image import Image + + +class CoverImage(CoverBehavior, Image): + """Image using cover behavior. + """ + + def __init__(self, **kwargs): + super(CoverImage, self).__init__(**kwargs) + texture = self._coreimage.texture + self.reference_size = texture.size + self.texture = texture + + +class MainApp(App): + + def build(self): + return CoverImage(source='../widgets/cityCC0.png') + + +if __name__ == '__main__': + MainApp().run() diff --git a/freechat-client/share/kivy-examples/cover/cover_video.py b/freechat-client/share/kivy-examples/cover/cover_video.py new file mode 100644 index 0000000..7be65b6 --- /dev/null +++ b/freechat-client/share/kivy-examples/cover/cover_video.py @@ -0,0 +1,31 @@ +import kivy +from kivy.app import App +from kivy.uix.behaviors import CoverBehavior +from kivy.uix.video import Video + + +class CoverVideo(CoverBehavior, Video): + """Video using cover behavior. + """ + + def _on_video_frame(self, *largs): + video = self._video + if not video: + return + texture = video.texture + self.reference_size = texture.size + self.calculate_cover() + self.duration = video.duration + self.position = video.position + self.texture = texture + self.canvas.ask_update() + + +class MainApp(App): + + def build(self): + return CoverVideo(source='../widgets/cityCC0.mpg', play=True) + + +if __name__ == '__main__': + MainApp().run() diff --git a/freechat-client/share/kivy-examples/demo/__pycache__/camera_puzzle.cpython-37.pyc b/freechat-client/share/kivy-examples/demo/__pycache__/camera_puzzle.cpython-37.pyc new file mode 100644 index 0000000..88f4fb5 Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/__pycache__/camera_puzzle.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/demo/camera_puzzle.py b/freechat-client/share/kivy-examples/demo/camera_puzzle.py new file mode 100644 index 0000000..c6f2a9f --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/camera_puzzle.py @@ -0,0 +1,98 @@ +''' +Shuffled Camera Feed Puzzle +=========================== + +This demonstrates using Scatter widgets with a live camera. +You should see a shuffled grid of rectangles that make up the +camera feed. You can drag the squares around to see the +unscrambled camera feed or double click to scramble the grid +again. +''' + + +from kivy.app import App +from kivy.uix.camera import Camera +from kivy.uix.widget import Widget +from kivy.uix.slider import Slider +from kivy.uix.scatter import Scatter +from kivy.animation import Animation +from kivy.graphics import Color, Rectangle +from kivy.properties import NumericProperty +from random import randint, random +from functools import partial + + +class Puzzle(Camera): + + blocksize = NumericProperty(100) + + def on_texture_size(self, instance, value): + self.build() + + def on_blocksize(self, instance, value): + self.build() + + def build(self): + self.clear_widgets() + texture = self.texture + if not texture: + return + bs = self.blocksize + tw, th = self.texture_size + for x in range(int(tw / bs)): + for y in range(int(th / bs)): + bx = x * bs + by = y * bs + subtexture = texture.get_region(bx, by, bs, bs) + # node = PuzzleNode(texture=subtexture, + # size=(bs, bs), pos=(bx, by)) + node = Scatter(pos=(bx, by), size=(bs, bs)) + with node.canvas: + Color(1, 1, 1) + Rectangle(size=node.size, texture=subtexture) + self.add_widget(node) + + self.shuffle() + + def shuffle(self): + texture = self.texture + bs = self.blocksize + tw, th = self.texture_size + count = int(tw / bs) * int(th / bs) + indices = list(range(count)) + childindex = 0 + while indices: + index = indices.pop(randint(0, len(indices) - 1)) + x = bs * (index % int(tw / bs)) + y = bs * int(index / int(tw / bs)) + child = self.children[childindex] + a = Animation(d=random() / 4.) + Animation(pos=(x, y), + t='out_quad', d=.4) + a.start(child) + childindex += 1 + + def on_touch_down(self, touch): + if touch.is_double_tap: + self.shuffle() + return True + super(Puzzle, self).on_touch_down(touch) + + +class PuzzleApp(App): + def build(self): + root = Widget() + puzzle = Puzzle(resolution=(640, 480), play=True) + slider = Slider(min=100, max=200, step=10, size=(800, 50)) + slider.bind(value=partial(self.on_value, puzzle)) + + root.add_widget(puzzle) + root.add_widget(slider) + return root + + def on_value(self, puzzle, instance, value): + value = int((value + 5) / 10) * 10 + puzzle.blocksize = value + instance.value = value + + +PuzzleApp().run() diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/demo/kivycatalog/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..9a0b27e Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/kivycatalog/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/AnchorLayoutContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/AnchorLayoutContainer.kv new file mode 100644 index 0000000..5890fac --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/AnchorLayoutContainer.kv @@ -0,0 +1,15 @@ +#:kivy 1.4 + +AnchorLayout: + anchor_x: "right" + anchor_y: "bottom" + Button: + text: "Button 1" + size_hint: .2, .4 + Button: + text: "Button 2" + size_hint: .4, .2 + + Button: + text: "Button 3" + size_hint: .2, .2 diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/BoxLayoutContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/BoxLayoutContainer.kv new file mode 100644 index 0000000..5cee03b --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/BoxLayoutContainer.kv @@ -0,0 +1,14 @@ +#:kivy 1.4 + +BoxLayout: + orientation: 'vertical' + padding: 20 + spacing: 10 + Button: + text: "Button 1" + size_hint: 1, None + Button: + text: "Button 2" + size_hint: 1, 0.5 + Button: + text: "Button 3" \ No newline at end of file diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/ButtonContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/ButtonContainer.kv new file mode 100644 index 0000000..9b71977 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/ButtonContainer.kv @@ -0,0 +1,27 @@ +#:kivy 1.4 + +GridLayout: + cols: 2 + Button: + text: "Button 1" + Button: + text: "Button 2" + font_size: 24 + Button: + text: "Button 3" + background_color: .7, .7, 1, 1 + Button: + text: "Button 4" + on_press: self.text = 'pressed' + on_release: self.text = 'Button 4' + ToggleButton: + text: "A toggle button" + ToggleButton: + text: "a toggle button in a group" + group: "money" + ToggleButton: + text: "A toggle in the down state" + state: "down" + ToggleButton: + text: "another toggle button in a group" + group: "money" diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/CheckBoxContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/CheckBoxContainer.kv new file mode 100644 index 0000000..2021466 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/CheckBoxContainer.kv @@ -0,0 +1,28 @@ +#:kivy 1.4 + +GridLayout: + cols: 2 + CheckBox: + Label: + text: "A checkbox" + CheckBox: + active: True + Label: + text: "Another checkbox" + CheckBox: + group: "money" + Label: + text: "A radio in a group" + CheckBox: + group: "money" + active: True + + Label: + text: "Another radio in same group" + Switch: + Label: + text: "A Switch" + Switch: + active: True + Label: + text: "An active switch" diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/FileChooserContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/FileChooserContainer.kv new file mode 100644 index 0000000..a14cef1 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/FileChooserContainer.kv @@ -0,0 +1,19 @@ +#:kivy 1.4 + +BoxLayout: + # Double as a Tabbed Panel Demo! + TabbedPanel: + tab_pos: "top_right" + default_tab_text: "List View" + default_tab_content: list_view_tab + + TabbedPanelHeader: + text: 'Icon View' + content: icon_view_tab + + FileChooserListView: + id: list_view_tab + + FileChooserIconView: + id: icon_view_tab + show_hidden: True diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/FloatLayoutContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/FloatLayoutContainer.kv new file mode 100644 index 0000000..303cec6 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/FloatLayoutContainer.kv @@ -0,0 +1,16 @@ +#:kivy 1.4 + +FloatLayout: + Button: + text: "Button 1" + pos: 100, 100 + size_hint: .2, .4 + Button: + text: "Button 2" + pos: 200, 200 + size_hint: .4, .2 + + Button: + text: "Button 3" + pos_hint: {'x': .8, 'y': .6} + size_hint: .2, .2 diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/GridLayoutContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/GridLayoutContainer.kv new file mode 100644 index 0000000..a6868bb --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/GridLayoutContainer.kv @@ -0,0 +1,20 @@ +#:kivy 1.4 + +GridLayout: + cols: 2 + Button: + text: "Button 1" + size_hint_x: None + width: 100 + Button: + text: "Button 2" + Button: + text: "Button 3" + size_hint_x: None + Button: + text: "Button 4" + Button: + text: "Button 5" + size_hint_x: None + Button: + text: "Button 6" diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/LabelContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/LabelContainer.kv new file mode 100644 index 0000000..220b108 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/LabelContainer.kv @@ -0,0 +1,62 @@ +#:kivy 1.4 + +GridLayout: + cols: 1 + Label: + text: "Label crowded by size hint" + size_hint_y: .2 + Label: + text: 'Label with\nmultiple\nlines' + size_hint_y: .4 + Label: + font_size: '48sp' + text: "Label [color=ff3333][sub]with[/sub][/color] [color=3333ff][b]mark[sup]up[/sup][/b][/color]" + markup: True + Button: + text: 'Labels in buttons' + GridLayout: + cols: 2 + size_hint_y: 3 + Button: + text: 'Left aligned at middle' + padding: 10, 10 + halign: 'left' + valign: 'middle' + text_size: self.size + Button: + text: 'right aligned at top' + padding: 10, 10 + halign: 'right' + valign: 'top' + text_size: self.size + Button: + text: 'Left aligned with no padding' + halign: 'left' + valign: 'middle' + text_size: self.size + Button: + text: 'Multiple\nbold italic centered\nlines' + halign: 'center' + valign: 'middle' + bold: True + italic: True + text_size: self.size + Button: + text: 'multiple\nspaced lines\ncentered' + padding: 10, 10 + halign: 'center' + valign: 'middle' + line_height: 1.5 + text_size: self.size + Button: + text: 'button without\npadding\nor align' + Label: + text: "Label with [ref=reference]reference[/ref]" + markup: True + on_ref_press: self.text = "ref clicked" + Label: + text: "different font" + bold: True + font_name: "data/fonts/RobotoMono-Regular.ttf" + font_size: 32 + valign: 'bottom' diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/MediaContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/MediaContainer.kv new file mode 100644 index 0000000..395f2c9 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/MediaContainer.kv @@ -0,0 +1,9 @@ +#:kivy 1.4 + +BoxLayout: + orientation: "vertical" + Image: + source: "../../widgets/cityCC0.png" + Video: + source: "../../widgets/cityCC0.mpg" + state: "play" diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/PlaygroundContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/PlaygroundContainer.kv new file mode 100644 index 0000000..b632bc2 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/PlaygroundContainer.kv @@ -0,0 +1,4 @@ +#:kivy 1.4 + +RstDocument: + text: "Welcome\n---------------\nThis Kivy Catalog is an interactive showcase of Kivy Widgets defined with the Kivy (.kv) language. You can edit the .kv language description in the left pane and see your changes affect the widgets in the right pane. Your changes will update the widget within a few seconds though the impatient could type 'Ctrl-S' or click 'Render Now'.\n\nYou can explore most Kivy widgets from the menu in the upper left corner. You can also use this playground to test your Kivy language code and adding a new .kv file to the interface is easy.\n\nSome Kivy widgets are omitted from this catalog or could have more complete .kv representation. This is beta software; pull requests are welcome." diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/PopupContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/PopupContainer.kv new file mode 100644 index 0000000..a519cdb --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/PopupContainer.kv @@ -0,0 +1,36 @@ +#:kivy 1.4 + +BoxLayout: + id: bl + orientation: "vertical" + popup: popup.__self__ + canvas: + Color: + rgba: .18, .18, .18, .91 + Rectangle: + size: self.size + pos: self.pos + Bubble: + size_hint: (None, None) + size: (150, 50) + pos_hint: {'center_x': .5, 'y': .6} + arrow_pos: 'bottom_mid' + orientation: 'horizontal' + BubbleButton: + text: 'This is' + BubbleButton: + text: 'a' + BubbleButton: + text: 'Bubble' + Button: + text: 'press to show popup' + on_release: root.popup.open() + Popup: + id: popup + on_parent: if self.parent == bl: bl.remove_widget(self) + title: "An example popup" + content: popupcontent + Button: + id: popupcontent + text: "press to dismiss" + on_release: popup.dismiss() diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/ProgressBarContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/ProgressBarContainer.kv new file mode 100644 index 0000000..3129b15 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/ProgressBarContainer.kv @@ -0,0 +1,17 @@ +#:kivy 1.4 + +BoxLayout: + orientation: 'vertical' + padding: 50 + ProgressBar: + id: bar + value: 140 + max: 300 + Slider: + id: slider + max: 200 + value: 140 + on_value: slider.value = self.value + Slider: + orientation: 'vertical' + on_value: slider.value = self.value diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/RestContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/RestContainer.kv new file mode 100644 index 0000000..83bffdf --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/RestContainer.kv @@ -0,0 +1,5 @@ +#:kivy 1.4 + +BoxLayout: + RstDocument: + text: ".. _top:\n\nHello world\n===========\n\nThis is an **emphased text**, some ``interpreted text``.\nAnd this is a reference to top_::\n\n $ print('Hello world')\n" diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/ScatterContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/ScatterContainer.kv new file mode 100644 index 0000000..aa668ee --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/ScatterContainer.kv @@ -0,0 +1,16 @@ +#:kivy 1.4 + +FloatLayout: + Scatter: + size_hint: None, None + size: 100, 100 + pos: 100, 100 + Image: + source: "../../widgets/cityCC0.png" + Scatter: + size_hint: None, None + size: 100, 100 + pos: 100, 100 + do_rotation: False + Label: + text: "something" diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/SelectorsContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/SelectorsContainer.kv new file mode 100644 index 0000000..342e679 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/SelectorsContainer.kv @@ -0,0 +1,10 @@ +#:kivy 1.4 + +BoxLayout: + orientation: 'vertical' + Spinner: + text: "Work" + values: "Work", "Home", "Mobile", "Skype" + size_hint: (None, None) + size: (100, 44) + # Wanted to put DropDown here, too, but it seems not to be working too well when loaded from .kv diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/StackLayoutContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/StackLayoutContainer.kv new file mode 100644 index 0000000..867261d --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/StackLayoutContainer.kv @@ -0,0 +1,25 @@ +#:kivy 1.4 + +StackLayout: + orientation: 'tb-lr' + padding: 10 + spacing: 5 + Button: + text: "Button 1" + size_hint: .2, .4 + width: 100 + Button: + text: "Button 2" + size_hint: .2, .4 + Button: + text: "Button 3" + size_hint: .2, .4 + Button: + text: "Button 4" + size_hint: .2, .4 + Button: + text: "Button 5" + size_hint: .2, .4 + Button: + text: "Button 6" + size_hint: .2, .4 \ No newline at end of file diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/TextContainer.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/TextContainer.kv new file mode 100644 index 0000000..657cdba --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/container_kvs/TextContainer.kv @@ -0,0 +1,20 @@ +#:kivy 1.4 + +BoxLayout: + orientation: "vertical" + TextInput: + text: "Single Line Input" + multiline: False + TextInput: + text: "Text Input, start typing here\nmultiline\nsupport" + background_color: .8, .8, 0, 1 + size_hint: 1, 3 + TextInput: + password: True + text: "Password (but you can't see it)" + multiline: False + on_text: viewer.text = self.text + TextInput: + id: viewer + readonly: True + text: "edit the password to see it here" diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/kivycatalog.kv b/freechat-client/share/kivy-examples/demo/kivycatalog/kivycatalog.kv new file mode 100644 index 0000000..e2e4c5d --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/kivycatalog.kv @@ -0,0 +1,144 @@ +#:kivy 1.4 +#:import KivyLexer kivy.extras.highlight.KivyLexer + +: + canvas.before: + Color: + rgb: 0, 0, 0 + Rectangle: + pos: self.pos + size: self.size + +: + language_box: language_box + screen_manager: screen_manager + auto_reload: chkbx.active + info_label: info_lbl + orientation: 'vertical' + BoxLayout: + padding: '2sp' + canvas: + Color: + rgba: 1, 1, 1, .6 + Rectangle: + size: self.size + pos: self.pos + size_hint: 1, None + height: '45sp' + Spinner: + size_hint: None, 1 + width: '108sp' + text: 'Welcome' + values: [screen.name for screen in screen_manager.screens] + on_text: root.show_kv(*args) + Widget: + BoxLayout: + size_hint: None, 1 + width: '150sp' + Label: + text: "Auto Reload" + CheckBox: + id: chkbx + active: True + size_hint_x: 1 + Button: + size_hint: None, 1 + width: '108sp' + text: 'Render Now' + on_release: root.change_kv(*args) + BoxLayout: + id: reactive_layout + orientation: 'vertical' if self.width < self.height else 'horizontal' + + Splitter: + id: editor_pane + max_size: (reactive_layout.height if self.vertical else reactive_layout.width) - self.strip_size + min_size: sp(30) + self.strip_size + vertical: 1 if reactive_layout.width < reactive_layout.height else 0 + sizable_from: 'bottom' if self.vertical else 'right' + size_hint: (1, None) if self.vertical else (None, 1) + size: 400, 400 + on_vertical: + mid_size = self.max_size/2 + if args[1]: self.height = mid_size + if not args[1]: self.width = mid_size + ScrollView: + id: kr_scroll + KivyRenderTextInput: + catalog: root + id: language_box + auto_indent: True + lexer: KivyLexer() + size_hint: 1, None + height: max(kr_scroll.height, self.minimum_height) + valign: "top" + text: "This box will display the kivy language for whatever has been selected" + on_text: root.schedule_reload() + on_cursor: root.schedule_reload() + ScreenManager: + id: screen_manager + Screen: + name: "Welcome" + PlaygroundContainer: + Screen: + name: "Float Layout" + FloatLayoutContainer + Screen: + name: "Box Layout" + BoxLayoutContainer: + Screen: + name: "Anchor Layout" + AnchorLayoutContainer: + Screen: + name: "Grid Layout" + GridLayoutContainer: + Screen: + name: "Stack Layout" + StackLayoutContainer: + Screen: + name: "Buttons" + ButtonContainer: + Screen: + name: "Labels" + LabelContainer: + Screen: + name: "Booleans" + CheckBoxContainer: + Screen: + name: "Progress Bar" + ProgressBarContainer: + Screen: + name: "Media" + MediaContainer: + Screen: + name: "Text" + TextContainer: + Screen: + name: "Popups" + PopupContainer: + Screen: + name: "Selectors" + SelectorsContainer: + Screen: + name: "File Choosers" + FileChooserContainer: + Screen: + name: "Scatter" + ScatterContainer: + Screen: + name: "ReST" + RestContainer: + FloatLayout: + size_hint: 1, None + height: 0 + TextInput: + id:info_lbl + readonly: True + font_size: '14sp' + background_color: (0, 0, 0, 1) + foreground_color: (1, 1, 1, 1) + opacity:0 + size_hint: 1, None + text_size: self.size + height: '150pt' + top: 0 diff --git a/freechat-client/share/kivy-examples/demo/kivycatalog/main.py b/freechat-client/share/kivy-examples/demo/kivycatalog/main.py new file mode 100755 index 0000000..0085e1d --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/kivycatalog/main.py @@ -0,0 +1,192 @@ +''' +Kivy Catalog +============ + +The Kivy Catalog viewer showcases widgets available in Kivy +and allows interactive editing of kivy language code to get immediate +feedback. You should see a two panel screen with a menu spinner button +(starting with 'Welcome') and other controls across the top.The left pane +contains kivy (.kv) code, and the right side is that code rendered. You can +edit the left pane, though changes will be lost when you use the menu +spinner button. The catalog will show you dozens of .kv examples controlling +different widgets and layouts. + +The catalog's interface is set in the file kivycatalog.kv, while the +interfaces for each menu option are set in containers_kvs directory. To +add a new .kv file to the Kivy Catalog, add a .kv file into the container_kvs +directory and reference that file in the ScreenManager section of +kivycatalog.kv. + +Known bugs include some issue with the drop +''' +import kivy +kivy.require('1.4.2') +import os +import sys +from kivy.app import App +from kivy.factory import Factory +from kivy.lang import Builder, Parser, ParserException +from kivy.properties import ObjectProperty +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.codeinput import CodeInput +from kivy.animation import Animation +from kivy.clock import Clock + +CATALOG_ROOT = os.path.dirname(__file__) + +# Config.set('graphics', 'width', '1024') +# Config.set('graphics', 'height', '768') + +'''List of classes that need to be instantiated in the factory from .kv files. +''' +CONTAINER_KVS = os.path.join(CATALOG_ROOT, 'container_kvs') +CONTAINER_CLASSES = [c[:-3] for c in os.listdir(CONTAINER_KVS) + if c.endswith('.kv')] + + +class Container(BoxLayout): + '''A container is essentially a class that loads its root from a known + .kv file. + + The name of the .kv file is taken from the Container's class. + We can't just use kv rules because the class may be edited + in the interface and reloaded by the user. + See :meth: change_kv where this happens. + ''' + + def __init__(self, **kwargs): + super(Container, self).__init__(**kwargs) + self.previous_text = open(self.kv_file).read() + parser = Parser(content=self.previous_text) + widget = Factory.get(parser.root.name)() + Builder._apply_rule(widget, parser.root, parser.root) + self.add_widget(widget) + + @property + def kv_file(self): + '''Get the name of the kv file, a lowercase version of the class + name. + ''' + return os.path.join(CONTAINER_KVS, self.__class__.__name__ + '.kv') + + +for class_name in CONTAINER_CLASSES: + globals()[class_name] = type(class_name, (Container,), {}) + + +class KivyRenderTextInput(CodeInput): + def keyboard_on_key_down(self, window, keycode, text, modifiers): + is_osx = sys.platform == 'darwin' + # Keycodes on OSX: + ctrl, cmd = 64, 1024 + key, key_str = keycode + + if text and key not in (list(self.interesting_keys.keys()) + [27]): + # This allows *either* ctrl *or* cmd, but not both. + if modifiers == ['ctrl'] or (is_osx and modifiers == ['meta']): + if key == ord('s'): + self.catalog.change_kv(True) + return + + return super(KivyRenderTextInput, self).keyboard_on_key_down( + window, keycode, text, modifiers) + + +class Catalog(BoxLayout): + '''Catalog of widgets. This is the root widget of the app. It contains + a tabbed pain of widgets that can be displayed and a textbox where .kv + language files for widgets being demoed can be edited. + + The entire interface for the Catalog is defined in kivycatalog.kv, + although individual containers are defined in the container_kvs + directory. + + To add a container to the catalog, + first create the .kv file in container_kvs + The name of the file (sans .kv) will be the name of the widget available + inside the kivycatalog.kv + Finally modify kivycatalog.kv to add an AccordionItem + to hold the new widget. + Follow the examples in kivycatalog.kv to ensure the item + has an appropriate id and the class has been referenced. + + You do not need to edit any python code, just .kv language files! + ''' + language_box = ObjectProperty() + screen_manager = ObjectProperty() + _change_kv_ev = None + + def __init__(self, **kwargs): + self._previously_parsed_text = '' + super(Catalog, self).__init__(**kwargs) + self.show_kv(None, 'Welcome') + self.carousel = None + + def show_kv(self, instance, value): + '''Called when an a item is selected, we need to show the .kv language + file associated with the newly revealed container.''' + + self.screen_manager.current = value + + child = self.screen_manager.current_screen.children[0] + with open(child.kv_file, 'rb') as file: + self.language_box.text = file.read().decode('utf8') + if self._change_kv_ev is not None: + self._change_kv_ev.cancel() + self.change_kv() + # reset undo/redo history + self.language_box.reset_undo() + + def schedule_reload(self): + if self.auto_reload: + txt = self.language_box.text + child = self.screen_manager.current_screen.children[0] + if txt == child.previous_text: + return + child.previous_text = txt + if self._change_kv_ev is not None: + self._change_kv_ev.cancel() + if self._change_kv_ev is None: + self._change_kv_ev = Clock.create_trigger(self.change_kv, 2) + self._change_kv_ev() + + def change_kv(self, *largs): + '''Called when the update button is clicked. Needs to update the + interface for the currently active kv widget, if there is one based + on the kv file the user entered. If there is an error in their kv + syntax, show a nice popup.''' + + txt = self.language_box.text + kv_container = self.screen_manager.current_screen.children[0] + try: + parser = Parser(content=txt) + kv_container.clear_widgets() + widget = Factory.get(parser.root.name)() + Builder._apply_rule(widget, parser.root, parser.root) + kv_container.add_widget(widget) + except (SyntaxError, ParserException) as e: + self.show_error(e) + except Exception as e: + self.show_error(e) + + def show_error(self, e): + self.info_label.text = str(e).encode('utf-8') + self.anim = Animation(top=190.0, opacity=1, d=2, t='in_back') +\ + Animation(top=190.0, d=3) +\ + Animation(top=0, opacity=0, d=2) + self.anim.start(self.info_label) + + +class KivyCatalogApp(App): + '''The kivy App that runs the main root. All we do is build a catalog + widget into the root.''' + + def build(self): + return Catalog() + + def on_pause(self): + return True + + +if __name__ == "__main__": + KivyCatalogApp().run() diff --git a/freechat-client/share/kivy-examples/demo/multistroke/__pycache__/gesturedatabase.cpython-37.pyc b/freechat-client/share/kivy-examples/demo/multistroke/__pycache__/gesturedatabase.cpython-37.pyc new file mode 100644 index 0000000..4a6ae60 Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/multistroke/__pycache__/gesturedatabase.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/demo/multistroke/__pycache__/helpers.cpython-37.pyc b/freechat-client/share/kivy-examples/demo/multistroke/__pycache__/helpers.cpython-37.pyc new file mode 100644 index 0000000..95e0798 Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/multistroke/__pycache__/helpers.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/demo/multistroke/__pycache__/historymanager.cpython-37.pyc b/freechat-client/share/kivy-examples/demo/multistroke/__pycache__/historymanager.cpython-37.pyc new file mode 100644 index 0000000..3b8586e Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/multistroke/__pycache__/historymanager.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/demo/multistroke/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/demo/multistroke/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..cfeb469 Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/multistroke/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/demo/multistroke/__pycache__/settings.cpython-37.pyc b/freechat-client/share/kivy-examples/demo/multistroke/__pycache__/settings.cpython-37.pyc new file mode 100644 index 0000000..e4c8455 Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/multistroke/__pycache__/settings.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/demo/multistroke/gesturedatabase.kv b/freechat-client/share/kivy-examples/demo/multistroke/gesturedatabase.kv new file mode 100644 index 0000000..24b982c --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/multistroke/gesturedatabase.kv @@ -0,0 +1,117 @@ +#:import os os + +: + size_hint: None, None + size: 120, 130 + on_pos: self._draw_trigger() + on_size: self._draw_trigger() + Label: + id: namelbl + text: root.name + size_hint: 1, None + height: 40 + font_size: 14 + color: 1, 0, 0, 1 + Label: + id: stats + text: + ( str(root.template_count) + " templates\nin " + + str(len(root.gesture_list)) + ' gestures' ) + size_hint: 1, None + height: 60 + ToggleButton: + id: select + text: 'Select' + size_hint: None, None + size: 120, 30 + on_state: root.toggle_selected() + +: + rows: 1 + spacing: 10 + padding: 10 + cols_minimum: {0: 200} + GridLayout: + id: menu + cols: 1 + spacing: 10 + padding: 10 + size_hint: None, 1 + width: 200 + Button: + text: root.selected_count and 'Deselect all' or 'Select all' + size_hint_y: None + height: 100 + on_press: root.mass_select() + Button: + text: + (root.selected_count + and 'Save ' + str(root.selected_count) + ' gestures' + or 'Save all') + size_hint_y: None + height: 100 + on_press: root.export_popup.open() + Button: + text: + (root.selected_count + and 'Unload ' + str(root.selected_count) + ' gestures' + or 'Unload all') + size_hint_y: None + height: 100 + on_press: root.unload_gestures() + Button: + text: 'Load from file' + size_hint_y: None + height: 100 + on_press: root.import_popup.open() + ScrollView: + on_scroll_y: root.redraw_all() + StackLayout: + id: gesture_list + spacing: 10 + padding: 10 + size_hint: 1, None + height: self.minimum_height + +: + title: 'Specify filename' + auto_dismiss: True + size_hint: None, None + size: 400, 400 + GridLayout: + cols: 1 + spacing: 10 + padding: 10 + rows_minimum: {0: 100} + Label: + text: + ( 'The extension .kg will be appended automatically.\n' + + 'The file is saved to the current working directory, unless\n' + + 'you specify an absolute path') + TextInput: + id: filename + multiline: False + size_hint: 1, None + height: 40 + Button: + id: save_btn + text: 'Save' + size_hint: 1, None + height: 45 + Button: + id: cancel_btn + text: 'Cancel' + size_hint: 1, None + height: 45 + on_press: root.dismiss() + +: + auto_dismiss: True + size_hint: None, None + size: 450, 400 + FileChooserListView: + id: filechooser + size_hint: None, None + size: 400, 380 + filters: ['*.kg'] + path: os.getcwd() diff --git a/freechat-client/share/kivy-examples/demo/multistroke/gesturedatabase.py b/freechat-client/share/kivy-examples/demo/multistroke/gesturedatabase.py new file mode 100644 index 0000000..6034f12 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/multistroke/gesturedatabase.py @@ -0,0 +1,180 @@ +__all__ = ('GestureDatabase', 'GestureDatabaseItem') + +from kivy.clock import Clock +from kivy.lang import Builder +from kivy.properties import NumericProperty, StringProperty +from kivy.properties import ListProperty, ObjectProperty +from kivy.uix.gridlayout import GridLayout +from kivy.uix.floatlayout import FloatLayout +from kivy.uix.popup import Popup +from kivy.graphics import Rectangle, Color +from kivy.multistroke import Recognizer + +# local libraries +from helpers import InformationPopup + + +Builder.load_file('gesturedatabase.kv') + + +class GestureExportPopup(Popup): + pass + + +class GestureImportPopup(Popup): + pass + + +class GestureDatabaseItem(FloatLayout): + name = StringProperty('(no name)') + template_count = NumericProperty(0) + gesture_list = ListProperty([]) + + def __init__(self, **kwargs): + super(GestureDatabaseItem, self).__init__(**kwargs) + self.rect = None + self._draw_trigger = Clock.create_trigger(self.draw_item, 0) + self.update_template_count() + self.bind(gesture_list=self.update_template_count) + self.register_event_type('on_select') + self.register_event_type('on_deselect') + + def toggle_selected(self, *l): + self._draw_rect(clear=True) + if self.ids.select.state == 'down': + self.dispatch('on_select') + self.ids.select.text = 'Deselect' + else: + self.dispatch('on_deselect') + self.ids.select.text = 'Select' + + def update_template_count(self, *l): + tpl_count = 0 + for g in self.gesture_list: + tpl_count += len(g.templates) + self.template_count = tpl_count + + def draw_item(self, *l): + self.ids.namelbl.pos = self.pos + self.ids.namelbl.y += 90 + self.ids.stats.pos = self.pos + self.ids.stats.y += 40 + self.ids.select.pos = self.pos + self._draw_rect() + + def _draw_rect(self, clear=False, *l): + col = self.ids.select.state == 'down' and 1 or .2 + with self.canvas: + Color(col, 0, 0, .15) + if self.rect or clear: + self.canvas.remove(self.rect) + self.rect = Rectangle(size=self.size, pos=self.pos) + + def on_select(*l): + pass + + def on_deselect(*l): + pass + + +class GestureDatabase(GridLayout): + selected_count = NumericProperty(0) + recognizer = ObjectProperty(None) + export_popup = ObjectProperty(GestureExportPopup()) + import_popup = ObjectProperty(GestureImportPopup()) + info_popup = ObjectProperty(InformationPopup()) + + def __init__(self, **kwargs): + super(GestureDatabase, self).__init__(**kwargs) + self.redraw_all = Clock.create_trigger(self._redraw_gesture_list, 0) + self.export_popup.ids.save_btn.bind(on_press=self.perform_export) + self.import_popup.ids.filechooser.bind(on_submit=self.perform_import) + + def import_gdb(self): + self.gdict = {} + for gesture in self.recognizer.db: + if gesture.name not in self.gdict: + self.gdict[gesture.name] = [] + self.gdict[gesture.name].append(gesture) + + self.selected_count = 0 + self.ids.gesture_list.clear_widgets() + for k in sorted(self.gdict, key=lambda n: n.lower()): + gitem = GestureDatabaseItem(name=k, gesture_list=self.gdict[k]) + gitem.bind(on_select=self.select_item) + gitem.bind(on_deselect=self.deselect_item) + self.ids.gesture_list.add_widget(gitem) + + def select_item(self, *l): + self.selected_count += 1 + + def deselect_item(self, *l): + self.selected_count -= 1 + + def mass_select(self, *l): + if self.selected_count: + for i in self.ids.gesture_list.children: + if i.ids.select.state == 'down': + i.ids.select.state = 'normal' + i.draw_item() + else: + for i in self.ids.gesture_list.children: + if i.ids.select.state == 'normal': + i.ids.select.state = 'down' + i.draw_item() + + def unload_gestures(self, *l): + if not self.selected_count: + self.recognizer.db = [] + self.ids.gesture_list.clear_widgets() + self.selected_count = 0 + return + + for i in self.ids.gesture_list.children[:]: + if i.ids.select.state == 'down': + self.selected_count -= 1 + for g in i.gesture_list: + # if g in self.recognizer.db: # not needed, for testing + self.recognizer.db.remove(g) + self.ids.gesture_list.remove_widget(i) + + def perform_export(self, *l): + path = self.export_popup.ids.filename.text + if not path: + self.export_popup.dismiss() + self.info_popup.text = 'Missing filename' + self.info_popup.open() + return + elif not path.lower().endswith('.kg'): + path += '.kg' + + self.save_selection_to_file(path) + + self.export_popup.dismiss() + self.info_popup.text = 'Gestures exported!' + self.info_popup.open() + + def perform_import(self, filechooser, *l): + count = len(self.recognizer.db) + for f in filechooser.selection: + self.recognizer.import_gesture(filename=f) + self.import_gdb() + self.info_popup.text = ("Imported %d gestures.\n" % + (len(self.recognizer.db) - count)) + self.import_popup.dismiss() + self.info_popup.open() + + def save_selection_to_file(self, filename, *l): + if not self.selected_count: + self.recognizer.export_gesture(filename=filename) + else: + tmpgdb = Recognizer() + for i in self.ids.gesture_list.children: + if i.ids.select.state == 'down': + for g in i.gesture_list: + tmpgdb.db.append(g) + tmpgdb.export_gesture(filename=filename) + + def _redraw_gesture_list(self, *l): + for child in self.ids.gesture_list.children: + child._draw_trigger() diff --git a/freechat-client/share/kivy-examples/demo/multistroke/helpers.py b/freechat-client/share/kivy-examples/demo/multistroke/helpers.py new file mode 100644 index 0000000..7c7b87a --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/multistroke/helpers.py @@ -0,0 +1,30 @@ +__all__ = ('InformationPopup', ) + +from kivy.uix.popup import Popup +from kivy.properties import StringProperty +from kivy.factory import Factory +from kivy.lang import Builder +from kivy.clock import Clock + +Builder.load_string(''' +: + auto_dismiss: True + size_hint: None, None + size: 400, 200 + on_open: root.dismiss_trigger() + title: root.title + Label: + text: root.text +''') + + +class InformationPopup(Popup): + title = StringProperty('Information') + text = StringProperty('') + + def __init__(self, time=1.5, **kwargs): + super(InformationPopup, self).__init__(**kwargs) + self.dismiss_trigger = Clock.create_trigger(self.dismiss, time) + + +Factory.register('InformationPopup', cls=InformationPopup) diff --git a/freechat-client/share/kivy-examples/demo/multistroke/historymanager.kv b/freechat-client/share/kivy-examples/demo/multistroke/historymanager.kv new file mode 100644 index 0000000..35c818b --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/multistroke/historymanager.kv @@ -0,0 +1,164 @@ +: + rows: 1 + spacing: 10 + GridLayout: + cols: 1 + size_hint_x: None + width: 150 + canvas: + Color: + rgba: 1, 1, 1, .1 + Rectangle: + size: self.size + pos: self.pos + + Button: + text: 'Clear History' + size_hint_y: None + height: 50 + on_press: root.clear_history() + + ScrollView: + id: scrollview + scroll_type: ['bars', 'content'] + bar_width: 4 + GridLayout: + id: history + cols: 1 + size_hint: 1, None + height: self.minimum_height + +: + orientation: 'vertical' + spacing: 10 + GridLayout: + id: settings + cols: 1 + top: root.top + Label: + text: '[b]Results (scroll for more)[/b]' + markup: True + size_hint_y: None + height: 30 + halign: 'left' + valign: 'middle' + text_size: self.size + canvas: + Color: + rgba: 47 / 255., 167 / 255., 212 / 255., .4 + Rectangle: + pos: self.x, self.y + 1 + size: self.size + Color: + rgb: .5, .5, .5 + Rectangle: + pos: self.x, self.y - 2 + size: self.width, 1 + + GridLayout: + id: analysis + top: root.top + rows: 1 + +: + canvas: + Color: + rgba: 1, 1, 1, self.selected and .3 or .1 + Rectangle: + pos: self.pos + size: self.size + + +: + canvas: + Color: + rgba: 1, 0, 0, .1 + Rectangle: + size: self.size + pos: self.pos + + ScrollView: + id: result_scrollview + scroll_type: ['bars', 'content'] + bar_width: 4 + GridLayout: + id: result_list + cols: 1 + size_hint: 1, None + height: self.minimum_height + + Button: + size_hint: None, None + width: 150 + height: 70 + text: 'Re-analyze' + on_press: root.dispatch('on_reanalyze_selected') + + +: + size_hint_y: None + height: 70 + markup: True + halign: 'left' + valign: 'top' + text_size: self.size + + +: + MultistrokeSettingTitle: + title: 'New gesture settings' + desc: 'Affects how to future input is matched against new gesture' + + MultistrokeSettingBoolean: + id: permute + title: 'Use Heap Permute algorithm?' + desc: + ('This will generate all possible stroke orders from the ' + + 'input. Only suitable for gestures with 1-3 strokes (or ' + + 'the number of templates will be huge)') + button_text: 'Heap Permute?' + value: True + + MultistrokeSettingBoolean: + id: stroke_sens + title: 'Require same number of strokes?' + desc: + ('When enabled, the new gesture will only match candidates ' + + 'with exactly the same stroke count. Enable if possible.') + button_text: 'Stroke sensitive?' + value: True + + MultistrokeSettingBoolean: + id: orientation_sens + title: 'Is gesture orientation sensitive?' + desc: + ('Enable to differentiate gestures that differ only by ' + + 'orientation (d/p, b/q, w/m), disable for gestures that ' + + 'look the same in any orientation (like a circle)') + button_text: 'Orientation\nsensitive?' + value: True + + MultistrokeSettingSlider: + id: angle_sim + title: 'Angle similarity threshold' + type: 'float' + desc: + ('Use a low number to distinguish similar gestures, higher ' + + 'number to match similar gestures (with differing angle)') + value: 30. + min: 1.0 + max: 179.0 + + MultistrokeSettingString: + id: name + title: 'Gesture name' + type: 'float' + desc: + ('Name of new gesture (including all generated templates). ' + + 'You can have as many gestures with the same name as you need') + + Button: + size_hint_y: None + height: 40 + text: 'Add to database' + on_press: root.parent.parent.parent.add_selected_to_database() diff --git a/freechat-client/share/kivy-examples/demo/multistroke/historymanager.py b/freechat-client/share/kivy-examples/demo/multistroke/historymanager.py new file mode 100644 index 0000000..b6abe6a --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/multistroke/historymanager.py @@ -0,0 +1,276 @@ +__all__ = ('GestureHistoryManager', 'GestureVisualizer') + +from kivy.app import App +from kivy.clock import Clock +from kivy.lang import Builder +from kivy.uix.widget import Widget +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.gridlayout import GridLayout +from kivy.uix.label import Label +from kivy.graphics import Color, Line +from kivy.properties import ObjectProperty, BooleanProperty +from kivy.compat import PY2 + +# local libraries +from helpers import InformationPopup +from settings import MultistrokeSettingsContainer + + +# refuse heap permute for gestures with more strokes than 3 +# (you can increase it, but 4 strokes = 384 templates, 5 = 3840) +MAX_PERMUTE_STROKES = 3 + +Builder.load_file('historymanager.kv') + + +class GestureHistoryManager(GridLayout): + selected = ObjectProperty(None, allownone=True) + + def __init__(self, **kwargs): + super(GestureHistoryManager, self).__init__(**kwargs) + self.gesturesettingsform = GestureSettingsForm() + rr = self.gesturesettingsform.rrdetails + rr.bind(on_reanalyze_selected=self.reanalyze_selected) + self.infopopup = InformationPopup() + self.recognizer = App.get_running_app().recognizer + + def reanalyze_selected(self, *l): + # recognize() can block the UI with max_gpf=100, show a message + self.infopopup.text = 'Please wait, analyzing ..' + self.infopopup.auto_dismiss = False + self.infopopup.open() + + # Get a reference to the original GestureContainer object + gesture_obj = self.selected._result_obj._gesture_obj + + # Reanalyze the candidate strokes using current database + res = self.recognizer.recognize(gesture_obj.get_vectors(), + max_gpf=100) + + # Tag the result with the gesture object (it didn't change) + res._gesture_obj = gesture_obj + + # Tag the selected item with the updated ProgressTracker + self.selected._result_obj = res + res.bind(on_complete=self._reanalyze_complete) + + def _reanalyze_complete(self, *l): + self.gesturesettingsform.load_visualizer(self.selected) + self.infopopup.dismiss() + + def add_selected_to_database(self, *l): + if self.selected is None: + raise Exception('add_gesture_to_database before load_visualizer?') + + if self.gesturesettingsform.addsettings is None: + raise Exception('add_gesture_to_database missing addsetings?') + + ids = self.gesturesettingsform.addsettings.ids + + name = ids.name.value.strip() + if name == '': + self.infopopup.auto_dismiss = True + self.infopopup.text = 'You must specify a name for the gesture' + self.infopopup.open() + return + + permute = ids.permute.value + sensitive = ids.orientation_sens.value + strokelen = ids.stroke_sens.value + angle_sim = ids.angle_sim.value + + cand = self.selected._result_obj._gesture_obj.get_vectors() + + if permute and len(cand) > MAX_PERMUTE_STROKES: + t = "Can't heap permute %d-stroke gesture " % (len(cand)) + self.infopopup.text = t + self.infopopup.auto_dismiss = True + self.infopopup.open() + return + + self.recognizer.add_gesture( + name, + cand, + use_strokelen=strokelen, + orientation_sensitive=sensitive, + angle_similarity=angle_sim, + permute=permute) + + self.infopopup.text = 'Gesture added to database' + self.infopopup.auto_dismiss = True + self.infopopup.open() + + def clear_history(self, *l): + if self.selected: + self.visualizer_deselect() + self.ids.history.clear_widgets() + + def visualizer_select(self, visualizer, *l): + if self.selected is not None: + self.selected.selected = False + else: + self.add_widget(self.gesturesettingsform) + + self.gesturesettingsform.load_visualizer(visualizer) + self.selected = visualizer + + def visualizer_deselect(self, *l): + self.selected = None + self.remove_widget(self.gesturesettingsform) + + def add_recognizer_result(self, result, *l): + '''The result object is a ProgressTracker with additional + data; in main.py it is tagged with the original GestureContainer + that was analyzed (._gesture_obj)''' + + # Create a GestureVisualizer that draws the gesture on canvas + visualizer = GestureVisualizer(result._gesture_obj, + size_hint=(None, None), size=(150, 150)) + + # Tag it with the result object so AddGestureForm.load_visualizer + # has the results to build labels in the scrollview + visualizer._result_obj = result + + visualizer.bind(on_select=self.visualizer_select) + visualizer.bind(on_deselect=self.visualizer_deselect) + + # Add the visualizer to the list of gestures in 'history' screen + self.ids.history.add_widget(visualizer) + self._trigger_layout() + self.ids.scrollview.update_from_scroll() + + +class RecognizerResultLabel(Label): + '''This Label subclass is used to show a single result from the + gesture matching process (is a child of GestureHistoryManager)''' + pass + + +class RecognizerResultDetails(BoxLayout): + '''Contains a ScrollView of RecognizerResultLabels, ie the list of + matched gestures and their score/distance (is a child of + GestureHistoryManager)''' + def __init__(self, **kwargs): + super(RecognizerResultDetails, self).__init__(**kwargs) + self.register_event_type('on_reanalyze_selected') + + def on_reanalyze_selected(self, *l): + pass + + +class AddGestureSettings(MultistrokeSettingsContainer): + pass + + +class GestureSettingsForm(BoxLayout): + '''This is the main content of the GestureHistoryManager, the form for + adding a new gesture to the recognizer. It is added to the widget tree + when a GestureVisualizer is selected.''' + + def __init__(self, **kwargs): + super(GestureSettingsForm, self).__init__(**kwargs) + self.infopopup = InformationPopup() + self.rrdetails = RecognizerResultDetails() + self.addsettings = None + self.app = App.get_running_app() + + def load_visualizer(self, visualizer): + if self.addsettings is None: + self.addsettings = AddGestureSettings() + self.ids.settings.add_widget(self.addsettings) + + self.visualizer = visualizer + analysis = self.ids.analysis + analysis.clear_widgets() + analysis.add_widget(self.rrdetails) + + scrollv = self.rrdetails.ids.result_scrollview + resultlist = self.rrdetails.ids.result_list + resultlist.clear_widgets() + + r = visualizer._result_obj.results + + if not len(r): + lbl = RecognizerResultLabel(text='[b]No match[/b]') + resultlist.add_widget(lbl) + scrollv.scroll_y = 1 + return + + if PY2: + d = r.iteritems + else: + d = r.items + + for one in sorted(d(), key=lambda x: x[1]['score'], + reverse=True): + data = one[1] + lbl = RecognizerResultLabel( + text='Name: [b]' + data['name'] + '[/b]' + + '\n Score: ' + str(data['score']) + + '\n Distance: ' + str(data['dist'])) + resultlist.add_widget(lbl) + + # Make sure the top is visible + scrollv.scroll_y = 1 + + +class GestureVisualizer(Widget): + selected = BooleanProperty(False) + + def __init__(self, gesturecontainer, **kwargs): + super(GestureVisualizer, self).__init__(**kwargs) + + self._gesture_container = gesturecontainer + + self._trigger_draw = Clock.create_trigger(self._draw_item, 0) + self.bind(pos=self._trigger_draw, size=self._trigger_draw) + self._trigger_draw() + + self.register_event_type('on_select') + self.register_event_type('on_deselect') + + def on_touch_down(self, touch): + if not self.collide_point(touch.x, touch.y): + return + self.selected = not self.selected + self.dispatch(self.selected and 'on_select' or 'on_deselect') + + # FIXME: This seems inefficient, is there a better way?? + def _draw_item(self, dt): + g = self._gesture_container + bb = g.bbox + minx, miny, maxx, maxy = bb['minx'], bb['miny'], bb['maxx'], bb['maxy'] + width, height = self.size + xpos, ypos = self.pos + + if g.height > g.width: + to_self = (height * 0.85) / g.height + else: + to_self = (width * 0.85) / g.width + + self.canvas.remove_group('gesture') + + cand = g.get_vectors() + col = g.color + for stroke in cand: + out = [] + append = out.append + for vec in stroke: + x, y = vec + x = (x - minx) * to_self + w = (maxx - minx) * to_self + append(x + xpos + (width - w) * .85 / 2) + + y = (y - miny) * to_self + h = (maxy - miny) * to_self + append(y + ypos + (height - h) * .85 / 2) + + with self.canvas: + Color(col[0], col[1], col[2], mode='rgb') + Line(points=out, group='gesture', width=2) + + def on_select(self, *l): + pass + + def on_deselect(self, *l): + pass diff --git a/freechat-client/share/kivy-examples/demo/multistroke/main.py b/freechat-client/share/kivy-examples/demo/multistroke/main.py new file mode 100644 index 0000000..4178832 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/multistroke/main.py @@ -0,0 +1,144 @@ +''' +Multistroke Recognition Database Demonstration +============================================== + +This application records gestures and attempts to match them. You should +see a black drawing surface with some buttons across the bottom. As you +make a gesture on the drawing surface, the gesture will be added to +the history and a match will be attempted. If you go to the history tab, +name the gesture, and add it to the database, then similar gestures in the +future will be recognized. You can load and save databases of gestures +in .kg files. + +This demonstration code spans many files, with this being the primary file. +The information pop-up ('No match') comes from the file helpers.py. +The history pane is managed in the file historymanager.py and described +in the file historymanager.kv. The database pane and storage is managed in +the file gesturedatabase.py and the described in the file gesturedatabase.kv. +The general logic of the sliders and buttons are in the file +settings.py and described in settings.kv. but the actual settings pane is +described in the file multistroke.kv and managed from this file. + +''' +from kivy.app import App +from kivy.uix.gridlayout import GridLayout +from kivy.uix.gesturesurface import GestureSurface +from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition +from kivy.uix.label import Label +from kivy.multistroke import Recognizer + +# Local libraries +from historymanager import GestureHistoryManager +from gesturedatabase import GestureDatabase +from settings import MultistrokeSettingsContainer + + +class MainMenu(GridLayout): + pass + + +class MultistrokeAppSettings(MultistrokeSettingsContainer): + pass + + +class MultistrokeApp(App): + + def goto_database_screen(self, *l): + self.database.import_gdb() + self.manager.current = 'database' + + def handle_gesture_cleanup(self, surface, g, *l): + if hasattr(g, '_result_label'): + surface.remove_widget(g._result_label) + + def handle_gesture_discard(self, surface, g, *l): + # Don't bother creating Label if it's not going to be drawn + if surface.draw_timeout == 0: + return + + text = '[b]Discarded:[/b] Not enough input' + g._result_label = Label(text=text, markup=True, size_hint=(None, None), + center=(g.bbox['minx'], g.bbox['miny'])) + self.surface.add_widget(g._result_label) + + def handle_gesture_complete(self, surface, g, *l): + result = self.recognizer.recognize(g.get_vectors()) + result._gesture_obj = g + result.bind(on_complete=self.handle_recognize_complete) + + def handle_recognize_complete(self, result, *l): + self.history.add_recognizer_result(result) + + # Don't bother creating Label if it's not going to be drawn + if self.surface.draw_timeout == 0: + return + + best = result.best + if best['name'] is None: + text = '[b]No match[/b]' + else: + text = 'Name: [b]%s[/b]\nScore: [b]%f[/b]\nDistance: [b]%f[/b]' % ( + best['name'], best['score'], best['dist']) + + g = result._gesture_obj + g._result_label = Label(text=text, markup=True, size_hint=(None, None), + center=(g.bbox['minx'], g.bbox['miny'])) + self.surface.add_widget(g._result_label) + + def build(self): + # Setting NoTransition breaks the "history" screen! Possibly related + # to some inexplicable rendering bugs on my particular system + self.manager = ScreenManager(transition=SlideTransition( + duration=.15)) + self.recognizer = Recognizer() + + # Setup the GestureSurface and bindings to our Recognizer + surface = GestureSurface(line_width=2, draw_bbox=True, + use_random_color=True) + surface_screen = Screen(name='surface') + surface_screen.add_widget(surface) + self.manager.add_widget(surface_screen) + + surface.bind(on_gesture_discard=self.handle_gesture_discard) + surface.bind(on_gesture_complete=self.handle_gesture_complete) + surface.bind(on_gesture_cleanup=self.handle_gesture_cleanup) + self.surface = surface + + # History is the list of gestures drawn on the surface + history = GestureHistoryManager() + history_screen = Screen(name='history') + history_screen.add_widget(history) + self.history = history + self.manager.add_widget(history_screen) + + # Database is the list of gesture templates in Recognizer + database = GestureDatabase(recognizer=self.recognizer) + database_screen = Screen(name='database') + database_screen.add_widget(database) + self.database = database + self.manager.add_widget(database_screen) + + # Settings screen + app_settings = MultistrokeAppSettings() + ids = app_settings.ids + + ids.max_strokes.bind(value=surface.setter('max_strokes')) + ids.temporal_win.bind(value=surface.setter('temporal_window')) + ids.timeout.bind(value=surface.setter('draw_timeout')) + ids.line_width.bind(value=surface.setter('line_width')) + ids.draw_bbox.bind(value=surface.setter('draw_bbox')) + ids.use_random_color.bind(value=surface.setter('use_random_color')) + + settings_screen = Screen(name='settings') + settings_screen.add_widget(app_settings) + self.manager.add_widget(settings_screen) + + # Wrap in a gridlayout so the main menu is always visible + layout = GridLayout(cols=1) + layout.add_widget(self.manager) + layout.add_widget(MainMenu()) + return layout + + +if __name__ in ('__main__', '__android__'): + MultistrokeApp().run() diff --git a/freechat-client/share/kivy-examples/demo/multistroke/multistroke.kv b/freechat-client/share/kivy-examples/demo/multistroke/multistroke.kv new file mode 100644 index 0000000..e84c954 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/multistroke/multistroke.kv @@ -0,0 +1,101 @@ +: + rows: 1 + size_hint: (1, None) + height: 50 + spacing: 5 + padding: 5 + ToggleButton: + group: 'mainmenu' + state: 'down' + text: 'Gesture Surface' + on_press: + app.manager.current = 'surface' + if self.state == 'normal': self.state = 'down' + ToggleButton: + group: 'mainmenu' + text: 'History' + on_press: + app.manager.current = 'history' + if self.state == 'normal': self.state = 'down' + ToggleButton: + group: 'mainmenu' + text: 'Database' + on_press: + app.goto_database_screen() + if self.state == 'normal': self.state = 'down' + ToggleButton: + group: 'mainmenu' + text: 'Settings' + on_press: + app.manager.current = 'settings' + if self.state == 'normal': self.state = 'down' + +: + pos_hint: {'top': 1} + + MultistrokeSettingTitle: + title: 'GestureSurface behavior' + desc: 'Affects how gestures are detected and cleaned up' + + MultistrokeSettingSlider: + id: max_strokes + title: 'Max strokes' + type: 'int' + desc: + ('Max number of strokes for a single gesture. If 0, the ' + + 'gesture will only be analyzed once the temporal window has ' + + 'expired since the last strokes touch up event') + value: 4 + min: 0 + max: 15 + + MultistrokeSettingSlider: + id: temporal_win + title: 'Temporal Window' + type: 'float' + desc: + ('Time to wait from last touch up in a gesture before analyzing ' + + 'the input. If 0, only analyzed once Max Strokes is reached') + value: 2. + min: 0 + max: 60. + + MultistrokeSettingTitle: + title: 'Drawing' + desc: 'Affects how gestures are visualized on the GestureSurface' + + MultistrokeSettingSlider: + id: timeout + title: 'Draw Timeout' + type: 'float' + desc: + ('How long to display the gesture (and result label) on the ' + + 'gesture surface once analysis has completed') + value: 2. + min: 0 + max: 60. + + MultistrokeSettingSlider: + id: line_width + title: 'Line width' + type: 'int' + desc: + ('Width of lines on the gesture surface; 0 does not draw ' + + 'anything; 1 uses OpenGL line, >1 uses custom drawing method.') + value: 2 + min: 0 + max: 10 + + MultistrokeSettingBoolean: + id: use_random_color + title: 'Use random color?' + desc: 'Use random color for each gesture? If disabled, white is used.' + button_text: 'Random color?' + value: True + + MultistrokeSettingBoolean: + id: draw_bbox + title: 'Draw gesture bounding box?' + desc: 'Enable to draw a bounding box around the gesture' + button_text: 'Draw bbox?' + value: True diff --git a/freechat-client/share/kivy-examples/demo/multistroke/settings.kv b/freechat-client/share/kivy-examples/demo/multistroke/settings.kv new file mode 100644 index 0000000..20462af --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/multistroke/settings.kv @@ -0,0 +1,110 @@ +: + cols: 1 + spacing: 5 + padding: 5 + size_hint_y: None + height: self.minimum_height + +: + size_hint_y: None + height: 70 + rows: 1 + canvas: + Color: + rgba: 47 / 255., 167 / 255., 212 / 255., .1 + Rectangle: + pos: self.x, self.y + 1 + size: self.size + Color: + rgb: .2, .2, .2 + Rectangle: + pos: self.x, self.y - 2 + size: self.width, 1 + Label: + size_hint_x: .6 + id: labellayout + markup: True + text: u'{0}\n[size=13sp][color=999999]{1}[/color][/size]'.format(root.title or '', root.desc or '') + font_size: '15sp' + text_size: self.size + valign: 'top' + +: + size_hint_y: None + height: 40 + markup: True + text: u'{0}\n[size=13sp][color=999999]{1}[/color][/size]'.format(root.title or '', root.desc or '') + font_size: '15sp' + text_size: self.size + valign: 'top' + halign: 'right' + canvas: + Color: + rgba: 47 / 255., 167 / 255., 212 / 255., .4 + Rectangle: + pos: self.x, self.y + 1 + size: self.size + Color: + rgb: .5, .5, .5 + Rectangle: + pos: self.x, self.y - 2 + size: self.width, 1 + +: + value: button.state == 'down' and True or False + ToggleButton: + id: button + text: root.button_text + size_hint_x: None + width: 150 + pos: root.pos + state: root.value and 'down' or 'normal' + +: + value: input.text + AnchorLayout: + size_hint_x: None + width: 150 + TextInput: + id: input + size_hint_y: None + height: 30 + pos: root.pos + multiline: True + text: root.value + +: + value: slider.value + Label: + id: sliderlabel + size_hint_x: None + width: 50 + text: str(root._to_numtype(slider.value)) + Slider: + id: slider + min: root.min + max: root.max + pos: root.pos + size_hint_x: None + width: 150 + value: root.value + +: + size_hint: None, None + size: 300, 150 + title: 'Edit setting' + BoxLayout: + orientation: 'vertical' + TextInput: + id: input + markup: False + multiline: False + on_text_validate: root.dispatch('on_validate', self.text) + BoxLayout: + orientation: 'horizontal' + Button: + text: 'OK' + on_press: root.dispatch('on_validate', input.text) + Button: + text: 'Cancel' + on_press: root.dismiss() diff --git a/freechat-client/share/kivy-examples/demo/multistroke/settings.py b/freechat-client/share/kivy-examples/demo/multistroke/settings.py new file mode 100644 index 0000000..6adb15d --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/multistroke/settings.py @@ -0,0 +1,97 @@ +__all__ = ('MultistrokeSettingsContainer', 'MultistrokeSettingItem', + 'MultistrokeSettingBoolean', 'MultistrokeSettingSlider', + 'MultistrokeSettingString', 'MultistrokeSettingTitle') + +from kivy.factory import Factory +from kivy.lang import Builder +from kivy.uix.gridlayout import GridLayout +from kivy.uix.label import Label +from kivy.properties import (StringProperty, NumericProperty, OptionProperty, + BooleanProperty) +from kivy.uix.popup import Popup + +Builder.load_file('settings.kv') + + +class MultistrokeSettingsContainer(GridLayout): + pass + + +class MultistrokeSettingItem(GridLayout): + title = StringProperty('') + desc = StringProperty('') + + +class MultistrokeSettingTitle(Label): + title = StringProperty('') + desc = StringProperty('') + + +class MultistrokeSettingBoolean(MultistrokeSettingItem): + button_text = StringProperty('') + value = BooleanProperty(False) + + +class MultistrokeSettingString(MultistrokeSettingItem): + value = StringProperty('') + + +class EditSettingPopup(Popup): + def __init__(self, **kwargs): + super(EditSettingPopup, self).__init__(**kwargs) + self.register_event_type('on_validate') + + def on_validate(self, *l): + pass + + +class MultistrokeSettingSlider(MultistrokeSettingItem): + min = NumericProperty(0) + max = NumericProperty(100) + type = OptionProperty('int', options=['float', 'int']) + value = NumericProperty(0) + + def __init__(self, **kwargs): + super(MultistrokeSettingSlider, self).__init__(**kwargs) + self._popup = EditSettingPopup() + self._popup.bind(on_validate=self._validate) + self._popup.bind(on_dismiss=self._dismiss) + + def _to_numtype(self, v): + try: + if self.type == 'float': + return round(float(v), 1) + else: + return int(v) + except ValueError: + return self.min + + def _dismiss(self, *l): + self._popup.ids.input.focus = False + + def _validate(self, instance, value): + self._popup.dismiss() + val = self._to_numtype(self._popup.ids.input.text) + if val < self.min: + val = self.min + elif val > self.max: + val = self.max + self.value = val + + def on_touch_down(self, touch): + if not self.ids.sliderlabel.collide_point(*touch.pos): + return super(MultistrokeSettingSlider, self).on_touch_down(touch) + ids = self._popup.ids + ids.value = str(self.value) + ids.input.text = str(self._to_numtype(self.value)) + self._popup.open() + ids.input.focus = True + ids.input.select_all() + + +Factory.register('MultistrokeSettingsContainer', + cls=MultistrokeSettingsContainer) +Factory.register('MultistrokeSettingTitle', cls=MultistrokeSettingTitle) +Factory.register('MultistrokeSettingBoolean', cls=MultistrokeSettingBoolean) +Factory.register('MultistrokeSettingSlider', cls=MultistrokeSettingSlider) +Factory.register('MultistrokeSettingString', cls=MultistrokeSettingString) diff --git a/freechat-client/share/kivy-examples/demo/pictures/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/demo/pictures/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..656b036 Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/pictures/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/demo/pictures/android.txt b/freechat-client/share/kivy-examples/demo/pictures/android.txt new file mode 100644 index 0000000..f00865d --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/pictures/android.txt @@ -0,0 +1,3 @@ +title=Pictures +author=Kivy team +orientation=landscape diff --git a/freechat-client/share/kivy-examples/demo/pictures/images/Bubbles.jpg b/freechat-client/share/kivy-examples/demo/pictures/images/Bubbles.jpg new file mode 100644 index 0000000..3e0db84 Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/pictures/images/Bubbles.jpg differ diff --git a/freechat-client/share/kivy-examples/demo/pictures/images/Ill1.jpg b/freechat-client/share/kivy-examples/demo/pictures/images/Ill1.jpg new file mode 100644 index 0000000..0555b14 Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/pictures/images/Ill1.jpg differ diff --git a/freechat-client/share/kivy-examples/demo/pictures/images/Wall.jpg b/freechat-client/share/kivy-examples/demo/pictures/images/Wall.jpg new file mode 100644 index 0000000..b114e7a Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/pictures/images/Wall.jpg differ diff --git a/freechat-client/share/kivy-examples/demo/pictures/images/faust_github.jpg b/freechat-client/share/kivy-examples/demo/pictures/images/faust_github.jpg new file mode 100644 index 0000000..a7fbbd2 Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/pictures/images/faust_github.jpg differ diff --git a/freechat-client/share/kivy-examples/demo/pictures/main.py b/freechat-client/share/kivy-examples/demo/pictures/main.py new file mode 100755 index 0000000..da545e0 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/pictures/main.py @@ -0,0 +1,73 @@ +''' +Basic Picture Viewer +==================== + +This simple image browser demonstrates the scatter widget. You should +see three framed photographs on a background. You can click and drag +the photos around, or multi-touch to drop a red dot to scale and rotate the +photos. + +The photos are loaded from the local images directory, while the background +picture is from the data shipped with kivy in kivy/data/images/background.jpg. +The file pictures.kv describes the interface and the file shadow32.png is +the border to make the images look like framed photographs. Finally, +the file android.txt is used to package the application for use with the +Kivy Launcher Android application. + +For Android devices, you can copy/paste this directory into +/sdcard/kivy/pictures on your Android device. + +The images in the image directory are from the Internet Archive, +`https://archive.org/details/PublicDomainImages`, and are in the public +domain. + +''' + +import kivy +kivy.require('1.0.6') + +from glob import glob +from random import randint +from os.path import join, dirname +from kivy.app import App +from kivy.logger import Logger +from kivy.uix.scatter import Scatter +from kivy.properties import StringProperty + + +class Picture(Scatter): + '''Picture is the class that will show the image with a white border and a + shadow. They are nothing here because almost everything is inside the + picture.kv. Check the rule named inside the file, and you'll see + how the Picture() is really constructed and used. + + The source property will be the filename to show. + ''' + + source = StringProperty(None) + + +class PicturesApp(App): + + def build(self): + + # the root is created in pictures.kv + root = self.root + + # get any files into images directory + curdir = dirname(__file__) + for filename in glob(join(curdir, 'images', '*')): + try: + # load the image + picture = Picture(source=filename, rotation=randint(-30, 30)) + # add to the main field + root.add_widget(picture) + except Exception as e: + Logger.exception('Pictures: Unable to load <%s>' % filename) + + def on_pause(self): + return True + + +if __name__ == '__main__': + PicturesApp().run() diff --git a/freechat-client/share/kivy-examples/demo/pictures/pictures.kv b/freechat-client/share/kivy-examples/demo/pictures/pictures.kv new file mode 100644 index 0000000..2255b15 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/pictures/pictures.kv @@ -0,0 +1,57 @@ +#:kivy 1.0 +#:import kivy kivy +#:import win kivy.core.window + +FloatLayout: + canvas: + Color: + rgb: 1, 1, 1 + Rectangle: + source: 'data/images/background.jpg' + size: self.size + + BoxLayout: + padding: 10 + spacing: 10 + size_hint: 1, None + pos_hint: {'top': 1} + height: 44 + Image: + size_hint: None, None + size: 24, 24 + source: 'data/logo/kivy-icon-24.png' + Label: + height: 24 + text_size: self.width, None + color: (1, 1, 1, .8) + text: 'Kivy %s - Pictures' % kivy.__version__ + + + +: + # each time a picture is created, the image can delay the loading + # as soon as the image is loaded, ensure that the center is changed + # to the center of the screen. + on_size: self.center = win.Window.center + size: image.size + size_hint: None, None + + Image: + id: image + source: root.source + + # create initial image to be 400 pixels width + size: 400, 400 / self.image_ratio + + # add shadow background + canvas.before: + Color: + rgba: 1,1,1,1 + BorderImage: + source: 'shadow32.png' + border: (36,36,36,36) + size:(self.width+72, self.height+72) + pos: (-36,-36) + + + diff --git a/freechat-client/share/kivy-examples/demo/pictures/shadow32.png b/freechat-client/share/kivy-examples/demo/pictures/shadow32.png new file mode 100644 index 0000000..f5e9f45 Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/pictures/shadow32.png differ diff --git a/freechat-client/share/kivy-examples/demo/shadereditor/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/demo/shadereditor/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..8595574 Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/shadereditor/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/demo/shadereditor/main.py b/freechat-client/share/kivy-examples/demo/shadereditor/main.py new file mode 100755 index 0000000..7cdf2f0 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/shadereditor/main.py @@ -0,0 +1,147 @@ +''' +Live Shader Editor +================== + +This provides a live editor for vertex and fragment editors. +You should see a window with two editable panes on the left +and a large kivy logo on the right.The top pane is the +Vertex shader and the bottom is the Fragment shader. The file shadereditor.kv +describes the interface. + +On each keystroke to either shader, declarations are added and the shaders +are compiled. If there are no errors, the screen is updated. Otherwise, +the error is visible as logging message in your terminal. +''' + + +import sys +import kivy +kivy.require('1.0.6') + +from kivy.app import App +from kivy.uix.floatlayout import FloatLayout +from kivy.core.window import Window +from kivy.factory import Factory +from kivy.graphics import RenderContext +from kivy.properties import StringProperty, ObjectProperty +from kivy.clock import Clock +from kivy.compat import PY2 + +fs_header = ''' +#ifdef GL_ES + precision highp float; +#endif + +/* Outputs from the vertex shader */ +varying vec4 frag_color; +varying vec2 tex_coord0; + +/* uniform texture samplers */ +uniform sampler2D texture0; + +/* custom one */ +uniform vec2 resolution; +uniform float time; +''' + +vs_header = ''' +#ifdef GL_ES + precision highp float; +#endif + +/* Outputs to the fragment shader */ +varying vec4 frag_color; +varying vec2 tex_coord0; + +/* vertex attributes */ +attribute vec2 vPosition; +attribute vec2 vTexCoords0; + +/* uniform variables */ +uniform mat4 modelview_mat; +uniform mat4 projection_mat; +uniform vec4 color; +''' + + +class ShaderViewer(FloatLayout): + fs = StringProperty(None) + vs = StringProperty(None) + + def __init__(self, **kwargs): + self.canvas = RenderContext() + super(ShaderViewer, self).__init__(**kwargs) + Clock.schedule_interval(self.update_shader, 0) + + def update_shader(self, *args): + s = self.canvas + s['projection_mat'] = Window.render_context['projection_mat'] + s['time'] = Clock.get_boottime() + s['resolution'] = list(map(float, self.size)) + s.ask_update() + + def on_fs(self, instance, value): + self.canvas.shader.fs = value + + def on_vs(self, instance, value): + self.canvas.shader.vs = value + + +Factory.register('ShaderViewer', cls=ShaderViewer) + + +class ShaderEditor(FloatLayout): + + source = StringProperty('data/logo/kivy-icon-512.png') + + fs = StringProperty(''' +void main (void){ + gl_FragColor = frag_color * texture2D(texture0, tex_coord0); +} +''') + vs = StringProperty(''' +void main (void) { + frag_color = color; + tex_coord0 = vTexCoords0; + gl_Position = projection_mat * modelview_mat * vec4(vPosition.xy, 0.0, 1.0); +} +''') + + viewer = ObjectProperty(None) + + def __init__(self, **kwargs): + super(ShaderEditor, self).__init__(**kwargs) + self.test_canvas = RenderContext() + s = self.test_canvas.shader + self.trigger_compile = Clock.create_trigger(self.compile_shaders, -1) + self.bind(fs=self.trigger_compile, vs=self.trigger_compile) + + def compile_shaders(self, *largs): + print('try compile') + if not self.viewer: + return + + # we don't use str() here because it will crash with non-ascii char + if PY2: + fs = fs_header + self.fs.encode('utf-8') + vs = vs_header + self.vs.encode('utf-8') + else: + fs = fs_header + self.fs + vs = vs_header + self.vs + + print('-->', fs) + self.viewer.fs = fs + print('-->', vs) + self.viewer.vs = vs + + +class ShaderEditorApp(App): + def build(self): + kwargs = {} + if len(sys.argv) > 1: + kwargs['source'] = sys.argv[1] + return ShaderEditor(**kwargs) + + +if __name__ == '__main__': + ShaderEditorApp().run() diff --git a/freechat-client/share/kivy-examples/demo/shadereditor/shadereditor.kv b/freechat-client/share/kivy-examples/demo/shadereditor/shadereditor.kv new file mode 100644 index 0000000..f11ef44 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/shadereditor/shadereditor.kv @@ -0,0 +1,39 @@ +#:kivy 1.0 +#: import GLShaderLexer pygments.lexers.GLShaderLexer + +: + viewer: viewer + + BoxLayout: + BoxLayout: + orientation: 'vertical' + size_hint_x: None + width: 350 + + Label: + text: 'Fragment Shader' + size_hint_y: None + height: self.texture_size[1] + 10 + CodeInput: + text: root.fs + lexer: GLShaderLexer() + on_text: root.fs = args[1] + + Label: + text: 'Vertex Shader' + size_hint_y: None + height: self.texture_size[1] + 10 + CodeInput: + text: root.vs + lexer: GLShaderLexer() + on_text: root.vs = args[1] + + ShaderViewer: + id: viewer + canvas: + Color: + rgb: 1, 1, 1 + Rectangle: + size: self.size + pos: self.pos + source: root.source diff --git a/freechat-client/share/kivy-examples/demo/showcase/README.txt b/freechat-client/share/kivy-examples/demo/showcase/README.txt new file mode 100644 index 0000000..4f195b6 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/README.txt @@ -0,0 +1,11 @@ +Showcase +======== + +Demonstrate all the possibilities of Kivy toolkit. + +Android +------- + +You can copy/paste this directory into /sdcard/kivy/showcase in your +android device. + diff --git a/freechat-client/share/kivy-examples/demo/showcase/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/demo/showcase/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..4db4b67 Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/showcase/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/demo/showcase/android.txt b/freechat-client/share/kivy-examples/demo/showcase/android.txt new file mode 100644 index 0000000..9b90b9a --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/android.txt @@ -0,0 +1,3 @@ +title=Showcase +author=Kivy team +orientation=landscape diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/background.png b/freechat-client/share/kivy-examples/demo/showcase/data/background.png new file mode 100644 index 0000000..77f42cc Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/showcase/data/background.png differ diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/faust_github.jpg b/freechat-client/share/kivy-examples/demo/showcase/data/faust_github.jpg new file mode 100644 index 0000000..a7fbbd2 Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/showcase/data/faust_github.jpg differ diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/icons/README b/freechat-client/share/kivy-examples/demo/showcase/data/icons/README new file mode 100644 index 0000000..cd3d10e --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/icons/README @@ -0,0 +1,4 @@ +Icons adapted from the Open Iconic set of icons, which are licensed under MIT. + +https://useiconic.com/ +https://github.com/iconic/open-iconic diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/icons/bug.png b/freechat-client/share/kivy-examples/demo/showcase/data/icons/bug.png new file mode 100644 index 0000000..cdf4e98 Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/showcase/data/icons/bug.png differ diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/icons/chevron-left.png b/freechat-client/share/kivy-examples/demo/showcase/data/icons/chevron-left.png new file mode 100644 index 0000000..2647b7f Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/showcase/data/icons/chevron-left.png differ diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/icons/chevron-right.png b/freechat-client/share/kivy-examples/demo/showcase/data/icons/chevron-right.png new file mode 100644 index 0000000..a9becdf Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/showcase/data/icons/chevron-right.png differ diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/accordions.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/accordions.kv new file mode 100644 index 0000000..36ecb98 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/accordions.kv @@ -0,0 +1,39 @@ +ShowcaseScreen: + name: 'Accordions' + + fullscreen: True + + BoxLayout: + size_hint_y: None + height: '48dp' + + ToggleButton: + id: tbh + text: 'Horizontal' + group: 'accordion' + state: 'down' + + ToggleButton: + text: 'Vertical' + group: 'accordion' + + Accordion: + + orientation: 'horizontal' if tbh.state == 'down' else 'vertical' + + AccordionItem: + title: 'Panel 1' + Label: + text: 'This is a label fit to the content view' + text_size: self.width, None + + AccordionItem: + title: 'Panel 2' + Button: + text: 'A button, what else?' + + AccordionItem: + title: 'Panel 3' + Label: + text: 'This is a label fit to the content view' + text_size: self.width, None diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/bubbles.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/bubbles.kv new file mode 100644 index 0000000..d0741f1 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/bubbles.kv @@ -0,0 +1,28 @@ +ShowcaseScreen: + name: 'Bubbles' + + Bubble: + size_hint_y: None + height: '48dp' + + BubbleButton: + text: 'Cut' + BubbleButton: + text: 'Copy' + BubbleButton: + text: 'Paste' + + Widget: + size_hint_y: None + height: '48dp' + + BoxLayout: + size_hint_y: None + height: '48dp' + Label: + text: 'Hello' + + Bubble: + arrow_pos: 'left_mid' + Label: + text: 'World' diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/buttons.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/buttons.kv new file mode 100644 index 0000000..c3c6e85 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/buttons.kv @@ -0,0 +1,26 @@ +ShowcaseScreen: + name: 'Buttons' + + Button: + size_hint_y: None + height: '48dp' + text: 'Button normal' + + Button: + size_hint_y: None + height: '48dp' + text: 'Button down' + state: 'down' + + Button: + size_hint_y: None + height: '48dp' + text: 'Button disabled' + disabled: True + + Button: + size_hint_y: None + height: '48dp' + text: 'Button down disabled' + state: 'down' + disabled: True diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/carousel.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/carousel.kv new file mode 100644 index 0000000..0fc97dd --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/carousel.kv @@ -0,0 +1,51 @@ +: + font_size: '48sp' + color: (.6, .6, .6, 1) + canvas.before: + Color: + rgb: (.9, .9, .9) + Rectangle: + pos: self.x + sp(2), self.y + sp(2) + size: self.width - sp(4), self.height - sp(4) + +ShowcaseScreen: + name: 'Carousel' + fullscreen: True + + BoxLayout: + size_hint_y: None + height: '48dp' + + ToggleButton: + text: 'Loop' + id: btnloop + + Label: + size_hint_x: None + width: self.height + text: '{}'.format(carousel.index) + + Button: + size_hint_x: None + width: self.height + text: 'Prev' + on_release: carousel.load_previous() + + Button: + size_hint_x: None + width: self.height + text: 'Next' + on_release: carousel.load_next() + + Carousel: + id: carousel + loop: btnloop.state == 'down' + + ColoredLabel: + text: 'Slide 0' + + ColoredLabel: + text: 'Slide 1' + + ColoredLabel: + text: 'Slide 2' diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/checkboxes.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/checkboxes.kv new file mode 100644 index 0000000..b33e803 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/checkboxes.kv @@ -0,0 +1,33 @@ +ShowcaseScreen: + name: 'CheckBoxes' + + GridLayout: + + cols: 3 + spacing: '8dp' + size_hint: .5, None + height: self.minimum_height + + Label: + text: 'Checkbox' + + CheckBox: + size_hint_y: None + height: '48dp' + + CheckBox: + size_hint_y: None + height: '48dp' + + Label: + text: 'CheckBox with group' + + CheckBox: + size_hint_y: None + height: '48dp' + group: 'g2' + + CheckBox: + size_hint_y: None + height: '48dp' + group: 'g2' diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/codeinput.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/codeinput.kv new file mode 100644 index 0000000..b90c618 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/codeinput.kv @@ -0,0 +1,9 @@ +ShowcaseScreen: + + fullscreen: True + name: 'CodeInput' + + CodeInput: + padding: '4dp' + text: 'class Hello(object):\n\tpass\n\nprint("Hello world")' + focus: True if root.parent else False diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/dropdown.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/dropdown.kv new file mode 100644 index 0000000..9afa310 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/dropdown.kv @@ -0,0 +1,40 @@ +ShowcaseScreen: + fullscreen: True + name: 'DropDown' + + # trick to not lost the Dropdown instance + # Dropdown itself is not really made to be used in kv. + __safe_id: [dropdown.__self__] + + Button: + id: btn + text: '-' + on_release: dropdown.open(self) + size_hint_y: None + height: '48dp' + + Widget: + on_parent: dropdown.dismiss() + + DropDown: + + id: dropdown + on_select: btn.text = 'Selected value: {}'.format(args[1]) + + Button: + text: 'Value A' + size_hint_y: None + height: '48dp' + on_release: dropdown.select('A') + + Button: + text: 'Value B' + size_hint_y: None + height: '48dp' + on_release: dropdown.select('B') + + Button: + text: 'Value C' + size_hint_y: None + height: '48dp' + on_release: dropdown.select('C') diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/filechoosers.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/filechoosers.kv new file mode 100644 index 0000000..a7fd296 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/filechoosers.kv @@ -0,0 +1,24 @@ +ShowcaseScreen: + name: 'FileChoosers' + fullscreen: True + + BoxLayout: + size_hint_y: None + height: '48dp' + + ToggleButton: + text: 'Icon' + state: 'down' + group: 'filechooser' + on_release: filechooser.view_mode = 'icon' + + ToggleButton: + text: 'List' + group: 'filechooser' + on_release: filechooser.view_mode = 'list' + + FileChooser: + id: filechooser + + FileChooserIconLayout + FileChooserListLayout diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/popups.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/popups.kv new file mode 100644 index 0000000..8adb785 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/popups.kv @@ -0,0 +1,17 @@ +ShowcaseScreen: + popup: popup.__self__ + fullscreen: True + name: 'Popups' + BoxLayout: + id: bl + Popup: + id: popup + title: "Hello World" + on_parent: + if self.parent == bl: self.parent.remove_widget(self) + Button: + text: 'press to dismiss' + on_release: popup.dismiss() + Button: + text: 'press to show Popup' + on_release: root.popup.open() diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/progressbar.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/progressbar.kv new file mode 100644 index 0000000..73a2cc6 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/progressbar.kv @@ -0,0 +1,15 @@ +ShowcaseScreen: + name: 'ProgressBar' + + Label: + text: 'Progression: {}%'.format(int(pb.value)) + size_hint_y: None + height: '48dp' + + ProgressBar: + id: pb + size_hint_x: .5 + size_hint_y: None + height: '48dp' + value: (app.time * 20) % 100. + diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/rstdocument.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/rstdocument.kv new file mode 100644 index 0000000..d007624 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/rstdocument.kv @@ -0,0 +1,24 @@ +ShowcaseScreen: + name: 'RstDocument' + fullscreen: True + on_parent: if not args[1]: textinput.focus = False + + GridLayout: + cols: 2 if root.width > root.height else 1 + spacing: '8dp' + + TextInput: + id: textinput + text: + ('.. _top:\n' + '\n' + 'Hello world\n' + '===========\n' + '\n' + 'This is an **emphased text**, *italic text*, ``interpreted text``.\n' + 'And this is a reference to top_::\n' + '\n' + ' $ print("Hello world")\n') + + RstDocument: + text: textinput.text diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/scatter.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/scatter.kv new file mode 100644 index 0000000..e406599 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/scatter.kv @@ -0,0 +1,14 @@ +ShowcaseScreen: + name: 'Scatter' + + Widget: + + Scatter: + id: scatter + size_hint: None, None + size: image.size + + Image: + id: image + source: 'data/faust_github.jpg' + size: self.texture_size diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/screenmanager.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/screenmanager.kv new file mode 100644 index 0000000..762ec2c --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/screenmanager.kv @@ -0,0 +1,46 @@ +#:import Factory kivy.factory.Factory + +ShowcaseScreen: + name: 'ScreenManager' + fullscreen: True + + BoxLayout: + size_hint_y: None + height: '48dp' + + Spinner: + text: 'Default transition' + values: ('SlideTransition', 'SwapTransition', 'FadeTransition', 'WipeTransition') + on_text: sm.transition = Factory.get(self.text)() + + ScreenManager: + id: sm + + Screen: + name: 'screen1' + canvas.before: + Color: + rgb: .8, .2, .2 + Rectangle: + size: self.size + + AnchorLayout: + Button: + size_hint: None, None + size: '150dp', '48dp' + text: 'Go to screen 2' + on_release: sm.current = 'screen2' + + Screen: + name: 'screen2' + canvas.before: + Color: + rgb: .2, .8, .2 + Rectangle: + size: self.size + AnchorLayout: + Button: + size_hint: None, None + size: '150dp', '48dp' + text: 'Go to screen 1' + on_release: sm.current = 'screen1' diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/sliders.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/sliders.kv new file mode 100644 index 0000000..c78b8e7 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/sliders.kv @@ -0,0 +1,55 @@ +ShowcaseScreen: + name: 'Sliders' + + BoxLayout: + size_hint_y: None + height: '48dp' + + Label: + text: 'Default' + + Slider: + id: s1 + + Label: + text: '{}'.format(s1.value) + + + BoxLayout: + size_hint_y: None + height: '48dp' + + Label: + text: 'Stepped' + + Slider: + id: s2 + step: 20 + + Label: + text: '{}'.format(s2.value) + + AnchorLayout: + size_hint_y: None + height: '100dp' + + GridLayout: + cols: 2 + spacing: '8dp' + size_hint_x: None + width: self.minimum_width + + Slider: + size_hint_x: None + width: '48dp' + orientation: 'vertical' + value: s1.value + on_value: s1.value = self.value + + Slider: + size_hint_x: None + width: '48dp' + orientation: 'vertical' + step: 20 + value: s2.value + on_value: s2.value = self.value diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/spinner.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/spinner.kv new file mode 100644 index 0000000..0be102d --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/spinner.kv @@ -0,0 +1,11 @@ +ShowcaseScreen: + name: 'Spinner' + fullscreen: True + + Spinner: + text: 'Home' + values: ('Home', 'Work', 'Other', 'Not defined') + size_hint_y: None + height: '48dp' + + Widget diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/splitter.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/splitter.kv new file mode 100644 index 0000000..90cb69b --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/splitter.kv @@ -0,0 +1,13 @@ +ShowcaseScreen: + name: 'Splitter' + fullscreen: True + + RelativeLayout: + id: rl + + Splitter: + sizable_from: 'right' + min_size: 10 + max_size: rl.width + Button: + text: 'Panel' diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/switches.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/switches.kv new file mode 100644 index 0000000..5182665 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/switches.kv @@ -0,0 +1,39 @@ +ShowcaseScreen: + name: 'Switches' + + BoxLayout: + size_hint_y: None + height: '48dp' + + Label: + text: 'Switch normal' + Switch: + + BoxLayout: + size_hint_y: None + height: '48dp' + + Label: + text: 'Switch active' + Switch: + active: True + + BoxLayout: + size_hint_y: None + height: '48dp' + + Label: + text: 'Switch off & disabled' + Switch: + disabled: True + active: False + + BoxLayout: + size_hint_y: None + height: '48dp' + + Label: + text: 'Switch on & disabled' + Switch: + disabled: True + active: True diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/tabbedpanel + layouts.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/tabbedpanel + layouts.kv new file mode 100755 index 0000000..4f2ae0b --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/tabbedpanel + layouts.kv @@ -0,0 +1,69 @@ +#:import random random.random + +ShowcaseScreen: + name: 'TabbedPanel + Layouts' + fullscreen: True + on_parent: if args[1] and tp.current_tab == tab_fl: app.showcase_floatlayout(fl) + + TabbedPanel: + id: tp + do_default_tab: False + + TabbedPanelItem: + id: tab_fl + text: 'FloatLayout' + on_release: app.showcase_floatlayout(fl) + FloatLayout: + CFloatLayout: + id: fl + TabbedPanelItem: + text: 'BoxLayout' + on_release: app.showcase_boxlayout(box) + FloatLayout + CBoxLayout: + id: box + TabbedPanelItem: + text: 'GridLayout' + on_release: app.showcase_gridlayout(grid) + FloatLayout + CGridLayout: + id: grid + rows: 3 + TabbedPanelItem: + on_release: app.showcase_stacklayout(stack) + text: 'StackLayout' + FloatLayout + CStackLayout: + id: stack + TabbedPanelItem: + text: 'AnchorLayout' + on_release: app.showcase_anchorlayout(anchor) + FloatLayout + CAnchorLayout: + id: anchor + BoxLayout: + orientation: 'vertical' + size_hint: .4, .5 + Button + Button + text: 'anchor_x: {}'.format(anchor.anchor_x) + Button + text: 'anchor_y: {}'.format(anchor.anchor_y) + Button + + + + + + + + + + pos_hint: {'center_x': .5, 'center_y': .5} + size_hint: .9, .9 + canvas.before: + Color: + rgba: .2, .3, .4, 1 + Rectangle: + size: self.size + pos: self.pos diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/textinputs.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/textinputs.kv new file mode 100644 index 0000000..00d25a9 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/textinputs.kv @@ -0,0 +1,48 @@ +ShowcaseScreen: + name: 'TextInputs' + focused: ti_default + on_parent: + if not args[1] and self.focused: self.focused.focus = False + if args[1]: ti_default.focus = True + + CTextInput + size_hint_y: None + height: '32dp' + multiline: False + text: 'Monoline textinput' + + CTextInput: + id: ti_default + size_hint_y: None + height: '32dp' + text: 'Focused textinput' + focus: True + + CTextInput: + size_hint_y: None + height: '32dp' + text: 'Password' + password: True + + CTextInput: + size_hint_y: None + height: '32dp' + text: 'Readonly textinput' + readonly: True + + CTextInput: + size_hint_y: None + height: '48dp' + text: 'Multiline textinput\nSecond line' + multiline: True + + CTextInput: + size_hint_y: None + height: '32dp' + disabled: True + text: 'Disabled textinput' + + + on_focus: + screen = self.parent.parent.parent.parent + if screen.parent: screen.focused = self diff --git a/freechat-client/share/kivy-examples/demo/showcase/data/screens/togglebutton.kv b/freechat-client/share/kivy-examples/demo/showcase/data/screens/togglebutton.kv new file mode 100644 index 0000000..4874f9b --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/data/screens/togglebutton.kv @@ -0,0 +1,39 @@ +ShowcaseScreen: + name: 'ToggleButton' + + GridLayout: + + cols: 3 + spacing: '8dp' + size_hint_y: None + height: self.minimum_height + + Label: + text: 'Choice 1' + + ToggleButton: + size_hint_y: None + height: '48dp' + text: 'A' + group: 'g1' + + ToggleButton: + size_hint_y: None + height: '48dp' + text: 'B' + group: 'g1' + + Label: + text: 'Choice 2' + + ToggleButton: + size_hint_y: None + height: '48dp' + text: 'A' + group: 'g2' + + ToggleButton: + size_hint_y: None + height: '48dp' + text: 'B' + group: 'g2' diff --git a/freechat-client/share/kivy-examples/demo/showcase/main.py b/freechat-client/share/kivy-examples/demo/showcase/main.py new file mode 100755 index 0000000..cda40f5 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/main.py @@ -0,0 +1,239 @@ +''' +Showcase of Kivy Features +========================= + +This showcases many features of Kivy. You should see a +menu bar across the top with a demonstration area below. The +first demonstration is the accordion layout. You can see, but not +edit, the kv language code for any screen by pressing the bug or +'show source' icon. Scroll through the demonstrations using the +left and right icons in the top right or selecting from the menu +bar. + +The file showcase.kv describes the main container, while each demonstration +pane is described in a separate .kv file in the data/screens directory. +The image data/background.png provides the gradient background while the +icons in data/icon directory are used in the control bar. The file +data/faust_github.jpg is used in the Scatter pane. The icons are +from `http://www.gentleface.com/free_icon_set.html` and licensed as +Creative Commons - Attribution and Non-commercial Use Only; they +sell a commercial license. + +The file android.txt is used to package the application for use with the +Kivy Launcher Android application. For Android devices, you can +copy/paste this directory into /sdcard/kivy/showcase on your Android device. + +''' + +from time import time +from kivy.app import App +from os.path import dirname, join +from kivy.lang import Builder +from kivy.properties import NumericProperty, StringProperty, BooleanProperty,\ + ListProperty +from kivy.clock import Clock +from kivy.animation import Animation +from kivy.uix.screenmanager import Screen + + +class ShowcaseScreen(Screen): + fullscreen = BooleanProperty(False) + + def add_widget(self, *args): + if 'content' in self.ids: + return self.ids.content.add_widget(*args) + return super(ShowcaseScreen, self).add_widget(*args) + + +class ShowcaseApp(App): + + index = NumericProperty(-1) + current_title = StringProperty() + time = NumericProperty(0) + show_sourcecode = BooleanProperty(False) + sourcecode = StringProperty() + screen_names = ListProperty([]) + hierarchy = ListProperty([]) + + def build(self): + self.title = 'hello world' + Clock.schedule_interval(self._update_clock, 1 / 60.) + self.screens = {} + self.available_screens = sorted([ + 'Buttons', 'ToggleButton', 'Sliders', 'ProgressBar', 'Switches', + 'CheckBoxes', 'TextInputs', 'Accordions', 'FileChoosers', + 'Carousel', 'Bubbles', 'CodeInput', 'DropDown', 'Spinner', + 'Scatter', 'Splitter', 'TabbedPanel + Layouts', 'RstDocument', + 'Popups', 'ScreenManager']) + self.screen_names = self.available_screens + curdir = dirname(__file__) + self.available_screens = [join(curdir, 'data', 'screens', + '{}.kv'.format(fn).lower()) for fn in self.available_screens] + self.go_next_screen() + + def on_pause(self): + return True + + def on_resume(self): + pass + + def on_current_title(self, instance, value): + self.root.ids.spnr.text = value + + def go_previous_screen(self): + self.index = (self.index - 1) % len(self.available_screens) + screen = self.load_screen(self.index) + sm = self.root.ids.sm + sm.switch_to(screen, direction='right') + self.current_title = screen.name + self.update_sourcecode() + + def go_next_screen(self): + self.index = (self.index + 1) % len(self.available_screens) + screen = self.load_screen(self.index) + sm = self.root.ids.sm + sm.switch_to(screen, direction='left') + self.current_title = screen.name + self.update_sourcecode() + + def go_screen(self, idx): + self.index = idx + self.root.ids.sm.switch_to(self.load_screen(idx), direction='left') + self.update_sourcecode() + + def go_hierarchy_previous(self): + ahr = self.hierarchy + if len(ahr) == 1: + return + if ahr: + ahr.pop() + if ahr: + idx = ahr.pop() + self.go_screen(idx) + + def load_screen(self, index): + if index in self.screens: + return self.screens[index] + screen = Builder.load_file(self.available_screens[index]) + self.screens[index] = screen + return screen + + def read_sourcecode(self): + fn = self.available_screens[self.index] + with open(fn) as fd: + return fd.read() + + def toggle_source_code(self): + self.show_sourcecode = not self.show_sourcecode + if self.show_sourcecode: + height = self.root.height * .3 + else: + height = 0 + + Animation(height=height, d=.3, t='out_quart').start( + self.root.ids.sv) + + self.update_sourcecode() + + def update_sourcecode(self): + if not self.show_sourcecode: + self.root.ids.sourcecode.focus = False + return + self.root.ids.sourcecode.text = self.read_sourcecode() + self.root.ids.sv.scroll_y = 1 + + def showcase_floatlayout(self, layout): + + def add_button(*t): + if not layout.get_parent_window(): + return + if len(layout.children) > 5: + layout.clear_widgets() + layout.add_widget(Builder.load_string(''' +#:import random random.random +Button: + size_hint: random(), random() + pos_hint: {'x': random(), 'y': random()} + text: + 'size_hint x: {} y: {}\\n pos_hint x: {} y: {}'.format(\ + self.size_hint_x, self.size_hint_y, self.pos_hint['x'],\ + self.pos_hint['y']) +''')) + Clock.schedule_once(add_button, 1) + Clock.schedule_once(add_button) + + def showcase_boxlayout(self, layout): + + def add_button(*t): + if not layout.get_parent_window(): + return + if len(layout.children) > 5: + layout.orientation = 'vertical'\ + if layout.orientation == 'horizontal' else 'horizontal' + layout.clear_widgets() + layout.add_widget(Builder.load_string(''' +Button: + text: self.parent.orientation if self.parent else '' +''')) + Clock.schedule_once(add_button, 1) + Clock.schedule_once(add_button) + + def showcase_gridlayout(self, layout): + + def add_button(*t): + if not layout.get_parent_window(): + return + if len(layout.children) > 15: + layout.rows = 3 if layout.rows is None else None + layout.cols = None if layout.rows == 3 else 3 + layout.clear_widgets() + layout.add_widget(Builder.load_string(''' +Button: + text: + 'rows: {}\\ncols: {}'.format(self.parent.rows, self.parent.cols)\ + if self.parent else '' +''')) + Clock.schedule_once(add_button, 1) + Clock.schedule_once(add_button) + + def showcase_stacklayout(self, layout): + orientations = ('lr-tb', 'tb-lr', + 'rl-tb', 'tb-rl', + 'lr-bt', 'bt-lr', + 'rl-bt', 'bt-rl') + + def add_button(*t): + if not layout.get_parent_window(): + return + if len(layout.children) > 11: + layout.clear_widgets() + cur_orientation = orientations.index(layout.orientation) + layout.orientation = orientations[cur_orientation - 1] + layout.add_widget(Builder.load_string(''' +Button: + text: self.parent.orientation if self.parent else '' + size_hint: .2, .2 +''')) + Clock.schedule_once(add_button, 1) + Clock.schedule_once(add_button) + + def showcase_anchorlayout(self, layout): + + def change_anchor(self, *l): + if not layout.get_parent_window(): + return + anchor_x = ('left', 'center', 'right') + anchor_y = ('top', 'center', 'bottom') + if layout.anchor_x == 'left': + layout.anchor_y = anchor_y[anchor_y.index(layout.anchor_y) - 1] + layout.anchor_x = anchor_x[anchor_x.index(layout.anchor_x) - 1] + + Clock.schedule_once(change_anchor, 1) + Clock.schedule_once(change_anchor, 1) + + def _update_clock(self, dt): + self.time = time() + + +if __name__ == '__main__': + ShowcaseApp().run() diff --git a/freechat-client/share/kivy-examples/demo/showcase/showcase.kv b/freechat-client/share/kivy-examples/demo/showcase/showcase.kv new file mode 100644 index 0000000..b68351d --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/showcase/showcase.kv @@ -0,0 +1,100 @@ +#:kivy 1.8.0 +#:import KivyLexer kivy.extras.highlight.KivyLexer +#:import Factory kivy.factory.Factory + + + background_color: .4, .4, .4, 1 + + + canvas.before: + Color: + rgba: 0.128, 0.128, 0.128, 1 + Rectangle: + size: self.size + pos: self.pos + border: 27, 20, 12, 12 + background_normal: 'atlas://data/images/defaulttheme/action_group' + option_cls: Factory.ActionSpinnerOptions + +: + on_size: self.width = '220dp' + +: + ScrollView: + do_scroll_x: False + do_scroll_y: False if root.fullscreen else (content.height > root.height - dp(16)) + AnchorLayout: + size_hint_y: None + height: root.height if root.fullscreen else max(root.height, content.height) + GridLayout: + id: content + cols: 1 + spacing: '8dp' + padding: '8dp' + size_hint: (1, 1) if root.fullscreen else (.8, None) + height: self.height if root.fullscreen else self.minimum_height + + +BoxLayout: + orientation: 'vertical' + + canvas.before: + Color: + rgb: .6, .6, .6 + Rectangle: + size: self.size + source: 'data/background.png' + + ActionBar: + + ActionView: + id: av + ActionPrevious: + with_previous: (False if sm.current_screen.name == 'button' else True) if sm.current_screen else False + title: 'Showcase' + ('' if not app.current_title else ' - {}'.format(app.current_title)) + on_release: app.go_hierarchy_previous() + + ActionSpinner: + id: spnr + important: True + text: 'Jump to Screen' + values: app.screen_names + on_text: + if sm.current != args[1]:\ + idx = app.screen_names.index(args[1]);\ + app.go_screen(idx) + ActionToggleButton: + text: 'Toggle sourcecode' + icon: 'data/icons/bug.png' + on_release: app.toggle_source_code() + ActionButton: + text: 'Previous screen' + icon: 'data/icons/chevron-left.png' + on_release: app.go_previous_screen() + + ActionButton: + text: 'Next screen' + icon: 'data/icons/chevron-right.png' + on_release: app.go_next_screen() + important: True + + ScrollView: + id: sv + size_hint_y: None + height: 0 + + CodeInput: + id: sourcecode + lexer: KivyLexer() + text: app.sourcecode + readonly: True + size_hint_y: None + font_size: '12sp' + height: self.minimum_height + + ScreenManager: + id: sm + on_current_screen: + spnr.text = args[1].name + idx = app.screen_names.index(args[1].name) + if idx > -1: app.hierarchy.append(idx) diff --git a/freechat-client/share/kivy-examples/demo/touchtracer/README.txt b/freechat-client/share/kivy-examples/demo/touchtracer/README.txt new file mode 100644 index 0000000..63a1ff1 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/touchtracer/README.txt @@ -0,0 +1,12 @@ +Touchtracer +=========== + +Touchtracer is a simple example that draws lines using all the touch events +detected by your hardware. + +Android +------- + +You can copy/paste this directory into /sdcard/kivy/touchtracer in your +android device. + diff --git a/freechat-client/share/kivy-examples/demo/touchtracer/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/demo/touchtracer/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..c78d32d Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/touchtracer/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/demo/touchtracer/android.txt b/freechat-client/share/kivy-examples/demo/touchtracer/android.txt new file mode 100644 index 0000000..4e93b39 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/touchtracer/android.txt @@ -0,0 +1,3 @@ +title=Touchtracer +author=Kivy team +orientation=landscape diff --git a/freechat-client/share/kivy-examples/demo/touchtracer/icon.png b/freechat-client/share/kivy-examples/demo/touchtracer/icon.png new file mode 100644 index 0000000..ea7c890 Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/touchtracer/icon.png differ diff --git a/freechat-client/share/kivy-examples/demo/touchtracer/main.py b/freechat-client/share/kivy-examples/demo/touchtracer/main.py new file mode 100755 index 0000000..84dc567 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/touchtracer/main.py @@ -0,0 +1,156 @@ +''' +Touch Tracer Line Drawing Demonstration +======================================= + +This demonstrates tracking each touch registered to a device. You should +see a basic background image. When you press and hold the mouse, you +should see cross-hairs with the coordinates written next to them. As +you drag, it leaves a trail. Additional information, like pressure, +will be shown if they are in your device's touch.profile. + +.. note:: + + A function `calculate_points` handling the points which will be drawn + has by default implemented a delay of 5 steps. To get more precise visual + results lower the value of the optional keyword argument `steps`. + +This program specifies an icon, the file icon.png, in its App subclass. +It also uses the particle.png file as the source for drawing the trails which +are white on transparent. The file touchtracer.kv describes the application. + +The file android.txt is used to package the application for use with the +Kivy Launcher Android application. For Android devices, you can +copy/paste this directory into /sdcard/kivy/touchtracer on your Android device. + +''' +__version__ = '1.0' + +import kivy +kivy.require('1.0.6') + +from kivy.app import App +from kivy.uix.floatlayout import FloatLayout +from kivy.uix.label import Label +from kivy.graphics import Color, Rectangle, Point, GraphicException +from random import random +from math import sqrt + + +def calculate_points(x1, y1, x2, y2, steps=5): + dx = x2 - x1 + dy = y2 - y1 + dist = sqrt(dx * dx + dy * dy) + if dist < steps: + return + o = [] + m = dist / steps + for i in range(1, int(m)): + mi = i / m + lastx = x1 + dx * mi + lasty = y1 + dy * mi + o.extend([lastx, lasty]) + return o + + +class Touchtracer(FloatLayout): + + def on_touch_down(self, touch): + win = self.get_parent_window() + ud = touch.ud + ud['group'] = g = str(touch.uid) + pointsize = 5 + if 'pressure' in touch.profile: + ud['pressure'] = touch.pressure + pointsize = (touch.pressure * 100000) ** 2 + ud['color'] = random() + + with self.canvas: + Color(ud['color'], 1, 1, mode='hsv', group=g) + ud['lines'] = [ + Rectangle(pos=(touch.x, 0), size=(1, win.height), group=g), + Rectangle(pos=(0, touch.y), size=(win.width, 1), group=g), + Point(points=(touch.x, touch.y), source='particle.png', + pointsize=pointsize, group=g)] + + ud['label'] = Label(size_hint=(None, None)) + self.update_touch_label(ud['label'], touch) + self.add_widget(ud['label']) + touch.grab(self) + return True + + def on_touch_move(self, touch): + if touch.grab_current is not self: + return + ud = touch.ud + ud['lines'][0].pos = touch.x, 0 + ud['lines'][1].pos = 0, touch.y + + index = -1 + + while True: + try: + points = ud['lines'][index].points + oldx, oldy = points[-2], points[-1] + break + except: + index -= 1 + + points = calculate_points(oldx, oldy, touch.x, touch.y) + + # if pressure changed create a new point instruction + if 'pressure' in ud: + if not .95 < (touch.pressure / ud['pressure']) < 1.05: + g = ud['group'] + pointsize = (touch.pressure * 100000) ** 2 + with self.canvas: + Color(ud['color'], 1, 1, mode='hsv', group=g) + ud['lines'].append( + Point(points=(), source='particle.png', + pointsize=pointsize, group=g)) + + if points: + try: + lp = ud['lines'][-1].add_point + for idx in range(0, len(points), 2): + lp(points[idx], points[idx + 1]) + except GraphicException: + pass + + ud['label'].pos = touch.pos + import time + t = int(time.time()) + if t not in ud: + ud[t] = 1 + else: + ud[t] += 1 + self.update_touch_label(ud['label'], touch) + + def on_touch_up(self, touch): + if touch.grab_current is not self: + return + touch.ungrab(self) + ud = touch.ud + self.canvas.remove_group(ud['group']) + self.remove_widget(ud['label']) + + def update_touch_label(self, label, touch): + label.text = 'ID: %s\nPos: (%d, %d)\nClass: %s' % ( + touch.id, touch.x, touch.y, touch.__class__.__name__) + label.texture_update() + label.pos = touch.pos + label.size = label.texture_size[0] + 20, label.texture_size[1] + 20 + + +class TouchtracerApp(App): + title = 'Touchtracer' + icon = 'icon.png' + + def build(self): + return Touchtracer() + + def on_pause(self): + return True + + +if __name__ == '__main__': + TouchtracerApp().run() diff --git a/freechat-client/share/kivy-examples/demo/touchtracer/particle.png b/freechat-client/share/kivy-examples/demo/touchtracer/particle.png new file mode 100644 index 0000000..ef79ae8 Binary files /dev/null and b/freechat-client/share/kivy-examples/demo/touchtracer/particle.png differ diff --git a/freechat-client/share/kivy-examples/demo/touchtracer/touchtracer.kv b/freechat-client/share/kivy-examples/demo/touchtracer/touchtracer.kv new file mode 100644 index 0000000..e104705 --- /dev/null +++ b/freechat-client/share/kivy-examples/demo/touchtracer/touchtracer.kv @@ -0,0 +1,29 @@ +#:kivy 1.0 +#:import kivy kivy + +: + canvas: + Color: + rgb: 1, 1, 1 + Rectangle: + source: 'data/images/background.jpg' + size: self.size + + BoxLayout: + padding: '10dp' + spacing: '10dp' + size_hint: 1, None + pos_hint: {'top': 1} + height: '44dp' + Image: + size_hint: None, None + size: '24dp', '24dp' + source: 'data/logo/kivy-icon-64.png' + mipmap: True + Label: + height: '24dp' + text_size: self.width, None + color: (1, 1, 1, .8) + text: 'Kivy %s - Touchtracer' % kivy.__version__ + valign: 'middle' + diff --git a/freechat-client/share/kivy-examples/frameworks/twisted/__pycache__/echo_client_app.cpython-37.pyc b/freechat-client/share/kivy-examples/frameworks/twisted/__pycache__/echo_client_app.cpython-37.pyc new file mode 100644 index 0000000..2ed8ecc Binary files /dev/null and b/freechat-client/share/kivy-examples/frameworks/twisted/__pycache__/echo_client_app.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/frameworks/twisted/__pycache__/echo_server_app.cpython-37.pyc b/freechat-client/share/kivy-examples/frameworks/twisted/__pycache__/echo_server_app.cpython-37.pyc new file mode 100644 index 0000000..e4bfe8e Binary files /dev/null and b/freechat-client/share/kivy-examples/frameworks/twisted/__pycache__/echo_server_app.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/frameworks/twisted/__pycache__/twistd_app.cpython-37.pyc b/freechat-client/share/kivy-examples/frameworks/twisted/__pycache__/twistd_app.cpython-37.pyc new file mode 100644 index 0000000..fbb3043 Binary files /dev/null and b/freechat-client/share/kivy-examples/frameworks/twisted/__pycache__/twistd_app.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/frameworks/twisted/echo_client_app.py b/freechat-client/share/kivy-examples/frameworks/twisted/echo_client_app.py new file mode 100644 index 0000000..7e4f4d2 --- /dev/null +++ b/freechat-client/share/kivy-examples/frameworks/twisted/echo_client_app.py @@ -0,0 +1,82 @@ +# install_twisted_rector must be called before importing the reactor +from __future__ import unicode_literals + +from kivy.support import install_twisted_reactor + +install_twisted_reactor() + +# A Simple Client that send messages to the Echo Server +from twisted.internet import reactor, protocol + + +class EchoClient(protocol.Protocol): + def connectionMade(self): + self.factory.app.on_connection(self.transport) + + def dataReceived(self, data): + self.factory.app.print_message(data.decode('utf-8')) + + +class EchoClientFactory(protocol.ClientFactory): + protocol = EchoClient + + def __init__(self, app): + self.app = app + + def startedConnecting(self, connector): + self.app.print_message('Started to connect.') + + def clientConnectionLost(self, connector, reason): + self.app.print_message('Lost connection.') + + def clientConnectionFailed(self, connector, reason): + self.app.print_message('Connection failed.') + + +from kivy.app import App +from kivy.uix.label import Label +from kivy.uix.textinput import TextInput +from kivy.uix.boxlayout import BoxLayout + + +# A simple kivy App, with a textbox to enter messages, and +# a large label to display all the messages received from +# the server +class TwistedClientApp(App): + connection = None + textbox = None + label = None + + def build(self): + root = self.setup_gui() + self.connect_to_server() + return root + + def setup_gui(self): + self.textbox = TextInput(size_hint_y=.1, multiline=False) + self.textbox.bind(on_text_validate=self.send_message) + self.label = Label(text='connecting...\n') + layout = BoxLayout(orientation='vertical') + layout.add_widget(self.label) + layout.add_widget(self.textbox) + return layout + + def connect_to_server(self): + reactor.connectTCP('localhost', 8000, EchoClientFactory(self)) + + def on_connection(self, connection): + self.print_message("Connected successfully!") + self.connection = connection + + def send_message(self, *args): + msg = self.textbox.text + if msg and self.connection: + self.connection.write(msg.encode('utf-8')) + self.textbox.text = "" + + def print_message(self, msg): + self.label.text += "{}\n".format(msg) + + +if __name__ == '__main__': + TwistedClientApp().run() diff --git a/freechat-client/share/kivy-examples/frameworks/twisted/echo_server_app.py b/freechat-client/share/kivy-examples/frameworks/twisted/echo_server_app.py new file mode 100644 index 0000000..ffbfd15 --- /dev/null +++ b/freechat-client/share/kivy-examples/frameworks/twisted/echo_server_app.py @@ -0,0 +1,49 @@ +# install_twisted_rector must be called before importing and using the reactor +from kivy.support import install_twisted_reactor + +install_twisted_reactor() + +from twisted.internet import reactor +from twisted.internet import protocol + + +class EchoServer(protocol.Protocol): + def dataReceived(self, data): + response = self.factory.app.handle_message(data) + if response: + self.transport.write(response) + + +class EchoServerFactory(protocol.Factory): + protocol = EchoServer + + def __init__(self, app): + self.app = app + + +from kivy.app import App +from kivy.uix.label import Label + + +class TwistedServerApp(App): + label = None + + def build(self): + self.label = Label(text="server started\n") + reactor.listenTCP(8000, EchoServerFactory(self)) + return self.label + + def handle_message(self, msg): + msg = msg.decode('utf-8') + self.label.text = "received: {}\n".format(msg) + + if msg == "ping": + msg = "Pong" + if msg == "plop": + msg = "Kivy Rocks!!!" + self.label.text += "responded: {}\n".format(msg) + return msg.encode('utf-8') + + +if __name__ == '__main__': + TwistedServerApp().run() diff --git a/freechat-client/share/kivy-examples/frameworks/twisted/twistd_app.py b/freechat-client/share/kivy-examples/frameworks/twisted/twistd_app.py new file mode 100644 index 0000000..cfd9f2a --- /dev/null +++ b/freechat-client/share/kivy-examples/frameworks/twisted/twistd_app.py @@ -0,0 +1,67 @@ +from kivy.support import install_twisted_reactor +install_twisted_reactor() + +import os +import sys + +from kivy.app import App +from kivy.uix.gridlayout import GridLayout +from kivy.properties import BooleanProperty +from kivy.lang import Builder + +from twisted.scripts._twistd_unix import UnixApplicationRunner, ServerOptions +from twisted.application.service import IServiceCollection + +TWISTD = 'twistd web -p 8087' + + +class AndroidApplicationRunner(UnixApplicationRunner): + + def run(self): + + self.preApplication() + self.application = self.createOrGetApplication() + self.logger.start(self.application) + sc = IServiceCollection(self.application) + + # reactor is already running, so we just start the service collection + sc.startService() + return self.application + + +Builder.load_string(''' +: + cols: 1 + Button: + text: root.running and 'STOP' or 'START' + on_release: root.cb_twistd() +''') + + +class TwistedTwistd(GridLayout): + + running = BooleanProperty(False) + + def cb_twistd(self, *la): + + if self.running: + IServiceCollection(self.app).stopService() + self.running = False + else: + sys.exc_clear() + sys.path.insert(0, os.path.abspath(os.getcwd())) + sys.argv = TWISTD.split(' ') + config = ServerOptions() + config.parseOptions() + self.app = AndroidApplicationRunner(config).run() + self.running = True + + +class TwistedTwistdApp(App): + + def build(self): + return TwistedTwistd() + + +if __name__ == '__main__': + TwistedTwistdApp().run() diff --git a/freechat-client/share/kivy-examples/gestures/__pycache__/gesture_board.cpython-37.pyc b/freechat-client/share/kivy-examples/gestures/__pycache__/gesture_board.cpython-37.pyc new file mode 100644 index 0000000..a9b1072 Binary files /dev/null and b/freechat-client/share/kivy-examples/gestures/__pycache__/gesture_board.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/gestures/__pycache__/my_gestures.cpython-37.pyc b/freechat-client/share/kivy-examples/gestures/__pycache__/my_gestures.cpython-37.pyc new file mode 100644 index 0000000..03b49b4 Binary files /dev/null and b/freechat-client/share/kivy-examples/gestures/__pycache__/my_gestures.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/gestures/gesture_board.py b/freechat-client/share/kivy-examples/gestures/gesture_board.py new file mode 100644 index 0000000..cdaee71 --- /dev/null +++ b/freechat-client/share/kivy-examples/gestures/gesture_board.py @@ -0,0 +1,95 @@ +from kivy.app import App + +from kivy.uix.floatlayout import FloatLayout +from kivy.graphics import Color, Ellipse, Line +from kivy.gesture import Gesture, GestureDatabase + +from my_gestures import cross, circle, check, square + + +def simplegesture(name, point_list): + """ + A simple helper function + """ + g = Gesture() + g.add_stroke(point_list) + g.normalize() + g.name = name + return g + + +class GestureBoard(FloatLayout): + """ + Our application main widget, derived from touchtracer example, use data + constructed from touches to match symboles loaded from my_gestures. + + """ + def __init__(self, *args, **kwargs): + super(GestureBoard, self).__init__() + self.gdb = GestureDatabase() + + # add pre-recorded gestures to database + self.gdb.add_gesture(cross) + self.gdb.add_gesture(check) + self.gdb.add_gesture(circle) + self.gdb.add_gesture(square) + + def on_touch_down(self, touch): + # start collecting points in touch.ud + # create a line to display the points + userdata = touch.ud + with self.canvas: + Color(1, 1, 0) + d = 30. + Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d)) + userdata['line'] = Line(points=(touch.x, touch.y)) + return True + + def on_touch_move(self, touch): + # store points of the touch movement + try: + touch.ud['line'].points += [touch.x, touch.y] + return True + except (KeyError) as e: + pass + + def on_touch_up(self, touch): + # touch is over, display informations, and check if it matches some + # known gesture. + g = simplegesture('', list(zip(touch.ud['line'].points[::2], + touch.ud['line'].points[1::2]))) + # gestures to my_gestures.py + print("gesture representation:", self.gdb.gesture_to_str(g)) + + # print match scores between all known gestures + print("cross:", g.get_score(cross)) + print("check:", g.get_score(check)) + print("circle:", g.get_score(circle)) + print("square:", g.get_score(square)) + + # use database to find the more alike gesture, if any + g2 = self.gdb.find(g, minscore=0.70) + + print(g2) + if g2: + if g2[1] == circle: + print("circle") + if g2[1] == square: + print("square") + if g2[1] == check: + print("check") + if g2[1] == cross: + print("cross") + + # erase the lines on the screen, this is a bit quick&dirty, since we + # can have another touch event on the way... + self.canvas.clear() + + +class DemoGesture(App): + def build(self): + return GestureBoard() + + +if __name__ == '__main__': + DemoGesture().run() diff --git a/freechat-client/share/kivy-examples/gestures/my_gestures.py b/freechat-client/share/kivy-examples/gestures/my_gestures.py new file mode 100644 index 0000000..31ed971 --- /dev/null +++ b/freechat-client/share/kivy-examples/gestures/my_gestures.py @@ -0,0 +1,90 @@ +from kivy.gesture import GestureDatabase + +gdb = GestureDatabase() + +cross = gdb.str_to_gesture( + 'eNq1l9tu3DYQhu/1It6bLjicE+cFtrcF/ACBYwv2Iqkt7G7a5u1DDqlT0lZ7I2Mxsj5JP2f4k' + 'xR1OH85//X9+Npfb98uffd7Ow6hO7wM0D0+vD/92T90Q8z/5gN218eH6+3y8aW/5lPqDl8H7g' + '7/KvLot3WDFCnNzw8f5/dbeSyVx+w/Hvuj3NUNUDMoKXzPj0DsTuGIGiRJGCOVbP4pV7E7/Ra' + 'ORJZMwhS1u35++v9WyFvh7rU2ENEMJI1RuLu+NnEEgyhpjEG2xb1y0H3Ek4vbKA6kEmyKEWdx' + 'WPaJsaVN8eidH2Ef8ejiOIqHdbeQLvolaLTFLxlty7ulsVlaNBKChCnmEpp+uRSSIozRBLbl3' + 'dSoe8m7rdF2kkc3FmGSB1FVphYT6qSejY2sOsXtyYRuLOIkHgEtGrZIKJP4Spk13ZG524qzrX' + 'FWLlHmfok/9UvcFndTUe8Rz8OVA7RIYXtAoluKdke3hJU42j0dQ24pwV7ybiptm1oGE+Rz4il' + 'u9w25q8R3qQtnZ2WKd+TutpLeox4pZmt1jHlh3VR3X8nuUceFdIm4qc5uKy9mapCY339jXKb+' + '08tjewlmN5VxH3H3lBcLcASZfzGv4osFPiVk5SnmCb6p766y7qbvvvL0Zg2GKtHGCDjPJ2FKi' + 'cfI2wuNuKsCu2i7qYLzdiP3BXGLYIs1DEAo0hh1eyaJeyq8i7b7KdM26ddNXpPO7SCSTnHbSn' + 'ErxXaQVndSJyeJGQOMMe+RJm1aLrk5bku7kYp7SLuPOvlI6/FHs4+87hH2Fats/p8vff8+beV' + 'Vyl5etTucMA/a7kSE+XAbNHVPmcGK2ZKBsxSciTPUyqAwUmdRKouFCToDqgwLU3MWQmVUmDnD' + '1O7jwsCfOuXFt0JxGKNDaS1rhVwhV5gqpBW0CnEJLaw0G4QKwwrGmlJaQaxw1bp5QRBsBb2iZ' + 'MvczQtSWjGvx09m5uXwmnk1tNKDEGYbZli94TX0aqg1nRrE5Z3WoFdDtWyFBr0aqR2URljLqa' + '1bbNDrsToywth69QfqGIrcaDVoPSoBqkNtbDE1Wi3iqsAtV6gesSdL0vKCalLNdqa5rjpB3vr' + 'z69utfJTmz8qTFclM/z6/3N4cSteSyvT28bW/PL0/935Ffdsd1n9Q7muT+dNw+Xj59lzFU+6W' + 'Y5L8ug5qwTR/PFH5bDz+AM/6Dqo=') + +circle = gdb.str_to_gesture( + 'eNq1WNtyGzcMfd8fiV+iIS4EyB9QXzuTD+g4icbxpLU1ttI2f18QoHa5jpy12qlGAyUw9hA4B' + 'yQh3dx/vf/z++7u8Hz69nSYfumfxzTdfD7C9OHdw+0fh3fTEe2f9kHT84d3z6enx6+HZ/svTz' + 'e/H/N0cxHkg4dNR2lQas8fH+8fTu2x0h6rrzz2a4uajhAZtBS+2yOA0z7tCDMkqjk1y0W1pfN' + '3+zNN+/dpl0pGqmdLJcv0/PH25+uwr5Onu74EMxErVLeGMT3fNXQDT4C1kopbLVBhG92LB91G' + 'h6RJinRb5A2ZF8euM/aP5JyxhVVShbBiJW9ho7OPcMZG1YTzWzTP2LgAm8XyBmx0bJqxsfSkm' + '8UqMzaRluVduW5ju5o4qwkKmFWruM28cGLNcW3eriXOWi5kv8zbNK7GcwmbabtP0LXEWcuB7M' + 'Y3pSVxVuRMiGFJaBOcXEzqYrZtwglLEsluBdOSen7R5LiN7nISzehAwsQZwC3yfwJ3PSnP4FZ' + '31fnNrZX/PS8uKOkCvpBiFkfSF2Sz3PpoC9wVpTqDExXKmkvYmoc274S8nRZ2RXlR1B5u5xGG' + '1bKcK7a5rtz77ILyIihVSVzL2bb8zuB4LefsgnJ+AzjQtTuUXVBeBCVRTKSMbq1HA/u9b7DMo' + 'hpWSLbPFnZFuf4/6NklzYOki57N1rzAQ8YV/HY3Ztc0L5piXR0BMqAj1GItLmELb/OeXdQ87F' + 'KB8QhIOKDXOXGzOb2BGVc1D9sUaNxJNiPM6LQkbpbS9lbKrmpeVAXluRtTTloXdDs2B95z3UY' + 'XV1UWVe2aPydutqAO6HIt7+KqCm0f7A2+Fk1JkNyiTQ+b8C6rzJdpyrkoQUlhUx6IZ61XEi8u' + 'qyzXKSODTSphAcsAjnBlz4irKvN9CjVxsXEwu2UZ9iopXcmLuqgKWwOMb2JJNoh2y284B9Q11' + 'WU6En2NFuRrFVVXVJdhN71QdDhjBIe3a/3xtg3/n54Oh4d5lFdps7zNmjd7Rt2laY9ad3V88X' + 'Q6apluW0TxiAL2Yc7qTkqjs6RwSjgxnOBOhpUTw6krJ7kz06up2D3iETUiNB7L7pT+WLZhf3h' + 'Ji5CIiLyU4zENZ5SlPYWoVSNZTeGMWv25vWnqzhq1amBKYNaotcTjuUdGrSXy8+rMGbWW7E6u' + '66SpRUStJRbgvGZDW0QUXqICjgqqjE6q4dSVM19Yrawi4MJqwUIJyTBqg5TGOpC6F1be9ON6t' + 'tdGVkB+XNA2ZYREjwFfCgmSNJKC8/JBjMbyAN0bzLjS5k3dG9RoLJJK95axY9K52KBAohGShB' + 'eCAgncdIFcABj79nJI8JHzT0L6/kg/CQk+mFd5Q/BBtKoRZNzXZz4g+MC0YhSCD+hqXWhGgCA' + 'n1dcFxWAqdV0uND1gMJWCTIyeBnRy7CtZeLl7KbxRLPaykMObXu1k+1rpIb2VL20Hm9siJFKl' + 'TiTqylu7t4SXx31o35ZW3p4zpZVXLyxNsAq5xBIFH/1syH1FCj76Hs69PSn4KHU8k2w+D5aCZ' + '+lbhKLqGvVJF5+i6hp0yRk3WiLFWSedfepdQOMBCtyFl/GsBe5a9xO4r8axESCNh7UNo+GFVw' + '95YB57VHuaHL0Pebwy7DYPb79IevLcex/W3n7/0dobhWI+X1buzVEoytprhcYN/OVwf/fl1H7' + '0sql+ry83CbbfxP66/3z64iF2m9sJZxjmPT3+fni6ffh08L9w/IixfkGL68PDb8enx8/fPsVS' + 'edrnnc05diDYoIA2CpbUvu7t/gFuoPx3') + +check = gdb.str_to_gesture( + 'eNq1l0tuI0cMhvd9EXsTofgmL6BsA/gAgcYWbGMmtmBpksztwyY1kgZI0rNpbdr+u+pjkX+9+' + 'v718+uf3zbP++Pp68d++vX8PIzp/ukA08Pd2+6P/d10wPwzHzQdH+6Op4/3z/tj/svT/ZeDTP' + 'f/CnmoZtNBZ5Rl/8P769tp7uZzt/iPbr/NraYD9AjmIXzLLoDTdmxgBLsSMMIw5OHzcP6eX9O' + '0/WVsCMFGmCuaGgjBdPy0+/8wXGFkeu4Ig7LzgISbMw/j6fh8hmMMBDIkdBYPimV4pQ7W8EQM' + 'UA4LMhMzCyW5watKgJoOHhxsuIz3wscVb8ExhpIxDoIgvcEzhoaiZ1geA20Rj+UAwlp4LDxd8' + 'OkqO4KHYXLI4oYOwEai4oPRmHiZXr6iXOiY9mXBFUNYacAVDm4uIOCiaXws24plK9oq7PIUr5' + '6iOqsyg+acyOrezJicpTCI3YYy5HtapFNZSldLCcRgCCk4hqniDZ2dHZjCMf1EXh47laNEN2M' + 'fEjkzJFgtK3BLHwEAGTcnlSu7LNPLUbo6+n2m5GbAuVzUr/ShYQzoSBSWi5iXJwyVqWRr4ctX' + '+om1mq+GR7ibAA8dJuHLfC5nGVbjl7dMS/tk1g3tB3OXZyWXsyyrsMtWtlXY5SnHGmwpPwW+s' + '3M15h5CkVvM8FyWcWH3Uce5io00A/8Eu7wUWoVdXoqswi4v5eIlseTWl6e9Cqh6+IUt6OoUwA' + 'JD88KwjC4rJVZAazmpsAa6jFRaA10+qqyBLht1DRu1bNQ1bLSy0S425mWFOc9khtxcnRwuaEW' + '6PZnH8sFp5aPRKuwy0i5GMnsmHJE32dz73a5oG3nJgLyemqDgXKtPu/m2//ix379d7u6m8+Xd' + 'bLrf5jg2Y9picD5OB/NpN4vQIrYYLWKJHiX6aJFblBahRSvRvEUsETuQjRapxe6uHSjPsBK7u' + '0CL0mKUyLKJ25/NLbRaUI+PzwGsRWrxzOr0qKNy5+ydHnVUzsftj7JFdK7cAUSrW3SugrdpRe' + 'eqdluV6Fxdu6hdv6hcCeYabQl7KFG5ElWpiM6itqgtWovWorXYlU6/d234y/71+eWUVud1dRv' + 'z2xT/en06vcwfWiP7QFU51dP7l/3H7u1xX2+gP9F+/MHc7jw1fz98vD99fTxV65yN6YfP81jE' + '8nDMa8j81bD5B2R9zCo=') + +square = gdb.str_to_gesture( + 'eNq1mEluIzcYRvd1EXsT4Z+HC6i3AXyAwG0LttEdW7DUSfr2YZHVEgk4KQGCtZH8RD4OH4eSb' + '1++vfz1c/O0Oxx/vO+mL8v7Hqbbxz1Odzev93/ubqY9lY/ljafD3c3h+P72bXcof8p0+32v0+' + '2HkrtabNrbrPJSf//28nqcq8VcLf+j2u9zqWmPrQdzF36WKkjTFjasKZKMaJwqGTp355/5a56' + '2v8FGREAVLIINymebDl/v/78Zqc3o9LS04EgogK6ECeSlhadFTomIHElsKqoS6/I6dPQL5JiW' + 'aSTKYMZEuS6PKs8L5DD03DB11U51+gnX7EVuGOQUgqDIxHGBnKqc1+XkJXLMyAyXUFkPlGqgp' + 'J/irnmSr7s5kThBIhAB5RJ3jZPOcYpbiIG6elkc81Je3DL222TVzTVMPoVJggFESoEGBIJndy' + 'irWWpYRonyAnfNkk9ZQkQYghuLSlnI7tfIa5i8hDmvZFBSUwdH5ixDgKv6XvNkP+mxbDxgo1S' + '2JIhr3DVPzpOb0IGQ3DTVhTPP8nEH+bpcaqCCJzkHOjlqpISFAp/lZMqMZqIBLnCBvCYqfJKL' + 'EqNyCgkFFNlZjt0qJaD1rS81UTknKuEGqYgRGUZdnsxlnapilrkiKafjurzmKec8Sy12KTPvT' + 'mWn5lle9mS/B2z9MJcaqOSqvC7TflRlkZZ7bM2vNVPFT/PXWJUv8ZO5hkiAQVkz5Wpat9dcVT' + '/JXoNVv8Quoz3Wl43WZDU/x241V1vfq+UrRTFhLicyAxpecG1YTdXOqVLXP4XSRmcHCg/NIPG' + 'AcnOs22uqdk4Vx777dfaaqp2uU+jPWGdkvcpeU7X8HLvXVP10pWJKOdSFksIMSgNXyWuofrpT' + 'yyUKaewgxuCJeJW8ZuqnB6TxIATspkXGJ16r8vkHwMP7bvd6epx3m5/ny0V/uy1X4wamLaWVt' + '+PeY7qfoQ8wG8wGvcKACjMGiDMsj/EDpApRB8gV0lhdKpSxulaoI7QKDQfoDfIAY4Cyyf4lc4' + 'lsJaSV4FotYYDzCd69bC6BfYloU5XUQ88GeYBLA9JD+6BfqX0J1VZtGThVKD72i+cS3k+NUKv' + 'WZkFbhMwfVMu+BOXYHy8lENqcaMuM2vyWp+WB2kJpoLrQNhOqI21Toa3HJAttw5c2fOKFtvGz' + 'jrSNmWikbdAAI11WMw8U23L2HCkOdBkxUk8/msyyCVsj0IeAKAP9aI5R+yJ1+mZqPXVYqPc0f' + 'jUSA82FZk9zmWNqo45hG5WfSB1lWOaCqDMwLDkTD/SXoQy0nTzPu5en52P9f4BO25jbLfTvl8' + 'fjc4VWoDZ4fPu+e79/fdjVL7we0jC+cC63nJJ/7N/fHn88NHdM29xw+VUXOp+Mzm7FcPi6+Re' + 'GcFi7') diff --git a/freechat-client/share/kivy-examples/guide/designwithkv/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/guide/designwithkv/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..6bbf1fb Binary files /dev/null and b/freechat-client/share/kivy-examples/guide/designwithkv/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/guide/designwithkv/controller.kv b/freechat-client/share/kivy-examples/guide/designwithkv/controller.kv new file mode 100644 index 0000000..7eeb4cc --- /dev/null +++ b/freechat-client/share/kivy-examples/guide/designwithkv/controller.kv @@ -0,0 +1,16 @@ +#:kivy 1.0 + +: + label_wid: my_custom_label + + BoxLayout: + orientation: 'vertical' + padding: 20 + + Button: + text: 'My controller info is: ' + root.info + on_press: root.do_action() + + Label: + id: my_custom_label + text: 'My label before button press' diff --git a/freechat-client/share/kivy-examples/guide/designwithkv/main.py b/freechat-client/share/kivy-examples/guide/designwithkv/main.py new file mode 100644 index 0000000..64e4334 --- /dev/null +++ b/freechat-client/share/kivy-examples/guide/designwithkv/main.py @@ -0,0 +1,29 @@ +import kivy +kivy.require('1.0.5') + +from kivy.uix.floatlayout import FloatLayout +from kivy.app import App +from kivy.properties import ObjectProperty, StringProperty + + +class Controller(FloatLayout): + '''Create a controller that receives a custom widget from the kv lang file. + + Add an action to be called from the kv lang file. + ''' + label_wid = ObjectProperty() + info = StringProperty() + + def do_action(self): + self.label_wid.text = 'My label after button press' + self.info = 'New info text' + + +class ControllerApp(App): + + def build(self): + return Controller(info='Hello world') + + +if __name__ == '__main__': + ControllerApp().run() diff --git a/freechat-client/share/kivy-examples/guide/firstwidget/1_skeleton.py b/freechat-client/share/kivy-examples/guide/firstwidget/1_skeleton.py new file mode 100644 index 0000000..1f8df31 --- /dev/null +++ b/freechat-client/share/kivy-examples/guide/firstwidget/1_skeleton.py @@ -0,0 +1,15 @@ +from kivy.app import App +from kivy.uix.widget import Widget + + +class MyPaintWidget(Widget): + pass + + +class MyPaintApp(App): + def build(self): + return MyPaintWidget() + + +if __name__ == '__main__': + MyPaintApp().run() diff --git a/freechat-client/share/kivy-examples/guide/firstwidget/2_print_touch.py b/freechat-client/share/kivy-examples/guide/firstwidget/2_print_touch.py new file mode 100644 index 0000000..8bc4db2 --- /dev/null +++ b/freechat-client/share/kivy-examples/guide/firstwidget/2_print_touch.py @@ -0,0 +1,16 @@ +from kivy.app import App +from kivy.uix.widget import Widget + + +class MyPaintWidget(Widget): + def on_touch_down(self, touch): + print(touch) + + +class MyPaintApp(App): + def build(self): + return MyPaintWidget() + + +if __name__ == '__main__': + MyPaintApp().run() diff --git a/freechat-client/share/kivy-examples/guide/firstwidget/3_draw_ellipse.py b/freechat-client/share/kivy-examples/guide/firstwidget/3_draw_ellipse.py new file mode 100644 index 0000000..05ca0f0 --- /dev/null +++ b/freechat-client/share/kivy-examples/guide/firstwidget/3_draw_ellipse.py @@ -0,0 +1,22 @@ +from kivy.app import App +from kivy.uix.widget import Widget +from kivy.graphics import Color, Ellipse + + +class MyPaintWidget(Widget): + + def on_touch_down(self, touch): + with self.canvas: + Color(1, 1, 0) + d = 30. + Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d)) + + +class MyPaintApp(App): + + def build(self): + return MyPaintWidget() + + +if __name__ == '__main__': + MyPaintApp().run() diff --git a/freechat-client/share/kivy-examples/guide/firstwidget/4_draw_line.py b/freechat-client/share/kivy-examples/guide/firstwidget/4_draw_line.py new file mode 100644 index 0000000..a7d286a --- /dev/null +++ b/freechat-client/share/kivy-examples/guide/firstwidget/4_draw_line.py @@ -0,0 +1,26 @@ +from kivy.app import App +from kivy.uix.widget import Widget +from kivy.graphics import Color, Ellipse, Line + + +class MyPaintWidget(Widget): + + def on_touch_down(self, touch): + with self.canvas: + Color(1, 1, 0) + d = 30. + Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d)) + touch.ud['line'] = Line(points=(touch.x, touch.y)) + + def on_touch_move(self, touch): + touch.ud['line'].points += [touch.x, touch.y] + + +class MyPaintApp(App): + + def build(self): + return MyPaintWidget() + + +if __name__ == '__main__': + MyPaintApp().run() diff --git a/freechat-client/share/kivy-examples/guide/firstwidget/5_random_colors.py b/freechat-client/share/kivy-examples/guide/firstwidget/5_random_colors.py new file mode 100644 index 0000000..25906b8 --- /dev/null +++ b/freechat-client/share/kivy-examples/guide/firstwidget/5_random_colors.py @@ -0,0 +1,28 @@ +from random import random +from kivy.app import App +from kivy.uix.widget import Widget +from kivy.graphics import Color, Ellipse, Line + + +class MyPaintWidget(Widget): + + def on_touch_down(self, touch): + color = (random(), random(), random()) + with self.canvas: + Color(*color) + d = 30. + Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d)) + touch.ud['line'] = Line(points=(touch.x, touch.y)) + + def on_touch_move(self, touch): + touch.ud['line'].points += [touch.x, touch.y] + + +class MyPaintApp(App): + + def build(self): + return MyPaintWidget() + + +if __name__ == '__main__': + MyPaintApp().run() diff --git a/freechat-client/share/kivy-examples/guide/firstwidget/6_button.py b/freechat-client/share/kivy-examples/guide/firstwidget/6_button.py new file mode 100644 index 0000000..428a6bb --- /dev/null +++ b/freechat-client/share/kivy-examples/guide/firstwidget/6_button.py @@ -0,0 +1,38 @@ +from random import random +from kivy.app import App +from kivy.uix.widget import Widget +from kivy.uix.button import Button +from kivy.graphics import Color, Ellipse, Line + + +class MyPaintWidget(Widget): + + def on_touch_down(self, touch): + color = (random(), 1, 1) + with self.canvas: + Color(*color, mode='hsv') + d = 30. + Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d)) + touch.ud['line'] = Line(points=(touch.x, touch.y)) + + def on_touch_move(self, touch): + touch.ud['line'].points += [touch.x, touch.y] + + +class MyPaintApp(App): + + def build(self): + parent = Widget() + self.painter = MyPaintWidget() + clearbtn = Button(text='Clear') + clearbtn.bind(on_release=self.clear_canvas) + parent.add_widget(self.painter) + parent.add_widget(clearbtn) + return parent + + def clear_canvas(self, obj): + self.painter.canvas.clear() + + +if __name__ == '__main__': + MyPaintApp().run() diff --git a/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/1_skeleton.cpython-37.pyc b/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/1_skeleton.cpython-37.pyc new file mode 100644 index 0000000..475e6f0 Binary files /dev/null and b/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/1_skeleton.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/2_print_touch.cpython-37.pyc b/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/2_print_touch.cpython-37.pyc new file mode 100644 index 0000000..6640143 Binary files /dev/null and b/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/2_print_touch.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/3_draw_ellipse.cpython-37.pyc b/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/3_draw_ellipse.cpython-37.pyc new file mode 100644 index 0000000..2a08e20 Binary files /dev/null and b/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/3_draw_ellipse.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/4_draw_line.cpython-37.pyc b/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/4_draw_line.cpython-37.pyc new file mode 100644 index 0000000..ee44a23 Binary files /dev/null and b/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/4_draw_line.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/5_random_colors.cpython-37.pyc b/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/5_random_colors.cpython-37.pyc new file mode 100644 index 0000000..1b4526e Binary files /dev/null and b/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/5_random_colors.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/6_button.cpython-37.pyc b/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/6_button.cpython-37.pyc new file mode 100644 index 0000000..8337b87 Binary files /dev/null and b/freechat-client/share/kivy-examples/guide/firstwidget/__pycache__/6_button.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/guide/quickstart/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/guide/quickstart/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..a827ab1 Binary files /dev/null and b/freechat-client/share/kivy-examples/guide/quickstart/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/guide/quickstart/main.py b/freechat-client/share/kivy-examples/guide/quickstart/main.py new file mode 100644 index 0000000..ee89836 --- /dev/null +++ b/freechat-client/share/kivy-examples/guide/quickstart/main.py @@ -0,0 +1,15 @@ +import kivy +kivy.require('1.0.6') # replace with your current kivy version ! + +from kivy.app import App +from kivy.uix.button import Button + + +class MyApp(App): + + def build(self): + return Button(text='Hello World') + + +if __name__ == '__main__': + MyApp().run() diff --git a/freechat-client/share/kivy-examples/includes/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/includes/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..893d44f Binary files /dev/null and b/freechat-client/share/kivy-examples/includes/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/includes/button.kv b/freechat-client/share/kivy-examples/includes/button.kv new file mode 100644 index 0000000..93f7c65 --- /dev/null +++ b/freechat-client/share/kivy-examples/includes/button.kv @@ -0,0 +1,9 @@ +#:kivy 1.8.0 + +: + canvas: + Color: + rgba: 1.0, 0.0, 0.0, 1.0 + Rectangle: + pos: self.pos + size: (self.size[0]/4, self.size[1]/4) \ No newline at end of file diff --git a/freechat-client/share/kivy-examples/includes/layout.kv b/freechat-client/share/kivy-examples/includes/layout.kv new file mode 100644 index 0000000..df4ea9e --- /dev/null +++ b/freechat-client/share/kivy-examples/includes/layout.kv @@ -0,0 +1,6 @@ +#:kivy 1.8.1 +#:include button.kv + +: + SpecialButton: + text: 'Includes!' diff --git a/freechat-client/share/kivy-examples/includes/main.py b/freechat-client/share/kivy-examples/includes/main.py new file mode 100644 index 0000000..8bf3f90 --- /dev/null +++ b/freechat-client/share/kivy-examples/includes/main.py @@ -0,0 +1,19 @@ +from kivy.app import App +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.button import Button + + +class SpecialButton(Button): + pass + + +class CustomLayout(BoxLayout): + pass + + +class TestApp(App): + pass + + +if __name__ == '__main__': + TestApp().run() diff --git a/freechat-client/share/kivy-examples/includes/test.kv b/freechat-client/share/kivy-examples/includes/test.kv new file mode 100644 index 0000000..9cbedf8 --- /dev/null +++ b/freechat-client/share/kivy-examples/includes/test.kv @@ -0,0 +1,5 @@ +#:kivy 1.8.1 +#:include layout.kv +#:include force button.kv + +CustomLayout: diff --git a/freechat-client/share/kivy-examples/keyboard/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/keyboard/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..102bb65 Binary files /dev/null and b/freechat-client/share/kivy-examples/keyboard/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/keyboard/android.txt b/freechat-client/share/kivy-examples/keyboard/android.txt new file mode 100755 index 0000000..388d1a6 --- /dev/null +++ b/freechat-client/share/kivy-examples/keyboard/android.txt @@ -0,0 +1,3 @@ +title=Keyboard +author=ZenCODE +orientation=landscape \ No newline at end of file diff --git a/freechat-client/share/kivy-examples/keyboard/main.py b/freechat-client/share/kivy-examples/keyboard/main.py new file mode 100755 index 0000000..c5ac658 --- /dev/null +++ b/freechat-client/share/kivy-examples/keyboard/main.py @@ -0,0 +1,226 @@ +""" +Custom Keyboards +================ + +This demo shows how to create and display custom keyboards on screen. +Note that the new "input_type" property of the TextInput means that this +is rarely needed. We provide this demo for the sake of completeness. +""" +# Author: Zen-CODE +from kivy.app import App +from kivy.lang import Builder +from kivy.core.window import Window +from kivy.uix.vkeyboard import VKeyboard +from kivy.properties import ObjectProperty +from kivy.uix.button import Button +from functools import partial +from kivy.config import Config +from kivy.uix.screenmanager import Screen, ScreenManager +from kivy import require + +# This example uses features introduced in Kivy 1.8.0, namely being able +# to load custom json files from the app folder. +require("1.8.0") + +Builder.load_string(''' +: + displayLabel: displayLabel + kbContainer: kbContainer + BoxLayout: + orientation: 'vertical' + Label: + size_hint_y: 0.15 + text: "Available Keyboard Layouts" + BoxLayout: + id: kbContainer + size_hint_y: 0.2 + orientation: "horizontal" + padding: 10 + Label: + id: displayLabel + size_hint_y: 0.15 + markup: True + text: "[b]Key pressed[/b] - None" + halign: "center" + Button: + text: "Back" + size_hint_y: 0.1 + on_release: root.manager.current = "mode" + Widget: + # Just a space taker to allow for the popup keyboard + size_hint_y: 0.5 + +: + center_label: center_label + mode_spinner: mode_spinner + FloatLayout: + BoxLayout: + orientation: "vertical" + size_hint: 0.8, 0.8 + pos_hint: {"x": 0.1, "y": 0.1} + padding: "5sp" + spacing: "5sp" + Label: + canvas: + Color: + rgba: 0, 0, 1, 0.3 + Rectangle: + pos: self.pos + size: self.size + + text: "Custom Keyboard Demo" + size_hint_y: 0.1 + Label: + id: center_label + markup: True + size_hint_y: 0.6 + BoxLayout: + orientation: "horizontal" + size_hint_y: 0.1 + padding: "5sp" + Widget: + size_hint_x: 0.2 + Label: + text: "Current keyboard mode :" + Spinner: + id: mode_spinner + values: "''", "'dock'", "'system'", "'systemanddock'",\ + "'systemandmulti'" + Button: + text: "Set" + on_release: root.set_mode(mode_spinner.text) + Widget: + size_hint_x: 0.2 + Widget: + size_hint_y: 0.1 + BoxLayout: + orientation: "horizontal" + size_hint_y: 0.1 + Button: + text: "Exit" + on_release: exit() + Button: + text: "Continue" + on_release: root.next() + +''') + + +class ModeScreen(Screen): + """ + Present the option to change keyboard mode and warn of system-wide + consequences. + """ + center_label = ObjectProperty() + mode_spinner = ObjectProperty() + + keyboard_mode = "" + + def on_pre_enter(self, *args): + """ Detect the current keyboard mode and set the text of the main + label accordingly. """ + + self.keyboard_mode = Config.get("kivy", "keyboard_mode") + self.mode_spinner.text = "'{0}'".format(self.keyboard_mode) + + p1 = "Current keyboard mode: '{0}'\n\n".format(self.keyboard_mode) + if self.keyboard_mode in ['dock', 'system', 'systemanddock']: + p2 = "You have the right setting to use this demo.\n\n" + else: + p2 = "You need the keyboard mode to 'dock', 'system' or '"\ + "'systemanddock'(below)\n in order to "\ + "use custom onscreen keyboards.\n\n" + + p3 = "[b][color=#ff0000]Warning:[/color][/b] This is a system-wide " \ + "setting and will affect all Kivy apps. If you change the\n" \ + " keyboard mode, please use this app" \ + " to reset this value to its original one." + + self.center_label.text = "".join([p1, p2, p3]) + + def set_mode(self, mode): + """ Sets the keyboard mode to the one specified """ + Config.set("kivy", "keyboard_mode", mode.replace("'", "")) + Config.write() + self.center_label.text = "Please restart the application for this\n" \ + "setting to take effect." + + def next(self): + """ Continue to the main screen """ + self.manager.current = "keyboard" + + +class KeyboardScreen(Screen): + """ + Screen containing all the available keyboard layouts. Clicking the buttons + switches to these layouts. + """ + displayLabel = ObjectProperty() + kbContainer = ObjectProperty() + + def __init__(self, **kwargs): + super(KeyboardScreen, self).__init__(**kwargs) + self._add_keyboards() + self._keyboard = None + + def _add_keyboards(self): + """ Add a buttons for each available keyboard layout. When clicked, + the buttons will change the keyboard layout to the one selected. """ + layouts = list(VKeyboard().available_layouts.keys()) + # Add the file in our app directory, the .json extension is required. + layouts.append("numeric.json") + for key in layouts: + self.kbContainer.add_widget( + Button( + text=key, + on_release=partial(self.set_layout, key))) + + def set_layout(self, layout, button): + """ Change the keyboard layout to the one specified by *layout*. """ + kb = Window.request_keyboard( + self._keyboard_close, self) + if kb.widget: + # If the current configuration supports Virtual Keyboards, this + # widget will be a kivy.uix.vkeyboard.VKeyboard instance. + self._keyboard = kb.widget + self._keyboard.layout = layout + else: + self._keyboard = kb + + self._keyboard.bind(on_key_down=self.key_down, + on_key_up=self.key_up) + + def _keyboard_close(self, *args): + """ The active keyboard is being closed. """ + if self._keyboard: + self._keyboard.unbind(on_key_down=self.key_down) + self._keyboard.unbind(on_key_up=self.key_up) + self._keyboard = None + + def key_down(self, keyboard, keycode, text, modifiers): + """ The callback function that catches keyboard events. """ + self.displayLabel.text = u"Key pressed - {0}".format(text) + + # def key_up(self, keyboard, keycode): + def key_up(self, keyboard, keycode, *args): + """ The callback function that catches keyboard events. """ + # system keyboard keycode: (122, 'z') + # dock keyboard keycode: 'z' + if isinstance(keycode, tuple): + keycode = keycode[1] + self.displayLabel.text += u" (up {0})".format(keycode) + + +class KeyboardDemo(App): + sm = None # The root screen manager + + def build(self): + self.sm = ScreenManager() + self.sm.add_widget(ModeScreen(name="mode")) + self.sm.add_widget(KeyboardScreen(name="keyboard")) + self.sm.current = "mode" + return self.sm + + +if __name__ == "__main__": + KeyboardDemo().run() diff --git a/freechat-client/share/kivy-examples/keyboard/numeric.json b/freechat-client/share/kivy-examples/keyboard/numeric.json new file mode 100755 index 0000000..56ef4b3 --- /dev/null +++ b/freechat-client/share/kivy-examples/keyboard/numeric.json @@ -0,0 +1,38 @@ +{ +"title" : "Numeric", +"description" : "A numeric keypad", +"cols" : 3, +"rows": 4, +"normal_1": [ +["7", "7", "7", 1], +["8", "8", "8", 1], +["9", "9", "9", 1]], +"normal_2": [ +["4", "4", "4", 1], +["5", "5", "5", 1], +["6", "6", "6", 1]], +"normal_3": [ +["1", "1", "1", 1], +["2", "2", "2", 1], +["3", "3", "3", 1]], +"normal_4": [ +["0", "0", "0", 1], +[".", ".", ".", 1], +["\u232b", null, "backspace", 1]], +"shift_1": [ +["7", "7", "7", 1], +["8", "8", "8", 1], +["9", "9", "9", 1]], +"shift_2": [ +["4", "4", "4", 1], +["5", "5", "5", 1], +["6", "6", "6", 1]], +"shift_3": [ +["1", "1", "1", 1], +["2", "2", "2", 1], +["3", "3", "3", 1]], +"shift_4": [ +["0", "0", "0", 1], +[".", ".", ".", 1], +["\u232b", null, "backspace", 1]] +} \ No newline at end of file diff --git a/freechat-client/share/kivy-examples/kinect/README.txt b/freechat-client/share/kivy-examples/kinect/README.txt new file mode 100644 index 0000000..b949efe --- /dev/null +++ b/freechat-client/share/kivy-examples/kinect/README.txt @@ -0,0 +1,13 @@ +Kinect Viewer +============= + +You must have libfreenect installed on your system to make it work. + +How it works +------------ + +1. The viewer gets the depth value from freenect. +2. Depths are multiplied by 32 to use the full range of 16 bits. +3. Depths are uploaded into a "luminance" texture. +4. We use a shader for mapping the depth to a special color. + diff --git a/freechat-client/share/kivy-examples/kinect/__pycache__/kinectviewer.cpython-37.pyc b/freechat-client/share/kivy-examples/kinect/__pycache__/kinectviewer.cpython-37.pyc new file mode 100644 index 0000000..ba08902 Binary files /dev/null and b/freechat-client/share/kivy-examples/kinect/__pycache__/kinectviewer.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/kinect/kinectviewer.py b/freechat-client/share/kivy-examples/kinect/kinectviewer.py new file mode 100644 index 0000000..b79cab7 --- /dev/null +++ b/freechat-client/share/kivy-examples/kinect/kinectviewer.py @@ -0,0 +1,283 @@ +import freenect +from time import sleep +from threading import Thread +from collections import deque +from kivy.app import App +from kivy.clock import Clock +from kivy.properties import NumericProperty, StringProperty +from kivy.graphics import RenderContext, Color, Rectangle +from kivy.graphics.texture import Texture +from kivy.core.window import Window +from kivy.uix.widget import Widget +from kivy.uix.slider import Slider +from kivy.uix.boxlayout import BoxLayout + + +fragment_header = ''' +#ifdef GL_ES + precision highp float; +#endif + +/* Outputs from the vertex shader */ +varying vec4 frag_color; +varying vec2 tex_coord0; + +/* uniform texture samplers */ +uniform sampler2D texture0; + +/* custom input */ +uniform float depth_range; +uniform vec2 size; +''' + +hsv_func = ''' +vec3 HSVtoRGB(vec3 color) { + float f,p,q,t, hueRound; + int hueIndex; + float hue, saturation, v; + vec3 result; + + /* just for clarity */ + hue = color.r; + saturation = color.g; + v = color.b; + + hueRound = floor(hue * 6.0); + hueIndex = mod(int(hueRound), 6.); + f = (hue * 6.0) - hueRound; + p = v * (1.0 - saturation); + q = v * (1.0 - f*saturation); + t = v * (1.0 - (1.0 - f)*saturation); + + switch(hueIndex) { + case 0: + result = vec3(v,t,p); + break; + case 1: + result = vec3(q,v,p); + break; + case 2: + result = vec3(p,v,t); + break; + case 3: + result = vec3(p,q,v); + break; + case 4: + result = vec3(t,p,v); + break; + case 5: + result = vec3(v,p,q); + break; + } + return result; +} +''' + +rgb_kinect = fragment_header + ''' +void main (void) { + float value = texture2D(texture0, tex_coord0).r; + value = mod(value * depth_range, 1.); + vec3 col = vec3(0., 0., 0.); + if ( value <= 0.33 ) + col.r = clamp(value, 0., 0.33) * 3.; + if ( value <= 0.66 ) + col.g = clamp(value - 0.33, 0., 0.33) * 3.; + col.b = clamp(value - 0.66, 0., 0.33) * 3.; + gl_FragColor = vec4(col, 1.); +} +''' + +points_kinect = fragment_header + hsv_func + ''' +void main (void) { + // threshold used to reduce the depth (better result) + const int th = 5; + + // size of a square + int square = floor(depth_range); + + // number of square on the display + vec2 count = size / square; + + // current position of the square + vec2 pos = floor(tex_coord0.xy * count) / count; + + // texture step to pass to another square + vec2 step = 1 / count; + + // texture step to pass to another pixel + vec2 pxstep = 1 / size; + + // center of the square + vec2 center = pos + step / 2.; + + // calculate average of every pixels in the square + float s = 0, x, y; + for (x = 0; x < square; x++) { + for (y = 0; y < square; y++) { + s += texture2D(texture0, pos + pxstep * vec2(x,y)).r; + } + } + float v = s / (square * square); + + // threshold the value + float dr = th / 10.; + v = min(v, dr) / dr; + + // calculate the distance between the center of the square and current + // pixel; display the pixel only if the distance is inside the circle + float vdist = length(abs(tex_coord0 - center) * size / square); + float value = 1 - v; + if ( vdist < value ) { + vec3 col = HSVtoRGB(vec3(value, 1., 1.)); + gl_FragColor = vec4(col, 1); + } +} +''' +hsv_kinect = fragment_header + hsv_func + ''' +void main (void) { + float value = texture2D(texture0, tex_coord0).r; + value = mod(value * depth_range, 1.); + vec3 col = HSVtoRGB(vec3(value, 1., 1.)); + gl_FragColor = vec4(col, 1.); +} +''' + + +class KinectDepth(Thread): + + def __init__(self, *largs, **kwargs): + super(KinectDepth, self).__init__(*largs, **kwargs) + self.daemon = True + self.queue = deque() + self.quit = False + self.index = 0 + + def run(self): + q = self.queue + while not self.quit: + depths = freenect.sync_get_depth(index=self.index) + if depths is None: + sleep(2) + continue + q.appendleft(depths) + + def pop(self): + return self.queue.pop() + + +class KinectViewer(Widget): + + depth_range = NumericProperty(7.7) + + shader = StringProperty("rgb") + + index = NumericProperty(0) + + def __init__(self, **kwargs): + # change the default canvas to RenderContext, we can change the shader + self.canvas = RenderContext() + self.canvas.shader.fs = hsv_kinect + + # add kinect depth provider, and start the thread + self.kinect = KinectDepth() + self.kinect.start() + + # parent init + super(KinectViewer, self).__init__(**kwargs) + + # allocate texture for pushing depth + self.texture = Texture.create( + size=(640, 480), colorfmt='luminance', bufferfmt='ushort') + self.texture.flip_vertical() + + # create default canvas element + with self.canvas: + Color(1, 1, 1) + Rectangle(size=Window.size, texture=self.texture) + + # add a little clock to update our glsl + Clock.schedule_interval(self.update_transformation, 0) + + def on_index(self, instance, value): + self.kinect.index = value + + def on_shader(self, instance, value): + if value == 'rgb': + self.canvas.shader.fs = rgb_kinect + elif value == 'hsv': + self.canvas.shader.fs = hsv_kinect + elif value == 'points': + self.canvas.shader.fs = points_kinect + + def update_transformation(self, *largs): + # update projection mat and uvsize + self.canvas['projection_mat'] = Window.render_context['projection_mat'] + self.canvas['depth_range'] = self.depth_range + self.canvas['size'] = list(map(float, self.size)) + try: + value = self.kinect.pop() + except: + return + f = value[0].astype('ushort') * 32 + self.texture.blit_buffer( + f.tostring(), colorfmt='luminance', bufferfmt='ushort') + self.canvas.ask_update() + + +class KinectViewerApp(App): + + def build(self): + root = BoxLayout(orientation='vertical') + + self.viewer = viewer = KinectViewer( + index=self.config.getint('kinect', 'index'), + shader=self.config.get('shader', 'theme')) + root.add_widget(viewer) + + toolbar = BoxLayout(size_hint=(1, None), height=50) + root.add_widget(toolbar) + + slider = Slider(min=1., max=32., value=1.) + + def update_depth_range(instance, value): + viewer.depth_range = value + + slider.bind(value=update_depth_range) + toolbar.add_widget(slider) + + return root + + def build_config(self, config): + config.add_section('kinect') + config.set('kinect', 'index', '0') + config.add_section('shader') + config.set('shader', 'theme', 'rgb') + + def build_settings(self, settings): + settings.add_json_panel('Kinect Viewer', self.config, data='''[ + { "type": "title", "title": "Kinect" }, + { "type": "numeric", "title": "Index", + "desc": "Kinect index, from 0 to X", + "section": "kinect", "key": "index" }, + { "type": "title", "title": "Shaders" }, + { "type": "options", "title": "Theme", + "desc": "Shader to use for a specific visualization", + "section": "shader", "key": "theme", + "options": ["rgb", "hsv", "points"]} + ]''') + + def on_config_change(self, config, section, key, value): + if config is not self.config: + return + token = (section, key) + if token == ('kinect', 'index'): + self.viewer.index = int(value) + elif token == ('shader', 'theme'): + if value == 'rgb': + self.viewer.canvas.shader.fs = rgb_kinect + elif value == 'hsv': + self.viewer.shader = value + + +if __name__ == '__main__': + KinectViewerApp().run() diff --git a/freechat-client/share/kivy-examples/kv/__pycache__/builder_template.cpython-37.pyc b/freechat-client/share/kivy-examples/kv/__pycache__/builder_template.cpython-37.pyc new file mode 100644 index 0000000..82007d7 Binary files /dev/null and b/freechat-client/share/kivy-examples/kv/__pycache__/builder_template.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/kv/__pycache__/kvrun.cpython-37.pyc b/freechat-client/share/kivy-examples/kv/__pycache__/kvrun.cpython-37.pyc new file mode 100644 index 0000000..866cc3f Binary files /dev/null and b/freechat-client/share/kivy-examples/kv/__pycache__/kvrun.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/kv/app_button.kv b/freechat-client/share/kivy-examples/kv/app_button.kv new file mode 100644 index 0000000..c6c5d7d --- /dev/null +++ b/freechat-client/share/kivy-examples/kv/app_button.kv @@ -0,0 +1,9 @@ +#:kivy 1.0 + +Widget: + Button: + text: "Hello World" + + Button: + text: "I'm another label" + pos: (200, 200) diff --git a/freechat-client/share/kivy-examples/kv/app_camera.kv b/freechat-client/share/kivy-examples/kv/app_camera.kv new file mode 100644 index 0000000..6d784c0 --- /dev/null +++ b/freechat-client/share/kivy-examples/kv/app_camera.kv @@ -0,0 +1,25 @@ +Camera: + canvas: + Color: + rgb: (1, 1, 1) + Rectangle: + texture: self.texture + size: (320, 240) + Color: + rgb: (0.5, 0, 1) + Rectangle: + texture: self.texture + pos: (320, 0) + size: (320, 240) + Color: + rgb: (0, 1, 0) + Rectangle: + texture: self.texture + pos: (320, 240) + size: (320, 240) + Color: + rgb: (1, 0, 0) + Rectangle: + texture: self.texture + pos: (0, 240) + size: (320, 240) diff --git a/freechat-client/share/kivy-examples/kv/app_fbo.kv b/freechat-client/share/kivy-examples/kv/app_fbo.kv new file mode 100644 index 0000000..508ec5a --- /dev/null +++ b/freechat-client/share/kivy-examples/kv/app_fbo.kv @@ -0,0 +1,11 @@ +#:kivy 1.0 + +Widget: + canvas: + Fbo: + size: (200, 200) + Color: + rgba: (0.7, 0.3, 0.5, 0.7) + Rectangle: + size: (200, 200) + pos: (200, 200) diff --git a/freechat-client/share/kivy-examples/kv/app_layout.kv b/freechat-client/share/kivy-examples/kv/app_layout.kv new file mode 100644 index 0000000..629c518 --- /dev/null +++ b/freechat-client/share/kivy-examples/kv/app_layout.kv @@ -0,0 +1,23 @@ +BoxLayout: + Button: + id: bswitch + + BoxLayout: + + orientation: 'vertical' if bswitch.state == 'down' else 'horizontal' + + Button: + id: btn1 + text: 'Button 1' + + Button: + text: btn1.state + + Button: + text: 'Button 3' + + Button: + text: 'Button 4' + + Button: + text: 'Button 5' diff --git a/freechat-client/share/kivy-examples/kv/app_logo.kv b/freechat-client/share/kivy-examples/kv/app_logo.kv new file mode 100644 index 0000000..5a223b2 --- /dev/null +++ b/freechat-client/share/kivy-examples/kv/app_logo.kv @@ -0,0 +1,36 @@ +Widget: + Video: + id: myvideo + source: '../widgets/cityCC0.mpg' + play: mybutton.state == 'down' + canvas: + Color: + rgb: (1, 1, 1) + BorderImage: + texture: self.texture + size: self.texture_size + + Image: + source: 'kivy.jpg' + canvas: + PushMatrix: + Rotate: + angle: 1 + BorderImage: + border: 250, 250, 250, 250 + texture: self.texture + size: self.texture_size + PopMatrix: + + Button: + id: mybutton + text: 'Push me' + pos: 100, 100 + + Slider: + width: myvideo.width + height: 25 + min: 0 + max: myvideo.duration + value: myvideo.position + pos: myvideo.pos diff --git a/freechat-client/share/kivy-examples/kv/app_scatter.kv b/freechat-client/share/kivy-examples/kv/app_scatter.kv new file mode 100644 index 0000000..52e52ac --- /dev/null +++ b/freechat-client/share/kivy-examples/kv/app_scatter.kv @@ -0,0 +1,6 @@ +Widget: + Scatter: + size: image.texture_size + Image: + id: image + source: 'kivy.jpg' diff --git a/freechat-client/share/kivy-examples/kv/app_stencil.kv b/freechat-client/share/kivy-examples/kv/app_stencil.kv new file mode 100644 index 0000000..cbc8c89 --- /dev/null +++ b/freechat-client/share/kivy-examples/kv/app_stencil.kv @@ -0,0 +1,27 @@ +Widget: + canvas: + + StencilPush + + # create a rectangle mask, from pos 100, 100, with a 100, 100 size. + Rectangle: + pos: 100, 100 + size: 100, 100 + + StencilUse + + # we want to show a big green rectangle, however, the previous stencil + # mask will crop us :) + Color: + rgb: 0, 1, 0 + Rectangle: + size: 900, 900 + + StencilUnUse + + # Remove the mask previously set + Rectangle: + pos: 100, 100 + size: 100, 100 + + StencilPop diff --git a/freechat-client/share/kivy-examples/kv/app_video.kv b/freechat-client/share/kivy-examples/kv/app_video.kv new file mode 100644 index 0000000..a358019 --- /dev/null +++ b/freechat-client/share/kivy-examples/kv/app_video.kv @@ -0,0 +1,42 @@ +BoxLayout: + + orientation: 'vertical' + spacing: 5 + padding: 5 + + Video: + id: myvideo + source: '../widgets/cityCC0.mpg' + allow_stretch: True + on_eos: self.play = True; print('woot we are looping!') + + BoxLayout: + size_hint_y: None + height: 30 + + Label: + id: mylabel + text: str(myvideo.position) + + Slider: + value: myvideo.position + max: myvideo.duration + on_value: print(args[1]) + + BoxLayout: + size_hint_y: None + height: 50 + spacing: 5 + + ToggleButton: + group: 'video' + text: 'Play' + state: 'down' if myvideo.play else 'normal' + on_press: myvideo.play = True + + ToggleButton: + group: 'video' + text: 'Stop' + state: 'down' if not myvideo.play else 'normal' + on_press: myvideo.play = False + diff --git a/freechat-client/share/kivy-examples/kv/builder_template.py b/freechat-client/share/kivy-examples/kv/builder_template.py new file mode 100644 index 0000000..56b7adb --- /dev/null +++ b/freechat-client/share/kivy-examples/kv/builder_template.py @@ -0,0 +1,28 @@ +from kivy.lang import Builder +from kivy.app import App +from kivy.uix.boxlayout import BoxLayout + +Builder.load_string(''' +[BlehItem@BoxLayout]: + orientation: 'vertical' + Label: + text: str(ctx.idx) + Button: + text: ctx.word +''') + + +class BlehApp(App): + + def build(self): + root = BoxLayout() + for idx, word in enumerate(('Hello', 'World')): + wid = Builder.template('BlehItem', **{ + 'idx': idx, 'word': word, + }) + root.add_widget(wid) + return root + + +if __name__ == '__main__': + BlehApp().run() diff --git a/freechat-client/share/kivy-examples/kv/ids/id_in_kv/__pycache__/id_in_kv.cpython-37.pyc b/freechat-client/share/kivy-examples/kv/ids/id_in_kv/__pycache__/id_in_kv.cpython-37.pyc new file mode 100644 index 0000000..dfc985f Binary files /dev/null and b/freechat-client/share/kivy-examples/kv/ids/id_in_kv/__pycache__/id_in_kv.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/kv/ids/id_in_kv/id_in_kv.py b/freechat-client/share/kivy-examples/kv/ids/id_in_kv/id_in_kv.py new file mode 100644 index 0000000..60251b0 --- /dev/null +++ b/freechat-client/share/kivy-examples/kv/ids/id_in_kv/id_in_kv.py @@ -0,0 +1,20 @@ +''' +The use of id in KV +=================== + +This small example shows how to refer from one widget +to another within KV. +''' + +import kivy +kivy.require('1.8.0') + +from kivy.app import App + + +class TestApp(App): + pass + + +if __name__ == '__main__': + TestApp().run() diff --git a/freechat-client/share/kivy-examples/kv/ids/id_in_kv/test.kv b/freechat-client/share/kivy-examples/kv/ids/id_in_kv/test.kv new file mode 100644 index 0000000..ef6a14b --- /dev/null +++ b/freechat-client/share/kivy-examples/kv/ids/id_in_kv/test.kv @@ -0,0 +1,11 @@ +#:kivy 1.8.0 + +BoxLayout: + orientation: 'vertical' + TextInput: + # setting the id of the widget + id: my_id + text: 'The text of the label is set within kivy' + Label: + # showing the text of the textinput by referring on the id + text: my_id.text diff --git a/freechat-client/share/kivy-examples/kv/ids/kv_and_py/__pycache__/kv_and_py.cpython-37.pyc b/freechat-client/share/kivy-examples/kv/ids/kv_and_py/__pycache__/kv_and_py.cpython-37.pyc new file mode 100644 index 0000000..03c9e32 Binary files /dev/null and b/freechat-client/share/kivy-examples/kv/ids/kv_and_py/__pycache__/kv_and_py.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/kv/ids/kv_and_py/kv_and_py.py b/freechat-client/share/kivy-examples/kv/ids/kv_and_py/kv_and_py.py new file mode 100644 index 0000000..927cead --- /dev/null +++ b/freechat-client/share/kivy-examples/kv/ids/kv_and_py/kv_and_py.py @@ -0,0 +1,34 @@ +''' +Referring on ids from Python +============================= + +This example shows how to refer to an id from a Python file. +''' + +import kivy +kivy.require('1.8.0') + +from kivy.app import App +from kivy.uix.boxlayout import BoxLayout + + +class RootWidget(BoxLayout): + + def first_function(self, status): + # print out the given parameter + print(status) + # check the status of the switch by referring on the id + if self.ids.my_switch.active is True: + # set the text of the label by referring on the id + self.ids.my_label.text = 'Switch is ON' + else: + # set the text of the label by referring on the id + self.ids.my_label.text = 'Switch is OFF' + + +class TestApp(App): + pass + + +if __name__ == '__main__': + TestApp().run() diff --git a/freechat-client/share/kivy-examples/kv/ids/kv_and_py/test.kv b/freechat-client/share/kivy-examples/kv/ids/kv_and_py/test.kv new file mode 100644 index 0000000..a182916 --- /dev/null +++ b/freechat-client/share/kivy-examples/kv/ids/kv_and_py/test.kv @@ -0,0 +1,11 @@ +#:kivy 1.8.0 + +RootWidget: + BoxLayout: + orientation: 'vertical' + Switch: + id: my_switch + on_active: root.first_function(self.active) + Label: + id: my_label + text: 'This text will be changed by the python file' diff --git a/freechat-client/share/kivy-examples/kv/kivy.jpg b/freechat-client/share/kivy-examples/kv/kivy.jpg new file mode 100644 index 0000000..12ed7e3 Binary files /dev/null and b/freechat-client/share/kivy-examples/kv/kivy.jpg differ diff --git a/freechat-client/share/kivy-examples/kv/kvrun.py b/freechat-client/share/kivy-examples/kv/kvrun.py new file mode 100644 index 0000000..97c139a --- /dev/null +++ b/freechat-client/share/kivy-examples/kv/kvrun.py @@ -0,0 +1,38 @@ +from kivy.app import App +from kivy.clock import Clock +from kivy.lang import Builder +from kivy.core.window import Window + + +class KvApp(App): + def __init__(self, filename, **kwargs): + self.filename = filename + super(KvApp, self).__init__(**kwargs) + + def _print_fps(self, *largs): + print('FPS: %2.4f (real draw: %d)' % ( + Clock.get_fps(), Clock.get_rfps())) + + def _reload_keypress(self, instance, code, *largs): + if code != 286: + return + for child in Window.children[:]: + Window.remove_widget(child) + root = Builder.load_file(self.filename) + Window.add_widget(root) + + def build(self): + Clock.schedule_interval(self._print_fps, 1) + Window.bind(on_keyboard=self._reload_keypress) + return Builder.load_file(self.filename) + + +if __name__ == '__main__': + import sys + import os + + if len(sys.argv) < 2: + print('Usage: %s filename.kv' % os.path.basename(sys.argv[0])) + sys.exit(1) + + KvApp(filename=sys.argv[1]).run() diff --git a/freechat-client/share/kivy-examples/miscellaneous/__pycache__/clipboard.cpython-37.pyc b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/clipboard.cpython-37.pyc new file mode 100644 index 0000000..6116e75 Binary files /dev/null and b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/clipboard.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/miscellaneous/__pycache__/imagesave.cpython-37.pyc b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/imagesave.cpython-37.pyc new file mode 100644 index 0000000..7eb26d7 Binary files /dev/null and b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/imagesave.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/miscellaneous/__pycache__/joystick.cpython-37.pyc b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/joystick.cpython-37.pyc new file mode 100644 index 0000000..e196f00 Binary files /dev/null and b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/joystick.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/miscellaneous/__pycache__/multiple_dropfile.cpython-37.pyc b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/multiple_dropfile.cpython-37.pyc new file mode 100644 index 0000000..3c9faa7 Binary files /dev/null and b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/multiple_dropfile.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/miscellaneous/__pycache__/on_textedit_event.cpython-37.pyc b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/on_textedit_event.cpython-37.pyc new file mode 100644 index 0000000..6db0381 Binary files /dev/null and b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/on_textedit_event.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/miscellaneous/__pycache__/shapecollisions.cpython-37.pyc b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/shapecollisions.cpython-37.pyc new file mode 100644 index 0000000..ba3d380 Binary files /dev/null and b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/shapecollisions.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/miscellaneous/__pycache__/shapedwindow.cpython-37.pyc b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/shapedwindow.cpython-37.pyc new file mode 100644 index 0000000..26fb7ab Binary files /dev/null and b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/shapedwindow.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/miscellaneous/__pycache__/two_panes.cpython-37.pyc b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/two_panes.cpython-37.pyc new file mode 100644 index 0000000..08932b0 Binary files /dev/null and b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/two_panes.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/miscellaneous/__pycache__/urlrequest.cpython-37.pyc b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/urlrequest.cpython-37.pyc new file mode 100644 index 0000000..3edaf0e Binary files /dev/null and b/freechat-client/share/kivy-examples/miscellaneous/__pycache__/urlrequest.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/miscellaneous/clipboard.py b/freechat-client/share/kivy-examples/miscellaneous/clipboard.py new file mode 100644 index 0000000..9dee424 --- /dev/null +++ b/freechat-client/share/kivy-examples/miscellaneous/clipboard.py @@ -0,0 +1,63 @@ +from kivy.lang import Builder +from kivy.uix.label import Label +from kivy.base import runTouchApp +from kivy.uix.boxlayout import BoxLayout + +import os + +Builder.load_string(''' +#:import Clipboard kivy.core.clipboard.Clipboard +: + orientation: 'vertical' + GridLayout: + cols: 3 + size_hint_y: None + height: self.minimum_height + Button: + text: 'Paste raw' + size_hint_y: None + height: 60 + on_release: root.make_labels(Clipboard.paste()) + + Button: + text: 'Paste & format' + size_hint_y: None + height: 60 + on_release: root.make_pretty_labels(Clipboard.paste()) + + Button: + text: 'Remove widgets' + size_hint_y: None + height: 60 + on_release: container.clear_widgets() + + ScrollView: + GridLayout: + cols: 1 + id: container + size_hint_y: None + height: self.minimum_height +''') + + +class Clip(BoxLayout): + def make_labels(self, values): + """Creates widgets from raw clipboard i.e. for each character in the + list that is provided by Clipboard.paste() + """ + print(repr(values)) + for value in values: + label = Label(text=value, size_hint_y=None, height=30) + self.ids.container.add_widget(label) + + def make_pretty_labels(self, values): + """Creates widgets from a list of values made by splitting clipboard + by the default OS line separator. Useful when copying columns of data. + """ + print(repr(values)) + for value in values.split(os.linesep): + label = Label(text=value, size_hint_y=None, height=30) + self.ids.container.add_widget(label) + + +runTouchApp(Clip()) diff --git a/freechat-client/share/kivy-examples/miscellaneous/imagesave.py b/freechat-client/share/kivy-examples/miscellaneous/imagesave.py new file mode 100644 index 0000000..f3a4d91 --- /dev/null +++ b/freechat-client/share/kivy-examples/miscellaneous/imagesave.py @@ -0,0 +1,14 @@ +# save an image into bytesio + +from kivy.core.image import Image +from io import BytesIO + +img = Image.load("data/logo/kivy-icon-512.png") + +bio = BytesIO() +ret = img.save(bio, fmt="png") +print("len=", len(bio.read())) + +bio = BytesIO() +ret = img.save(bio, fmt="jpg") +print("len=", len(bio.read())) diff --git a/freechat-client/share/kivy-examples/miscellaneous/joystick.py b/freechat-client/share/kivy-examples/miscellaneous/joystick.py new file mode 100644 index 0000000..1cea874 --- /dev/null +++ b/freechat-client/share/kivy-examples/miscellaneous/joystick.py @@ -0,0 +1,83 @@ +# Joystick / Gamepad example +# STOP_FIRE from https://wiki.libsdl.org/SDL_JoyAxisEvent + +from kivy.app import App +from kivy.clock import Clock +from kivy.uix.widget import Widget +from kivy.core.window import Window +from kivy.properties import ObjectProperty, ListProperty + + +class Listener(Widget): + # fire / trigger axis + FIRE = (2, 5) + STOP_FIRE = -32767 + + # min value for user to actually trigger axis + OFFSET = 15000 + + # current values + event instance + VALUES = ListProperty([]) + HOLD = ObjectProperty(None) + + def __init__(self, **kwargs): + super(Listener, self).__init__(**kwargs) + + # get joystick events first + Window.bind(on_joy_hat=self.on_joy_hat) + Window.bind(on_joy_ball=self.on_joy_ball) + Window.bind(on_joy_axis=self.on_joy_axis) + Window.bind(on_joy_button_up=self.on_joy_button_up) + Window.bind(on_joy_button_down=self.on_joy_button_down) + + # show values in console + def print_values(self, *args): + print(self.VALUES) + + def joy_motion(self, event, id, axis, value): + # HAT first, returns max values + if isinstance(value, tuple): + if not value[0] and not value[1]: + Clock.unschedule(self.HOLD) + else: + self.VALUES = [event, id, axis, value] + self.HOLD = Clock.schedule_interval(self.print_values, 0) + return + + # unschedule if at zero or at minimum (FIRE) + if axis in self.FIRE and value < self.STOP_FIRE: + Clock.unschedule(self.HOLD) + return + elif abs(value) < self.OFFSET or self.HOLD: + Clock.unschedule(self.HOLD) + + # schedule if over OFFSET (to prevent accidental event with low value) + if (axis in self.FIRE and value > self.STOP_FIRE or + axis not in self.FIRE and abs(value) >= self.OFFSET): + self.VALUES = [event, id, axis, value] + self.HOLD = Clock.schedule_interval(self.print_values, 0) + + # replace window instance with identifier + def on_joy_axis(self, win, stickid, axisid, value): + self.joy_motion('axis', stickid, axisid, value) + + def on_joy_ball(self, win, stickid, ballid, xvalue, yvalue): + self.joy_motion('ball', stickid, ballid, (xvalue, yvalue)) + + def on_joy_hat(self, win, stickid, hatid, value): + self.joy_motion('hat', stickid, hatid, value) + + def on_joy_button_down(self, win, stickid, buttonid): + print('button_down', stickid, buttonid) + + def on_joy_button_up(self, win, stickid, buttonid): + print('button_up', stickid, buttonid) + + +class JoystickApp(App): + def build(self): + return Listener() + + +if __name__ == '__main__': + JoystickApp().run() diff --git a/freechat-client/share/kivy-examples/miscellaneous/multiple_dropfile.py b/freechat-client/share/kivy-examples/miscellaneous/multiple_dropfile.py new file mode 100644 index 0000000..930f3c9 --- /dev/null +++ b/freechat-client/share/kivy-examples/miscellaneous/multiple_dropfile.py @@ -0,0 +1,51 @@ +from kivy.app import App +from kivy.uix.button import Button +from kivy.core.window import Window +from kivy.uix.boxlayout import BoxLayout + + +class DropFile(Button): + def __init__(self, **kwargs): + super(DropFile, self).__init__(**kwargs) + + # get app instance to add function from widget + app = App.get_running_app() + + # add function to the list + app.drops.append(self.on_dropfile) + + def on_dropfile(self, widget, filename): + # a function catching a dropped file + # if it's dropped in the widget's area + if self.collide_point(*Window.mouse_pos): + # on_dropfile's filename is bytes (py3) + self.text = filename.decode('utf-8') + + +class DropApp(App): + def build(self): + # set an empty list that will be later populated + # with functions from widgets themselves + self.drops = [] + + # bind handling function to 'on_dropfile' + Window.bind(on_dropfile=self.handledrops) + + box = BoxLayout() + dropleft = DropFile(text='left') + box.add_widget(dropleft) + dropright = DropFile(text='right') + box.add_widget(dropright) + return box + + def handledrops(self, *args): + # this will execute each function from list with arguments from + # Window.on_dropfile + # + # make sure `Window.on_dropfile` works on your system first, + # otherwise the example won't work at all + for func in self.drops: + func(*args) + + +DropApp().run() diff --git a/freechat-client/share/kivy-examples/miscellaneous/on_textedit_event.py b/freechat-client/share/kivy-examples/miscellaneous/on_textedit_event.py new file mode 100644 index 0000000..c361f07 --- /dev/null +++ b/freechat-client/share/kivy-examples/miscellaneous/on_textedit_event.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- + +''' +on_textedit event sample. +''' +from kivy.app import App +from kivy.uix.widget import Widget +from kivy.lang import Builder +from kivy.properties import StringProperty +from kivy.core.text import LabelBase, DEFAULT_FONT +from kivy.uix.textinput import TextInput +from kivy.base import EventLoop + + +class TextInputIME(TextInput): + testtext = StringProperty() + + def __init__(self, **kwargs): + super(TextInputIME, self).__init__(**kwargs) + EventLoop.window.bind(on_textedit=self._on_textedit) + + def _on_textedit(self, window, text): + self.testtext = text + + +class MainWidget(Widget): + text = StringProperty() + + def __init__(self, **kwargs): + super(MainWidget, self).__init__(**kwargs) + self.text = '' + + def confim(self): + self.text = self.ids["text_box"].text + + def changeFont(self): + try: + LabelBase.register(DEFAULT_FONT, self.ids["text_font"].text) + except Exception: + self.ids["text_font"].text = "can't load font." + + +class TextEditTestApp(App): + def __init__(self, **kwargs): + super(TextEditTestApp, self).__init__(**kwargs) + + def build(self): + return MainWidget() + + +if __name__ == '__main__': + Builder.load_string(''' +: + BoxLayout: + orientation: 'vertical' + size: root.size + BoxLayout: + Label: + size_hint_x: 3 + text: "Multi language font file path" + TextInput: + id: text_font + size_hint_x: 5 + Button: + size_hint_x: 2 + text: "Change Font" + on_press: root.changeFont() + BoxLayout: + Label: + size_hint_x: 3 + text: "Text editing by IME" + Label: + size_hint_x: 7 + text:text_box.testtext + canvas.before: + Color: + rgb: 0.5765 ,0.5765 ,0.5843 + Rectangle: + pos: self.pos + size: self.size + BoxLayout: + Label: + size_hint_x: 3 + text: "Enter text ->" + TextInputIME: + id: text_box + size_hint_x: 7 + focus: True + BoxLayout: + Button: + size_hint_x: 3 + text: "Confirm text property" + on_press: root.confim() + Label: + size_hint_x: 7 + text: root.text + canvas.before: + Color: + rgb: 0.5765 ,0.5765 ,0.5843 + Rectangle: + pos: self.pos + size: self.size + ''') + TextEditTestApp().run() diff --git a/freechat-client/share/kivy-examples/miscellaneous/shapecollisions.py b/freechat-client/share/kivy-examples/miscellaneous/shapecollisions.py new file mode 100644 index 0000000..928dc4d --- /dev/null +++ b/freechat-client/share/kivy-examples/miscellaneous/shapecollisions.py @@ -0,0 +1,397 @@ +# This is a simple demo for advanced collisions and mesh creation from a set +# of points. Its purpose is only to give an idea on how to make complex stuff. + +# Check garden.collider for better performance. + +from math import cos, sin, pi, sqrt +from random import random, randint +from itertools import combinations + +from kivy.app import App +from kivy.clock import Clock +from kivy.uix.label import Label +from kivy.uix.widget import Widget +from kivy.core.window import Window +from kivy.graphics import Color, Mesh, Point +from kivy.uix.floatlayout import FloatLayout +from kivy.properties import ( + ListProperty, + StringProperty, + ObjectProperty, + NumericProperty +) + + +# Cloud polygon, 67 vertices + custom origin [150, 50] +cloud_poly = [ + 150, 50, + 109.7597, 112.9600, 115.4326, 113.0853, 120.1966, 111.9883, + 126.0889, 111.9570, 135.0841, 111.9570, 138.5944, 112.5525, + 145.7403, 115.5301, 150.5357, 120.3256, 155.5313, 125.5938, + 160.8438, 130.5000, 165.7813, 132.5000, 171.8125, 132.3438, + 177.5000, 128.4688, 182.1531, 121.4990, 185.1438, 114.0406, + 185.9181, 108.5649, 186.2226, 102.5978, 187.8059, 100.2231, + 193.2257, 100.1622, 197.6712, 101.8671, 202.6647, 104.1809, + 207.1102, 105.8858, 214.2351, 105.0333, 219.3747, 102.8301, + 224.0413, 98.7589, 225.7798, 93.7272, 226.0000, 86.8750, + 222.9375, 81.0625, 218.3508, 76.0867, 209.8301, 70.8090, + 198.7806, 66.1360, 189.7651, 62.2327, 183.6082, 56.6252, + 183.2784, 50.5778, 190.9155, 42.7294, 196.8470, 36.1343, + 197.7339, 29.9272, 195.5720, 23.4430, 191.2500, 15.9803, + 184.0574, 9.5882, 175.8811, 3.9951, 165.7992, 3.4419, + 159.0369, 7.4370, 152.5205, 14.8125, 147.4795, 24.2162, + 142.4385, 29.0103, 137.0287, 30.9771, 127.1560, 27.4818, + 119.1371, 20.0388, 112.1820, 11.3690, 104.6541, 7.1976, + 97.2080, 6.2979, 88.9437, 9.8149, 80.3433, 17.3218, + 76.5924, 26.5452, 78.1678, 37.0432, 83.5068, 47.1104, + 92.8529, 58.3561, 106.3021, 69.2978, 108.9615, 73.9329, + 109.0375, 80.6955, 104.4713, 88.6708, 100.6283, 95.7483, + 100.1226, 101.5114, 102.8532, 107.2745, 105.6850, 110.9144, + 109.7597, 112.9600 +] + + +class BaseShape(Widget): + '''(internal) Base class for moving with touches or calls.''' + + # keep references for offset + _old_pos = ListProperty([0, 0]) + _old_touch = ListProperty([0, 0]) + _new_touch = ListProperty([0, 0]) + + # shape properties + name = StringProperty('') + poly = ListProperty([]) + shape = ObjectProperty() + poly_len = NumericProperty(0) + shape_len = NumericProperty(0) + debug_collider = ObjectProperty() + debug_collider_len = NumericProperty(0) + + def __init__(self, **kwargs): + '''Create a shape with size [100, 100] + and give it a label if it's named. + ''' + super(BaseShape, self).__init__(**kwargs) + self.size_hint = (None, None) + self.add_widget(Label(text=self.name)) + + def move_label(self, x, y, *args): + '''Move label with shape name as the only child.''' + self.children[0].pos = [x, y] + + def move_collider(self, offset_x, offset_y, *args): + '''Move debug collider when the shape moves.''' + points = self.debug_collider.points[:] + + for i in range(0, self.debug_collider_len, 2): + points[i] += offset_x + points[i + 1] += offset_y + self.debug_collider.points = points + + def on_debug_collider(self, instance, value): + '''Recalculate length of collider points' array.''' + self.debug_collider_len = len(value.points) + + def on_poly(self, instance, value): + '''Recalculate length of polygon points' array.''' + self.poly_len = len(value) + + def on_shape(self, instance, value): + '''Recalculate length of Mesh vertices' array.''' + self.shape_len = len(value.vertices) + + def on_pos(self, instance, pos): + '''Move polygon and its Mesh on each position change. + This event is above all and changes positions of the other + children-like components, so that a simple:: + + shape.pos = (100, 200) + + would move everything, not just the widget itself. + ''' + + # position changed by touch + offset_x = self._new_touch[0] - self._old_touch[0] + offset_y = self._new_touch[1] - self._old_touch[1] + + # position changed by call (shape.pos = X) + if not offset_x and not offset_y: + offset_x = pos[0] - self._old_pos[0] + offset_y = pos[1] - self._old_pos[1] + self._old_pos = pos + + # move polygon points by offset + for i in range(0, self.poly_len, 2): + self.poly[i] += offset_x + self.poly[i + 1] += offset_y + + # stick label to bounding box (widget) + if self.name: + self.move_label(*pos) + + # move debug collider if available + if self.debug_collider is not None: + self.move_collider(offset_x, offset_y) + + # return if no Mesh available + if self.shape is None: + return + + # move Mesh vertices by offset + points = self.shape.vertices[:] + for i in range(0, self.shape_len, 2): + points[i] += offset_x + points[i + 1] += offset_y + self.shape.vertices = points + + def on_touch_move(self, touch, *args): + '''Move shape with dragging.''' + + # grab single touch for shape + if touch.grab_current is not self: + return + + # get touches + x, y = touch.pos + new_pos = [x, y] + self._new_touch = new_pos + self._old_touch = [touch.px, touch.py] + + # get offsets, move & trigger on_pos event + offset_x = self._new_touch[0] - self._old_touch[0] + offset_y = self._new_touch[1] - self._old_touch[1] + self.pos = [self.x + offset_x, self.y + offset_y] + + def shape_collide(self, x, y, *args): + '''Point to polygon collision through a list of points.''' + + # ignore if no polygon area is set + poly = self.poly + if not poly: + return False + + n = self.poly_len + inside = False + p1x = poly[0] + p1y = poly[1] + + # compare point pairs via PIP algo, too long, read + # https://en.wikipedia.org/wiki/Point_in_polygon + for i in range(0, n + 2, 2): + p2x = poly[i % n] + p2y = poly[(i + 1) % n] + + if y > min(p1y, p2y) and y <= max(p1y, p2y) and x <= max(p1x, p2x): + if p1y != p2y: + xinters = (y - p1y) * (p2x - p1x) / (p2y - p1y) + p1x + if p1x == p2x or x <= xinters: + inside = not inside + + p1x, p1y = p2x, p2y + return inside + + +class RegularShape(BaseShape): + '''Starting from center and creating edges around for i.e.: + regular triangles, squares, regular pentagons, up to "circle". + ''' + + def __init__(self, edges=3, color=None, **kwargs): + super(RegularShape, self).__init__(**kwargs) + if edges < 3: + raise Exception('Not enough edges! (3+ only)') + + color = color or [random() for i in range(3)] + rad_edge = (pi * 2) / float(edges) + r_x = self.width / 2.0 + r_y = self.height / 2.0 + poly = [] + vertices = [] + for i in range(edges): + # get points within a circle with radius of [r_x, r_y] + x = cos(rad_edge * i) * r_x + self.center_x + y = sin(rad_edge * i) * r_y + self.center_y + poly.extend([x, y]) + + # add UV layout zeros for Mesh, see Mesh docs + vertices.extend([x, y, 0, 0]) + + # draw Mesh shape from generated poly points + with self.canvas: + Color(rgba=(color[0], color[1], color[2], 0.6)) + self.shape = Mesh( + pos=self.pos, + vertices=vertices, + indices=list(range(edges)), + mode='triangle_fan' + ) + self.poly = poly + + def on_touch_down(self, touch, *args): + if self.shape_collide(*touch.pos): + touch.grab(self) + + +class MeshShape(BaseShape): + '''Starting from a custom origin and custom points, draw + a convex Mesh shape with both touch and shape collisions. + + .. note:: + + To get the points, use e.g. Pen tool from your favorite + graphics editor and export it to a human readable format. + ''' + + def __init__(self, color=None, **kwargs): + super(MeshShape, self).__init__(**kwargs) + + color = color or [random() for i in range(3)] + min_x = 10000 + min_y = 10000 + max_x = 0 + max_y = 0 + + # first point has to be the center of the convex shape's mass, + # that's where the triangle fan starts from + poly = [ + 50, 50, 0, 0, 100, 0, 100, 100, 0, 100 + ] if not self.poly else self.poly + + # make the polygon smaller to fit 100x100 bounding box + poly = [round(p / 1.5, 4) for p in poly] + poly_len = len(poly) + + # create list of vertices & get edges of the polygon + vertices = [] + vertices_len = 0 + for i in range(0, poly_len, 2): + min_x = poly[i] if poly[i] < min_x else min_x + min_y = poly[i + 1] if poly[i + 1] < min_y else min_y + max_x = poly[i] if poly[i] > max_x else max_x + max_y = poly[i + 1] if poly[i + 1] > max_y else max_y + + # add UV layout zeros for Mesh + vertices_len += 4 + vertices.extend([poly[i], poly[i + 1], 0, 0]) + + # get center of poly from edges + poly_center_x, poly_center_y = [ + (max_x - min_x) / 2.0, + (max_y - min_y) / 2.0 + ] + + # get distance from the widget's center and push the points to + # the widget's origin, so that min_x and min_y for the poly would + # result in 0 i.e.: points moved as close as possible to [0, 0] + # -> No editor gives poly points moved to the origin directly + dec_x = (self.center_x - poly_center_x) - min_x + dec_y = (self.center_y - poly_center_y) - min_y + + # move polygon points to the bounding box (touch) + for i in range(0, poly_len, 2): + poly[i] += dec_x + poly[i + 1] += dec_y + + # move mesh points to the bounding box (image) + # has to contain the same points as polygon + for i in range(0, vertices_len, 4): + vertices[i] += dec_x + vertices[i + 1] += dec_y + + # draw Mesh shape from generated poly points + with self.canvas: + Color(rgba=(color[0], color[1], color[2], 0.6)) + self.shape = Mesh( + pos=self.pos, + vertices=vertices, + indices=list(range(int(poly_len / 2.0))), + mode='triangle_fan' + ) + # debug polygon points with Line to see the origin point + # and intersections with the other points + # Line(points=poly) + self.poly = poly + + def on_touch_down(self, touch, *args): + if self.shape_collide(*touch.pos): + touch.grab(self) + + +class Collisions(App): + def __init__(self, **kwargs): + super(Collisions, self).__init__(**kwargs) + # register an event for collision + self.register_event_type('on_collision') + + def collision_circles(self, shapes=None, distance=100, debug=False, *args): + '''Simple circle <-> circle collision between the shapes i.e. there's + a simple line between the centers of the two shapes and the collision + is only about measuring distance -> 1+ radii intersections. + ''' + + # get all combinations from all available shapes + if not hasattr(self, 'combins'): + self.combins = list(combinations(shapes, 2)) + + for com in self.combins: + x = (com[0].center_x - com[1].center_x) ** 2 + y = (com[0].center_y - com[1].center_y) ** 2 + if sqrt(x + y) <= distance: + # dispatch a custom event if the objects collide + self.dispatch('on_collision', (com[0], com[1])) + + # draw collider only if debugging + if not debug: + return + + # add circle collider only if the shape doesn't have one + for shape in shapes: + if shape.debug_collider is not None: + continue + + d = distance / 2.0 + cx, cy = shape.center + points = [(cx + d * cos(i), cy + d * sin(i)) for i in range(44)] + points = [p for ps in points for p in ps] + with shape.canvas: + Color(rgba=(0, 1, 0, 1)) + shape.debug_collider = Point(points=points) + + def on_collision(self, pair, *args): + '''Dispatched when objects collide, gives back colliding objects + as a "pair" argument holding their instances. + ''' + print('Collision {} x {}'.format(pair[0].name, pair[1].name)) + + def build(self): + # the environment for all 2D shapes + scene = FloatLayout() + + # list of 2D shapes, starting with regular ones + shapes = [ + RegularShape( + name='Shape {}'.format(x), edges=x + ) for x in range(3, 13) + ] + + shapes.append(MeshShape(name='DefaultMesh')) + shapes.append(MeshShape(name='Cloud', poly=cloud_poly)) + shapes.append(MeshShape( + name='3QuarterCloud', + poly=cloud_poly[:110] + )) + + # move shapes to some random position + for shape in shapes: + shape.pos = [randint(50, i - 50) for i in Window.size] + scene.add_widget(shape) + + # check for simple collisions between the shapes + Clock.schedule_interval( + lambda *t: self.collision_circles(shapes, debug=True), 0.1) + return scene + + +if __name__ == '__main__': + Collisions().run() diff --git a/freechat-client/share/kivy-examples/miscellaneous/shapedwindow.py b/freechat-client/share/kivy-examples/miscellaneous/shapedwindow.py new file mode 100644 index 0000000..ee17e2c --- /dev/null +++ b/freechat-client/share/kivy-examples/miscellaneous/shapedwindow.py @@ -0,0 +1,98 @@ +from kivy.config import Config +Config.set('graphics', 'shaped', 1) + +from kivy.resources import resource_find +default_shape = Config.get('kivy', 'window_shape') +alpha_shape = resource_find('data/logo/kivy-icon-512.png') + +from kivy.app import App +from kivy.lang import Builder +from kivy.core.window import Window +from kivy.uix.boxlayout import BoxLayout +from kivy.properties import ( + BooleanProperty, + StringProperty, + ListProperty, +) + + +Builder.load_string(''' +#:import win kivy.core.window.Window + +: + orientation: 'vertical' + BoxLayout: + Button: + text: 'default_shape' + on_release: app.shape_image = app.default_shape + Button: + text: 'alpha_shape' + on_release: app.shape_image = app.alpha_shape + + BoxLayout: + ToggleButton: + group: 'mode' + text: 'default' + state: 'down' + on_release: win.shape_mode = 'default' + ToggleButton: + group: 'mode' + text: 'binalpha' + on_release: win.shape_mode = 'binalpha' + ToggleButton: + group: 'mode' + text: 'reversebinalpha' + on_release: win.shape_mode = 'reversebinalpha' + ToggleButton: + group: 'mode' + text: 'colorkey' + on_release: win.shape_mode = 'colorkey' + + BoxLayout: + ToggleButton: + group: 'cutoff' + text: 'cutoff True' + state: 'down' + on_release: win.shape_cutoff = True + ToggleButton: + group: 'cutoff' + text: 'cutoff False' + on_release: win.shape_cutoff = False + + BoxLayout: + ToggleButton: + group: 'colorkey' + text: '1, 1, 1, 1' + state: 'down' + on_release: win.shape_color_key = [1, 1, 1, 1] + ToggleButton: + group: 'colorkey' + text: '0, 0, 0, 1' + on_release: win.shape_color_key = [0, 0, 0, 1] +''') + + +class Root(BoxLayout): + pass + + +class ShapedWindow(App): + shape_image = StringProperty('', force_dispatch=True) + + def on_shape_image(self, instance, value): + if 'kivy-icon' in value: + Window.size = (512, 512) + Window.shape_image = self.alpha_shape + else: + Window.size = (800, 600) + Window.shape_image = self.default_shape + + def build(self): + self.default_shape = default_shape + self.alpha_shape = alpha_shape + + return Root() + + +if __name__ == '__main__': + ShapedWindow().run() diff --git a/freechat-client/share/kivy-examples/miscellaneous/two_panes.py b/freechat-client/share/kivy-examples/miscellaneous/two_panes.py new file mode 100644 index 0000000..389d236 --- /dev/null +++ b/freechat-client/share/kivy-examples/miscellaneous/two_panes.py @@ -0,0 +1,47 @@ +''' +Demonstrates using kv language to create some simple buttons and a +label, with each button modifying the label text. +''' + +from kivy.app import App +from kivy.uix.boxlayout import BoxLayout +from kivy.lang import Builder + +Builder.load_string(''' +: + BoxLayout: + orientation: 'vertical' + Button: + text: 'some string ' + on_press: the_right_pane.text += self.text + Button: + text: 'one two three four ' + on_press: the_right_pane.text += self.text + Button: + text: 'follow the yellow brick road ' + on_press: the_right_pane.text += self.text + Button: + text: 'five six seven eight ' + on_press: the_right_pane.text += self.text + Button: + text: 'CLEAR LABEL' + on_press: the_right_pane.text = '' + Label: + id: the_right_pane + text: '' + text_size: self.size + halign: 'center' + valign: 'middle' +''') + + +class MainWidget(BoxLayout): + pass + + +class ExampleApp(App): + def build(self): + return MainWidget() + + +ExampleApp().run() diff --git a/freechat-client/share/kivy-examples/miscellaneous/urlrequest.py b/freechat-client/share/kivy-examples/miscellaneous/urlrequest.py new file mode 100644 index 0000000..cafe987 --- /dev/null +++ b/freechat-client/share/kivy-examples/miscellaneous/urlrequest.py @@ -0,0 +1,128 @@ +from kivy.lang import Builder +from kivy.app import App +from kivy.network.urlrequest import UrlRequest +from kivy.properties import NumericProperty, StringProperty, DictProperty + +import json + + +KV = ''' +#:import json json +#:import C kivy.utils.get_color_from_hex + +BoxLayout: + orientation: 'vertical' + Label: + text: 'see https://httpbin.org for more information' + + TextInput: + id: ti + hint_text: 'type url or select from dropdown' + size_hint_y: None + height: 48 + multiline: False + foreground_color: + ( + C('000000') + if (self.text).startswith('http') else + C('FF2222') + ) + + BoxLayout: + size_hint_y: None + height: 48 + Spinner: + id: spinner + text: 'select' + values: + [ + 'http://httpbin.org/ip', + 'http://httpbin.org/user-agent', + 'http://httpbin.org/headers', + 'http://httpbin.org/delay/3', + 'http://httpbin.org/image/jpeg', + 'http://httpbin.org/image/png', + 'https://httpbin.org/delay/3', + 'https://httpbin.org/image/jpeg', + 'https://httpbin.org/image/png', + ] + on_text: ti.text = self.text + + Button: + text: 'GET' + on_press: app.fetch_content(ti.text) + disabled: not (ti.text).startswith('http') + size_hint_x: None + width: 50 + + Label: + text: str(app.status) + + TextInput: + readonly: True + text: app.result_text + + Image: + source: app.result_image + nocache: True + + TextInput + readonly: True + text: json.dumps(app.headers, indent=2) +''' + + +class UrlExample(App): + status = NumericProperty() + result_text = StringProperty() + result_image = StringProperty() + headers = DictProperty() + + def build(self): + return Builder.load_string(KV) + + def fetch_content(self, url): + self.cleanup() + UrlRequest( + url, + on_success=self.on_success, + on_failure=self.on_failure, + on_error=self.on_error + ) + + def cleanup(self): + self.result_text = '' + self.result_image = '' + self.status = 0 + self.headers = {} + + def on_success(self, req, result): + self.cleanup() + headers = req.resp_headers + content_type = headers.get('content-type', headers.get('Content-Type')) + if content_type.startswith('image/'): + fn = 'tmpfile.{}'.format(content_type.split('/')[1]) + with open(fn, 'wb') as f: + f.write(result) + self.result_image = fn + else: + if isinstance(result, dict): + self.result_text = json.dumps(result, indent=2) + else: + self.result_text = result + self.status = req.resp_status + self.headers = headers + + def on_failure(self, req, result): + self.cleanup() + self.result_text = result + self.status = req.resp_status + self.headers = req.resp_headers + + def on_error(self, req, result): + self.cleanup() + self.result_text = str(result) + + +if __name__ == '__main__': + UrlExample().run() diff --git a/freechat-client/share/kivy-examples/settings/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/settings/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..9cb638c Binary files /dev/null and b/freechat-client/share/kivy-examples/settings/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/settings/android.txt b/freechat-client/share/kivy-examples/settings/android.txt new file mode 100644 index 0000000..8b1f3e7 --- /dev/null +++ b/freechat-client/share/kivy-examples/settings/android.txt @@ -0,0 +1,3 @@ +title=Settings +author=Kivy team +orientation=landscape diff --git a/freechat-client/share/kivy-examples/settings/main.py b/freechat-client/share/kivy-examples/settings/main.py new file mode 100755 index 0000000..6ae4e77 --- /dev/null +++ b/freechat-client/share/kivy-examples/settings/main.py @@ -0,0 +1,122 @@ +""" +Config Example +============== + +This file contains a simple example of how the use the Kivy settings classes in +a real app. It allows the user to change the caption and font_size of the label +and stores these changes. + +When the user next runs the programs, their changes are restored. + +""" + +from kivy.app import App +from kivy.uix.settings import SettingsWithTabbedPanel +from kivy.logger import Logger +from kivy.lang import Builder + +# We first define our GUI +kv = ''' +BoxLayout: + orientation: 'vertical' + Button: + text: 'Configure app (or press F1)' + on_release: app.open_settings() + Label: + id: label + text: 'Hello' +''' + +# This JSON defines entries we want to appear in our App configuration screen +json = ''' +[ + { + "type": "string", + "title": "Label caption", + "desc": "Choose the text that appears in the label", + "section": "My Label", + "key": "text" + }, + { + "type": "numeric", + "title": "Label font size", + "desc": "Choose the font size the label", + "section": "My Label", + "key": "font_size" + } +] +''' + + +class MyApp(App): + def build(self): + """ + Build and return the root widget. + """ + # The line below is optional. You could leave it out or use one of the + # standard options, such as SettingsWithSidebar, SettingsWithSpinner + # etc. + self.settings_cls = MySettingsWithTabbedPanel + + # We apply the saved configuration settings or the defaults + root = Builder.load_string(kv) + label = root.ids.label + label.text = self.config.get('My Label', 'text') + label.font_size = float(self.config.get('My Label', 'font_size')) + return root + + def build_config(self, config): + """ + Set the default values for the configs sections. + """ + config.setdefaults('My Label', {'text': 'Hello', 'font_size': 20}) + + def build_settings(self, settings): + """ + Add our custom section to the default configuration object. + """ + # We use the string defined above for our JSON, but it could also be + # loaded from a file as follows: + # settings.add_json_panel('My Label', self.config, 'settings.json') + settings.add_json_panel('My Label', self.config, data=json) + + def on_config_change(self, config, section, key, value): + """ + Respond to changes in the configuration. + """ + Logger.info("main.py: App.on_config_change: {0}, {1}, {2}, {3}".format( + config, section, key, value)) + + if section == "My Label": + if key == "text": + self.root.ids.label.text = value + elif key == 'font_size': + self.root.ids.label.font_size = float(value) + + def close_settings(self, settings=None): + """ + The settings panel has been closed. + """ + Logger.info("main.py: App.close_settings: {0}".format(settings)) + super(MyApp, self).close_settings(settings) + + +class MySettingsWithTabbedPanel(SettingsWithTabbedPanel): + """ + It is not usually necessary to create subclass of a settings panel. There + are many built-in types that you can use out of the box + (SettingsWithSidebar, SettingsWithSpinner etc.). + + You would only want to create a Settings subclass like this if you want to + change the behavior or appearance of an existing Settings class. + """ + def on_close(self): + Logger.info("main.py: MySettingsWithTabbedPanel.on_close") + + def on_config_change(self, config, section, key, value): + Logger.info( + "main.py: MySettingsWithTabbedPanel.on_config_change: " + "{0}, {1}, {2}, {3}".format(config, section, key, value)) + + +MyApp().run() diff --git a/freechat-client/share/kivy-examples/shader/__pycache__/plasma.cpython-37.pyc b/freechat-client/share/kivy-examples/shader/__pycache__/plasma.cpython-37.pyc new file mode 100644 index 0000000..eb0ced8 Binary files /dev/null and b/freechat-client/share/kivy-examples/shader/__pycache__/plasma.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/shader/__pycache__/rotated.cpython-37.pyc b/freechat-client/share/kivy-examples/shader/__pycache__/rotated.cpython-37.pyc new file mode 100644 index 0000000..3ad09a6 Binary files /dev/null and b/freechat-client/share/kivy-examples/shader/__pycache__/rotated.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/shader/__pycache__/shadertree.cpython-37.pyc b/freechat-client/share/kivy-examples/shader/__pycache__/shadertree.cpython-37.pyc new file mode 100644 index 0000000..aeadbb5 Binary files /dev/null and b/freechat-client/share/kivy-examples/shader/__pycache__/shadertree.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/shader/plasma.kv b/freechat-client/share/kivy-examples/shader/plasma.kv new file mode 100644 index 0000000..58c842a --- /dev/null +++ b/freechat-client/share/kivy-examples/shader/plasma.kv @@ -0,0 +1,9 @@ +#:kivy 1.0 + +: + canvas: + Color: + rgb: 1, 0, 0 + Rectangle: + pos: self.pos + size: self.size diff --git a/freechat-client/share/kivy-examples/shader/plasma.py b/freechat-client/share/kivy-examples/shader/plasma.py new file mode 100644 index 0000000..81a9a41 --- /dev/null +++ b/freechat-client/share/kivy-examples/shader/plasma.py @@ -0,0 +1,86 @@ +''' +Plasma Shader +============= + +This shader example have been taken from +http://www.iquilezles.org/apps/shadertoy/ with some adaptation. + +This might become a Kivy widget when experimentation will be done. +''' + + +from kivy.clock import Clock +from kivy.app import App +from kivy.uix.floatlayout import FloatLayout +from kivy.core.window import Window +from kivy.graphics import RenderContext +from kivy.properties import StringProperty + + +# Plasma shader +plasma_shader = ''' +$HEADER$ + +uniform vec2 resolution; +uniform float time; + +void main(void) +{ + vec4 frag_coord = frag_modelview_mat * gl_FragCoord; + float x = frag_coord.x; + float y = frag_coord.y; + float mov0 = x+y+cos(sin(time)*2.)*100.+sin(x/100.)*1000.; + float mov1 = y / resolution.y / 0.2 + time; + float mov2 = x / resolution.x / 0.2; + float c1 = abs(sin(mov1+time)/2.+mov2/2.-mov1-mov2+time); + float c2 = abs(sin(c1+sin(mov0/1000.+time) + +sin(y/40.+time)+sin((x+y)/100.)*3.)); + float c3 = abs(sin(c2+cos(mov1+mov2+c2)+cos(mov2)+sin(x/1000.))); + gl_FragColor = vec4( c1,c2,c3,1.0); +} +''' + + +class ShaderWidget(FloatLayout): + + # property to set the source code for fragment shader + fs = StringProperty(None) + + def __init__(self, **kwargs): + # Instead of using Canvas, we will use a RenderContext, + # and change the default shader used. + self.canvas = RenderContext() + + # call the constructor of parent + # if they are any graphics object, they will be added on our new canvas + super(ShaderWidget, self).__init__(**kwargs) + + # We'll update our glsl variables in a clock + Clock.schedule_interval(self.update_glsl, 1 / 60.) + + def on_fs(self, instance, value): + # set the fragment shader to our source code + shader = self.canvas.shader + old_value = shader.fs + shader.fs = value + if not shader.success: + shader.fs = old_value + raise Exception('failed') + + def update_glsl(self, *largs): + self.canvas['time'] = Clock.get_boottime() + self.canvas['resolution'] = list(map(float, self.size)) + # This is needed for the default vertex shader. + win_rc = Window.render_context + self.canvas['projection_mat'] = win_rc['projection_mat'] + self.canvas['modelview_mat'] = win_rc['modelview_mat'] + self.canvas['frag_modelview_mat'] = win_rc['frag_modelview_mat'] + + +class PlasmaApp(App): + def build(self): + return ShaderWidget(fs=plasma_shader) + + +if __name__ == '__main__': + PlasmaApp().run() diff --git a/freechat-client/share/kivy-examples/shader/rotated.kv b/freechat-client/share/kivy-examples/shader/rotated.kv new file mode 100644 index 0000000..e7be110 --- /dev/null +++ b/freechat-client/share/kivy-examples/shader/rotated.kv @@ -0,0 +1,91 @@ +#:kivy 1.10.1 + +: + canvas.before: + PushMatrix + Rotate: + angle: 45 + origin: self.center + canvas.after: + PopMatrix + +: + canvas.before: + PushMatrix + PushMatrix: + stack: 'frag_modelview_mat' + Rotate: + angle: 45 + origin: self.center + Rotate: + stack: 'frag_modelview_mat' + angle: 45 + origin: self.center + canvas.after: + PopMatrix + PopMatrix: + stack: 'frag_modelview_mat' + +: + font_size: 30 + outline_width: 1 + pos_hint: {'center_x': .5, 'center_y': .5} + +: + font_size: 60 + outline_width: 3 + +: + size_hint: .3, .3 + pos_hint: {'center_x': .25, 'center_y': .25} + canvas: + Color: + rgb: 1., .6, .3 + Rectangle: + pos: self.pos + size: self.size + +: + size_hint: .3, .3 + pos_hint: {'center_x': .75, 'center_y': .75} + canvas: + Color: + rgb: .3, .6, .9 + Rectangle: + pos: self.pos + size: self.size + + SmallLabel: + text: 'Phase Shifted' + +: + size_hint: .3, .3 + pos_hint: {'center_x': .25, 'center_y': .75} + canvas: + Color: + rgb: .3, .6, .9 + Rectangle: + pos: self.pos + size: self.size + + SmallLabel: + text: 'In Phase' + +: + mini: mini + canvas: + Color: + rgb: .9, .6, .3 + Rectangle: + pos: self.pos + size: self.size + + LargeTiltedLabel: + text: 'far out' + pos_hint: {'center_x': .75, 'center_y': .25} + + MiniShaderWidget + id: mini + + PhaseShiftedWidget + InPhaseWidget diff --git a/freechat-client/share/kivy-examples/shader/rotated.py b/freechat-client/share/kivy-examples/shader/rotated.py new file mode 100644 index 0000000..cba176c --- /dev/null +++ b/freechat-client/share/kivy-examples/shader/rotated.py @@ -0,0 +1,102 @@ +''' +Rotated Shader +============= + +This shader example is a modified version of plasma.py that shows how to +rotate areas of fragment shaders bounded by vertex_instructions. +''' +from kivy.app import App +from kivy.clock import Clock +from kivy.factory import Factory +from kivy.graphics import RenderContext +from kivy.properties import StringProperty +from kivy.uix.widget import Widget + +# imported early for side effects needed for Shader +import kivy.core.window + + +shared_code = ''' +$HEADER$ + +uniform float time; + +vec4 tex(void) +{ + return frag_color * texture2D(texture0, tex_coord0); +} + +float plasmaFunc(float n1, float n2, float n3, float n4) +{ + vec4 fPos = frag_modelview_mat * gl_FragCoord; + return abs(sin( + sin(sin(fPos.x / n1) + time) + + sin(fPos.y / n2 + time) + + n4 * sin((fPos.x + fPos.y) / n3))); +} + +''' + + +plasma_shader = shared_code + ''' +void main(void) +{ + float green = plasmaFunc(40., 30., 100., 3.5); + gl_FragColor = vec4(1.0, green, 1.0, 1.0) * tex(); +} + +''' + + +plasma_shader2 = shared_code + ''' +void main(void) +{ + float red = plasmaFunc(30., 20., 10., .5); + gl_FragColor = vec4(red, 1.0, 1.0, 1.0) * tex(); +} + +''' + + +class ShaderWidget(Widget): + + # property to set the source code for fragment shader + fs = StringProperty(None) + + def __init__(self, **kwargs): + # Instead of using Canvas, we will use a RenderContext, + # and change the default fragment shader used. + self.canvas = RenderContext(use_parent_projection=True, + use_parent_modelview=True, + use_parent_frag_modelview=True) + + # call the constructor of parent + # if they are any graphics object, they will be added on our new canvas + super(ShaderWidget, self).__init__(**kwargs) + + # We'll update our glsl variables in a clock + Clock.schedule_interval(self.update_glsl, 1 / 60.) + + def update_glsl(self, *largs): + self.canvas['time'] = Clock.get_boottime() + + def on_fs(self, instance, value): + # set the fragment shader to our source code + shader = self.canvas.shader + old_value = shader.fs + shader.fs = value + if not shader.success: + shader.fs = old_value + raise Exception('failed') + + +class RotatedApp(App): + def build(self): + main_widget = Factory.MainWidget() + main_widget.fs = plasma_shader + main_widget.mini.fs = plasma_shader2 + return main_widget + + +if __name__ == '__main__': + RotatedApp().run() diff --git a/freechat-client/share/kivy-examples/shader/shadertree.kv b/freechat-client/share/kivy-examples/shader/shadertree.kv new file mode 100644 index 0000000..bb49a8d --- /dev/null +++ b/freechat-client/share/kivy-examples/shader/shadertree.kv @@ -0,0 +1,29 @@ +#:kivy 1.10.1 + +: + Button: + text: 'Hello World' + pos_hint: {'center_x': .25, 'center_y': .5} + size_hint: None, None + ScatterImage + +: + size: image.size + pos_hint: {'center_x': .75, 'center_y': .5} + size_hint: None, None + Image: + id: image + source: 'tex3.jpg' + size: self.texture_size + +: + shader_btn: shader_btn + shader_widget: shader_widget + + ShaderWidget: + id: shader_widget + Button: + id: shader_btn + text: 'Change fragment shader' + size_hint_y: None + height: 50 diff --git a/freechat-client/share/kivy-examples/shader/shadertree.py b/freechat-client/share/kivy-examples/shader/shadertree.py new file mode 100644 index 0000000..d304ddf --- /dev/null +++ b/freechat-client/share/kivy-examples/shader/shadertree.py @@ -0,0 +1,193 @@ +''' +Tree shader +=========== + +This example is an experimentation to show how we can use shader for a tree +subset. Here, we made a ShaderTreeWidget, different than the ShaderWidget +in the plasma.py example. + +The ShaderTree widget create a Frambuffer, render his children on it, and +render the Framebuffer with a specific Shader. +With this way, you can apply cool effect on your widgets :) + +''' + +from kivy.clock import Clock +from kivy.app import App +from kivy.uix.floatlayout import FloatLayout +from kivy.core.window import Window # side effects needed by Shader +from kivy.properties import StringProperty, ObjectProperty +from kivy.graphics import (RenderContext, Fbo, Color, ClearColor, ClearBuffers, + Rectangle) + +import itertools + + +header = ''' +$HEADER$ + +uniform vec2 resolution; +uniform float time; +''' + +# pulse (Danguafer/Silexars, 2010) +shader_pulse = header + ''' +void main(void) +{ + vec2 halfres = resolution.xy/2.0; + vec2 cPos = vec4(frag_modelview_mat * gl_FragCoord).xy; + + cPos.x -= 0.5*halfres.x*sin(time/2.0)+0.3*halfres.x*cos(time)+halfres.x; + cPos.y -= 0.4*halfres.y*sin(time/5.0)+0.3*halfres.y*cos(time)+halfres.y; + float cLength = length(cPos); + + vec2 uv = tex_coord0+(cPos/cLength)*sin(cLength/30.0-time*10.0)/25.0; + vec3 col = texture2D(texture0,uv).xyz*50.0/cLength; + + gl_FragColor = vec4(col,1.0); +} +''' + +# post processing (by iq, 2009) +shader_postprocessing = header + ''' +uniform vec2 uvsize; +uniform vec2 uvpos; +void main(void) +{ + vec2 q = tex_coord0 * vec2(1, -1); + vec2 uv = 0.5 + (q-0.5);//*(0.9);// + 0.1*sin(0.2*time)); + + vec3 oricol = texture2D(texture0,vec2(q.x,1.0-q.y)).xyz; + vec3 col; + + col.r = texture2D(texture0,vec2(uv.x+0.003,-uv.y)).x; + col.g = texture2D(texture0,vec2(uv.x+0.000,-uv.y)).y; + col.b = texture2D(texture0,vec2(uv.x-0.003,-uv.y)).z; + + col = clamp(col*0.5+0.5*col*col*1.2,0.0,1.0); + + //col *= 0.5 + 0.5*16.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y); + + col *= vec3(0.8,1.0,0.7); + + col *= 0.9+0.1*sin(10.0*time+uv.y*1000.0); + + col *= 0.97+0.03*sin(110.0*time); + + float comp = smoothstep( 0.2, 0.7, sin(time) ); + //col = mix( col, oricol, clamp(-2.0+2.0*q.x+3.0*comp,0.0,1.0) ); + + gl_FragColor = vec4(col,1.0); +} +''' + +shader_monochrome = header + ''' +void main() { + vec4 rgb = texture2D(texture0, tex_coord0); + float c = (rgb.x + rgb.y + rgb.z) * 0.3333; + gl_FragColor = vec4(c, c, c, 1.0); +} +''' + + +class ShaderWidget(FloatLayout): + + # property to set the source code for fragment shader + fs = StringProperty(None) + + # texture of the framebuffer + texture = ObjectProperty(None) + + def __init__(self, **kwargs): + # Instead of using canvas, we will use a RenderContext, + # and change the default shader used. + self.canvas = RenderContext(use_parent_projection=True, + use_parent_modelview=True, + use_parent_frag_modelview=True) + + with self.canvas: + self.fbo = Fbo(size=self.size) + self.fbo_color = Color(1, 1, 1, 1) + self.fbo_rect = Rectangle() + + with self.fbo: + ClearColor(0, 0, 0, 0) + ClearBuffers() + + # call the constructor of parent + # if they are any graphics object, they will be added on our new canvas + super(ShaderWidget, self).__init__(**kwargs) + + # We'll update our glsl variables in a clock + Clock.schedule_interval(self.update_glsl, 0) + + def update_glsl(self, *largs): + self.canvas['time'] = Clock.get_boottime() + self.canvas['resolution'] = [float(v) for v in self.size] + + def on_fs(self, instance, value): + # set the fragment shader to our source code + shader = self.canvas.shader + old_value = shader.fs + shader.fs = value + if not shader.success: + shader.fs = old_value + raise Exception('failed') + + # + # now, if we have new widget to add, + # add their graphics canvas to our Framebuffer, not the usual canvas. + # + + def add_widget(self, widget): + c = self.canvas + self.canvas = self.fbo + super(ShaderWidget, self).add_widget(widget) + self.canvas = c + + def remove_widget(self, widget): + c = self.canvas + self.canvas = self.fbo + super(ShaderWidget, self).remove_widget(widget) + self.canvas = c + + def on_size(self, instance, value): + self.fbo.size = value + self.texture = self.fbo.texture + self.fbo_rect.size = value + + def on_pos(self, instance, value): + self.fbo_rect.pos = value + + def on_texture(self, instance, value): + self.fbo_rect.texture = value + + +class RootWidget(FloatLayout): + shader_btn = ObjectProperty(None) + shader_widget = ObjectProperty(None) + + def __init__(self, **kwargs): + super(RootWidget, self).__init__(**kwargs) + + # prepare shader list + available_shaders = [ + shader_pulse, + shader_postprocessing, + shader_monochrome, + ] + self.shaders = itertools.cycle(available_shaders) + + self.shader_btn.bind(on_release=self.change) + + def change(self, *largs): + self.shader_widget.fs = next(self.shaders) + + +class ShaderTreeApp(App): + def build(self): + return RootWidget() + + +if __name__ == '__main__': + ShaderTreeApp().run() diff --git a/freechat-client/share/kivy-examples/shader/tex3.jpg b/freechat-client/share/kivy-examples/shader/tex3.jpg new file mode 100644 index 0000000..fe64a0f Binary files /dev/null and b/freechat-client/share/kivy-examples/shader/tex3.jpg differ diff --git a/freechat-client/share/kivy-examples/svg/__pycache__/benchmark.cpython-37.pyc b/freechat-client/share/kivy-examples/svg/__pycache__/benchmark.cpython-37.pyc new file mode 100644 index 0000000..3a1ddd3 Binary files /dev/null and b/freechat-client/share/kivy-examples/svg/__pycache__/benchmark.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/svg/__pycache__/main-smaa.cpython-37.pyc b/freechat-client/share/kivy-examples/svg/__pycache__/main-smaa.cpython-37.pyc new file mode 100644 index 0000000..96fc6df Binary files /dev/null and b/freechat-client/share/kivy-examples/svg/__pycache__/main-smaa.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/svg/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/svg/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..5fb2f2e Binary files /dev/null and b/freechat-client/share/kivy-examples/svg/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/svg/benchmark.py b/freechat-client/share/kivy-examples/svg/benchmark.py new file mode 100644 index 0000000..39c28d5 --- /dev/null +++ b/freechat-client/share/kivy-examples/svg/benchmark.py @@ -0,0 +1,19 @@ +from kivy.core.window import Window +from kivy.graphics.svg import Svg +from time import time +import sys +import os + +filename = sys.argv[1] +if "PROFILE" in os.environ: + import pstats + import cProfile + cProfile.runctx("Svg(filename)", globals(), locals(), "Profile.prof") + s = pstats.Stats("Profile.prof") + s.sort_stats("time").print_callers() +else: + print("Loading {}".format(filename)) + start = time() + svg = Svg(filename) + end = time() + print("Loaded in {:.2f}s".format((end - start))) diff --git a/freechat-client/share/kivy-examples/svg/cloud.svg b/freechat-client/share/kivy-examples/svg/cloud.svg new file mode 100644 index 0000000..2292d8e --- /dev/null +++ b/freechat-client/share/kivy-examples/svg/cloud.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/freechat-client/share/kivy-examples/svg/main-smaa.py b/freechat-client/share/kivy-examples/svg/main-smaa.py new file mode 100644 index 0000000..423a908 --- /dev/null +++ b/freechat-client/share/kivy-examples/svg/main-smaa.py @@ -0,0 +1,155 @@ +import sys +from glob import glob +from os.path import join, dirname +from kivy.uix.scatter import Scatter +from kivy.uix.widget import Widget +from kivy.uix.label import Label +from kivy.app import App +from kivy.graphics.svg import Svg +from kivy.core.window import Window +from kivy.uix.floatlayout import FloatLayout +from kivy.lang import Builder + + +smaa_ui = ''' +#:kivy 1.8.0 + +BoxLayout: + orientation: 'horizontal' + pos_hint: {'top': 1} + size_hint_y: None + height: '48dp' + padding: '2dp' + spacing: '2dp' + Label: + text: 'Quality:' + ToggleButton: + text: 'Low' + group: 'smaa-quality' + on_release: app.smaa.quality = 'low' + ToggleButton: + text: 'Medium' + group: 'smaa-quality' + on_release: app.smaa.quality = 'medium' + ToggleButton: + text: 'High' + group: 'smaa-quality' + on_release: app.smaa.quality = 'high' + ToggleButton: + text: 'Ultra' + group: 'smaa-quality' + state: 'down' + on_release: app.smaa.quality = 'ultra' + + Label: + text: 'Debug:' + ToggleButton: + text: 'None' + group: 'smaa-debug' + state: 'down' + on_release: app.smaa.debug = '' + ToggleButton: + text: 'Source' + group: 'smaa-debug' + on_release: app.smaa.debug = 'source' + ToggleButton: + text: 'Edges' + group: 'smaa-debug' + on_release: app.smaa.debug = 'edges' + ToggleButton: + text: 'Blend' + group: 'smaa-debug' + on_release: app.smaa.debug = 'blend' + +''' + + +class SvgWidget(Scatter): + + def __init__(self, filename): + super(SvgWidget, self).__init__() + with self.canvas: + svg = Svg(filename) + + self.size = svg.width, svg.height + + +class SvgApp(App): + + def build(self): + from kivy.garden.smaa import SMAA + + Window.bind(on_keyboard=self._on_keyboard_handler) + + self.smaa = SMAA() + self.effects = [self.smaa, Widget()] + self.effect_index = 0 + self.label = Label(text='SMAA', top=Window.height) + self.effect = effect = self.effects[0] + self.root = FloatLayout() + self.root.add_widget(effect) + + if 0: + from kivy.graphics import Color, Rectangle + wid = Widget(size=Window.size) + with wid.canvas: + Color(1, 1, 1, 1) + Rectangle(size=Window.size) + effect.add_widget(wid) + + if 1: + # from kivy.uix.image import Image + # root.add_widget(Image(source='data/logo/kivy-icon-512.png', + # size=(800, 600))) + + filenames = sys.argv[1:] + if not filenames: + filenames = glob(join(dirname(__file__), '*.svg')) + + for filename in filenames: + svg = SvgWidget(filename) + effect.add_widget(svg) + + effect.add_widget(self.label) + svg.scale = 5. + svg.center = Window.center + + if 0: + wid = Scatter(size=Window.size) + from kivy.graphics import Color, Triangle, Rectangle + with wid.canvas: + Color(0, 0, 0, 1) + Rectangle(size=Window.size) + Color(1, 1, 1, 1) + w, h = Window.size + cx, cy = w / 2., h / 2. + Triangle(points=[cx - w * 0.25, cy - h * 0.25, + cx, cy + h * 0.25, + cx + w * 0.25, cy - h * 0.25]) + effect.add_widget(wid) + + if 0: + from kivy.uix.button import Button + from kivy.uix.slider import Slider + effect.add_widget(Button(text='Hello World')) + effect.add_widget(Slider(pos=(200, 200))) + + control_ui = Builder.load_string(smaa_ui) + self.root.add_widget(control_ui) + + def _on_keyboard_handler(self, instance, key, *args): + if key == 32: + self.effect_index = (self.effect_index + 1) % 2 + childrens = self.effect.children[:] + self.effect.clear_widgets() + self.root.remove_widget(self.effect) + self.effect = self.effects[self.effect_index] + self.root.add_widget(self.effect) + for child in reversed(childrens): + self.effect.add_widget(child) + self.label.text = self.effect.__class__.__name__ + Window.title = self.label.text + + +if __name__ == '__main__': + SvgApp().run() diff --git a/freechat-client/share/kivy-examples/svg/main.py b/freechat-client/share/kivy-examples/svg/main.py new file mode 100644 index 0000000..38f74f1 --- /dev/null +++ b/freechat-client/share/kivy-examples/svg/main.py @@ -0,0 +1,50 @@ +import sys +from glob import glob +from os.path import join, dirname +from kivy.uix.scatter import Scatter +from kivy.app import App +from kivy.graphics.svg import Svg +from kivy.core.window import Window +from kivy.uix.floatlayout import FloatLayout +from kivy.lang import Builder + +Builder.load_string(""" +: + do_rotation: False +: + canvas.before: + Color: + rgb: (1, 1, 1) + Rectangle: + pos: self.pos + size: self.size +""") + + +class SvgWidget(Scatter): + + def __init__(self, filename, **kwargs): + super(SvgWidget, self).__init__(**kwargs) + with self.canvas: + svg = Svg(filename) + self.size = svg.width, svg.height + + +class SvgApp(App): + + def build(self): + self.root = FloatLayout() + + filenames = sys.argv[1:] + if not filenames: + filenames = glob(join(dirname(__file__), '*.svg')) + + for filename in filenames: + svg = SvgWidget(filename, size_hint=(None, None)) + self.root.add_widget(svg) + svg.scale = 5. + svg.center = Window.center + + +if __name__ == '__main__': + SvgApp().run() diff --git a/freechat-client/share/kivy-examples/svg/music.svg b/freechat-client/share/kivy-examples/svg/music.svg new file mode 100644 index 0000000..69699a1 --- /dev/null +++ b/freechat-client/share/kivy-examples/svg/music.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/freechat-client/share/kivy-examples/svg/ship.svg b/freechat-client/share/kivy-examples/svg/ship.svg new file mode 100644 index 0000000..46fd38f --- /dev/null +++ b/freechat-client/share/kivy-examples/svg/ship.svg @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/freechat-client/share/kivy-examples/svg/sun.svg b/freechat-client/share/kivy-examples/svg/sun.svg new file mode 100644 index 0000000..b040f28 --- /dev/null +++ b/freechat-client/share/kivy-examples/svg/sun.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/freechat-client/share/kivy-examples/svg/tiger.svg b/freechat-client/share/kivy-examples/svg/tiger.svg new file mode 100644 index 0000000..61d267c --- /dev/null +++ b/freechat-client/share/kivy-examples/svg/tiger.svg @@ -0,0 +1,813 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/freechat-client/share/kivy-examples/text/__pycache__/pango_demo.cpython-37.pyc b/freechat-client/share/kivy-examples/text/__pycache__/pango_demo.cpython-37.pyc new file mode 100644 index 0000000..5746746 Binary files /dev/null and b/freechat-client/share/kivy-examples/text/__pycache__/pango_demo.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/text/pango_demo.py b/freechat-client/share/kivy-examples/text/pango_demo.py new file mode 100644 index 0000000..9aa8de6 --- /dev/null +++ b/freechat-client/share/kivy-examples/text/pango_demo.py @@ -0,0 +1,296 @@ +# -*- coding: utf-8 -*- + +from kivy.base import runTouchApp +from kivy.lang import Builder +from kivy.factory import Factory as F + + +class DemoBox(F.ButtonBehavior, F.BoxLayout): + base_direction = F.StringProperty(None, allownone=True) + font_context = F.StringProperty(None, allownone=True) + font_size = F.NumericProperty(10) + + +runTouchApp(Builder.load_string(''' +#:import F kivy.factory.Factory +: + bold: True + size_hint_x: None + width: '150dp' + text_size: self.size + halign: 'right' + valign: 'middle' +: + hacked_state: False + allow_no_selection: False + on_state: self.hacked_state = self.state == 'down' +: + text: 'auto' + group: 'halign' + on_hacked_state: for c in root.parent.__boxes.children: \ + c.halign = root.text +: + text: '20' + group: 'font' + on_hacked_state: for c in root.parent.__boxes.children: \ + c.font_size = int(root.text) +: + text: 'system://' + group: 'context' + on_hacked_state: for c in root.parent.__boxes.children: \ + c.font_context = root.text +: + text: 'None' + group: 'basedir' + on_hacked_state: for c in root.parent.__boxes.children: \ + c.base_direction = root.text +: + size_hint: .8, .8 + text: '' + BoxLayout: + orientation: 'vertical' + TextInput: + multiline: True + id: ti + text: root.text + cursor_width: 3 + Button: + size_hint_y: None + text: 'Close' + on_press: root.dismiss() +: + text: ti.text + language: '' + halign: 'auto' + font_size: '20sp' + font_context: 'system://' + base_direction: None + markup: True + orientation: 'horizontal' + padding: '5dp' + spacing: '5dp' + size_hint_y: None + height: lbl.texture_size[1] + 25 + on_text: + if self.text: ti.text = self.text + Button: + text: 'Open' + size_hint_x: None + on_press: + pop = F.EditPopup() + pop.text = lbl.text + pop.ids.ti.halign = root.halign + pop.ids.ti.font_size = root.font_size + pop.ids.ti.font_context = root.font_context != 'None' \ + and root.font_context or None + pop.ids.ti.base_direction = root.base_direction != 'None' \ + and root.base_direction or None + pop.title = 'Edit: {}'.format(root.language) + pop.open() + Label: + text: root.language + text_size: self.size + halign: 'left' + bold: True + size_hint_x: None + width: 150 + halign: 'left' + valign: 'middle' + font_size: '15sp' + color: 1, 1, 0, 1 + canvas.before: + Color: + rgba: 1, 1, 1, .5 + Rectangle: + pos: self.pos + size: self.size + Label: + id: lbl + halign: root.halign + text: root.text + markup: root.markup + font_context: root.font_context != 'None' and \ + root.font_context or None + base_direction: root.base_direction != 'None' and \ + root.base_direction or None + font_size: root.font_size + text_size: self.width, None + canvas.before: + Color: + rgba: 1, 1, 1, .1 + Rectangle: + pos: self.pos + size: self.size + TextInput: + id: ti + halign: root.halign + cursor_width: 3 + font_context: root.font_context != 'None' and root.font_context or None + base_direction: root.base_direction != 'None' and \ + root.base_direction or None + font_size: root.font_size +BoxLayout: + orientation: 'vertical' + ScrollView: + id: sv + bar_color: [.1, .75, .1, .95] + bar_inactive_color: [.5, .5, .5, .8] + bar_width: '20dp' + BoxLayout: + id: boxes + orientation: 'vertical' + size_hint: None, None + height: self.minimum_height + width: sv.width - 25 # don't draw below scrollbar + DemoBox: + markup: True + language: 'Arabic' + text: 'اَلْحَمْدُ لِلّٰهِ رَبِّ \ + [color=ff0000]الْعَالَمِينَ\ + \\nاَلرَّحْ[/color]مٰنِ الرَّحِيمِ' + DemoBox: + language: 'Arabic + English' + text: 'اِيَّاكَ نَعْبُدُ Kivyوَ اِيَّاكَ نَسْتَعِينُ\\nKivy' + DemoBox: + language: 'English + Arabic' + text: 'Kivy\\nاِيَّاكَ نَعْبُدُ وَKivy اِيَّاكَ نَسْتَعِينُ' + DemoBox: + language: 'Hebrew' + text: 'בְּרֵאשִׁ֖ית בָּרָ֣א \ + \\nאֱלֹהִ֑ים אֵ֥ת הַשָּׁמַ֖יִם וְאֵ֥ת הָאָֽרֶץ׃' + DemoBox: + language: 'Hebrew + English' + text: 'בְּרֵאKivyשִׁ֖ית בָּרָ֣א \\nKivy' + DemoBox: + language: 'English + Hebrew' + text: 'Kivy\\nבְּרֵאשִׁ֖יKivyת בָּרָ֣א ' + DemoBox: + language: 'Chinese' + text: '你好,这是中文竖排测试。\\n欢迎来到中国北京。' + DemoBox: + language: 'Chinese + English' + text: '你好,这是Kivy中文竖排测试。\\nKivy' + DemoBox: + language: 'English + Chinese' + text: 'Kivy\\n你好,这是中Kivy文竖排测试。' + DemoBox: + language: 'Syriac' + text: 'ܐܬܐܡܘܢ ܥܠܝܡܢ \\nܘܥܠܝܡܬܢ' + DemoBox: + language: 'Syriac + English' + text: 'ܐܬܐܡܘܢ Kivyܥܠܝܡܢ ܘܥܠܝܡܬܢ\\nKivy' + DemoBox: + language: 'English + Syriac' + text: 'Kivyܐܬܐܡܘܢ ܥܠKivyܝܡܢ ܘܥܠܝܡܬܢ\\nKivy' + DemoBox: + language: 'Tibetan' + text: ' འབྲུག་རྒྱལ་ཁབ\\n་འདི་དགའ་ཏོག་ཏོ་ཡོད།' + DemoBox: + language: 'Tibetan + English' + text: ' འ Kivyབྲུག་རྒྱལ་ཁབ\\n་འདི་དགKivyའ་ཏོག་ཏོ་ཡོད།' + DemoBox: + language: 'English + Tibetan' + text: 'Regular letters\\n\ + འབྲུག་རྒྱལ་ཁབ་འདི་དགའ་Kivyཏོག་ཏོ་ཡོད།' + DemoBox: + language: 'Braille (EN)' + text: '⠊⠀⠉⠁⠝⠀⠑⠁⠞⠀⠛⠇⠁⠎⠎⠀\\n⠁⠝⠙⠀⠊⠞⠀⠙⠕⠑⠎⠝⠞⠀⠓⠥⠗⠞⠀⠍⠑' + DemoBox: + language: 'Braille (EN) + English' + text: '⠊⠀⠉⠁⠝⠀⠑⠁⠞Kivy\\n⠀⠛⠇⠁⠎⠎⠀⠁⠝Kivy⠙⠀⠊⠞⠀⠙⠕⠑⠎⠝⠞⠀⠓⠥⠗⠞⠀⠍⠑' + DemoBox: + markup: True + language: 'Braille (EN) + English' + text: '⠊⠀⠉⠁⠝⠀⠑⠁⠞Kivy\\n⠀⠛⠇⠁⠎⠎⠀⠁⠝Kivy\ + ⠙⠀⠊⠞⠀[color=ff0000]⠙⠕⠑⠎⠝⠞⠀⠓⠥⠗⠞⠀⠍⠑[/color]' + # --------------------------------------- HALIGN + BoxLayout: + __boxes: boxes + orientation: 'horizontal' + size_hint_y: None + height: '30dp' + MenuLabel: + text: 'set halign =' + HalignButton: + text: 'auto' + state: 'down' + HalignButton: + text: 'left' + HalignButton: + text: 'center' + HalignButton: + text: 'right' +# Not supported by textinput +# HalignButton: +# text: 'justify' + # --------------------------------BASE DIRECTION + BoxLayout: + __boxes: boxes + orientation: 'horizontal' + size_hint_y: None + height: '30dp' + MenuLabel: + text: 'set base_direction =' + BaseDirButton: + text: 'None' + state: 'down' + BaseDirButton: + text: 'ltr' + BaseDirButton: + text: 'rtl' + # --------------------------------- FONT CONTEXT + BoxLayout: + __boxes: boxes + orientation: 'horizontal' + size_hint_y: None + height: '30dp' + MenuLabel: + text: 'set font_context =' + ContextButton: + text: 'None' + ContextButton: + text: 'system://' + state: 'down' + ContextButton: + text: 'system://user' + ContextButton: + text: 'user' + # ------------------------------------ FONT SIZE + BoxLayout: + __boxes: boxes + orientation: 'horizontal' + size_hint_y: None + height: '30dp' + MenuLabel: + text: 'set font_size =' + FontButton: + text: '10' + FontButton: + text: '20' + state: 'down' + FontButton: + text: '30' + FontButton: + text: '40' + FontButton: + text: '50' + FontButton: + text: '75' + FontButton: + text: '100' +# BoxLayout: +# orientation: 'horizontal' +# size_hint_y: None +# height: '30dp' +# Button: +# color: 0, 1, 0, 1 +# text: 'Add font: user' +# Button: +# color: 0, 1, 0, 1 +# text: 'Add font: system://user' +# ToggleButton: +# text: 'Enable markup' +# state: 'down' +# on_state: +# for c in boxes.children: c.markup = self.state == 'down' +''')) diff --git a/freechat-client/share/kivy-examples/tutorials/notes/final/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/tutorials/notes/final/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..ec3c3ca Binary files /dev/null and b/freechat-client/share/kivy-examples/tutorials/notes/final/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/tutorials/notes/final/data/icon.png b/freechat-client/share/kivy-examples/tutorials/notes/final/data/icon.png new file mode 100644 index 0000000..66596ec Binary files /dev/null and b/freechat-client/share/kivy-examples/tutorials/notes/final/data/icon.png differ diff --git a/freechat-client/share/kivy-examples/tutorials/notes/final/main.py b/freechat-client/share/kivy-examples/tutorials/notes/final/main.py new file mode 100644 index 0000000..e9ebc6d --- /dev/null +++ b/freechat-client/share/kivy-examples/tutorials/notes/final/main.py @@ -0,0 +1,163 @@ +''' +Notes +===== + +Simple application for reading/writing notes. + +''' + +__version__ = '1.0' + +import json +from os.path import join, exists +from kivy.app import App +from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition +from kivy.properties import ListProperty, StringProperty, \ + NumericProperty, BooleanProperty, AliasProperty +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.floatlayout import FloatLayout +from kivy.clock import Clock + + +class MutableTextInput(FloatLayout): + + text = StringProperty() + multiline = BooleanProperty(True) + + def __init__(self, **kwargs): + super(MutableTextInput, self).__init__(**kwargs) + Clock.schedule_once(self.prepare, 0) + + def prepare(self, *args): + self.w_textinput = self.ids.w_textinput.__self__ + self.w_label = self.ids.w_label.__self__ + self.view() + + def on_touch_down(self, touch): + if self.collide_point(*touch.pos) and touch.is_double_tap: + self.edit() + return super(MutableTextInput, self).on_touch_down(touch) + + def edit(self): + self.clear_widgets() + self.add_widget(self.w_textinput) + self.w_textinput.focus = True + + def view(self): + self.clear_widgets() + if not self.text: + self.w_label.text = "Double tap/click to edit" + self.add_widget(self.w_label) + + def check_focus_and_view(self, textinput): + if not textinput.focus: + self.text = textinput.text + self.view() + + +class NoteView(Screen): + + note_index = NumericProperty() + note_title = StringProperty() + note_content = StringProperty() + + +class NoteListItem(BoxLayout): + note_content = StringProperty() + note_title = StringProperty() + note_index = NumericProperty() + + +class Notes(Screen): + + data = ListProperty() + + def _get_data_for_widgets(self): + return [{ + 'note_index': index, + 'note_content': item['content'], + 'note_title': item['title']} + for index, item in enumerate(self.data)] + + data_for_widgets = AliasProperty(_get_data_for_widgets, bind=['data']) + + +class NoteApp(App): + + def build(self): + self.notes = Notes(name='notes') + self.load_notes() + + self.transition = SlideTransition(duration=.35) + root = ScreenManager(transition=self.transition) + root.add_widget(self.notes) + return root + + def load_notes(self): + if not exists(self.notes_fn): + return + with open(self.notes_fn) as fd: + data = json.load(fd) + self.notes.data = data + + def save_notes(self): + with open(self.notes_fn, 'w') as fd: + json.dump(self.notes.data, fd) + + def del_note(self, note_index): + del self.notes.data[note_index] + self.save_notes() + self.refresh_notes() + self.go_notes() + + def edit_note(self, note_index): + note = self.notes.data[note_index] + name = 'note{}'.format(note_index) + + if self.root.has_screen(name): + self.root.remove_widget(self.root.get_screen(name)) + + view = NoteView( + name=name, + note_index=note_index, + note_title=note.get('title'), + note_content=note.get('content')) + + self.root.add_widget(view) + self.transition.direction = 'left' + self.root.current = view.name + + def add_note(self): + self.notes.data.append({'title': 'New note', 'content': ''}) + note_index = len(self.notes.data) - 1 + self.edit_note(note_index) + + def set_note_content(self, note_index, note_content): + self.notes.data[note_index]['content'] = note_content + data = self.notes.data + self.notes.data = [] + self.notes.data = data + self.save_notes() + self.refresh_notes() + + def set_note_title(self, note_index, note_title): + self.notes.data[note_index]['title'] = note_title + self.save_notes() + self.refresh_notes() + + def refresh_notes(self): + data = self.notes.data + self.notes.data = [] + self.notes.data = data + + def go_notes(self): + self.transition.direction = 'right' + self.root.current = 'notes' + + @property + def notes_fn(self): + return join(self.user_data_dir, 'notes.json') + + +if __name__ == '__main__': + NoteApp().run() diff --git a/freechat-client/share/kivy-examples/tutorials/notes/final/note.kv b/freechat-client/share/kivy-examples/tutorials/notes/final/note.kv new file mode 100644 index 0000000..d9677a2 --- /dev/null +++ b/freechat-client/share/kivy-examples/tutorials/notes/final/note.kv @@ -0,0 +1,154 @@ +#:kivy 1.7.1 +#:import Factory kivy.factory.Factory + +: + canvas: + Color: + rgb: .2, .2, .2 + Rectangle: + size: self.size + +: + Label: + id: w_label + pos: root.pos + text: root.text + + TextInput: + id: w_textinput + pos: root.pos + text: root.text + multiline: root.multiline + on_focus: root.check_focus_and_view(self) + +: + RstDocument: + id: w_label + pos: root.pos + text: root.text + + TextInput: + id: w_textinput + pos: root.pos + text: root.text + multiline: root.multiline + on_focus: root.check_focus_and_view(self) + + +: + + on_note_content: app.set_note_content(self.note_index, self.note_content) + on_note_title: app.set_note_title(self.note_index, self.note_title) + + BoxLayout: + + orientation: 'vertical' + + BoxLayout: + + orientation: 'horizontal' + size_hint_y: None + height: '48dp' + padding: '5dp' + + canvas: + Color: + rgb: .3, .3, .3 + Rectangle: + pos: self.pos + size: self.size + + Button: + text: '<' + size_hint_x: None + width: self.height + on_release: app.go_notes() + + MutableLabelTextInput: + text: root.note_title + font_size: '16sp' + multiline: False + on_text: root.note_title = self.text + + Button: + text: 'X' + size_hint_x: None + width: self.height + on_release: app.del_note(root.note_index) + + + MutableRstDocumentTextInput: + text: root.note_content + on_text: root.note_content = self.text + +: + + height: '48sp' + size_hint_y: None + + canvas: + Color: + rgb: .3, .3, .3 + Rectangle: + pos: self.pos + size: self.width, 1 + + BoxLayout: + + padding: '5dp' + + Label: + text: root.note_title + + Button: + text: '>' + size_hint_x: None + width: self.height + on_release: app.edit_note(root.note_index) + +: + + BoxLayout: + + orientation: 'vertical' + + BoxLayout: + + orientation: 'horizontal' + size_hint_y: None + height: '48dp' + padding: '5dp' + + canvas: + Color: + rgb: .3, .3, .3 + Rectangle: + pos: self.pos + size: self.size + + Image: + source: 'data/icon.png' + mipmap: True + size_hint_x: None + width: self.height + + Label: + text: 'Notes' + font_size: '16sp' + + Button: + text: '+' + size_hint_x: None + width: self.height + on_release: app.add_note() + + RecycleView: + data: root.data_for_widgets + viewclass: 'NoteListItem' + RecycleBoxLayout: + default_size: None, dp(56) + default_size_hint: 1, None + size_hint_y: None + height: self.minimum_height + orientation: 'vertical' + spacing: dp(2) diff --git a/freechat-client/share/kivy-examples/tutorials/pong/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/tutorials/pong/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..430d8f1 Binary files /dev/null and b/freechat-client/share/kivy-examples/tutorials/pong/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/tutorials/pong/main.py b/freechat-client/share/kivy-examples/tutorials/pong/main.py new file mode 100644 index 0000000..b3dede4 --- /dev/null +++ b/freechat-client/share/kivy-examples/tutorials/pong/main.py @@ -0,0 +1,82 @@ +import kivy +kivy.require('1.1.1') + +from kivy.app import App +from kivy.uix.widget import Widget +from kivy.properties import ( + NumericProperty, ReferenceListProperty, ObjectProperty, BooleanProperty +) +from kivy.vector import Vector +from kivy.clock import Clock + + +class PongPaddle(Widget): + score = NumericProperty(0) + can_bounce = BooleanProperty(True) + + def bounce_ball(self, ball): + if self.collide_widget(ball) and self.can_bounce: + vx, vy = ball.velocity + offset = (ball.center_y - self.center_y) / (self.height / 2) + bounced = Vector(-1 * vx, vy) + vel = bounced * 1.1 + ball.velocity = vel.x, vel.y + offset + self.can_bounce = False + elif not self.collide_widget(ball) and not self.can_bounce: + self.can_bounce = True + + +class PongBall(Widget): + velocity_x = NumericProperty(0) + velocity_y = NumericProperty(0) + velocity = ReferenceListProperty(velocity_x, velocity_y) + + def move(self): + self.pos = Vector(*self.velocity) + self.pos + + +class PongGame(Widget): + ball = ObjectProperty(None) + player1 = ObjectProperty(None) + player2 = ObjectProperty(None) + + def serve_ball(self, vel=(4, 0)): + self.ball.center = self.center + self.ball.velocity = vel + + def update(self, dt): + self.ball.move() + + # bounce ball off paddles + self.player1.bounce_ball(self.ball) + self.player2.bounce_ball(self.ball) + + # bounce ball off bottom or top + if (self.ball.y < self.y) or (self.ball.top > self.top): + self.ball.velocity_y *= -1 + + # went off a side to score point? + if self.ball.x < self.x: + self.player2.score += 1 + self.serve_ball(vel=(4, 0)) + if self.ball.x > self.width: + self.player1.score += 1 + self.serve_ball(vel=(-4, 0)) + + def on_touch_move(self, touch): + if touch.x < self.width / 3: + self.player1.center_y = touch.y + if touch.x > self.width - self.width / 3: + self.player2.center_y = touch.y + + +class PongApp(App): + def build(self): + game = PongGame() + game.serve_ball() + Clock.schedule_interval(game.update, 1.0 / 60.0) + return game + + +if __name__ == '__main__': + PongApp().run() diff --git a/freechat-client/share/kivy-examples/tutorials/pong/pong.kv b/freechat-client/share/kivy-examples/tutorials/pong/pong.kv new file mode 100644 index 0000000..6cca4a3 --- /dev/null +++ b/freechat-client/share/kivy-examples/tutorials/pong/pong.kv @@ -0,0 +1,53 @@ +#:kivy 1.0.9 + +: + size: 50, 50 + canvas: + Ellipse: + pos: self.pos + size: self.size + +: + size: 25, 200 + canvas: + Rectangle: + pos:self.pos + size:self.size + +: + ball: pong_ball + player1: player_left + player2: player_right + + canvas: + Rectangle: + pos: self.center_x - 5, 0 + size: 10, self.height + + Label: + font_size: 70 + center_x: root.width / 4 + top: root.top - 50 + text: str(root.player1.score) + + Label: + font_size: 70 + center_x: root.width * 3 / 4 + top: root.top - 50 + text: str(root.player2.score) + + PongBall: + id: pong_ball + center: self.parent.center + + PongPaddle: + id: player_left + x: root.x + center_y: root.center_y + + PongPaddle: + id: player_right + x: root.width - self.width + center_y: root.center_y + + diff --git a/freechat-client/share/kivy-examples/tutorials/pong/steps/step1/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/tutorials/pong/steps/step1/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..b87e600 Binary files /dev/null and b/freechat-client/share/kivy-examples/tutorials/pong/steps/step1/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/tutorials/pong/steps/step1/main.py b/freechat-client/share/kivy-examples/tutorials/pong/steps/step1/main.py new file mode 100644 index 0000000..7e63552 --- /dev/null +++ b/freechat-client/share/kivy-examples/tutorials/pong/steps/step1/main.py @@ -0,0 +1,15 @@ +from kivy.app import App +from kivy.uix.widget import Widget + + +class PongGame(Widget): + pass + + +class PongApp(App): + def build(self): + return PongGame() + + +if __name__ == '__main__': + PongApp().run() diff --git a/freechat-client/share/kivy-examples/tutorials/pong/steps/step1/pong.kv b/freechat-client/share/kivy-examples/tutorials/pong/steps/step1/pong.kv new file mode 100644 index 0000000..c858540 --- /dev/null +++ b/freechat-client/share/kivy-examples/tutorials/pong/steps/step1/pong.kv @@ -0,0 +1,2 @@ +#:kivy 1.0.9 + diff --git a/freechat-client/share/kivy-examples/tutorials/pong/steps/step2/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/tutorials/pong/steps/step2/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..f4fa87e Binary files /dev/null and b/freechat-client/share/kivy-examples/tutorials/pong/steps/step2/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/tutorials/pong/steps/step2/main.py b/freechat-client/share/kivy-examples/tutorials/pong/steps/step2/main.py new file mode 100644 index 0000000..7e63552 --- /dev/null +++ b/freechat-client/share/kivy-examples/tutorials/pong/steps/step2/main.py @@ -0,0 +1,15 @@ +from kivy.app import App +from kivy.uix.widget import Widget + + +class PongGame(Widget): + pass + + +class PongApp(App): + def build(self): + return PongGame() + + +if __name__ == '__main__': + PongApp().run() diff --git a/freechat-client/share/kivy-examples/tutorials/pong/steps/step2/pong.kv b/freechat-client/share/kivy-examples/tutorials/pong/steps/step2/pong.kv new file mode 100644 index 0000000..6ef2362 --- /dev/null +++ b/freechat-client/share/kivy-examples/tutorials/pong/steps/step2/pong.kv @@ -0,0 +1,21 @@ +#:kivy 1.0.9 + +: + canvas: + Rectangle: + pos: self.center_x - 5, 0 + size: 10, self.height + + Label: + font_size: 70 + center_x: root.width / 4 + top: root.top - 50 + text: "0" + + Label: + font_size: 70 + center_x: root.width * 3 / 4 + top: root.top - 50 + text: "0" + + diff --git a/freechat-client/share/kivy-examples/tutorials/pong/steps/step3/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/tutorials/pong/steps/step3/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..9b48581 Binary files /dev/null and b/freechat-client/share/kivy-examples/tutorials/pong/steps/step3/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/tutorials/pong/steps/step3/main.py b/freechat-client/share/kivy-examples/tutorials/pong/steps/step3/main.py new file mode 100644 index 0000000..501a2c3 --- /dev/null +++ b/freechat-client/share/kivy-examples/tutorials/pong/steps/step3/main.py @@ -0,0 +1,26 @@ +from kivy.app import App +from kivy.uix.widget import Widget +from kivy.properties import NumericProperty, ReferenceListProperty +from kivy.vector import Vector + + +class PongBall(Widget): + velocity_x = NumericProperty(0) + velocity_y = NumericProperty(0) + velocity = ReferenceListProperty(velocity_x, velocity_y) + + def move(self): + self.pos = Vector(*self.velocity) + self.pos + + +class PongGame(Widget): + pass + + +class PongApp(App): + def build(self): + return PongGame() + + +if __name__ == '__main__': + PongApp().run() diff --git a/freechat-client/share/kivy-examples/tutorials/pong/steps/step3/pong.kv b/freechat-client/share/kivy-examples/tutorials/pong/steps/step3/pong.kv new file mode 100644 index 0000000..c930ef4 --- /dev/null +++ b/freechat-client/share/kivy-examples/tutorials/pong/steps/step3/pong.kv @@ -0,0 +1,31 @@ +#:kivy 1.0.9 + +: + size: 50, 50 + canvas: + Ellipse: + pos: self.pos + size: self.size + +: + canvas: + Rectangle: + pos: self.center_x - 5, 0 + size: 10, self.height + + Label: + font_size: 70 + center_x: root.width / 4 + top: root.top - 50 + text: "0" + + Label: + font_size: 70 + center_x: root.width * 3 / 4 + top: root.top - 50 + text: "0" + + PongBall: + center: self.parent.center + + diff --git a/freechat-client/share/kivy-examples/tutorials/pong/steps/step4/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/tutorials/pong/steps/step4/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..df35fb5 Binary files /dev/null and b/freechat-client/share/kivy-examples/tutorials/pong/steps/step4/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/tutorials/pong/steps/step4/main.py b/freechat-client/share/kivy-examples/tutorials/pong/steps/step4/main.py new file mode 100644 index 0000000..5fe7821 --- /dev/null +++ b/freechat-client/share/kivy-examples/tutorials/pong/steps/step4/main.py @@ -0,0 +1,48 @@ +from kivy.app import App +from kivy.uix.widget import Widget +from kivy.properties import ( + NumericProperty, ReferenceListProperty, ObjectProperty +) +from kivy.vector import Vector +from kivy.clock import Clock +from random import randint + + +class PongBall(Widget): + velocity_x = NumericProperty(0) + velocity_y = NumericProperty(0) + velocity = ReferenceListProperty(velocity_x, velocity_y) + + def move(self): + self.pos = Vector(*self.velocity) + self.pos + + +class PongGame(Widget): + ball = ObjectProperty(None) + + def serve_ball(self): + self.ball.center = self.center + self.ball.velocity = Vector(4, 0).rotate(randint(0, 360)) + + def update(self, dt): + self.ball.move() + + # bounce off top and bottom + if (self.ball.y < 0) or (self.ball.top > self.height): + self.ball.velocity_y *= -1 + + # bounce off left and right + if (self.ball.x < 0) or (self.ball.right > self.width): + self.ball.velocity_x *= -1 + + +class PongApp(App): + def build(self): + game = PongGame() + game.serve_ball() + Clock.schedule_interval(game.update, 1.0 / 60.0) + return game + + +if __name__ == '__main__': + PongApp().run() diff --git a/freechat-client/share/kivy-examples/tutorials/pong/steps/step4/pong.kv b/freechat-client/share/kivy-examples/tutorials/pong/steps/step4/pong.kv new file mode 100644 index 0000000..deb73ec --- /dev/null +++ b/freechat-client/share/kivy-examples/tutorials/pong/steps/step4/pong.kv @@ -0,0 +1,34 @@ +#:kivy 1.0.9 + +: + size: 50, 50 + canvas: + Ellipse: + pos: self.pos + size: self.size + +: + ball: pong_ball + + canvas: + Rectangle: + pos: self.center_x - 5, 0 + size: 10, self.height + + Label: + font_size: 70 + center_x: root.width / 4 + top: root.top - 50 + text: "0" + + Label: + font_size: 70 + center_x: root.width * 3 / 4 + top: root.top - 50 + text: "0" + + PongBall: + id: pong_ball + center: self.parent.center + + diff --git a/freechat-client/share/kivy-examples/tutorials/pong/steps/step5/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/tutorials/pong/steps/step5/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..b7e242d Binary files /dev/null and b/freechat-client/share/kivy-examples/tutorials/pong/steps/step5/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/tutorials/pong/steps/step5/main.py b/freechat-client/share/kivy-examples/tutorials/pong/steps/step5/main.py new file mode 100644 index 0000000..d2152a3 --- /dev/null +++ b/freechat-client/share/kivy-examples/tutorials/pong/steps/step5/main.py @@ -0,0 +1,75 @@ +from kivy.app import App +from kivy.uix.widget import Widget +from kivy.properties import ( + NumericProperty, ReferenceListProperty, ObjectProperty +) +from kivy.vector import Vector +from kivy.clock import Clock + + +class PongPaddle(Widget): + score = NumericProperty(0) + + def bounce_ball(self, ball): + if self.collide_widget(ball): + vx, vy = ball.velocity + offset = (ball.center_y - self.center_y) / (self.height / 2) + bounced = Vector(-1 * vx, vy) + vel = bounced * 1.1 + ball.velocity = vel.x, vel.y + offset + + +class PongBall(Widget): + velocity_x = NumericProperty(0) + velocity_y = NumericProperty(0) + velocity = ReferenceListProperty(velocity_x, velocity_y) + + def move(self): + self.pos = Vector(*self.velocity) + self.pos + + +class PongGame(Widget): + ball = ObjectProperty(None) + player1 = ObjectProperty(None) + player2 = ObjectProperty(None) + + def serve_ball(self, vel=(4, 0)): + self.ball.center = self.center + self.ball.velocity = vel + + def update(self, dt): + self.ball.move() + + # bounce of paddles + self.player1.bounce_ball(self.ball) + self.player2.bounce_ball(self.ball) + + # bounce ball off bottom or top + if (self.ball.y < self.y) or (self.ball.top > self.top): + self.ball.velocity_y *= -1 + + # went of to a side to score point? + if self.ball.x < self.x: + self.player2.score += 1 + self.serve_ball(vel=(4, 0)) + if self.ball.x > self.width: + self.player1.score += 1 + self.serve_ball(vel=(-4, 0)) + + def on_touch_move(self, touch): + if touch.x < self.width / 3: + self.player1.center_y = touch.y + if touch.x > self.width - self.width / 3: + self.player2.center_y = touch.y + + +class PongApp(App): + def build(self): + game = PongGame() + game.serve_ball() + Clock.schedule_interval(game.update, 1.0 / 60.0) + return game + + +if __name__ == '__main__': + PongApp().run() diff --git a/freechat-client/share/kivy-examples/tutorials/pong/steps/step5/pong.kv b/freechat-client/share/kivy-examples/tutorials/pong/steps/step5/pong.kv new file mode 100644 index 0000000..6cca4a3 --- /dev/null +++ b/freechat-client/share/kivy-examples/tutorials/pong/steps/step5/pong.kv @@ -0,0 +1,53 @@ +#:kivy 1.0.9 + +: + size: 50, 50 + canvas: + Ellipse: + pos: self.pos + size: self.size + +: + size: 25, 200 + canvas: + Rectangle: + pos:self.pos + size:self.size + +: + ball: pong_ball + player1: player_left + player2: player_right + + canvas: + Rectangle: + pos: self.center_x - 5, 0 + size: 10, self.height + + Label: + font_size: 70 + center_x: root.width / 4 + top: root.top - 50 + text: str(root.player1.score) + + Label: + font_size: 70 + center_x: root.width * 3 / 4 + top: root.top - 50 + text: str(root.player2.score) + + PongBall: + id: pong_ball + center: self.parent.center + + PongPaddle: + id: player_left + x: root.x + center_y: root.center_y + + PongPaddle: + id: player_right + x: root.width - self.width + center_y: root.center_y + + diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/accordion_1.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/accordion_1.cpython-37.pyc new file mode 100644 index 0000000..9e1fffd Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/accordion_1.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/actionbar.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/actionbar.cpython-37.pyc new file mode 100644 index 0000000..fb0e7b9 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/actionbar.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/asyncimage.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/asyncimage.cpython-37.pyc new file mode 100644 index 0000000..19a02f3 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/asyncimage.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/boxlayout_poshint.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/boxlayout_poshint.cpython-37.pyc new file mode 100644 index 0000000..7ae1d46 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/boxlayout_poshint.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/bubble_test.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/bubble_test.cpython-37.pyc new file mode 100644 index 0000000..165ac99 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/bubble_test.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/camera.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/camera.cpython-37.pyc new file mode 100644 index 0000000..ded948d Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/camera.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/carousel_buttons.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/carousel_buttons.cpython-37.pyc new file mode 100644 index 0000000..1e82815 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/carousel_buttons.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/codeinput.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/codeinput.cpython-37.pyc new file mode 100644 index 0000000..0b34e27 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/codeinput.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/colorpicker.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/colorpicker.cpython-37.pyc new file mode 100644 index 0000000..04fb267 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/colorpicker.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/colorusage.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/colorusage.cpython-37.pyc new file mode 100644 index 0000000..79e3fff Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/colorusage.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/compound_selection.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/compound_selection.cpython-37.pyc new file mode 100644 index 0000000..d8a0130 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/compound_selection.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/customcollide.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/customcollide.cpython-37.pyc new file mode 100644 index 0000000..0268990 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/customcollide.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/effectwidget.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/effectwidget.cpython-37.pyc new file mode 100644 index 0000000..7982fae Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/effectwidget.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/effectwidget2.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/effectwidget2.cpython-37.pyc new file mode 100644 index 0000000..022a419 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/effectwidget2.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/effectwidget3_advanced.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/effectwidget3_advanced.cpython-37.pyc new file mode 100644 index 0000000..8f540c1 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/effectwidget3_advanced.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/fbowidget.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/fbowidget.cpython-37.pyc new file mode 100644 index 0000000..d24b024 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/fbowidget.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/focus_behavior.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/focus_behavior.cpython-37.pyc new file mode 100644 index 0000000..56ba2a3 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/focus_behavior.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/image_mipmap.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/image_mipmap.cpython-37.pyc new file mode 100644 index 0000000..65dead8 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/image_mipmap.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/keyboardlistener.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/keyboardlistener.cpython-37.pyc new file mode 100644 index 0000000..e964108 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/keyboardlistener.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/label_mipmap.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/label_mipmap.cpython-37.pyc new file mode 100644 index 0000000..d9727dc Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/label_mipmap.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/label_sizing.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/label_sizing.cpython-37.pyc new file mode 100644 index 0000000..bbdd5ba Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/label_sizing.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/label_text_size.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/label_text_size.cpython-37.pyc new file mode 100644 index 0000000..3622232 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/label_text_size.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/label_with_markup.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/label_with_markup.cpython-37.pyc new file mode 100644 index 0000000..e4c6efa Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/label_with_markup.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/lang_dynamic_classes.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/lang_dynamic_classes.cpython-37.pyc new file mode 100644 index 0000000..ff10194 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/lang_dynamic_classes.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/pagelayout.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/pagelayout.cpython-37.pyc new file mode 100644 index 0000000..d6dc841 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/pagelayout.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/popup_with_kv.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/popup_with_kv.cpython-37.pyc new file mode 100644 index 0000000..ab80276 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/popup_with_kv.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/rstexample.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/rstexample.cpython-37.pyc new file mode 100644 index 0000000..a2de199 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/rstexample.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/scatter.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/scatter.cpython-37.pyc new file mode 100644 index 0000000..e2d105f Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/scatter.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/screenmanager.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/screenmanager.cpython-37.pyc new file mode 100644 index 0000000..6097470 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/screenmanager.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/scrollview.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/scrollview.cpython-37.pyc new file mode 100644 index 0000000..4702fc1 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/scrollview.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/settings.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/settings.cpython-37.pyc new file mode 100644 index 0000000..6a424c4 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/settings.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/shorten_text.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/shorten_text.cpython-37.pyc new file mode 100644 index 0000000..850ab8d Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/shorten_text.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/spinner.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/spinner.cpython-37.pyc new file mode 100644 index 0000000..e3ead2e Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/spinner.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/splitter.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/splitter.cpython-37.pyc new file mode 100644 index 0000000..9af8434 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/splitter.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/tabbed_panel_showcase.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/tabbed_panel_showcase.cpython-37.pyc new file mode 100644 index 0000000..18ab903 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/tabbed_panel_showcase.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/tabbedpanel.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/tabbedpanel.cpython-37.pyc new file mode 100644 index 0000000..b48bd55 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/tabbedpanel.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/textalign.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/textalign.cpython-37.pyc new file mode 100644 index 0000000..af5a377 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/textalign.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/textinput.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/textinput.cpython-37.pyc new file mode 100644 index 0000000..ada7c4f Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/textinput.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/unicode_textinput.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/unicode_textinput.cpython-37.pyc new file mode 100644 index 0000000..fbc9bac Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/unicode_textinput.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/__pycache__/videoplayer.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/__pycache__/videoplayer.cpython-37.pyc new file mode 100644 index 0000000..81b1405 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/__pycache__/videoplayer.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/accordion_1.py b/freechat-client/share/kivy-examples/widgets/accordion_1.py new file mode 100644 index 0000000..e205743 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/accordion_1.py @@ -0,0 +1,17 @@ +from kivy.uix.accordion import Accordion, AccordionItem +from kivy.uix.label import Label +from kivy.app import App + + +class AccordionApp(App): + def build(self): + root = Accordion() + for x in range(5): + item = AccordionItem(title='Title %d' % x) + item.add_widget(Label(text='Very big content\n' * 10)) + root.add_widget(item) + return root + + +if __name__ == '__main__': + AccordionApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/actionbar.py b/freechat-client/share/kivy-examples/widgets/actionbar.py new file mode 100644 index 0000000..b48db9a --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/actionbar.py @@ -0,0 +1,32 @@ +from kivy.base import runTouchApp +from kivy.lang import Builder + +runTouchApp(Builder.load_string(''' +ActionBar: + pos_hint: {'top':1} + ActionView: + use_separator: True + ActionPrevious: + title: 'Action Bar' + with_previous: False + ActionOverflow: + ActionButton: + icon: 'atlas://data/images/defaulttheme/audio-volume-high' + ActionButton: + important: True + text: 'Important' + ActionButton: + text: 'Btn2' + ActionButton: + text: 'Btn3' + ActionButton: + text: 'Btn4' + ActionGroup: + text: 'Group1' + ActionButton: + text: 'Btn5' + ActionButton: + text: 'Btn6' + ActionButton: + text: 'Btn7' +''')) diff --git a/freechat-client/share/kivy-examples/widgets/asyncimage.py b/freechat-client/share/kivy-examples/widgets/asyncimage.py new file mode 100644 index 0000000..b358443 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/asyncimage.py @@ -0,0 +1,35 @@ +''' +Asynchronous image loading +========================== + +Test of the widget AsyncImage. +We are just putting it in a CenteredAsyncImage for being able to center the +image on screen without doing upscale like the original AsyncImage. +''' + +from kivy.app import App +from kivy.uix.image import AsyncImage +from kivy.lang import Builder + + +Builder.load_string(''' +: + size_hint: 0.8, 0.8 + pos_hint: {'center_x': 0.5, 'center_y': 0.5} + mipmap: True +''') + + +class CenteredAsyncImage(AsyncImage): + pass + + +class TestAsyncApp(App): + def build(self): + url = ('https://upload.wikimedia.org/wikipedia/commons/thumb/8/89/' + 'STS-116_spacewalk_1.jpg/1024px-STS-116_spacewalk_1.jpg') + return CenteredAsyncImage(source=url) + + +if __name__ == '__main__': + TestAsyncApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/boxlayout_poshint.py b/freechat-client/share/kivy-examples/widgets/boxlayout_poshint.py new file mode 100644 index 0000000..70bb2f7 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/boxlayout_poshint.py @@ -0,0 +1,54 @@ +from kivy.uix.gridlayout import GridLayout +from kivy.app import App +from kivy.lang import Builder + +Builder.load_string(''' +: + cols: 1 + + BoxLayout: + orientation: 'vertical' + Button: + size_hint_x: 0.4 + pos_hint: {'x': 0} + text: 'pos_hint: x=0' + + Button: + size_hint_x: 0.2 + pos_hint: {'center_x': 0.5} + text: 'pos_hint: center_x=0.5' + + Button: + size_hint_x: 0.4 + pos_hint: {'right': 1} + text: 'pos_hint: right=1' + + BoxLayout: + Button: + size_hint_y: 0.4 + pos_hint: {'y': 0} + text: 'pos_hint: y=0' + + Button: + size_hint_y: 0.2 + pos_hint: {'center_y': .5} + text: 'pos_hint: center_y=0.5' + + Button: + size_hint_y: 0.4 + pos_hint: {'top': 1} + text: 'pos_hint: top=1' +''') + + +class Demo(GridLayout): + pass + + +class DemoApp(App): + def build(self): + return Demo() + + +if __name__ == '__main__': + DemoApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/bubble_test.py b/freechat-client/share/kivy-examples/widgets/bubble_test.py new file mode 100644 index 0000000..9dfab81 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/bubble_test.py @@ -0,0 +1,59 @@ +''' +Bubble +====== + +Test of the widget Bubble. +''' + +from kivy.app import App +from kivy.uix.floatlayout import FloatLayout +from kivy.uix.button import Button +from kivy.lang import Builder +from kivy.uix.bubble import Bubble + +Builder.load_string(''' + + size_hint: (None, None) + size: (160, 120) + pos_hint: {'center_x': .5, 'y': .6} + BubbleButton: + text: 'Cut' + BubbleButton: + text: 'Copy' + BubbleButton: + text: 'Paste' +''') + + +class cut_copy_paste(Bubble): + pass + + +class BubbleShowcase(FloatLayout): + + def __init__(self, **kwargs): + super(BubbleShowcase, self).__init__(**kwargs) + self.but_bubble = Button(text='Press to show bubble') + self.but_bubble.bind(on_release=self.show_bubble) + self.add_widget(self.but_bubble) + + def show_bubble(self, *l): + if not hasattr(self, 'bubb'): + self.bubb = bubb = cut_copy_paste() + self.add_widget(bubb) + else: + values = ('left_top', 'left_mid', 'left_bottom', 'top_left', + 'top_mid', 'top_right', 'right_top', 'right_mid', + 'right_bottom', 'bottom_left', 'bottom_mid', 'bottom_right') + index = values.index(self.bubb.arrow_pos) + self.bubb.arrow_pos = values[(index + 1) % len(values)] + + +class TestBubbleApp(App): + + def build(self): + return BubbleShowcase() + + +if __name__ == '__main__': + TestBubbleApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/camera.py b/freechat-client/share/kivy-examples/widgets/camera.py new file mode 100644 index 0000000..00309bb --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/camera.py @@ -0,0 +1,33 @@ +from kivy.app import App +from kivy.lang import Builder + + +kv = ''' +BoxLayout: + orientation: 'vertical' + + Camera: + id: camera + resolution: 399, 299 + + BoxLayout: + orientation: 'horizontal' + size_hint_y: None + height: '48dp' + Button: + text: 'Start' + on_release: camera.play = True + + Button: + text: 'Stop' + on_release: camera.play = False +''' + + +class CameraApp(App): + def build(self): + return Builder.load_string(kv) + + +if __name__ == '__main__': + CameraApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/carousel_buttons.py b/freechat-client/share/kivy-examples/widgets/carousel_buttons.py new file mode 100644 index 0000000..2904685 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/carousel_buttons.py @@ -0,0 +1,50 @@ +''' +Carousel example with button inside. +This is a tiny test for testing the scroll distance/timeout +And ensure the down/up are dispatched if no gesture is done. +''' +from kivy.uix.carousel import Carousel +from kivy.uix.gridlayout import GridLayout +from kivy.app import App +from kivy.lang import Builder + +Builder.load_string(''' +: + cols: 3 + Label: + text: str(id(root)) + Button + Button + Button + Button + text: 'load(page 3)' + on_release: + carousel = root.parent.parent + carousel.load_slide(carousel.slides[2]) + Button + Button + text: 'prev' + on_release: + root.parent.parent.load_previous() + Button + Button + text: 'next' + on_release: + root.parent.parent.load_next() +''') + + +class Page(GridLayout): + pass + + +class TestApp(App): + def build(self): + root = Carousel() + for x in range(10): + root.add_widget(Page()) + return root + + +if __name__ == '__main__': + TestApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/cityCC0.mpg b/freechat-client/share/kivy-examples/widgets/cityCC0.mpg new file mode 100644 index 0000000..626b342 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/cityCC0.mpg differ diff --git a/freechat-client/share/kivy-examples/widgets/cityCC0.png b/freechat-client/share/kivy-examples/widgets/cityCC0.png new file mode 100644 index 0000000..3b91d9e Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/cityCC0.png differ diff --git a/freechat-client/share/kivy-examples/widgets/codeinput.py b/freechat-client/share/kivy-examples/widgets/codeinput.py new file mode 100644 index 0000000..34fbb4e --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/codeinput.py @@ -0,0 +1,225 @@ +from kivy.app import App +from kivy.extras.highlight import KivyLexer +from kivy.uix.spinner import Spinner, SpinnerOption +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.codeinput import CodeInput +from kivy.uix.behaviors import EmacsBehavior +from kivy.uix.popup import Popup +from kivy.properties import ListProperty +from kivy.core.window import Window +from kivy.core.text import LabelBase +from pygments import lexers +import codecs +import os + +example_text = ''' +---------------------Python---------------------------------- +import kivy +kivy.require('1.0.6') # replace with your current kivy version ! +from kivy.app import App +from kivy.uix.button import Button + +class MyApp(App): + def build(self): + return Button(text='Hello World') + +if __name__ == '__main__': + MyApp().run() +----------------------Java----------------------------------- + +public static byte toUnsignedByte(int intVal) { + byte byteVal; + return (byte)(intVal & 0xFF); +} +---------------------kv lang--------------------------------- +#:kivy 1.0 + +: + canvas: + Color: + rgb: .5, .5, .5 + Rectangle: + pos: self.pos + size: self.size +---------------------HTML------------------------------------ + +
+ + + +----------------------Emacs key bindings--------------------- +This CodeInput inherits from EmacsBehavior, so you can use Emacs key bindings +if you want! To try out Emacs key bindings, set the "Key bindings" option to +"Emacs". Experiment with the shortcuts below on some of the text in this window +(just be careful not to delete the cheat sheet before you have made note of the +commands!) + +Shortcut Description +-------- ----------- +Control + a Move cursor to the beginning of the line +Control + e Move cursor to the end of the line +Control + f Move cursor one character to the right +Control + b Move cursor one character to the left +Alt + f Move cursor to the end of the word to the right +Alt + b Move cursor to the start of the word to the left +Alt + Backspace Delete text left of the cursor to the beginning of word +Alt + d Delete text right of the cursor to the end of the word +Alt + w Copy selection +Control + w Cut selection +Control + y Paste selection +''' + + +class Fnt_SpinnerOption(SpinnerOption): + pass + + +class LoadDialog(Popup): + + def load(self, path, selection): + self.choosen_file = [None, ] + self.choosen_file = selection + Window.title = selection[0][selection[0].rfind(os.sep) + 1:] + self.dismiss() + + def cancel(self): + self.dismiss() + + +class SaveDialog(Popup): + + def save(self, path, selection): + _file = codecs.open(selection, 'w', encoding='utf8') + _file.write(self.text) + Window.title = selection[selection.rfind(os.sep) + 1:] + _file.close() + self.dismiss() + + def cancel(self): + self.dismiss() + + +class CodeInputWithBindings(EmacsBehavior, CodeInput): + '''CodeInput with keybindings. + To add more bindings, add the behavior before CodeInput in the class + definition. + ''' + pass + + +class CodeInputTest(App): + + files = ListProperty([None, ]) + + def build(self): + b = BoxLayout(orientation='vertical') + languages = Spinner( + text='language', + values=sorted(['KvLexer', ] + list(lexers.LEXERS.keys()))) + + languages.bind(text=self.change_lang) + + menu = BoxLayout( + size_hint_y=None, + height='30pt') + fnt_size = Spinner( + text='12', + values=list(map(str, list(range(5, 40))))) + fnt_size.bind(text=self._update_size) + + fonts = [ + file for file in LabelBase._font_dirs_files + if file.endswith('.ttf')] + + fnt_name = Spinner( + text='RobotoMono', + option_cls=Fnt_SpinnerOption, + values=fonts) + fnt_name.bind(text=self._update_font) + mnu_file = Spinner( + text='File', + values=('Open', 'SaveAs', 'Save', 'Close')) + mnu_file.bind(text=self._file_menu_selected) + key_bindings = Spinner( + text='Key bindings', + values=('Default key bindings', 'Emacs key bindings')) + key_bindings.bind(text=self._bindings_selected) + + menu.add_widget(mnu_file) + menu.add_widget(fnt_size) + menu.add_widget(fnt_name) + menu.add_widget(languages) + menu.add_widget(key_bindings) + b.add_widget(menu) + + self.codeinput = CodeInputWithBindings( + lexer=KivyLexer(), + font_size=12, + text=example_text, + key_bindings='default', + ) + + b.add_widget(self.codeinput) + + return b + + def _update_size(self, instance, size): + self.codeinput.font_size = float(size) + + def _update_font(self, instance, fnt_name): + instance.font_name = self.codeinput.font_name = fnt_name + + def _file_menu_selected(self, instance, value): + if value == 'File': + return + instance.text = 'File' + if value == 'Open': + if not hasattr(self, 'load_dialog'): + self.load_dialog = LoadDialog() + self.load_dialog.open() + self.load_dialog.bind(choosen_file=self.setter('files')) + elif value == 'SaveAs': + if not hasattr(self, 'saveas_dialog'): + self.saveas_dialog = SaveDialog() + self.saveas_dialog.text = self.codeinput.text + self.saveas_dialog.open() + elif value == 'Save': + if self.files[0]: + _file = codecs.open(self.files[0], 'w', encoding='utf8') + _file.write(self.codeinput.text) + _file.close() + elif value == 'Close': + if self.files[0]: + self.codeinput.text = '' + Window.title = 'untitled' + + def _bindings_selected(self, instance, value): + value = value.split(' ')[0] + self.codeinput.key_bindings = value.lower() + + def on_files(self, instance, values): + if not values[0]: + return + _file = codecs.open(values[0], 'r', encoding='utf8') + self.codeinput.text = _file.read() + _file.close() + + def change_lang(self, instance, z): + if z == 'KvLexer': + lx = KivyLexer() + else: + lx = lexers.get_lexer_by_name(lexers.LEXERS[z][2][0]) + self.codeinput.lexer = lx + + +if __name__ == '__main__': + CodeInputTest().run() diff --git a/freechat-client/share/kivy-examples/widgets/codeinputtest.kv b/freechat-client/share/kivy-examples/widgets/codeinputtest.kv new file mode 100644 index 0000000..3819375 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/codeinputtest.kv @@ -0,0 +1,53 @@ +#:import os os +: + font_name: self.text + +: + title: filechooser.path + choosen_file: None + BoxLayout: + size: root.size + pos: root.pos + orientation: "vertical" + FileChooserListView: + id: filechooser + path: os.getcwd() + + BoxLayout: + size_hint_y: None + height: 30 + Button: + text: "Cancel" + on_release: root.cancel() + + Button: + text: "Load" + on_release: root.load(filechooser.path, filechooser.selection) + +: + text_input: text_input + BoxLayout: + size: root.size + pos: root.pos + orientation: "vertical" + FileChooserListView: + id: filechooser + path: os.getcwd() + on_selection: text_input.text = self.selection and self.selection[0] or '' + + TextInput: + id: text_input + size_hint_y: None + height: 30 + multiline: False + + BoxLayout: + size_hint_y: None + height: 30 + Button: + text: "Cancel" + on_release: root.cancel() + + Button: + text: "Save" + on_release: root.save(filechooser.path, text_input.text) diff --git a/freechat-client/share/kivy-examples/widgets/colorpicker.py b/freechat-client/share/kivy-examples/widgets/colorpicker.py new file mode 100644 index 0000000..5c2d645 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/colorpicker.py @@ -0,0 +1,234 @@ +from kivy.app import App +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.scatter import Scatter +from kivy.uix.popup import Popup +from kivy.properties import ObjectProperty, StringProperty +from kivy.graphics import Color, Point + +from math import sqrt +from os import walk +from os.path import dirname, join + +from kivy.lang import Builder + +Builder.load_string(''' +#:import os os +: + # each time a picture is created, the image can delay the loading + # as soon as the image is loaded, ensure that the center is changed + # to the center of the screen. + on_size: self.center = app.main_root_widget.center + size: img.size + size_hint: None, None + on_touch_down: if self.collide_point(*args[1].pos): app.current_image = img + + Image: + id: img + source: root.source + + # create initial image to be 400 pixels width + size: 400, 400 / self.image_ratio + + # add shadow background + canvas.before: + Color: + rgba: 1, 1, 1, 1 + BorderImage: + source: '../demo/pictures/shadow32.png' + border: (36, 36, 36, 36) + size:(self.width + 72, self.height + 72) + pos: (-36, -36) + +: + color: 1, 1, 1, 1 + title: 'Color Slector' + content:content + BoxLayout: + id: content + orientation: 'vertical' + ColorPicker: + id: clr_picker + color: root.color + BoxLayout: + size_hint_y: None + height: '27sp' + Button: + text: 'ok' + on_release: + root.color = clr_picker.color + root.dismiss() + Button: + text: 'cancel' + on_release: root.dismiss() + + + orientation: 'vertical' + padding: '2pt' + canvas.before: + Color: + rgba: .5, .4, .9, .2 + Rectangle: + pos: self.pos + size: self.size + Label: + size_hint_y: None + font_size: '18sp' + text_size: self.width, None + valign: 'middle' + halign: 'center' + height: self.texture.size[1] if self.texture else 10 + text: + ("Selected Image:\\n" + app.current_image.source.split(os.sep)[-1] + if app.current_image else 'None') + Button: + text: 'Brush' + size_hint_y: None + height: self.parent.width + on_release: + app.color_selector.open() + app.color_mode = 'brush' + Image: + color: app.color_selector.color + source: '../demo/touchtracer/particle.png' + allow_stretch: True + size: self.parent.size + pos: self.parent.pos + Button: + text: 'cursor' + on_release: app.color_mode = 'cursor' + Button: + text: 'clear' + on_release: + app.handle_clear() + + + current_image: None + client_area: client_area + RelativeLayout: + id: client_area + Splitter: + sizable_from: 'left' + size_hint: None, 1 + width: '99dp' + LeftPanel: + +''') + + +def calculate_points(x1, y1, x2, y2, steps=5): + dx = x2 - x1 + dy = y2 - y1 + dist = sqrt(dx * dx + dy * dy) + if dist < steps: + return + o = [] + m = dist / steps + for i in range(1, int(m)): + mi = i / m + lastx = x1 + dx * mi + lasty = y1 + dy * mi + o.extend([lastx, lasty]) + return o + + +class ColorSelector(Popup): + pass + + +class Picture(Scatter): + + source = StringProperty(None) + '''path to the Image to be loaded + ''' + + def __init__(self, **kwargs): + super(Picture, self).__init__(**kwargs) + self._app = App.get_running_app() + + def on_touch_down(self, touch): + _app = self._app + if (_app.color_mode[0] == 'c' or + not self.collide_point(*touch.pos)): + return super(Picture, self).on_touch_down(touch) + ud = touch.ud + ud['group'] = g = str(touch.uid) + _pos = list(self.ids.img.to_widget(*touch.pos)) + _pos[0] += self.parent.x + with self.ids.img.canvas.after: + ud['color'] = Color(*_app.color_selector.color, group=g) + ud['lines'] = Point(points=(_pos), + source='../demo/touchtracer/particle.png', + pointsize=5, group=g) + touch.grab(self) + return True + + def on_touch_move(self, touch): + if touch.grab_current is not self: + return + _app = self._app + if _app.color_mode[0] == 'c' or not self.collide_point(*touch.pos): + return super(Picture, self).on_touch_move(touch) + ud = touch.ud + _pos = list(self.ids.img.to_widget(*touch.pos)) + _pos[0] += self.parent.x + points = ud['lines'].points + oldx, oldy = points[-2], points[-1] + points = calculate_points(oldx, oldy, _pos[0], _pos[1]) + if points: + try: + lp = ud['lines'].add_point + for idx in range(0, len(points), 2): + lp(points[idx], points[idx + 1]) + except GraphicException: + pass + + def on_touch_up(self, touch): + if touch.grab_current is not self: + return + _app = self._app + if _app.color_mode[0] == 'c': + return super(Picture, self).on_touch_up(touch) + touch.ungrab(self) + ud = touch.ud + self.canvas.remove_group(ud['group']) + + +class MainRootWidget(BoxLayout): + + clent_area = ObjectProperty(None) + # The Client Area in which all editing is Done + + def on_parent(self, instance, parent): + if parent: + _dir = join(dirname(__file__), 'lists/fruit_images/') + for image in list(walk(_dir))[0][2]: + if image.find('512') > -1: + self.client_area.add_widget(Picture(source=_dir + image)) + + +class MainApp(App): + + main_root_widget = ObjectProperty(None) + # we will be accessing this later as App.main_root_widget + + current_image = ObjectProperty(None) + '''This is a handle to the currently selected image on which the effects + would be applied.''' + + color_mode = StringProperty('cursor') + '''This defines the current mode `brush` or `cursor`. `brush` mode allows + adding brush strokes to the currently selected Image. + ''' + + def build(self): + self.color_selector = ColorSelector() + self.main_root_widget = MainRootWidget() + return self.main_root_widget + + def handle_clear(self): + if self.current_image: + self.current_image.canvas.after.clear() + + +if __name__ == '__main__': + MainApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/colorusage.py b/freechat-client/share/kivy-examples/widgets/colorusage.py new file mode 100644 index 0000000..618cd94 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/colorusage.py @@ -0,0 +1,62 @@ +from kivy.app import App +from kivy.uix.gridlayout import GridLayout +from kivy.lang import Builder + +Builder.load_string(""" +#:import hex kivy.utils.get_color_from_hex + +: + cols: 2 + canvas: + Color: + rgba: 1, 1, 1, 1 + Rectangle: + pos: self.pos + size: self.size + + Label: + canvas.before: + Color: + rgb: 39/255., 174/255., 96/255. + Rectangle: + pos: self.pos + size: self.size + text: "rgb: 39/255., 174/255., 96/255." + Label: + canvas.before: + Color: + rgba: 39/255., 174/255., 96/255., 1 + Rectangle: + pos: self.pos + size: self.size + text: "rgba: 39/255., 174/255., 96/255., 1" + Label: + canvas.before: + Color: + hsv: 145/360., 77.6/100, 68.2/100 + Rectangle: + pos: self.pos + size: self.size + text: "hsv: 145/360., 77.6/100, 68.2/100" + Label: + canvas.before: + Color: + rgba: hex('#27ae60') + Rectangle: + pos: self.pos + size: self.size + text: "rgba: hex('#27ae60')" +""") + + +class Root(GridLayout): + pass + + +class ColorusageApp(App): + def build(self): + return Root() + + +if __name__ == "__main__": + ColorusageApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/compound_selection.py b/freechat-client/share/kivy-examples/widgets/compound_selection.py new file mode 100644 index 0000000..98ab7f5 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/compound_selection.py @@ -0,0 +1,83 @@ +from kivy.uix.gridlayout import GridLayout +from kivy.uix.button import Button +from kivy.uix.behaviors import CompoundSelectionBehavior +from kivy.uix.behaviors import FocusBehavior +from kivy.app import runTouchApp + + +class SelectableGrid(FocusBehavior, CompoundSelectionBehavior, GridLayout): + + def __init__(self, **kwargs): + super(SelectableGrid, self).__init__(**kwargs) + + def print_selection(*l): + print('selected: ', [x.text for x in self.selected_nodes]) + self.bind(selected_nodes=print_selection) + + def keyboard_on_key_down(self, window, keycode, text, modifiers): + if super(SelectableGrid, self).keyboard_on_key_down( + window, keycode, text, modifiers): + return True + if self.select_with_key_down(window, keycode, text, modifiers): + return True + return False + + def keyboard_on_key_up(self, window, keycode): + if super(SelectableGrid, self).keyboard_on_key_up(window, keycode): + return True + if self.select_with_key_up(window, keycode): + return True + return False + + def goto_node(self, key, last_node, last_node_idx): + ''' This function is used to go to the node by typing the number + of the text of the button. + ''' + node, idx = super(SelectableGrid, self).goto_node(key, last_node, + last_node_idx) + if node != last_node: + return node, idx + + items = list(enumerate(self.get_selectable_nodes())) + '''If self.nodes_order_reversed (the default due to using + self.children which is reversed), the index is counted from the + starts of the selectable nodes, like normal but the nodes are traversed + in the reverse order. + ''' + # start searching after the last selected node + if not self.nodes_order_reversed: + items = items[last_node_idx + 1:] + items[:last_node_idx + 1] + else: + items = items[:last_node_idx][::-1] + items[last_node_idx:][::-1] + + for i, child in items: + if child.text.startswith(key): + return child, i + return node, idx + + def select_node(self, node): + node.background_color = (1, 0, 0, 1) + return super(SelectableGrid, self).select_node(node) + + def deselect_node(self, node): + node.background_color = (1, 1, 1, 1) + super(SelectableGrid, self).deselect_node(node) + + def do_touch(self, instance, touch): + if ('button' in touch.profile and touch.button in + ('scrollup', 'scrolldown', 'scrollleft', 'scrollright')) or\ + instance.collide_point(*touch.pos): + self.select_with_touch(instance, touch) + else: + return False + return True + + +root = SelectableGrid(cols=5, up_count=5, multiselect=True, scroll_count=1) +for i in range(40): + c = Button(text=str(i)) + c.bind(on_touch_down=root.do_touch) + root.add_widget(c) + + +runTouchApp(root) diff --git a/freechat-client/share/kivy-examples/widgets/customcollide.py b/freechat-client/share/kivy-examples/widgets/customcollide.py new file mode 100644 index 0000000..a8df02a --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/customcollide.py @@ -0,0 +1,82 @@ +''' +Custom shape & collide widget +============================= + +This is a Triangle widget with a triangle shape based on 3 points (p1, p2, p3), +plus a custom collision function. + +The p1, p2, p3 are automatically calculated from the position and the size of +the Widget bounding box. We are using them to draw the triangle shape. +(Please note in the kv the special case for Scatter.) + +Then we need to setup a new collision function to collide only on the triangle. +We are using a external method that will check if a point is inside a polygon +(we consider our triangle as a polygon). +''' + + +import kivy +kivy.require('1.0.8') + +from kivy.uix.scatter import Scatter +from kivy.properties import ListProperty +from kivy.lang import Builder + + +Builder.load_string(''' +: + # example for doing a triangle + # this will automatically recalculate pX from pos/size + p1: 0, 0 + p2: self.width, 0 + p3: self.width / 2, self.height + + # If you use a Widget instead of Scatter as base class, you need that: + #p1: self.pos + #p2: self.right, self.y + #p3: self.center_x, self.top + + # draw something + canvas: + Color: + rgb: 1, 0, 0 + Triangle: + points: self.p1 + self.p2 + self.p3 +''') + + +def point_inside_polygon(x, y, poly): + '''Taken from http://www.ariel.com.au/a/python-point-int-poly.html + ''' + n = len(poly) + inside = False + p1x = poly[0] + p1y = poly[1] + for i in range(0, n + 2, 2): + p2x = poly[i % n] + p2y = poly[(i + 1) % n] + if y > min(p1y, p2y): + if y <= max(p1y, p2y): + if x <= max(p1x, p2x): + if p1y != p2y: + xinters = (y - p1y) * (p2x - p1x) / (p2y - p1y) + p1x + if p1x == p2x or x <= xinters: + inside = not inside + p1x, p1y = p2x, p2y + return inside + + +class Triangle(Scatter): + p1 = ListProperty([0, 0]) + p2 = ListProperty([0, 0]) + p3 = ListProperty([0, 0]) + + def collide_point(self, x, y): + x, y = self.to_local(x, y) + return point_inside_polygon(x, y, + self.p1 + self.p2 + self.p3) + + +if __name__ == '__main__': + from kivy.base import runTouchApp + runTouchApp(Triangle(size_hint=(None, None))) diff --git a/freechat-client/share/kivy-examples/widgets/effectwidget.py b/freechat-client/share/kivy-examples/widgets/effectwidget.py new file mode 100644 index 0000000..f8a652d --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/effectwidget.py @@ -0,0 +1,200 @@ +''' +Example usage of the effectwidget. + +Currently highly experimental. +''' + +from kivy.app import App +from kivy.uix.effectwidget import EffectWidget +from kivy.uix.spinner import Spinner +from kivy.uix.boxlayout import BoxLayout +from kivy.lang import Builder +from kivy.properties import ObjectProperty + +from kivy.uix.effectwidget import (MonochromeEffect, + InvertEffect, + ScanlinesEffect, + ChannelMixEffect, + ScanlinesEffect, + FXAAEffect, + PixelateEffect, + HorizontalBlurEffect, + VerticalBlurEffect) + + +class ComparisonWidget(EffectWidget): + pass + + +class ComparisonWidget(EffectWidget): + pass + + +class EffectSpinner(Spinner): + pass + + +class SpinnerRow(BoxLayout): + effectwidget = ObjectProperty() + + def update_effectwidget(self, *args): + effects = [] + for child in self.children[::-1]: + text = child.text + if text == 'none': + pass + if text == 'fxaa': + effects.append(FXAAEffect()) + if text == 'monochrome': + effects.append(MonochromeEffect()) + if text == 'invert': + effects.append(InvertEffect()) + if text == 'mix': + effects.append(ChannelMixEffect()) + if text == 'flash': + effects.append(FlashEffect()) + if text == 'blur_h': + effects.append(HorizontalBlurEffect()) + if text == 'blur_v': + effects.append(VerticalBlurEffect()) + if text == 'postprocessing': + effects.append(ScanlinesEffect()) + if text == 'pixelate': + effects.append(PixelateEffect()) + + if self.effectwidget: + self.effectwidget.effects = effects + + +example = Builder.load_string(''' +#:import Vector kivy.vector.Vector +BoxLayout: + orientation: 'vertical' + FloatLayout: + ComparisonWidget: + pos_hint: {'x': 0, 'y': 0} + size_hint: 0.5, 1 + id: effect1 + ComparisonWidget: + pos_hint: {'x': pos_slider.value, 'y': 0} + size_hint: 0.5, 1 + id: effect2 + background_color: (rs.value, gs.value, bs.value, als.value) + SpinnerRow: + effectwidget: effect1 + text: 'left effects' + SpinnerRow: + effectwidget: effect2 + text: 'right effects' + BoxLayout: + size_hint_y: None + height: sp(40) + Label: + text: 'control overlap:' + Slider: + min: 0 + max: 0.5 + value: 0.5 + id: pos_slider + BoxLayout: + size_hint_y: None + height: sp(40) + Label: + text: 'right bg r,g,b,a' + Slider: + min: 0 + max: 1 + value: 0 + id: rs + Slider: + min: 0 + max: 1 + value: 0 + id: gs + Slider: + min: 0 + max: 1 + value: 0 + id: bs + Slider: + min: 0 + max: 1 + value: 0 + id: als + + +: + Widget: + canvas: + Color: + rgba: 1, 0, 0, 1 + Ellipse: + pos: Vector(self.pos) + 0.5*Vector(self.size) + size: 0.4*Vector(self.size) + Color: + rgba: 0, 1, 0.3, 1 + Ellipse: + pos: Vector(self.pos) + 0.1*Vector(self.size) + size: 0.6*Vector(self.size) + Color: + rgba: 0.5, 0.3, 0.8, 1 + Ellipse: + pos: Vector(self.pos) + Vector([0, 0.6])*Vector(self.size) + size: 0.4*Vector(self.size) + Color: + rgba: 1, 0.8, 0.1, 1 + Ellipse: + pos: Vector(self.pos) + Vector([0.5, 0])*Vector(self.size) + size: 0.4*Vector(self.size) + Color: + rgba: 0, 0, 0.8, 1 + Line: + points: + [self.x, self.y, + self.x + self.width, self.y + 0.3*self.height, + self.x + 0.2*self.width, self.y + 0.1*self.height, + self.x + 0.85*self.width, self.y + 0.72*self.height, + self.x + 0.31*self.width, self.y + 0.6*self.height, + self.x, self.top] + width: 1 + Color: + rgba: 0, 0.9, 0.1, 1 + Line: + points: + [self.x + self.width, self.y + self.height, + self.x + 0.35*self.width, self.y + 0.6*self.height, + self.x + 0.7*self.width, self.y + 0.15*self.height, + self.x + 0.2*self.width, self.y + 0.22*self.height, + self.x + 0.3*self.width, self.y + 0.92*self.height] + width: 2 + +: + orientation: 'horizontal' + size_hint_y: None + height: dp(40) + text: '' + Label: + text: root.text + EffectSpinner: + on_text: root.update_effectwidget() + EffectSpinner: + on_text: root.update_effectwidget() + EffectSpinner: + on_text: root.update_effectwidget() + +: + text: 'none' + values: + ['none', 'fxaa', 'monochrome', + 'invert', 'mix', + 'blur_h', 'blur_v', + 'postprocessing', 'pixelate',] +''') + + +class EffectApp(App): + def build(self): + return example + + +EffectApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/effectwidget2.py b/freechat-client/share/kivy-examples/widgets/effectwidget2.py new file mode 100644 index 0000000..1c6f0b5 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/effectwidget2.py @@ -0,0 +1,47 @@ +''' +This is an example of creating your own effect by writing a glsl string. +''' + +from kivy.base import runTouchApp +from kivy.lang import Builder +from kivy.uix.effectwidget import EffectWidget, EffectBase + + +# The effect string is glsl code defining an effect function. +effect_string = ''' +vec4 effect(vec4 color, sampler2D texture, vec2 tex_coords, vec2 coords) +{ + // Note that time is a uniform variable that is automatically + // provided to all effects. + float red = color.x * abs(sin(time*2.0)); + float green = color.y; // No change + float blue = color.z * (1.0 - abs(sin(time*2.0))); + return vec4(red, green, blue, color.w); +} +''' + + +class DemoEffect(EffectWidget): + def __init__(self, *args, **kwargs): + self.effect_reference = EffectBase(glsl=effect_string) + super(DemoEffect, self).__init__(*args, **kwargs) + + +widget = Builder.load_string(''' +DemoEffect: + effects: [self.effect_reference] if checkbox.active else [] + orientation: 'vertical' + Button: + text: 'Some text so you can see what happens.' + BoxLayout: + size_hint_y: None + height: dp(50) + Label: + text: 'Enable effect?' + CheckBox: + id: checkbox + active: True +''') + + +runTouchApp(widget) diff --git a/freechat-client/share/kivy-examples/widgets/effectwidget3_advanced.py b/freechat-client/share/kivy-examples/widgets/effectwidget3_advanced.py new file mode 100644 index 0000000..fbaf88f --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/effectwidget3_advanced.py @@ -0,0 +1,63 @@ +''' +This example demonstrates creating and usind an AdvancedEffectBase. In +this case, we use it to efficiently pass the touch coordinates into the shader. +''' + +from kivy.base import runTouchApp +from kivy.properties import ListProperty +from kivy.lang import Builder +from kivy.uix.effectwidget import EffectWidget, AdvancedEffectBase + + +effect_string = ''' +uniform vec2 touch; + +vec4 effect(vec4 color, sampler2D texture, vec2 tex_coords, vec2 coords) +{ + vec2 distance = 0.025*(coords - touch); + float dist_mag = (distance.x*distance.x + distance.y*distance.y); + vec3 multiplier = vec3(abs(sin(dist_mag - time))); + return vec4(multiplier * color.xyz, 1.0); +} +''' + + +class TouchEffect(AdvancedEffectBase): + touch = ListProperty([0.0, 0.0]) + + def __init__(self, *args, **kwargs): + super(TouchEffect, self).__init__(*args, **kwargs) + self.glsl = effect_string + + self.uniforms = {'touch': [0.0, 0.0]} + + def on_touch(self, *args, **kwargs): + self.uniforms['touch'] = [float(i) for i in self.touch] + + +class TouchWidget(EffectWidget): + def __init__(self, *args, **kwargs): + super(TouchWidget, self).__init__(*args, **kwargs) + self.effect = TouchEffect() + self.effects = [self.effect] + + def on_touch_down(self, touch): + super(TouchWidget, self).on_touch_down(touch) + self.on_touch_move(touch) + + def on_touch_move(self, touch): + self.effect.touch = touch.pos + + +root = Builder.load_string(''' +TouchWidget: + Button: + text: 'Some text!' + Image: + source: 'data/logo/kivy-icon-512.png' + allow_stretch: True + keep_ratio: False +''') + + +runTouchApp(root) diff --git a/freechat-client/share/kivy-examples/widgets/fbowidget.py b/freechat-client/share/kivy-examples/widgets/fbowidget.py new file mode 100644 index 0000000..898463f --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/fbowidget.py @@ -0,0 +1,111 @@ +''' +FBO example +=========== + +This is an example of how to use FBO (Frame Buffer Object) to speedup graphics. +An Fbo is like a texture that you can draw on it. + +By default, all the children are added in the canvas of the parent. +When you are displaying thousand of widget, you'll do thousands of graphics +instructions each frame. +The idea is to do this drawing only one time in a Fbo, and then, draw the Fbo +every frame instead of all children's graphics instructions. + +We created a FboFloatLayout that create his canvas, and a Fbo. +After the Fbo is created, we are adding Color and Rectangle instruction to +display the texture of the Fbo itself. +The overload of on_pos/on_size are here to update size of Fbo if needed, and +adapt the position/size of the rectangle too. + +Then, when a child is added or removed, we are redirecting addition/removal of +graphics instruction to our Fbo. This is why add_widget/remove_widget are +overloaded too. + +.. note:: + + This solution can be helpful but not ideal. Multisampling are not available + in Framebuffer. We will work to add the support of it if the hardware is + capable of, but it could be not the same. + +''' + + +# needed to create Fbo, must be resolved in future kivy version +from kivy.core.window import Window + +from kivy.graphics import Color, Rectangle, Canvas +from kivy.graphics.fbo import Fbo +from kivy.uix.floatlayout import FloatLayout +from kivy.properties import ObjectProperty + + +class FboFloatLayout(FloatLayout): + + texture = ObjectProperty(None, allownone=True) + + def __init__(self, **kwargs): + self.canvas = Canvas() + with self.canvas: + self.fbo = Fbo(size=self.size) + Color(1, 1, 1) + self.fbo_rect = Rectangle() + + # wait that all the instructions are in the canvas to set texture + self.texture = self.fbo.texture + super(FboFloatLayout, self).__init__(**kwargs) + + def add_widget(self, *largs): + # trick to attach graphics instruction to fbo instead of canvas + canvas = self.canvas + self.canvas = self.fbo + ret = super(FboFloatLayout, self).add_widget(*largs) + self.canvas = canvas + return ret + + def remove_widget(self, *largs): + canvas = self.canvas + self.canvas = self.fbo + super(FboFloatLayout, self).remove_widget(*largs) + self.canvas = canvas + + def on_size(self, instance, value): + self.fbo.size = value + self.texture = self.fbo.texture + self.fbo_rect.size = value + + def on_pos(self, instance, value): + self.fbo_rect.pos = value + + def on_texture(self, instance, value): + self.fbo_rect.texture = value + + +if __name__ == '__main__': + from kivy.uix.button import Button + from kivy.app import App + + class TestFboApp(App): + def build(self): + + # test with FboFloatLayout or FloatLayout + # comment/uncomment to test it + root = FboFloatLayout() + # root = FloatLayout() + + # this part of creation can be slow. try to optimize the loop a + # little bit. + s = 30 + size = (s, s) + sh = (None, None) + add = root.add_widget + print('Creating 5000 widgets...') + for i in range(5000): + x = (i % 40) * s + y = int(i / 40) * s + add(Button(text=str(i), pos=(x, y), size_hint=sh, size=size)) + if i % 1000 == 1000 - 1: + print(5000 - i - 1, 'left...') + + return root + + TestFboApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/focus_behavior.py b/freechat-client/share/kivy-examples/widgets/focus_behavior.py new file mode 100644 index 0000000..bf4fcbc --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/focus_behavior.py @@ -0,0 +1,98 @@ +from kivy.app import App +from kivy.uix.gridlayout import GridLayout +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.label import Label +from kivy.uix.behaviors import FocusBehavior +from kivy.graphics import Color, Rectangle + + +class FocusWithColor(FocusBehavior): + ''' Class that when focused, changes its background color to red. + ''' + + _color = None + _rect = None + + def __init__(self, **kwargs): + super(FocusWithColor, self).__init__(**kwargs) + with self.canvas: + self._color = Color(1, 1, 1, .2) + self._rect = Rectangle(size=self.size, pos=self.pos) + self.bind(size=self._update_rect, pos=self._update_rect) + + def _update_rect(self, instance, value): + self._rect.pos = instance.pos + self._rect.size = instance.size + + def on_focused(self, instance, value, *largs): + self._color.rgba = [1, 0, 0, .2] if value else [1, 1, 1, .2] + + +class FocusLabel(FocusWithColor, Label): + '''A label, which in addition to turn red when focused, it also sets the + keyboard input to the text of the label. + ''' + + def keyboard_on_key_down(self, window, keycode, text, modifiers): + '''We call super before doing anything else to enable tab cycling + by FocusBehavior. If we wanted to use tab for ourselves, we could just + not call it, or call it if we didn't need tab. + ''' + if super(FocusLabel, self).keyboard_on_key_down(window, keycode, + text, modifiers): + return True + self.text = keycode[1] + return True + + +class FocusGridLayout(FocusWithColor, GridLayout): + pass + + +class FocusBoxLayout(FocusWithColor, BoxLayout): + pass + + +class FocusApp(App): + + def build(self): + root = FocusBoxLayout(padding=[10, 10], spacing=10) + self.grid1 = grid1 = FocusGridLayout(cols=4, padding=[10, 10], + spacing=10) + self.grid2 = grid2 = FocusGridLayout(cols=4, padding=[10, 10], + spacing=10) + root.add_widget(FocusLabel(text='Left', size_hint_x=0.4)) + root.add_widget(grid1) + root.add_widget(grid2) + root.add_widget(FocusLabel(text='Right', size_hint_x=0.4)) + + for i in range(40): + grid1.add_widget(FocusLabel(text='l' + str(i))) + for i in range(40): + grid2.add_widget(FocusLabel(text='r' + str(i))) + + # make elements 29, 9 un-focusable. The widgets are displayed in + # reverse order, so 9 = 39 - 10 + grid2.children[30].text = grid1.children[14].text =\ + grid2.children[15].text = grid1.children[34].text = 'Skip me' + grid2.children[15].is_focusable = False + grid2.children[30].is_focusable = False + # similarly, make 39 - 14 = 25, and 5 un-focusable + grid1.children[14].is_focusable = False + grid1.children[34].is_focusable = False + # don't move focus passed this element + grid2.children[35].focus_next = StopIteration + grid2.children[35].text = 'Stop forward' + + # exchange the links between the sides so that it'll skip to the other + # side in the middle. Remember that children are displayed reversed + # in layouts. + grid1.children[10].focus_next = grid2.children[9] + grid2.children[10].focus_next = grid1.children[9] + grid1.children[10].text = '-->' + grid2.children[10].text = '<--' + return root + + +if __name__ == '__main__': + FocusApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/image_mipmap.py b/freechat-client/share/kivy-examples/widgets/image_mipmap.py new file mode 100644 index 0000000..365f3e7 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/image_mipmap.py @@ -0,0 +1,31 @@ +''' +Image mipmap +============ + +Difference between a mipmapped image and no mipmap image. +The lower image is normal, and the top image is mipmapped. +''' + +import kivy +kivy.require('1.0.7') + +from kivy.app import App +from kivy.uix.scatter import ScatterPlane +from kivy.uix.image import Image +from os.path import join + + +class LabelMipmapTest(App): + def build(self): + s = ScatterPlane(scale=.5) + filename = join(kivy.kivy_data_dir, 'logo', 'kivy-icon-256.png') + l1 = Image(source=filename, pos=(400, 100), size=(256, 256)) + l2 = Image(source=filename, pos=(400, 356), size=(256, 256), + mipmap=True) + s.add_widget(l1) + s.add_widget(l2) + return s + + +if __name__ == '__main__': + LabelMipmapTest().run() diff --git a/freechat-client/share/kivy-examples/widgets/keyboardlistener.py b/freechat-client/share/kivy-examples/widgets/keyboardlistener.py new file mode 100644 index 0000000..f5b41af --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/keyboardlistener.py @@ -0,0 +1,42 @@ +import kivy +kivy.require('1.0.8') + +from kivy.core.window import Window +from kivy.uix.widget import Widget + + +class MyKeyboardListener(Widget): + + def __init__(self, **kwargs): + super(MyKeyboardListener, self).__init__(**kwargs) + self._keyboard = Window.request_keyboard( + self._keyboard_closed, self, 'text') + if self._keyboard.widget: + # If it exists, this widget is a VKeyboard object which you can use + # to change the keyboard layout. + pass + self._keyboard.bind(on_key_down=self._on_keyboard_down) + + def _keyboard_closed(self): + print('My keyboard have been closed!') + self._keyboard.unbind(on_key_down=self._on_keyboard_down) + self._keyboard = None + + def _on_keyboard_down(self, keyboard, keycode, text, modifiers): + print('The key', keycode, 'have been pressed') + print(' - text is %r' % text) + print(' - modifiers are %r' % modifiers) + + # Keycode is composed of an integer + a string + # If we hit escape, release the keyboard + if keycode[1] == 'escape': + keyboard.release() + + # Return True to accept the key. Otherwise, it will be used by + # the system. + return True + + +if __name__ == '__main__': + from kivy.base import runTouchApp + runTouchApp(MyKeyboardListener()) diff --git a/freechat-client/share/kivy-examples/widgets/label_mipmap.py b/freechat-client/share/kivy-examples/widgets/label_mipmap.py new file mode 100644 index 0000000..4028c85 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/label_mipmap.py @@ -0,0 +1,28 @@ +''' +Label mipmap +============ + +This show how to create a mipmapped label, and the visual difference between a +non mipmapped and mipmapped label. +''' + +import kivy +kivy.require('1.0.7') + +from kivy.app import App +from kivy.uix.scatter import ScatterPlane +from kivy.uix.label import Label + + +class LabelMipmapTest(App): + def build(self): + s = ScatterPlane(scale=.5) + l1 = Label(text='Kivy rulz', font_size=98, pos=(400, 100), mipmap=True) + l2 = Label(text='Kivy rulz', font_size=98, pos=(400, 328)) + s.add_widget(l1) + s.add_widget(l2) + return s + + +if __name__ == '__main__': + LabelMipmapTest().run() diff --git a/freechat-client/share/kivy-examples/widgets/label_sizing.py b/freechat-client/share/kivy-examples/widgets/label_sizing.py new file mode 100644 index 0000000..71c26fd --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/label_sizing.py @@ -0,0 +1,193 @@ + +""" +Label textsize +============ + +This example shows how to size a Label to its content (texture_size) and how +setting text_size controls text wrapping. +""" +from kivy.app import App +from kivy.clock import Clock +from kivy.lang import Builder +from kivy.properties import StringProperty, NumericProperty, BooleanProperty + +# Copied from https://en.wikipedia.org/wiki/A_Tale_of_Two_Cities +# Published in 1859 and public domain. +# The newline after the title will help demonstrate halign +_example_title_text = 'A Tale of Two Cities, by Charles Dickens\n' +_example_text = """It was the best of times, it was the worst of times, +it was the age of wisdom, it was the age of foolishness, it was the epoch of +belief, it was the epoch of incredulity, it was the season of Light, it was +the season of Darkness, it was the spring of hope, it was the winter of +despair, we had everything before us, we had nothing before us, we were all +going direct to Heaven, we were all going direct the other way - in short, +the period was so far like the present period, that some of its noisiest +authorities insisted on its being received, for good or for evil, in the +superlative degree of comparison only. +""" + +# Note: Many of the Widgets (StackLayout, ToggleButton, Spinner) have +# defaults set at the bottom of the KV, where DemoLabel and HeadingLabel +# are also defined. +_kv_code = """ +BoxLayout: + orientation: 'vertical' + + HeadingLabel: + text: 'These modify all demonstration Labels' + + StackLayout: + # Button is a subclass of Label and can be sized + # to text in the same way + + Button: + text: 'Reset' + on_press: app.reset_words() + + ToggleButton: + text: 'Shorten' + on_state: + app.shorten=self.state=='down' + + ToggleButton: + text: 'max_lines=3' + on_state: + app.max_lines=3 if self.state=='down' else 0 + + Spinner: + text: 'bottom' + values: 'bottom', 'middle', 'top' + on_text: app.valign=self.text + + Spinner: + text: 'left' + values: 'left', 'center', 'right', 'justify' + on_text: app.halign=self.text + + GridLayout: + id: grid_layout + cols: 2 + height: cm(6) + size_hint_y: None + + HeadingLabel: + text: "Default, no text_size set" + + HeadingLabel: + text: 'text_size bound to size' + + DemoLabel: + id: left_content + disabled_color: 0, 0, 0, 0 + + DemoLabel: + id: right_content + text_size: self.size + padding: dp(6), dp(6) + + ToggleButton: + text: 'Disable left' + on_state: + left_content.disabled=self.state=='down' + + # Need one Widget without size_hint_y: None, so that BoxLayout fills + # available space. + HeadingLabel: + text: 'text_size width set, size bound to texture_size' + text_size: self.size + size_hint_y: 1 + + DemoLabel: + id: bottom_content + # This Label wraps and expands its height to fit the text because + # only text_size width is set and the Label size binds to texture_size. + text_size: self.width, None + size: self.texture_size + padding: mm(4), mm(4) + size_hint_y: None + +# The column heading labels have their width set by the parent, +# but determine their height from the text. +: + bold: True + padding: dp(6), dp(4) + valign: 'bottom' + height: self.texture_size[1] + text_size: self.width, None + size_hint_y: None + +: + padding: dp(10), dp(8) + size_hint: None, None + size: self.texture_size + +# This inherits Button and the modifications above, so reset size +: + size: sp(68), self.texture_size[1] + +: + halign: app.halign + valign: app.valign + shorten: app.shorten + max_lines: app.max_lines + + canvas: + Color: + rgb: 68/255.0, 164/255.0, 201/255.0 + Line: + rectangle: self.x, self.y, self.width, self.height + +: + size_hint_y: None + spacing: dp(6) + padding: dp(6), dp(4) + height: self.minimum_height +""" + + +class LabelTextureSizeExample(App): + # All Labels use these properties, set to Label defaults + valign = StringProperty('bottom') + halign = StringProperty('left') + shorten = BooleanProperty(False) + max_lines = NumericProperty(0) + + def build(self): + self._add_word_ev = None + return Builder.load_string(_kv_code) + + def on_start(self): + widget_ids = self.root.ids + self.text_content_widgets = (widget_ids.left_content, + widget_ids.right_content, + widget_ids.bottom_content) + self.reset_words() + + def reset_words(self): + if self._add_word_ev is not None: + self._add_word_ev.cancel() + self._add_word_ev = None + for content_widget in self.text_content_widgets: + content_widget.text = _example_title_text + # initialize words generator + self.words = (word for word in _example_text.split()) + self.add_word() + + def add_word(self, dt=None): + try: + word = next(self.words) + except StopIteration: + return + + for content_widget in self.text_content_widgets: + content_widget.text += word + ' ' + + pause_time = 0.03 * len(word) + if word.endswith(','): + pause_time += 0.6 + + self._add_word_ev = Clock.schedule_once(self.add_word, pause_time) + + +if __name__ == '__main__': + LabelTextureSizeExample().run() diff --git a/freechat-client/share/kivy-examples/widgets/label_text_size.py b/freechat-client/share/kivy-examples/widgets/label_text_size.py new file mode 100644 index 0000000..71a91f4 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/label_text_size.py @@ -0,0 +1,49 @@ + +''' +Label textsize +============ + +This example shows how the textsize and line_height property are used +to format label widget +''' + +import kivy +kivy.require('1.0.7') + +from kivy.app import App +from kivy.uix.label import Label + + +_long_text = ("""Lorem ipsum dolor sit amet, consectetur adipiscing elit. """ + """Phasellus odio nisi, pellentesque molestie adipiscing vitae, aliquam """ + """at tellus. Fusce quis est ornare erat pulvinar elementum ut sed """ + """felis. Donec vel neque mauris. In sit amet nunc sit amet diam dapibus""" + """ lacinia. In sodales placerat mauris, ut euismod augue laoreet at. """ + """Integer in neque non odio fermentum volutpat nec nec nulla. Donec et """ + """risus non mi viverra posuere. Phasellus cursus augue purus, eget """ + """volutpat leo. Phasellus sed dui vitae ipsum mattis facilisis vehicula""" + """ eu justo.\n\n""" + """Quisque neque dolor, egestas sed venenatis eget, porta id ipsum. Ut """ + """faucibus, massa vitae imperdiet rutrum, sem dolor rhoncus magna, non """ + """lacinia nulla risus non dui. Nulla sit amet risus orci. Nunc libero """ + """justo, interdum eu pulvinar vel, pulvinar et lectus. Phasellus sed """ + """luctus diam. Pellentesque non feugiat dolor. Cras at dolor velit, """ + """gravida congue velit. Aliquam erat volutpat. Nullam eu nunc dui, quis""" + """ sagittis dolor. Ut nec dui eget odio pulvinar placerat. Pellentesque""" + """ mi metus, tristique et placerat ac, pulvinar vel quam. Nam blandit """ + """magna a urna imperdiet molestie. Nullam ut nisi eget enim laoreet """ + """sodales sit amet a felis.\n""") + + +class LabelTextSizeTest(App): + def build(self): + z = Label( + text=_long_text, + text_size=(600, None), + line_height=1.5 + ) + return z + + +if __name__ == '__main__': + LabelTextSizeTest().run() diff --git a/freechat-client/share/kivy-examples/widgets/label_with_markup.py b/freechat-client/share/kivy-examples/widgets/label_with_markup.py new file mode 100644 index 0000000..4a13026 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/label_with_markup.py @@ -0,0 +1,21 @@ +from kivy.app import App +from kivy.lang import Builder + +root = Builder.load_string(''' +Label: + text: + ('[b]Hello[/b] [color=ff0099]World[/color]\\n' + '[color=ff0099]Hello[/color] [b]World[/b]\\n' + '[b]Hello[/b] [color=ff0099]World[/color]') + markup: True + font_size: '64pt' +''') + + +class LabelWithMarkup(App): + def build(self): + return root + + +if __name__ == '__main__': + LabelWithMarkup().run() diff --git a/freechat-client/share/kivy-examples/widgets/lang_dynamic_classes.py b/freechat-client/share/kivy-examples/widgets/lang_dynamic_classes.py new file mode 100644 index 0000000..ba3cc79 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/lang_dynamic_classes.py @@ -0,0 +1,18 @@ +# Dynamic kv classes + +from kivy.lang import Builder +from kivy.base import runTouchApp + +root = Builder.load_string(''' +: + source: None + Image: + source: root.source + center: root.center + +ImageButton: + source: 'kivy/data/logo/kivy-icon-512.png' +''') + + +runTouchApp(root) diff --git a/freechat-client/share/kivy-examples/widgets/pagelayout.py b/freechat-client/share/kivy-examples/widgets/pagelayout.py new file mode 100644 index 0000000..55e8feb --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/pagelayout.py @@ -0,0 +1,64 @@ +from kivy.base import runTouchApp +from kivy.lang import Builder + +kv = ''' +PageLayout: + BoxLayout: + canvas: + Color: + rgba: 216/255., 195/255., 88/255., 1 + Rectangle: + pos: self.pos + size: self.size + + orientation: 'vertical' + Label: + size_hint_y: None + height: 1.5 * self.texture_size[1] + text: 'page 1' + + Button: + text: 'test' + on_press: print("test") + + BoxLayout: + orientation: 'vertical' + canvas: + Color: + rgba: 109/255., 8/255., 57/255., 1 + Rectangle: + pos: self.pos + size: self.size + + Label: + text: 'page 2' + + AsyncImage: + source: 'http://kivy.org/logos/kivy-logo-black-64.png' + + GridLayout: + canvas: + Color: + rgba: 37/255., 39/255., 30/255., 1 + Rectangle: + pos: self.pos + size: self.size + + cols: 2 + Label: + text: 'page 3' + AsyncImage: + source: 'http://kivy.org/slides/kivyandroid-thumb.jpg' + Button: + text: 'test' + on_press: print("test last page") + AsyncImage: + source: 'http://kivy.org/slides/kivypictures-thumb.jpg' + Widget + AsyncImage: + source: 'http://kivy.org/slides/particlepanda-thumb.jpg' +''' + + +if __name__ == '__main__': + runTouchApp(Builder.load_string(kv)) diff --git a/freechat-client/share/kivy-examples/widgets/popup_with_kv.py b/freechat-client/share/kivy-examples/widgets/popup_with_kv.py new file mode 100644 index 0000000..71104bb --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/popup_with_kv.py @@ -0,0 +1,35 @@ +''' +Example to show a Popup usage with the content from kv lang. +''' +from kivy.uix.popup import Popup +from kivy.uix.button import Button +from kivy.app import App +from kivy.lang import Builder + +Builder.load_string(''' +: + size_hint: .5, .5 + auto_dismiss: False + title: 'Hello world' + Button: + text: 'Click me to dismiss' + on_press: root.dismiss() + +''') + + +class CustomPopup(Popup): + pass + + +class TestApp(App): + def build(self): + b = Button(on_press=self.show_popup, text="Show Popup") + return b + + def show_popup(self, b): + p = CustomPopup() + p.open() + + +TestApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/recycleview/__pycache__/basic_data.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/recycleview/__pycache__/basic_data.cpython-37.pyc new file mode 100644 index 0000000..48ec1bd Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/recycleview/__pycache__/basic_data.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/recycleview/basic_data.py b/freechat-client/share/kivy-examples/widgets/recycleview/basic_data.py new file mode 100644 index 0000000..9407125 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/recycleview/basic_data.py @@ -0,0 +1,119 @@ +from random import sample +from string import ascii_lowercase + +from kivy.app import App +from kivy.lang import Builder +from kivy.uix.boxlayout import BoxLayout + + +kv = """ +: + canvas.before: + Color: + rgba: 0.5, 0.5, 0.5, 1 + Rectangle: + size: self.size + pos: self.pos + value: '' + Label: + text: root.value + +: + canvas: + Color: + rgba: 0.3, 0.3, 0.3, 1 + Rectangle: + size: self.size + pos: self.pos + rv: rv + orientation: 'vertical' + GridLayout: + cols: 3 + rows: 2 + size_hint_y: None + height: dp(108) + padding: dp(8) + spacing: dp(16) + Button: + text: 'Populate list' + on_press: root.populate() + Button: + text: 'Sort list' + on_press: root.sort() + Button: + text: 'Clear list' + on_press: root.clear() + BoxLayout: + spacing: dp(8) + Button: + text: 'Insert new item' + on_press: root.insert(new_item_input.text) + TextInput: + id: new_item_input + size_hint_x: 0.6 + hint_text: 'value' + padding: dp(10), dp(10), 0, 0 + BoxLayout: + spacing: dp(8) + Button: + text: 'Update first item' + on_press: root.update(update_item_input.text) + TextInput: + id: update_item_input + size_hint_x: 0.6 + hint_text: 'new value' + padding: dp(10), dp(10), 0, 0 + Button: + text: 'Remove first item' + on_press: root.remove() + + RecycleView: + id: rv + scroll_type: ['bars', 'content'] + scroll_wheel_distance: dp(114) + bar_width: dp(10) + viewclass: 'Row' + RecycleBoxLayout: + default_size: None, dp(56) + default_size_hint: 1, None + size_hint_y: None + height: self.minimum_height + orientation: 'vertical' + spacing: dp(2) +""" + +Builder.load_string(kv) + + +class Test(BoxLayout): + + def populate(self): + self.rv.data = [{'value': ''.join(sample(ascii_lowercase, 6))} + for x in range(50)] + + def sort(self): + self.rv.data = sorted(self.rv.data, key=lambda x: x['value']) + + def clear(self): + self.rv.data = [] + + def insert(self, value): + self.rv.data.insert(0, {'value': value or 'default value'}) + + def update(self, value): + if self.rv.data: + self.rv.data[0]['value'] = value or 'default new value' + self.rv.refresh_from_data() + + def remove(self): + if self.rv.data: + self.rv.data.pop(0) + + +class TestApp(App): + def build(self): + return Test() + + +if __name__ == '__main__': + TestApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/rstexample.py b/freechat-client/share/kivy-examples/widgets/rstexample.py new file mode 100644 index 0000000..0bfaa01 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/rstexample.py @@ -0,0 +1,128 @@ +''' +QuickReference for Rst +====================== + +This is a markup example: [b]Hello[/b] [i]world[/i] +And if i really want to write my code: &bl; Hello world &br; + +And video widget +---------------- + +.. video:: cityCC0.mpg + + +Inline Markup +------------- + +- *emphasis* +- **strong emphasis** +- `interpreted text` +- ``inline literal`` +- reference_ +- `phrase reference`_ +- anonymous__ +- _`inline internal target` + +.. _top: + +Internal crossreferences, like example_, or bottom_. + +Image +----- + +Woot! + +What about a little image ? + +.. image:: kivy/data/logo/kivy-icon-256.png + +Grid +---- + ++------------+------------+-----------+ +| Header 1 | Header 2 | Header 3 | ++============+============+===========+ +| body row 1 | column 2 | column 3 | ++------------+------------+-----------+ +| body row 2 | column 2 | column 3 | ++------------+------------+-----------+ +| body row 3 | column 2 | column 3 | ++------------+------------+-----------+ + +Term list +--------- + +:Authors: + Tony J. (Tibs) Ibbs, + David Goodger + (and sundry other good-natured folks) + +.. _example: + +:Version: 1.0 of 2001/08/08 +:Dedication: To my father. + +Definition list +--------------- + +what + Definition lists associate a term with a definition. + +how + The term is a one-line phrase, and the definition is one or more paragraphs + or body elements, indented relative to the term. Blank lines are not allowed + between term and definition. + + +Block quotes +------------ + +Block quotes are just: + + Indented paragraphs, + + and they may nest. + +Admonitions +----------- + +.. warning:: + + This is just a Test. + +.. note:: + + And this is just a note. Let's test some literal:: + + $ echo 'Hello world' + Hello world + +Ordered list +------------ + +#. My item number one +#. My item number two with some more content + and it's continuing on the second line? +#. My third item:: + + Oh wait, we can put code! + +#. My four item:: + + No way. + +.. _bottom: + +Go to top_''' + +from kivy.uix.rst import RstDocument +from kivy.app import App + + +class RstApp(App): + def build(self): + return RstDocument(text=__doc__) + + +if __name__ == '__main__': + RstApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/scatter.kv b/freechat-client/share/kivy-examples/widgets/scatter.kv new file mode 100644 index 0000000..33e4a46 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/scatter.kv @@ -0,0 +1,53 @@ +#:kivy 1.0 + +: + canvas: + Color: + hsv: 0, 1, .5 + Rectangle: + size: self.size + + canvas.after: + Color: + hsv: .1, 1, .5 + a: .2 + Rectangle: + pos: self.pos + size: self.bbox[1] + + Color: + rgb: 0, 1, 0 + Line: + points: [self.x, self.top, self.right, self.top] + Line: + points: [self.x, self.y, self.x, self.top] + Line: + points: [self.center_x, self.y, self.center_x, self.top] + Line: + points: [self.x, self.center_y, self.right, self.center_y] + + Line: + points: [self.center[0], self.center[1], self.right, self.top] + + + BoxLayout: + size: root.size + orientation: 'vertical' + Label: + text: 'Position\n' + str(root.pos) + text_size: (root.width, None) + Label: + text: 'Size\n' + str(root.size) + text_size: (root.width, None) + Label: + text: 'Center\n' + str(root.center) + text_size: (root.width, None) + Label: + text: 'Bounding Box\n' + str(root.bbox) + text_size: (root.width, None) + Label: + text: 'Top\n' + str(root.top) + text_size: (root.width, None) + Label: + text: 'Right\n' + str(root.right) + text_size: (root.width, None) diff --git a/freechat-client/share/kivy-examples/widgets/scatter.py b/freechat-client/share/kivy-examples/widgets/scatter.py new file mode 100644 index 0000000..3a9c215 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/scatter.py @@ -0,0 +1,16 @@ +from kivy.uix.scatter import Scatter +from kivy.app import App + + +class MyScatter(Scatter): + pass + + +class ScatterApp(App): + def build(self): + s = MyScatter(size=(400, 400), size_hint=(None, None)) + s.top = 500 + return s + + +ScatterApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/screenmanager.py b/freechat-client/share/kivy-examples/widgets/screenmanager.py new file mode 100644 index 0000000..c032961 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/screenmanager.py @@ -0,0 +1,106 @@ +from kivy.app import App +from kivy.uix.screenmanager import ScreenManager, Screen +from kivy.properties import NumericProperty +from kivy.lang import Builder + +Builder.load_string(''' +#:import random random.random +#:import SlideTransition kivy.uix.screenmanager.SlideTransition +#:import SwapTransition kivy.uix.screenmanager.SwapTransition +#:import WipeTransition kivy.uix.screenmanager.WipeTransition +#:import FadeTransition kivy.uix.screenmanager.FadeTransition +#:import RiseInTransition kivy.uix.screenmanager.RiseInTransition +#:import FallOutTransition kivy.uix.screenmanager.FallOutTransition +#:import NoTransition kivy.uix.screenmanager.NoTransition + +: + hue: random() + canvas: + Color: + hsv: self.hue, .5, .3 + Rectangle: + size: self.size + + Label: + font_size: 42 + text: root.name + + Button: + text: 'Next screen' + size_hint: None, None + pos_hint: {'right': 1} + size: 150, 50 + on_release: root.manager.current = root.manager.next() + + Button: + text: 'Previous screen' + size_hint: None, None + size: 150, 50 + on_release: root.manager.current = root.manager.previous() + + BoxLayout: + size_hint: .5, None + height: 250 + pos_hint: {'center_x': .5} + orientation: 'vertical' + + Button: + text: 'Use SlideTransition with "up" direction' + on_release: root.manager.transition = \ + SlideTransition(direction="up") + + Button: + text: 'Use SlideTransition with "down" direction' + on_release: root.manager.transition = \ + SlideTransition(direction="down") + + Button: + text: 'Use SlideTransition with "left" direction' + on_release: root.manager.transition = \ + SlideTransition(direction="left") + + Button: + text: 'Use SlideTransition with "right" direction' + on_release: root.manager.transition = \ + SlideTransition(direction="right") + + Button: + text: 'Use SwapTransition' + on_release: root.manager.transition = SwapTransition() + + Button: + text: 'Use WipeTransition' + on_release: root.manager.transition = WipeTransition() + + Button: + text: 'Use FadeTransition' + on_release: root.manager.transition = FadeTransition() + + Button: + text: 'Use FallOutTransition' + on_release: root.manager.transition = FallOutTransition() + + Button: + text: 'Use RiseInTransition' + on_release: root.manager.transition = RiseInTransition() + Button: + text: 'Use NoTransition' + on_release: root.manager.transition = NoTransition(duration=0) +''') + + +class CustomScreen(Screen): + hue = NumericProperty(0) + + +class ScreenManagerApp(App): + + def build(self): + root = ScreenManager() + for x in range(4): + root.add_widget(CustomScreen(name='Screen %d' % x)) + return root + + +if __name__ == '__main__': + ScreenManagerApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/scrollview.kv b/freechat-client/share/kivy-examples/widgets/scrollview.kv new file mode 100644 index 0000000..5be0562 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/scrollview.kv @@ -0,0 +1,16 @@ +#:kivy 1.0.4 +: + canvas: + Color: + rgb: 1, 0, 0 + Rectangle: + pos: self.pos + size: self.size + +: + canvas: + Color: + rgb: 1, 1, 0 + Rectangle: + pos: self.pos + size: self.size diff --git a/freechat-client/share/kivy-examples/widgets/scrollview.py b/freechat-client/share/kivy-examples/widgets/scrollview.py new file mode 100644 index 0000000..8564a0a --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/scrollview.py @@ -0,0 +1,40 @@ +import kivy +kivy.require('1.0.8') + +from kivy.app import App +from kivy.uix.button import Button +from kivy.uix.scrollview import ScrollView +from kivy.uix.gridlayout import GridLayout + + +class ScrollViewApp(App): + + def build(self): + + # create a default grid layout with custom width/height + layout = GridLayout(cols=1, padding=10, spacing=10, + size_hint=(None, None), width=500) + + # when we add children to the grid layout, its size doesn't change at + # all. we need to ensure that the height will be the minimum required + # to contain all the childs. (otherwise, we'll child outside the + # bounding box of the childs) + layout.bind(minimum_height=layout.setter('height')) + + # add button into that grid + for i in range(30): + btn = Button(text=str(i), size=(480, 40), + size_hint=(None, None)) + layout.add_widget(btn) + + # create a scroll view, with a size < size of the grid + root = ScrollView(size_hint=(None, None), size=(500, 320), + pos_hint={'center_x': .5, 'center_y': .5}, do_scroll_x=False) + root.add_widget(layout) + + return root + + +if __name__ == '__main__': + + ScrollViewApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/sequenced_images/__pycache__/main.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/sequenced_images/__pycache__/main.cpython-37.pyc new file mode 100644 index 0000000..2330d18 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/sequenced_images/__pycache__/main.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/sequenced_images/android.txt b/freechat-client/share/kivy-examples/widgets/sequenced_images/android.txt new file mode 100644 index 0000000..b74f94e --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/sequenced_images/android.txt @@ -0,0 +1,3 @@ +title=main +author=seesaw +orientation=portrait diff --git a/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/bird.zip b/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/bird.zip new file mode 100644 index 0000000..b0bc0f5 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/bird.zip differ diff --git a/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/button_white.png b/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/button_white.png new file mode 100644 index 0000000..5971c93 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/button_white.png differ diff --git a/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/button_white_animated.zip b/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/button_white_animated.zip new file mode 100644 index 0000000..243223e Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/button_white_animated.zip differ diff --git a/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/cube.zip b/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/cube.zip new file mode 100644 index 0000000..c823dee Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/cube.zip differ diff --git a/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/info.png b/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/info.png new file mode 100644 index 0000000..17a130d Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/info.png differ diff --git a/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/info.zip b/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/info.zip new file mode 100644 index 0000000..d6206a2 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/info.zip differ diff --git a/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/simple_cv_joint_animated.gif b/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/simple_cv_joint_animated.gif new file mode 100644 index 0000000..1ec32dc Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/sequenced_images/data/images/simple_cv_joint_animated.gif differ diff --git a/freechat-client/share/kivy-examples/widgets/sequenced_images/main.kv b/freechat-client/share/kivy-examples/widgets/sequenced_images/main.kv new file mode 100644 index 0000000..e586c2c --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/sequenced_images/main.kv @@ -0,0 +1,63 @@ +#:kivy 1.0.9 +: + canvas.before: + Color: + rgb: (1, 1, 1) + BorderImage: + border: root.border if root.border else (16, 16, 16, 16) + pos: self.pos + size: self.size + texture: self.texture_background + + + on_size: self.center = win.Window.center + size: imag.size + size_hint: None, None + Image: + id: imag + source: 'data/images/simple_cv_joint_animated.gif' + on_touch_down: root.parent.parent.parent.currentObj = self + + + on_size: self.center = win.Window.center + size: imag.size + size_hint: None, None + Image: + id: imag + source: 'data/images/cube.zip' + anim_delay: 0.05 + on_touch_down: root.parent.parent.parent.currentObj = self + + + on_size: self.center = win.Window.center + size: imag.size + size_hint: None, None + Image: + id: imag + source: 'data/images/bird.zip' + on_touch_down: root.parent.parent.parent.currentObj = self + + + size_hint: (.2, 1) + padding: 10 + cols: 1 + canvas: + Color: + rgba: .1,.45,.31,.9 + Rectangle: + pos: self.pos + size:self.size + Label: + halign: 'center' + text_size: self.size + text: root.currentObj.source if root.currentObj else 'click on a Image to change it\'s properties' + Label: + id: spdlbl + halign: 'center' + text_size: self.size + text: 'No Image selected' if not root.currentObj else 'Animation speed: %f FPS' %(1/root.currentObj.anim_delay) if root.currentObj.anim_delay > 0 else 'Animation speed: 0 FPS' + Slider: + min:0 + max: 100 if root.currentObj else 0 + value: (1/root.currentObj.anim_delay) if (root.currentObj and root.currentObj.anim_delay>0) else 0 + on_value: root.on_value(self, args[1], spdlbl) diff --git a/freechat-client/share/kivy-examples/widgets/sequenced_images/main.py b/freechat-client/share/kivy-examples/widgets/sequenced_images/main.py new file mode 100644 index 0000000..b3ed73f --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/sequenced_images/main.py @@ -0,0 +1,150 @@ +import kivy +kivy.require('1.0.8') + +from kivy.app import App +from kivy.uix.floatlayout import FloatLayout +from kivy.uix.gridlayout import GridLayout +from uix.custom_button import AnimatedButton +from kivy.uix.scatter import Scatter +from kivy.properties import ObjectProperty + + +class gifScatter(Scatter): + def __init__(self, **kwargs): + super(gifScatter, self).__init__() + + +class zipScatter(Scatter): + def __init__(self, **kwargs): + super(zipScatter, self).__init__() + + +class jpgScatter(Scatter): + def __init__(self, **kwargs): + super(jpgScatter, self).__init__() + + +class Right_Frame(GridLayout): + + currentObj = ObjectProperty(None) + + def __init__(self, **kwargs): + super(Right_Frame, self).__init__() + + def on_value(self, *l): + if self.currentObj: + if abs(l[1]) <= 0: + self.currentObj.anim_delay = -1 + l[2].text = 'Animation speed: %f FPS' % 0 + else: + self.currentObj.anim_delay = 1 / l[1] + l[2].text = 'Animation speed: %f FPS' % ( + 1 / self.currentObj.anim_delay) + else: + l[0].max = 0 + l[2].text = 'No Image selected' + + +class mainclass(FloatLayout): + + currentObj = ObjectProperty(None) + + def __init__(self, **kwargs): + super(mainclass, self).__init__() + + # initialize variables + self.sign = .10 + + # setup Layouts + layout = GridLayout(size_hint=(1, 1), cols=3, rows=1) + left_frame = GridLayout(size_hint=(.25, 1), cols=1) + client_frame = FloatLayout(size_hint=(1, 1)) + self.right_frame = Right_Frame() + + # setup buttons in left frame + but_load_gif = AnimatedButton(text='load gif', halign='center') + but_load_zip_png = AnimatedButton(text='load zipped\n png/s', + halign='center') + but_load_zip_jpg = AnimatedButton(text='load zipped\n jpg/s', + halign='center') + but_animated = AnimatedButton(text='animated button\n' + 'made using\nSequenced Images\n press to animate', + halign='center', + background_normal='data/images/button_white.png', + background_down='data/images/button_white_animated.zip') + but_animated_normal = AnimatedButton(text='borderless\n' + 'animated button\npress to stop', + halign='center', + background_down='data/images/button_white.png', + background_normal='data/images/button_white_animated.zip') + but_animated_borderless = AnimatedButton(text='Borderless', + background_normal='data/images/info.png', + background_down='data/images/info.zip', halign='center') + but_animated_bordered = AnimatedButton(text='With Border', + background_normal='data/images/info.png', + background_down='data/images/info.zip', halign='center') + + # Handle button press/release + def load_images(*l): + if l[0].text == 'load gif' or l[0].text == 'load gif\n from cache': + l[0].text = 'load gif\n from cache' + sctr = gifScatter() + if (l[0].text == 'load zipped\n png/s' or + l[0].text == 'load zipped\n png/s from cache'): + l[0].text = 'load zipped\n png/s from cache' + sctr = zipScatter() + if (l[0].text == 'load zipped\n jpg/s' or + l[0].text == 'load zipped\n jpg/s from cache'): + l[0].text = 'load zipped\n jpg/s from cache' + sctr = jpgScatter() + + client_frame.add_widget(sctr, 1) + + # position scatter + sctr.pos = (240 + self.sign, 200 + self.sign) + self.sign += 10 + if self.sign > 200: + self.sign = 10 + sctr.pos = (300, 200 - self.sign) + + # bind function on on_release + but_load_gif.bind(on_release=load_images) + but_load_zip_png.bind(on_release=load_images) + but_load_zip_jpg.bind(on_release=load_images) + + # add widgets to left frame + left_frame.add_widget(but_load_gif) + left_frame.add_widget(but_load_zip_png) + left_frame.add_widget(but_load_zip_jpg) + left_frame.add_widget(but_animated) + left_frame.add_widget(but_animated_normal) + left_frame.add_widget(but_animated_borderless) + left_frame.add_widget(but_animated_bordered) + + # set/remove border for borderless widgets (16,16,16,16) by default + but_animated_normal.border = \ + but_animated_borderless.border = (0, 0, 0, 0) + + # add widgets to the main layout + layout.add_widget(left_frame) + layout.add_widget(client_frame) + layout.add_widget(self.right_frame) + + # add main layout to root + self.add_widget(layout) + + def on_currentObj(self, *l): + self.right_frame.currentObj = self.currentObj + + +class mainApp(App): + + def build(self): + upl = mainclass() + upl.size_hint = (1, 1) + upl.pos_hint = {'top': 0, 'right': 1} + return upl + + +if __name__ == '__main__': + mainApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/sequenced_images/uix/__init__.py b/freechat-client/share/kivy-examples/widgets/sequenced_images/uix/__init__.py new file mode 100644 index 0000000..899b04a --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/sequenced_images/uix/__init__.py @@ -0,0 +1,7 @@ +''' +UIX +=== + +The `uix` contains all the class for creating and arranging Custom Widgets. +A widget is an element of a graphical user interface. +''' diff --git a/freechat-client/share/kivy-examples/widgets/sequenced_images/uix/__pycache__/__init__.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/sequenced_images/uix/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000..24b2388 Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/sequenced_images/uix/__pycache__/__init__.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/sequenced_images/uix/__pycache__/custom_button.cpython-37.pyc b/freechat-client/share/kivy-examples/widgets/sequenced_images/uix/__pycache__/custom_button.cpython-37.pyc new file mode 100644 index 0000000..450075e Binary files /dev/null and b/freechat-client/share/kivy-examples/widgets/sequenced_images/uix/__pycache__/custom_button.cpython-37.pyc differ diff --git a/freechat-client/share/kivy-examples/widgets/sequenced_images/uix/custom_button.py b/freechat-client/share/kivy-examples/widgets/sequenced_images/uix/custom_button.py new file mode 100644 index 0000000..c3cf3ed --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/sequenced_images/uix/custom_button.py @@ -0,0 +1,101 @@ + +__all__ = ('AnimatedButton') + +from kivy.factory import Factory +from kivy.uix.label import Label +from kivy.uix.image import Image +from kivy.graphics import * +from kivy.properties import StringProperty, OptionProperty, \ + ObjectProperty, BooleanProperty + + +class AnimatedButton(Label): + + state = OptionProperty('normal', options=('normal', 'down')) + allow_stretch = BooleanProperty(True) + keep_ratio = BooleanProperty(False) + border = ObjectProperty(None) + anim_delay = ObjectProperty(None) + background_normal = StringProperty( + 'atlas://data/images/defaulttheme/button') + texture_background = ObjectProperty(None) + background_down = StringProperty( + 'atlas://data/images/defaulttheme/button_pressed') + + def __init__(self, **kwargs): + super(AnimatedButton, self).__init__(**kwargs) + + self.register_event_type('on_press') + self.register_event_type('on_release') + # borderImage.border by default is ... + self.border = (16, 16, 16, 16) + # Image to display depending on state + self.img = Image( + source=self.background_normal, + allow_stretch=self.allow_stretch, + keep_ratio=self.keep_ratio, + mipmap=True) + + # reset animation if anim_delay is changed + def anim_reset(*l): + self.img.anim_delay = self.anim_delay + + self.bind(anim_delay=anim_reset) + self.anim_delay = .1 + # update self.texture when image.texture changes + self.img.bind(texture=self.on_tex_changed) + self.on_tex_changed() + + # update image source when background image is changed + def background_changed(*l): + self.img.source = self.background_normal + self.anim_delay = .1 + + self.bind(background_normal=background_changed) + + def on_tex_changed(self, *largs): + self.texture_background = self.img.texture + + def _do_press(self): + self.state = 'down' + + def _do_release(self): + self.state = 'normal' + + def on_touch_down(self, touch): + if not self.collide_point(touch.x, touch.y): + return False + if repr(self) in touch.ud: + return False + touch.grab(self) + touch.ud[repr(self)] = True + _animdelay = self.img.anim_delay + self.img.source = self.background_down + self.img.anim_delay = _animdelay + self._do_press() + self.dispatch('on_press') + return True + + def on_touch_move(self, touch): + return repr(self) in touch.ud + + def on_touch_up(self, touch): + if touch.grab_current is not self: + return + assert(repr(self) in touch.ud) + touch.ungrab(self) + _animdelay = self.img._coreimage.anim_delay + self.img.source = self.background_normal + self.anim_delay = _animdelay + self._do_release() + self.dispatch('on_release') + return True + + def on_press(self): + pass + + def on_release(self): + pass + + +Factory.register('AnimatedButton', cls=AnimatedButton) diff --git a/freechat-client/share/kivy-examples/widgets/settings.py b/freechat-client/share/kivy-examples/widgets/settings.py new file mode 100644 index 0000000..f479ade --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/settings.py @@ -0,0 +1,93 @@ +from kivy.app import App +from kivy.uix.button import Button +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.label import Label +from kivy.uix.popup import Popup +from kivy.uix.settings import (SettingsWithSidebar, + SettingsWithSpinner, + SettingsWithTabbedPanel) +from kivy.properties import OptionProperty, ObjectProperty + + +class SettingsApp(App): + + display_type = OptionProperty('normal', options=['normal', 'popup']) + + settings_popup = ObjectProperty(None, allownone=True) + + def build(self): + + paneltype = Label(text='What kind of settings panel to use?') + + sidebar_button = Button(text='Sidebar') + sidebar_button.bind(on_press=lambda j: self.set_settings_cls( + SettingsWithSidebar)) + spinner_button = Button(text='Spinner') + spinner_button.bind(on_press=lambda j: self.set_settings_cls( + SettingsWithSpinner)) + tabbed_button = Button(text='TabbedPanel') + tabbed_button.bind(on_press=lambda j: self.set_settings_cls( + SettingsWithTabbedPanel)) + + buttons = BoxLayout(orientation='horizontal') + buttons.add_widget(sidebar_button) + buttons.add_widget(spinner_button) + buttons.add_widget(tabbed_button) + + displaytype = Label(text='How to display the settings?') + display_buttons = BoxLayout(orientation='horizontal') + onwin_button = Button(text='on window') + onwin_button.bind(on_press=lambda j: self.set_display_type('normal')) + popup_button = Button(text='in a popup') + popup_button.bind(on_press=lambda j: self.set_display_type('popup')) + display_buttons.add_widget(onwin_button) + display_buttons.add_widget(popup_button) + + instruction = Label(text='Click to open the settings panel:') + settings_button = Button(text='Open settings') + settings_button.bind(on_press=self.open_settings) + + layout = BoxLayout(orientation='vertical') + layout.add_widget(paneltype) + layout.add_widget(buttons) + layout.add_widget(displaytype) + layout.add_widget(display_buttons) + layout.add_widget(instruction) + layout.add_widget(settings_button) + + return layout + + def on_settings_cls(self, *args): + self.destroy_settings() + + def set_settings_cls(self, panel_type): + self.settings_cls = panel_type + + def set_display_type(self, display_type): + self.destroy_settings() + self.display_type = display_type + + def display_settings(self, settings): + if self.display_type == 'popup': + p = self.settings_popup + if p is None: + self.settings_popup = p = Popup(content=settings, + title='Settings', + size_hint=(0.8, 0.8)) + if p.content is not settings: + p.content = settings + p.open() + else: + super(SettingsApp, self).display_settings(settings) + + def close_settings(self, *args): + if self.display_type == 'popup': + p = self.settings_popup + if p is not None: + p.dismiss() + else: + super(SettingsApp, self).close_settings() + + +if __name__ == '__main__': + SettingsApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/shorten_text.py b/freechat-client/share/kivy-examples/widgets/shorten_text.py new file mode 100644 index 0000000..524086a --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/shorten_text.py @@ -0,0 +1,80 @@ +''' +Demonstrate shorten / number of line in label +============================================= + +--------------- ------- ------------------------------------------------------- +Number of lines Shorten Behavior +--------------- ------- ------------------------------------------------------- +0 (unlimited) False Default behavior +1 False Display as much as possible, at least one word +N False Display as much as possible +0 (unlimited) True Default behavior (as kivy <= 1.7 series) +1 True Display as much as possible, shorten long word. +N True Display as much as possible, shorten long word. +--------------- ------- ------------------------------------------------------- + +''' + + +from kivy.app import App +from kivy.lang import Builder + +kv = ''' +: + step: 1 + Label: + text: '{}'.format(int(root.value)) + size: self.texture_size + top: root.center_y - sp(20) + center_x: root.value_pos[0] + +BoxLayout: + orientation: 'vertical' + BoxLayout: + spacing: '10dp' + padding: '4dp' + size_hint_y: None + height: '48dp' + LabeledSlider: + id: slider + value: 500 + min: 25 + max: root.width + on_value: self.value = int(self.value) + ToggleButton: + id: shorten + text: 'Shorten' + LabeledSlider: + id: max_lines + value: 0 + min: 0 + max: 5 + + AnchorLayout: + RelativeLayout: + size_hint: None, None + size: slider.value, 50 + canvas: + Color: + rgb: .4, .4, .4 + Rectangle: + size: self.size + Label: + size_hint: 1, 1 + text_size: self.size + shorten: shorten.state == 'down' + max_lines: max_lines.value + valign: 'middle' + halign: 'center' + color: (1, 1, 1, 1) + font_size: 22 + text: 'Michaelangelo Smith' +''' + + +class ShortenText(App): + def build(self): + return Builder.load_string(kv) + + +ShortenText().run() diff --git a/freechat-client/share/kivy-examples/widgets/spinner.py b/freechat-client/share/kivy-examples/widgets/spinner.py new file mode 100644 index 0000000..ff98291 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/spinner.py @@ -0,0 +1,17 @@ +from kivy.uix.spinner import Spinner +from kivy.base import runTouchApp + +spinner = Spinner( + text='Home', + values=('Home', 'Work', 'Other', 'Custom'), + size_hint=(None, None), size=(100, 44), + pos_hint={'center_x': .5, 'center_y': .5}) + + +def show_selected_value(spinner, text): + print('The spinner', spinner, 'has text', text) + + +spinner.bind(text=show_selected_value) + +runTouchApp(spinner) diff --git a/freechat-client/share/kivy-examples/widgets/splitter.py b/freechat-client/share/kivy-examples/widgets/splitter.py new file mode 100644 index 0000000..a00afd0 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/splitter.py @@ -0,0 +1,74 @@ +from kivy.base import runTouchApp +from kivy.lang import Builder + +bl = Builder.load_string(''' +BoxLayout: + orientation: 'vertical' + BoxLayout: + size_hint_y: None + height: sp(60) + Label: + text: 'keep_within_parent?' + CheckBox: + id: in_parent_box + active: False + Label: + text: 'rescale_with_parent?' + CheckBox: + id: rescale_box + active: False + BoxLayout: + orientation: 'horizontal' + Button: + text: 'left btn' + size_hint_x: 0.3 + BoxLayout: + orientation: 'vertical' + Button: + text: "Btn0" + BoxLayout: + Splitter: + sizable_from: 'right' + keep_within_parent: in_parent_box.active + rescale_with_parent: rescale_box.active + Button: + text: 'Btn5' + Button: + text: 'Btn6' + BoxLayout: + sizable_from: 'top' + BoxLayout: + orientation: 'horizontal' + BoxLayout: + orientation: 'vertical' + Button: + text: "Btn1" + Splitter: + sizable_from: 'top' + keep_within_parent: in_parent_box.active + rescale_with_parent: rescale_box.active + Button: + text: "Btn2" + Splitter: + sizable_from: 'left' + keep_within_parent: in_parent_box.active + rescale_with_parent: rescale_box.active + Button: + text: "Btn3" + BoxLayout: + orientation: 'vertical' + size_hint_x: 0.3 + Button: + text: 'right btn' + Splitter: + sizable_from: 'bottom' + keep_within_parent: in_parent_box.active + rescale_with_parent: rescale_box.active + Button: + text: 'Btn7' + Button: + text: 'right btn' +''') + + +runTouchApp(bl) diff --git a/freechat-client/share/kivy-examples/widgets/tabbed_panel_showcase.py b/freechat-client/share/kivy-examples/widgets/tabbed_panel_showcase.py new file mode 100644 index 0000000..66f583f --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/tabbed_panel_showcase.py @@ -0,0 +1,317 @@ +''' +TabbedPanel +============ + +Test of the widget TabbedPanel showing all capabilities. +''' + +from kivy.app import App +from kivy.animation import Animation +from kivy.uix.floatlayout import FloatLayout +from kivy.uix.tabbedpanel import TabbedPanel, TabbedPanelHeader +from kivy.factory import Factory + + +class StandingHeader(TabbedPanelHeader): + pass + + +class CloseableHeader(TabbedPanelHeader): + pass + + +Factory.register('StandingHeader', cls=StandingHeader) +Factory.register('CloseableHeader', cls=CloseableHeader) + +from kivy.lang import Builder + +Builder.load_string(''' + + but: _but + Button: + id: _but + text: 'Press to show Tabbed Panel' + on_release: root.show_tab() + + + color: 0,0,0,0 + disabled_color: self.color + Scatter: + do_translation: False + do_scale: False + do_rotation: False + auto_bring_to_front: False + rotation: 70 + size_hint: None, None + size: lbl.size + center_x: root.center_x + center_y: root.center_y + Label: + id: lbl + text: root.text + size: root.size + color: 1, 1, 1, .5 if self.disabled else 1 + pos: 0,0 + + + size_hint: (.45, .45) + pos_hint: {'center_x': .25, 'y': .55} + # replace the default tab with our custom tab class + default_tab_cls: sh.__class__ + do_default_tab: True + default_tab_content: default_content.__self__ + tab_width: 40 + tab_height: 70 + FloatLayout: + RstDocument: + id: default_content + text: '\\n'.join(("Standing tabs", "-------------",\ + "Tabs in \\'%s\\' position" %root.tab_pos)) + Image: + id: tab_2_content + source: 'data/images/defaulttheme-0.png' + Image: + id: tab_3_content + source: 'data/images/image-loading.gif' + StandingHeader: + id: sh + content: tab_2_content.__self__ + text: 'tab 2' + StandingHeader: + content: tab_3_content + text: 'tab 3' + + + color: 0,0,0,0 + disabled_color: self.color + # variable tab_width + text: 'tabx' + size_hint_x: None + width: self.texture_size[0] + 40 + BoxLayout: + pos: root.pos + size_hint: None, None + size: root.size + padding: 3 + Label: + id: lbl + text: root.text + BoxLayout: + size_hint: None, 1 + orientation: 'vertical' + width: 22 + Image: + source: 'tools/theming/defaulttheme/close.png' + on_touch_down: + if self.collide_point(*args[1].pos) :\ + root.panel.remove_widget(root) + + + + tab_pos: 'top_right' + size_hint: (.45, .45) + pos_hint: {'center_x': .75, 'y': .55} + # replace the default tab with our custom tab + default_tab: def_tab + # allow variable tab width + tab_width: None + FloatLayout: + RstDocument: + id: default_content + text: '\\n'.join(("Closeable tabs", "---------------",\ + "- The tabs above are also scrollable",\ + "- Tabs in \\'%s\\' position" %root.tab_pos)) + Image: + id: tab_2_content + source: 'data/images/defaulttheme-0.png' + BoxLayout: + id: tab_3_content + BubbleButton: + text: 'Press to add new tab' + on_release: root.add_header() + BubbleButton: + text: 'Press set this tab as default' + on_release: root.default_tab = tab3 + CloseableHeader: + id: def_tab + text: 'default tab' + content:default_content.__self__ + panel: root + CloseableHeader: + text: 'tab2' + content: tab_2_content.__self__ + panel: root + CloseableHeader: + id: tab3 + text: 'tab3' + content: tab_3_content.__self__ + panel: root + CloseableHeader: + panel: root + CloseableHeader: + panel: root + CloseableHeader: + panel: root + CloseableHeader: + panel: root + CloseableHeader: + panel: root + CloseableHeader: + panel: root + CloseableHeader: + panel: root + + + tab_pos: 'bottom_left' + size_hint: (.45, .45) + pos_hint: {'center_x': .25, 'y': .02} + do_default_tab: False + + TabbedPanelItem: + id: settings + text: 'Settings' + RstDocument: + text: '\\n'.join(("Normal tabs", "-------------",\ + "Tabs in \\'%s\\' position" %root.tab_pos)) + TabbedPanelItem: + text: 'tab2' + BubbleButton: + text: 'switch to settings' + on_press: root.switch_to(settings) + TabbedPanelItem: + text: 'tab3' + Image: + source: 'data/images/image-loading.gif' + + + tab_pos: 'right_top' + size_hint: (.45, .45) + pos_hint: {'center_x': .75, 'y': .02} + default_tab: def_tab + tab_height: img.width + FloatLayout: + RstDocument: + id: default_content + text: '\\n'.join(("Image tabs","-------------",\ + "1. Normal image tab","2. Image with Text","3. Rotated Image",\ + "4. Tabs in \\'%s\\' position" %root.tab_pos)) + Image: + id: tab_2_content + source: 'data/images/defaulttheme-0.png' + VideoPlayer: + id: tab_3_content + source: 'cityCC0.mpg' + TabbedPanelHeader: + id: def_tab + content:default_content.__self__ + border: 0, 0, 0, 0 + background_down: 'cityCC0.png' + background_normal:'sequenced_images/data/images/info.png' + TabbedPanelHeader: + id: tph + content: tab_2_content.__self__ + BoxLayout: + pos: tph.pos + size: tph.size + orientation: 'vertical' + Image: + source: 'sequenced_images/data/images/info.png'\ + if tph.state == 'normal' else 'cityCC0.png' + Label: + text: 'text & img' + TabbedPanelHeader: + id: my_header + content: tab_3_content.__self__ + Scatter: + do_translation: False + do_scale: False + do_rotation: False + auto_bring_to_front: False + rotation: 90 + size_hint: None, None + size: img.size + center: my_header.center + Image: + id: img + source: 'sequenced_images/data/images/info.png'\ + if my_header.state == 'normal' else 'cityCC0.png' + size: my_header.size + allow_stretch: True + keep_ratio: False +''') + + +class Tp(TabbedPanel): + + # override tab switching method to animate on tab switch + def switch_to(self, header): + anim = Animation(opacity=0, d=.24, t='in_out_quad') + + def start_anim(_anim, child, in_complete, *lt): + _anim.start(child) + + def _on_complete(*lt): + if header.content: + header.content.opacity = 0 + anim = Animation(opacity=1, d=.43, t='in_out_quad') + start_anim(anim, header.content, True) + super(Tp, self).switch_to(header) + + anim.bind(on_complete=_on_complete) + if self.current_tab.content: + start_anim(anim, self.current_tab.content, False) + else: + _on_complete() + + +class PanelLeft(Tp): + pass + + +class PanelRight(Tp): + + def add_header(self): + self.add_widget(CloseableHeader(panel=self)) + + +class PanelbLeft(Tp): + pass + + +class PanelbRight(Tp): + pass + + +class TabShowcase(FloatLayout): + + def show_tab(self): + if not hasattr(self, 'tab'): + self.tab = tab = PanelLeft() + self.add_widget(tab) + self.tab1 = tab = PanelRight() + self.add_widget(tab) + self.tab2 = tab = PanelbRight() + self.add_widget(tab) + self.tab3 = tab = PanelbLeft() + self.add_widget(tab) + self.but.text = \ + 'Tabs in variable positions, press to change to top_left' + else: + values = ('left_top', 'left_mid', 'left_bottom', 'top_left', + 'top_mid', 'top_right', 'right_top', 'right_mid', + 'right_bottom', 'bottom_left', 'bottom_mid', 'bottom_right') + index = values.index(self.tab.tab_pos) + self.tab.tab_pos = self.tab1.tab_pos = self.tab2.tab_pos\ + = self.tab3.tab_pos = values[(index + 1) % len(values)] + self.but.text = 'Tabs in \'%s\' position,' % self.tab.tab_pos\ + + '\n press to change to next pos' + + +class TestTabApp(App): + + def build(self): + return TabShowcase() + + +if __name__ == '__main__': + TestTabApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/tabbedpanel.py b/freechat-client/share/kivy-examples/widgets/tabbedpanel.py new file mode 100644 index 0000000..355c718 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/tabbedpanel.py @@ -0,0 +1,50 @@ +''' +TabbedPanel +============ + +Test of the widget TabbedPanel. +''' + +from kivy.app import App +from kivy.uix.tabbedpanel import TabbedPanel +from kivy.lang import Builder + +Builder.load_string(""" + +: + size_hint: .5, .5 + pos_hint: {'center_x': .5, 'center_y': .5} + do_default_tab: False + + TabbedPanelItem: + text: 'first tab' + Label: + text: 'First tab content area' + TabbedPanelItem: + text: 'tab2' + BoxLayout: + Label: + text: 'Second tab content area' + Button: + text: 'Button that does nothing' + TabbedPanelItem: + text: 'tab3' + RstDocument: + text: + '\\n'.join(("Hello world", "-----------", + "You are in the third tab.")) + +""") + + +class Test(TabbedPanel): + pass + + +class TabbedPanelApp(App): + def build(self): + return Test() + + +if __name__ == '__main__': + TabbedPanelApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/textalign.kv b/freechat-client/share/kivy-examples/widgets/textalign.kv new file mode 100644 index 0000000..674e493 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/textalign.kv @@ -0,0 +1,49 @@ +#:kivy 1.0 + +: + canvas.before: + Color: + rgb: 1, 0, 0 + Rectangle: + pos: self.pos + size: self.size + +: + grid: _grid + Label: + pos_hint: {'top': 1} + size_hint_y: None + height: 50 + font_size: 16 + text: 'Demonstration of text valign and halign' + GridLayout: + id: _grid + rows: 3 + cols: 3 + spacing: 10 + size_hint: (None, None) + pos_hint: {'center_x': .5, 'center_y': .5} + BoxLayout: + size_hint_y: None + height: 50 + ToggleButton: + halign: 'center' + group: 'case' + text: 'label.text_size =\n(None, None)' + on_release: root.app.select(0) + state: 'down' + ToggleButton: + halign: 'center' + group: 'case' + text: 'label.text_size =\n(label.width, None)' + on_release: root.app.select(1) + ToggleButton: + halign: 'center' + group: 'case' + text: 'label.text_size =\n(None, label.height)' + on_release: root.app.select(2) + ToggleButton: + halign: 'center' + group: 'case' + text: 'label.text_size =\n(label.width, label.height)' + on_release: root.app.select(3) diff --git a/freechat-client/share/kivy-examples/widgets/textalign.py b/freechat-client/share/kivy-examples/widgets/textalign.py new file mode 100644 index 0000000..45c5bfc --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/textalign.py @@ -0,0 +1,48 @@ +from kivy.app import App +from kivy.uix.label import Label +from kivy.uix.floatlayout import FloatLayout +from kivy.properties import ObjectProperty + + +class BoundedLabel(Label): + pass + + +class Selector(FloatLayout): + app = ObjectProperty(None) + grid = ObjectProperty(None) + + +class TextAlignApp(App): + + def select(self, case): + for _child in self.selector.grid.children[:]: + self.selector.grid.remove_widget(_child) + for valign in ('bottom', 'middle', 'top'): + for halign in ('left', 'center', 'right'): + label = BoundedLabel(text='V: %s\nH: %s' % (valign, halign), + size_hint=(None, None), + size=(150, 150), + halign=halign, valign=valign) + if case == 0: + label.text_size = (None, None) + elif case == 1: + label.text_size = (label.width, None) + elif case == 2: + label.text_size = (None, label.height) + else: + label.text_size = label.size + self.selector.grid.add_widget(label) + + self.selector.grid.bind(minimum_size=self.selector.grid.setter('size')) + + def build(self): + self.root = FloatLayout() + self.selector = Selector(app=self) + self.root.add_widget(self.selector) + self.grid = None + self.select(0) + return self.root + + +TextAlignApp().run() diff --git a/freechat-client/share/kivy-examples/widgets/textinput.py b/freechat-client/share/kivy-examples/widgets/textinput.py new file mode 100644 index 0000000..4871a7c --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/textinput.py @@ -0,0 +1,59 @@ +''' +Textinput tests +=============== + +This test is used to demonstrate virtual keyboard according to current +configuration. +Run this test as:: + + # use dock virtual keyboard (one instance) + python textinput.py -c kivy:keyboard_mode:dock + # use multi users virtual keyboard (multiples instance) + python textinput.py -c kivy:keyboard_mode:multi + # use system keyboard (one instance) + python textinput.py -c kivy:keyboard_mode:system + # use automatic detection from current platform + python textinput.py -c kivy:keyboard_mode: + +''' + +import kivy +kivy.require('1.0.8') + +from kivy.core.window import Window +from kivy.uix.textinput import TextInput +from kivy.uix.floatlayout import FloatLayout +from kivy.uix.scatter import Scatter +from kivy.uix.button import Button +from kivy.uix.label import Label +from kivy.config import Config +from kivy.base import runTouchApp + +if __name__ == '__main__': + + root = FloatLayout() + + # create a button to release everything + def release_all_keyboard(*l): + Window.release_all_keyboards() + btn = Button(text='Release\nall\nkeyboards', size_hint=(None, None), + halign='center') + btn.bind(on_release=release_all_keyboard) + root.add_widget(btn) + + # show current configuration + lbl = 'Configuration keyboard_mode is %r, keyboard_layout is %r' % ( + Config.get('kivy', 'keyboard_mode'), + Config.get('kivy', 'keyboard_layout')) + label = Label(text=lbl, size_hint_y=None, height=50, pos_hint={'top': 1}) + root.add_widget(label) + + s = Scatter(size_hint=(None, None), pos=(300, 300)) + s.add_widget(TextInput(size_hint=(None, None), size=(100, 50))) + root.add_widget(s) + + s = Scatter(size_hint=(None, None), pos=(400, 300), rotation=45) + s.add_widget(TextInput(size_hint=(None, None), size=(100, 50))) + root.add_widget(s) + + runTouchApp(root) diff --git a/freechat-client/share/kivy-examples/widgets/unicode_textinput.py b/freechat-client/share/kivy-examples/widgets/unicode_textinput.py new file mode 100644 index 0000000..84924a8 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/unicode_textinput.py @@ -0,0 +1,244 @@ +# -*- coding: utf-8 -*- + +from kivy.app import App +from kivy.lang import Builder +from kivy.properties import StringProperty, ObjectProperty +from kivy.core.text import Label as CoreLabel +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.floatlayout import FloatLayout +from kivy.uix.spinner import SpinnerOption +from kivy.uix.popup import Popup +import os + + +Builder.load_string(''' +#: import utils kivy +#: import os os +#: import Factory kivy.factory.Factory + + font_name: self.text if self.text else self.font_name + + + orientation: 'vertical' + txt_input: unicode_txt + spnr_fnt: fnt_spnr + BoxLayout: + size_hint: 1, .05 + Spinner: + id: fnt_spnr + text: 'RobotoMono-Regular' + font_name: self.text if self.text else self.font_name + values: app.get_font_list + option_cls: Factory.FntSpinnerOption + Spinner: + id: fntsz_spnr + text: '15' + values: map(str, map(sp, range(5,39))) + ScrollView: + size_hint: 1, .9 + TextInput: + id: unicode_txt + background_color: .8811, .8811, .8811, 1 + foreground_color: 0, 0, 0, 1 + font_name: fnt_spnr.font_name + font_size: fntsz_spnr.text + 'sp' + text: root.unicode_string + size_hint: 1, None + height: self.minimum_height + BoxLayout: + size_hint: 1, .05 + Label: + text: 'current font: ' + unicode_txt.font_name + Button: + size_hint: .15, 1 + text: 'change Font ...' + valign: 'middle' + halign: 'center' + text_size: self.size + on_release: root.show_load() + +: + platform: utils.platform + BoxLayout: + size: root.size + pos: root.pos + BoxLayout: + orientation: "vertical" + size_hint: .2, 1 + Button: + size_hint: 1, .2 + text: 'User font directory\\n' + valign: 'middle' + halign: 'center' + text_size: self.size + on_release: + _platform = root.platform + filechooser.path = (os.path.expanduser('~/.fonts') + if _platform == 'linux' else '/system/fonts' + if _platform == 'android' + else os.path.expanduser('~/Library/Fonts') + if _platform == 'macosx' + else os.environ['WINDIR'] +'\Fonts\') + Button: + size_hint: 1, .2 + text: 'System Font directory' + valign: 'middle' + halign: 'center' + text_size: self.size + on_release: + _platform = root.platform + filechooser.path = ('/usr/share/fonts' + if _platform == 'linux' else '/system/fonts' + if _platform == 'android' else os.path.expanduser + ('/System/Library/Fonts') if _platform == 'macosx' + else os.environ['WINDIR'] + "\Fonts\") + Label: + text: 'BookMarks' + BoxLayout: + orientation: "vertical" + FileChooserListView: + id: filechooser + filters: ['*.ttf'] + BoxLayout: + size_hint_y: None + height: 30 + Button: + text: "cancel" + on_release: root.cancel() + Button: + text: "load" + on_release: filechooser.selection != [] and root.load\ +(filechooser.path, filechooser.selection) +''') + + +class FntSpinnerOption(SpinnerOption): + pass + + +class LoadDialog(FloatLayout): + load = ObjectProperty(None) + cancel = ObjectProperty(None) + + +class Unicode_TextInput(BoxLayout): + + txt_input = ObjectProperty(None) + unicode_string = StringProperty("""Latin-1 supplement: éé çç ßß + +List of major languages taken from Google Translate +____________________________________________________ +Try changing the font to see if the font can render the glyphs you need in your +application. Scroll to see all languages in the list. + +Basic Latin: The quick brown fox jumps over the lazy old dog. +Albanian: Kafe të shpejtë dhelpra hedhje mbi qen lazy vjetër. +الثعلب البني السريع يقفز فوق الكلب القديمة البطيئة. :Arabic +Africans: Die vinnige bruin jakkals spring oor die lui hond. +Armenian: Արագ Brown Fox jumps ավելի ծույլ հին շունը. +Azerbaijani: Tez qonur tülkü də tənbəl yaşlı it üzərində atlamalar. +Basque: Azkar marroia fox alferrak txakur zaharra baino gehiago jauzi. +Belarusian: Хуткі карычневы ліс пераскоквае праз гультаяваты стары сабака. +Bengali: দ্রুত বাদামী শিয়াল অলস পুরানো কুকুর বেশি +Bulgarian: Бързата кафява лисица скача над мързелив куче. +Chinese Simpl: 敏捷的棕色狐狸跳过懒惰的老狗。 +Catalan: La cigonya tocava el saxofon en el vell gos mandrós. +Croation: Brzo smeđa lisica skoči preko lijen stari pas. +Czech: Rychlá hnědá liška skáče přes líného starého psa. +Danish: Den hurtige brune ræv hopper over den dovne gamle hund. +Dutch: De snelle bruine vos springt over de luie oude hond. +Estonian: Kiire pruun rebane hüppab üle laisa vana koer. +Filipino: Ang mabilis na brown soro jumps sa ang tamad lumang aso. +Finnish: Nopea ruskea kettu hyppää yli laiska vanha koira. +French: Le renard brun rapide saute par dessus le chien + paresseux vieux. +Galician: A lixeira raposo marrón ataca o can preguiceiro de idade. +Gregorian: სწრაფი ყავისფერი მელა jumps გამო ზარმაცი წლის ძაღლი. +German: Der schnelle braune Fuchs springt über den faulen alten Hund. +Greek: Η γρήγορη καφέ αλεπού πηδάει πάνω από το τεμπέλικο + γέρικο σκυλί. +Gujrati: આ ઝડપી ભુરો શિયાળ તે બેકાર જૂના કૂતરા પર કૂદકા. +Gurmukhi: ਤੇਜ ਭੂਰੇ ਰੰਗ ਦੀ ਲੂੰਬੜੀ ਆਲਸੀ ਬੁੱਢੇ ਕੁੱਤੇ ਦੇ ਉਤੋਂ ਦੀ ਟੱਪਦੀ ਹੈ । +Hiation Creole: Rapid mawon Rena a so sou chen an parese fin vye granmoun. +Hebrew: השועל החום הזריז קופץ על הכלב הישן עצלן. +Hindi: तेज भूरे रंग की लोमड़ी आलसी बूढ़े कुत्ते के उपर से कूदती है ॥ +Hungarian: A gyors barna róka átugorja a lusta vén kutya. +Icelandic: The fljótur Brown refur stökk yfir latur gamall hundur. +Indonesian: Cepat rubah cokelat melompat atas anjing tua malas. +Irish: An sionnach donn tapaidh jumps thar an madra leisciúil d\'aois. +Italian: The quick brown fox salta sul cane pigro vecchio. +Japanese: 速い茶色のキツネは、のろまな古いイヌに飛びかかった。 +Kannada: ತ್ವರಿತ ಕಂದು ನರಿ ಆಲೂಗಡ್ಡೆ ಹಳೆಯ ಶ್ವಾನ ಮೇಲೆ ಜಿಗಿತಗಳು. +Korean: 무궁화 게으른 옛 피었습니다. +Latin: Vivamus adipiscing orci et rutrum tincidunt super vetus canis. +Latvian: Ātra brūna lapsa lec pāri slinkam vecs suns. +Lithuanian: Greita ruda lapė šokinėja per tingus senas šuo. +Macedonian: Брзата кафена лисица скокови над мрзливи стариот пес. +Malay: Fox coklat cepat melompat atas anjing lama malas. +Maltese: Il-volpi kannella malajr jumps fuq il-kelb qodma għażżien. +Norweigian: Den raske brune reven hopper over den late gamle hunden. +Persian: روباه قهوه ای سریع روی سگ تنبل قدیمی میپرد. +Polish: Szybki brązowy lis przeskoczył nad leniwym psem życia. +Portugese: A ligeira raposa marrom ataca o cão preguiçoso de idade. +Romanian: Rapidă maro vulpea sare peste cainele lenes vechi. +Russian: Быстрая коричневая лисица перепрыгивает ленивого старого пса. +Serniam: Брза смеђа лисица прескаче лењог пса старог. +Slovak: Rýchla hnedá líška skáče cez lenivého starého psa. +Slovenian: Kožuščku hudobnega nad leni starega psa. +Spanish: La cigüeña tocaba el saxofón en el viejo perro perezoso. +Swahili: Haraka brown fox anaruka juu ya mbwa wavivu zamani. +Swedish: Den snabba bruna räven hoppar över den lata gammal hund. +Tamil: விரைவான பிரவுன் ஃபாக்ஸ் சோம்பேறி பழைய நாய் மீது + தொடரப்படுகிறது +Telugu: శీఘ్ర బ్రౌన్ ఫాక్స్ సోమరితనం పాత కుక్క కంటే హెచ్చుతగ్గుల. +Thai: สีน้ำตาลอย่างรวดเร็วจิ้งจอกกระโดดมากกว่าสุนัขเก่าที่ขี้เกียจ +Turkish: Hızlı kahverengi tilki tembel köpeğin üstünden atlar. +Ukranian: Швидкий коричневий лис перестрибує через лінивий старий пес. +Urdu: فوری بھوری لومڑی سست بوڑھے کتے پر کودتا. +Vietnamese: Các con cáo nâu nhanh chóng nhảy qua con chó lười biếng cũ. +Welsh: Mae'r cyflym frown llwynog neidio dros y ci hen ddiog. +Yiddish: דער גיך ברוין פוקס דזשאַמפּס איבער די פויל אַלט הונט.""") + + def dismiss_popup(self): + self._popup.dismiss() + + def load(self, _path, _fname): + self.txt_input.font_name = _fname[0] + _f_name = _fname[0][_fname[0].rfind(os.sep) + 1:] + self.spnr_fnt.text = _f_name[:_f_name.rfind('.')] + self._popup.dismiss() + + def show_load(self): + content = LoadDialog(load=self.load, cancel=self.dismiss_popup) + self._popup = Popup(title="load file", content=content, + size_hint=(0.9, 0.9)) + self._popup.open() + + +from kivy.utils import reify + + +class unicode_app(App): + + def build(self): + return Unicode_TextInput() + + @reify + def get_font_list(self): + '''Get a list of all the fonts available on this system. + ''' + + fonts_path = CoreLabel.get_system_fonts_dir() + flist = [] + + for fdir in fonts_path: + for fpath in sorted(os.listdir(fdir)): + if fpath.endswith('.ttf'): + flist.append(fpath[:-4]) + + return sorted(flist) + + +if __name__ == '__main__': + + unicode_app().run() diff --git a/freechat-client/share/kivy-examples/widgets/videoplayer.py b/freechat-client/share/kivy-examples/widgets/videoplayer.py new file mode 100644 index 0000000..6eeafc7 --- /dev/null +++ b/freechat-client/share/kivy-examples/widgets/videoplayer.py @@ -0,0 +1,26 @@ +import kivy +kivy.require('1.2.0') + +from sys import argv +from os.path import dirname, join +from kivy.app import App +from kivy.uix.videoplayer import VideoPlayer + +# check what formats are supported for your targeted devices +# for example try h264 video and acc audo for android using an mp4 +# container + + +class VideoPlayerApp(App): + + def build(self): + if len(argv) > 1: + filename = argv[1] + else: + curdir = dirname(__file__) + filename = join(curdir, 'cityCC0.mpg') + return VideoPlayer(source=filename, state='play') + + +if __name__ == '__main__': + VideoPlayerApp().run() diff --git a/freechat-client/src/client.py b/freechat-client/src/client.py new file mode 100644 index 0000000..f46e7d9 --- /dev/null +++ b/freechat-client/src/client.py @@ -0,0 +1,35 @@ +# main entry point module for the app + +import os, sys, json +from os.path import expanduser +from PySide2.QtQuick import QQuickView +from PySide2.QtCore import QStringListModel, Qt +from PySide2.QtGui import QGuiApplication + +def load_config(): + with open(expanduser('~') + '/.config/freechat-client/config.json') as cfg: + data = json.load(cfg) + + return data + + + +if __name__ == '__main__': + config = load_config() + # setup the window + server_names = [name for name in config['servers']] + app = QGuiApplication([]) + view = QQuickView() + view.setResizeMode(QQuickView.SizeRootObjectToView) + + listmodel = QStringListModel() + listmodel.setStringList(server_names) + view.rootContext().setContextProperty('listModel', listmodel) + + if view.status() == QQuickView.Error: + sys.exit(1) + + else: + view.show() + app.exec_() + del view diff --git a/freechat-client/src/configuration.py b/freechat-client/src/configuration.py new file mode 100644 index 0000000..d26b558 --- /dev/null +++ b/freechat-client/src/configuration.py @@ -0,0 +1,8 @@ +''' +Basic user configurations are handled via a basic json file +''' +import json + +class UserConfig(object): + pass + diff --git a/freechat-client/src/core.py b/freechat-client/src/core.py new file mode 100644 index 0000000..10dc1b3 --- /dev/null +++ b/freechat-client/src/core.py @@ -0,0 +1,96 @@ +# main entry point + +import sys, os +from os.path import expanduser +import json +from PySide2.QtCore import Slot, qApp +from PySide2.QtGui import QKeySequence +from PySide2.QtWidgets import QMainWindow, QAction, QHeaderView, QSizePolicy, \ + QTableView, QWidget, QApplication +from PySide2.QtCore import Qt, QAbstractTableModel, QModelIndex +from PySide2.QtGui import QColor + +''' +Here we find general UI elements +Most callbacks to networked functionality and data handling is found in other, more relevant modules +''' + + +class MainWindow(QMainWindow): + def __init__(self, widget): + QMainWindow.__init__(self) + self.setWindowTitle('Freechat') + self.setCentralWidget(widget) + + # Exit action + exit_action = QAction('Exit', self) + exit_action.setShortcut(QKeySequence.Quit) + exit_action.triggered.connect(self.close) + + # Window dimensions + geometry = qApp.desktop().availableGeometry(self) + self.setFixedSize(geometry.width() * 0.8, geometry.height() * 0.6) + + +class ServerList(QAbstractTableModel): + def __init__(self, data=None): + QAbstractTableModel.__init__(self) + self.load_server_list(data) + + def load_server_list(self, data): + ''' + at this point we assume that + a. the config has been loaded from somewhere + b. its actually there + ''' + # Data here is meant to be a list of dictionary's + self._server_names = [serv['name'] for serv in data] + self.b_server_descs = [serv['description'] for serv in data] + + self.column_count = 2 + self.row_count = len(self._server_names) + + def rowCount(self, parent=QModelIndex()): + return self.row_count + + def columnCount(self, parent=QModelIndex()): + return self.column_count + + +class Widget(QWidget): + def __init__(self, data): + QWidget.__init__(self) + + self.model = ServerList(data) + self.table_view = QTableView() + + # table headers + self.horizontal_header = self.table_view.horizontalHeader() + + +def read_whole_config(): + _config = {} + with open(expanduser('~') + '/.config/freechat-client/config.json') as cfg: + _config = json.load(cfg) + + return _config + + + +if __name__ == '__main__': + config = read_whole_config() + server_list = config['servers'] + username = config['global-username'] + app = QApplication([]) + + widget = Widget(server_list) + window = MainWindow(widget) + window.show() + + sys.exit(app.exec_()) + + + + + +