@fps-games/vfx 0.1.1 → 0.3.3

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 (250) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/README.md +41 -0
  3. package/dist/effects/coin-burst/index.js +6 -2
  4. package/dist/effects/comet-trail-flame/index.js +3 -1
  5. package/dist/effects/debris-smoke/index.js +1 -0
  6. package/dist/effects/electric-arc/index.js +1 -0
  7. package/dist/effects/energy-shield/index.js +1 -0
  8. package/dist/effects/explosion/index.js +3 -2
  9. package/dist/effects/hit-flash/index.js +12 -4
  10. package/dist/effects/laser-beam/index.js +14 -2
  11. package/dist/effects/lumber_vehicle_upgrade_aura/index.js +1 -0
  12. package/dist/effects/monster-hit/index.js +2 -1
  13. package/dist/effects/player-upgrade/index.js +5 -3
  14. package/dist/effects/pulse-laser-volley/index.js +14 -4
  15. package/dist/effects/thruster-flame/index.js +3 -1
  16. package/dist/effects/treasure-attention/index.d.ts +54 -0
  17. package/dist/effects/treasure-attention/index.js +535 -0
  18. package/dist/effects/ufo-thread-flame/index.js +1 -0
  19. package/dist/effects/vehicle-upgrade/index.js +4 -1
  20. package/dist/effects/weapon-trail/index.js +8 -3
  21. package/dist/effects/wood_crusher_sawdust/index.d.ts +4 -0
  22. package/dist/effects/wood_cutter_sawdust/index.d.ts +4 -0
  23. package/dist/index.js +85 -17
  24. package/dist/types.d.ts +80 -0
  25. package/index.json +19 -1
  26. package/package.json +9 -4
  27. package/packages/effects/treasure-attention/vfx-params.json +49 -0
  28. package/tooling/vfx-cli.mjs +8 -1
  29. package/docs/AUTHORING_EFFECTS.md +0 -297
  30. package/docs/VFX_LIBRARY_ARCHITECTURE_chatgpt.md +0 -1580
  31. package/docs/VFX_LIBRARY_EXECUTION_PLAN.md +0 -229
  32. package/docs/VFX_LIBRARY_PLAN.md +0 -546
  33. package/docs/vfx-ab/RESULTS.md +0 -35
  34. package/docs/vfx-ab/lumber-order/vehicle-exhaust-smoke/after.png +0 -0
  35. package/docs/vfx-ab/lumber-order/vehicle-exhaust-smoke/before.png +0 -0
  36. package/docs/vfx-ab/lumber-truck/vehicle-exhaust-smoke/after.png +0 -0
  37. package/docs/vfx-ab/lumber-truck/vehicle-exhaust-smoke/before.png +0 -0
  38. package/docs/vfx-integration_chatgpt.md +0 -462
  39. package/docs/weapon-trail-visualization.html +0 -241
  40. package/packages/EffectPackageService.ts +0 -240
  41. package/packages/SceneVfxService.ts +0 -96
  42. package/packages/build.mesh.yellow_build_upgrade_indicator/assets/runtime/simpleMeshEffect.v1.js +0 -333
  43. package/packages/build.mesh.yellow_build_upgrade_indicator/assets/shaders/mesh-effect-preview.frag.glsl +0 -25
  44. package/packages/build.mesh.yellow_build_upgrade_indicator/assets/shaders/mesh-effect-preview.vert.glsl +0 -11
  45. package/packages/build.mesh.yellow_build_upgrade_indicator/assets/textures/effect_jianbian.png +0 -0
  46. package/packages/build.mesh.yellow_build_upgrade_indicator/effect.json +0 -927
  47. package/packages/build.mesh.yellow_build_upgrade_indicator/media/contact-sheet.png +0 -0
  48. package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.gif +0 -0
  49. package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.mp4 +0 -0
  50. package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.webm +0 -0
  51. package/packages/build.mesh.yellow_build_upgrade_indicator/media/thumbnail.png +0 -0
  52. package/packages/build.mesh.yellow_build_upgrade_indicator/metadata/description.json +0 -197
  53. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/03-effect.original.json +0 -895
  54. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/03-normalized-vfx-to-babylon-report.json +0 -241
  55. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/04-preview-overrides.json +0 -542
  56. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/04-preview-tuning-report.json +0 -69
  57. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/asset-map.json +0 -125
  58. package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/lineage.json +0 -44
  59. package/packages/build.particle.golden_upgrade_starburst/assets/runtime/particleEmitter.v1.js +0 -210
  60. package/packages/build.particle.golden_upgrade_starburst/assets/textures/effect_guangdian.png +0 -0
  61. package/packages/build.particle.golden_upgrade_starburst/effect.json +0 -880
  62. package/packages/build.particle.golden_upgrade_starburst/media/contact-sheet.png +0 -0
  63. package/packages/build.particle.golden_upgrade_starburst/media/preview.gif +0 -0
  64. package/packages/build.particle.golden_upgrade_starburst/media/preview.mp4 +0 -0
  65. package/packages/build.particle.golden_upgrade_starburst/media/preview.webm +0 -0
  66. package/packages/build.particle.golden_upgrade_starburst/media/thumbnail.png +0 -0
  67. package/packages/build.particle.golden_upgrade_starburst/metadata/description.json +0 -161
  68. package/packages/build.particle.golden_upgrade_starburst/provenance/03-effect.original.json +0 -762
  69. package/packages/build.particle.golden_upgrade_starburst/provenance/03-normalized-vfx-to-babylon-report.json +0 -260
  70. package/packages/build.particle.golden_upgrade_starburst/provenance/04-preview-overrides.json +0 -436
  71. package/packages/build.particle.golden_upgrade_starburst/provenance/04-preview-tuning-report.json +0 -40
  72. package/packages/build.particle.golden_upgrade_starburst/provenance/asset-map.json +0 -115
  73. package/packages/build.particle.golden_upgrade_starburst/provenance/lineage.json +0 -40
  74. package/packages/build.particle.orange_upgrade_transform_sparks/assets/runtime/particleEmitter.v1.js +0 -210
  75. package/packages/build.particle.orange_upgrade_transform_sparks/assets/textures/b5b27ab1-e740-4398-b407-848fc2b2c897.png +0 -0
  76. package/packages/build.particle.orange_upgrade_transform_sparks/effect.json +0 -887
  77. package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.gif +0 -0
  78. package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.mp4 +0 -0
  79. package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.webm +0 -0
  80. package/packages/build.particle.orange_upgrade_transform_sparks/media/thumbnail.png +0 -0
  81. package/packages/build.particle.orange_upgrade_transform_sparks/metadata/description.json +0 -179
  82. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/03-effect.original.json +0 -859
  83. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/03-normalized-vfx-to-babylon-report.json +0 -260
  84. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/04-preview-overrides.json +0 -478
  85. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/04-preview-tuning-report.json +0 -40
  86. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/asset-map.json +0 -114
  87. package/packages/build.particle.orange_upgrade_transform_sparks/provenance/lineage.json +0 -41
  88. package/packages/build.particle.wood_chip_dust_burst/assets/runtime/particleEmitter.v1.js +0 -210
  89. package/packages/build.particle.wood_chip_dust_burst/assets/textures/effect_yanwu4.png +0 -0
  90. package/packages/build.particle.wood_chip_dust_burst/assets/textures/suipian3.png +0 -0
  91. package/packages/build.particle.wood_chip_dust_burst/effect.json +0 -1400
  92. package/packages/build.particle.wood_chip_dust_burst/media/contact-sheet.png +0 -0
  93. package/packages/build.particle.wood_chip_dust_burst/media/preview.gif +0 -0
  94. package/packages/build.particle.wood_chip_dust_burst/media/preview.mp4 +0 -0
  95. package/packages/build.particle.wood_chip_dust_burst/media/preview.webm +0 -0
  96. package/packages/build.particle.wood_chip_dust_burst/media/thumbnail.png +0 -0
  97. package/packages/build.particle.wood_chip_dust_burst/metadata/description.json +0 -173
  98. package/packages/build.particle.wood_chip_dust_burst/provenance/03-effect.original.json +0 -1277
  99. package/packages/build.particle.wood_chip_dust_burst/provenance/03-normalized-vfx-to-babylon-report.json +0 -329
  100. package/packages/build.particle.wood_chip_dust_burst/provenance/04-preview-overrides.json +0 -749
  101. package/packages/build.particle.wood_chip_dust_burst/provenance/04-preview-tuning-report.json +0 -60
  102. package/packages/build.particle.wood_chip_dust_burst/provenance/asset-map.json +0 -146
  103. package/packages/build.particle.wood_chip_dust_burst/provenance/lineage.json +0 -69
  104. package/packages/effects/building-upgrade/effect.json +0 -6
  105. package/packages/effects/building-upgrade/index.ts +0 -387
  106. package/packages/effects/character-entrance/effect.json +0 -6
  107. package/packages/effects/character-entrance/index.ts +0 -308
  108. package/packages/effects/coin-burst/index.ts +0 -43
  109. package/packages/effects/comet-trail-flame/assets/textures/trail_5x4.webp +0 -0
  110. package/packages/effects/comet-trail-flame/index.ts +0 -106
  111. package/packages/effects/conveyor-upgrade/effect.json +0 -6
  112. package/packages/effects/conveyor-upgrade/index.ts +0 -401
  113. package/packages/effects/debris-smoke/assets/models/rock_debris.glb +0 -0
  114. package/packages/effects/debris-smoke/assets/textures/smoke22.webp +0 -0
  115. package/packages/effects/debris-smoke/index.ts +0 -101
  116. package/packages/effects/door_open_gold_flakes/assets/runtime/goldFlakes.v1.js +0 -397
  117. package/packages/effects/door_open_gold_flakes/door_open_gold_flakes.json +0 -498
  118. package/packages/effects/door_open_gold_flakes/index.ts +0 -11
  119. package/packages/effects/electric-arc/assets/textures/spark_4x4.webp +0 -0
  120. package/packages/effects/electric-arc/index.ts +0 -62
  121. package/packages/effects/energy-shield/effect.json +0 -7
  122. package/packages/effects/energy-shield/index.ts +0 -431
  123. package/packages/effects/explosion/assets/textures/baozha29.webp +0 -0
  124. package/packages/effects/explosion/assets/textures/glow01.webp +0 -0
  125. package/packages/effects/explosion/assets/textures/lizi01.webp +0 -0
  126. package/packages/effects/explosion/assets/textures/xulie_lizibaozha02_5x5.webp +0 -0
  127. package/packages/effects/explosion/index.ts +0 -114
  128. package/packages/effects/ground-tile-upgrade/effect.json +0 -6
  129. package/packages/effects/ground-tile-upgrade/index.ts +0 -410
  130. package/packages/effects/hit-flash/index.ts +0 -69
  131. package/packages/effects/laser-beam/assets/textures/laser_glow.webp +0 -0
  132. package/packages/effects/laser-beam/assets/textures/laser_noise.webp +0 -0
  133. package/packages/effects/laser-beam/index.ts +0 -6
  134. package/packages/effects/laser-beam-factory.ts +0 -135
  135. package/packages/effects/lumber-cart-suction/effect.json +0 -6
  136. package/packages/effects/lumber-cart-suction/index.ts +0 -399
  137. package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb +0 -0
  138. package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb.versions/.active +0 -1
  139. package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb.versions/1781589063890_upload.glb +0 -0
  140. package/packages/effects/lumber-debris-scatter/assets/runtime/solidParticleScatter.v1.js +0 -236
  141. package/packages/effects/lumber-debris-scatter/effect.json +0 -228
  142. package/packages/effects/lumber-debris-scatter/index.ts +0 -780
  143. package/packages/effects/lumber_vehicle_gear_spin/assets/runtime/gearSpin.v1.js +0 -202
  144. package/packages/effects/lumber_vehicle_gear_spin/index.ts +0 -11
  145. package/packages/effects/lumber_vehicle_gear_spin/lumber_vehicle_gear_spin.json +0 -338
  146. package/packages/effects/lumber_vehicle_upgrade_aura/assets/runtime/upgradeAura.v1.js +0 -353
  147. package/packages/effects/lumber_vehicle_upgrade_aura/index.ts +0 -11
  148. package/packages/effects/lumber_vehicle_upgrade_aura/lumber_vehicle_upgrade_aura.json +0 -365
  149. package/packages/effects/lumber_vehicle_wood_chips/assets/runtime/solidParticleScatter.v1.js +0 -310
  150. package/packages/effects/lumber_vehicle_wood_chips/index.ts +0 -11
  151. package/packages/effects/lumber_vehicle_wood_chips/lumber_vehicle_wood_chips.json +0 -335
  152. package/packages/effects/monster-hit/index.ts +0 -128
  153. package/packages/effects/player-upgrade/effect.json +0 -6
  154. package/packages/effects/player-upgrade/index.ts +0 -635
  155. package/packages/effects/pulse-laser-volley/assets/textures/bolt_guangshu.webp +0 -0
  156. package/packages/effects/pulse-laser-volley/index.ts +0 -204
  157. package/packages/effects/resource-collect-sparkles/effect.json +0 -6
  158. package/packages/effects/resource-collect-sparkles/index.ts +0 -254
  159. package/packages/effects/run-footstep-dust/assets/runtime/runFootstepDust.v1.js +0 -215
  160. package/packages/effects/run-footstep-dust/effect.json +0 -183
  161. package/packages/effects/run-footstep-dust/index.ts +0 -377
  162. package/packages/effects/space-shared.ts +0 -120
  163. package/packages/effects/thruster-flame/index.ts +0 -305
  164. package/packages/effects/tree-chop-dust/assets/textures/tree_chop_dust_atlas.png +0 -0
  165. package/packages/effects/tree-chop-dust/effect.json +0 -8
  166. package/packages/effects/tree-chop-dust/index.ts +0 -202
  167. package/packages/effects/tree-leaf-chop-burst/assets/runtime/particleEmitter.v1.js +0 -303
  168. package/packages/effects/tree-leaf-chop-burst/assets/textures/tree_leaf_chop_burst_leaf_atlas.png +0 -0
  169. package/packages/effects/tree-leaf-chop-burst/effect.json +0 -498
  170. package/packages/effects/tree-leaf-chop-burst/index.ts +0 -294
  171. package/packages/effects/tree_chop_dust_burst/assets/runtime/particleEmitter.v1.js +0 -318
  172. package/packages/effects/tree_chop_dust_burst/assets/textures/tree_chop_dust_burst_dust.png +0 -0
  173. package/packages/effects/tree_chop_dust_burst/index.ts +0 -13
  174. package/packages/effects/tree_chop_dust_burst/tree_chop_dust_burst.json +0 -412
  175. package/packages/effects/ufo-thread-flame/assets/textures/flame_flow.webp +0 -0
  176. package/packages/effects/ufo-thread-flame/assets/textures/flame_spike.webp +0 -0
  177. package/packages/effects/ufo-thread-flame/index.ts +0 -152
  178. package/packages/effects/vehicle-exhaust-smoke/assets/textures/vehicle_exhaust_smoke_atlas.png +0 -0
  179. package/packages/effects/vehicle-exhaust-smoke/effect.json +0 -8
  180. package/packages/effects/vehicle-exhaust-smoke/index.ts +0 -298
  181. package/packages/effects/vehicle-upgrade/effect.json +0 -6
  182. package/packages/effects/vehicle-upgrade/index.ts +0 -401
  183. package/packages/effects/weapon-trail/assets/textures/trail_wedge.png +0 -0
  184. package/packages/effects/weapon-trail/index.ts +0 -313
  185. package/packages/effects/wood-crusher-sawdust/assets/runtime/particleEmitter.v1.js +0 -312
  186. package/packages/effects/wood-crusher-sawdust/assets/textures/wood_crusher_sawdust_dust.png +0 -0
  187. package/packages/effects/wood-crusher-sawdust/assets/textures/wood_crusher_sawdust_fiber.png +0 -0
  188. package/packages/effects/wood-crusher-sawdust/index.ts +0 -43
  189. package/packages/effects/wood-crusher-sawdust/wood_crusher_sawdust.json +0 -592
  190. package/packages/effects/wood-cutter-sawdust/assets/runtime/particleEmitter.v1.js +0 -312
  191. package/packages/effects/wood-cutter-sawdust/assets/textures/wood_cutter_sawdust_chip.png +0 -0
  192. package/packages/effects/wood-cutter-sawdust/assets/textures/wood_cutter_sawdust_dust.png +0 -0
  193. package/packages/effects/wood-cutter-sawdust/index.ts +0 -43
  194. package/packages/effects/wood-cutter-sawdust/wood_cutter_sawdust.json +0 -592
  195. package/packages/effects/wood-sawdust-effect-factory.ts +0 -194
  196. package/packages/effects/wood_crusher_sawdust/assets/runtime/particleEmitter.v1.js +0 -318
  197. package/packages/effects/wood_crusher_sawdust/assets/textures/wood_crusher_sawdust_dust.png +0 -0
  198. package/packages/effects/wood_crusher_sawdust/assets/textures/wood_crusher_sawdust_fiber.png +0 -0
  199. package/packages/effects/wood_crusher_sawdust/index.ts +0 -29
  200. package/packages/effects/wood_crusher_sawdust/wood_crusher_sawdust.json +0 -592
  201. package/packages/effects/wood_cutter_sawdust/assets/runtime/particleEmitter.v1.js +0 -318
  202. package/packages/effects/wood_cutter_sawdust/assets/textures/wood_cutter_sawdust_chip.png +0 -0
  203. package/packages/effects/wood_cutter_sawdust/assets/textures/wood_cutter_sawdust_dust.png +0 -0
  204. package/packages/effects/wood_cutter_sawdust/index.ts +0 -29
  205. package/packages/effects/wood_cutter_sawdust/wood_cutter_sawdust.json +0 -592
  206. package/packages/effects/wood_peel_material_test/assets/runtime/woodPeelMaterialTest.v1.js +0 -196
  207. package/packages/effects/wood_peel_material_test/index.ts +0 -11
  208. package/packages/effects/wood_peel_material_test/wood_peel_material_test.json +0 -136
  209. package/packages/env.particle.forest_edge_fog/assets/runtime/particleEmitter.v1.js +0 -210
  210. package/packages/env.particle.forest_edge_fog/assets/textures/f12a23c4-b924-4322-a260-3d982428f1e8.png +0 -0
  211. package/packages/env.particle.forest_edge_fog/assets/textures/yuan.png +0 -0
  212. package/packages/env.particle.forest_edge_fog/effect.json +0 -854
  213. package/packages/env.particle.forest_edge_fog/media/preview.gif +0 -0
  214. package/packages/env.particle.forest_edge_fog/media/preview.mp4 +0 -0
  215. package/packages/env.particle.forest_edge_fog/media/preview.webm +0 -0
  216. package/packages/env.particle.forest_edge_fog/media/thumbnail.png +0 -0
  217. package/packages/env.particle.forest_edge_fog/metadata/description.json +0 -148
  218. package/packages/env.particle.forest_edge_fog/provenance/03-effect.original.json +0 -827
  219. package/packages/env.particle.forest_edge_fog/provenance/03-normalized-vfx-to-babylon-report.json +0 -196
  220. package/packages/env.particle.forest_edge_fog/provenance/04-preview-overrides.json +0 -432
  221. package/packages/env.particle.forest_edge_fog/provenance/04-preview-tuning-report.json +0 -28
  222. package/packages/env.particle.forest_edge_fog/provenance/asset-map.json +0 -124
  223. package/packages/env.particle.forest_edge_fog/provenance/lineage.json +0 -41
  224. package/packages/generation.ts +0 -14
  225. package/packages/index.ts +0 -14
  226. package/packages/legacy-particle-runtime.ts +0 -113
  227. package/packages/manifestRuntimePackage.ts +0 -519
  228. package/packages/registry.ts +0 -85
  229. package/packages/rendering.ts +0 -13
  230. package/packages/resource.particle.viscous_oil_suction/assets/runtime/top_disk_suction/particleEmitter.v1.js +0 -424
  231. package/packages/resource.particle.viscous_oil_suction/assets/textures/Glow ad.png +0 -0
  232. package/packages/resource.particle.viscous_oil_suction/effect.json +0 -1254
  233. package/packages/resource.particle.viscous_oil_suction/media/preview.gif +0 -0
  234. package/packages/resource.particle.viscous_oil_suction/media/preview.mp4 +0 -0
  235. package/packages/resource.particle.viscous_oil_suction/media/preview.webm +0 -0
  236. package/packages/resource.particle.viscous_oil_suction/media/thumbnail.png +0 -0
  237. package/packages/resource.particle.viscous_oil_suction/metadata/description.json +0 -122
  238. package/packages/resource.particle.viscous_oil_suction/provenance/03-effect.original.json +0 -1051
  239. package/packages/resource.particle.viscous_oil_suction/provenance/03-normalized-vfx-to-babylon-report.json +0 -200
  240. package/packages/resource.particle.viscous_oil_suction/provenance/04-preview-overrides.json +0 -581
  241. package/packages/resource.particle.viscous_oil_suction/provenance/04-preview-tuning-report.json +0 -28
  242. package/packages/resource.particle.viscous_oil_suction/provenance/asset-map.json +0 -111
  243. package/packages/resource.particle.viscous_oil_suction/provenance/lineage.json +0 -45
  244. package/packages/types.ts +0 -107
  245. package/tooling/check-dist-runtime.mjs +0 -166
  246. package/tooling/generate-index.mjs +0 -55
  247. package/tooling/test-guardrails.mjs +0 -157
  248. package/tooling/validate-boundary.mjs +0 -92
  249. package/tooling/validate-effects.mjs +0 -304
  250. package/tooling/validate.mjs +0 -53
