@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,20 @@
1
+ export class ParticleCurveEditorView extends View {
2
+ /**
3
+ * @param {object} options
4
+ * @param {function():object} options.read the parameter's current value
5
+ * @param {function(object):void} options.write commit a new value
6
+ */
7
+ constructor({ read, write }: {
8
+ read: () => object;
9
+ write: (arg0: object) => void;
10
+ });
11
+ el: HTMLDivElement;
12
+ /**
13
+ * Re-read the parameter and redraw.
14
+ */
15
+ refresh(): void;
16
+ render(): void;
17
+ #private;
18
+ }
19
+ import View from "../../../../src/view/View.js";
20
+ //# sourceMappingURL=ParticleCurveEditorView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ParticleCurveEditorView.d.ts","sourceRoot":"","sources":["../../../../../editor/view/particles/effect/ParticleCurveEditorView.js"],"names":[],"mappings":"AAgEA;IA6CI;;;;OAIG;IACH;QAHsC,IAAI,QAApB,MAAM;QACc,KAAK,SAA3B,MAAM,KAAE,IAAI;OAiF/B;IAzEG,mBAAuC;IA2E3C;;OAEG;IACH,gBAcC;IAgRD,eAiEC;;CACJ;iBA/hBgB,8BAA8B"}
@@ -0,0 +1,574 @@
1
+ import { AnimationCurve } from "../../../../src/engine/animation/curve/AnimationCurve.js";
2
+ import { Keyframe } from "../../../../src/engine/animation/curve/Keyframe.js";
3
+ import { clamp01 } from "../../../../src/core/math/clamp01.js";
4
+ import {
5
+ particle_curve_animation,
6
+ particle_curve_from_animation,
7
+ } from "../../../../src/shade/renderer/particles/graph/particle_ramp.js";
8
+ import View from "../../../../src/view/View.js";
9
+
10
+ /**
11
+ * A curve, edited in the unit square: `t` across, the value up, and the keys that make it draggable.
12
+ *
13
+ * Drag a key to move it. Click where there is no key and one is added there, with tangents that
14
+ * leave the curve looking like it did — so adding a key is somewhere to make an edit *from* rather
15
+ * than an edit in itself. Middle-click a key, or press the remove button, and it goes. The picker
16
+ * below sets the selected key's tangents, which is what shapes the curve on either side of it.
17
+ *
18
+ * ## It is an AnimationCurve
19
+ *
20
+ * Not a lookalike. The model here is the engine's own {@link AnimationCurve}, the curve is drawn by
21
+ * asking it what it is at each pixel, and what the node stores is that class's own JSON. So the
22
+ * picture is the engine's evaluation rather than a second opinion about it, and a curve authored
23
+ * here means the same thing anywhere else a curve is wanted.
24
+ *
25
+ * The compiled program is a third thing again — the curve written out as VM arithmetic, see
26
+ * {@link ../../../../src/shade/renderer/particles/graph/particle_ramp.js} — and its agreeing with
27
+ * this one is what `particle_ramp.spec.js` checks.
28
+ *
29
+ * ## The unit square
30
+ *
31
+ * Drawn from 0 to 1 on both axes, and keys are held inside it, because that is what the node is for:
32
+ * `t` normalised in, a factor out. A curve that wants to go to eleven is that curve times eleven,
33
+ * which is a `mul` node and is visible in the graph — where a value of eleven hidden inside a
34
+ * control would not be.
35
+ *
36
+ * ## When an edit is committed
37
+ *
38
+ * On pointer up, for the reason set out in {@link ./ParticleGradientEditorView.js}: a key dragged
39
+ * across the square is one thing to undo, not the hundred pointer events it was made of.
40
+ */
41
+
42
+ /** @type {number} */
43
+ const WIDTH = 208;
44
+
45
+ /** @type {number} */
46
+ const HEIGHT = 84;
47
+
48
+ /** Room around the plot, so a key at 0 or 1 is drawn whole rather than clipped in half. */
49
+ const MARGIN = 7;
50
+
51
+ /** How near a key a press has to be to take hold of it rather than make a new one. */
52
+ const GRAB_RADIUS = 8;
53
+
54
+ /**
55
+ * What the tangent picker offers. Each is a way of deciding a key's two tangents, and between them
56
+ * they cover what anybody actually wants from a curve of this size.
57
+ * @type {Object<string, string>}
58
+ */
59
+ const TANGENT_MODES = Object.freeze({
60
+ Smooth: "smooth",
61
+ Linear: "linear",
62
+ Flat: "flat",
63
+ });
64
+
65
+ export class ParticleCurveEditorView extends View {
66
+ /**
67
+ * The curve being edited — a working copy, drawn continuously and committed on release.
68
+ * @type {AnimationCurve}
69
+ */
70
+ #curve = new AnimationCurve();
71
+
72
+ /** @type {HTMLCanvasElement} */
73
+ #canvas;
74
+
75
+ /** @type {CanvasRenderingContext2D|null} */
76
+ #context = null;
77
+
78
+ /** @type {number} */
79
+ #selected = 0;
80
+
81
+ /** @type {boolean} */
82
+ #dragging = false;
83
+
84
+ /** @type {function():object} */
85
+ #read;
86
+
87
+ /** @type {function(object):void} */
88
+ #commit;
89
+
90
+ /**
91
+ * Which rule each key's tangents came from, by key.
92
+ *
93
+ * A curve is keys and tangents and nothing else — that is the format the rest of the engine
94
+ * reads, and putting a mode in it would be inventing one nobody else understands. So the mode is
95
+ * *read off* the numbers when a curve arrives ({@link #modeOf}) and remembered here for as long
96
+ * as it is being edited.
97
+ *
98
+ * Remembered rather than re-derived, because re-deriving it is exactly wrong at the one moment it
99
+ * is wanted: moving a key changes the slope to its neighbours, so a key that was linear stops
100
+ * looking linear the instant it needs re-deriving, and asking the curve after the move would
101
+ * answer "smooth" every time.
102
+ *
103
+ * @type {WeakMap<import("../../../../src/engine/animation/curve/Keyframe.js").Keyframe, string>}
104
+ */
105
+ #modes = new WeakMap();
106
+
107
+ /** @type {HTMLSelectElement} */
108
+ #tangents;
109
+
110
+ /**
111
+ * @param {object} options
112
+ * @param {function():object} options.read the parameter's current value
113
+ * @param {function(object):void} options.write commit a new value
114
+ */
115
+ constructor({ read, write }) {
116
+ super();
117
+
118
+ this.#read = read;
119
+ this.#commit = write;
120
+
121
+ this.el = document.createElement('div');
122
+
123
+ this.addClass('ui-particle-curve');
124
+
125
+ const canvas = this.#canvas = document.createElement('canvas');
126
+
127
+ canvas.width = WIDTH;
128
+ canvas.height = HEIGHT;
129
+ canvas.classList.add('plot');
130
+
131
+ this.el.appendChild(canvas);
132
+
133
+ const fields = document.createElement('div');
134
+
135
+ fields.classList.add('key-fields');
136
+
137
+ this.el.appendChild(fields);
138
+
139
+ const tangents = this.#tangents = document.createElement('select');
140
+
141
+ tangents.classList.add('ui-particle-parameter-select', 'tangents');
142
+ tangents.title = "How the selected key's tangents are decided";
143
+
144
+ for (const [label, mode] of Object.entries(TANGENT_MODES)) {
145
+ const option = document.createElement('option');
146
+
147
+ option.value = mode;
148
+ option.textContent = label;
149
+
150
+ tangents.appendChild(option);
151
+ }
152
+
153
+ fields.appendChild(tangents);
154
+
155
+ const remove = document.createElement('button');
156
+
157
+ remove.type = 'button';
158
+ remove.classList.add('remove');
159
+ remove.textContent = '−';
160
+ remove.title = "Remove the selected key (or middle-click it)";
161
+
162
+ fields.appendChild(remove);
163
+
164
+ canvas.addEventListener('pointerdown', event => this.#press(event));
165
+ canvas.addEventListener('pointermove', event => this.#move(event));
166
+ canvas.addEventListener('pointerup', event => this.#release(event));
167
+ canvas.addEventListener('pointercancel', event => this.#release(event));
168
+
169
+ tangents.addEventListener('change', () => {
170
+ const key = this.#curve.keys[this.#selected];
171
+
172
+ if (key === undefined) {
173
+ return;
174
+ }
175
+
176
+ this.#modes.set(key, tangents.value);
177
+ this.#applyTangents(this.#selected, tangents.value);
178
+
179
+ this.#commit(particle_curve_from_animation(this.#curve));
180
+ this.render();
181
+ });
182
+
183
+ remove.addEventListener('click', () => this.#removeSelected());
184
+
185
+ this.on.linked.add(() => {
186
+ if (this.#context === null) {
187
+ this.#context = canvas.getContext('2d');
188
+ }
189
+
190
+ this.refresh();
191
+ });
192
+
193
+ this.refresh();
194
+ }
195
+
196
+ /**
197
+ * Re-read the parameter and redraw.
198
+ */
199
+ refresh() {
200
+ const value = this.#read();
201
+
202
+ this.#curve = particle_curve_animation(
203
+ value !== null && typeof value === "object" && Array.isArray(value.keys) ? value : { keys: [] }
204
+ );
205
+
206
+ this.#selected = Math.min(this.#selected, Math.max(0, this.#curve.keys.length - 1));
207
+
208
+ // read off the numbers now, while they still say what rule made them
209
+ this.#curve.keys.forEach((key, index) => this.#modes.set(key, this.#modeOf(index)));
210
+
211
+ this.#writeFields();
212
+ this.render();
213
+ }
214
+
215
+ /**
216
+ * @param {PointerEvent} event
217
+ * @returns {{time: number, value: number}} where in the unit square the pointer is
218
+ */
219
+ #pointOf(event) {
220
+ const rect = this.#canvas.getBoundingClientRect();
221
+
222
+ const scale = rect.width / WIDTH;
223
+
224
+ const x = (event.clientX - rect.left) / scale - MARGIN;
225
+ const y = (event.clientY - rect.top) / (rect.height / HEIGHT) - MARGIN;
226
+
227
+ return {
228
+ time: clamp01(x / (WIDTH - MARGIN * 2)),
229
+ // the plot runs upward and the canvas runs downward
230
+ value: clamp01(1 - y / (HEIGHT - MARGIN * 2)),
231
+ };
232
+ }
233
+
234
+ /**
235
+ * @param {number} time
236
+ * @param {number} value
237
+ * @returns {{x: number, y: number}} the point in canvas pixels
238
+ */
239
+ #plot(time, value) {
240
+ return {
241
+ x: MARGIN + clamp01(time) * (WIDTH - MARGIN * 2),
242
+ y: MARGIN + (1 - clamp01(value)) * (HEIGHT - MARGIN * 2),
243
+ };
244
+ }
245
+
246
+ /**
247
+ * @param {PointerEvent} event
248
+ * @returns {number} the index of the key under the pointer, or -1
249
+ */
250
+ #keyUnder(event) {
251
+ const rect = this.#canvas.getBoundingClientRect();
252
+
253
+ const scale = rect.width / WIDTH;
254
+
255
+ const x = (event.clientX - rect.left) / scale;
256
+ const y = (event.clientY - rect.top) / (rect.height / HEIGHT);
257
+
258
+ let nearest = -1;
259
+ let distance = Infinity;
260
+
261
+ this.#curve.keys.forEach((key, index) => {
262
+ const point = this.#plot(key.time, key.value);
263
+
264
+ const away = Math.hypot(point.x - x, point.y - y);
265
+
266
+ if (away <= GRAB_RADIUS && away < distance) {
267
+ nearest = index;
268
+ distance = away;
269
+ }
270
+ });
271
+
272
+ return nearest;
273
+ }
274
+
275
+ /**
276
+ * @param {PointerEvent} event
277
+ */
278
+ #press(event) {
279
+ const key = this.#keyUnder(event);
280
+
281
+ if (event.button === 1) {
282
+ if (key !== -1) {
283
+ this.#selected = key;
284
+ this.#removeSelected();
285
+ }
286
+
287
+ event.preventDefault();
288
+ return;
289
+ }
290
+
291
+ if (event.button !== 0) {
292
+ return;
293
+ }
294
+
295
+ if (key !== -1) {
296
+ this.#selected = key;
297
+ } else {
298
+ const { time } = this.#pointOf(event);
299
+
300
+ // On the curve where it already is, with tangents that keep it looking the same, so the
301
+ // click is somewhere to edit from rather than an edit.
302
+ this.#selected = this.#curve.add(Keyframe.from(time, this.#curve.evaluate(time)));
303
+
304
+ this.#modes.set(this.#curve.keys[this.#selected], TANGENT_MODES.Smooth);
305
+ this.#applyTangents(this.#selected, TANGENT_MODES.Smooth);
306
+
307
+ this.#commit(particle_curve_from_animation(this.#curve));
308
+ }
309
+
310
+ this.#dragging = true;
311
+
312
+ if (typeof this.#canvas.setPointerCapture === "function") {
313
+ this.#canvas.setPointerCapture(event.pointerId);
314
+ }
315
+
316
+ this.#writeFields();
317
+ this.render();
318
+ }
319
+
320
+ /**
321
+ * @param {PointerEvent} event
322
+ */
323
+ #move(event) {
324
+ if (!this.#dragging) {
325
+ return;
326
+ }
327
+
328
+ const key = this.#curve.keys[this.#selected];
329
+
330
+ if (key === undefined) {
331
+ return;
332
+ }
333
+
334
+ const { time, value } = this.#pointOf(event);
335
+
336
+ key.time = time;
337
+ key.value = value;
338
+
339
+ // The curve keeps its keys in time order and this one may have crossed a neighbour. Sorting
340
+ // by hand rather than removing and re-adding, so that the key object — and the selection
341
+ // pointing at it — survive the move.
342
+ this.#selected = resort(this.#curve.keys, this.#selected);
343
+
344
+ this.render();
345
+ }
346
+
347
+ /**
348
+ * @param {PointerEvent} event
349
+ */
350
+ #release(event) {
351
+ if (!this.#dragging) {
352
+ return;
353
+ }
354
+
355
+ this.#dragging = false;
356
+
357
+ if (typeof this.#canvas.releasePointerCapture === "function" && this.#canvas.hasPointerCapture?.(event.pointerId)) {
358
+ this.#canvas.releasePointerCapture(event.pointerId);
359
+ }
360
+
361
+ // A key that moved changed the slope on both sides of it, so whichever rule its neighbours
362
+ // were following has to be applied again — otherwise a "Linear" segment stops being straight
363
+ // the moment either of its ends is dragged.
364
+ this.#reapplyAround(this.#selected);
365
+
366
+ this.#commit(particle_curve_from_animation(this.#curve));
367
+
368
+ this.#writeFields();
369
+ this.render();
370
+ }
371
+
372
+ #removeSelected() {
373
+ // A curve with one key is a constant, which is a thing to be; a curve with none is nothing,
374
+ // and evaluates to zero whatever it is asked. The last key stays.
375
+ if (this.#curve.keys.length <= 1) {
376
+ return;
377
+ }
378
+
379
+ this.#curve.keys.splice(this.#selected, 1);
380
+
381
+ this.#selected = Math.min(this.#selected, this.#curve.keys.length - 1);
382
+
383
+ this.#reapplyAround(this.#selected);
384
+
385
+ this.#commit(particle_curve_from_animation(this.#curve));
386
+ this.#writeFields();
387
+ this.render();
388
+ }
389
+
390
+ /**
391
+ * Re-derive the tangents of a key and its neighbours from the rule each of them was following.
392
+ *
393
+ * Both Linear and Smooth are claims about where the neighbours are, so moving a key falsifies
394
+ * them on all three; Flat is a claim about nothing and re-applying it changes no number. The
395
+ * rules come from {@link #modes} rather than from the curve, for the reason set out there.
396
+ *
397
+ * @param {number} index
398
+ */
399
+ #reapplyAround(index) {
400
+ for (const neighbour of [index - 1, index, index + 1]) {
401
+ const key = this.#curve.keys[neighbour];
402
+
403
+ if (key !== undefined) {
404
+ this.#applyTangents(neighbour, this.#modes.get(key) ?? TANGENT_MODES.Smooth);
405
+ }
406
+ }
407
+ }
408
+
409
+ /**
410
+ * @param {number} index
411
+ * @param {string} mode a {@link TANGENT_MODES}
412
+ */
413
+ #applyTangents(index, mode) {
414
+ const keys = this.#curve.keys;
415
+
416
+ const key = keys[index];
417
+
418
+ if (key === undefined) {
419
+ return;
420
+ }
421
+
422
+ if (mode === TANGENT_MODES.Flat) {
423
+ key.inTangent = 0;
424
+ key.outTangent = 0;
425
+ return;
426
+ }
427
+
428
+ if (mode === TANGENT_MODES.Linear) {
429
+ // each side takes the slope to its own neighbour, which is what makes the segment on
430
+ // that side a straight line
431
+ this.#curve.alignTangents(index);
432
+ return;
433
+ }
434
+
435
+ // Smooth: one slope for both sides, taken across the key rather than up to it — the
436
+ // Catmull-Rom tangent, which is what makes a curve pass through its keys without a corner
437
+ // at any of them.
438
+ const previous = keys[index - 1] ?? key;
439
+ const next = keys[index + 1] ?? key;
440
+
441
+ const span = next.time - previous.time;
442
+
443
+ const slope = span === 0 ? 0 : (next.value - previous.value) / span;
444
+
445
+ key.inTangent = slope;
446
+ key.outTangent = slope;
447
+ }
448
+
449
+ /**
450
+ * Which rule a key's tangents look like they came from. There is nowhere to *store* the answer —
451
+ * a curve is keys and tangents, and adding a mode to it would be inventing a format the rest of
452
+ * the engine does not read — so it is recovered from the numbers, which is exact for the two
453
+ * cases that matter and falls back to Smooth.
454
+ *
455
+ * @param {number} index
456
+ * @returns {string} a {@link TANGENT_MODES}
457
+ */
458
+ #modeOf(index) {
459
+ const key = this.#curve.keys[index];
460
+
461
+ if (key === undefined) {
462
+ return TANGENT_MODES.Smooth;
463
+ }
464
+
465
+ if (key.inTangent === 0 && key.outTangent === 0) {
466
+ return TANGENT_MODES.Flat;
467
+ }
468
+
469
+ const linear = new AnimationCurve();
470
+
471
+ linear.keys = this.#curve.keys.map(other => other.clone());
472
+ linear.alignTangents(index);
473
+
474
+ return linear.keys[index].inTangent === key.inTangent && linear.keys[index].outTangent === key.outTangent
475
+ ? TANGENT_MODES.Linear
476
+ : TANGENT_MODES.Smooth;
477
+ }
478
+
479
+ #writeFields() {
480
+ const key = this.#curve.keys[this.#selected];
481
+
482
+ this.#tangents.value = (key === undefined ? undefined : this.#modes.get(key)) ?? TANGENT_MODES.Smooth;
483
+ }
484
+
485
+ render() {
486
+ const context = this.#context;
487
+
488
+ if (context === null) {
489
+ return;
490
+ }
491
+
492
+ const canvas = this.#canvas;
493
+
494
+ context.clearRect(0, 0, canvas.width, canvas.height);
495
+
496
+ context.fillStyle = '#171b21';
497
+ context.fillRect(0, 0, canvas.width, canvas.height);
498
+
499
+ // the unit square, so "0" and "1" are somewhere rather than implied
500
+ context.strokeStyle = '#2c323b';
501
+ context.lineWidth = 1;
502
+ context.beginPath();
503
+
504
+ for (const fraction of [0, 0.5, 1]) {
505
+ const horizontal = this.#plot(0, fraction);
506
+ const vertical = this.#plot(fraction, 0);
507
+
508
+ context.moveTo(MARGIN, horizontal.y + 0.5);
509
+ context.lineTo(WIDTH - MARGIN, horizontal.y + 0.5);
510
+
511
+ context.moveTo(vertical.x + 0.5, MARGIN);
512
+ context.lineTo(vertical.x + 0.5, HEIGHT - MARGIN);
513
+ }
514
+
515
+ context.stroke();
516
+
517
+ // The curve itself, asked of the AnimationCurve a pixel at a time — the same evaluation the
518
+ // rest of the engine does, so what is drawn is what the curve is.
519
+ context.strokeStyle = '#7fb5ff';
520
+ context.lineWidth = 1.5;
521
+ context.beginPath();
522
+
523
+ for (let x = MARGIN; x <= WIDTH - MARGIN; x++) {
524
+ const time = (x - MARGIN) / (WIDTH - MARGIN * 2);
525
+
526
+ const point = this.#plot(time, this.#curve.evaluate(time));
527
+
528
+ if (x === MARGIN) {
529
+ context.moveTo(point.x, point.y);
530
+ } else {
531
+ context.lineTo(point.x, point.y);
532
+ }
533
+ }
534
+
535
+ context.stroke();
536
+
537
+ this.#curve.keys.forEach((key, index) => {
538
+ const point = this.#plot(key.time, key.value);
539
+
540
+ context.beginPath();
541
+ context.arc(point.x, point.y, index === this.#selected ? 4 : 3, 0, Math.PI * 2);
542
+
543
+ context.fillStyle = index === this.#selected ? '#ffd35c' : '#d6d8da';
544
+ context.fill();
545
+
546
+ context.lineWidth = 1;
547
+ context.strokeStyle = '#171b21';
548
+ context.stroke();
549
+ });
550
+ }
551
+ }
552
+
553
+ /**
554
+ * Move one element of an already-sorted-but-for-it array back into place, and say where it went.
555
+ *
556
+ * @param {Array<{time: number}>} keys sorted by time, except possibly at `index`
557
+ * @param {number} index
558
+ * @returns {number} where the element is now
559
+ */
560
+ function resort(keys, index) {
561
+ let at = index;
562
+
563
+ while (at > 0 && keys[at - 1].time > keys[at].time) {
564
+ [keys[at - 1], keys[at]] = [keys[at], keys[at - 1]];
565
+ at--;
566
+ }
567
+
568
+ while (at < keys.length - 1 && keys[at + 1].time < keys[at].time) {
569
+ [keys[at + 1], keys[at]] = [keys[at], keys[at + 1]];
570
+ at++;
571
+ }
572
+
573
+ return at;
574
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"ParticleEmitterInspectorView.d.ts","sourceRoot":"","sources":["../../../../../editor/view/particles/effect/ParticleEmitterInspectorView.js"],"names":[],"mappings":"AA+DA;IAkDI;;;OAGG;IACH;QAFyG,MAAM,EAApG,OAAO,qDAAqD,EAAE,sBAAsB;OAqC9F;IAhCG,mBAAuC;IAIvC;;OAEG;IACH,QAFU,OAAO,qDAAqD,EAAE,sBAAsB,CAE1E;IA2BxB;;;;;;OAMG;IACH,gBAiBC;;CAyXJ;iBAjiBgB,8BAA8B"}
1
+ {"version":3,"file":"ParticleEmitterInspectorView.d.ts","sourceRoot":"","sources":["../../../../../editor/view/particles/effect/ParticleEmitterInspectorView.js"],"names":[],"mappings":"AA+DA;IAkDI;;;OAGG;IACH;QAFyG,MAAM,EAApG,OAAO,qDAAqD,EAAE,sBAAsB;OAqC9F;IAhCG,mBAAuC;IAIvC;;OAEG;IACH,QAFU,OAAO,qDAAqD,EAAE,sBAAsB,CAE1E;IA2BxB;;;;;;OAMG;IACH,gBAiBC;;CAmZJ;iBA3jBgB,8BAA8B"}
@@ -231,7 +231,7 @@ export class ParticleEmitterInspectorView extends View {
231
231
  }
