How to render Manim animations faster? - manim

I found out that this animation takes a lot of time to render when there are more than 20 lines of text. Is there anything I can do to speed it up?
import itertools as it
class FormulaExample(Scene):
def setup(self):
self.text_example = Text("How are we doing?\nPlease help us\nimprove Stack Overflow.\nThanks!", font="Roboto", stroke_width=0)
class FadeInFromDirections(LaggedStart):
CONFIG = {
"directions":[DL,DOWN,DR,RIGHT,UR,UP,UL,LEFT],
"magnitude":1,
"lag_ratio":.05
}
def __init__(self, text , **kwargs):
digest_config(self, kwargs)
self.reverse_directions=it.cycle(list(reversed(self.directions)))
super().__init__(
*[FadeInFromPoint(obj,point=obj.get_center()+d*self.magnitude)
for obj,d in zip(text,self.reverse_directions)],
**kwargs
)
class FadeInFromDirectionsExample(FormulaExample):
def construct(self):
self.play(
FadeInFromDirections(self.text_example),
run_time=3
)
self.wait()

when compiling, you can use low quality mode, this will speed up compilation significantly, (which is good enough for previewing)

Related

kivy touch events bubbling and overriding on_ methods

The pictures example in /share/kivy-examples/demo/pictures places Image widget in Scatter. I'd like to extend the example and replace Image with <ImageButton#ButtonBehavior+Image>. However, the touch events are not implemented correctly. The ImageButtons are press-able but the drag functionality from the original example is lost.
At first I simply changed Image to <ImageButton#ButtonBehavior+Image> in the pictures.kv file. I see in the documentation that I may need to (re)implement on-press or on_touch_down. To that end, I've added these methods in the Picture class:
class Picture(Scatter):
source = StringProperty(None)
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
print('picture touch down')
else:
print('no collide in picture')
super(Picture, self).on_touch_down(touch)
def on_touch_move(self, touch):
if self.collide_point(*touch.pos):
print('touch move')
super(Picture, self).on_touch_move(touch)
I see the print statements in the terminal. But the ImageButtons are still consuming the on_press, and I know this from a print statement in that event handler. I tried to re-implement on_press and just not do anything with pass, and then I had an idea of calling self.parent.on_touch_down, but I don't have a touch object to pass into it.
One idea would be to
class ImageButton(ButtonBehavior, Image):
'''
def on_press(self):
print("button pressed")
print()
return super(ImageButton, self).on_press()
'''
def on_press(self):
pass
So, say I want the ImageButton to only register a double-clicks, and otherwise, for the widgets to behave just like in the example. How would I achieve that? Somewhat related
While there may be a way of distinguishing between a quick touch_down followed immediately by a touch_up, it is easier to show the desired functionality by letting an ImageButton press be activated with a double_tap:
class ImageButton(ButtonBehavior, Image):
def __init__(self, **kwargs):
super(ImageButton, self).__init__(**kwargs)
def on_touch_down(self, touch):
if self.collide_point(*touch.pos) and touch.is_double_tap:
self.on_press(touch)
return True
return False
def on_press(self,touch):
#whatever else you want to happen
return True

Why app code does not recognize design code?

I'm fairly new into programming so this may be lousy question.
I'm watching tutorials of kivy programming (https://youtu.be/k4QCoS-hj-s?list=PLCC34OHNcOtpz7PJQ7Tv7hqFBP_xDDjqg) and I'm stuck at design language code.
Basically, I'm trying to write a design language code (my.kv) for an app enter code here(design.py) which should be connected with this lines in design.py, because of "My" in class:
class MyApp(App):
def build(self):
return MyGridLayout()
Also, line in design.py:
class MyGridLayout(Widget):
is connected to first line in my.kv:
<MyGridLayout>
However, it seems design.py does not recognize it, even though they are saved in the same folder.
I was thinking problem may be in different operating systems (Linux-Windows) because of types of brackets, but I don't know what is the Windows parallel to Linux angle brackets.
Any thoughts?
EDIT
I tried what #NameKhan72 proposed:
from kivy.lang import Builder
class MyApp(App):
def build(self):
kv = Builder.load_file('my.kv')
return MyGridLayout()
but still getting error - "no such file or directory: "my.kv"".
EDIT2
I found the mistake. Of course, it was connected to my experience in programming. I didn't put ":" at the end of "". Now there is no error but after opening app I get a black screen.
I tried everything I found on the web but nothing so far.
This is code:
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
class MyGridLayout(Widget):
name = ObjectProperty(None)
pizza = ObjectProperty(None)
color = ObjectProperty(None)
def press(self):
name = self.name.text
pizza = self.pizza.text
color = self.color.text
print("Hello " + name + ", you like " + pizza + "pizza, and your favorite color is " + color + ".")
self.name.text =""
self.pizza.text =""
self.color.text =""
class MyApp(App):
def build(self):
return MyGridLayout()
if __name__ == "__main__":
MyApp().run()
This is design code in my.kv:
<MyGridLayout>:
name:name
pizza:pizza
color:color
GridLayout:
cols:1
size: root.width, root.height
GridLayout:
cols:2
Label:
text: "Name"
TextInput:
id: name
multiline:False
Label:
text: "Favorite pizza"
TextInput:
id: pizza
multiline:False
Label:
text: "Favorite color"
TextInput:
id: color
multiline:False
Button:
text: "Submit"
font_size: 32
on_press: root.press()
Is it typo or what? I rewrited the whole code 2x to be sure but still getting black screen.
You need to load the kv-file into python:
from kivy.lang import Builder
class MyApp(App):
def build(self):
kv = Builder.load_file('my.kv')
return MyGridLayout()
The answer my friend is blowing in the wind.
Nope, my problem was saving in wrong file extension. While saving, I writed my.kv but my PC saved it as my.kv.py. That was the reason why code didn't recognize design code.
Thanks for help, surely it'll help me in the future :)
you should use Builder.load_file("filename.kv") or `Builder.load_string(""
""")but to import it usefrom kivy.lang import Builder`

