@skenora/runtime 0.1.2

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 (270) hide show
  1. package/README.md +92 -0
  2. package/dist/core/built-in-runtime-capabilities.d.ts +21 -0
  3. package/dist/core/built-in-runtime-capabilities.d.ts.map +1 -0
  4. package/dist/core/built-in-runtime-capabilities.js +175 -0
  5. package/dist/core/built-in-runtime-capabilities.js.map +1 -0
  6. package/dist/core/runtime-capability-registry.d.ts +90 -0
  7. package/dist/core/runtime-capability-registry.d.ts.map +1 -0
  8. package/dist/core/runtime-capability-registry.js +42 -0
  9. package/dist/core/runtime-capability-registry.js.map +1 -0
  10. package/dist/core/runtime-document-coordinator.d.ts +28 -0
  11. package/dist/core/runtime-document-coordinator.d.ts.map +1 -0
  12. package/dist/core/runtime-document-coordinator.js +124 -0
  13. package/dist/core/runtime-document-coordinator.js.map +1 -0
  14. package/dist/core/runtime-events.d.ts +43 -0
  15. package/dist/core/runtime-events.d.ts.map +1 -0
  16. package/dist/core/runtime-events.js +2 -0
  17. package/dist/core/runtime-events.js.map +1 -0
  18. package/dist/core/runtime-session.d.ts +93 -0
  19. package/dist/core/runtime-session.d.ts.map +1 -0
  20. package/dist/core/runtime-session.js +1344 -0
  21. package/dist/core/runtime-session.js.map +1 -0
  22. package/dist/editor-tools/camera-path-editing-controller.d.ts +36 -0
  23. package/dist/editor-tools/camera-path-editing-controller.d.ts.map +1 -0
  24. package/dist/editor-tools/camera-path-editing-controller.js +212 -0
  25. package/dist/editor-tools/camera-path-editing-controller.js.map +1 -0
  26. package/dist/editor-tools/camera-path-visualizer.d.ts +28 -0
  27. package/dist/editor-tools/camera-path-visualizer.d.ts.map +1 -0
  28. package/dist/editor-tools/camera-path-visualizer.js +151 -0
  29. package/dist/editor-tools/camera-path-visualizer.js.map +1 -0
  30. package/dist/editor-tools/drop-preview-controller.d.ts +34 -0
  31. package/dist/editor-tools/drop-preview-controller.d.ts.map +1 -0
  32. package/dist/editor-tools/drop-preview-controller.js +209 -0
  33. package/dist/editor-tools/drop-preview-controller.js.map +1 -0
  34. package/dist/editor-tools/grid-helper.d.ts +18 -0
  35. package/dist/editor-tools/grid-helper.d.ts.map +1 -0
  36. package/dist/editor-tools/grid-helper.js +27 -0
  37. package/dist/editor-tools/grid-helper.js.map +1 -0
  38. package/dist/editor-tools/light-editing-controller.d.ts +25 -0
  39. package/dist/editor-tools/light-editing-controller.d.ts.map +1 -0
  40. package/dist/editor-tools/light-editing-controller.js +207 -0
  41. package/dist/editor-tools/light-editing-controller.js.map +1 -0
  42. package/dist/editor-tools/node-operations.d.ts +51 -0
  43. package/dist/editor-tools/node-operations.d.ts.map +1 -0
  44. package/dist/editor-tools/node-operations.js +182 -0
  45. package/dist/editor-tools/node-operations.js.map +1 -0
  46. package/dist/editor-tools/selection-controller.d.ts +44 -0
  47. package/dist/editor-tools/selection-controller.d.ts.map +1 -0
  48. package/dist/editor-tools/selection-controller.js +299 -0
  49. package/dist/editor-tools/selection-controller.js.map +1 -0
  50. package/dist/editor-tools/shape-drawing-controller.d.ts +45 -0
  51. package/dist/editor-tools/shape-drawing-controller.d.ts.map +1 -0
  52. package/dist/editor-tools/shape-drawing-controller.js +205 -0
  53. package/dist/editor-tools/shape-drawing-controller.js.map +1 -0
  54. package/dist/editor-tools/shape-editing-controller.d.ts +40 -0
  55. package/dist/editor-tools/shape-editing-controller.d.ts.map +1 -0
  56. package/dist/editor-tools/shape-editing-controller.js +340 -0
  57. package/dist/editor-tools/shape-editing-controller.js.map +1 -0
  58. package/dist/editor.d.ts +12 -0
  59. package/dist/editor.d.ts.map +1 -0
  60. package/dist/editor.js +12 -0
  61. package/dist/editor.js.map +1 -0
  62. package/dist/index.d.ts +2 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +2 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/inspection/node-tools.d.ts +51 -0
  67. package/dist/inspection/node-tools.d.ts.map +1 -0
  68. package/dist/inspection/node-tools.js +282 -0
  69. package/dist/inspection/node-tools.js.map +1 -0
  70. package/dist/interaction/runtime-third-person-controller.d.ts +24 -0
  71. package/dist/interaction/runtime-third-person-controller.d.ts.map +1 -0
  72. package/dist/interaction/runtime-third-person-controller.js +71 -0
  73. package/dist/interaction/runtime-third-person-controller.js.map +1 -0
  74. package/dist/interaction/third-person-controller.d.ts +61 -0
  75. package/dist/interaction/third-person-controller.d.ts.map +1 -0
  76. package/dist/interaction/third-person-controller.js +400 -0
  77. package/dist/interaction/third-person-controller.js.map +1 -0
  78. package/dist/interaction.d.ts +3 -0
  79. package/dist/interaction.d.ts.map +1 -0
  80. package/dist/interaction.js +3 -0
  81. package/dist/interaction.js.map +1 -0
  82. package/dist/presentation/scene-renderer.d.ts +75 -0
  83. package/dist/presentation/scene-renderer.d.ts.map +1 -0
  84. package/dist/presentation/scene-renderer.js +324 -0
  85. package/dist/presentation/scene-renderer.js.map +1 -0
  86. package/dist/presentation/viewport-controller.d.ts +13 -0
  87. package/dist/presentation/viewport-controller.d.ts.map +1 -0
  88. package/dist/presentation/viewport-controller.js +186 -0
  89. package/dist/presentation/viewport-controller.js.map +1 -0
  90. package/dist/projection/annotation-projector.d.ts +28 -0
  91. package/dist/projection/annotation-projector.d.ts.map +1 -0
  92. package/dist/projection/annotation-projector.js +98 -0
  93. package/dist/projection/annotation-projector.js.map +1 -0
  94. package/dist/projection/built-in-entity-projectors.d.ts +7 -0
  95. package/dist/projection/built-in-entity-projectors.d.ts.map +1 -0
  96. package/dist/projection/built-in-entity-projectors.js +75 -0
  97. package/dist/projection/built-in-entity-projectors.js.map +1 -0
  98. package/dist/projection/camera-entity-factory.d.ts +9 -0
  99. package/dist/projection/camera-entity-factory.d.ts.map +1 -0
  100. package/dist/projection/camera-entity-factory.js +93 -0
  101. package/dist/projection/camera-entity-factory.js.map +1 -0
  102. package/dist/projection/document-applier.d.ts +38 -0
  103. package/dist/projection/document-applier.d.ts.map +1 -0
  104. package/dist/projection/document-applier.js +219 -0
  105. package/dist/projection/document-applier.js.map +1 -0
  106. package/dist/projection/entity-projection-registry.d.ts +56 -0
  107. package/dist/projection/entity-projection-registry.d.ts.map +1 -0
  108. package/dist/projection/entity-projection-registry.js +121 -0
  109. package/dist/projection/entity-projection-registry.js.map +1 -0
  110. package/dist/projection/model-importer.d.ts +41 -0
  111. package/dist/projection/model-importer.d.ts.map +1 -0
  112. package/dist/projection/model-importer.js +469 -0
  113. package/dist/projection/model-importer.js.map +1 -0
  114. package/dist/projection/particle-capability.d.ts +5 -0
  115. package/dist/projection/particle-capability.d.ts.map +1 -0
  116. package/dist/projection/particle-capability.js +2 -0
  117. package/dist/projection/particle-capability.js.map +1 -0
  118. package/dist/projection/particle-factory.d.ts +18 -0
  119. package/dist/projection/particle-factory.d.ts.map +1 -0
  120. package/dist/projection/particle-factory.js +313 -0
  121. package/dist/projection/particle-factory.js.map +1 -0
  122. package/dist/projection/primitive-factory.d.ts +5 -0
  123. package/dist/projection/primitive-factory.d.ts.map +1 -0
  124. package/dist/projection/primitive-factory.js +55 -0
  125. package/dist/projection/primitive-factory.js.map +1 -0
  126. package/dist/projection/procedural-factory.d.ts +6 -0
  127. package/dist/projection/procedural-factory.d.ts.map +1 -0
  128. package/dist/projection/procedural-factory.js +34 -0
  129. package/dist/projection/procedural-factory.js.map +1 -0
  130. package/dist/projection/runtime-projection-state.d.ts +19 -0
  131. package/dist/projection/runtime-projection-state.d.ts.map +1 -0
  132. package/dist/projection/runtime-projection-state.js +58 -0
  133. package/dist/projection/runtime-projection-state.js.map +1 -0
  134. package/dist/projection/shape-factory.d.ts +5 -0
  135. package/dist/projection/shape-factory.d.ts.map +1 -0
  136. package/dist/projection/shape-factory.js +101 -0
  137. package/dist/projection/shape-factory.js.map +1 -0
  138. package/dist/projection-entry.d.ts +10 -0
  139. package/dist/projection-entry.d.ts.map +1 -0
  140. package/dist/projection-entry.js +8 -0
  141. package/dist/projection-entry.js.map +1 -0
  142. package/dist/simulation/fixed-step-scheduler.d.ts +13 -0
  143. package/dist/simulation/fixed-step-scheduler.d.ts.map +1 -0
  144. package/dist/simulation/fixed-step-scheduler.js +45 -0
  145. package/dist/simulation/fixed-step-scheduler.js.map +1 -0
  146. package/dist/simulation/simulation-runtime-model.d.ts +24 -0
  147. package/dist/simulation/simulation-runtime-model.d.ts.map +1 -0
  148. package/dist/simulation/simulation-runtime-model.js +63 -0
  149. package/dist/simulation/simulation-runtime-model.js.map +1 -0
  150. package/dist/simulation/simulation-wgsl.d.ts +3 -0
  151. package/dist/simulation/simulation-wgsl.d.ts.map +1 -0
  152. package/dist/simulation/simulation-wgsl.js +294 -0
  153. package/dist/simulation/simulation-wgsl.js.map +1 -0
  154. package/dist/simulation/webgpu-simulation-renderer.d.ts +67 -0
  155. package/dist/simulation/webgpu-simulation-renderer.d.ts.map +1 -0
  156. package/dist/simulation/webgpu-simulation-renderer.js +504 -0
  157. package/dist/simulation/webgpu-simulation-renderer.js.map +1 -0
  158. package/dist/simulation/webgpu-types.d.ts +90 -0
  159. package/dist/simulation/webgpu-types.d.ts.map +1 -0
  160. package/dist/simulation/webgpu-types.js +10 -0
  161. package/dist/simulation/webgpu-types.js.map +1 -0
  162. package/dist/simulation.d.ts +4 -0
  163. package/dist/simulation.d.ts.map +1 -0
  164. package/dist/simulation.js +4 -0
  165. package/dist/simulation.js.map +1 -0
  166. package/dist/systems/animation-controller.d.ts +52 -0
  167. package/dist/systems/animation-controller.d.ts.map +1 -0
  168. package/dist/systems/animation-controller.js +146 -0
  169. package/dist/systems/animation-controller.js.map +1 -0
  170. package/dist/systems/camera-controller.d.ts +41 -0
  171. package/dist/systems/camera-controller.d.ts.map +1 -0
  172. package/dist/systems/camera-controller.js +207 -0
  173. package/dist/systems/camera-controller.js.map +1 -0
  174. package/dist/systems/camera-path-controller.d.ts +39 -0
  175. package/dist/systems/camera-path-controller.d.ts.map +1 -0
  176. package/dist/systems/camera-path-controller.js +287 -0
  177. package/dist/systems/camera-path-controller.js.map +1 -0
  178. package/dist/systems/environment-controller.d.ts +18 -0
  179. package/dist/systems/environment-controller.d.ts.map +1 -0
  180. package/dist/systems/environment-controller.js +251 -0
  181. package/dist/systems/environment-controller.js.map +1 -0
  182. package/dist/systems/environment-texture.d.ts +7 -0
  183. package/dist/systems/environment-texture.d.ts.map +1 -0
  184. package/dist/systems/environment-texture.js +57 -0
  185. package/dist/systems/environment-texture.js.map +1 -0
  186. package/dist/systems/fog-controller.d.ts +12 -0
  187. package/dist/systems/fog-controller.d.ts.map +1 -0
  188. package/dist/systems/fog-controller.js +60 -0
  189. package/dist/systems/fog-controller.js.map +1 -0
  190. package/dist/systems/generated-texture-cache.d.ts +33 -0
  191. package/dist/systems/generated-texture-cache.d.ts.map +1 -0
  192. package/dist/systems/generated-texture-cache.js +101 -0
  193. package/dist/systems/generated-texture-cache.js.map +1 -0
  194. package/dist/systems/glass-transmission-controller.d.ts +21 -0
  195. package/dist/systems/glass-transmission-controller.d.ts.map +1 -0
  196. package/dist/systems/glass-transmission-controller.js +119 -0
  197. package/dist/systems/glass-transmission-controller.js.map +1 -0
  198. package/dist/systems/gpu-program-cache.d.ts +19 -0
  199. package/dist/systems/gpu-program-cache.d.ts.map +1 -0
  200. package/dist/systems/gpu-program-cache.js +95 -0
  201. package/dist/systems/gpu-program-cache.js.map +1 -0
  202. package/dist/systems/ground-controller.d.ts +14 -0
  203. package/dist/systems/ground-controller.d.ts.map +1 -0
  204. package/dist/systems/ground-controller.js +121 -0
  205. package/dist/systems/ground-controller.js.map +1 -0
  206. package/dist/systems/lighting-controller.d.ts +23 -0
  207. package/dist/systems/lighting-controller.d.ts.map +1 -0
  208. package/dist/systems/lighting-controller.js +204 -0
  209. package/dist/systems/lighting-controller.js.map +1 -0
  210. package/dist/systems/material-animation-controller.d.ts +26 -0
  211. package/dist/systems/material-animation-controller.d.ts.map +1 -0
  212. package/dist/systems/material-animation-controller.js +221 -0
  213. package/dist/systems/material-animation-controller.js.map +1 -0
  214. package/dist/systems/material-binding-resolver.d.ts +16 -0
  215. package/dist/systems/material-binding-resolver.d.ts.map +1 -0
  216. package/dist/systems/material-binding-resolver.js +54 -0
  217. package/dist/systems/material-binding-resolver.js.map +1 -0
  218. package/dist/systems/material-controller.d.ts +29 -0
  219. package/dist/systems/material-controller.d.ts.map +1 -0
  220. package/dist/systems/material-controller.js +233 -0
  221. package/dist/systems/material-controller.js.map +1 -0
  222. package/dist/systems/material-preparation.d.ts +9 -0
  223. package/dist/systems/material-preparation.d.ts.map +1 -0
  224. package/dist/systems/material-preparation.js +51 -0
  225. package/dist/systems/material-preparation.js.map +1 -0
  226. package/dist/systems/material-slots.d.ts +18 -0
  227. package/dist/systems/material-slots.d.ts.map +1 -0
  228. package/dist/systems/material-slots.js +78 -0
  229. package/dist/systems/material-slots.js.map +1 -0
  230. package/dist/systems/owned-material-controller.d.ts +20 -0
  231. package/dist/systems/owned-material-controller.d.ts.map +1 -0
  232. package/dist/systems/owned-material-controller.js +611 -0
  233. package/dist/systems/owned-material-controller.js.map +1 -0
  234. package/dist/systems/pbr-material.d.ts +22 -0
  235. package/dist/systems/pbr-material.d.ts.map +1 -0
  236. package/dist/systems/pbr-material.js +358 -0
  237. package/dist/systems/pbr-material.js.map +1 -0
  238. package/dist/systems/post-process-controller.d.ts +17 -0
  239. package/dist/systems/post-process-controller.d.ts.map +1 -0
  240. package/dist/systems/post-process-controller.js +246 -0
  241. package/dist/systems/post-process-controller.js.map +1 -0
  242. package/dist/systems/runtime-clock.d.ts +9 -0
  243. package/dist/systems/runtime-clock.d.ts.map +1 -0
  244. package/dist/systems/runtime-clock.js +25 -0
  245. package/dist/systems/runtime-clock.js.map +1 -0
  246. package/dist/systems/skybox-controller.d.ts +15 -0
  247. package/dist/systems/skybox-controller.d.ts.map +1 -0
  248. package/dist/systems/skybox-controller.js +282 -0
  249. package/dist/systems/skybox-controller.js.map +1 -0
  250. package/dist/systems/sprite-sheet-controller.d.ts +52 -0
  251. package/dist/systems/sprite-sheet-controller.d.ts.map +1 -0
  252. package/dist/systems/sprite-sheet-controller.js +187 -0
  253. package/dist/systems/sprite-sheet-controller.js.map +1 -0
  254. package/dist/systems/surface-effect-plugin.d.ts +26 -0
  255. package/dist/systems/surface-effect-plugin.d.ts.map +1 -0
  256. package/dist/systems/surface-effect-plugin.js +204 -0
  257. package/dist/systems/surface-effect-plugin.js.map +1 -0
  258. package/dist/systems/surface-program-plugin.d.ts +29 -0
  259. package/dist/systems/surface-program-plugin.d.ts.map +1 -0
  260. package/dist/systems/surface-program-plugin.js +139 -0
  261. package/dist/systems/surface-program-plugin.js.map +1 -0
  262. package/dist/systems/texture-animation-controller.d.ts +18 -0
  263. package/dist/systems/texture-animation-controller.d.ts.map +1 -0
  264. package/dist/systems/texture-animation-controller.js +147 -0
  265. package/dist/systems/texture-animation-controller.js.map +1 -0
  266. package/dist/systems/weather-controller.d.ts +16 -0
  267. package/dist/systems/weather-controller.d.ts.map +1 -0
  268. package/dist/systems/weather-controller.js +205 -0
  269. package/dist/systems/weather-controller.js.map +1 -0
  270. package/package.json +63 -0
