@woosh/meep-engine 3.16.0 → 3.17.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 (410) hide show
  1. package/editor/particles/effect/ParticleEffectDocument.d.ts +21 -6
  2. package/editor/particles/effect/ParticleEffectDocument.d.ts.map +1 -1
  3. package/editor/particles/effect/ParticleEffectDocument.js +38 -17
  4. package/editor/view/node-graph/NodeGraphClipboard.d.ts +186 -0
  5. package/editor/view/node-graph/NodeGraphClipboard.d.ts.map +1 -0
  6. package/editor/view/node-graph/NodeGraphClipboard.js +231 -0
  7. package/editor/view/node-graph/NodeGraphEditorView.d.ts +59 -1
  8. package/editor/view/node-graph/NodeGraphEditorView.d.ts.map +1 -1
  9. package/editor/view/node-graph/NodeGraphEditorView.js +248 -5
  10. package/editor/view/node-graph/NodeGraphView.d.ts.map +1 -1
  11. package/editor/view/node-graph/NodeGraphView.js +84 -8
  12. package/editor/view/node-graph/actions/connection_bind_actions.d.ts +23 -0
  13. package/editor/view/node-graph/actions/connection_bind_actions.d.ts.map +1 -0
  14. package/editor/view/node-graph/actions/connection_bind_actions.js +39 -0
  15. package/editor/view/particles/effect/ParticleCodeEditorView.d.ts.map +1 -1
  16. package/editor/view/particles/effect/ParticleCodeEditorView.js +4 -3
  17. package/editor/view/particles/effect/ParticleCurveEditorView.d.ts +20 -0
  18. package/editor/view/particles/effect/ParticleCurveEditorView.d.ts.map +1 -0
  19. package/editor/view/particles/effect/ParticleCurveEditorView.js +574 -0
  20. package/editor/view/particles/effect/ParticleEmitterInspectorView.d.ts.map +1 -1
  21. package/editor/view/particles/effect/ParticleEmitterInspectorView.js +27 -1
  22. package/editor/view/particles/effect/ParticleGradientEditorView.d.ts +24 -0
  23. package/editor/view/particles/effect/ParticleGradientEditorView.d.ts.map +1 -0
  24. package/editor/view/particles/effect/ParticleGradientEditorView.js +472 -0
  25. package/editor/view/particles/effect/ParticleGraphEditorView.d.ts +5 -0
  26. package/editor/view/particles/effect/ParticleGraphEditorView.d.ts.map +1 -1
  27. package/editor/view/particles/effect/ParticleGraphEditorView.js +61 -31
  28. package/editor/view/particles/effect/ParticleNodeParametersView.d.ts.map +1 -1
  29. package/editor/view/particles/effect/ParticleNodeParametersView.js +33 -0
  30. package/editor/view/particles/effect/particle-editor.css +123 -35
  31. package/package.json +1 -1
  32. package/src/core/binary/allocator/OffsetAllocator.d.ts +25 -16
  33. package/src/core/binary/allocator/OffsetAllocator.d.ts.map +1 -1
  34. package/src/core/binary/allocator/OffsetAllocator.js +10 -1
  35. package/src/core/collection/array/typed/float32_array_hash.d.ts +21 -0
  36. package/src/core/collection/array/typed/float32_array_hash.d.ts.map +1 -0
  37. package/src/core/collection/array/typed/float32_array_hash.js +38 -0
  38. package/src/core/graph/csr/CSRGraph.d.ts +8 -1
  39. package/src/core/graph/csr/CSRGraph.d.ts.map +1 -1
  40. package/src/core/graph/csr/CSRGraph.js +14 -6
  41. package/src/core/model/node-graph/visual/layout/LayoutProblem.d.ts +24 -0
  42. package/src/core/model/node-graph/visual/layout/LayoutProblem.d.ts.map +1 -1
  43. package/src/core/model/node-graph/visual/layout/LayoutProblem.js +27 -0
  44. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts +26 -0
  45. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.d.ts.map +1 -1
  46. package/src/core/model/node-graph/visual/layout/NodeGraphLayoutOptions.js +28 -0
  47. package/src/core/model/node-graph/visual/layout/RouteGrid.d.ts +92 -3
  48. package/src/core/model/node-graph/visual/layout/RouteGrid.d.ts.map +1 -1
  49. package/src/core/model/node-graph/visual/layout/RouteGrid.js +405 -242
  50. package/src/core/model/node-graph/visual/layout/RouteSearch.d.ts +50 -5
  51. package/src/core/model/node-graph/visual/layout/RouteSearch.d.ts.map +1 -1
  52. package/src/core/model/node-graph/visual/layout/RouteSearch.js +160 -24
  53. package/src/core/model/node-graph/visual/layout/RouteSet.d.ts +7 -0
  54. package/src/core/model/node-graph/visual/layout/RouteSet.d.ts.map +1 -1
  55. package/src/core/model/node-graph/visual/layout/RouteSet.js +8 -0
  56. package/src/core/model/node-graph/visual/layout/layout_assign_coordinates.js +9 -3
  57. package/src/core/model/node-graph/visual/layout/layout_build_problem.d.ts.map +1 -1
  58. package/src/core/model/node-graph/visual/layout/layout_build_problem.js +7 -0
  59. package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts +9 -3
  60. package/src/core/model/node-graph/visual/layout/layout_insert_lanes.d.ts.map +1 -1
  61. package/src/core/model/node-graph/visual/layout/layout_insert_lanes.js +17 -3
  62. package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts +9 -6
  63. package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts.map +1 -1
  64. package/src/core/model/node-graph/visual/layout/layout_node_graph.js +49 -7
  65. package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts +11 -1
  66. package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts.map +1 -1
  67. package/src/core/model/node-graph/visual/layout/layout_order_layers.js +135 -16
  68. package/src/core/model/node-graph/visual/layout/route_connections.d.ts +29 -0
  69. package/src/core/model/node-graph/visual/layout/route_connections.d.ts.map +1 -1
  70. package/src/core/model/node-graph/visual/layout/route_connections.js +716 -309
  71. package/src/core/model/node-graph/visual/layout/route_grid_build.d.ts +3 -2
  72. package/src/core/model/node-graph/visual/layout/route_grid_build.d.ts.map +1 -1
  73. package/src/core/model/node-graph/visual/layout/route_grid_build.js +7 -15
  74. package/src/core/model/node-graph/visual/layout/route_nudge.d.ts +6 -0
  75. package/src/core/model/node-graph/visual/layout/route_nudge.d.ts.map +1 -1
  76. package/src/core/model/node-graph/visual/layout/route_nudge.js +42 -13
  77. package/src/engine/animation/AnimationUtils.js +246 -246
  78. package/src/engine/animation/Animations.js +74 -74
  79. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +2078 -2078
  80. package/src/engine/ecs/EventType.d.ts +0 -1
  81. package/src/engine/ecs/EventType.js +1 -26
  82. package/src/engine/ecs/ik/ik_write_local_rotation.d.ts +1 -1
  83. package/src/engine/ecs/ik/ik_write_local_rotation.d.ts.map +1 -1
  84. package/src/engine/ecs/ik/ik_write_local_rotation.js +3 -7
  85. package/src/engine/ecs/parent/EntityNode.d.ts.map +1 -1
  86. package/src/engine/ecs/parent/EntityNode.js +4 -9
  87. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.d.ts.map +1 -1
  88. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +360 -364
  89. package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.d.ts +41 -0
  90. package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.d.ts.map +1 -0
  91. package/src/engine/ecs/transform/TRANSFORM64_EVENT_CHANGE.js +40 -0
  92. package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +8 -0
  93. package/src/engine/ecs/transform/t64_announce_change.d.ts +10 -7
  94. package/src/engine/ecs/transform/t64_announce_change.d.ts.map +1 -1
  95. package/src/engine/ecs/transform/t64_announce_change.js +12 -12
  96. package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.d.ts +30 -0
  97. package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.d.ts.map +1 -0
  98. package/src/engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.js +29 -0
  99. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.d.ts.map +1 -1
  100. package/src/engine/ecs/transform-attachment/TransformAttachmentSystem.js +13 -21
  101. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.d.ts.map +1 -1
  102. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.js +4 -8
  103. package/src/engine/graphics3/LightSystem.d.ts.map +1 -1
  104. package/src/engine/graphics3/LightSystem.js +4 -8
  105. package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
  106. package/src/engine/graphics3/MeshSystem.js +9 -19
  107. package/src/engine/graphics3/ParticleEmitterSystem.d.ts.map +1 -1
  108. package/src/engine/graphics3/ParticleEmitterSystem.js +4 -8
  109. package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
  110. package/src/engine/graphics3/ShadedGeometrySystem.js +4 -10
  111. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.d.ts +1 -1
  112. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.d.ts.map +1 -1
  113. package/src/engine/grid/transform2grid/Transform2GridPositionSystem.js +4 -8
  114. package/src/engine/intelligence/behavior/ecs/OrbitingBehavior.js +218 -218
  115. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  116. package/src/engine/physics/ecs/PhysicsSystem.js +2 -5
  117. package/src/engine/sound/ecs/SoundListenerSystem.d.ts.map +1 -1
  118. package/src/engine/sound/ecs/SoundListenerSystem.js +6 -8
  119. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts +0 -4
  120. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts.map +1 -1
  121. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.js +5 -11
  122. package/src/shade/playground/particle_editor/README.md +43 -2
  123. package/src/shade/playground/particle_system/particle_prototype.d.ts.map +1 -1
  124. package/src/shade/playground/particle_system/particle_prototype.js +4 -5
  125. package/src/shade/playground/particle_system/particle_scene.js +4 -4
  126. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  127. package/src/shade/renderer/Renderer.js +13 -1
  128. package/src/shade/renderer/particles/DESIGN.md +104 -19
  129. package/src/shade/renderer/particles/GPUParticleSystem.d.ts +64 -50
  130. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  131. package/src/shade/renderer/particles/GPUParticleSystem.js +176 -78
  132. package/src/shade/renderer/particles/ParticleConstants.d.ts +59 -23
  133. package/src/shade/renderer/particles/ParticleConstants.d.ts.map +1 -1
  134. package/src/shade/renderer/particles/ParticleConstants.js +66 -23
  135. package/src/shade/renderer/particles/ParticleRenderMode.d.ts +19 -0
  136. package/src/shade/renderer/particles/ParticleRenderMode.d.ts.map +1 -0
  137. package/src/shade/renderer/particles/ParticleRenderMode.js +33 -0
  138. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts.map +1 -1
  139. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.js +167 -166
  140. package/src/shade/renderer/particles/data/particle_emitter_record.d.ts +37 -0
  141. package/src/shade/renderer/particles/data/particle_emitter_record.d.ts.map +1 -0
  142. package/src/shade/renderer/particles/data/particle_emitter_record.js +109 -0
  143. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.d.ts +3 -3
  144. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.js +303 -303
  145. package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts +18 -0
  146. package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts.map +1 -1
  147. package/src/shade/renderer/particles/graph/ParticleNodeDescription.js +152 -133
  148. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts +0 -11
  149. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts.map +1 -1
  150. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.js +720 -621
  151. package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts.map +1 -1
  152. package/src/shade/renderer/particles/graph/compile_particle_graph.js +8 -3
  153. package/src/shade/renderer/particles/graph/flatten_particle_graph.d.ts.map +1 -1
  154. package/src/shade/renderer/particles/graph/flatten_particle_graph.js +244 -213
  155. package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.d.ts.map +1 -1
  156. package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.js +6 -0
  157. package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.d.ts.map +1 -1
  158. package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.js +294 -319
  159. package/src/shade/renderer/particles/graph/groups/particle_groups_noise.d.ts.map +1 -1
  160. package/src/shade/renderer/particles/graph/groups/particle_groups_noise.js +524 -517
  161. package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.d.ts +22 -0
  162. package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.d.ts.map +1 -0
  163. package/src/shade/renderer/particles/graph/groups/particle_groups_psrdnoise.js +517 -0
  164. package/src/shade/renderer/particles/graph/groups/simplex_reference.d.ts.map +1 -1
  165. package/src/shade/renderer/particles/graph/groups/simplex_reference.js +185 -159
  166. package/src/shade/renderer/particles/graph/make_particle_group.d.ts.map +1 -1
  167. package/src/shade/renderer/particles/graph/make_particle_group.js +2 -20
  168. package/src/shade/renderer/particles/graph/particle_compare_ops.d.ts +17 -0
  169. package/src/shade/renderer/particles/graph/particle_compare_ops.d.ts.map +1 -0
  170. package/src/shade/renderer/particles/graph/particle_compare_ops.js +22 -0
  171. package/src/shade/renderer/particles/graph/particle_graph_diagnostic.d.ts +28 -8
  172. package/src/shade/renderer/particles/graph/particle_graph_diagnostic.d.ts.map +1 -1
  173. package/src/shade/renderer/particles/graph/particle_graph_diagnostic.js +49 -25
  174. package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts +40 -0
  175. package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts.map +1 -1
  176. package/src/shade/renderer/particles/graph/particle_node_parameters.js +312 -234
  177. package/src/shade/renderer/particles/graph/particle_node_presentation.d.ts.map +1 -1
  178. package/src/shade/renderer/particles/graph/particle_node_presentation.js +59 -3
  179. package/src/shade/renderer/particles/graph/particle_ramp.d.ts +230 -0
  180. package/src/shade/renderer/particles/graph/particle_ramp.d.ts.map +1 -0
  181. package/src/shade/renderer/particles/graph/particle_ramp.js +403 -0
  182. package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts +7 -1
  183. package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts.map +1 -1
  184. package/src/shade/renderer/particles/graph/validate_particle_graph.js +66 -10
  185. package/src/shade/renderer/particles/graph_particles.d.ts +23 -69
  186. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  187. package/src/shade/renderer/particles/graph_particles.js +105 -262
  188. package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
  189. package/src/shade/renderer/particles/graph_particles_avboit.js +3 -2
  190. package/src/shade/renderer/particles/graph_particles_billboard.d.ts +37 -0
  191. package/src/shade/renderer/particles/graph_particles_billboard.d.ts.map +1 -0
  192. package/src/shade/renderer/particles/graph_particles_billboard.js +93 -0
  193. package/src/shade/renderer/particles/isa/InstructionStream.d.ts +51 -22
  194. package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -1
  195. package/src/shade/renderer/particles/isa/InstructionStream.js +98 -38
  196. package/src/shade/renderer/particles/isa/ParticleProgram.d.ts +49 -8
  197. package/src/shade/renderer/particles/isa/ParticleProgram.d.ts.map +1 -1
  198. package/src/shade/renderer/particles/isa/ParticleProgram.js +95 -150
  199. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts +306 -64
  200. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts.map +1 -1
  201. package/src/shade/renderer/particles/isa/ParticleVMISA.js +505 -136
  202. package/src/shade/renderer/particles/isa/particle_assembly.d.ts +36 -12
  203. package/src/shade/renderer/particles/isa/particle_assembly.d.ts.map +1 -1
  204. package/src/shade/renderer/particles/isa/particle_assembly.js +354 -139
  205. package/src/shade/renderer/particles/isa/validate_particle_program.d.ts +9 -0
  206. package/src/shade/renderer/particles/isa/validate_particle_program.d.ts.map +1 -0
  207. package/src/shade/renderer/particles/isa/validate_particle_program.js +128 -0
  208. package/src/shade/renderer/particles/layout/ParticleLayout.d.ts +23 -0
  209. package/src/shade/renderer/particles/layout/ParticleLayout.d.ts.map +1 -1
  210. package/src/shade/renderer/particles/layout/ParticleLayout.js +68 -0
  211. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts +77 -0
  212. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts.map +1 -0
  213. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.js +219 -0
  214. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts +83 -0
  215. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts.map +1 -0
  216. package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.js +283 -0
  217. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts +133 -0
  218. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts.map +1 -0
  219. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.js +334 -0
  220. package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.d.ts +117 -0
  221. package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.d.ts.map +1 -0
  222. package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.js +70 -0
  223. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts +97 -0
  224. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts.map +1 -0
  225. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.js +462 -0
  226. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.d.ts +116 -0
  227. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.d.ts.map +1 -0
  228. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.js +687 -0
  229. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts +57 -0
  230. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts.map +1 -0
  231. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.js +860 -0
  232. package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.d.ts +115 -0
  233. package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.d.ts.map +1 -0
  234. package/src/shade/renderer/particles/optimizer/dag/particle_vector_rules.js +264 -0
  235. package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts +81 -42
  236. package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts.map +1 -1
  237. package/src/shade/renderer/particles/optimizer/optimize_particle_program.js +477 -478
  238. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts +100 -0
  239. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts.map +1 -0
  240. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.js +236 -0
  241. package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts +139 -59
  242. package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts.map +1 -1
  243. package/src/shade/renderer/particles/optimizer/particle_program_analysis.js +764 -647
  244. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts +40 -7
  245. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts.map +1 -1
  246. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.js +376 -213
  247. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts +30 -3
  248. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts.map +1 -1
  249. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.js +337 -223
  250. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts +24 -38
  251. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts.map +1 -1
  252. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.js +166 -206
  253. package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts +99 -0
  254. package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts.map +1 -0
  255. package/src/shade/renderer/particles/optimizer/pass_allocate_registers.js +313 -0
  256. package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts +3 -2
  257. package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts.map +1 -1
  258. package/src/shade/renderer/particles/optimizer/pass_dedup_constants.js +198 -197
  259. package/src/shade/renderer/particles/optimizer/pass_eliminate_dead_code.d.ts.map +1 -1
  260. package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts +19 -0
  261. package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts.map +1 -1
  262. package/src/shade/renderer/particles/optimizer/pass_fold_constants.js +678 -561
  263. package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts +22 -0
  264. package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts.map +1 -0
  265. package/src/shade/renderer/particles/optimizer/pass_inline_constants.js +221 -0
  266. package/src/shade/renderer/particles/optimizer/pass_narrow_widths.d.ts.map +1 -1
  267. package/src/shade/renderer/particles/optimizer/pass_narrow_widths.js +63 -72
  268. package/src/shade/renderer/particles/optimizer/pass_pack_registers.d.ts.map +1 -1
  269. package/src/shade/renderer/particles/optimizer/pass_pack_registers.js +87 -86
  270. package/src/shade/renderer/particles/optimizer/pass_peephole.d.ts.map +1 -1
  271. package/src/shade/renderer/particles/optimizer/pass_peephole.js +392 -271
  272. package/src/shade/renderer/particles/optimizer/pass_propagate_copies.d.ts.map +1 -1
  273. package/src/shade/renderer/particles/optimizer/pass_propagate_copies.js +361 -268
  274. package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts +4 -0
  275. package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts.map +1 -0
  276. package/src/shade/renderer/particles/optimizer/pass_schedule.js +244 -0
  277. package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.d.ts.map +1 -1
  278. package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.js +154 -151
  279. package/src/shade/renderer/particles/particle_test_fixtures.d.ts +20 -0
  280. package/src/shade/renderer/particles/particle_test_fixtures.d.ts.map +1 -1
  281. package/src/shade/renderer/particles/particle_test_fixtures.js +229 -203
  282. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts +99 -25
  283. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts.map +1 -1
  284. package/src/shade/renderer/particles/runtime/EmitterRegistry.js +438 -286
  285. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts +109 -0
  286. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts.map +1 -0
  287. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.js +127 -0
  288. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +87 -102
  289. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
  290. package/src/shade/renderer/particles/runtime/ParticleEmitter.js +184 -163
  291. package/src/shade/renderer/particles/runtime/ProgramArena.d.ts +26 -0
  292. package/src/shade/renderer/particles/runtime/ProgramArena.d.ts.map +1 -1
  293. package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts +130 -0
  294. package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts.map +1 -0
  295. package/src/shade/renderer/particles/runtime/ProgramHeap.js +595 -0
  296. package/src/shade/renderer/particles/runtime/ProgramPlacement.d.ts +91 -0
  297. package/src/shade/renderer/particles/runtime/ProgramPlacement.d.ts.map +1 -0
  298. package/src/shade/renderer/particles/runtime/ProgramPlacement.js +106 -0
  299. package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts +5 -2
  300. package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts.map +1 -1
  301. package/src/shade/renderer/particles/runtime/create_particle_effect.js +22 -19
  302. package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.d.ts +28 -0
  303. package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.d.ts.map +1 -0
  304. package/src/shade/renderer/particles/shaders/chunk_particle_emit_step.js +136 -0
  305. package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.d.ts +35 -0
  306. package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.d.ts.map +1 -0
  307. package/src/shade/renderer/particles/shaders/chunk_particle_simulate_step.js +133 -0
  308. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts +18 -9
  309. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  310. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +20 -80
  311. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts +33 -0
  312. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts.map +1 -0
  313. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.js +114 -0
  314. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts +8 -0
  315. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  316. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +33 -101
  317. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts +45 -0
  318. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts.map +1 -0
  319. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.js +123 -0
  320. package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts +51 -0
  321. package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts.map +1 -0
  322. package/src/shade/renderer/particles/sort/graph_particle_sort.js +120 -0
  323. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts +6 -0
  324. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts.map +1 -0
  325. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.js +16 -0
  326. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts +4 -1
  327. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts.map +1 -1
  328. package/src/shade/renderer/particles/vm/ParticleVMReference.js +261 -140
  329. package/src/shade/renderer/particles/vm/chunk_particle_vm.d.ts.map +1 -1
  330. package/src/shade/renderer/particles/vm/chunk_particle_vm.js +217 -255
  331. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.d.ts +43 -0
  332. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.d.ts.map +1 -0
  333. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_fast.js +55 -0
  334. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.d.ts +62 -0
  335. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.d.ts.map +1 -0
  336. package/src/shade/renderer/particles/vm/chunk_particle_vm_registers_wide.js +86 -0
  337. package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.d.ts +22 -0
  338. package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.d.ts.map +1 -0
  339. package/src/shade/renderer/shader/chunk/math/chunk_mod_v3f.js +32 -0
  340. package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.d.ts +9 -0
  341. package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.d.ts.map +1 -0
  342. package/src/shade/renderer/shader/chunk/math/chunk_mod_v4f.js +19 -0
  343. package/src/shade/renderer/shader/chunk/noise/psrdnoise/README.md +65 -0
  344. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.d.ts +24 -0
  345. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.d.ts.map +1 -0
  346. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2.js +83 -0
  347. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.d.ts +25 -0
  348. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.d.ts.map +1 -0
  349. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_hash.js +42 -0
  350. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.d.ts +31 -0
  351. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.d.ts.map +1 -0
  352. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise2_kernel.js +80 -0
  353. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.d.ts +26 -0
  354. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.d.ts.map +1 -0
  355. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3.js +109 -0
  356. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.d.ts +38 -0
  357. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.d.ts.map +1 -0
  358. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_kernel.js +129 -0
  359. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.d.ts +21 -0
  360. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.d.ts.map +1 -0
  361. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_permute.js +35 -0
  362. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.d.ts +19 -0
  363. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.d.ts.map +1 -0
  364. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_skew.js +28 -0
  365. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.d.ts +13 -0
  366. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.d.ts.map +1 -0
  367. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_psrdnoise3_unskew.js +22 -0
  368. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.d.ts +22 -0
  369. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.d.ts.map +1 -0
  370. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise2.js +59 -0
  371. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.d.ts +23 -0
  372. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.d.ts.map +1 -0
  373. package/src/shade/renderer/shader/chunk/noise/psrdnoise/chunk_srdnoise3.js +74 -0
  374. package/src/shade/wgsl/emulator/ComputeShaderEmulator.d.ts +34 -1
  375. package/src/shade/wgsl/emulator/ComputeShaderEmulator.d.ts.map +1 -1
  376. package/src/shade/wgsl/emulator/ComputeShaderEmulator.js +41 -1
  377. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts +3 -2
  378. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
  379. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +49 -10
  380. package/src/view/minimap/dom/MinimapCameraView.d.ts.map +1 -1
  381. package/src/view/minimap/dom/MinimapCameraView.js +4 -9
  382. package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts +0 -15
  383. package/src/core/model/node-graph/visual/layout/BoxLayoutSpec.d.ts.map +0 -1
  384. package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts +0 -45
  385. package/src/core/model/node-graph/visual/layout/ConnectedBoxLayouter.d.ts.map +0 -1
  386. package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts +0 -24
  387. package/src/core/model/node-graph/visual/layout/ConnectionEndpointLayoutSpec.d.ts.map +0 -1
  388. package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts +0 -19
  389. package/src/core/model/node-graph/visual/layout/ConnectionLayoutSpec.d.ts.map +0 -1
  390. package/src/engine/ecs/transform/__probe.d.ts +0 -4
  391. package/src/engine/ecs/transform/__probe.d.ts.map +0 -1
  392. package/src/engine/ecs/util/hideEntityGracefully.d.ts +0 -9
  393. package/src/engine/ecs/util/hideEntityGracefully.d.ts.map +0 -1
  394. package/src/shade/renderer/buffer/table/gpu_database_emulator_image.d.ts +0 -27
  395. package/src/shade/renderer/buffer/table/gpu_database_emulator_image.d.ts.map +0 -1
  396. package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts +0 -14
  397. package/src/shade/renderer/particles/cull/chunk_particle_cull.d.ts.map +0 -1
  398. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_LAYOUT.d.ts +0 -156
  399. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_LAYOUT.d.ts.map +0 -1
  400. package/src/shade/renderer/particles/runtime/Emitter.d.ts +0 -219
  401. package/src/shade/renderer/particles/runtime/Emitter.d.ts.map +0 -1
  402. package/src/shade/renderer/particles/runtime/ParticleSpawnScheduler.d.ts +0 -77
  403. package/src/shade/renderer/particles/runtime/ParticleSpawnScheduler.d.ts.map +0 -1
  404. package/src/shade/renderer/particles/runtime/ProgramArena.js +0 -155
  405. package/src/shade/renderer/particles/runtime/emitter_database_image.d.ts +0 -15
  406. package/src/shade/renderer/particles/runtime/emitter_database_image.d.ts.map +0 -1
  407. package/src/shade/renderer/particles/runtime/spawn_request_encoding.d.ts +0 -34
  408. package/src/shade/renderer/particles/runtime/spawn_request_encoding.d.ts.map +0 -1
  409. package/src/shade/renderer/particles/shaders/chunk_particle_context.d.ts +0 -32
  410. package/src/shade/renderer/particles/shaders/chunk_particle_context.d.ts.map +0 -1
