@fps-games/vfx 0.1.1

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 (375) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/EffectPackageService.d.ts +26 -0
  3. package/dist/SceneVfxService.d.ts +27 -0
  4. package/dist/chunks/legacy-particle-runtime-CbJYVxdd.js +75 -0
  5. package/dist/chunks/manifestRuntimePackage-CXQFSTo2.js +356 -0
  6. package/dist/chunks/rendering-CV3nhygX.js +13 -0
  7. package/dist/chunks/space-shared-BXV1hc0k.js +124 -0
  8. package/dist/chunks/wood-sawdust-effect-factory-DlETNaBn.js +129 -0
  9. package/dist/effects/building-upgrade/effect.json.d.ts +9 -0
  10. package/dist/effects/building-upgrade/index.d.ts +20 -0
  11. package/dist/effects/building-upgrade/index.js +337 -0
  12. package/dist/effects/character-entrance/effect.json.d.ts +9 -0
  13. package/dist/effects/character-entrance/index.d.ts +18 -0
  14. package/dist/effects/character-entrance/index.js +271 -0
  15. package/dist/effects/coin-burst/index.d.ts +6 -0
  16. package/dist/effects/coin-burst/index.js +45 -0
  17. package/dist/effects/comet-trail-flame/index.d.ts +11 -0
  18. package/dist/effects/comet-trail-flame/index.js +103 -0
  19. package/dist/effects/conveyor-upgrade/effect.json.d.ts +9 -0
  20. package/dist/effects/conveyor-upgrade/index.d.ts +20 -0
  21. package/dist/effects/conveyor-upgrade/index.js +349 -0
  22. package/dist/effects/debris-smoke/index.d.ts +10 -0
  23. package/dist/effects/debris-smoke/index.js +108 -0
  24. package/dist/effects/door_open_gold_flakes/door_open_gold_flakes.json.d.ts +501 -0
  25. package/dist/effects/door_open_gold_flakes/index.d.ts +1 -0
  26. package/dist/effects/door_open_gold_flakes/index.js +524 -0
  27. package/dist/effects/electric-arc/index.d.ts +8 -0
  28. package/dist/effects/electric-arc/index.js +71 -0
  29. package/dist/effects/energy-shield/index.d.ts +46 -0
  30. package/dist/effects/energy-shield/index.js +365 -0
  31. package/dist/effects/explosion/index.d.ts +11 -0
  32. package/dist/effects/explosion/index.js +129 -0
  33. package/dist/effects/ground-tile-upgrade/effect.json.d.ts +9 -0
  34. package/dist/effects/ground-tile-upgrade/index.d.ts +20 -0
  35. package/dist/effects/ground-tile-upgrade/index.js +357 -0
  36. package/dist/effects/hit-flash/index.d.ts +8 -0
  37. package/dist/effects/hit-flash/index.js +71 -0
  38. package/dist/effects/laser-beam/index.d.ts +1 -0
  39. package/dist/effects/laser-beam/index.js +152 -0
  40. package/dist/effects/laser-beam-factory.d.ts +12 -0
  41. package/dist/effects/lumber-cart-suction/effect.json.d.ts +9 -0
  42. package/dist/effects/lumber-cart-suction/index.d.ts +26 -0
  43. package/dist/effects/lumber-cart-suction/index.js +322 -0
  44. package/dist/effects/lumber-debris-scatter/effect.json.d.ts +231 -0
  45. package/dist/effects/lumber-debris-scatter/index.d.ts +20 -0
  46. package/dist/effects/lumber-debris-scatter/index.js +637 -0
  47. package/dist/effects/lumber_vehicle_gear_spin/index.d.ts +1 -0
  48. package/dist/effects/lumber_vehicle_gear_spin/index.js +363 -0
  49. package/dist/effects/lumber_vehicle_gear_spin/lumber_vehicle_gear_spin.json.d.ts +341 -0
  50. package/dist/effects/lumber_vehicle_upgrade_aura/index.d.ts +1 -0
  51. package/dist/effects/lumber_vehicle_upgrade_aura/index.js +391 -0
  52. package/dist/effects/lumber_vehicle_upgrade_aura/lumber_vehicle_upgrade_aura.json.d.ts +368 -0
  53. package/dist/effects/lumber_vehicle_wood_chips/index.d.ts +1 -0
  54. package/dist/effects/lumber_vehicle_wood_chips/index.js +360 -0
  55. package/dist/effects/lumber_vehicle_wood_chips/lumber_vehicle_wood_chips.json.d.ts +338 -0
  56. package/dist/effects/monster-hit/index.d.ts +15 -0
  57. package/dist/effects/monster-hit/index.js +156 -0
  58. package/dist/effects/player-upgrade/effect.json.d.ts +9 -0
  59. package/dist/effects/player-upgrade/index.d.ts +24 -0
  60. package/dist/effects/player-upgrade/index.js +539 -0
  61. package/dist/effects/pulse-laser-volley/index.d.ts +17 -0
  62. package/dist/effects/pulse-laser-volley/index.js +173 -0
  63. package/dist/effects/resource-collect-sparkles/effect.json.d.ts +9 -0
  64. package/dist/effects/resource-collect-sparkles/index.d.ts +21 -0
  65. package/dist/effects/resource-collect-sparkles/index.js +222 -0
  66. package/dist/effects/run-footstep-dust/effect.json.d.ts +186 -0
  67. package/dist/effects/run-footstep-dust/index.d.ts +23 -0
  68. package/dist/effects/run-footstep-dust/index.js +343 -0
  69. package/dist/effects/space-shared.d.ts +44 -0
  70. package/dist/effects/thruster-flame/index.d.ts +15 -0
  71. package/dist/effects/thruster-flame/index.js +301 -0
  72. package/dist/effects/tree-chop-dust/effect.json.d.ts +11 -0
  73. package/dist/effects/tree-chop-dust/index.d.ts +17 -0
  74. package/dist/effects/tree-chop-dust/index.js +165 -0
  75. package/dist/effects/tree-leaf-chop-burst/index.d.ts +19 -0
  76. package/dist/effects/tree-leaf-chop-burst/index.js +219 -0
  77. package/dist/effects/tree_chop_dust_burst/index.d.ts +1 -0
  78. package/dist/effects/tree_chop_dust_burst/index.js +443 -0
  79. package/dist/effects/tree_chop_dust_burst/tree_chop_dust_burst.json.d.ts +415 -0
  80. package/dist/effects/ufo-thread-flame/index.d.ts +21 -0
  81. package/dist/effects/ufo-thread-flame/index.js +140 -0
  82. package/dist/effects/vehicle-exhaust-smoke/effect.json.d.ts +11 -0
  83. package/dist/effects/vehicle-exhaust-smoke/index.d.ts +19 -0
  84. package/dist/effects/vehicle-exhaust-smoke/index.js +242 -0
  85. package/dist/effects/vehicle-upgrade/effect.json.d.ts +9 -0
  86. package/dist/effects/vehicle-upgrade/index.d.ts +20 -0
  87. package/dist/effects/vehicle-upgrade/index.js +349 -0
  88. package/dist/effects/weapon-trail/index.d.ts +26 -0
  89. package/dist/effects/weapon-trail/index.js +351 -0
  90. package/dist/effects/wood-crusher-sawdust/index.d.ts +2 -0
  91. package/dist/effects/wood-crusher-sawdust/index.js +648 -0
  92. package/dist/effects/wood-crusher-sawdust/wood_crusher_sawdust.json.d.ts +595 -0
  93. package/dist/effects/wood-cutter-sawdust/index.d.ts +2 -0
  94. package/dist/effects/wood-cutter-sawdust/index.js +648 -0
  95. package/dist/effects/wood-cutter-sawdust/wood_cutter_sawdust.json.d.ts +595 -0
  96. package/dist/effects/wood-sawdust-effect-factory.d.ts +36 -0
  97. package/dist/effects/wood_crusher_sawdust/index.d.ts +16 -0
  98. package/dist/effects/wood_crusher_sawdust/index.js +634 -0
  99. package/dist/effects/wood_crusher_sawdust/wood_crusher_sawdust.json.d.ts +595 -0
  100. package/dist/effects/wood_cutter_sawdust/index.d.ts +16 -0
  101. package/dist/effects/wood_cutter_sawdust/index.js +634 -0
  102. package/dist/effects/wood_cutter_sawdust/wood_cutter_sawdust.json.d.ts +595 -0
  103. package/dist/effects/wood_peel_material_test/index.d.ts +1 -0
  104. package/dist/effects/wood_peel_material_test/index.js +157 -0
  105. package/dist/effects/wood_peel_material_test/wood_peel_material_test.json.d.ts +139 -0
  106. package/dist/generation.d.ts +7 -0
  107. package/dist/index.d.ts +8 -0
  108. package/dist/index.js +309 -0
  109. package/dist/legacy-particle-runtime.d.ts +30 -0
  110. package/dist/manifestRuntimePackage.d.ts +68 -0
  111. package/dist/registry.d.ts +20 -0
  112. package/dist/rendering.d.ts +5 -0
  113. package/dist/types.d.ts +83 -0
  114. package/docs/AUTHORING_EFFECTS.md +297 -0
  115. package/docs/VFX_LIBRARY_ARCHITECTURE_chatgpt.md +1580 -0
  116. package/docs/VFX_LIBRARY_EXECUTION_PLAN.md +229 -0
  117. package/docs/VFX_LIBRARY_PLAN.md +546 -0
  118. package/docs/vfx-ab/RESULTS.md +35 -0
  119. package/docs/vfx-ab/lumber-order/vehicle-exhaust-smoke/after.png +0 -0
  120. package/docs/vfx-ab/lumber-order/vehicle-exhaust-smoke/before.png +0 -0
  121. package/docs/vfx-ab/lumber-truck/vehicle-exhaust-smoke/after.png +0 -0
  122. package/docs/vfx-ab/lumber-truck/vehicle-exhaust-smoke/before.png +0 -0
  123. package/docs/vfx-integration_chatgpt.md +462 -0
  124. package/docs/weapon-trail-visualization.html +241 -0
  125. package/index.json +381 -0
  126. package/package.json +51 -0
  127. package/packages/EffectPackageService.ts +240 -0
  128. package/packages/SceneVfxService.ts +96 -0
  129. package/packages/build.mesh.yellow_build_upgrade_indicator/assets/runtime/simpleMeshEffect.v1.js +333 -0
  130. package/packages/build.mesh.yellow_build_upgrade_indicator/assets/shaders/mesh-effect-preview.frag.glsl +25 -0
  131. package/packages/build.mesh.yellow_build_upgrade_indicator/assets/shaders/mesh-effect-preview.vert.glsl +11 -0
  132. package/packages/build.mesh.yellow_build_upgrade_indicator/assets/textures/effect_jianbian.png +0 -0
  133. package/packages/build.mesh.yellow_build_upgrade_indicator/effect.json +927 -0
  134. package/packages/build.mesh.yellow_build_upgrade_indicator/media/contact-sheet.png +0 -0
  135. package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.gif +0 -0
  136. package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.mp4 +0 -0
  137. package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.webm +0 -0
  138. package/packages/build.mesh.yellow_build_upgrade_indicator/media/thumbnail.png +0 -0
  139. package/packages/build.mesh.yellow_build_upgrade_indicator/metadata/description.json +197 -0
  140. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/03-effect.original.json +895 -0
  141. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/03-normalized-vfx-to-babylon-report.json +241 -0
  142. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/04-preview-overrides.json +542 -0
  143. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/04-preview-tuning-report.json +69 -0
  144. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/asset-map.json +125 -0
  145. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/lineage.json +44 -0
  146. package/packages/build.particle.golden_upgrade_starburst/assets/runtime/particleEmitter.v1.js +210 -0
  147. package/packages/build.particle.golden_upgrade_starburst/assets/textures/effect_guangdian.png +0 -0
  148. package/packages/build.particle.golden_upgrade_starburst/effect.json +880 -0
  149. package/packages/build.particle.golden_upgrade_starburst/media/contact-sheet.png +0 -0
  150. package/packages/build.particle.golden_upgrade_starburst/media/preview.gif +0 -0
  151. package/packages/build.particle.golden_upgrade_starburst/media/preview.mp4 +0 -0
  152. package/packages/build.particle.golden_upgrade_starburst/media/preview.webm +0 -0
  153. package/packages/build.particle.golden_upgrade_starburst/media/thumbnail.png +0 -0
  154. package/packages/build.particle.golden_upgrade_starburst/metadata/description.json +161 -0
  155. package/packages/build.particle.golden_upgrade_starburst/provenance/03-effect.original.json +762 -0
  156. package/packages/build.particle.golden_upgrade_starburst/provenance/03-normalized-vfx-to-babylon-report.json +260 -0
  157. package/packages/build.particle.golden_upgrade_starburst/provenance/04-preview-overrides.json +436 -0
  158. package/packages/build.particle.golden_upgrade_starburst/provenance/04-preview-tuning-report.json +40 -0
  159. package/packages/build.particle.golden_upgrade_starburst/provenance/asset-map.json +115 -0
  160. package/packages/build.particle.golden_upgrade_starburst/provenance/lineage.json +40 -0
  161. package/packages/build.particle.orange_upgrade_transform_sparks/assets/runtime/particleEmitter.v1.js +210 -0
  162. package/packages/build.particle.orange_upgrade_transform_sparks/assets/textures/b5b27ab1-e740-4398-b407-848fc2b2c897.png +0 -0
  163. package/packages/build.particle.orange_upgrade_transform_sparks/effect.json +887 -0
  164. package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.gif +0 -0
  165. package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.mp4 +0 -0
  166. package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.webm +0 -0
  167. package/packages/build.particle.orange_upgrade_transform_sparks/media/thumbnail.png +0 -0
  168. package/packages/build.particle.orange_upgrade_transform_sparks/metadata/description.json +179 -0
  169. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/03-effect.original.json +859 -0
  170. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/03-normalized-vfx-to-babylon-report.json +260 -0
  171. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/04-preview-overrides.json +478 -0
  172. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/04-preview-tuning-report.json +40 -0
  173. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/asset-map.json +114 -0
  174. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/lineage.json +41 -0
  175. package/packages/build.particle.wood_chip_dust_burst/assets/runtime/particleEmitter.v1.js +210 -0
  176. package/packages/build.particle.wood_chip_dust_burst/assets/textures/effect_yanwu4.png +0 -0
  177. package/packages/build.particle.wood_chip_dust_burst/assets/textures/suipian3.png +0 -0
  178. package/packages/build.particle.wood_chip_dust_burst/effect.json +1400 -0
  179. package/packages/build.particle.wood_chip_dust_burst/media/contact-sheet.png +0 -0
  180. package/packages/build.particle.wood_chip_dust_burst/media/preview.gif +0 -0
  181. package/packages/build.particle.wood_chip_dust_burst/media/preview.mp4 +0 -0
  182. package/packages/build.particle.wood_chip_dust_burst/media/preview.webm +0 -0
  183. package/packages/build.particle.wood_chip_dust_burst/media/thumbnail.png +0 -0
  184. package/packages/build.particle.wood_chip_dust_burst/metadata/description.json +173 -0
  185. package/packages/build.particle.wood_chip_dust_burst/provenance/03-effect.original.json +1277 -0
  186. package/packages/build.particle.wood_chip_dust_burst/provenance/03-normalized-vfx-to-babylon-report.json +329 -0
  187. package/packages/build.particle.wood_chip_dust_burst/provenance/04-preview-overrides.json +749 -0
  188. package/packages/build.particle.wood_chip_dust_burst/provenance/04-preview-tuning-report.json +60 -0
  189. package/packages/build.particle.wood_chip_dust_burst/provenance/asset-map.json +146 -0
  190. package/packages/build.particle.wood_chip_dust_burst/provenance/lineage.json +69 -0
  191. package/packages/effects/building-upgrade/effect.json +6 -0
  192. package/packages/effects/building-upgrade/index.ts +387 -0
  193. package/packages/effects/building-upgrade/vfx-params.json +24 -0
  194. package/packages/effects/character-entrance/effect.json +6 -0
  195. package/packages/effects/character-entrance/index.ts +308 -0
  196. package/packages/effects/character-entrance/vfx-params.json +24 -0
  197. package/packages/effects/coin-burst/index.ts +43 -0
  198. package/packages/effects/coin-burst/vfx-params.json +5 -0
  199. package/packages/effects/comet-trail-flame/assets/textures/trail_5x4.webp +0 -0
  200. package/packages/effects/comet-trail-flame/index.ts +106 -0
  201. package/packages/effects/comet-trail-flame/vfx-params.json +5 -0
  202. package/packages/effects/conveyor-upgrade/effect.json +6 -0
  203. package/packages/effects/conveyor-upgrade/index.ts +401 -0
  204. package/packages/effects/conveyor-upgrade/vfx-params.json +21 -0
  205. package/packages/effects/debris-smoke/assets/models/rock_debris.glb +0 -0
  206. package/packages/effects/debris-smoke/assets/textures/smoke22.webp +0 -0
  207. package/packages/effects/debris-smoke/index.ts +101 -0
  208. package/packages/effects/debris-smoke/vfx-params.json +5 -0
  209. package/packages/effects/door_open_gold_flakes/assets/runtime/goldFlakes.v1.js +397 -0
  210. package/packages/effects/door_open_gold_flakes/door_open_gold_flakes.json +498 -0
  211. package/packages/effects/door_open_gold_flakes/index.ts +11 -0
  212. package/packages/effects/door_open_gold_flakes/vfx-params.json +23 -0
  213. package/packages/effects/electric-arc/assets/textures/spark_4x4.webp +0 -0
  214. package/packages/effects/electric-arc/index.ts +62 -0
  215. package/packages/effects/electric-arc/vfx-params.json +5 -0
  216. package/packages/effects/energy-shield/effect.json +7 -0
  217. package/packages/effects/energy-shield/index.ts +431 -0
  218. package/packages/effects/energy-shield/vfx-params.json +29 -0
  219. package/packages/effects/explosion/assets/textures/baozha29.webp +0 -0
  220. package/packages/effects/explosion/assets/textures/glow01.webp +0 -0
  221. package/packages/effects/explosion/assets/textures/lizi01.webp +0 -0
  222. package/packages/effects/explosion/assets/textures/xulie_lizibaozha02_5x5.webp +0 -0
  223. package/packages/effects/explosion/index.ts +114 -0
  224. package/packages/effects/explosion/vfx-params.json +5 -0
  225. package/packages/effects/ground-tile-upgrade/effect.json +6 -0
  226. package/packages/effects/ground-tile-upgrade/index.ts +410 -0
  227. package/packages/effects/ground-tile-upgrade/vfx-params.json +21 -0
  228. package/packages/effects/hit-flash/index.ts +69 -0
  229. package/packages/effects/hit-flash/vfx-params.json +5 -0
  230. package/packages/effects/laser-beam/assets/textures/laser_glow.webp +0 -0
  231. package/packages/effects/laser-beam/assets/textures/laser_noise.webp +0 -0
  232. package/packages/effects/laser-beam/index.ts +6 -0
  233. package/packages/effects/laser-beam/vfx-params.json +5 -0
  234. package/packages/effects/laser-beam-factory.ts +135 -0
  235. package/packages/effects/lumber-cart-suction/effect.json +6 -0
  236. package/packages/effects/lumber-cart-suction/index.ts +399 -0
  237. package/packages/effects/lumber-cart-suction/vfx-params.json +30 -0
  238. package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb +0 -0
  239. package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb.versions/.active +1 -0
  240. package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb.versions/1781589063890_upload.glb +0 -0
  241. package/packages/effects/lumber-debris-scatter/assets/runtime/solidParticleScatter.v1.js +236 -0
  242. package/packages/effects/lumber-debris-scatter/effect.json +228 -0
  243. package/packages/effects/lumber-debris-scatter/index.ts +780 -0
  244. package/packages/effects/lumber-debris-scatter/vfx-params.json +19 -0
  245. package/packages/effects/lumber_vehicle_gear_spin/assets/runtime/gearSpin.v1.js +202 -0
  246. package/packages/effects/lumber_vehicle_gear_spin/index.ts +11 -0
  247. package/packages/effects/lumber_vehicle_gear_spin/lumber_vehicle_gear_spin.json +338 -0
  248. package/packages/effects/lumber_vehicle_gear_spin/vfx-params.json +21 -0
  249. package/packages/effects/lumber_vehicle_upgrade_aura/assets/runtime/upgradeAura.v1.js +353 -0
  250. package/packages/effects/lumber_vehicle_upgrade_aura/index.ts +11 -0
  251. package/packages/effects/lumber_vehicle_upgrade_aura/lumber_vehicle_upgrade_aura.json +365 -0
  252. package/packages/effects/lumber_vehicle_upgrade_aura/vfx-params.json +15 -0
  253. package/packages/effects/lumber_vehicle_wood_chips/assets/runtime/solidParticleScatter.v1.js +310 -0
  254. package/packages/effects/lumber_vehicle_wood_chips/index.ts +11 -0
  255. package/packages/effects/lumber_vehicle_wood_chips/lumber_vehicle_wood_chips.json +335 -0
  256. package/packages/effects/lumber_vehicle_wood_chips/vfx-params.json +11 -0
  257. package/packages/effects/monster-hit/index.ts +128 -0
  258. package/packages/effects/monster-hit/vfx-params.json +5 -0
  259. package/packages/effects/player-upgrade/effect.json +6 -0
  260. package/packages/effects/player-upgrade/index.ts +635 -0
  261. package/packages/effects/player-upgrade/vfx-params.json +28 -0
  262. package/packages/effects/pulse-laser-volley/assets/textures/bolt_guangshu.webp +0 -0
  263. package/packages/effects/pulse-laser-volley/index.ts +204 -0
  264. package/packages/effects/pulse-laser-volley/vfx-params.json +5 -0
  265. package/packages/effects/resource-collect-sparkles/effect.json +6 -0
  266. package/packages/effects/resource-collect-sparkles/index.ts +254 -0
  267. package/packages/effects/resource-collect-sparkles/vfx-params.json +25 -0
  268. package/packages/effects/run-footstep-dust/assets/runtime/runFootstepDust.v1.js +215 -0
  269. package/packages/effects/run-footstep-dust/effect.json +183 -0
  270. package/packages/effects/run-footstep-dust/index.ts +377 -0
  271. package/packages/effects/run-footstep-dust/vfx-params.json +27 -0
  272. package/packages/effects/space-shared.ts +120 -0
  273. package/packages/effects/thruster-flame/index.ts +305 -0
  274. package/packages/effects/thruster-flame/vfx-params.json +5 -0
  275. package/packages/effects/tree-chop-dust/assets/textures/tree_chop_dust_atlas.png +0 -0
  276. package/packages/effects/tree-chop-dust/effect.json +8 -0
  277. package/packages/effects/tree-chop-dust/index.ts +202 -0
  278. package/packages/effects/tree-chop-dust/vfx-params.json +21 -0
  279. package/packages/effects/tree-leaf-chop-burst/assets/runtime/particleEmitter.v1.js +303 -0
  280. package/packages/effects/tree-leaf-chop-burst/assets/textures/tree_leaf_chop_burst_leaf_atlas.png +0 -0
  281. package/packages/effects/tree-leaf-chop-burst/effect.json +498 -0
  282. package/packages/effects/tree-leaf-chop-burst/index.ts +294 -0
  283. package/packages/effects/tree-leaf-chop-burst/vfx-params.json +27 -0
  284. package/packages/effects/tree_chop_dust_burst/assets/runtime/particleEmitter.v1.js +318 -0
  285. package/packages/effects/tree_chop_dust_burst/assets/textures/tree_chop_dust_burst_dust.png +0 -0
  286. package/packages/effects/tree_chop_dust_burst/index.ts +13 -0
  287. package/packages/effects/tree_chop_dust_burst/tree_chop_dust_burst.json +412 -0
  288. package/packages/effects/tree_chop_dust_burst/vfx-params.json +9 -0
  289. package/packages/effects/ufo-thread-flame/assets/textures/flame_flow.webp +0 -0
  290. package/packages/effects/ufo-thread-flame/assets/textures/flame_spike.webp +0 -0
  291. package/packages/effects/ufo-thread-flame/index.ts +152 -0
  292. package/packages/effects/ufo-thread-flame/vfx-params.json +5 -0
  293. package/packages/effects/vehicle-exhaust-smoke/assets/textures/vehicle_exhaust_smoke_atlas.png +0 -0
  294. package/packages/effects/vehicle-exhaust-smoke/effect.json +8 -0
  295. package/packages/effects/vehicle-exhaust-smoke/index.ts +298 -0
  296. package/packages/effects/vehicle-exhaust-smoke/vfx-params.json +23 -0
  297. package/packages/effects/vehicle-upgrade/effect.json +6 -0
  298. package/packages/effects/vehicle-upgrade/index.ts +401 -0
  299. package/packages/effects/vehicle-upgrade/vfx-params.json +21 -0
  300. package/packages/effects/weapon-trail/assets/textures/trail_wedge.png +0 -0
  301. package/packages/effects/weapon-trail/index.ts +313 -0
  302. package/packages/effects/weapon-trail/vfx-params.json +5 -0
  303. package/packages/effects/wood-crusher-sawdust/assets/runtime/particleEmitter.v1.js +312 -0
  304. package/packages/effects/wood-crusher-sawdust/assets/textures/wood_crusher_sawdust_dust.png +0 -0
  305. package/packages/effects/wood-crusher-sawdust/assets/textures/wood_crusher_sawdust_fiber.png +0 -0
  306. package/packages/effects/wood-crusher-sawdust/index.ts +43 -0
  307. package/packages/effects/wood-crusher-sawdust/vfx-params.json +24 -0
  308. package/packages/effects/wood-crusher-sawdust/wood_crusher_sawdust.json +592 -0
  309. package/packages/effects/wood-cutter-sawdust/assets/runtime/particleEmitter.v1.js +312 -0
  310. package/packages/effects/wood-cutter-sawdust/assets/textures/wood_cutter_sawdust_chip.png +0 -0
  311. package/packages/effects/wood-cutter-sawdust/assets/textures/wood_cutter_sawdust_dust.png +0 -0
  312. package/packages/effects/wood-cutter-sawdust/index.ts +43 -0
  313. package/packages/effects/wood-cutter-sawdust/vfx-params.json +24 -0
  314. package/packages/effects/wood-cutter-sawdust/wood_cutter_sawdust.json +592 -0
  315. package/packages/effects/wood-sawdust-effect-factory.ts +194 -0
  316. package/packages/effects/wood_crusher_sawdust/assets/runtime/particleEmitter.v1.js +318 -0
  317. package/packages/effects/wood_crusher_sawdust/assets/textures/wood_crusher_sawdust_dust.png +0 -0
  318. package/packages/effects/wood_crusher_sawdust/assets/textures/wood_crusher_sawdust_fiber.png +0 -0
  319. package/packages/effects/wood_crusher_sawdust/index.ts +29 -0
  320. package/packages/effects/wood_crusher_sawdust/vfx-params.json +14 -0
  321. package/packages/effects/wood_crusher_sawdust/wood_crusher_sawdust.json +592 -0
  322. package/packages/effects/wood_cutter_sawdust/assets/runtime/particleEmitter.v1.js +318 -0
  323. package/packages/effects/wood_cutter_sawdust/assets/textures/wood_cutter_sawdust_chip.png +0 -0
  324. package/packages/effects/wood_cutter_sawdust/assets/textures/wood_cutter_sawdust_dust.png +0 -0
  325. package/packages/effects/wood_cutter_sawdust/index.ts +29 -0
  326. package/packages/effects/wood_cutter_sawdust/vfx-params.json +14 -0
  327. package/packages/effects/wood_cutter_sawdust/wood_cutter_sawdust.json +592 -0
  328. package/packages/effects/wood_peel_material_test/assets/runtime/woodPeelMaterialTest.v1.js +196 -0
  329. package/packages/effects/wood_peel_material_test/index.ts +11 -0
  330. package/packages/effects/wood_peel_material_test/vfx-params.json +9 -0
  331. package/packages/effects/wood_peel_material_test/wood_peel_material_test.json +136 -0
  332. package/packages/env.particle.forest_edge_fog/assets/runtime/particleEmitter.v1.js +210 -0
  333. package/packages/env.particle.forest_edge_fog/assets/textures/f12a23c4-b924-4322-a260-3d982428f1e8.png +0 -0
  334. package/packages/env.particle.forest_edge_fog/assets/textures/yuan.png +0 -0
  335. package/packages/env.particle.forest_edge_fog/effect.json +854 -0
  336. package/packages/env.particle.forest_edge_fog/media/preview.gif +0 -0
  337. package/packages/env.particle.forest_edge_fog/media/preview.mp4 +0 -0
  338. package/packages/env.particle.forest_edge_fog/media/preview.webm +0 -0
  339. package/packages/env.particle.forest_edge_fog/media/thumbnail.png +0 -0
  340. package/packages/env.particle.forest_edge_fog/metadata/description.json +148 -0
  341. package/packages/env.particle.forest_edge_fog/provenance/03-effect.original.json +827 -0
  342. package/packages/env.particle.forest_edge_fog/provenance/03-normalized-vfx-to-babylon-report.json +196 -0
  343. package/packages/env.particle.forest_edge_fog/provenance/04-preview-overrides.json +432 -0
  344. package/packages/env.particle.forest_edge_fog/provenance/04-preview-tuning-report.json +28 -0
  345. package/packages/env.particle.forest_edge_fog/provenance/asset-map.json +124 -0
  346. package/packages/env.particle.forest_edge_fog/provenance/lineage.json +41 -0
  347. package/packages/generation.ts +14 -0
  348. package/packages/index.ts +14 -0
  349. package/packages/legacy-particle-runtime.ts +113 -0
  350. package/packages/manifestRuntimePackage.ts +519 -0
  351. package/packages/registry.ts +85 -0
  352. package/packages/rendering.ts +13 -0
  353. package/packages/resource.particle.viscous_oil_suction/assets/runtime/top_disk_suction/particleEmitter.v1.js +424 -0
  354. package/packages/resource.particle.viscous_oil_suction/assets/textures/Glow ad.png +0 -0
  355. package/packages/resource.particle.viscous_oil_suction/effect.json +1254 -0
  356. package/packages/resource.particle.viscous_oil_suction/media/preview.gif +0 -0
  357. package/packages/resource.particle.viscous_oil_suction/media/preview.mp4 +0 -0
  358. package/packages/resource.particle.viscous_oil_suction/media/preview.webm +0 -0
  359. package/packages/resource.particle.viscous_oil_suction/media/thumbnail.png +0 -0
  360. package/packages/resource.particle.viscous_oil_suction/metadata/description.json +122 -0
  361. package/packages/resource.particle.viscous_oil_suction/provenance/03-effect.original.json +1051 -0
  362. package/packages/resource.particle.viscous_oil_suction/provenance/03-normalized-vfx-to-babylon-report.json +200 -0
  363. package/packages/resource.particle.viscous_oil_suction/provenance/04-preview-overrides.json +581 -0
  364. package/packages/resource.particle.viscous_oil_suction/provenance/04-preview-tuning-report.json +28 -0
  365. package/packages/resource.particle.viscous_oil_suction/provenance/asset-map.json +111 -0
  366. package/packages/resource.particle.viscous_oil_suction/provenance/lineage.json +45 -0
  367. package/packages/types.ts +107 -0
  368. package/tooling/check-dist-runtime.mjs +166 -0
  369. package/tooling/generate-index.mjs +55 -0
  370. package/tooling/test-guardrails.mjs +157 -0
  371. package/tooling/validate-boundary.mjs +92 -0
  372. package/tooling/validate-effects.mjs +304 -0
  373. package/tooling/validate.mjs +53 -0
  374. package/tooling/vfx-cli.mjs +232 -0
  375. package/tooling/vfx-package-resolution.mjs +28 -0
