create-definedmotion 0.1.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 (98) hide show
  1. package/bin/index.js +3 -0
  2. package/package.json +37 -0
  3. package/src/cli.js +100 -0
  4. package/template/.editorconfig +9 -0
  5. package/template/.prettierignore +6 -0
  6. package/template/.prettierrc.yaml +10 -0
  7. package/template/_gitignore +10 -0
  8. package/template/build/entitlements.mac.plist +12 -0
  9. package/template/build/icon.icns +0 -0
  10. package/template/build/icon.ico +0 -0
  11. package/template/build/icon.png +0 -0
  12. package/template/electron-builder.yml +43 -0
  13. package/template/electron.vite.config.ts +50 -0
  14. package/template/eslint.config.mjs +24 -0
  15. package/template/package-lock.json +10299 -0
  16. package/template/package.json +64 -0
  17. package/template/resources/icon.png +0 -0
  18. package/template/src/assets/audio/fadeSound.mp3 +0 -0
  19. package/template/src/assets/audio/fadeSound2.mp3 +0 -0
  20. package/template/src/assets/audio/interstellar.mp3 +0 -0
  21. package/template/src/assets/audio/keyboard1.mp3 +0 -0
  22. package/template/src/assets/audio/keyboard2.mp3 +0 -0
  23. package/template/src/assets/audio/keyboard3.mp3 +0 -0
  24. package/template/src/assets/audio/tick_sound.mp3 +0 -0
  25. package/template/src/assets/base.css +67 -0
  26. package/template/src/assets/electron.svg +10 -0
  27. package/template/src/assets/fonts/Geo-Regular.woff +0 -0
  28. package/template/src/assets/fonts/Montserrat-Italic-VariableFont_wght.woff2 +0 -0
  29. package/template/src/assets/fonts/Montserrat-Medium.ttf +0 -0
  30. package/template/src/assets/fonts/Montserrat-Medium.woff +0 -0
  31. package/template/src/assets/fonts/Montserrat-VariableFont_wght.woff2 +0 -0
  32. package/template/src/assets/fonts/glitch.ttf +0 -0
  33. package/template/src/assets/hdri/indoor1.hdr +0 -0
  34. package/template/src/assets/hdri/metro1.hdr +0 -0
  35. package/template/src/assets/hdri/outdoor1.hdr +0 -0
  36. package/template/src/assets/hdri/photo-studio1.hdr +0 -0
  37. package/template/src/assets/hdri/photo-studio2.hdr +0 -0
  38. package/template/src/assets/hdri/photo-studio3.hdr +0 -0
  39. package/template/src/assets/objects/keyboardScene/ibm-keyboard.glb +0 -0
  40. package/template/src/assets/wavy-lines.svg +25 -0
  41. package/template/src/entry.ts +20 -0
  42. package/template/src/example_scenes/alternativesScene.ts +88 -0
  43. package/template/src/example_scenes/dependencyScene.ts +116 -0
  44. package/template/src/example_scenes/fourierMachineScene.ts +108 -0
  45. package/template/src/example_scenes/fourierSeriesScene.ts +678 -0
  46. package/template/src/example_scenes/keyboardScene.ts +447 -0
  47. package/template/src/example_scenes/surfaceScene.ts +88 -0
  48. package/template/src/example_scenes/tutorials/easy1.ts +59 -0
  49. package/template/src/example_scenes/tutorials/easy2.ts +141 -0
  50. package/template/src/example_scenes/tutorials/easy3.ts +133 -0
  51. package/template/src/example_scenes/tutorials/medium1.ts +154 -0
  52. package/template/src/example_scenes/vectorField.ts +209 -0
  53. package/template/src/example_scenes/visulizingFunctions.ts +246 -0
  54. package/template/src/main/index.ts +101 -0
  55. package/template/src/main/rendering.ts +219 -0
  56. package/template/src/main/storage.ts +35 -0
  57. package/template/src/preload/index.d.ts +8 -0
  58. package/template/src/preload/index.ts +36 -0
  59. package/template/src/renderer/index.html +17 -0
  60. package/template/src/renderer/src/App.svelte +130 -0
  61. package/template/src/renderer/src/app.css +24 -0
  62. package/template/src/renderer/src/env.d.ts +2 -0
  63. package/template/src/renderer/src/lib/animation/animations.ts +214 -0
  64. package/template/src/renderer/src/lib/animation/captureCanvas.ts +85 -0
  65. package/template/src/renderer/src/lib/animation/helpers.ts +7 -0
  66. package/template/src/renderer/src/lib/animation/interpolations.ts +155 -0
  67. package/template/src/renderer/src/lib/animation/protocols.ts +79 -0
  68. package/template/src/renderer/src/lib/audio/loader.ts +104 -0
  69. package/template/src/renderer/src/lib/fonts/Roboto_Regular.json +1 -0
  70. package/template/src/renderer/src/lib/fonts/montserrat-medium.json +1 -0
  71. package/template/src/renderer/src/lib/fonts/montserrat.json +1 -0
  72. package/template/src/renderer/src/lib/general/helpers.ts +77 -0
  73. package/template/src/renderer/src/lib/general/onDestory.ts +10 -0
  74. package/template/src/renderer/src/lib/mathHelpers/vectors.ts +18 -0
  75. package/template/src/renderer/src/lib/rendering/bumpMaps/noise.ts +84 -0
  76. package/template/src/renderer/src/lib/rendering/helpers.ts +35 -0
  77. package/template/src/renderer/src/lib/rendering/lighting3d.ts +387 -0
  78. package/template/src/renderer/src/lib/rendering/materials.ts +6 -0
  79. package/template/src/renderer/src/lib/rendering/objects/import.ts +148 -0
  80. package/template/src/renderer/src/lib/rendering/objects2d.ts +489 -0
  81. package/template/src/renderer/src/lib/rendering/objects3d.ts +89 -0
  82. package/template/src/renderer/src/lib/rendering/protocols.ts +21 -0
  83. package/template/src/renderer/src/lib/rendering/setup.ts +71 -0
  84. package/template/src/renderer/src/lib/rendering/svg/drawing.ts +213 -0
  85. package/template/src/renderer/src/lib/rendering/svg/parsing.ts +717 -0
  86. package/template/src/renderer/src/lib/rendering/svg/rastered.ts +42 -0
  87. package/template/src/renderer/src/lib/rendering/svgObjects.ts +1137 -0
  88. package/template/src/renderer/src/lib/scene/helpers.ts +89 -0
  89. package/template/src/renderer/src/lib/scene/sceneClass.ts +648 -0
  90. package/template/src/renderer/src/lib/shaders/background_gradient/frag.glsl +12 -0
  91. package/template/src/renderer/src/lib/shaders/background_gradient/vert.glsl +6 -0
  92. package/template/src/renderer/src/lib/shaders/hdri_blur/frag.glsl +45 -0
  93. package/template/src/renderer/src/lib/shaders/hdri_blur/vert.glsl +5 -0
  94. package/template/src/renderer/src/main.ts +9 -0
  95. package/template/svelte.config.mjs +7 -0
  96. package/template/tsconfig.json +4 -0
  97. package/template/tsconfig.node.json +10 -0
  98. package/template/tsconfig.web.json +32 -0