@@ -0,0 +1,403 @@
1
+ import { AnimationCurve } from "../../../../engine/animation/curve/AnimationCurve.js";
2
+
3
+ /**
4
+ * Ramps: a curve and a colour gradient, and the arithmetic either one becomes.
5
+ *
6
+ * Both are the same shape of thing — a value that depends on one number `t`, written down as a
7
+ * handful of points with something interpolated between them — and both are *authored data* rather
8
+ * than wiring, so neither can be a {@link ./ParticleNodeGroup.js node group}: a group's body is
9
+ * fixed when the group is built, and a gradient with five stops is different arithmetic from a
10
+ * gradient with two. They are expanding node types instead (see
11
+ * {@link ./ParticleNodeDescription.js ParticleNodeDescription#expand}), and this is what they expand
12
+ * *into*: stock nodes, which is to say VM instructions, with the curve rolled out along them.
13
+ *
14
+ * ## Rolled out, not sampled
15
+ *
16
+ * There is a `CURVE` opcode, and it is not this. That one samples a row of the animation-curve table
17
+ * a host uploads, which is the right answer for a curve an author is dragging around at runtime and
18
+ * the wrong one for a curve that is part of the effect: it costs a table, a row, a handle to keep in
19
+ * step with it, and a texture fetch. A ramp with four stops rolls out to about twenty instructions
20
+ * of pure arithmetic, needs nothing from the host, and constant-folds where an author has left a
21
+ * segment flat.
22
+ *
23
+ * ## How a piecewise function becomes straight-line code
24
+ *
25
+ * There is no control flow to pick a segment with, so every segment is evaluated and the ones that
26
+ * do not apply are made to contribute nothing. Each segment gets a weight
27
+ *
28
+ * u = clamp((t - t0) / (t1 - t0), 0, 1)
29
+ *
30
+ * which is 0 everywhere before the segment, 1 everywhere after it, and the position within it in
31
+ * between. Contributions are then written as *differences* and summed:
32
+ *
33
+ * f(t) = v0 + sum over segments of c(u), where c(0) = 0 and c(1) = v1 - v0
34
+ *
35
+ * Before a segment, `u` is 0 and it adds nothing. After it, `u` is 1 and it has added exactly the
36
+ * step from its start value to its end value, so the segments before the one `t` is in telescope to
37
+ * "the value at the start of this segment" and the ones after it are silent. Only one segment is
38
+ * ever partway through, and its `c(u)` is the interpolation. The sum is therefore the piecewise
39
+ * function exactly — not an approximation of it — and it is three or four instructions per segment
40
+ * with no comparisons and no branches.
41
+ *
42
+ * It also gives the endpoint behaviour for free: `t` below the first stop leaves every weight at 0
43
+ * and the value is the first stop's, and above the last stop every weight is 1. That is what
44
+ * {@link AnimationCurve#evaluate} does at the ends, so the rollout and the editor's own preview
45
+ * agree there as well as in the middle.
46
+ *
47
+ * ## Why a gradient is not four curves
48
+ *
49
+ * A curve is an {@link AnimationCurve} — keys with tangents, the same class the rest of the engine
50
+ * animates with, so a curve authored here can be moved anywhere a curve is wanted and the editor's
51
+ * preview is the engine's own evaluation rather than a second opinion about it.
52
+ *
53
+ * A gradient is *not* four of those. A colour stop is one position with a colour on it, and that is
54
+ * the whole reason a gradient is easy to author: drag the stop and the colour moves. Four
55
+ * independent curves would let the red key drift away from the green one, and the interface the
56
+ * stops are for — Photoshop's, and everybody else's — could no longer be drawn over the data. So a
57
+ * gradient keeps a shared position per stop and interpolates linearly, and shares with the curve the
58
+ * thing actually worth sharing: the weights above, and the sum they go into.
59
+ */
60
+
61
+ /**
62
+ * One key of a curve, as it is stored in a node's parameters — the shape {@link AnimationCurve}
63
+ * writes and reads.
64
+ *
65
+ * @typedef {object} ParticleCurveKey
66
+ * @property {number} time
67
+ * @property {number} value
68
+ * @property {number} inTangent
69
+ * @property {number} outTangent
70
+ */
71
+
72
+ /**
73
+ * A curve, as a node parameter holds one.
74
+ *
75
+ * @typedef {{keys: ParticleCurveKey[]}} ParticleCurveParameter
76
+ */
77
+
78
+ /**
79
+ * One stop of a gradient: where it sits along `t`, and the colour there. The colour is always four
80
+ * numbers, whatever the node reads of it — an RGB gradient uses the first three — so that a gradient
81
+ * survives being moved between the two node types with its alpha intact.
82
+ *
83
+ * @typedef {{position: number, color: number[]}} ParticleGradientStop
84
+ */
85
+
86
+ /**
87
+ * How many lanes a gradient's colour is written with, whichever node reads it.
88
+ * @type {number}
89
+ */
90
+ export const PARTICLE_GRADIENT_COLOR_COMPONENTS = 4;
91
+
92
+ /**
93
+ * A fresh straight 0..1 ramp: what a curve node starts as.
94
+ *
95
+ * Linear rather than eased, because a curve node's first job is almost always to be *changed*, and a
96
+ * straight line is the shape whose change is easiest to see. Tangents of 1 are what make it straight
97
+ * — see {@link roll_out_particle_curve}.
98
+ *
99
+ * @returns {ParticleCurveParameter}
100
+ */
101
+ export function particle_curve_default() {
102
+ return {
103
+ keys: [
104
+ { time: 0, value: 0, inTangent: 1, outTangent: 1 },
105
+ { time: 1, value: 1, inTangent: 1, outTangent: 1 },
106
+ ],
107
+ };
108
+ }
109
+
110
+ /**
111
+ * A fresh black-to-white gradient: what a gradient node starts as.
112
+ *
113
+ * @returns {ParticleGradientStop[]}
114
+ */
115
+ export function particle_gradient_default() {
116
+ return [
117
+ { position: 0, color: [0, 0, 0, 1] },
118
+ { position: 1, color: [1, 1, 1, 1] },
119
+ ];
120
+ }
121
+
122
+ /**
123
+ * @param {*} value
124
+ * @returns {boolean} whether it is a finite number
125
+ */
126
+ function is_number(value) {
127
+ return typeof value === "number" && Number.isFinite(value);
128
+ }
129
+
130
+ /**
131
+ * Whether a value is a curve parameter this can lower — every key a record of four finite numbers.
132
+ *
133
+ * The validator's question and the editor's, asked in one place so that "a curve" means the same
134
+ * thing to both. Not a repair: something that fails this is reported against the node rather than
135
+ * quietly turned into a curve nobody asked for.
136
+ *
137
+ * @param {*} value
138
+ * @returns {boolean}
139
+ */
140
+ export function is_particle_curve(value) {
141
+ if (value === null || typeof value !== "object" || !Array.isArray(value.keys)) {
142
+ return false;
143
+ }
144
+
145
+ return value.keys.every(key => key !== null
146
+ && typeof key === "object"
147
+ && is_number(key.time)
148
+ && is_number(key.value)
149
+ && is_number(key.inTangent)
150
+ && is_number(key.outTangent));
151
+ }
152
+
153
+ /**
154
+ * Whether a value is a gradient parameter this can lower.
155
+ *
156
+ * @param {*} value
157
+ * @returns {boolean}
158
+ */
159
+ export function is_particle_gradient(value) {
160
+ if (!Array.isArray(value)) {
161
+ return false;
162
+ }
163
+
164
+ return value.every(stop => stop !== null
165
+ && typeof stop === "object"
166
+ && is_number(stop.position)
167
+ && Array.isArray(stop.color)
168
+ && stop.color.length === PARTICLE_GRADIENT_COLOR_COMPONENTS
169
+ && stop.color.every(is_number));
170
+ }
171
+
172
+ /**
173
+ * A curve's keys in time order.
174
+ *
175
+ * Sorted here rather than trusted, because a key dragged past its neighbour in the editor is an
176
+ * ordinary thing to do and the rollout's telescoping sum is only the piecewise function if the
177
+ * segments are walked in order.
178
+ *
179
+ * @param {ParticleCurveParameter} value
180
+ * @returns {ParticleCurveKey[]}
181
+ */
182
+ export function particle_curve_keys(value) {
183
+ return value.keys.slice().sort((a, b) => a.time - b.time);
184
+ }
185
+
186
+ /**
187
+ * The same curve as the engine's own {@link AnimationCurve} — what the editor draws and evaluates,
188
+ * and what a spec checks the rolled-out instructions against.
189
+ *
190
+ * @param {ParticleCurveParameter} value
191
+ * @returns {AnimationCurve}
192
+ */
193
+ export function particle_curve_animation(value) {
194
+ const curve = new AnimationCurve();
195
+
196
+ curve.fromJSON(value);
197
+
198
+ return curve;
199
+ }
200
+
201
+ /**
202
+ * A curve parameter holding what this {@link AnimationCurve} holds.
203
+ *
204
+ * @param {AnimationCurve} curve
205
+ * @returns {ParticleCurveParameter}
206
+ */
207
+ export function particle_curve_from_animation(curve) {
208
+ return {
209
+ keys: curve.keys.map(key => ({
210
+ time: key.time,
211
+ value: key.value,
212
+ inTangent: key.inTangent,
213
+ outTangent: key.outTangent,
214
+ })),
215
+ };
216
+ }
217
+
218
+ /**
219
+ * A gradient's stops in position order, each with its colour copied.
220
+ *
221
+ * @param {ParticleGradientStop[]} value
222
+ * @returns {ParticleGradientStop[]}
223
+ */
224
+ export function particle_gradient_stops(value) {
225
+ return value
226
+ .map(stop => ({ position: stop.position, color: stop.color.slice() }))
227
+ .sort((a, b) => a.position - b.position);
228
+ }
229
+
230
+ /**
231
+ * What a gradient is at `t`, in JavaScript: the same piecewise-linear function the rollout computes,
232
+ * for an editor to draw the strip with and for a spec to check the instructions against.
233
+ *
234
+ * @param {ParticleGradientStop[]} value
235
+ * @param {number} t
236
+ * @returns {number[]} four channels
237
+ */
238
+ export function particle_gradient_sample(value, t) {
239
+ const stops = particle_gradient_stops(value);
240
+
241
+ if (stops.length === 0) {
242
+ return new Array(PARTICLE_GRADIENT_COLOR_COMPONENTS).fill(0);
243
+ }
244
+
245
+ let result = stops[0].color.slice();
246
+
247
+ for (let i = 1; i < stops.length; i++) {
248
+ const span = stops[i].position - stops[i - 1].position;
249
+
250
+ const u = span > 0
251
+ ? Math.min(1, Math.max(0, (t - stops[i - 1].position) / span))
252
+ : (t < stops[i].position ? 0 : 1);
253
+
254
+ result = result.map((channel, lane) => channel + (stops[i].color[lane] - stops[i - 1].color[lane]) * u);
255
+ }
256
+
257
+ return result;
258
+ }
259
+
260
+ /**
261
+ * One segment's weight: 0 before it, 1 after it, and where along it `t` is in between.
262
+ *
263
+ * The divide is done here in JavaScript rather than by the program — `t * (1/span) - t0/span` is one
264
+ * multiply-add against two literals, where dividing at runtime would be a subtract and a divide
265
+ * against two more. Both of the literals fold into the constant pool, and the optimizer's constant
266
+ * inlining puts them in the instruction word itself.
267
+ *
268
+ * A segment of zero width is a jump rather than a ramp, and there is no `(t - t0) / 0` that says so.
269
+ * `step` does: it is 1 from the segment's position onward, which is what the sum needs to carry the
270
+ * whole of that segment's difference across in one place.
271
+ *
272
+ * @param {import("./ParticleGroupBuilder.js").ParticleGroupBuilder} g
273
+ * @param {*} t the value being looked up
274
+ * @param {number} start where the segment begins
275
+ * @param {number} end where it ends
276
+ * @returns {*} a scalar in `[0, 1]`
277
+ */
278
+ function segment_weight(g, t, start, end) {
279
+ const span = end - start;
280
+
281
+ if (span <= 0) {
282
+ return g.step(g.f(end), t);
283
+ }
284
+
285
+ return g.saturate(g.mad(t, g.f(1 / span), g.f(-start / span)));
286
+ }
287
+
288
+ /**
289
+ * Roll a curve out into arithmetic: `t` in, the curve's value at `t` out, as a scalar.
290
+ *
291
+ * Each segment is a cubic Hermite in its own weight, written in the form the sum wants — `c(0) = 0`
292
+ * and `c(1)` the step across the segment — which is the standard basis with the leading value
293
+ * subtracted back off:
294
+ *
295
+ * c(u) = ((A·u + B)·u + C)·u, A = m0 + m1 - 2Δv, B = 3Δv - 2m0 - m1, C = m0
296
+ *
297
+ * where `Δv` is the segment's rise and `m0`, `m1` are its tangents scaled by its width — exactly what
298
+ * {@link ../../../../engine/animation/curve/evaluate_two_key_curve.js} hands
299
+ * {@link ../../../../core/math/spline/spline3_hermite.js}, so a curve evaluates here to what it
300
+ * evaluates to anywhere else in the engine. Three multiply-adds, the last of which is also the
301
+ * accumulation.
302
+ *
303
+ * A segment whose tangents are its own slope has `A` and `B` at zero, which is a straight line and
304
+ * one instruction instead of three. A segment that neither rises nor turns contributes nothing at
305
+ * all and is not emitted — which is how the flat tail an author leaves on a fade costs nothing.
306
+ *
307
+ * @param {import("./ParticleGroupBuilder.js").ParticleGroupBuilder} g
308
+ * @param {*} t
309
+ * @param {ParticleCurveParameter} value
310
+ * @returns {*} a scalar
311
+ */
312
+ export function roll_out_particle_curve(g, t, value) {
313
+ const keys = particle_curve_keys(value);
314
+
315
+ // An empty curve is zero and a single key is a constant, which is what AnimationCurve evaluates
316
+ // them to — a node with nothing in it still compiles, and shows what it is worth.
317
+ if (keys.length === 0) {
318
+ return g.f(0);
319
+ }
320
+
321
+ let result = g.f(keys[0].value);
322
+
323
+ for (let i = 1; i < keys.length; i++) {
324
+ const k0 = keys[i - 1];
325
+ const k1 = keys[i];
326
+
327
+ const span = k1.time - k0.time;
328
+
329
+ // the tangents are per unit of `t`, and the polynomial is in the segment's own 0..1
330
+ const m0 = k0.outTangent * span;
331
+ const m1 = k1.inTangent * span;
332
+
333
+ const rise = k1.value - k0.value;
334
+
335
+ const a = m0 + m1 - 2 * rise;
336
+ const b = 3 * rise - 2 * m0 - m1;
337
+ const c = m0;
338
+
339
+ if (a === 0 && b === 0 && c === 0) {
340
+ continue;
341
+ }
342
+
343
+ const u = segment_weight(g, t, k0.time, k1.time);
344
+
345
+ if (a === 0 && b === 0) {
346
+ result = g.mad(u, g.f(c), result);
347
+ continue;
348
+ }
349
+
350
+ const cubic = g.mad(g.mad(u, g.f(a), g.f(b)), u, g.f(c));
351
+
352
+ result = g.mad(cubic, u, result);
353
+ }
354
+
355
+ return result;
356
+ }
357
+
358
+ /**
359
+ * Roll a gradient out into arithmetic: `t` in, the colour at `t` out.
360
+ *
361
+ * The same sum as the curve's, with a vector where the curve has a number and a straight line where
362
+ * it has a cubic — a stop's difference times the segment's weight, scaled and added. The weight is
363
+ * one lane and the difference is three or four, which is what `scale` is for: a vector times a
364
+ * broadcast scalar, one instruction, no widening.
365
+ *
366
+ * A segment between two stops of the same colour adds a zero vector and is not emitted, so the flat
367
+ * run an author leaves at either end of a gradient is free.
368
+ *
369
+ * @param {import("./ParticleGroupBuilder.js").ParticleGroupBuilder} g
370
+ * @param {*} t
371
+ * @param {ParticleGradientStop[]} value
372
+ * @param {number} components how many channels to produce: 3 for an RGB gradient, 4 for RGBA
373
+ * @returns {*} a vector of `components` lanes
374
+ */
375
+ export function roll_out_particle_gradient(g, t, value, components) {
376
+ const stops = particle_gradient_stops(value);
377
+
378
+ const channels = stop => stop.color.slice(0, components);
379
+
380
+ if (stops.length === 0) {
381
+ return g.f(...new Array(components).fill(0));
382
+ }
383
+
384
+ let result = g.f(...channels(stops[0]));
385
+
386
+ for (let i = 1; i < stops.length; i++) {
387
+ const from = channels(stops[i - 1]);
388
+ const to = channels(stops[i]);
389
+
390
+ const difference = to.map((channel, lane) => channel - from[lane]);
391
+
392
+ if (difference.every(channel => channel === 0)) {
393
+ continue;
394
+ }
395
+
396
+ const u = segment_weight(g, t, stops[i - 1].position, stops[i].position);
397
+
398
+ result = g.add(result, g.scale(g.f(...difference), u));
399
+ }
400
+
401
+ return result;
402
+ }
403
+
@@ -40,6 +40,12 @@ export type PARTICLE_GRAPH_PHASE = string;
40
40
  * narrower or wider than it is comes back as a warning naming the lanes, against the node reading
