pymations 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/THIRD-PARTY-NOTICES +23 -0
- package/engine/LICENSE-polygon-clipping.txt +11 -0
- package/engine/anim.js +8 -7
- package/engine/manifest.json +1 -0
- package/package.json +1 -1
- package/pyctures.py +4 -2
- package/pymations.js +17 -4
- package/pymations.py +803 -36
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"files":["anim.js","opentype.min.js","katex.min.js","katex.min.css","fonts/KaTeX_AMS-Regular.ttf","fonts/KaTeX_AMS-Regular.woff2","fonts/KaTeX_Caligraphic-Bold.ttf","fonts/KaTeX_Caligraphic-Bold.woff2","fonts/KaTeX_Caligraphic-Regular.ttf","fonts/KaTeX_Caligraphic-Regular.woff2","fonts/KaTeX_Fraktur-Bold.ttf","fonts/KaTeX_Fraktur-Bold.woff2","fonts/KaTeX_Fraktur-Regular.ttf","fonts/KaTeX_Fraktur-Regular.woff2","fonts/KaTeX_Main-Bold.ttf","fonts/KaTeX_Main-Bold.woff2","fonts/KaTeX_Main-BoldItalic.ttf","fonts/KaTeX_Main-BoldItalic.woff2","fonts/KaTeX_Main-Italic.ttf","fonts/KaTeX_Main-Italic.woff2","fonts/KaTeX_Main-Regular.ttf","fonts/KaTeX_Main-Regular.woff2","fonts/KaTeX_Math-BoldItalic.ttf","fonts/KaTeX_Math-BoldItalic.woff2","fonts/KaTeX_Math-Italic.ttf","fonts/KaTeX_Math-Italic.woff2","fonts/KaTeX_SansSerif-Bold.ttf","fonts/KaTeX_SansSerif-Bold.woff2","fonts/KaTeX_SansSerif-Italic.ttf","fonts/KaTeX_SansSerif-Italic.woff2","fonts/KaTeX_SansSerif-Regular.ttf","fonts/KaTeX_SansSerif-Regular.woff2","fonts/KaTeX_Script-Regular.ttf","fonts/KaTeX_Script-Regular.woff2","fonts/KaTeX_Size1-Regular.ttf","fonts/KaTeX_Size1-Regular.woff2","fonts/KaTeX_Size2-Regular.ttf","fonts/KaTeX_Size2-Regular.woff2","fonts/KaTeX_Size3-Regular.ttf","fonts/KaTeX_Size3-Regular.woff2","fonts/KaTeX_Size4-Regular.ttf","fonts/KaTeX_Size4-Regular.woff2","fonts/KaTeX_Typewriter-Regular.ttf","fonts/KaTeX_Typewriter-Regular.woff2","fonts/LiberationSans-Bold.ttf","fonts/LiberationSans-BoldItalic.ttf","fonts/LiberationSans-Italic.ttf","fonts/LiberationSans-Regular.ttf"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pymations",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Maths animations from Python on any web page: the browser half of Pymations, with its animation engine. Runs Manim Community scripts. Python runs in the browser with Pyodide.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./pymations.js",
|
package/pyctures.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
# GENERATED by circuitry/scripts/sync-pymations-lib.mjs from src/lib/python-canvas/canvas-runtime-py.ts (version
|
|
1
|
+
# GENERATED by circuitry/scripts/sync-pymations-lib.mjs from src/lib/python-canvas/canvas-runtime-py.ts (version 13).
|
|
2
2
|
# Do not edit here: change it in Circuitry, then run the script.
|
|
3
3
|
# Pymations is MIT licensed; see LICENSE.
|
|
4
4
|
import sys, io, json, time, math, traceback, threading, types
|
|
5
5
|
|
|
6
|
-
VERSION = "
|
|
6
|
+
VERSION = "13"
|
|
7
7
|
USER_FILE = "main.py"
|
|
8
8
|
|
|
9
9
|
# Fixed handles the frame defines before anything runs.
|
|
@@ -31,6 +31,7 @@ class _State:
|
|
|
31
31
|
self.sections = {} # name -> ms this frame (measure mode)
|
|
32
32
|
self.vt = None # virtual seconds while recording, else None
|
|
33
33
|
self.live = False # frame code has run (draw(), await frame(), an event)
|
|
34
|
+
self.source = "" # the user's file, for modules that map lines (Pymations)
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
# WHICH RUN A THREAD IS WORKING FOR. On the device every frame is its own
|
|
@@ -776,6 +777,7 @@ def start(source, info_json):
|
|
|
776
777
|
S.thread = threading.get_ident()
|
|
777
778
|
S.busy = True
|
|
778
779
|
S.started = time.monotonic()
|
|
780
|
+
S.source = source
|
|
779
781
|
info = json.loads(info_json)
|
|
780
782
|
S.measuring = bool(info.get("measure"))
|
|
781
783
|
# Recording: virtual time from frame 0, and the same random numbers each take.
|
package/pymations.js
CHANGED
|
@@ -68,13 +68,14 @@ function prop(obj, name) {
|
|
|
68
68
|
|
|
69
69
|
// ---------------------------------------------------------------- images by relative path
|
|
70
70
|
|
|
71
|
-
/** A relative path to
|
|
72
|
-
const IMAGE_PATH = /^(?![a-z][a-z0-9+.-]*:|\/)(?:\.\/)?[^\s"'<>?#]+\.(png|jpe?g|gif|webp|svg|bmp|avif|mp3|wav|ogg|m4a|aac|flac)$/i
|
|
71
|
+
/** A relative path to a picture, a sound or a font file: no scheme, not absolute, a known extension (pages.IMAGE_PATH). */
|
|
72
|
+
const IMAGE_PATH = /^(?![a-z][a-z0-9+.-]*:|\/)(?:\.\/)?[^\s"'<>?#]+\.(png|jpe?g|gif|webp|svg|bmp|avif|mp3|wav|ogg|m4a|aac|flac|ttf|otf|woff2?)$/i
|
|
73
73
|
export function isRelativeImagePath(s) { return typeof s === 'string' && s.length < 300 && IMAGE_PATH.test(s) }
|
|
74
74
|
export const IMAGE_TYPES = {
|
|
75
75
|
png: 'image/png', jpg: 'image/jpeg', jpeg: 'image/jpeg', gif: 'image/gif',
|
|
76
76
|
webp: 'image/webp', svg: 'image/svg+xml', bmp: 'image/bmp', avif: 'image/avif',
|
|
77
77
|
mp3: 'audio/mpeg', wav: 'audio/wav', ogg: 'audio/ogg', m4a: 'audio/mp4', aac: 'audio/aac', flac: 'audio/flac',
|
|
78
|
+
ttf: 'font/ttf', otf: 'font/otf', woff: 'font/woff', woff2: 'font/woff2',
|
|
78
79
|
}
|
|
79
80
|
/** The key an image is packed under: as written, without a leading "./". */
|
|
80
81
|
const packedKey = (s) => s.replace(/^(\.\/)+/, '')
|
|
@@ -438,7 +439,7 @@ function unpackEngine(eng) {
|
|
|
438
439
|
window.fetch = (input, init) => {
|
|
439
440
|
const url = typeof input === 'string' ? input : (input && input.url) || String(input)
|
|
440
441
|
if (url.startsWith(prefix)) {
|
|
441
|
-
const b64 = fonts[decodeURIComponent(url.slice(prefix.length))]
|
|
442
|
+
const b64 = fonts[decodeURIComponent(url.slice(prefix.length).split(/[?#]/)[0])]
|
|
442
443
|
if (b64 != null) return Promise.resolve(new Response(fromBase64(b64), { headers: { 'Content-Type': 'font/ttf' } }))
|
|
443
444
|
}
|
|
444
445
|
return pageFetch(input, init)
|
|
@@ -1006,6 +1007,9 @@ class Player {
|
|
|
1006
1007
|
if (scene.opt.controls !== false) this.makeBar()
|
|
1007
1008
|
this.onKey = (e) => this.key(e)
|
|
1008
1009
|
window.addEventListener('keydown', this.onKey)
|
|
1010
|
+
// The engine's notices (a font or an equation still loading after a
|
|
1011
|
+
// while) and errors from work it finishes later, collected once a second.
|
|
1012
|
+
this.poll = setInterval(() => this.takeErrors(), 1000)
|
|
1009
1013
|
}
|
|
1010
1014
|
|
|
1011
1015
|
/** A new run. Python's first command resets the engine itself. */
|
|
@@ -1045,6 +1049,7 @@ class Player {
|
|
|
1045
1049
|
}
|
|
1046
1050
|
|
|
1047
1051
|
destroy() {
|
|
1052
|
+
clearInterval(this.poll)
|
|
1048
1053
|
this.halt()
|
|
1049
1054
|
this.observer.disconnect()
|
|
1050
1055
|
window.removeEventListener('keydown', this.onKey)
|
|
@@ -1064,7 +1069,15 @@ class Player {
|
|
|
1064
1069
|
}
|
|
1065
1070
|
|
|
1066
1071
|
takeErrors() {
|
|
1067
|
-
|
|
1072
|
+
const e = this.engine
|
|
1073
|
+
if (typeof e.takeNotices === 'function') {
|
|
1074
|
+
for (const n of e.takeNotices()) this.scene.log('info', 'animation: ' + ((n && n.message) || String(n)))
|
|
1075
|
+
}
|
|
1076
|
+
// Strings, or {message, line} with the Python line that made the command.
|
|
1077
|
+
for (const x of e.takeErrors ? e.takeErrors() : []) {
|
|
1078
|
+
if (x && typeof x === 'object') this.report((x.line ? 'line ' + x.line + ': ' : '') + (x.message || String(x)))
|
|
1079
|
+
else this.report(String(x))
|
|
1080
|
+
}
|
|
1068
1081
|
}
|
|
1069
1082
|
|
|
1070
1083
|
report(msg) {
|