Spaces:
Sleeping
Sleeping
Patrick Rathje
commited on
Commit
·
96fb70e
1
Parent(s):
5c94804
Working examples
Browse files- app.py +54 -19
- examples/code.tsx +36 -0
- examples/gradio-motion-canvas-example.tsx +64 -0
- examples/latex.tsx +12 -0
- examples/motion-canvas-blur.tsx +17 -0
- examples/simple-sphere.tsx +23 -0
app.py
CHANGED
@@ -5,6 +5,7 @@ import shutil
|
|
5 |
import uuid
|
6 |
import subprocess
|
7 |
from threading import Timer
|
|
|
8 |
|
9 |
from gradio_motioncanvasplayer import MotionCanvasPlayer
|
10 |
|
@@ -84,32 +85,66 @@ def build_project(code):
|
|
84 |
# cleanup tmp dir
|
85 |
shutil.rmtree(tmp_dir)
|
86 |
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
gr.Markdown("# Motion Canvas MCP Server")
|
102 |
with gr.Row():
|
103 |
with gr.Column():
|
104 |
-
gr.Markdown("## TS Input for
|
105 |
-
|
106 |
-
|
|
|
107 |
logs = gr.Textbox(value="", label="Build Logs", interactive=False)
|
108 |
with gr.Column():
|
109 |
gr.Markdown("## Preview")
|
110 |
-
player = MotionCanvasPlayer(
|
111 |
-
|
112 |
|
|
|
|
|
|
|
|
|
113 |
submit.click(build_project, inputs=[code], outputs=[player, logs], api_name="build_project")
|
114 |
|
115 |
if __name__ == "__main__":
|
|
|
5 |
import uuid
|
6 |
import subprocess
|
7 |
from threading import Timer
|
8 |
+
from functools import partial
|
9 |
|
10 |
from gradio_motioncanvasplayer import MotionCanvasPlayer
|
11 |
|
|
|
85 |
# cleanup tmp dir
|
86 |
shutil.rmtree(tmp_dir)
|
87 |
|
88 |
+
def load_example_code(example_name):
|
89 |
+
return open(os.path.join(os.path.dirname(__file__), "examples", example_name + ".tsx")).read()
|
90 |
+
|
91 |
+
def build_example(example_name):
|
92 |
+
iterator = build_project(load_example_code(example_name))
|
93 |
+
last = next(iterator)
|
94 |
+
for last in iterator:
|
95 |
+
continue
|
96 |
+
|
97 |
+
path = last[0]
|
98 |
+
assert path
|
99 |
+
return path
|
100 |
+
|
101 |
+
print("Building examples...")
|
102 |
+
EXAMPLES = [
|
103 |
+
{
|
104 |
+
"name": "Gradio + Motion Canvas",
|
105 |
+
"code": load_example_code("gradio-motion-canvas-example"),
|
106 |
+
"project_path": build_example("gradio-motion-canvas-example")
|
107 |
+
},
|
108 |
+
{
|
109 |
+
"name": "Blur",
|
110 |
+
"code": load_example_code("motion-canvas-blur"),
|
111 |
+
"project_path": build_example("motion-canvas-blur")
|
112 |
+
},
|
113 |
+
{
|
114 |
+
"name": "Latex",
|
115 |
+
"code": load_example_code("latex"),
|
116 |
+
"project_path": build_example("latex")
|
117 |
+
},
|
118 |
+
{
|
119 |
+
"name": "Code",
|
120 |
+
"code": load_example_code("code"),
|
121 |
+
"project_path": build_example("code")
|
122 |
+
},
|
123 |
+
|
124 |
+
]
|
125 |
+
print("Examples built!")
|
126 |
+
|
127 |
+
def load_example(example):
|
128 |
+
return example['project_path'], example['code'], ""
|
129 |
+
|
130 |
+
|
131 |
+
with gr.Blocks(theme=gr.themes.Monochrome()) as demo:
|
132 |
gr.Markdown("# Motion Canvas MCP Server")
|
133 |
with gr.Row():
|
134 |
with gr.Column():
|
135 |
+
gr.Markdown("## TS Input for Your Scene")
|
136 |
+
gr.Markdown("Leverage the power of Motion Canvas to create your own animations using TypeScript.")
|
137 |
+
code = gr.Code(value=EXAMPLES[0]['code'], language="typescript")
|
138 |
+
submit = gr.Button("Build", variant="primary")
|
139 |
logs = gr.Textbox(value="", label="Build Logs", interactive=False)
|
140 |
with gr.Column():
|
141 |
gr.Markdown("## Preview")
|
142 |
+
player = MotionCanvasPlayer(EXAMPLES[0]['project_path'], auto=True, quality=0.5, width=1920, height=1080, variables="{}")
|
|
|
143 |
|
144 |
+
for ex in EXAMPLES:
|
145 |
+
btn = gr.Button("Load Example: " + ex["name"], variant="secondary")
|
146 |
+
btn.click(partial(load_example, ex), outputs=[player, code, logs])
|
147 |
+
|
148 |
submit.click(build_project, inputs=[code], outputs=[player, logs], api_name="build_project")
|
149 |
|
150 |
if __name__ == "__main__":
|
examples/code.tsx
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {makeScene2D, Code} from '@motion-canvas/2d';
|
2 |
+
import {all, createRef, DEFAULT, waitFor} from '@motion-canvas/core';
|
3 |
+
|
4 |
+
// Visit https://motioncanvas.io/docs/code/ for more information.
|
5 |
+
export default makeScene2D(function* (view) {
|
6 |
+
view.fill('white');
|
7 |
+
const code = createRef<Code>();
|
8 |
+
|
9 |
+
view.add(
|
10 |
+
<Code
|
11 |
+
ref={code}
|
12 |
+
fontSize={28}
|
13 |
+
fontFamily={'JetBrains Mono, monospace'}
|
14 |
+
fill={"black"}
|
15 |
+
offsetX={-1}
|
16 |
+
x={-400}
|
17 |
+
code={'const number = 7;'}
|
18 |
+
/>,
|
19 |
+
);
|
20 |
+
|
21 |
+
yield* waitFor(0.6);
|
22 |
+
yield* all(
|
23 |
+
code().code.replace(code().findFirstRange('number'), 'variable', 0.6),
|
24 |
+
code().code.prepend(0.6)`function example() {\n `,
|
25 |
+
code().code.append(0.6)`\n}`,
|
26 |
+
);
|
27 |
+
|
28 |
+
yield* waitFor(0.6);
|
29 |
+
yield* code().selection(code().findFirstRange('variable'), 0.6);
|
30 |
+
|
31 |
+
yield* waitFor(0.6);
|
32 |
+
yield* all(
|
33 |
+
code().code('const number = 7;', 0.6),
|
34 |
+
code().selection(DEFAULT, 0.6),
|
35 |
+
);
|
36 |
+
});
|
examples/gradio-motion-canvas-example.tsx
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {makeScene2D, Img, Layout, Icon} from '@motion-canvas/2d';
|
2 |
+
import {createRef, easeOutCubic, spring, all, waitFor} from '@motion-canvas/core';
|
3 |
+
|
4 |
+
let gradioLogoSvg = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='576'%20height='576'%20viewBox='0%200%20576%20576'%20fill='none'%3e%3cpath%20d='M287.5%20229L86%20344.5L287.5%20460L489%20344.5L287.5%20229Z'%20stroke='url(%23paint0_linear_102_7)'%20stroke-width='59'%20stroke-linejoin='round'/%3e%3cpath%20d='M287.5%20116L86%20231.5L287.5%20347L489%20231.5L287.5%20116Z'%20stroke='url(%23paint1_linear_102_7)'%20stroke-width='59'%20stroke-linejoin='round'/%3e%3cpath%20d='M86%20344L288%20229'%20stroke='url(%23paint2_linear_102_7)'%20stroke-width='59'%20stroke-linejoin='bevel'/%3e%3cdefs%3e%3clinearGradient%20id='paint0_linear_102_7'%20x1='60'%20y1='341'%20x2='429.5'%20y2='344'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20stop-color='%23F9D100'/%3e%3cstop%20offset='1'%20stop-color='%23F97700'/%3e%3c/linearGradient%3e%3clinearGradient%20id='paint1_linear_102_7'%20x1='513.5'%20y1='231'%20x2='143.5'%20y2='231'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20stop-color='%23F9D100'/%3e%3cstop%20offset='1'%20stop-color='%23F97700'/%3e%3c/linearGradient%3e%3clinearGradient%20id='paint2_linear_102_7'%20x1='60'%20y1='344'%20x2='428.987'%20y2='341.811'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20stop-color='%23F9D100'/%3e%3cstop%20offset='1'%20stop-color='%23F97700'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e"
|
5 |
+
|
6 |
+
export default makeScene2D(function* (view) {
|
7 |
+
view.fill('white'); // set the background of this scene
|
8 |
+
|
9 |
+
const gradioLogo = createRef<Img>();
|
10 |
+
const addIcon = createRef<Icon>();
|
11 |
+
const motionCanvasLogo = createRef<Img>();
|
12 |
+
const plusIcon = createRef<Icon>();
|
13 |
+
const heartIcon = createRef<Icon>();
|
14 |
+
|
15 |
+
view.add(
|
16 |
+
<Layout layout direction={'row'} size={'100%'} padding={100} gap={0} alignItems={'center'} justifyContent={'center'}>
|
17 |
+
<Img ref={gradioLogo} src={gradioLogoSvg} width='25%' offset={[1,2]}/>
|
18 |
+
<Icon ref={addIcon} icon="material-symbols-light:add-2-rounded" color="#404040" width='20%' margin={-10} />
|
19 |
+
<Img ref={motionCanvasLogo} src="https://motioncanvas.io/img/logo.svg" width='25%' margin={-10} />
|
20 |
+
<Icon ref={plusIcon} icon="material-symbols-light:equal" color="#404040" width='20%' margin={-30} />
|
21 |
+
<Icon ref={heartIcon} icon="material-symbols-light:favorite" color="#ff6470" width='25%' />
|
22 |
+
</Layout>
|
23 |
+
);
|
24 |
+
|
25 |
+
let initalMargin = view.size().y*1.5;
|
26 |
+
gradioLogo().margin.bottom(initalMargin);
|
27 |
+
addIcon().margin.bottom(initalMargin);
|
28 |
+
motionCanvasLogo().margin.bottom(initalMargin);
|
29 |
+
plusIcon().margin.bottom(initalMargin);
|
30 |
+
heartIcon().margin.bottom(initalMargin);
|
31 |
+
|
32 |
+
const MySpring = {
|
33 |
+
mass: 0.04,
|
34 |
+
stiffness: 10.0,
|
35 |
+
damping: 0.85,
|
36 |
+
initialVelocity: 8.0,
|
37 |
+
};
|
38 |
+
|
39 |
+
let springInAnim = function(obj : any) {
|
40 |
+
return spring(MySpring, initalMargin, 0, 5, value => {
|
41 |
+
obj().margin.bottom(value);
|
42 |
+
});
|
43 |
+
};
|
44 |
+
|
45 |
+
yield* springInAnim(gradioLogo);
|
46 |
+
yield* springInAnim(addIcon);
|
47 |
+
yield* springInAnim(motionCanvasLogo);
|
48 |
+
yield* springInAnim(plusIcon);
|
49 |
+
yield* springInAnim(heartIcon);
|
50 |
+
|
51 |
+
yield * waitFor(1);
|
52 |
+
|
53 |
+
// let them fade away
|
54 |
+
yield* all(
|
55 |
+
gradioLogo().opacity(0, 1, easeOutCubic),
|
56 |
+
addIcon().opacity(0, 1, easeOutCubic),
|
57 |
+
motionCanvasLogo().opacity(0, 1, easeOutCubic),
|
58 |
+
plusIcon().opacity(0, 1, easeOutCubic),
|
59 |
+
heartIcon().opacity(0, 1, easeOutCubic),
|
60 |
+
);
|
61 |
+
|
62 |
+
yield * waitFor(1);
|
63 |
+
|
64 |
+
});
|
examples/latex.tsx
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {Latex, makeScene2D} from '@motion-canvas/2d';
|
2 |
+
import {createRef, waitFor} from '@motion-canvas/core';
|
3 |
+
|
4 |
+
// Visit https://motioncanvas.io/docs/latex/ for more information.
|
5 |
+
export default makeScene2D(function* (view) {
|
6 |
+
view.fill('white');
|
7 |
+
const tex = createRef<Latex>();
|
8 |
+
view.add(<Latex ref={tex} tex="{{1}} + {{2}}" fill="black" />);
|
9 |
+
|
10 |
+
yield* waitFor(0.5);
|
11 |
+
yield* tex().tex(['2', '+', '3', '+', '4'], 1);
|
12 |
+
});
|
examples/motion-canvas-blur.tsx
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {Img, makeScene2D} from '@motion-canvas/2d';
|
2 |
+
import {createRef} from '@motion-canvas/core';
|
3 |
+
|
4 |
+
// Visit https://motioncanvas.io/docs for more information.
|
5 |
+
export default makeScene2D(function* (view) {
|
6 |
+
view.fill('#141414');
|
7 |
+
|
8 |
+
const iconRef = createRef<Img>();
|
9 |
+
yield view.add(<Img src={'https://motioncanvas.io/img/logo_dark.svg'} size={500} ref={iconRef} />);
|
10 |
+
// Modification happens by accessing the `filters` property.
|
11 |
+
// Individual filters don't need to be initialized. If a filter you set doesn't
|
12 |
+
// exists, it will be automatically created and added to the list of filters.
|
13 |
+
// If you have multiple filters of the same type, this will only
|
14 |
+
// modify the first instance (you can use the array method for more control).
|
15 |
+
yield* iconRef().filters.blur(10, 1);
|
16 |
+
yield* iconRef().filters.blur(0, 1);
|
17 |
+
});
|
examples/simple-sphere.tsx
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {makeScene2D, Circle} from '@motion-canvas/2d';
|
2 |
+
import {all, createRef} from '@motion-canvas/core';
|
3 |
+
|
4 |
+
// Visit https://motioncanvas.io/docs for more information.
|
5 |
+
export default makeScene2D(function* (view) {
|
6 |
+
const myCircle = createRef<Circle>();
|
7 |
+
|
8 |
+
view.add(
|
9 |
+
<Circle
|
10 |
+
ref={myCircle}
|
11 |
+
// try changing these properties:
|
12 |
+
x={-300}
|
13 |
+
width={140}
|
14 |
+
height={140}
|
15 |
+
fill="#e13238"
|
16 |
+
/>,
|
17 |
+
);
|
18 |
+
|
19 |
+
yield* all(
|
20 |
+
myCircle().position.x(300, 1).to(-300, 1),
|
21 |
+
myCircle().fill('#e6a700', 1).to('#e13238', 1),
|
22 |
+
);
|
23 |
+
});
|