41
41
  * it. The shape of a finding is {@link ./particle_graph_diagnostic.js ParticleGraphDiagnostic}.
42
42
  *
43
+ * ## What is not a problem
44
+ *
45
+ * Only what reaches a sink is compiled, so only what reaches a sink can be wrong. A node no sink
46
+ * depends on is reported once, as information, and nothing else found against it is reported at
47
+ * all — see {@link report_unreachable}, which has the last word on every finding here.
48
+ *
43
49
  * ## Groups
44
50
  *
45
51
  * A {@link ./ParticleNodeGroup.js group} is checked as the node it looks like — its inputs must be
@@ -62,5 +68,5 @@ export const PARTICLE_GRAPH_PHASE: Readonly<{
62
68
  INIT: "init";
63
69
  UPDATE: "update";
64
70
  }>;
65
- export { PARTICLE_GRAPH_ERROR, PARTICLE_GRAPH_WARNING } from "./particle_graph_diagnostic.js";
71
+ export { PARTICLE_GRAPH_ERROR, PARTICLE_GRAPH_INFO, PARTICLE_GRAPH_WARNING } from "./particle_graph_diagnostic.js";
66
72
  //# sourceMappingURL=validate_particle_graph.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate_particle_graph.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/graph/validate_particle_graph.js"],"names":[],"mappings":"AAsDA;;;;;;;;GAQG;AACH;IAN0E,MAAM,GAArE,OAAO,6BAA6B,EAAE,cAAc;IAEnC,KAAK,GAAtB,MAAM;IAEJ,yBAAyB,CAqDrC;;;;;;;;mCAnES,MAAM;AAtChB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH;;;;;;;;GAQG;AACH;;;GAGG"}