@@ -1,519 +0,0 @@
1
- import { Engine } from '@babylonjs/core/Engines/engine';
2
- import { Color3, Color4 } from '@babylonjs/core/Maths/math.color';
3
- import { Vector3 } from '@babylonjs/core/Maths/math.vector';
4
- import { Material } from '@babylonjs/core/Materials/material';
5
- import { MaterialPluginBase } from '@babylonjs/core/Materials/materialPluginBase';
6
- import { PBRMaterial } from '@babylonjs/core/Materials/PBR/pbrMaterial';
7
- import { DynamicTexture } from '@babylonjs/core/Materials/Textures/dynamicTexture';
8
- import { Texture } from '@babylonjs/core/Materials/Textures/texture';
9
- import { StandardMaterial } from '@babylonjs/core/Materials/standardMaterial';
10
- import { CreateBox } from '@babylonjs/core/Meshes/Builders/boxBuilder';
11
- import { CreateCylinder } from '@babylonjs/core/Meshes/Builders/cylinderBuilder';
12
- import { CreateDisc } from '@babylonjs/core/Meshes/Builders/discBuilder';
13
- import { CreatePlane } from '@babylonjs/core/Meshes/Builders/planeBuilder';
14
- import { CreateTube } from '@babylonjs/core/Meshes/Builders/tubeBuilder';
15
- import { Mesh } from '@babylonjs/core/Meshes/mesh';
16
- import { VertexData } from '@babylonjs/core/Meshes/mesh.vertexData';
17
- import { TransformNode } from '@babylonjs/core/Meshes/transformNode';
18
- import { ParticleSystem } from '@babylonjs/core/Particles/particleSystem';
19
- import { SolidParticleSystem } from '@babylonjs/core/Particles/solidParticleSystem';
20
- import { SceneLoader } from '@babylonjs/core/Loading/sceneLoader';
21
- import type { Scene } from '@babylonjs/core/scene';
22
-
23
- import type {
24
- VfxColorValue,
25
- VfxDebugAnchor,
26
- VfxEffectHandle,
27
- VfxEffectPackage,
28
- VfxEffectPackageContext,
29
- VfxParamDefinition,
30
- VfxParamValue,
31
- VfxParamValues,
32
- } from './types';
33
-
34
- type LegacyTunableParamType = 'number' | 'color' | 'enum' | string;
35
-
36
- interface LegacyTunableTarget {
37
- emitter: string;
38
- property: string;
39
- operator?: string;
40
- defaultValue?: unknown;
41
- }
42
-
43
- interface LegacyTunableParam {
44
- key: string;
45
- label?: string;
46
- labelEn?: string;
47
- labelZh?: string;
48
- type: LegacyTunableParamType;
49
- default?: unknown;
50
- min?: number;
51
- max?: number;
52
- step?: number;
53
- options?: Array<{ value: string; label?: string }>;
54
- target?: LegacyTunableTarget;
55
- targets?: LegacyTunableTarget[];
56
- }
57
-
58
- interface LegacyEmitterConfig {
59
- name: string;
60
- enabled?: boolean;
61
- runtime?: {
62
- adapter?: string;
63
- stopAfterSeconds?: number;
64
- disposeOnComplete?: boolean;
65
- };
66
- [key: string]: unknown;
67
- }
68
-
69
- interface LegacyRuntimeAdapterConfig {
70
- id: string;
71
- entry: string;
72
- moduleFormat?: string;
73
- exports?: string[];
74
- }
75
-
76
- interface LegacyEffectManifest {
77
- id?: string;
78
- name?: {
79
- en?: string;
80
- zh?: string;
81
- };
82
- assets?: Record<string, unknown> | unknown[];
83
- source?: unknown;
84
- emitters?: LegacyEmitterConfig[];
85
- runtime?: {
86
- driver?: string;
87
- adapters?: LegacyRuntimeAdapterConfig[];
88
- };
89
- tunableParams?: LegacyTunableParam[];
90
- defaultParams?: Record<string, unknown>;
91
- debug?: {
92
- playAnchor?: string;
93
- livePreview?: boolean;
94
- };
95
- }
96
-
97
- type RuntimePreview = {
98
- start?: () => void;
99
- stop?: () => void;
100
- dispose?: () => void;
101
- isStarted?: () => boolean;
102
- setPosition?: (position: Vector3) => void;
103
- setScaling?: (scaling: Vector3) => void;
104
- };
105
-
106
- const BABYLON_RUNTIME_API = {
107
- Color3,
108
- Color4,
109
- DynamicTexture,
110
- Engine,
111
- Material,
112
- MaterialPluginBase,
113
- Mesh,
114
- MeshBuilder: {
115
- CreateBox,
116
- CreateCylinder,
117
- CreateDisc,
118
- CreatePlane,
119
- CreateTube,
120
- },
121
- PBRMaterial,
122
- ParticleSystem,
123
- SceneLoader,
124
- SolidParticleSystem,
125
- StandardMaterial,
126
- Texture,
127
- TransformNode,
128
- Vector3,
129
- VertexData,
130
- } as const;
131
-
132
- export interface ManifestRuntimeEffectPackageOptions {
133
- id: string;
134
- manifest: LegacyEffectManifest;
135
- assetUrls: Record<string, string>;
136
- }
137
-
138
- export function createManifestRuntimeEffectPackage(options: ManifestRuntimeEffectPackageOptions): VfxEffectPackage {
139
- const { id, manifest, assetUrls } = options;
140
- return {
141
- id,
142
- nameZh: manifest.name?.zh ?? manifest.name?.en ?? id,
143
- manifest: {
144
- id: manifest.id ?? id,
145
- nameZh: manifest.name?.zh ?? manifest.name?.en ?? id,
146
- assets: collectManifestAssetPaths(manifest),
147
- source: readManifestSource(manifest),
148
- },
149
- defaultParams: buildDefaultParams(manifest),
150
- debugAnchor: normalizeDebugAnchor(manifest.debug?.playAnchor),
151
- debugParams: buildDebugParams(manifest),
152
- create(context) {
153
- return createManifestRuntimeHandle(context, manifest, assetUrls, id);
154
- },
155
- };
156
- }
157
-
158
- function createManifestRuntimeHandle(
159
- context: VfxEffectPackageContext,
160
- manifest: LegacyEffectManifest,
161
- assetUrls: Record<string, string>,
162
- effectId: string,
163
- ): VfxEffectHandle {
164
- const root = context.root;
165
- const previews: RuntimePreview[] = [];
166
- const cleanupCallbacks: Array<() => void> = [];
167
- let disposed = false;
168
-
169
- const ready = startRuntimePreviews().catch((error) => {
170
- console.warn(`[VFX] Failed to play effect package "${effectId}".`, error);
171
- });
172
-
173
- return {
174
- root,
175
- ready,
176
- dispose() {
177
- disposed = true;
178
- for (const cleanup of cleanupCallbacks.splice(0)) cleanup();
179
- for (const preview of previews.splice(0)) {
180
- preview.stop?.();
181
- preview.dispose?.();
182
- }
183
- disposeRoot(root);
184
- },
185
- };
186
-
187
- async function startRuntimePreviews(): Promise<void> {
188
- const emitters = (manifest.emitters ?? [])
189
- .filter((emitter) => emitter.enabled !== false)
190
- .map(cloneEmitter);
191
-
192
- for (const [index, emitter] of emitters.entries()) {
193
- if (disposed) return;
194
- applyTunableValues(emitter, manifest.tunableParams ?? [], context.params);
195
- emitter.origin = {
196
- x: context.position.x,
197
- y: context.position.y,
198
- z: context.position.z,
199
- };
200
- emitter.rotationY = root.rotation.y;
201
- const preview = await playEmitter(manifest, emitter, assetUrls, index, effectId, context.scene);
202
- if (!preview) continue;
203
- if (disposed) {
204
- preview.stop?.();
205
- preview.dispose?.();
206
- continue;
207
- }
208
- syncPreviewPosition(context, preview, cleanupCallbacks);
209
- previews.push(preview);
210
- }
211
- }
212
- }
213
-
214
- function syncPreviewPosition(
215
- context: VfxEffectPackageContext,
216
- preview: RuntimePreview,
217
- cleanupCallbacks: Array<() => void>,
218
- ): void {
219
- if (typeof preview.setPosition !== 'function') return;
220
- preview.setPosition(context.root.getAbsolutePosition());
221
- const observer = context.scene.onBeforeRenderObservable.add(() => {
222
- preview.setPosition?.(context.root.getAbsolutePosition());
223
- preview.setScaling?.(context.root.scaling);
224
- });
225
- cleanupCallbacks.push(() => {
226
- context.scene.onBeforeRenderObservable.remove(observer);
227
- });
228
- }
229
-
230
- async function playEmitter(
231
- manifest: LegacyEffectManifest,
232
- emitter: LegacyEmitterConfig,
233
- assetUrls: Record<string, string>,
234
- index: number,
235
- effectId: string,
236
- scene: Scene,
237
- ): Promise<RuntimePreview | null> {
238
- const adapterId = resolveEmitterAdapterId(manifest, emitter);
239
- if (!adapterId) {
240
- console.warn(`[VFX] Missing runtime adapter for ${effectId}/${emitter.name}`);
241
- return null;
242
- }
243
-
244
- const adapter = manifest.runtime?.adapters?.find((item) => item.id === adapterId)
245
- ?? manifest.runtime?.adapters?.[0];
246
- if (!adapter) {
247
- console.warn(`[VFX] Adapter "${adapterId}" is not registered in ${effectId}`);
248
- return null;
249
- }
250
-
251
- const adapterUrl = assetUrls[adapter.entry];
252
- if (!adapterUrl) {
253
- console.warn(`[VFX] Missing runtime asset "${adapter.entry}" for ${effectId}`);
254
- return null;
255
- }
256
-
257
- const runtimeModule = await import(/* @vite-ignore */ adapterUrl) as Record<string, unknown>;
258
- const createRuntimeName = adapter.exports?.find((name) => name.startsWith('create'))
259
- ?? getRuntimeFactoryName(adapter.id);
260
- const createRuntime = runtimeModule[createRuntimeName];
261
- if (typeof createRuntime !== 'function') {
262
- console.warn(`[VFX] Runtime "${adapter.id}" does not export "${createRuntimeName}"`);
263
- return null;
264
- }
265
-
266
- return await createRuntime({
267
- BABYLON: BABYLON_RUNTIME_API,
268
- scene,
269
- emitter,
270
- index,
271
- shouldStart: true,
272
- urlForPackagePath: (packagePath: string) => assetUrls[packagePath] ?? packagePath,
273
- }) as RuntimePreview;
274
- }
275
-
276
- function resolveEmitterAdapterId(manifest: LegacyEffectManifest, emitter: LegacyEmitterConfig): string | undefined {
277
- const runtimeAdapter = emitter.runtime?.adapter;
278
- if (runtimeAdapter) return runtimeAdapter;
279
- const adapters = manifest.runtime?.adapters ?? [];
280
- if (adapters.length === 1) return adapters[0].id;
281
- if (manifest.runtime?.driver === 'solidParticleScatter') return 'solidParticleScatter/v1';
282
- if (manifest.runtime?.driver === 'particle') return 'particleEmitter/v1';
283
- return adapters[0]?.id;
284
- }
285
-
286
- function getRuntimeFactoryName(adapterId: string): string {
287
- if (adapterId === 'solidParticleScatter/v1') return 'createSolidParticleScatterRuntime';
288
- if (adapterId === 'particleEmitter/v1') return 'createParticleEmitterRuntime';
289
- if (adapterId === 'gearSpin/v1') return 'createGearSpinRuntime';
290
- if (adapterId === 'goldFlakes/v1') return 'createGoldFlakesRuntime';
291
- if (adapterId === 'upgradeAura/v1') return 'createUpgradeAuraRuntime';
292
- if (adapterId === 'woodPeelMaterialTest/v1') return 'createWoodPeelMaterialTestRuntime';
293
- if (adapterId === 'simpleMeshEffect/v1') return 'createSimpleMeshEffectRuntime';
294
- return 'createVfxRuntime';
295
- }
296
-
297
- function applyTunableValues(
298
- emitter: LegacyEmitterConfig,
299
- params: LegacyTunableParam[],
300
- values: VfxParamValues,
301
- ): void {
302
- for (const param of params) {
303
- if (!(param.key in values)) continue;
304
- const targets = param.targets ?? (param.target ? [param.target] : []);
305
- for (const target of targets) {
306
- if (target.emitter !== emitter.name) continue;
307
- applyTunableTarget(emitter, target, values[param.key]);
308
- }
309
- }
310
- }
311
-
312
- function applyTunableTarget(emitter: LegacyEmitterConfig, target: LegacyTunableTarget, value: VfxParamValue): void {
313
- const operator = target.operator ?? 'set';
314
- if (operator === 'set') {
315
- setNestedValue(emitter, target.property, normalizeTunableValue(emitter, target.property, value));
316
- return;
317
- }
318
-
319
- if (operator === 'scaleDefault') {
320
- const multiplier = Number(value);
321
- const baseValue = Number(target.defaultValue ?? getNestedValue(emitter, target.property));
322
- if (!Number.isFinite(multiplier) || !Number.isFinite(baseValue)) return;
323
- setNestedValue(emitter, target.property, baseValue * multiplier);
324
- return;
325
- }
326
-
327
- if (operator === 'scaleVectorDefault') {
328
- const multiplier = Number(value);
329
- if (!Number.isFinite(multiplier)) return;
330
- setNestedValue(emitter, target.property, scaleVectorDefaultValue(target.defaultValue, multiplier));
331
- }
332
- }
333
-
334
- function scaleVectorDefaultValue(defaultValue: unknown, multiplier: number): unknown {
335
- if (!defaultValue || typeof defaultValue !== 'object' || Array.isArray(defaultValue)) return defaultValue;
336
-
337
- const source = defaultValue as { x?: unknown; y?: unknown; z?: unknown; scaleAxes?: unknown };
338
- const scaleAxes = source.scaleAxes && typeof source.scaleAxes === 'object' && !Array.isArray(source.scaleAxes)
339
- ? source.scaleAxes as Record<string, unknown>
340
- : { x: true, y: true, z: true };
341
-
342
- const scaleComponent = (axis: 'x' | 'y' | 'z') => {
343
- const base = Number(source[axis] ?? 0);
344
- if (!Number.isFinite(base)) return 0;
345
- return scaleAxes[axis] === false ? base : base * multiplier;
346
- };
347
-
348
- return {
349
- x: scaleComponent('x'),
350
- y: scaleComponent('y'),
351
- z: scaleComponent('z'),
352
- };
353
- }
354
-
355
- function setNestedValue(target: Record<string, unknown>, path: string, value: unknown): void {
356
- const parts = path.split('.').filter(Boolean);
357
- if (parts.length === 0) return;
358
-
359
- let cursor: Record<string, unknown> = target;
360
- for (const part of parts.slice(0, -1)) {
361
- const next = cursor[part];
362
- if (!next || typeof next !== 'object' || Array.isArray(next)) {
363
- cursor[part] = {};
364
- }
365
- cursor = cursor[part] as Record<string, unknown>;
366
- }
367
-
368
- cursor[parts[parts.length - 1]] = value;
369
- }
370
-
371
- function normalizeTunableValue(emitter: LegacyEmitterConfig, path: string, value: VfxParamValue): unknown {
372
- if (isColorValue(value)) {
373
- return {
374
- r: value.r,
375
- g: value.g,
376
- b: value.b,
377
- a: readExistingAlpha(emitter, path),
378
- };
379
- }
380
-
381
- if (typeof value !== 'string' || !/^#[0-9a-f]{6}$/i.test(value)) return value;
382
-
383
- const alpha = readExistingAlpha(emitter, path);
384
-
385
- return {
386
- r: parseInt(value.slice(1, 3), 16) / 255,
387
- g: parseInt(value.slice(3, 5), 16) / 255,
388
- b: parseInt(value.slice(5, 7), 16) / 255,
389
- a: alpha,
390
- };
391
- }
392
-
393
- function readExistingAlpha(emitter: LegacyEmitterConfig, path: string): number {
394
- const existing = getNestedValue(emitter, path);
395
- const alpha = existing && typeof existing === 'object' && 'a' in existing
396
- ? Number((existing as { a?: unknown }).a)
397
- : 1;
398
- return Number.isFinite(alpha) ? alpha : 1;
399
- }
400
-
401
- function getNestedValue(target: Record<string, unknown>, path: string): unknown {
402
- let cursor: unknown = target;
403
- for (const part of path.split('.').filter(Boolean)) {
404
- if (!cursor || typeof cursor !== 'object' || Array.isArray(cursor)) return undefined;
405
- cursor = (cursor as Record<string, unknown>)[part];
406
- }
407
- return cursor;
408
- }
409
-
410
- function buildDefaultParams(manifest: LegacyEffectManifest): VfxParamValues {
411
- const params: VfxParamValues = {};
412
- for (const [key, value] of Object.entries(manifest.defaultParams ?? {})) {
413
- if (isVfxParamValue(value)) params[key] = value;
414
- }
415
- for (const param of manifest.tunableParams ?? []) {
416
- if (param.default !== undefined && isVfxParamValue(param.default)) {
417
- params[param.key] = param.default;
418
- }
419
- }
420
- return params;
421
- }
422
-
423
- function buildDebugParams(manifest: LegacyEffectManifest): VfxParamDefinition[] {
424
- const result: VfxParamDefinition[] = [];
425
- for (const param of manifest.tunableParams ?? []) {
426
- const label = param.labelZh ?? param.label ?? param.labelEn ?? param.key;
427
- if (param.type === 'number') {
428
- result.push({
429
- key: param.key,
430
- label,
431
- kind: 'number',
432
- min: param.min,
433
- max: param.max,
434
- step: param.step,
435
- });
436
- continue;
437
- }
438
- if (param.type === 'color') {
439
- result.push({
440
- key: param.key,
441
- label,
442
- kind: 'color',
443
- });
444
- continue;
445
- }
446
- if (param.type === 'enum' && Array.isArray(param.options)) {
447
- result.push({
448
- key: param.key,
449
- label,
450
- kind: 'enum',
451
- options: param.options.map((option) => ({
452
- value: option.value,
453
- label: option.label ?? option.value,
454
- })),
455
- });
456
- }
457
- }
458
- return result;
459
- }
460
-
461
- function isVfxParamValue(value: unknown): value is VfxParamValue {
462
- if (typeof value === 'number') return Number.isFinite(value);
463
- if (typeof value === 'string') return true;
464
- if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
465
- const color = value as Record<string, unknown>;
466
- return typeof color.r === 'number'
467
- && Number.isFinite(color.r)
468
- && typeof color.g === 'number'
469
- && Number.isFinite(color.g)
470
- && typeof color.b === 'number'
471
- && Number.isFinite(color.b);
472
- }
473
-
474
- function isColorValue(value: unknown): value is VfxColorValue {
475
- if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
476
- const color = value as Record<string, unknown>;
477
- return typeof color.r === 'number'
478
- && Number.isFinite(color.r)
479
- && typeof color.g === 'number'
480
- && Number.isFinite(color.g)
481
- && typeof color.b === 'number'
482
- && Number.isFinite(color.b);
483
- }
484
-
485
- function normalizeDebugAnchor(value: string | undefined): VfxDebugAnchor | undefined {
486
- return value === 'player' || value === 'playerRight' ? value : undefined;
487
- }
488
-
489
- function collectManifestAssetPaths(manifest: LegacyEffectManifest): string[] {
490
- const paths: string[] = [];
491
- const collect = (value: unknown): void => {
492
- if (Array.isArray(value)) {
493
- for (const item of value) collect(item);
494
- return;
495
- }
496
- if (!value || typeof value !== 'object') return;
497
- const record = value as Record<string, unknown>;
498
- if (typeof record.packagePath === 'string') paths.push(record.packagePath);
499
- for (const child of Object.values(record)) collect(child);
500
- };
501
- collect(manifest.assets);
502
- return Array.from(new Set(paths));
503
- }
504
-
505
- function readManifestSource(manifest: LegacyEffectManifest): string | undefined {
506
- if (typeof manifest.source === 'string') return manifest.source;
507
- if (!manifest.source || typeof manifest.source !== 'object') return undefined;
508
- const source = manifest.source as Record<string, unknown>;
509
- return typeof source.sourceId === 'string' ? source.sourceId : undefined;
510
- }
511
-
512
- function cloneEmitter(emitter: LegacyEmitterConfig): LegacyEmitterConfig {
513
- return JSON.parse(JSON.stringify(emitter)) as LegacyEmitterConfig;
514
- }
515
-
516
- function disposeRoot(root: TransformNode): void {
517
- if (typeof root.isDisposed === 'function' && root.isDisposed()) return;
518
- root.dispose(false, true);
519
- }
@@ -1,85 +0,0 @@
1
- // 注册表:库提供 buildRegistry(纯函数);glob 调用在「项目侧」(Vite 编译期相对解析),
2
- // 项目把 glob 结果传进来 → 得到一个 VfxRegistry,注入给 EffectPackageService。
3
- import type { VfxEffectPackage, VfxParamValues } from './types';
4
-
5
- export interface VfxRegistry {
6
- getEffectPackage(effectId: string): VfxEffectPackage | undefined;
7
- getEffectPackages(): VfxEffectPackage[];
8
- savedParams: Record<string, Partial<VfxParamValues>>;
9
- }
10
-
11
- export interface BuildRegistryInput {
12
- /** import.meta.glob('./effects/*\/index.ts', { eager: true }) 的结果 */
13
- modules: Record<string, Record<string, unknown>>;
14
- /** import.meta.glob('./effects/*\/vfx-params.json', { eager: true }) 的结果(可选) */
15
- params?: Record<string, { default: unknown } | unknown>;
16
- /** 可选:判定某目录是否仅调试用(prod 构建剔除) */
17
- isDebugOnly?: (dir: string) => boolean;
18
- /** 可选:prod 标志,配合 isDebugOnly 过滤 */
19
- prod?: boolean;
20
- }
21
-
22
- export function isVfxEffectPackage(value: unknown): value is VfxEffectPackage {
23
- return (
24
- !!value &&
25
- typeof value === 'object' &&
26
- typeof (value as VfxEffectPackage).id === 'string' &&
27
- typeof (value as VfxEffectPackage).create === 'function'
28
- );
29
- }
30
-
31
- function pickPackage(mod: Record<string, unknown>): VfxEffectPackage | null {
32
- if (isVfxEffectPackage((mod as { default?: unknown }).default)) {
33
- return (mod as { default: VfxEffectPackage }).default;
34
- }
35
- for (const value of Object.values(mod)) if (isVfxEffectPackage(value)) return value;
36
- return null;
37
- }
38
-
39
- function dirOf(path: string): string {
40
- const m = path.match(/\/effects\/([^/]+)\//) ?? path.match(/^\.\/effects\/([^/]+)\//);
41
- return m ? m[1] : path;
42
- }
43
-
44
- function sanitizeParamsFile(value: unknown): Partial<VfxParamValues> {
45
- const v = value && typeof value === 'object' && 'default' in (value as object)
46
- ? (value as { default: unknown }).default
47
- : value;
48
- if (!v || typeof v !== 'object' || Array.isArray(v)) return {};
49
- const params = (v as { params?: unknown }).params;
50
- if (params && typeof params === 'object' && !Array.isArray(params)) return params as Partial<VfxParamValues>;
51
- return v as Partial<VfxParamValues>;
52
- }
53
-
54
- export function buildRegistry(input: BuildRegistryInput): VfxRegistry {
55
- const paramsByDir: Record<string, Partial<VfxParamValues>> = {};
56
- for (const [path, mod] of Object.entries(input.params ?? {})) {
57
- paramsByDir[dirOf(path)] = sanitizeParamsFile(mod);
58
- }
59
-
60
- const map = new Map<string, VfxEffectPackage>();
61
- const savedParams: Record<string, Partial<VfxParamValues>> = {};
62
- for (const [path, mod] of Object.entries(input.modules)) {
63
- const dir = dirOf(path);
64
- if (input.prod && input.isDebugOnly?.(dir)) continue;
65
- const pkg = pickPackage(mod);
66
- if (!pkg) {
67
- console.warn('[vfx] no VfxEffectPackage export found in', path);
68
- continue;
69
- }
70
- if (map.has(pkg.id)) {
71
- throw new Error(`[vfx] duplicate effect id "${pkg.id}" (dir: ${dir})`);
72
- }
73
- const saved = paramsByDir[dir] ?? {};
74
- pkg.savedParams = saved;
75
- savedParams[pkg.id] = saved;
76
- map.set(pkg.id, pkg);
77
- }
78
-
79
- const list = [...map.values()].sort((a, b) => a.id.localeCompare(b.id));
80
- return {
81
- getEffectPackage: (id) => map.get(id),
82
- getEffectPackages: () => list,
83
- savedParams,
84
- };
85
- }
@@ -1,13 +0,0 @@
1
- import type { ParticleSystem } from '@babylonjs/core/Particles/particleSystem';
2
- import type { SpriteManager } from '@babylonjs/core/Sprites/spriteManager';
3
-
4
- export const VFX_RENDERING_GROUP_ID = 2;
5
-
6
- export function configureVfxSpriteManager(manager: SpriteManager): void {
7
- manager.renderingGroupId = VFX_RENDERING_GROUP_ID;
8
- manager.disableDepthWrite = true;
9
- }
10
-
11
- export function configureVfxParticleSystem(system: ParticleSystem): void {
12
- system.renderingGroupId = VFX_RENDERING_GROUP_ID;
13
- }