create-definedmotion 0.1.4 → 0.3.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.
Files changed (81) hide show
  1. package/package.json +2 -2
  2. package/template/package-lock.json +313 -59
  3. package/template/package.json +1 -0
  4. package/template/src/assets/audio/testing_shadow_glow_song.mp3 +0 -0
  5. package/template/src/assets/for_tests/svg/gravity_text.svg +38 -0
  6. package/template/src/assets/for_tests/svg/grip_figure.svg +28 -0
  7. package/template/src/entry.ts +4 -5
  8. package/template/src/example_scenes/alternativesScene.ts +1 -1
  9. package/template/src/example_scenes/dependencyScene.ts +2 -4
  10. package/template/src/example_scenes/fourierSeriesScene.ts +10 -11
  11. package/template/src/example_scenes/keyboardScene.ts +14 -16
  12. package/template/src/example_scenes/latex_text_transitions_scene.ts +146 -0
  13. package/template/src/example_scenes/tests/animations/camera_movements/test_2d_camera_centers_labels.ts +53 -0
  14. package/template/src/example_scenes/tests/animations/camera_movements/test_2d_camera_hits_markers.ts +40 -0
  15. package/template/src/example_scenes/tests/animations/camera_movements/test_camera_rotate_quaternion.ts +17 -0
  16. package/template/src/example_scenes/tests/animations/camera_movements/test_camera_waypoints_sequential.ts +29 -0
  17. package/template/src/example_scenes/tests/animations/camera_movements/test_fly_camera_waypoints_verifiable.ts +87 -0
  18. package/template/src/example_scenes/tests/animations/camera_movements/test_zoom_perspective_sequential.ts +17 -0
  19. package/template/src/example_scenes/tests/animations/latex/test_latex_blue_particle_transition.ts +82 -0
  20. package/template/src/example_scenes/tests/animations/latex/test_latex_highlight_animation.ts +64 -0
  21. package/template/src/example_scenes/tests/animations/latex/test_latex_mark_animation.ts +42 -0
  22. package/template/src/example_scenes/tests/animations/latex/test_latex_particle_transition.ts +48 -0
  23. package/template/src/example_scenes/tests/animations/latex/test_latex_particle_transition_complex.ts +65 -0
  24. package/template/src/example_scenes/tests/animations/latex/test_latex_particle_transition_super_complex.ts +86 -0
  25. package/template/src/example_scenes/tests/animations/latex/test_with_environment_latex_particle_transition.ts +80 -0
  26. package/template/src/example_scenes/tests/animations/latex/test_write_latex_animation.ts +28 -0
  27. package/template/src/example_scenes/tests/animations/latex/test_write_latex_animation_2.ts +34 -0
  28. package/template/src/example_scenes/tests/animations/latex/test_write_latex_animation_3.ts +34 -0
  29. package/template/src/example_scenes/tests/animations/test_updater.ts +24 -0
  30. package/template/src/example_scenes/tests/audio/test_long_audio.ts +11 -0
  31. package/template/src/example_scenes/tests/audio/test_many_short_sounds.ts +50 -0
  32. package/template/src/example_scenes/tests/deferred_anims/testing_deferredAnims.ts +71 -0
  33. package/template/src/example_scenes/tests/deferred_anims/testing_deferredAnims2.ts +65 -0
  34. package/template/src/example_scenes/tests/environment/test_hdri_performance.ts +14 -0
  35. package/template/src/example_scenes/tests/svg/test_basic_latex_query.ts +59 -0
  36. package/template/src/example_scenes/tests/svg/test_basic_svg.ts +11 -0
  37. package/template/src/example_scenes/tests/svg/test_colored_latex_to_svg.ts +42 -0
  38. package/template/src/example_scenes/tests/svg/test_complex_latex_to_svg.ts +22 -0
  39. package/template/src/example_scenes/tests/svg/test_latex_to_svg.ts +17 -0
  40. package/template/src/example_scenes/tests/svg/test_material_on_latex.ts +43 -0
  41. package/template/src/example_scenes/tests/svg/test_query_latex_variables.ts +66 -0
  42. package/template/src/example_scenes/tests/svg/test_regular_text_latex.ts +21 -0
  43. package/template/src/example_scenes/tests/svg/test_super_complex_latex_to_svg.ts +98 -0
  44. package/template/src/example_scenes/tests/svg/test_transition_svgs.ts +33 -0
  45. package/template/src/example_scenes/tests/svg/test_update_svg_object.ts +19 -0
  46. package/template/src/example_scenes/tests/svg/test_yellow_grip_symbol_svg.ts +11 -0
  47. package/template/src/example_scenes/tutorials/easy1.ts +4 -4
  48. package/template/src/example_scenes/tutorials/easy3.ts +1 -1
  49. package/template/src/example_scenes/tutorials/medium1.ts +3 -5
  50. package/template/src/example_scenes/vectorField.ts +2 -4
  51. package/template/src/example_scenes/visulizingFunctions.ts +5 -7
  52. package/template/src/main/index.ts +59 -3
  53. package/template/src/main/rendering.ts +38 -21
  54. package/template/src/preload/index.ts +15 -1
  55. package/template/src/renderer/index.html +1 -1
  56. package/template/src/renderer/src/App.svelte +215 -32
  57. package/template/src/renderer/src/application_assets/360.svg +39 -0
  58. package/template/src/renderer/src/application_assets/move.svg +37 -0
  59. package/template/src/renderer/src/lib/animation/animations.ts +141 -88
  60. package/template/src/renderer/src/lib/animation/captureCanvas.ts +3 -17
  61. package/template/src/renderer/src/lib/animation/interpolations.ts +2 -1
  62. package/template/src/renderer/src/lib/animation/latexMarkAndHighlight.ts +349 -0
  63. package/template/src/renderer/src/lib/animation/latexTransitionsAndWrite.ts +558 -0
  64. package/template/src/renderer/src/lib/audio/manager.ts +185 -0
  65. package/template/src/renderer/src/lib/general/helpers.ts +16 -47
  66. package/template/src/renderer/src/lib/rendering/hdri.ts +273 -0
  67. package/template/src/renderer/src/lib/rendering/lighting3d.ts +0 -105
  68. package/template/src/renderer/src/lib/rendering/setup.ts +7 -1
  69. package/template/src/renderer/src/lib/rendering/svg/latexSVGQueries.ts +44 -0
  70. package/template/src/renderer/src/lib/rendering/svg/latexToSVG.ts +132 -0
  71. package/template/src/renderer/src/lib/rendering/svg/svgObjectHelpers.ts +59 -0
  72. package/template/src/renderer/src/lib/rendering/svg/svgRendering.ts +120 -0
  73. package/template/src/renderer/src/lib/scene/sceneClass.ts +180 -62
  74. package/template/src/renderer/src/lib/animation/helpers.ts +0 -7
  75. package/template/src/renderer/src/lib/audio/loader.ts +0 -104
  76. package/template/src/renderer/src/lib/rendering/materials.ts +0 -6
  77. package/template/src/renderer/src/lib/rendering/protocols.ts +0 -21
  78. package/template/src/renderer/src/lib/rendering/svg/drawing.ts +0 -213
  79. package/template/src/renderer/src/lib/rendering/svg/parsing.ts +0 -717
  80. package/template/src/renderer/src/lib/rendering/svg/rastered.ts +0 -42
  81. package/template/src/renderer/src/lib/rendering/svgObjects.ts +0 -1137