1
+ {"version":3,"file":"validate_particle_graph.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/graph/validate_particle_graph.js"],"names":[],"mappings":"AAqEA;;;;;;;;GAQG;AACH;IAN0E,MAAM,GAArE,OAAO,6BAA6B,EAAE,cAAc;IAEnC,KAAK,GAAtB,MAAM;IAEJ,yBAAyB,CAoDrC;;;;;;;;mCAlES,MAAM;AA5ChB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH;;;;;;;;GAQG;AACH;;;GAGG"}
@@ -2,10 +2,19 @@ import { PortDirection } from "../../../../core/model/node-graph/node/PortDirect
2
2
  import { VM_MAX_WIDTH } from "../isa/ParticleVMISA.js";
3
3
  import { infer_particle_graph_types } from "./infer_particle_graph_types.js";
4
4
  import { is_particle_group_description } from "./ParticleNodeGroup.js";
5
- import { PARTICLE_GRAPH_ERROR, PARTICLE_GRAPH_WARNING } from "./particle_graph_diagnostic.js";
5
+ import {
6
+ PARTICLE_GRAPH_ERROR,
7
+ PARTICLE_GRAPH_INFO,
8
+ PARTICLE_GRAPH_WARNING,
9
+ } from "./particle_graph_diagnostic.js";
6
10
  import { PARTICLE_PARAMETER_KIND, particle_node_parameters } from "./particle_node_parameters.js";