kivy: have tcp event open popup

I'm new to kivy, so apologies if I've missed something really basic here but I am struggling to understand both the behavior I'm getting as well as my inability to get the outcome I'm after.
The goal
The kivy app should be listening for TCP events from an external server, with certain triggers causing various stuffs in the kivy app. In this case, I want the external server to be able to open a popup in the app.
Illustrative Code
I have adopted the following (working) demo code from another SO answer that I can no longer seem to find, so apologies for the plagiarism but it is not intentional.
server.py
import socket
serversocket = socket.socket()
host = 'localhost'
port = 54545
serversocket.bind(('', port))
serversocket.listen(1)
clientsocket,addr = serversocket.accept()
print("got a connection from %s" % str(addr))
while True:
msg = input("> ")
clientsocket.send(msg.encode('utf-8'))
client.py
import socket
class MySocket:
def __init__(self,host="localhost",port=54545):
self.sock = socket.socket()
self.sock.connect((host, port))
def get_data(self):
return self.sock.recv(1024)
main.py
import kivy
from kivy.app import App
from kivy.event import EventDispatcher
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from threading import Thread
from client import *
kivy.require('1.9.1')
class MyEventDispatcher(EventDispatcher):
def __init__(self, **kwargs):
self.register_event_type('on_test')
super(MyEventDispatcher, self).__init__(**kwargs)
def do_something(self, value):
self.dispatch('on_test', value)
def on_test(self, *args):
print('I am dispatched', args)
CustomPopup().open()
class CustomPopup(Popup):
pass
class MainScreen(Label):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
self.sock = MySocket()
Thread(target=self.get_data).start()
def get_data(self):
while True:
self.text = self.sock.get_data().decode('utf-8').strip()
if self.text == 'click':
MyEventDispatcher().do_something(self.text)
class MyApp(App):
def build(self):
return MainScreen()
if __name__ == "__main__":
MyApp().run()
my.kv
<MainScreen>:
Button:
text: 'I do nothing'
<CustomPopup>:
title: 'Popup window'
size_hint: .5, .5
auto_dismiss: False
GridLayout:
cols: 1
Label:
size_hint: .9, .9
halign: 'center'
valign: 'middle'
text: 'message text goes here'
text_size: self.width, None
Button:
text: 'A: Close'
on_release: root.dismiss()
Button:
text: 'B: Close'
on_release: root.dismiss()
This all works in that I can send the trigger word click from the server and the popup will open, it has multiple placeholder buttons that work. Hooray.
The problem, however, is that I seem to require the dummy button on the main app screen, which I do not want. If I simply eliminate the <MainScreen> bit from the .kv file, sending the click keyword leads to:
I am dispatched ('click',)
Segmentation fault (core dumped)
but I can send any other string and it will display on screen as expected.
So, the basic questions are:
How do I get this to work as desired and
Why does placing a non-functional button on the screen make the popup work?
Thanks!

best tool for rendering short items of text in wxPython and Kivi