@@ -0,0 +1,42 @@
1
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
2
+ import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
3
+ import { latexToSVG } from "$renderer/lib/rendering/svg/latexToSVG";
4
+
5
+ export const test_colored_latex_to_svg = (): AnimatedScene => {
6
+ return new AnimatedScene(1000, 1000, SpaceSetting.ThreeDim, HotReloadSetting.TraceFromStart, async (dm) => {
7
+
8
+ // 1) Inline colors via \style{color:...}
9
+ const eq1 = latexToSVG(String.raw`
10
+ \begin{aligned}
11
+ \style{color:#ff3b3b}{\nabla\cdot\vec{E}} &=
12
+ \style{color:rgba(255,59,59,0.5)}{\frac{\rho}{\varepsilon_0}}
13
+
14
+ \style{color:#3b82f6}{e^{i\theta}} &=
15
+ \style{color:#10b981}{\cos\theta} +
16
+ \style{color:#f59e0b}{i\sin\theta}
17
+ \end{aligned}
18
+ `, { display: true });
19
+
20
+ // 2) Mixed \textcolor and CSS rgba, plus a semi-transparent bbox
21
+ const eq2 = latexToSVG(String.raw`
22
+ \bbox[6px, border:1px solid rgba(0,255,255,0.5), background:rgba(0,0,0,0.25)]{
23
+ \textcolor{#22c55e}{\mathbb{E}[X]}
24
+ = \style{color:rgba(34,197,94,0.6)}{\int_{\mathbb{R}} x\, d\mathbb{P}(x)}
25
+ }
26
+ `, { display: true });
27
+
28
+ // 3) A palette inside a matrix
29
+ const eq3 = latexToSVG(String.raw`
30
+ \begin{bmatrix}
31
+ \style{color:#ef4444}{a} & \style{color:#f97316}{b} & \style{color:#eab308}{c}\\
32
+ \style{color:#22c55e}{d} & \style{color:#3b82f6}{e} & \style{color:#a855f7}{f}\\
33
+ \style{color:#ec4899}{g} & \style{color:#06b6d4}{h} & \style{color:#9ca3af}{i}
34
+ \end{bmatrix}
35
+ `, { display: true });
36
+
37
+ // Place them using your width normalization
38
+ const g1 = createSVGShape(eq1, 14); g1.position.set(0, 5, 0); dm.add(g1);
39
+ const g2 = createSVGShape(eq2, 12); g2.position.set(0, 0, 0); dm.add(g2);
40
+ const g3 = createSVGShape(eq3, 10); g3.position.set(0, -5, 0); dm.add(g3);
41
+ });
42
+ };
@@ -0,0 +1,22 @@
1
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
2
+ import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
3
+ import { latexToSVG } from "$renderer/lib/rendering/svg/latexToSVG";
4
+
5
+
6
+ export const test_complex_latex_to_svg = (): AnimatedScene => {
7
+ return new AnimatedScene(1000, 1000, SpaceSetting.ThreeDim, HotReloadSetting.TraceFromStart, async (dm) => {
8
+ const raw = latexToSVG(String.raw`
9
+ \begin{aligned}
10
+ \hat{f}(\omega) &= \int_{-\infty}^{\infty} f(t)\,e^{-i\omega t}\,dt,\\
11
+ f(t) &= \frac{1}{2\pi}\int_{-\infty}^{\infty} \hat{f}(\omega)\,e^{i\omega t}\,d\omega,\\[6pt]
12
+ \Gamma(z) &= \int_{0}^{\infty} t^{z-1} e^{-t}\,dt,\qquad
13
+ \zeta(s) = \prod_{p\in\mathbb{P}} \frac{1}{1-p^{-s}}
14
+ \end{aligned}
15
+ `, { display: true });
16
+
17
+ console.log("RAW", raw)
18
+
19
+ const g = createSVGShape(raw, 12);
20
+ dm.add(g);
21
+ });
22
+ };
@@ -0,0 +1,17 @@
1
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
2
+ import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
3
+ import { latexToSVG } from "$renderer/lib/rendering/svg/latexToSVG";
4
+
5
+
6
+ export const test_latex_to_svg = (): AnimatedScene => {
7
+ return new AnimatedScene(
8
+ 1000, 1000,
9
+ SpaceSetting.ThreeDim,
10
+ HotReloadSetting.TraceFromStart,
11
+ async (dm) => {
12
+ const svg = latexToSVG(String.raw`\nabla \cdot \vec{E} = \frac{\rho}{\varepsilon_0}`);
13
+ const g = createSVGShape(svg, 10);
14
+ dm.add(g);
15
+ }
16
+ );
17
+ };
@@ -0,0 +1,43 @@
1
+ import { createBumpMap } from "$renderer/lib/rendering/bumpMaps/noise";
2
+ import { addHDRI, HDRIs, loadHDRIData } from "$renderer/lib/rendering/hdri";
3
+ import { addSceneLighting, } from "$renderer/lib/rendering/lighting3d";
4
+ import { latexToSVG } from "$renderer/lib/rendering/svg/latexToSVG";
5
+ import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
6
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
7
+ import * as THREE from 'three';
8
+
9
+
10
+ const hdriData = await loadHDRIData(HDRIs.outdoor1, 1)
11
+
12
+
13
+ export const test_material_on_latex = (): AnimatedScene => {
14
+ return new AnimatedScene(
15
+ 1000, 1000,
16
+ SpaceSetting.ThreeDim,
17
+ HotReloadSetting.TraceFromStart,
18
+ async (dm) => {
19
+
20
+
21
+ await addHDRI(dm, hdriData, 6)
22
+ const svg = latexToSVG(String.raw`\nabla \cdot \vec{E} = \frac{\rho}{\varepsilon_0}`);
23
+ const group = createSVGShape(svg, 20);
24
+
25
+ // the material you want to apply
26
+ const metalMaterial = new THREE.MeshStandardMaterial({
27
+ color: 0xffffff, // slightly darker red often looks nicer for metal
28
+ metalness: 0.9, // close to 1 = very metallic
29
+ roughness: 0.3, // lower = more shiny, higher = more matte
30
+ side: THREE.DoubleSide,
31
+ });
32
+
33
+ group.traverse((obj) => {
34
+ if ((obj as THREE.Mesh).isMesh) {
35
+ const mesh = obj as THREE.Mesh;
36
+ mesh.material = metalMaterial;
37
+ }
38
+ });
39
+
40
+ dm.add(group);
41
+ }
42
+ );
43
+ };
@@ -0,0 +1,66 @@
1
+ import * as THREE from 'three';
2
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from '$renderer/lib/scene/sceneClass';
3
+ import { latexToSVG } from '$renderer/lib/rendering/svg/latexToSVG';
4
+ import { createSVGShape } from '$renderer/lib/rendering/svg/svgRendering';
5
+ import { queryLaTeXClass } from '$renderer/lib/rendering/svg/latexSVGQueries';
6
+ import { createAnim } from '$renderer/lib/animation/protocols';
7
+ import { easeInOutQuad } from '$renderer/lib/animation/interpolations';
8
+
9
+ export const test_latex_query_variables = (): AnimatedScene => {
10
+ return new AnimatedScene(
11
+ 1000,
12
+ 1000,
13
+ SpaceSetting.ThreeDim,
14
+ HotReloadSetting.TraceFromStart,
15
+ async (dm) => {
16
+ // 1) More complicated LaTeX expression with many variables
17
+ // Tag every variable occurrence with \dmClass{variable}{...}
18
+ const latex = String.raw`
19
+ f(\dmClass{variable}{x}, \dmClass{variable}{y})
20
+ = \int_{\dmClass{variable}{x_0}}^{\dmClass{variable}{x_1}}
21
+ \dmClass{variable}{y}(t)\, e^{-\dmClass{variable}{\alpha} t}
22
+ \, dt
23
+ `;
24
+
25
+ // 2) Convert LaTeX → SVG → THREE.Group
26
+ const svg = latexToSVG(latex);
27
+ const equationGroup = createSVGShape(svg, 20); // width ≈ 10 units
28
+ dm.add(equationGroup);
29
+
30
+ // 3) Query all meshes that belong to class "variable"
31
+ const hit = queryLaTeXClass(equationGroup, 'variable');
32
+ if (!hit) {
33
+ console.warn('No meshes found for LaTeX class "variable"');
34
+ return;
35
+ }
36
+
37
+ // Somewhere when you build the meshes
38
+ const targetColor = new THREE.Color(0x00ff88); // the “variable” color
39
+ const white = new THREE.Color(0xffffff);
40
+ const tmpColor = new THREE.Color();
41
+
42
+ // Example: you have an array of meshes you want to tint
43
+ const variableMeshes: THREE.Mesh[] = hit.meshes;
44
+
45
+ // Make sure materials are independent if you plan to animate them
46
+ for (const mesh of variableMeshes) {
47
+ mesh.material = (mesh.material as THREE.Material).clone();
48
+ }
49
+
50
+ const colorAnim = createAnim(easeInOutQuad(0, 1, 300), (t) => {
51
+ tmpColor.lerpColors(white, targetColor, t); // tmp = white * (1-t) + target * t
52
+ for (const mesh of variableMeshes) {
53
+ const mat = mesh.material as THREE.MeshBasicMaterial;
54
+ mat.color.copy(tmpColor);
55
+ }
56
+ });
57
+
58
+
59
+ for (let i = 0; i<20; i++) {
60
+ dm.addAnims(colorAnim.copy())
61
+ dm.addAnims(colorAnim.copy().reverse())
62
+ }
63
+
64
+ }
65
+ );
66
+ };
@@ -0,0 +1,21 @@
1
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
2
+ import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
3
+ import { latexToSVG } from "$renderer/lib/rendering/svg/latexToSVG";
4
+
5
+
6
+ export const test_regular_text_latex = (): AnimatedScene => {
7
+ return new AnimatedScene(
8
+ 1000, 1000,
9
+ SpaceSetting.ThreeDim,
10
+ HotReloadSetting.TraceFromStart,
11
+ async (dm) => {
12
+ const svg = latexToSVG(String.raw`\text{This library is "DefinedMotion"}`);
13
+ const g = createSVGShape(svg, 20);
14
+ g.position.y += 2
15
+ const svg2 = latexToSVG(String.raw`\text{\textsf{This library is "DefinedMotion"}}`);
16
+ const g2 = createSVGShape(svg2, 20);
17
+ g2.position.y -= 2
18
+ dm.add(g, g2);
19
+ }
20
+ );
21
+ };
@@ -0,0 +1,98 @@
1
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
2
+ import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
3
+ import { latexToSVG } from "$renderer/lib/rendering/svg/latexToSVG";
4
+
5
+ export const test_super_complex_latex_to_svg = (): AnimatedScene => {
6
+ return new AnimatedScene(
7
+ 1000, 1000,
8
+ SpaceSetting.ThreeDim,
9
+ HotReloadSetting.TraceFromStart,
10
+ async (dm) => {
11
+
12
+ // 1) Big "everything" block
13
+ const block1 = latexToSVG(String.raw`
14
+ \begin{aligned}
15
+ \textbf{Fourier:}\quad
16
+ \hat{f}(\omega) &= \int_{-\infty}^{\infty} f(t)\,e^{-i\omega t}\,dt,
17
+ & f(t) &= \frac{1}{2\pi}\int_{-\infty}^{\infty} \hat{f}(\omega)\,e^{i\omega t}\,d\omega \\[6pt]
18
+ \textbf{Gamma/Zeta:}\quad
19
+ \Gamma(z) &= \int_{0}^{\infty} t^{z-1} e^{-t}\,dt,
20
+ & \zeta(s) &= \prod_{p\in\mathbb{P}} \frac{1}{1-p^{-s}} \\[6pt]
21
+ \textbf{Cauchy–Schwarz:}\quad
22
+ \big|\langle \mathbf{x},\mathbf{y}\rangle\big| &\le \|\mathbf{x}\|_2\,\|\mathbf{y}\|_2 \\[6pt]
23
+ \textbf{Euler:}\quad
24
+ e^{i\theta} &= \cos\theta + i\sin\theta \\[6pt]
25
+ \textbf{Gradient step:}\quad
26
+ \theta_{t+1} &= \theta_t - \eta\,\nabla_\theta \mathcal{L}(\theta_t) \\[6pt]
27
+ \textbf{KL:}\quad
28
+ \mathrm{KL}\!\left(p\,\|\,q\right) &= \int p(x)\,\log\!\frac{p(x)}{q(x)}\,dx \\[6pt]
29
+ \textbf{Limits:}\quad
30
+ \limsup_{n\to\infty} a_n &\ge \liminf_{n\to\infty} a_n \\[6pt]
31
+ \textbf{Argmin:}\quad
32
+ \hat{\theta} &= \arg\min_{\theta\in\mathbb{R}^d} \; \frac{1}{n}\sum_{i=1}^n \ell\!\big(f_\theta(x_i), y_i\big) \\[6pt]
33
+ \textbf{Binomial:}\quad
34
+ (1+x)^n &= \sum_{k=0}^{n} \binom{n}{k} x^k
35
+ \end{aligned}
36
+ `);
37
+
38
+ const g1 = createSVGShape(block1, 16); // width in your world units
39
+ g1.position.set(0, 6, 0);
40
+ dm.add(g1);
41
+
42
+
43
+ // 2) Matrix / determinant / vector hats & bars / piecewise
44
+ const block2 = latexToSVG(String.raw`
45
+ \begin{aligned}
46
+ \textbf{Matrix:}\quad
47
+ A &= \begin{bmatrix}
48
+ a & b & c\\
49
+ d & e & f\\
50
+ g & h & i
51
+ \end{bmatrix},
52
+ &\quad \det(A) &=
53
+ \left|\begin{matrix}
54
+ a & b & c\\
55
+ d & e & f\\
56
+ g & h & i
57
+ \end{matrix}\right| \\[6pt]
58
+ \textbf{Vectors:}\quad
59
+ \hat{\mathbf{v}} &= \frac{\mathbf{v}}{\|\mathbf{v}\|},\qquad
60
+ \overline{x} = \frac{1}{n}\sum_{k=1}^{n} x_k,\qquad
61
+ \vec{\nabla}\cdot\vec{E} = \frac{\rho}{\varepsilon_0} \\[6pt]
62
+ \textbf{Piecewise:}\quad
63
+ \mathrm{ReLU}(x) &=
64
+ \begin{cases}
65
+ 0, & x<0\\
66
+ x, & x\ge 0
67
+ \end{cases}
68
+ \end{aligned}
69
+ `);
70
+
71
+ const g2 = createSVGShape(block2, 14);
72
+ g2.position.set(0, -2, 0);
73
+ dm.add(g2);
74
+
75
+
76
+ // 3) Probability / expectation / covariance / set notation / sqrt
77
+ const block3 = latexToSVG(String.raw`
78
+ \begin{aligned}
79
+ \textbf{Probability:}\quad
80
+ \mathbb{P}(A\mid B) &= \frac{\mathbb{P}(A\cap B)}{\mathbb{P}(B)},\qquad
81
+ \mathbb{E}[X] = \int_{\mathbb{R}} x\, d\mathbb{P}(x) \\[6pt]
82
+ \textbf{Variance/Covariance:}\quad
83
+ \mathrm{Var}(X) &= \mathbb{E}[X^2] - (\mathbb{E}[X])^2,\qquad
84
+ \mathrm{Cov}(X,Y) = \mathbb{E}[XY]-\mathbb{E}[X]\mathbb{E}[Y] \\[6pt]
85
+ \textbf{Sets/Norms:}\quad
86
+ \mathcal{S} &= \{\,x\in\mathbb{R}^n : \|x\|_2 \le r\,\},\qquad
87
+ \sqrt[n]{1+x} \approx 1 + \frac{x}{n}
88
+ \end{aligned}
89
+ `);
90
+
91
+ const g3 = createSVGShape(block3, 12);
92
+ g3.position.set(0, -8.5, 0);
93
+ dm.add(g3);
94
+
95
+
96
+ }
97
+ );
98
+ };
@@ -0,0 +1,33 @@
1
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
2
+ import gravityTextSVG from '$assets/for_tests/svg/gravity_text.svg?raw'
3
+ import gripSVG from '$assets/for_tests/svg/grip_figure.svg?raw'
4
+ import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
5
+ import { updateSVGShape } from "$renderer/lib/rendering/svg/svgObjectHelpers";
6
+ import { fadeOut, setOpacity, updateSVGAnim } from "$renderer/lib/animation/animations";
7
+ import { latexToSVG } from "$renderer/lib/rendering/svg/latexToSVG";
8
+
9
+
10
+ export const test_transition_svgs = ():AnimatedScene => {
11
+ return new AnimatedScene(1000, 1000, SpaceSetting.ThreeDim, HotReloadSetting.TraceFromStart, async (dm) => {
12
+ const svgObject = createSVGShape(gravityTextSVG, 15)
13
+ dm.add(svgObject)
14
+
15
+ dm.addWait(500)
16
+ const anim = updateSVGAnim(svgObject, gripSVG, 300, 10)
17
+ dm.addAnims(anim)
18
+ dm.addWait(500)
19
+ const raw = latexToSVG(String.raw`
20
+ \begin{aligned}
21
+ \hat{f}(\omega) &= \int_{-\infty}^{\infty} f(t)\,e^{-i\omega t}\,dt,\\
22
+ f(t) &= \frac{1}{2\pi}\int_{-\infty}^{\infty} \hat{f}(\omega)\,e^{i\omega t}\,d\omega,\\[6pt]
23
+ \Gamma(z) &= \int_{0}^{\infty} t^{z-1} e^{-t}\,dt,\qquad
24
+ \zeta(s) = \prod_{p\in\mathbb{P}} \frac{1}{1-p^{-s}}
25
+ \end{aligned}
26
+ `, { display: true });
27
+ const anim2 = updateSVGAnim(svgObject, raw, 300, 20)
28
+ dm.addAnims(anim2)
29
+ dm.addWait(500)
30
+ const anim3 = fadeOut(svgObject, 300)
31
+ dm.addAnims(anim3)
32
+ })
33
+ }
@@ -0,0 +1,19 @@
1
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
2
+ import gravityTextSVG from '$assets/for_tests/svg/gravity_text.svg?raw'
3
+ import gripSVG from '$assets/for_tests/svg/grip_figure.svg?raw'
4
+ import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
5
+ import { updateSVGShape } from "$renderer/lib/rendering/svg/svgObjectHelpers";
6
+
7
+
8
+ export const test_update_svg_object = ():AnimatedScene => {
9
+ return new AnimatedScene(1000, 1000, SpaceSetting.ThreeDim, HotReloadSetting.TraceFromStart, async (dm) => {
10
+ const svgObject = createSVGShape(gravityTextSVG, 10)
11
+ dm.add(svgObject)
12
+
13
+ dm.addWait(500)
14
+ dm.do(() => {
15
+ updateSVGShape(svgObject, gripSVG)
16
+ })
17
+ dm.addWait(500)
18
+ })
19
+ }
@@ -0,0 +1,11 @@
1
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
2
+ import gravityTextSVG from '$assets/for_tests/svg/grip_figure.svg?raw'
3
+ import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
4
+
5
+
6
+ export const test_yellow_grip_symbol_svg = ():AnimatedScene => {
7
+ return new AnimatedScene(1000, 1000, SpaceSetting.ThreeDim, HotReloadSetting.TraceFromStart, async (dm) => {
8
+ const shape = createSVGShape(gravityTextSVG, 10)
9
+ dm.add(shape)
10
+ })
11
+ }
@@ -37,18 +37,18 @@ export function tutorial_easy1(): AnimatedScene {
37
37
  // And give a function that is called for each frame with the current interpolation value
38
38
  const anim = createAnim(easeInOutQuad(-5, 5, 500), (value) => (circle.position.x = value))
39
39
 
40
- // We use "addAnim" to schedule an animation, it will run from the frame (tick) it was added at
40
+ // We use "addAnims" to schedule an animation, it will run from the frame (tick) it was added at
41
41
  // Since this is our first added animation in this scene, we are currently at tick 0, So it will just add to the start.
42
42
  // But say that we are in a complex animation and our previous buildings would mean that we are at frame 49878 for example (we wouldn't know this)
43
43
  // Then it just adds the animation with that offset
44
- scene.addAnim(anim)
44
+ scene.addAnims(anim)
45
45
 
46
46
  // To make the circle also go back, we can reverse the entire animation and add it again
47
47
  // Notice that we are copying it, this is so that the reverse() doesn't affect the original variable "anim"
48
- scene.addAnim(anim.copy().reverse())
48
+ scene.addAnims(anim.copy().reverse())
49
49
 
50
50
  // We now finally add a function that will be called at each frame (tick) in our animation
51
- // This doesn't push the tick forward like the "addAnim" does.
51
+ // This doesn't push the tick forward like the "addAnims" does.
52
52
  // It just declares a function that should be run at each frame
53
53
  // For this animation, we want to set a color to the circle at each frame.
54
54
  scene.onEachTick((tick) => {
@@ -124,7 +124,7 @@ export function tutorial_easy3(): AnimatedScene {
124
124
  })
125
125
 
126
126
  // Start the slide show
127
- scene.addAnim(switcher)
127
+ scene.addAnims(switcher)
128
128
 
129
129
  // Let it run a bit after the last change (nice tail for render/export)
130
130
  scene.addWait(1_000)
@@ -12,12 +12,10 @@ import { AnimatedScene, HotReloadSetting, SpaceSetting } from '$renderer/lib/sce
12
12
  // If your helpers live elsewhere, tweak these paths:
13
13
  import {
14
14
  addBackgroundGradient,
15
- addHDRI,
16
- loadHDRIData,
17
- HDRIs
18
15
  } from '$renderer/lib/rendering/lighting3d'
19
16
  import { setOpacity } from '$renderer/lib/animation/animations'
20
17
  import { createLine } from '$renderer/lib/rendering/objects2d'
18
+ import { addHDRI, HDRIs, loadHDRIData } from '$renderer/lib/rendering/hdri'
21
19
 
22
20
  // ─────────────────────────────────────────────────────────────────────────────
23
21
  // Step 0: Scene constants and materials
@@ -67,8 +65,8 @@ export function tutorial_medium1(): AnimatedScene {
67
65
  // Step 3: Lighting & background
68
66
  // HDRI gives nice reflections/IBL; gradient provides a subtle backdrop.
69
67
  // ───────────────────────────────────────────────────────────────────────
70
- const hdriData = await loadHDRIData(HDRIs.photoStudio1, 2, 0.5) // (lods, intensity normalization)
71
- await addHDRI(scene, hdriData, 0.3) // envMap intensity
68
+ const hdriData = await loadHDRIData(HDRIs.photoStudio1, 2) // (lods, intensity normalization)
69
+ await addHDRI(scene, hdriData, 0.3, 0.5) // envMap intensity
72
70
 
73
71
  addBackgroundGradient({
74
72
  scene,
@@ -1,11 +1,9 @@
1
+ import { addHDRI, HDRIs, loadHDRIData } from '$renderer/lib/rendering/hdri'
1
2
  import { linspace } from '../renderer/src/lib/mathHelpers/vectors'
2
3
  import { COLORS } from '../renderer/src/lib/rendering/helpers'
3
4
  import {
4
5
  addBackgroundGradient,
5
- addHDRI,
6
6
  addSceneLighting,
7
- HDRIs,
8
- loadHDRIData
9
7
  } from '../renderer/src/lib/rendering/lighting3d'
10
8
  import { createFastText } from '../renderer/src/lib/rendering/objects2d'
11
9
  import { AnimatedScene, HotReloadSetting, SpaceSetting } from '../renderer/src/lib/scene/sceneClass'
@@ -41,7 +39,7 @@ export const field: VectorField3D = (x, y, z, time) => {
41
39
  }
42
40
  }
43
41
 
44
- const hdriData = await loadHDRIData(HDRIs.outdoor1, 2, 1)
42
+ const hdriData = await loadHDRIData(HDRIs.outdoor1, 2)
45
43
 
46
44
  export const vectorFieldScene = (): AnimatedScene => {
47
45
  return new AnimatedScene(
@@ -1,10 +1,7 @@
1
1
  import { COLORS } from '../renderer/src/lib/rendering/helpers'
2
2
  import {
3
3
  addBackgroundGradient,
4
- addHDRI,
5
4
  addSceneLighting,
6
- HDRIs,
7
- loadHDRIData
8
5
  } from '../renderer/src/lib/rendering/lighting3d'
9
6
  import { AnimatedScene, HotReloadSetting, SpaceSetting } from '../renderer/src/lib/scene/sceneClass'
10
7
  import * as THREE from 'three'
@@ -19,6 +16,7 @@ import {
19
16
  setOpacity
20
17
  } from '../renderer/src/lib/animation/animations'
21
18
  import { createFastText, updateText } from '../renderer/src/lib/rendering/objects2d'
19
+ import { addHDRI, HDRIs, loadHDRIData } from '$renderer/lib/rendering/hdri'
22
20
 
23
21
  const functions: [string, (x: number) => number][] = [
24
22
  // ──────────── Start Simple & Recognizable ────────────
@@ -95,9 +93,9 @@ const morphAnimation = (
95
93
  line.setPoints(interpolate(vecFunc1, vecFunc2, value))
96
94
  })
97
95
  }
98
- const hdriData = await loadHDRIData(HDRIs.outdoor1, 1, 1)
96
+ const hdriData = await loadHDRIData(HDRIs.outdoor1, 1)
99
97
 
100
- export const functionsAnimation = (): AnimatedScene => {
98
+ export const animatedFunctionsScene = (): AnimatedScene => {
101
99
  return new AnimatedScene(
102
100
  1080,
103
101
  2160,
@@ -157,11 +155,11 @@ export const functionsAnimation = (): AnimatedScene => {
157
155
  scene.addSequentialBackgroundAnims(
158
156
  morphAnimation(plotLine, vecFuncs[i], vecFuncs[i + 1], 300)
159
157
  )
160
- scene.addAnim(fadeOut(textNode, 150))
158
+ scene.addAnims(fadeOut(textNode, 150))
161
159
  scene.do(async () => {
162
160
  await updateText(textNode, functions[i + 1][0])
163
161
  })
164
- scene.addAnim(fadeIn(textNode, 150))
162
+ scene.addAnims(fadeIn(textNode, 150))
165
163
  scene.addWait(800)
166
164
  }
167
165
 
@@ -1,18 +1,41 @@
1
- import { app, shell, BrowserWindow, ipcMain } from 'electron'
1
+ import { app, shell, BrowserWindow, ipcMain, nativeTheme, screen } from 'electron'
2
2
  import { join } from 'path'
3
3
  import { electronApp, optimizer, is } from '@electron-toolkit/utils'
4
4
  import icon from '../../resources/icon.png?asset'
5
5
  import { renderVideo } from './rendering'
6
6
  import { deleteRenderedContent } from './storage'
7
+ import ElectronStore from 'electron-store'
8
+
9
+ const store = new ElectronStore()
10
+
11
+ // Force light mode
12
+ nativeTheme.themeSource = 'light'
7
13
 
8
14
  let mainWindow: BrowserWindow
9
15
 
16
+ function getHzForWebContents(wc: Electron.WebContents): number {
17
+ const win = BrowserWindow.fromWebContents(wc)
18
+ if (win) {
19
+ const b = win.getBounds()
20
+ const nearest = screen.getDisplayNearestPoint({ x: b.x, y: b.y })
21
+ return nearest.displayFrequency || 60
22
+ }
23
+ // Fallback to primary display
24
+ return screen.getPrimaryDisplay().displayFrequency || 60
25
+ }
26
+
10
27
  function createWindow(): void {
11
28
  // Create the browser window.
29
+
30
+ const defaultBounds = { width: 1000, height: 1300 }
31
+ const savedBounds: any = store.get('windowBounds', defaultBounds)
12
32
  mainWindow = new BrowserWindow({
13
- width: 1000,
14
- height: 1300,
33
+ width: savedBounds.width,
34
+ height: savedBounds.height,
35
+ x: savedBounds.x,
36
+ y: savedBounds.y,
15
37
  show: false,
38
+ title: "DefinedMotion",
16
39
  autoHideMenuBar: true,
17
40
  ...(process.platform === 'linux' ? { icon } : {}),
18
41
  webPreferences: {
@@ -26,6 +49,14 @@ function createWindow(): void {
26
49
  }
27
50
  })
28
51
 
52
+ mainWindow.on('resize', () => {
53
+ store.set('windowBounds', mainWindow.getBounds())
54
+ })
55
+
56
+ mainWindow.on('move', () => {
57
+ store.set('windowBounds', mainWindow.getBounds())
58
+ })
59
+
29
60
  mainWindow.on('ready-to-show', () => {
30
61
  mainWindow.show()
31
62
  })
@@ -75,6 +106,31 @@ app.whenReady().then(() => {
75
106
  // dock icon is clicked and there are no other windows open.
76
107
  if (BrowserWindow.getAllWindows().length === 0) createWindow()
77
108
  })
109
+
110
+ // RPC: renderer asks main for the current display refresh rate (Hz)
111
+ ipcMain.handle('get-display-hz', (event) => {
112
+ return getHzForWebContents(event.sender)
113
+ })
114
+
115
+ function broadcastHzToAllWindows() {
116
+ for (const w of BrowserWindow.getAllWindows()) {
117
+ const hz = getHzForWebContents(w.webContents)
118
+ w.webContents.send('display-hz-changed', hz)
119
+ }
120
+ }
121
+
122
+ // Display geometry / metrics changed (resolution/scale/mode changes, some moves)
123
+ screen.on('display-metrics-changed', () => {
124
+ broadcastHzToAllWindows()
125
+ })
126
+
127
+ // Displays added/removed (dock/undock, hot-plug)
128
+ screen.on('display-added', () => {
129
+ broadcastHzToAllWindows()
130
+ })
131
+ screen.on('display-removed', () => {
132
+ broadcastHzToAllWindows()
133
+ })
78
134
  })
79
135
 
80
136
  ipcMain.handle('start-video-render', async (event, options) => {