11
+ import { is_particle_curve, is_particle_gradient } from "./particle_ramp.js";
7
12
 
8
- export { PARTICLE_GRAPH_ERROR, PARTICLE_GRAPH_WARNING } from "./particle_graph_diagnostic.js";
13
+ export {
14
+ PARTICLE_GRAPH_ERROR,
15
+ PARTICLE_GRAPH_INFO,
16
+ PARTICLE_GRAPH_WARNING,
17
+ } from "./particle_graph_diagnostic.js";
9
18
 
10
19
  /**
11
20
  * Check a particle graph and say what is wrong with it, per node.
@@ -28,6 +37,12 @@ export { PARTICLE_GRAPH_ERROR, PARTICLE_GRAPH_WARNING } from "./particle_graph_d
28
37
  * narrower or wider than it is comes back as a warning naming the lanes, against the node reading
29
38
  * it. The shape of a finding is {@link ./particle_graph_diagnostic.js ParticleGraphDiagnostic}.
30
39
  *
40
+ * ## What is not a problem
41
+ *
42
+ * Only what reaches a sink is compiled, so only what reaches a sink can be wrong. A node no sink
43
+ * depends on is reported once, as information, and nothing else found against it is reported at
44
+ * all — see {@link report_unreachable}, which has the last word on every finding here.
45
+ *
31
46
  * ## Groups
32
47
  *
33
48
  * A {@link ./ParticleNodeGroup.js group} is checked as the node it looks like — its inputs must be
@@ -107,11 +122,10 @@ export function validate_particle_graph(graph, { layout, phase } = {}) {
107
122
 
108
123
  report_duplicate_writes(sinks, layout, error);
109
124
  report_missing_kill(sinks, phase, warning);
110
- report_unreachable(graph, nodes, sinks, warning);
111
125
  report_cycles(nodes, error);
112
126
  report_conversions(graph, layout, diagnostics);
113
127
 
114
- return diagnostics;
128
+ return report_unreachable(nodes, sinks, diagnostics);
115
129
  }
116
130
 
117
131
  /**
@@ -223,6 +237,32 @@ function check_parameters(node, description, layout, error) {
223
237
  }
224
238
  break;
225
239
 
240
+ // A curve and a gradient are the only parameters with a shape underneath them, and both
241
+ // are written out into instructions rather than read at runtime — so a malformed one is
242
+ // a compile that throws rather than a value that misbehaves, and it is worth catching
243
+ // here where it can be put on the node.
244
+ case PARTICLE_PARAMETER_KIND.CURVE:
245
+ if (!is_particle_curve(value)) {
246
+ error(
247
+ node.id,
248
+ `Parameter '${parameter.name}' must be a curve: `
249
+ + "keys of time, value, inTangent and outTangent, all finite numbers."
250
+ );
251
+ }
252
+ break;
253
+
254
+ case PARTICLE_PARAMETER_KIND.GRADIENT:
255
+ if (!is_particle_gradient(value)) {
256
+ error(
257
+ node.id,
258
+ `Parameter '${parameter.name}' must be a gradient: `
259
+ + "stops of a finite position and four finite colour channels."
260
+ );
261
+ } else if (value.length === 0) {
262
+ error(node.id, `Parameter '${parameter.name}' has no stops, so it has no colour.`);
263
+ }
264
+ break;
265
+
226
266
  default:
227
267
  break;
228
268
  }
@@ -351,15 +391,23 @@ function report_conversions(graph, layout, diagnostics) {
351
391
  }
352
392
 
353
393
  /**
354
- * Nodes no sink depends on are compiled away without a word, which is a confusing thing for an
355
- * author to watch happen. Saying so is worth a warning and never an error.
394
+ * Have the last word on the nodes no sink depends on.
395
+ *
396
+ * Compilation starts from the sinks, so a node nothing downstream reads is never lowered: it cannot
397
+ * break the effect and it cannot cost an instruction. Half a graph waiting to be wired up is what
398
+ * most of authoring looks like, and an editor that called that an error would refuse to compile the
399
+ * working half over it — so everything found against such a node is dropped, and what is said in
400
+ * its place is the one thing an author cannot see for themselves: that it is not running.
401
+ *
402
+ * The note is {@link PARTICLE_GRAPH_INFO}, which is not a problem with the graph. Findings about the
403
+ * graph as a whole are left alone, being about no node and so about none of this.
356
404
  *
357
- * @param {NodeGraph} graph
358
405
  * @param {NodeInstance[]} nodes
359
406
  * @param {NodeInstance[]} sinks
360
- * @param {function(number, string):void} warning
407
+ * @param {ParticleGraphDiagnostic[]} diagnostics everything the checks above found
408
+ * @returns {ParticleGraphDiagnostic[]}
361
409
  */
362
- function report_unreachable(graph, nodes, sinks, warning) {
410
+ function report_unreachable(nodes, sinks, diagnostics) {
363
411
  const reached = new Set();
364
412
  const stack = sinks.slice();
365
413
 
@@ -377,11 +425,19 @@ function report_unreachable(graph, nodes, sinks, warning) {
377
425
  }
378
426
  }
379
427
 
428
+ const kept = diagnostics.filter(diagnostic => diagnostic.node < 0 || reached.has(diagnostic.node));
429
+
380
430
  for (const node of nodes) {
381
431
  if (!reached.has(node.id)) {
382
- warning(node.id, "Nothing downstream reads this node, so it is dropped when the graph is compiled.");
432
+ kept.push({
433
+ node: node.id,
434
+ message: "Nothing downstream reads this node, so it is left out when the graph is compiled.",
435
+ severity: PARTICLE_GRAPH_INFO,
436
+ });
383
437
  }
384
438
  }
439
+
440
+ return kept;
385
441
  }
386
442
 
387
443
  /**