@@ -0,0 +1,68 @@
1
+ import { VfxEffectPackage } from './types';
2
+ type LegacyTunableParamType = 'number' | 'color' | 'enum' | string;
3
+ interface LegacyTunableTarget {
4
+ emitter: string;
5
+ property: string;
6
+ operator?: string;
7
+ defaultValue?: unknown;
8
+ }
9
+ interface LegacyTunableParam {
10
+ key: string;
11
+ label?: string;
12
+ labelEn?: string;
13
+ labelZh?: string;
14
+ type: LegacyTunableParamType;
15
+ default?: unknown;
16
+ min?: number;
17
+ max?: number;
18
+ step?: number;
19
+ options?: Array<{
20
+ value: string;
21
+ label?: string;
22
+ }>;
23
+ target?: LegacyTunableTarget;
24
+ targets?: LegacyTunableTarget[];
25
+ }
26
+ interface LegacyEmitterConfig {
27
+ name: string;
28
+ enabled?: boolean;
29
+ runtime?: {
30
+ adapter?: string;
31
+ stopAfterSeconds?: number;
32
+ disposeOnComplete?: boolean;
33
+ };
34
+ [key: string]: unknown;
35
+ }
36
+ interface LegacyRuntimeAdapterConfig {
37
+ id: string;
38
+ entry: string;
39
+ moduleFormat?: string;
40
+ exports?: string[];
41
+ }
42
+ interface LegacyEffectManifest {
43
+ id?: string;
44
+ name?: {
45
+ en?: string;
46
+ zh?: string;
47
+ };
48
+ assets?: Record<string, unknown> | unknown[];
49
+ source?: unknown;
50
+ emitters?: LegacyEmitterConfig[];
51
+ runtime?: {
52
+ driver?: string;
53
+ adapters?: LegacyRuntimeAdapterConfig[];
54
+ };
55
+ tunableParams?: LegacyTunableParam[];
56
+ defaultParams?: Record<string, unknown>;
57
+ debug?: {
58
+ playAnchor?: string;
59
+ livePreview?: boolean;
60
+ };
61
+ }
62
+ export interface ManifestRuntimeEffectPackageOptions {
63
+ id: string;
64
+ manifest: LegacyEffectManifest;
65
+ assetUrls: Record<string, string>;
66
+ }
67
+ export declare function createManifestRuntimeEffectPackage(options: ManifestRuntimeEffectPackageOptions): VfxEffectPackage;
68
+ export {};
@@ -0,0 +1,20 @@
1
+ import { VfxEffectPackage, VfxParamValues } from './types';
2
+ export interface VfxRegistry {
3
+ getEffectPackage(effectId: string): VfxEffectPackage | undefined;
4
+ getEffectPackages(): VfxEffectPackage[];
5
+ savedParams: Record<string, Partial<VfxParamValues>>;
6
+ }
7
+ export interface BuildRegistryInput {
8
+ /** import.meta.glob('./effects/*\/index.ts', { eager: true }) 的结果 */
9
+ modules: Record<string, Record<string, unknown>>;
10
+ /** import.meta.glob('./effects/*\/vfx-params.json', { eager: true }) 的结果(可选) */
11
+ params?: Record<string, {
12
+ default: unknown;
13
+ } | unknown>;
14
+ /** 可选:判定某目录是否仅调试用(prod 构建剔除) */
15
+ isDebugOnly?: (dir: string) => boolean;
16
+ /** 可选:prod 标志,配合 isDebugOnly 过滤 */
17
+ prod?: boolean;
18
+ }
19
+ export declare function isVfxEffectPackage(value: unknown): value is VfxEffectPackage;
20
+ export declare function buildRegistry(input: BuildRegistryInput): VfxRegistry;
@@ -0,0 +1,5 @@
1
+ import { ParticleSystem } from '@babylonjs/core/Particles/particleSystem';
2
+ import { SpriteManager } from '@babylonjs/core/Sprites/spriteManager';
3
+ export declare const VFX_RENDERING_GROUP_ID = 2;
4
+ export declare function configureVfxSpriteManager(manager: SpriteManager): void;
5
+ export declare function configureVfxParticleSystem(system: ParticleSystem): void;
@@ -0,0 +1,83 @@
1
+ import { Scene } from '@babylonjs/core/scene';
2
+ import { Vector3 } from '@babylonjs/core/Maths/math.vector';
3
+ import { TransformNode } from '@babylonjs/core/Meshes/transformNode';
4
+ export type VfxDebugAnchor = 'playerRight' | 'player';
5
+ export type VfxParamValue = number | string | VfxColorValue;
6
+ export type VfxParamValues = Record<string, VfxParamValue>;
7
+ export interface VfxColorValue {
8
+ r: number;
9
+ g: number;
10
+ b: number;
11
+ }
12
+ export type VfxParamKind = 'number' | 'color' | 'enum' | 'opacity' | 'lifetime' | 'scale';
13
+ export interface VfxParamDefinitionBase {
14
+ key: string;
15
+ label: string;
16
+ kind: VfxParamKind;
17
+ description?: string;
18
+ }
19
+ export interface VfxNumberParamDefinition extends VfxParamDefinitionBase {
20
+ kind: 'number' | 'opacity' | 'lifetime' | 'scale';
21
+ min?: number;
22
+ max?: number;
23
+ step?: number;
24
+ }
25
+ export interface VfxColorParamDefinition extends VfxParamDefinitionBase {
26
+ kind: 'color';
27
+ }
28
+ export interface VfxEnumParamOption {
29
+ value: string;
30
+ label: string;
31
+ }
32
+ export interface VfxEnumParamDefinition extends VfxParamDefinitionBase {
33
+ kind: 'enum';
34
+ options: VfxEnumParamOption[];
35
+ }
36
+ export type VfxParamDefinition = VfxNumberParamDefinition | VfxColorParamDefinition | VfxEnumParamDefinition;
37
+ export interface VfxEffectPackageContext<PParams extends VfxParamValues = VfxParamValues> {
38
+ scene: Scene;
39
+ root: TransformNode;
40
+ position: Vector3;
41
+ rotationY: number;
42
+ renderingGroupId?: number;
43
+ params: PParams;
44
+ }
45
+ export interface VfxEffectHandle {
46
+ root: TransformNode;
47
+ ready?: Promise<void>;
48
+ dispose(): void;
49
+ }
50
+ export interface VfxEffectManifest {
51
+ id: string;
52
+ nameZh: string;
53
+ assets?: string[];
54
+ source?: string;
55
+ }
56
+ export interface VfxSpawnParamKeys {
57
+ offsetX?: string;
58
+ offsetY?: string;
59
+ offsetZ?: string;
60
+ }
61
+ export interface VfxSpawnTransform {
62
+ position?: Vector3;
63
+ rotationY?: number;
64
+ renderingGroupId?: number;
65
+ }
66
+ export interface VfxParamsFile {
67
+ schemaVersion: string;
68
+ effectId?: string;
69
+ updatedAt?: string | null;
70
+ params?: Partial<VfxParamValues>;
71
+ }
72
+ export interface VfxEffectPackage<PParams extends VfxParamValues = VfxParamValues> {
73
+ id: string;
74
+ nameZh: string;
75
+ manifest?: VfxEffectManifest;
76
+ defaultParams: PParams;
77
+ debugAnchor?: VfxDebugAnchor;
78
+ spawnParams?: VfxSpawnParamKeys;
79
+ savedParams?: Partial<VfxParamValues>;
80
+ debugParams: VfxParamDefinition[];
81
+ create(context: VfxEffectPackageContext<PParams>): VfxEffectHandle;
82
+ }
83
+ export type VfxDebugOverrides = Record<string, Partial<VfxParamValues>>;
@@ -0,0 +1,297 @@
1
+ # 如何制作一个 VFX 特效(@fps/vfx 作者指南)
2
+
3
+ 面向在 `fps-vfx-library` 里**新增/修改特效**的人(human 或 coding agent)。读完你能从零写出一个能被项目导入、能在 DEV 调试面板里调参的特效。
4
+
5
+ 配套:运行手册见 `.claude/skills/vfx-library-maintenance/`;库总设计见 issue #1 / `docs/VFX_LIBRARY_PLAN.md`;参数运转的代码细节见本文 §5。
6
+
7
+ ---
8
+
9
+ ## 0. 核心概念:一个特效 = 一个 `VfxEffectPackage`
10
+
11
+ 每个特效是 `packages/effects/<dir>/index.ts` 导出的一个对象,实现 `VfxEffectPackage`(定义在 `packages/types.ts`):
12
+
13
+ ```ts
14
+ interface VfxEffectPackage<P> {
15
+ id: string; // 全局唯一 id
16
+ nameZh: string; // 中文名(面板下拉显示)
17
+ defaultParams: P; // 参数默认值(运行时真正用的数据)
18
+ debugParams: VfxParamDefinition[]; // 参数的 UI 描述(面板照它建控件)
19
+ create(ctx): VfxEffectHandle; // 唯一入口:用 ctx + params 在场景里建出特效
20
+ debugAnchor?: 'playerRight' | 'player'; // 面板里默认 spawn 锚点
21
+ manifest?: VfxEffectManifest; // 可选:检索元数据
22
+ spawnParams?, savedParams?; // 可选:见 §5
23
+ }
24
+ ```
25
+
26
+ 宿主(项目)只通过 `playEffectPackage(id, params, transform)` 触发它;特效拿到 `ctx`(scene/root/position/params)自给自足地建粒子/网格。**特效绝不 import 项目代码**(纯净契约,§7)。
27
+
28
+ **两类实现**:
29
+ - **code 类**(逃生舱):`index.ts` 手写 `create()`,直接用 Babylon `ParticleSystem`/`Sprite`/`Mesh`。适合复杂、跟随、mesh/GLB 特效。**本指南主讲这类。**
30
+ - **data 类**(数据驱动):`index.ts` 是薄包装,调工厂 `createManifestRuntimeEffectPackage` 读 manifest JSON。适合标准粒子、AI 可生成。见 §6。
31
+
32
+ ---
33
+
34
+ ## 1. 五分钟:一个最小 code 特效
35
+
36
+ 目录:`packages/effects/ember-sparks/`
37
+
38
+ ```
39
+ ember-sparks/
40
+ ├── index.ts # 特效本体
41
+ ├── vfx-params.json # 调参种子(项目会拷走并各自调)
42
+ └── assets/textures/ember_spark.png # 贴图(经 ?url 打包内联)
43
+ ```
44
+
45
+ `index.ts`:
46
+
47
+ ```ts
48
+ import { Color4 } from '@babylonjs/core/Maths/math.color';
49
+ import { ParticleSystem } from '@babylonjs/core/Particles/particleSystem';
50
+ import { Texture } from '@babylonjs/core/Materials/Textures/texture';
51
+ import type { VfxColorValue, VfxEffectPackage, VfxParamValues } from '../../types';
52
+ import { VFX_RENDERING_GROUP_ID } from '../../rendering';
53
+ import sparkTextureUrl from './assets/textures/ember_spark.png?url'; // ✅ 资源用 ?url
54
+
55
+ // 1) 参数类型 + 默认值
56
+ interface EmberSparksParams extends VfxParamValues {
57
+ lifetime: number; // 特效整体存活秒数
58
+ count: number; // 粒子数
59
+ size: number; // 粒子大小
60
+ speed: number; // 飞散速度
61
+ color: VfxColorValue; // 颜色 {r,g,b}(0..1)
62
+ }
63
+
64
+ const DEFAULT_PARAMS: EmberSparksParams = {
65
+ lifetime: 1.2, count: 60, size: 0.12, speed: 3, color: { r: 1, g: 0.6, b: 0.15 },
66
+ };
67
+
68
+ export const emberSparksEffectPackage: VfxEffectPackage<EmberSparksParams> = {
69
+ id: 'ember-sparks',
70
+ nameZh: '火星迸射',
71
+ defaultParams: DEFAULT_PARAMS,
72
+ debugAnchor: 'playerRight',
73
+
74
+ // 2) 面板控件:每条 = 一个旋钮。key 必须与 defaultParams / create() 读取的 key 一致(见 §4)
75
+ debugParams: [
76
+ { key: 'lifetime', label: '存活时长', kind: 'lifetime', min: 0.2, max: 5, step: 0.1 },
77
+ { key: 'count', label: '粒子数', kind: 'number', min: 1, max: 300, step: 1 },
78
+ { key: 'size', label: '粒子大小', kind: 'scale', min: 0.01,max: 2, step: 0.01 },
79
+ { key: 'speed', label: '飞散速度', kind: 'number', min: 0, max: 20, step: 0.1 },
80
+ { key: 'color', label: '颜色', kind: 'color' },
81
+ ],
82
+
83
+ // 3) create:用 ctx + params 建特效。每个 params.<key> 来自五层合并后的最终值
84
+ create({ scene, root, position, renderingGroupId, params }) {
85
+ root.position.copyFrom(position);
86
+ const ps = new ParticleSystem('ember_sparks', Math.ceil(params.count), scene);
87
+ ps.particleTexture = new Texture(sparkTextureUrl, scene);
88
+ ps.emitter = root; // 挂在 root 上 → 宿主 reparent root 即可跟随物体
89
+ ps.minSize = ps.maxSize = params.size;
90
+ ps.minEmitPower = params.speed * 0.5;
91
+ ps.maxEmitPower = params.speed;
92
+ ps.color1 = new Color4(params.color.r, params.color.g, params.color.b, 1);
93
+ ps.emitRate = params.count / params.lifetime;
94
+ ps.renderingGroupId = renderingGroupId ?? VFX_RENDERING_GROUP_ID; // ✅ 用库常量,别写 magic number
95
+ ps.start();
96
+
97
+ const stopTimer = window.setTimeout(() => ps.stop(), params.lifetime * 1000);
98
+ // 4) 必须返回 handle:root + dispose(清理一切,别漏 timer/observer/system)
99
+ return {
100
+ root,
101
+ dispose() { window.clearTimeout(stopTimer); ps.dispose(); root.dispose(); },
102
+ };
103
+ },
104
+ };
105
+ ```
106
+
107
+ `vfx-params.json`(种子,项目会拷走并各自调;`params` 里只放想覆盖默认值的项,空也行):
108
+
109
+ ```json
110
+ { "schemaVersion": "vfx-params/1.0", "effectId": "ember-sparks", "params": {} }
111
+ ```
112
+
113
+ 校验 + 自测:
114
+
115
+ ```bash
116
+ node tooling/validate-effects.mjs --effect ember-sparks # 单个特效快速 lint
117
+ pnpm validate # 全量(含 build + dist 扫描)
118
+ ```
119
+
120
+ 装进一个项目试调:`node node_modules/@fps/vfx/tooling/vfx-cli.mjs add ember-sparks --project .` → `pnpm dev` → 右下 **VFX** 按钮 → 选「火星迸射」→ 调参 → 播放/保存。
121
+
122
+ ---
123
+
124
+ ## 2. `create(ctx)` 契约
125
+
126
+ `ctx`(`VfxEffectPackageContext`)给你:
127
+
128
+ | 字段 | 含义 |
129
+ |---|---|
130
+ | `scene` | Babylon `Scene` |
131
+ | `root` | 已建好的 `TransformNode`,已放到 spawn 位置;**把特效挂在它下面**,宿主 reparent 它即可跟随 |
132
+ | `position` | spawn 世界坐标(= `root.position` 的副本) |
133
+ | `rotationY` | spawn 朝向 |
134
+ | `renderingGroupId` | 渲染组(可选;没有就用 `VFX_RENDERING_GROUP_ID`) |
135
+ | `params` | **五层合并后的最终参数**(见 §5),按 key 读 |
136
+
137
+ 返回 `VfxEffectHandle`:
138
+
139
+ ```ts
140
+ interface VfxEffectHandle {
141
+ root: TransformNode;
142
+ ready?: Promise<void>; // 异步加载(GLB/贴图)时返回它;宿主可 await(warmup 用),别漏
143
+ dispose(): void; // 清理一切:粒子系统 / observer / setTimeout / mesh / root.dispose()
144
+ }
145
+ ```
146
+
147
+ 规则:
148
+ - **跟随型特效用 code 类**,把发射器挂 `root`,宿主 reparent root 即跟随(`root.getWorldMatrix()`)。data 类一次性定位、不跟随。
149
+ - **异步加载**(GLB、贴图)→ 把加载 promise 放 `ready`,且 `dispose` 要能在加载未完成时也安全清理(置 `disposed` 标志)。参考 `lumber-debris-scatter`。
150
+ - `create()` 内部抛错不会崩场景(service 有 try/catch 兜底),但**别把资源泄漏在错误路径**。
151
+
152
+ ---
153
+
154
+ ## 3. `debugParams` 是什么、面板怎么用它
155
+
156
+ `debugParams` 是**参数的 UI 描述**;DEV 调试面板**照它自动生成控件**(`runtime-vfx-debug-panel.ts` 读 `effectPackage.debugParams`,一条 = 一个旋钮)。你不用写任何面板代码——声明即出控件。
157
+
158
+ 每条是一个 `VfxParamDefinition`:
159
+
160
+ | `kind` | 面板控件 | 额外字段 | 值类型 |
161
+ |---|---|---|---|
162
+ | `number` | 数字输入框 | `min` / `max` / `step` | `number` |
163
+ | `lifetime` | 数字框(语义=时长) | `min` / `max` / `step` | `number` |
164
+ | `scale` | 数字框(语义=缩放) | `min` / `max` / `step` | `number` |
165
+ | `opacity` | 数字框(语义=透明度) | `min` / `max` / `step` | `number` |
166
+ | `color` | 取色器 | — | `{ r, g, b }`(0..1) |
167
+ | `enum` | 下拉 | `options: [{value,label}]` | `string` |
168
+
169
+ 公共字段:`key`(必填,见 §4)、`label`(中文标签)、`description?`。
170
+
171
+ ```ts
172
+ { key: 'scatterShape', label: '散落形态', kind: 'enum',
173
+ options: [ { value: 'radial', label: '中心外扩' }, { value: 'vertical', label: '垂直下落' } ] }
174
+ ```
175
+
176
+ > 不想暴露到面板的内部参数:放 `defaultParams` 但**不放** `debugParams` 即可(常见且允许)。反过来不行——见 §4。
177
+
178
+ ---
179
+
180
+ ## 4. ⭐ key 一致性:面板↔参数靠 `key` 字符串对齐
181
+
182
+ 三处用**同一个 key 串**起来:
183
+
184
+ ```
185
+ debugParams[i].key ←→ defaultParams[key] ←→ create() 里读的 params[key]
186
+ ```
187
+
188
+ - 面板把旋钮的值写进 `params[key]`;`create()` 用 `params[key]` 去设粒子属性。key 对不上 → **旋钮调了没反应**。
189
+ - 硬规则(guardrail 强制):**每个 `debugParams[].key` 必须在 `defaultParams` 里有默认值**。`validate-effects.mjs` 会静态检查;拼错 key(如 `partcileCount`)会被拦下:
190
+ ```
191
+ [参数] debugParams 旋钮 [partcileCount] 在 defaultParams 里没有对应默认值 → 面板调它不生效…
192
+ ```
193
+ - 反向(`defaultParams` 有、`debugParams` 没有)= 内部参数,允许(不强制每个值都给旋钮)。
194
+ - 你在 `create()` 里读哪些 `params.<key>`,就应该在 `defaultParams` 给默认值;想让人调的,再加进 `debugParams`。
195
+
196
+ ---
197
+
198
+ ## 5. 参数怎么运转(五层合并)
199
+
200
+ `playEffectPackage(id, explicitParams, transform)`(`EffectPackageService.ts`)按顺序合并 5 层,**后面的盖前面的**,得到最终 `params` 传给 `create()`:
201
+
202
+ ```
203
+ 1. 生成默认(spawn 位置偏移 offsetX/Y/Z)
204
+ 2. defaultParams —— 你在库里写的默认值
205
+ 3. savedParams —— 项目的 vfx-params.json(经 buildRegistry 注入)
206
+ 4. 运行时 override —— 面板调参时 setDebugOverride 实时写的
207
+ 5. explicitParams —— 调用方临时传的(gameplay 触发时算的动态值)
208
+ ```
209
+
210
+ 含义:
211
+ - **面板调参 = 第 4 层**;点「保存」→ 写回项目 `effects/<id>/vfx-params.json`(第 3 层)→ 下次加载即新默认。
212
+ - **库代码不被改**(模型 C:代码在 `@fps/vfx` 包,调参在项目的 `vfx-params.json`)。
213
+ - **面板调好的值,游戏正式跑也生效**——gameplay 的 system 触发也走同一条合并。
214
+
215
+ 调参面板的存盘端点(DEV):面板「保存」→ `POST /__debug_panel_config?file=effects/<id>/vfx-params.json`(vite 中间件落盘,只写 `params`)。
216
+
217
+ ---
218
+
219
+ ## 6. data 类特效(manifest + 工厂)
220
+
221
+ 标准粒子可以不手写 `create()`,改用工厂读 manifest:
222
+
223
+ ```ts
224
+ // packages/effects/spark_puff/index.ts
225
+ import manifest from './spark_puff.json'; // vfx-effect-package 格式(emitters + tunableParams)
226
+ import runtimeUrl from './assets/runtime/particleEmitter.v1.js?url'; // 引擎适配器,?url 注入
227
+ import texUrl from './assets/textures/spark.png?url';
228
+ import { createManifestRuntimeEffectPackage } from '../../manifestRuntimePackage';
229
+
230
+ export const sparkPuffEffectPackage = createManifestRuntimeEffectPackage({
231
+ id: 'spark_puff',
232
+ manifest,
233
+ assetUrls: {
234
+ 'assets/runtime/particleEmitter.v1.js': runtimeUrl,
235
+ 'assets/textures/spark.png': texUrl,
236
+ },
237
+ });
238
+ ```
239
+
240
+ - `defaultParams` / `debugParams` / `nameZh` 由**工厂从 manifest 的 `tunableParams` 生成**(所以 data 类 index.ts 里看不到它们字面量,key 检查也跳过)。
241
+ - 双发射器(dust + 碎屑)有专用工厂 `createWoodSawdustEffectPackage`(见 `wood-crusher-sawdust`)。
242
+ - data 类**一次性定位、不跟随**;要跟随用 code 类。
243
+
244
+ ---
245
+
246
+ ## 7. 硬约束:库纯净契约(违反会被 guardrail 拦)
247
+
248
+ 1. **不 import 任何项目代码**。只允许 `@babylonjs/*`、库内相对路径(`../../types`/`../../rendering`)、自身资源。特效↔宿主唯一通道 = `create(ctx)`。
249
+ 2. **资源自带**:贴图/GLB/runtime-js 放包内,`import x from './assets/…?url'`。**禁 `new URL(…, import.meta.url)`**(库 build 不内联它)。
250
+ 3. **glTF 只用核心 loader**:`import '@babylonjs/loaders/glTF/2.0/glTFLoader'`。**禁全量 barrel**(`@babylonjs/loaders` / `…/glTF`)——会把 `MeshoptDecoder` 拉进 consumer 包,违反 Playable 策略(#2 v0.1.1)。GLB 必须 plain(零扩展)。见 `lumber-debris-scatter`。
251
+ 4. **配置参数化**:任何"配置值"做成 `defaultParams`/`debugParams`,经 `params` 传入。
252
+ 5. **渲染组用常量** `VFX_RENDERING_GROUP_ID`,别写 magic number。
253
+
254
+ ---
255
+
256
+ ## 8. 工作流:校验 → 安装 → 发版
257
+
258
+ ```bash
259
+ # 作者本地(改完特效):
260
+ node tooling/validate-effects.mjs --effect <id> # 单特效快速 lint
261
+ pnpm validate # 全量 guardrail(boundary+lint+typecheck+build+dist)
262
+ pnpm test:guardrails # guardrail 回归
263
+
264
+ # 在某项目里调试:
265
+ node node_modules/@fps/vfx/tooling/vfx-cli.mjs add <id> --project . # 装桩+种子params
266
+ pnpm dev # → VFX 面板调参/保存
267
+
268
+ # 发版(让消费方拿到新特效):
269
+ pnpm release -- minor --dry-run # 预演(新增特效=minor)
270
+ pnpm release -- minor # gate→bump→index/CHANGELOG→提交dist→tag→push
271
+ ```
272
+
273
+ ---
274
+
275
+ ## 9. 常见坑
276
+
277
+ | 坑 | 现象 | 修 |
278
+ |---|---|---|
279
+ | 全量 glTF loader | prod 构建被 meshopt 检查卡住 | 用 `@babylonjs/loaders/glTF/2.0/glTFLoader` |
280
+ | `new URL(...)` 引资源 | 库 build 后资源丢失 | 改 `import x from './…?url'` |
281
+ | debugParams key 拼错 | 面板旋钮调了没反应 | key 对齐 defaultParams(guardrail 会拦) |
282
+ | 想跟随却用了 data 类 | 特效不跟物体 | 用 code 类,挂 `root`,宿主 reparent |
283
+ | `dispose` 漏清理 | 切场景/重复播泄漏 | dispose 清 system/observer/timer/mesh/root |
284
+ | 异步加载没给 `ready` | warmup 时机错乱 | 返回 handle 时带 `ready: Promise` |
285
+ | 引用项目模块 | boundary 报错 | 改成 ctx 注入 / 自带资源 |
286
+
287
+ ---
288
+
289
+ ## 10. 提交前 checklist
290
+
291
+ - [ ] `packages/effects/<dir>/index.ts` 导出 `VfxEffectPackage`(`id`/`nameZh`/`defaultParams`/`debugParams`/`create`)。
292
+ - [ ] 资源在 `assets/` 下,经 `?url` 引;GLB 用核心 loader。
293
+ - [ ] `debugParams` 每个 `key` 都在 `defaultParams`(面板↔参数对齐)。
294
+ - [ ] `create()` 用 `ctx` + `params`,不 import 项目;`dispose()` 清理彻底。
295
+ - [ ] 有 `vfx-params.json` 种子(合法 JSON)。
296
+ - [ ] `pnpm validate` + `pnpm test:guardrails` 全绿。
297
+ - [ ] DEV 面板里能选到、能调、能播、能存。