I have a multi-platform app running on desktop (wxPython) and mobile (kivy). In it I want to render small areas of variable text in a window in the app. The text will depend on the state of the app. I am happy to use rtf, html or reStructuredText. I need to use the same source for the text on each platform.
A typical example of a text snippet would be:
Heading
=======
1. With 24 widgets pull a **long** one;
2. with fewer, push a **wide** one.
Which would render as:
Heading
With 24 widgets pull a long one;
with fewer, push a wide one.
My question is: which format should I use?
My preference would be reStructuredText. There appears to be a kivy widget to support this but nothing in wxPython
One solution is to use the docutils package.
This will take reStructuredText and output it as html. I can then use the wxPython wx.html control to display the output.
import wx
import wx.html as wxhtml
from docutils.core import publish_string
class MainFrame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.panel = MainPanel(self)
sizer = wx.BoxSizer()
sizer.Add(self.panel)
self.SetSizerAndFit(sizer)
self.Show()
input_string = ("Heading\n"
"=======\n"
"\n"
"1. With 24 widgets pull a **long** one;\n"
"2. with fewer, push a **wide** one.\n")
self.display_rst(input_string)
def display_rst(self, rst):
html = publish_string(rst, writer_name='html')
self.panel.html.SetPage(html)
class MainPanel(wx.Panel):
def __init__(self, parent, *args, **kwargs):
wx.Panel.__init__(self, parent, *args, **kwargs)
display_style = wx.VSCROLL|wx.HSCROLL|wx.TE_READONLY|wx.BORDER_SIMPLE
self.html = wxhtml.HtmlWindow(self, -1, size=(300, 200),
style=display_style)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self.html)
self.SetSizer(sizer)
if __name__ == "__main__":
SCREEN_APP = wx.App()
MAIN_FRAME = MainFrame(None, title="Display HTML")
SCREEN_APP.MainLoop()

Why do I need to create a new instance of a Line instead of simply update or add and remove it in Kivy

I am attempting to draw a line with the mouse by dragging from one point to another point of the window. I also want to represent the line while I am dragging. Like drawing a line in an old MS PaintBrush.
My problem is that I have only been able to achieve this by constantly removing the old Line and adding a new Vertex Instruction to the canvas. However, I cannot update existing instructions. Not even adding and removing the same instruction. It has to be a new instance of Line. You can see the result that I want by running the following code. If you try to run it with the commented lines it doesn't work any more.
from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout
from kivy.graphics import Line
class MyCanvas(RelativeLayout):
def on_touch_down(self, touch):
with self.canvas:
self.line = Line(points=[touch.x,touch.y,touch.x+1,touch.y+1])
self.bind(on_touch_move=self.update_line, on_touch_up=self.end_line)
return True
def update_line(self, instance, touch):
self.line.points[2] = touch.x
self.line.points[3] = touch.y
self.canvas.remove(self.line)
# self.canvas.add(self.line) # - this doesn't work
# self.canvas.ask_update() # - not even using this
with self.canvas:
self.line = Line(points=self.line.points) # this works
def end_line(self, instance, touch):
self.unbind(on_touch_move=self.update_line)
self.unbind(on_touch_up=self.end_line)
self.line.points[2] = touch.x
self.line.points[3] = touch.y
self.canvas.remove(self.line)
# self.canvas.add(self.line) # - this doesn't work
# self.canvas.ask_update() #- not even using this
self.canvas.add(Line(points=self.line.points)) # this way works
class ExampleApp(App):
def build(self):
return MyCanvas()
ExampleApp().run()
I also tried using Kivy properties as suggested in this other question with the Color instruction. It didn't work and there is another question related to it.
I am struggling with the same problem. I started from the 6_button.py example from the kivy/guide/firstwidget directory
I found something that works (using pop twice to remove the last x,y pair from points) But I think it is very awkward, see my code below. I hope someone can tel us how to 'update' properly.
based on 6_button.py
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 = 10.
Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
touch.ud['line'] = Line(points=(touch.x, touch.y, touch.x+30, touch.y))
#print(dir(touch.ud['line']))
def on_touch_move(self, touch):
#touch.ud['line'].points += [touch.x, touch.y]
touch.ud['line'].points.pop() #
touch.ud['line'].points.pop() # works but is awkward
touch.ud['line'].points += [touch.x, touch.y] #
#touch.ud['line'].points[2:4] = [touch.x, touch.y]
#self.canvas.ask_update() # no error but didnt work
#touch.ud['line'].ask_update() # didnt work
#print(touch.ud['line'].points)
#touch.ud['line'].needs_redraw() # error 'bool not callable'
#touch.ud['line'].needs_redraw = True # error 'not writable'
#touch.ud['line'].needs_redraw #no error but doesnt work
class MyPaintApp(App):
def build(self):
parent = Widget()
painter = MyPaintWidget()
clearbtn = Button(text='Clear')
parent.add_widget(painter)
parent.add_widget(clearbtn)
def clear_canvas(obj):
painter.canvas.clear()
clearbtn.bind(on_release=clear_canvas)
return parent
if __name__ == '__main__':
MyPaintApp().run()

Resources