232
232
 
233
233
  section.addChild(this.#vectorRow("flipbook (cols, rows)", "flipbook", 2));
234
- section.addChild(this.#vectorRow("atlas (u, v, w, h)", "atlas_region", 4));
234
+ section.addChild(this.#textRow("texture", "texture"));
235
235
 
236
236
  return section;
237
237
  }
@@ -456,6 +456,32 @@ export class ParticleEmitterInspectorView extends View {
456
456
  return row(field.label, input, field.help);
457
457
  }
458
458
 
459
+ /**
460
+ * A row for a field holding a string, or nothing. An empty field reads back as `null` rather
461
+ * than `""`: the emitter's texture is a URL or the absence of one, and an empty string is
462
+ * neither.
463
+ *
464
+ * @param {string} label
465
+ * @param {string} key emitter field
466
+ * @returns {View}
467
+ */
468
+ #textRow(label, key) {
469
+ const field = text_input(this.effect.emitter[key] ?? "");
470
+
471
+ field.addEventListener('change', () => {
472
+ this.effect.emitter[key] = field.value === "" ? null : field.value;
473
+ this.effect.touch();
474
+ });
475
+
476
+ this.#readers.push(() => {
477
+ if (document.activeElement !== field) {
478
+ field.value = this.effect.emitter[key] ?? "";
479
+ }
480
+ });
481
+
482
+ return row(label, field);
483
+ }
484
+
459
485
  /**
460
486
  * @param {string} label
461
487
  * @param {string} key emitter field holding an array
@@ -0,0 +1,24 @@
1
+ export class ParticleGradientEditorView extends View {
2
+ /**
3
+ * @param {object} options
4
+ * @param {function():Array} options.read the parameter's current value
5
+ * @param {function(Array):void} options.write commit a new value
6
+ * @param {boolean} [options.alpha] whether the node reads the alpha channel; an RGB gradient
7
+ * still *stores* one — see {@link ./particle_ramp.js} — but does not offer it for editing
8
+ */
9
+ constructor({ read, write, alpha }: {
10
+ read: () => any[];
11
+ write: (arg0: any[]) => void;
12
+ alpha?: boolean;
13
+ });
14
+ el: HTMLDivElement;
15
+ /**
16
+ * Re-read the parameter and redraw. Called when the value changed somewhere else — an undo, the
17
+ * code layer, a script.
18
+ */
19
+ refresh(): void;
20
+ render(): void;
21
+ #private;
22
+ }
23
+ import View from "../../../../src/view/View.js";
24
+ //# sourceMappingURL=ParticleGradientEditorView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ParticleGradientEditorView.d.ts","sourceRoot":"","sources":["../../../../../editor/view/particles/effect/ParticleGradientEditorView.js"],"names":[],"mappings":"AAkDA;IAsCI;;;;;;OAMG;IACH;QALqC,IAAI;QACA,KAAK,mBAAnB,IAAI;QACF,KAAK,GAAvB,OAAO;OAqFjB;IA3EG,mBAAuC;IAyF3C;;;OAGG;IACH,gBAWC;IAoLD,eAoDC;;CACJ;iBAnbgB,8BAA8B"}