@@ -0,0 +1,121 @@
1
+ /** Projects document ground and shadow-catcher settings. */
2
+ import { StandardMaterial } from "@babylonjs/core/Materials/standardMaterial";
3
+ import { Color3 } from "@babylonjs/core/Maths/math.color";
4
+ import { MeshBuilder } from "@babylonjs/core/Meshes/meshBuilder";
5
+ import { ShadowOnlyMaterial } from "@babylonjs/materials/shadowOnly";
6
+ import { calculateNodeBounds } from "./camera-controller.js";
7
+ /** Owns the document-created ground mesh and its material. */
8
+ export class GroundController {
9
+ scene;
10
+ #ground = null;
11
+ #config = null;
12
+ #disposed = false;
13
+ constructor(scene) {
14
+ this.scene = scene;
15
+ }
16
+ get ground() {
17
+ return this.#ground;
18
+ }
19
+ apply(config) {
20
+ this.#assertActive();
21
+ this.#release();
22
+ this.#config = structuredClone(config);
23
+ if (!config.enabled)
24
+ return;
25
+ const fitted = config.fitToScene
26
+ ? fitGroundToScene(this.scene, config)
27
+ : null;
28
+ const groundSize = fitted?.size ?? config.size;
29
+ const ground = MeshBuilder.CreateGround("skenora-ground", { width: groundSize, height: groundSize }, this.scene);
30
+ ground.position.set(fitted?.centerX ?? 0, config.height ?? 0, fitted?.centerZ ?? 0);
31
+ const color = parseColor(config.color, Color3.Gray());
32
+ ground.material =
33
+ config.mode === "shadow-catcher"
34
+ ? createShadowCatcher(this.scene, color, config.shadowOpacity)
35
+ : createGroundMaterial(this.scene, color, config.opacity);
36
+ ground.receiveShadows = config.receiveShadows;
37
+ ground.isPickable = false;
38
+ ground.metadata = {
39
+ skenora: { helper: "ground", fittedSize: groundSize },
40
+ };
41
+ this.#ground = ground;
42
+ }
43
+ capture(fallback) {
44
+ const source = this.#config ?? fallback;
45
+ const material = this.#ground?.material;
46
+ const standard = material instanceof StandardMaterial ? material : null;
47
+ const shadow = material instanceof ShadowOnlyMaterial ? material : null;
48
+ return {
49
+ ...structuredClone(source),
50
+ enabled: Boolean(this.#ground?.isEnabled()),
51
+ mode: shadow ? "shadow-catcher" : source.mode,
52
+ size: readGroundSize(this.#ground) ?? source.size,
53
+ height: this.#ground?.position.y ?? source.height ?? 0,
54
+ color: standard?.diffuseColor.toHexString() ?? source.color,
55
+ opacity: standard?.alpha ?? source.opacity,
56
+ shadowOpacity: shadow?.alpha ?? source.shadowOpacity,
57
+ receiveShadows: this.#ground?.receiveShadows ?? source.receiveShadows,
58
+ };
59
+ }
60
+ dispose() {
61
+ if (this.#disposed)
62
+ return;
63
+ this.#disposed = true;
64
+ this.#release();
65
+ this.#config = null;
66
+ }
67
+ #release() {
68
+ this.#ground?.dispose(false, true);
69
+ this.#ground = null;
70
+ }
71
+ #assertActive() {
72
+ if (this.#disposed) {
73
+ throw new Error("GroundController has been disposed");
74
+ }
75
+ }
76
+ }
77
+ function fitGroundToScene(scene, config) {
78
+ const meshes = scene.meshes.filter((mesh) => !hasHelperMetadata(mesh));
79
+ const bounds = calculateNodeBounds(meshes);
80
+ if (!bounds)
81
+ return null;
82
+ const width = bounds.maximum.x - bounds.minimum.x;
83
+ const depth = bounds.maximum.z - bounds.minimum.z;
84
+ return {
85
+ size: Math.max(width, depth, 0.01) * (config.padding ?? 1.5),
86
+ centerX: bounds.center.x,
87
+ centerZ: bounds.center.z,
88
+ };
89
+ }
90
+ function readGroundSize(ground) {
91
+ const metadata = ground?.metadata;
92
+ return typeof metadata?.skenora?.fittedSize === "number"
93
+ ? metadata.skenora.fittedSize
94
+ : null;
95
+ }
96
+ function hasHelperMetadata(mesh) {
97
+ const metadata = mesh.metadata;
98
+ return metadata?.skenora?.helper !== undefined;
99
+ }
100
+ function createGroundMaterial(scene, color, opacity) {
101
+ const material = new StandardMaterial("skenora-ground-material", scene);
102
+ material.diffuseColor = color;
103
+ material.alpha = opacity;
104
+ material.specularColor = Color3.Black();
105
+ return material;
106
+ }
107
+ function createShadowCatcher(scene, color, opacity) {
108
+ const material = new ShadowOnlyMaterial("skenora-shadow-catcher-material", scene);
109
+ material.shadowColor = color;
110
+ material.alpha = opacity;
111
+ return material;
112
+ }
113
+ function parseColor(value, fallback) {
114
+ try {
115
+ return Color3.FromHexString(value);
116
+ }
117
+ catch {
118
+ return fallback;
119
+ }
120
+ }
121
+ //# sourceMappingURL=ground-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ground-controller.js","sourceRoot":"","sources":["../../src/systems/ground-controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { Light } from "@babylonjs/core/Lights/light";
2
+ import { ShadowGenerator } from "@babylonjs/core/Lights/Shadows/shadowGenerator";
3
+ import type { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh";
4
+ import type { Scene } from "@babylonjs/core/scene";
5
+ import type { LightConfig } from "@skenora/contracts";
6
+ export interface LightingControllerOptions {
7
+ isShadowCaster?: (mesh: AbstractMesh) => boolean;
8
+ }
9
+ /** Creates lights and shadow generators from serializable, renderer-neutral data. */
10
+ export declare class LightingController {
11
+ #private;
12
+ readonly scene: Scene;
13
+ constructor(scene: Scene, options?: LightingControllerOptions);
14
+ get lights(): readonly Light[];
15
+ getShadowGenerator(lightId: string): ShadowGenerator | null;
16
+ getLight(lightId: string): Light | null;
17
+ getConfig(lightId: string): LightConfig | null;
18
+ apply(configs: readonly Readonly<LightConfig>[]): void;
19
+ refreshShadowCasters(): void;
20
+ capture(): readonly LightConfig[];
21
+ dispose(): void;
22
+ }
23
+ //# sourceMappingURL=lighting-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lighting-controller.d.ts","sourceRoot":"","sources":["../../src/systems/lighting-controller.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,gDAAgD,CAAC;AAIjF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAQtD,MAAM,WAAW,yBAAyB;IACxC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC;CAClD;AAED,qFAAqF;AACrF,qBAAa,kBAAkB;;IAC7B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;gBAKV,KAAK,EAAE,KAAK,EAAE,OAAO,GAAE,yBAA8B;IAMjE,IAAI,MAAM,IAAI,SAAS,KAAK,EAAE,CAE7B;IAED,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAM3D,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI;IAMvC,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAO9C,KAAK,CAAC,OAAO,EAAE,SAAS,QAAQ,CAAC,WAAW,CAAC,EAAE,GAAG,IAAI;IAUtD,oBAAoB,IAAI,IAAI;IAW5B,OAAO,IAAI,SAAS,WAAW,EAAE;IAqCjC,OAAO,IAAI,IAAI;CA4ChB"}
@@ -0,0 +1,204 @@
1
+ /** Projects document light configuration into Babylon-owned lights. */
2
+ import { DirectionalLight } from "@babylonjs/core/Lights/directionalLight";
3
+ import { HemisphericLight } from "@babylonjs/core/Lights/hemisphericLight";
4
+ import { Light } from "@babylonjs/core/Lights/light";
5
+ import { PointLight } from "@babylonjs/core/Lights/pointLight";
6
+ import { ShadowGenerator } from "@babylonjs/core/Lights/Shadows/shadowGenerator";
7
+ import { SpotLight } from "@babylonjs/core/Lights/spotLight";
8
+ import { Color3 } from "@babylonjs/core/Maths/math.color";
9
+ import { Matrix, Vector3 } from "@babylonjs/core/Maths/math.vector";
10
+ /** Creates lights and shadow generators from serializable, renderer-neutral data. */
11
+ export class LightingController {
12
+ scene;
13
+ #isShadowCaster;
14
+ #managed = [];
15
+ #disposed = false;
16
+ constructor(scene, options = {}) {
17
+ this.scene = scene;
18
+ this.#isShadowCaster =
19
+ options.isShadowCaster ?? ((mesh) => !hasHelperMetadata(mesh));
20
+ }
21
+ get lights() {
22
+ return this.#managed.map((entry) => entry.light);
23
+ }
24
+ getShadowGenerator(lightId) {
25
+ return (this.#managed.find((entry) => entry.config.id === lightId)?.shadow ?? null);
26
+ }
27
+ getLight(lightId) {
28
+ return (this.#managed.find((entry) => entry.config.id === lightId)?.light ?? null);
29
+ }
30
+ getConfig(lightId) {
31
+ const config = this.#managed.find((entry) => entry.config.id === lightId)?.config;
32
+ return config ? cloneLightConfig(config) : null;
33
+ }
34
+ apply(configs) {
35
+ this.#assertActive();
36
+ this.#release();
37
+ for (const config of configs) {
38
+ const light = createLight(this.scene, config);
39
+ const shadow = this.#createShadowGenerator(light, config);
40
+ this.#managed.push({ config: cloneLightConfig(config), light, shadow });
41
+ }
42
+ }
43
+ refreshShadowCasters() {
44
+ this.#assertActive();
45
+ for (const entry of this.#managed) {
46
+ if (!entry.shadow)
47
+ continue;
48
+ for (const mesh of this.scene.meshes) {
49
+ if (!this.#isShadowCaster(mesh))
50
+ continue;
51
+ entry.shadow.addShadowCaster(mesh, true);
52
+ }
53
+ }
54
+ }
55
+ capture() {
56
+ return this.#managed.map((entry) => {
57
+ const { light, shadow, config } = entry;
58
+ const next = {
59
+ ...cloneLightConfig(config),
60
+ enabled: light.isEnabled(),
61
+ intensity: light.intensity,
62
+ color: {
63
+ r: light.diffuse.r,
64
+ g: light.diffuse.g,
65
+ b: light.diffuse.b,
66
+ },
67
+ };
68
+ if (light instanceof PointLight || light instanceof SpotLight) {
69
+ next.position = toVectorValue(light.position);
70
+ next.range = light.range;
71
+ next.radius = light.radius;
72
+ }
73
+ else if (light instanceof DirectionalLight) {
74
+ next.position = toVectorValue(light.position);
75
+ }
76
+ if (light instanceof SpotLight) {
77
+ next.angle = light.angle;
78
+ next.exponent = light.exponent;
79
+ }
80
+ if (shadow && next.shadows) {
81
+ next.shadows = {
82
+ ...next.shadows,
83
+ bias: shadow.bias,
84
+ normalBias: shadow.normalBias,
85
+ darkness: shadow.darkness,
86
+ frustumEdgeFalloff: shadow.frustumEdgeFalloff,
87
+ };
88
+ }
89
+ return next;
90
+ });
91
+ }
92
+ dispose() {
93
+ if (this.#disposed)
94
+ return;
95
+ this.#disposed = true;
96
+ this.#release();
97
+ }
98
+ #createShadowGenerator(light, config) {
99
+ if (!config.shadows?.enabled || light instanceof HemisphericLight) {
100
+ return null;
101
+ }
102
+ const shadow = new ShadowGenerator(config.shadows.mapSize, light, true);
103
+ shadow.bias = config.shadows.bias;
104
+ shadow.normalBias = config.shadows.normalBias ?? 0;
105
+ shadow.darkness = config.shadows.darkness ?? 0;
106
+ shadow.frustumEdgeFalloff = config.shadows.frustumEdgeFalloff ?? 0;
107
+ applyShadowFiltering(shadow, config.shadows.filtering ?? "pcf");
108
+ shadow.enableSoftTransparentShadow = config.shadows.transparent ?? false;
109
+ for (const mesh of this.scene.meshes) {
110
+ if (!this.#isShadowCaster(mesh))
111
+ continue;
112
+ shadow.addShadowCaster(mesh, true);
113
+ }
114
+ return shadow;
115
+ }
116
+ #release() {
117
+ for (const entry of this.#managed) {
118
+ entry.shadow?.dispose();
119
+ entry.light.dispose();
120
+ }
121
+ this.#managed = [];
122
+ }
123
+ #assertActive() {
124
+ if (this.#disposed) {
125
+ throw new Error("LightingController has been disposed");
126
+ }
127
+ }
128
+ }
129
+ function createLight(scene, config) {
130
+ const position = toVector3(config.position ?? { x: 0, y: 3, z: 0 });
131
+ const direction = directionFromRotation(config.rotation);
132
+ let light;
133
+ if (config.type === "directional") {
134
+ const directional = new DirectionalLight(config.id, direction, scene);
135
+ directional.position = position;
136
+ light = directional;
137
+ }
138
+ else if (config.type === "point") {
139
+ const point = new PointLight(config.id, position, scene);
140
+ point.range = config.range ?? Number.MAX_VALUE;
141
+ point.radius = config.radius ?? 0;
142
+ light = point;
143
+ }
144
+ else if (config.type === "spot") {
145
+ const spot = new SpotLight(config.id, position, direction, config.angle ?? Math.PI / 3, config.exponent ?? 1, scene);
146
+ spot.range = config.range ?? Number.MAX_VALUE;
147
+ spot.radius = config.radius ?? 0;
148
+ light = spot;
149
+ }
150
+ else {
151
+ light = new HemisphericLight(config.id, direction, scene);
152
+ }
153
+ light.setEnabled(config.enabled);
154
+ light.intensity = config.intensity;
155
+ light.diffuse = new Color3(config.color.r, config.color.g, config.color.b);
156
+ light.falloffType = toFalloff(config.falloff);
157
+ light.intensityMode = toIntensityMode(config.intensityMode);
158
+ light.metadata = { skenora: { managed: true, lightId: config.id } };
159
+ return light;
160
+ }
161
+ function applyShadowFiltering(shadow, filtering) {
162
+ shadow.usePercentageCloserFiltering = filtering === "pcf";
163
+ shadow.useContactHardeningShadow = filtering === "pcss";
164
+ shadow.useExponentialShadowMap = filtering === "esm";
165
+ shadow.useBlurExponentialShadowMap = filtering === "blurred-esm";
166
+ }
167
+ function toFalloff(value) {
168
+ if (value === "physical")
169
+ return Light.FALLOFF_PHYSICAL;
170
+ if (value === "gltf")
171
+ return Light.FALLOFF_GLTF;
172
+ return Light.FALLOFF_DEFAULT;
173
+ }
174
+ function toIntensityMode(value) {
175
+ if (value === "luminous-power")
176
+ return Light.INTENSITYMODE_LUMINOUSPOWER;
177
+ if (value === "luminous-intensity") {
178
+ return Light.INTENSITYMODE_LUMINOUSINTENSITY;
179
+ }
180
+ if (value === "illuminance")
181
+ return Light.INTENSITYMODE_ILLUMINANCE;
182
+ if (value === "luminance")
183
+ return Light.INTENSITYMODE_LUMINANCE;
184
+ return Light.INTENSITYMODE_AUTOMATIC;
185
+ }
186
+ function directionFromRotation(rotation) {
187
+ if (!rotation)
188
+ return new Vector3(0, -1, 0);
189
+ return Vector3.TransformNormal(new Vector3(0, 0, 1), Matrix.RotationYawPitchRoll(rotation.y, rotation.x, rotation.z)).normalize();
190
+ }
191
+ function hasHelperMetadata(mesh) {
192
+ const metadata = mesh.metadata;
193
+ return metadata?.skenora?.helper !== undefined;
194
+ }
195
+ function cloneLightConfig(config) {
196
+ return structuredClone(config);
197
+ }
198
+ function toVector3(value) {
199
+ return new Vector3(value.x, value.y, value.z);
200
+ }
201
+ function toVectorValue(value) {
202
+ return { x: value.x, y: value.y, z: value.z };
203
+ }
204
+ //# sourceMappingURL=lighting-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lighting-controller.js","sourceRoot":"","sources":["../../src/systems/lighting-controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { type MaterialAnimatedProperty, type MaterialAnimationPlayOptions, type MaterialAnimationResult, type MaterialAnimationState, type MaterialAnimationValue, type MaterialOverride, type MaterialParameterAnimation, type ParameterEasing } from "@skenora/contracts";
2
+ import type { RuntimeClock } from "./runtime-clock.js";
3
+ interface MaterialAnimationTarget {
4
+ /** Preflight both endpoints and every target instance without changing it. */
5
+ validate(materialId: string, animation: Readonly<MaterialParameterAnimation>): void;
6
+ write(materialId: string, property: MaterialAnimatedProperty, value: MaterialAnimationValue): void;
7
+ }
8
+ /** One transient writer per material/property; never mutates document definitions. */
9
+ export declare class MaterialAnimationController {
10
+ #private;
11
+ constructor(clock: RuntimeClock, target: MaterialAnimationTarget, onState?: (state: MaterialAnimationState) => void, maxRunning?: number);
12
+ setMaterials(materials: Readonly<Record<string, MaterialOverride>>): void;
13
+ startAuto(): void;
14
+ play(materialId: string, animationId: string, options?: MaterialAnimationPlayOptions): Promise<MaterialAnimationResult>;
15
+ pause(materialId: string, animationId: string): boolean;
16
+ resume(materialId: string, animationId: string): boolean;
17
+ stop(materialId: string, animationId: string): void;
18
+ reset(materialId: string, animationId: string): void;
19
+ getState(materialId: string, animationId: string): MaterialAnimationState | null;
20
+ cancelTarget(materialId: string, property: string): void;
21
+ stopAll(): void;
22
+ dispose(): void;
23
+ }
24
+ export declare function easeParameter(value: number, easing: ParameterEasing): number;
25
+ export {};
26
+ //# sourceMappingURL=material-animation-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"material-animation-controller.d.ts","sourceRoot":"","sources":["../../src/systems/material-animation-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,wBAAwB,EAC7B,KAAK,4BAA4B,EACjC,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,0BAA0B,EAC/B,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAWpD,UAAU,uBAAuB;IAC/B,8EAA8E;IAC9E,QAAQ,CACN,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,QAAQ,CAAC,0BAA0B,CAAC,GAC9C,IAAI,CAAC;IACR,KAAK,CACH,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,wBAAwB,EAClC,KAAK,EAAE,sBAAsB,GAC5B,IAAI,CAAC;CACT;AAED,sFAAsF;AACtF,qBAAa,2BAA2B;;gBAWpC,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,uBAAuB,EAC/B,OAAO,GAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAe,EAC3D,UAAU,SAAM;IAQlB,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,GAAG,IAAI;IAMzE,SAAS,IAAI,IAAI;IAYjB,IAAI,CACF,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,4BAAiC,GACzC,OAAO,CAAC,uBAAuB,CAAC;IAiDnC,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO;IAQvD,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO;IAQxD,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAMnD,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAoBpD,QAAQ,CACN,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,sBAAsB,GAAG,IAAI;IAMhC,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAUxD,OAAO,IAAI,IAAI;IAKf,OAAO,IAAI,IAAI;CA8GhB;AAID,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,MAAM,CAM5E"}
@@ -0,0 +1,221 @@
1
+ import { MATERIAL_ANIMATION_RULE, MaterialAnimationError, normalizeMaterialAnimation, validateFieldRule, } from "@skenora/contracts";
2
+ /** One transient writer per material/property; never mutates document definitions. */
3
+ export class MaterialAnimationController {
4
+ #target;
5
+ #onState;
6
+ #unsubscribe;
7
+ #maxRunning;
8
+ #running = new Map();
9
+ #states = new Map();
10
+ #materials = {};
11
+ #disposed = false;
12
+ constructor(clock, target, onState = () => { }, maxRunning = 256) {
13
+ this.#target = target;
14
+ this.#onState = onState;
15
+ this.#maxRunning = maxRunning;
16
+ this.#unsubscribe = clock.subscribe((delta) => this.#tick(delta));
17
+ }
18
+ setMaterials(materials) {
19
+ this.stopAll();
20
+ this.#materials = structuredClone(materials);
21
+ this.#states.clear();
22
+ }
23
+ startAuto() {
24
+ for (const material of Object.values(this.#materials)) {
25
+ if (!material.creation)
26
+ continue;
27
+ for (const animation of material.animations ?? []) {
28
+ if (animation.autoStart) {
29
+ // Async frame failures already emit a sanitized failed state.
30
+ void this.play(material.id, animation.id).catch(() => { });
31
+ }
32
+ }
33
+ }
34
+ }
35
+ play(materialId, animationId, options = {}) {
36
+ const animation = this.#require(materialId, animationId);
37
+ if (options.signal?.aborted)
38
+ return Promise.resolve({ status: "cancelled" });
39
+ this.#target.validate(materialId, animation);
40
+ if (this.#running.size >= this.#maxRunning &&
41
+ ![...this.#running.values()].some((running) => running.materialId === materialId &&
42
+ running.animation.property === animation.property))
43
+ throw new MaterialAnimationError("material-animation-budget-exceeded", materialId, animationId);
44
+ // Validate before cancelling the previous writer, including for replay.
45
+ this.#target.write(materialId, animation.property, structuredClone(animation.from));
46
+ this.cancelTarget(materialId, animation.property);
47
+ return new Promise((resolve, reject) => {
48
+ const key = trackKey(materialId, animationId);
49
+ const running = {
50
+ materialId,
51
+ animation,
52
+ elapsedMs: 0,
53
+ paused: false,
54
+ resolve,
55
+ reject,
56
+ removeAbort: () => { },
57
+ };
58
+ const abort = () => {
59
+ if (this.#running.get(key) === running)
60
+ this.#finish(key, running, "cancelled");
61
+ };
62
+ options.signal?.addEventListener("abort", abort, { once: true });
63
+ running.removeAbort = () => options.signal?.removeEventListener("abort", abort);
64
+ this.#running.set(key, running);
65
+ this.#publish(running, "running");
66
+ if (options.signal?.aborted)
67
+ abort();
68
+ });
69
+ }
70
+ pause(materialId, animationId) {
71
+ const running = this.#running.get(trackKey(materialId, animationId));
72
+ if (!running || running.paused)
73
+ return false;
74
+ running.paused = true;
75
+ this.#publish(running, "paused");
76
+ return true;
77
+ }
78
+ resume(materialId, animationId) {
79
+ const running = this.#running.get(trackKey(materialId, animationId));
80
+ if (!running?.paused)
81
+ return false;
82
+ running.paused = false;
83
+ this.#publish(running, "running");
84
+ return true;
85
+ }
86
+ stop(materialId, animationId) {
87
+ const key = trackKey(materialId, animationId);
88
+ const running = this.#running.get(key);
89
+ if (running)
90
+ this.#finish(key, running, "cancelled");
91
+ }
92
+ reset(materialId, animationId) {
93
+ const animation = this.#require(materialId, animationId);
94
+ this.#target.validate(materialId, animation);
95
+ this.#target.write(materialId, animation.property, structuredClone(animation.from));
96
+ this.cancelTarget(materialId, animation.property);
97
+ const state = {
98
+ materialId,
99
+ animationId,
100
+ property: animation.property,
101
+ status: "reset",
102
+ elapsedMs: 0,
103
+ };
104
+ this.#states.set(trackKey(materialId, animationId), state);
105
+ this.#emit(state);
106
+ }
107
+ getState(materialId, animationId) {
108
+ return structuredClone(this.#states.get(trackKey(materialId, animationId)) ?? null);
109
+ }
110
+ cancelTarget(materialId, property) {
111
+ for (const [key, running] of this.#running) {
112
+ if (running.materialId === materialId &&
113
+ running.animation.property === property)
114
+ this.#finish(key, running, "cancelled");
115
+ }
116
+ }
117
+ stopAll() {
118
+ for (const [key, running] of this.#running)
119
+ this.#finish(key, running, "cancelled");
120
+ }
121
+ dispose() {
122
+ if (this.#disposed)
123
+ return;
124
+ this.#disposed = true;
125
+ this.stopAll();
126
+ this.#unsubscribe();
127
+ this.#materials = {};
128
+ this.#states.clear();
129
+ }
130
+ #require(materialId, animationId) {
131
+ const material = this.#materials[materialId];
132
+ const animation = material?.creation
133
+ ? material.animations?.find((item) => item.id === animationId)
134
+ : undefined;
135
+ if (this.#disposed || !animation)
136
+ throw new MaterialAnimationError("material-animation-missing", materialId, animationId);
137
+ if (validateFieldRule(animation, MATERIAL_ANIMATION_RULE).length)
138
+ throw new MaterialAnimationError("material-animation-invalid", materialId, animationId);
139
+ return normalizeMaterialAnimation(animation);
140
+ }
141
+ #tick(deltaMs) {
142
+ for (const [key, running] of [...this.#running]) {
143
+ if (running.paused || this.#running.get(key) !== running)
144
+ continue;
145
+ const { animation } = running;
146
+ running.elapsedMs += deltaMs;
147
+ const raw = running.elapsedMs / animation.durationMs;
148
+ const leg = Math.floor(raw);
149
+ const fraction = animation.loop === "none" ? Math.min(raw, 1) : raw % 1;
150
+ const progress = animation.loop === "ping-pong" && leg % 2 === 1
151
+ ? 1 - fraction
152
+ : fraction;
153
+ const value = interpolate(animation.from, animation.to, easeParameter(progress, animation.easing));
154
+ try {
155
+ this.#target.write(running.materialId, animation.property, value);
156
+ this.#states.set(key, this.#state(running, "running"));
157
+ if (animation.loop === "none" && raw >= 1)
158
+ this.#finish(key, running, "completed");
159
+ }
160
+ catch {
161
+ this.#running.delete(key);
162
+ running.removeAbort();
163
+ this.#publish(running, "failed", "material-animation-failed");
164
+ running.reject(new MaterialAnimationError("material-animation-failed", running.materialId, animation.id));
165
+ }
166
+ }
167
+ }
168
+ #finish(key, running, status) {
169
+ this.#running.delete(key);
170
+ running.removeAbort();
171
+ this.#publish(running, status);
172
+ running.resolve({ status });
173
+ }
174
+ #state(running, status) {
175
+ return {
176
+ materialId: running.materialId,
177
+ animationId: running.animation.id,
178
+ property: running.animation.property,
179
+ status,
180
+ elapsedMs: running.elapsedMs,
181
+ };
182
+ }
183
+ #publish(running, status, code) {
184
+ const state = {
185
+ ...this.#state(running, status),
186
+ ...(code ? { code } : {}),
187
+ };
188
+ this.#states.set(trackKey(running.materialId, running.animation.id), state);
189
+ this.#emit(state);
190
+ }
191
+ #emit(state) {
192
+ try {
193
+ this.#onState(structuredClone(state));
194
+ }
195
+ catch {
196
+ /* Host observers cannot retain a completed writer or its abort listener. */
197
+ }
198
+ }
199
+ }
200
+ const trackKey = (materialId, animationId) => JSON.stringify([materialId, animationId]);
201
+ export function easeParameter(value, easing) {
202
+ if (easing === "easeIn")
203
+ return value ** 3;
204
+ if (easing === "easeOut")
205
+ return 1 - (1 - value) ** 3;
206
+ if (easing === "easeInOut")
207
+ return value < 0.5 ? 4 * value ** 3 : 1 - (-2 * value + 2) ** 3 / 2;
208
+ return value;
209
+ }
210
+ function interpolate(from, to, progress) {
211
+ if (typeof from === "number" && typeof to === "number")
212
+ return from * (1 - progress) + to * progress;
213
+ if (typeof from !== "number" && typeof to !== "number")
214
+ return {
215
+ r: from.r * (1 - progress) + to.r * progress,
216
+ g: from.g * (1 - progress) + to.g * progress,
217
+ b: from.b * (1 - progress) + to.b * progress,
218
+ };
219
+ throw new Error("Animation endpoints must have matching types");
220
+ }
221
+ //# sourceMappingURL=material-animation-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"material-animation-controller.js","sourceRoot":"","sources":["../../src/systems/material-animation-controller.ts"],"names":[],"mappings":"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"}