@@ -0,0 +1,89 @@
1
+ import * as THREE from 'three'
2
+
3
+ export function createFunctionSurface(
4
+ func: (a: number, b: number) => number,
5
+ xMin: number,
6
+ xMax: number,
7
+ yMin: number,
8
+ yMax: number,
9
+ xSegments: number = 200,
10
+ ySegments: number = 200
11
+ ) {
12
+ // Create a plane geometry
13
+ const width = xMax - xMin
14
+ const height = yMax - yMin
15
+ const geometry = new THREE.PlaneGeometry(width, height, xSegments, ySegments)
16
+
17
+ // Get the vertices and update z values based on the function
18
+ const vertices = geometry.attributes.position
19
+
20
+ for (let i = 0; i <= xSegments; i++) {
21
+ for (let j = 0; j <= ySegments; j++) {
22
+ const index = i * (ySegments + 1) + j
23
+
24
+ // Map indices to actual x,y coordinates in our desired range
25
+ const x = xMin + (i / xSegments) * width
26
+ const z = yMin + (j / ySegments) * height
27
+
28
+ // Set vertex X and Y
29
+ vertices.setX(index, x)
30
+ const y = func(x, z)
31
+ vertices.setY(index, y)
32
+
33
+ // Calculate Z using the provided function
34
+
35
+ vertices.setZ(index, z)
36
+ }
37
+ }
38
+
39
+ // Ensure normals are computed for proper lighting
40
+ geometry.computeVertexNormals()
41
+
42
+ // Create mesh with the geometry
43
+ const material = new THREE.MeshPhongMaterial({
44
+ color: 0x156289,
45
+ emissive: 0x072534,
46
+ side: THREE.DoubleSide,
47
+ flatShading: false,
48
+ wireframe: false
49
+ })
50
+
51
+ const mesh = new THREE.Mesh(geometry, material)
52
+ return mesh
53
+ }
54
+
55
+ // Function to update an existing function surface with a new time value
56
+ export function updateFunctionSurface(
57
+ mesh: THREE.Mesh,
58
+ func: (a: number, b: number) => number,
59
+ xMin: number,
60
+ xMax: number,
61
+ yMin: number,
62
+ yMax: number,
63
+ xSegments: number = 200,
64
+ ySegments: number = 200
65
+ ) {
66
+ const width = xMax - xMin
67
+ const height = yMax - yMin
68
+ const vertices = mesh.geometry.attributes.position
69
+
70
+ for (let i = 0; i <= xSegments; i++) {
71
+ for (let j = 0; j <= ySegments; j++) {
72
+ const index = i * (ySegments + 1) + j
73
+
74
+ // Map indices to actual x,y coordinates
75
+ const x = xMin + (i / xSegments) * width
76
+ const z = yMin + (j / ySegments) * height
77
+
78
+ // Update Y position based on the function with time
79
+ const y = func(x, z)
80
+ vertices.setY(index, y)
81
+ }
82
+ }
83
+
84
+ // Mark vertices for update
85
+ vertices.needsUpdate = true
86
+
87
+ // Recompute normals for proper lighting
88
+ mesh.geometry.computeVertexNormals()
89
+ }
@@ -0,0 +1,21 @@
1
+ import * as THREE from 'three'
2
+ import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
3
+
4
+ export interface SceneComponents {
5
+ camera: THREE.PerspectiveCamera | THREE.OrthographicCamera
6
+ renderer: THREE.WebGLRenderer
7
+ scene: THREE.Scene
8
+ controls: OrbitControls
9
+ }
10
+
11
+ export const RERENDER = (state: SceneComponents) => {
12
+ state.renderer.render(state.scene, state.camera)
13
+ }
14
+
15
+ export const ADD = (state: SceneComponents, element: THREE.Mesh) => {
16
+ state.scene.add(element)
17
+ }
18
+
19
+ export const REMOVE = (state: SceneComponents, element: THREE.Mesh) => {
20
+ state.scene.remove(element)
21
+ }
@@ -0,0 +1,71 @@
1
+ import * as THREE from 'three'
2
+ import type { SceneComponents } from './protocols'
3
+ import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
4
+
5
+ export const createScene = (
6
+ container: HTMLElement,
7
+ pixelsWidth: number,
8
+ pixelsHeight: number,
9
+ threeDim: boolean,
10
+ zoom: number,
11
+ farLimit: number
12
+ ): SceneComponents => {
13
+ // Create the scene
14
+ const scene: THREE.Scene = new THREE.Scene()
15
+
16
+ // Get the container dimensions
17
+ const width: number = container.clientWidth
18
+ const height: number = container.clientHeight
19
+ // Use the provided dimensions for aspect ratio calculation
20
+ const aspect: number = pixelsWidth / pixelsHeight
21
+
22
+ // Camera setup
23
+ let camera: THREE.PerspectiveCamera | THREE.OrthographicCamera
24
+ let controls: OrbitControls | null = null
25
+
26
+ if (threeDim) {
27
+ // 3D configuration
28
+ camera = new THREE.PerspectiveCamera(75, aspect, 0.1, farLimit)
29
+ camera.position.set(0, 0, zoom)
30
+ } else {
31
+ // 2D configuration
32
+ camera = new THREE.OrthographicCamera(-zoom * aspect, zoom * aspect, zoom, -zoom, 1, farLimit)
33
+ camera.position.set(0, 0, zoom)
34
+ }
35
+
36
+ // Add orbit controls
37
+ controls = new OrbitControls(camera, container)
38
+ controls.enableDamping = true
39
+ controls.dampingFactor = 0.3
40
+
41
+ if (!threeDim) {
42
+ // Custom 2D controls behavior
43
+ controls.enableRotate = false // Disable rotation for 2D
44
+ controls.mouseButtons = {
45
+ LEFT: THREE.MOUSE.PAN, // Only allow panning with left mouse
46
+ MIDDLE: THREE.MOUSE.DOLLY,
47
+ RIGHT: THREE.MOUSE.PAN
48
+ }
49
+ controls.touches = {
50
+ ONE: THREE.TOUCH.PAN,
51
+ TWO: THREE.TOUCH.DOLLY_PAN
52
+ }
53
+ controls.maxZoom = 10 // Limit zoom for 2D view
54
+ controls.minZoom = 0.1
55
+ }
56
+
57
+ // Create the renderer with antialiasing enabled and set its internal resolution
58
+ const renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer({ antialias: true })
59
+ renderer.setSize(width, height)
60
+ renderer.setPixelRatio(window.devicePixelRatio)
61
+ renderer.setViewport(0, 0, pixelsWidth, pixelsHeight)
62
+ renderer.setClearColor(0x000000)
63
+
64
+ // Append the renderer's canvas element to the provided container
65
+ container.appendChild(renderer.domElement)
66
+
67
+ renderer.render(scene, camera)
68
+
69
+ // Return the created objects for further manipulation if needed
70
+ return { scene, camera, renderer, controls }
71
+ }
@@ -0,0 +1,213 @@
1
+ import { COLORS } from '../helpers'
2
+ import { isApproximatelyEqual2D, isApproximatelyEqual2d3d, VectorizedElementNode } from './parsing'
3
+ import * as THREE from 'three'
4
+
5
+ export const drawVectorizedNodes = (
6
+ vectorizedNodes: VectorizedElementNode[],
7
+ width: number,
8
+ options?: {
9
+ defaultFillColor?: number
10
+ defaultStrokeColor?: number
11
+ }
12
+ ): THREE.Group => {
13
+ const { defaultFillColor = 0xff9900, defaultStrokeColor = 0x0099ff } = options ?? {}
14
+
15
+ const rootGroup = new THREE.Group()
16
+
17
+ const drawNode = (node: VectorizedElementNode): THREE.Object3D => {
18
+ const nodeGroup = new THREE.Group()
19
+
20
+ const props = node.properties ?? {}
21
+ const hasFill = 'fill' in props && props.fill !== 'none'
22
+ const hasStroke = 'stroke' in props && props.stroke !== 'none'
23
+
24
+ if (node.points.length >= 2 && node.tagName !== 'path' && (hasFill || hasStroke)) {
25
+ // ✅ Fill if applicable
26
+ if (node.isClosed && node.points.length >= 3 && hasFill) {
27
+ const shape = new THREE.Shape(node.points.map(([x, y]) => new THREE.Vector2(x, y)))
28
+ const fillColor = new THREE.Color()
29
+
30
+ const mesh = new THREE.Mesh(
31
+ new THREE.ShapeGeometry(shape),
32
+ new THREE.MeshBasicMaterial({ color: fillColor, side: THREE.DoubleSide })
33
+ )
34
+ nodeGroup.add(mesh)
35
+ }
36
+
37
+ // ✅ Stroke if applicable
38
+ if (hasStroke) {
39
+ const vertices: [number, number, number][] = node.points.map(([x, y]) => [x, y, 0])
40
+ const geometry = pointsToStroke(vertices, props['stroke-width'] || 1)
41
+
42
+ const strokeColor = new THREE.Color(
43
+ typeof props.stroke === 'string' ? props.stroke : defaultStrokeColor
44
+ )
45
+
46
+ const material = new THREE.MeshBasicMaterial({
47
+ color: strokeColor,
48
+ side: THREE.DoubleSide,
49
+ depthWrite: false,
50
+ depthTest: false
51
+ })
52
+ const strokeMesh = new THREE.Mesh(geometry, material)
53
+ nodeGroup.add(strokeMesh)
54
+ }
55
+ }
56
+
57
+ if (node.tagName === 'path') {
58
+ const vertices: [number, number, number][] = node.points.map(([x, y]) => [x, y, 0])
59
+ let previousStart = 0
60
+ node.subpathIndices.forEach((index) => {
61
+ if (previousStart !== index) {
62
+ const subpathIsClosed = isApproximatelyEqual2d3d(
63
+ vertices[previousStart],
64
+ vertices[index - 1]
65
+ )
66
+
67
+ if (subpathIsClosed && hasFill) {
68
+ const shape = new THREE.Shape(
69
+ node.points.slice(previousStart, index).map(([x, y]) => new THREE.Vector2(x, y))
70
+ )
71
+ const fillColor = COLORS.black
72
+
73
+ const mesh = new THREE.Mesh(
74
+ new THREE.ShapeGeometry(shape),
75
+ new THREE.MeshBasicMaterial({ color: fillColor, side: THREE.DoubleSide })
76
+ )
77
+
78
+ nodeGroup.add(mesh)
79
+ } else {
80
+ const geometry = pointsToStroke(
81
+ vertices.slice(previousStart, index),
82
+ (props['stroke-width'] as number) || 1
83
+ )
84
+
85
+ const strokeColor = COLORS.black
86
+
87
+ const material = new THREE.MeshBasicMaterial({
88
+ color: strokeColor,
89
+ side: THREE.DoubleSide,
90
+ depthWrite: false,
91
+ depthTest: false
92
+ })
93
+ const strokeMesh = new THREE.Mesh(geometry, material)
94
+ nodeGroup.add(strokeMesh)
95
+ }
96
+
97
+ previousStart = index
98
+ }
99
+ })
100
+ }
101
+
102
+ for (const child of node.children) {
103
+ if (typeof child === 'string') continue
104
+ const childGroup = drawNode(child)
105
+ nodeGroup.add(childGroup)
106
+ }
107
+
108
+ return nodeGroup
109
+ }
110
+
111
+ for (const node of vectorizedNodes) {
112
+ const group = drawNode(node)
113
+ rootGroup.add(group)
114
+ }
115
+
116
+ const originalBox = new THREE.Box3().setFromObject(rootGroup)
117
+ const originalWidth = originalBox.max.x - originalBox.min.x
118
+ if (originalWidth <= 0) return rootGroup
119
+
120
+ const scaleFactor = width / originalWidth
121
+ rootGroup.scale.set(scaleFactor, -scaleFactor, 1) // Single Y flip here
122
+
123
+ // Center the scaled group
124
+ const scaledBox = new THREE.Box3().setFromObject(rootGroup)
125
+ const center = scaledBox.getCenter(new THREE.Vector3())
126
+ rootGroup.position.sub(center)
127
+
128
+ return rootGroup
129
+ }
130
+
131
+ function pointsToStroke(points: [number, number, number][], width: number): THREE.BufferGeometry {
132
+ const halfWidth = width / 2
133
+ const leftOffsets: [number, number][] = []
134
+ const rightOffsets: [number, number][] = []
135
+
136
+ // Helper: compute a unit normal (perpendicular) from point A to B.
137
+ function computeNormal(
138
+ A: [number, number, number],
139
+ B: [number, number, number]
140
+ ): [number, number, number] {
141
+ const dx = B[0] - A[0]
142
+ const dy = B[1] - A[1]
143
+ const len = Math.sqrt(dx * dx + dy * dy)
144
+ if (len === 0) return [0, 0, 0]
145
+ // Rotate by 90° counterclockwise: (-dy, dx)
146
+ return [-dy / len, dx / len, 0]
147
+ }
148
+
149
+ // Use the normal of the first segment for the first point.
150
+ const nStart = computeNormal(points[0], points[1])
151
+ leftOffsets.push([points[0][0] + nStart[0] * halfWidth, points[0][1] + nStart[1] * halfWidth])
152
+ rightOffsets.push([points[0][0] - nStart[0] * halfWidth, points[0][1] - nStart[1] * halfWidth])
153
+
154
+ // For internal points, average the normals of adjacent segments.
155
+ for (let i = 1; i < points.length - 1; i++) {
156
+ const n1 = computeNormal(points[i - 1], points[i])
157
+ const n2 = computeNormal(points[i], points[i + 1])
158
+ // Average the two normals.
159
+ const avg: [number, number, number] = [n1[0] + n2[0], n1[1] + n2[1], 0]
160
+ const len = Math.sqrt(avg[0] * avg[0] + avg[1] * avg[1])
161
+ const normal: [number, number, number] = len === 0 ? n2 : [avg[0] / len, avg[1] / len, 0]
162
+ leftOffsets.push([points[i][0] + normal[0] * halfWidth, points[i][1] + normal[1] * halfWidth])
163
+ rightOffsets.push([points[i][0] - normal[0] * halfWidth, points[i][1] - normal[1] * halfWidth])
164
+ }
165
+
166
+ // Use the normal of the last segment for the last point.
167
+ const nEnd = computeNormal(points[points.length - 2], points[points.length - 1])
168
+ leftOffsets.push([
169
+ points[points.length - 1][0] + nEnd[0] * halfWidth,
170
+ points[points.length - 1][1] + nEnd[1] * halfWidth
171
+ ])
172
+ rightOffsets.push([
173
+ points[points.length - 1][0] - nEnd[0] * halfWidth,
174
+ points[points.length - 1][1] - nEnd[1] * halfWidth
175
+ ])
176
+
177
+ // Build triangles for each segment between consecutive points.
178
+ const positions: number[] = []
179
+ const normals: number[] = []
180
+ // All normals face +Z for a flat XY-plane.
181
+ const nz = [0, 0, 1]
182
+
183
+ for (let i = 0; i < points.length - 1; i++) {
184
+ // Create vertices for the quad:
185
+ // leftOffsets[i], rightOffsets[i], rightOffsets[i+1], leftOffsets[i+1]
186
+ const v0 = leftOffsets[i]
187
+ const v1 = rightOffsets[i]
188
+ const v2 = rightOffsets[i + 1]
189
+ const v3 = leftOffsets[i + 1]
190
+
191
+ // Triangle 1: v0, v1, v2
192
+ positions.push(v0[0], v0[1], 0)
193
+ positions.push(v1[0], v1[1], 0)
194
+ positions.push(v2[0], v2[1], 0)
195
+
196
+ // Triangle 2: v0, v2, v3
197
+ positions.push(v0[0], v0[1], 0)
198
+ positions.push(v2[0], v2[1], 0)
199
+ positions.push(v3[0], v3[1], 0)
200
+
201
+ // Each triangle has 3 vertices, add normals for each (pointing up)
202
+ for (let j = 0; j < 6; j++) {
203
+ normals.push(...nz)
204
+ }
205
+ }
206
+
207
+ const geometry = new THREE.BufferGeometry()
208
+ geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3))
209
+ geometry.setAttribute('normal', new THREE.Float32BufferAttribute(normals, 3))
210
+ geometry.computeBoundingSphere()
211
+
212
+ return geometry
213
+ }