@fps-games/vfx 0.3.2 → 0.3.4
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.
- package/CHANGELOG.md +16 -0
- package/README.md +5 -5
- package/dist/effects/treasure-attention/index.d.ts +1 -1
- package/package.json +6 -5
- package/tooling/vfx-cli.mjs +31 -22
- package/tooling/vfx-package-resolution.mjs +8 -8
- package/docs/AUTHORING_EFFECTS.md +0 -297
- package/docs/INTEGRATION.md +0 -194
- package/docs/VFX_LIBRARY_ARCHITECTURE_chatgpt.md +0 -1580
- package/docs/VFX_LIBRARY_EXECUTION_PLAN.md +0 -229
- package/docs/VFX_LIBRARY_PLAN.md +0 -546
- package/docs/hit-flash-red-method.md +0 -155
- package/docs/treasure_attention_fx_babylonjs_guide.md +0 -901
- package/docs/vfx-ab/RESULTS.md +0 -35
- package/docs/vfx-ab/lumber-order/vehicle-exhaust-smoke/after.png +0 -0
- package/docs/vfx-ab/lumber-order/vehicle-exhaust-smoke/before.png +0 -0
- package/docs/vfx-ab/lumber-truck/vehicle-exhaust-smoke/after.png +0 -0
- package/docs/vfx-ab/lumber-truck/vehicle-exhaust-smoke/before.png +0 -0
- package/docs/vfx-integration_chatgpt.md +0 -462
- package/docs/vfx-placement-design.md +0 -164
- package/docs/weapon-trail-visualization.html +0 -241
- package/packages/EffectPackageService.ts +0 -346
- package/packages/SceneVfxService.ts +0 -96
- package/packages/build.mesh.yellow_build_upgrade_indicator/assets/runtime/simpleMeshEffect.v1.js +0 -333
- package/packages/build.mesh.yellow_build_upgrade_indicator/assets/shaders/mesh-effect-preview.frag.glsl +0 -25
- package/packages/build.mesh.yellow_build_upgrade_indicator/assets/shaders/mesh-effect-preview.vert.glsl +0 -11
- package/packages/build.mesh.yellow_build_upgrade_indicator/assets/textures/effect_jianbian.png +0 -0
- package/packages/build.mesh.yellow_build_upgrade_indicator/effect.json +0 -927
- package/packages/build.mesh.yellow_build_upgrade_indicator/media/contact-sheet.png +0 -0
- package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.gif +0 -0
- package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.mp4 +0 -0
- package/packages/build.mesh.yellow_build_upgrade_indicator/media/preview.webm +0 -0
- package/packages/build.mesh.yellow_build_upgrade_indicator/media/thumbnail.png +0 -0
- package/packages/build.mesh.yellow_build_upgrade_indicator/metadata/description.json +0 -197
- package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/03-effect.original.json +0 -895
- package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/03-normalized-vfx-to-babylon-report.json +0 -241
- package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/04-preview-overrides.json +0 -542
- package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/04-preview-tuning-report.json +0 -69
- package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/asset-map.json +0 -125
- package/packages/build.mesh.yellow_build_upgrade_indicator/provenance/lineage.json +0 -44
- package/packages/build.particle.golden_upgrade_starburst/assets/runtime/particleEmitter.v1.js +0 -210
- package/packages/build.particle.golden_upgrade_starburst/assets/textures/effect_guangdian.png +0 -0
- package/packages/build.particle.golden_upgrade_starburst/effect.json +0 -880
- package/packages/build.particle.golden_upgrade_starburst/media/contact-sheet.png +0 -0
- package/packages/build.particle.golden_upgrade_starburst/media/preview.gif +0 -0
- package/packages/build.particle.golden_upgrade_starburst/media/preview.mp4 +0 -0
- package/packages/build.particle.golden_upgrade_starburst/media/preview.webm +0 -0
- package/packages/build.particle.golden_upgrade_starburst/media/thumbnail.png +0 -0
- package/packages/build.particle.golden_upgrade_starburst/metadata/description.json +0 -161
- package/packages/build.particle.golden_upgrade_starburst/provenance/03-effect.original.json +0 -762
- package/packages/build.particle.golden_upgrade_starburst/provenance/03-normalized-vfx-to-babylon-report.json +0 -260
- package/packages/build.particle.golden_upgrade_starburst/provenance/04-preview-overrides.json +0 -436
- package/packages/build.particle.golden_upgrade_starburst/provenance/04-preview-tuning-report.json +0 -40
- package/packages/build.particle.golden_upgrade_starburst/provenance/asset-map.json +0 -115
- package/packages/build.particle.golden_upgrade_starburst/provenance/lineage.json +0 -40
- package/packages/build.particle.orange_upgrade_transform_sparks/assets/runtime/particleEmitter.v1.js +0 -210
- package/packages/build.particle.orange_upgrade_transform_sparks/assets/textures/b5b27ab1-e740-4398-b407-848fc2b2c897.png +0 -0
- package/packages/build.particle.orange_upgrade_transform_sparks/effect.json +0 -887
- package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.gif +0 -0
- package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.mp4 +0 -0
- package/packages/build.particle.orange_upgrade_transform_sparks/media/preview.webm +0 -0
- package/packages/build.particle.orange_upgrade_transform_sparks/media/thumbnail.png +0 -0
- package/packages/build.particle.orange_upgrade_transform_sparks/metadata/description.json +0 -179
- package/packages/build.particle.orange_upgrade_transform_sparks/provenance/03-effect.original.json +0 -859
- package/packages/build.particle.orange_upgrade_transform_sparks/provenance/03-normalized-vfx-to-babylon-report.json +0 -260
- package/packages/build.particle.orange_upgrade_transform_sparks/provenance/04-preview-overrides.json +0 -478
- package/packages/build.particle.orange_upgrade_transform_sparks/provenance/04-preview-tuning-report.json +0 -40
- package/packages/build.particle.orange_upgrade_transform_sparks/provenance/asset-map.json +0 -114
- package/packages/build.particle.orange_upgrade_transform_sparks/provenance/lineage.json +0 -41
- package/packages/build.particle.wood_chip_dust_burst/assets/runtime/particleEmitter.v1.js +0 -210
- package/packages/build.particle.wood_chip_dust_burst/assets/textures/effect_yanwu4.png +0 -0
- package/packages/build.particle.wood_chip_dust_burst/assets/textures/suipian3.png +0 -0
- package/packages/build.particle.wood_chip_dust_burst/effect.json +0 -1400
- package/packages/build.particle.wood_chip_dust_burst/media/contact-sheet.png +0 -0
- package/packages/build.particle.wood_chip_dust_burst/media/preview.gif +0 -0
- package/packages/build.particle.wood_chip_dust_burst/media/preview.mp4 +0 -0
- package/packages/build.particle.wood_chip_dust_burst/media/preview.webm +0 -0
- package/packages/build.particle.wood_chip_dust_burst/media/thumbnail.png +0 -0
- package/packages/build.particle.wood_chip_dust_burst/metadata/description.json +0 -173
- package/packages/build.particle.wood_chip_dust_burst/provenance/03-effect.original.json +0 -1277
- package/packages/build.particle.wood_chip_dust_burst/provenance/03-normalized-vfx-to-babylon-report.json +0 -329
- package/packages/build.particle.wood_chip_dust_burst/provenance/04-preview-overrides.json +0 -749
- package/packages/build.particle.wood_chip_dust_burst/provenance/04-preview-tuning-report.json +0 -60
- package/packages/build.particle.wood_chip_dust_burst/provenance/asset-map.json +0 -146
- package/packages/build.particle.wood_chip_dust_burst/provenance/lineage.json +0 -69
- package/packages/effects/building-upgrade/effect.json +0 -6
- package/packages/effects/building-upgrade/index.ts +0 -387
- package/packages/effects/character-entrance/effect.json +0 -6
- package/packages/effects/character-entrance/index.ts +0 -308
- package/packages/effects/coin-burst/index.ts +0 -48
- package/packages/effects/comet-trail-flame/assets/textures/trail_5x4.webp +0 -0
- package/packages/effects/comet-trail-flame/index.ts +0 -107
- package/packages/effects/conveyor-upgrade/effect.json +0 -6
- package/packages/effects/conveyor-upgrade/index.ts +0 -401
- package/packages/effects/debris-smoke/assets/models/rock_debris.glb +0 -0
- package/packages/effects/debris-smoke/assets/textures/smoke22.webp +0 -0
- package/packages/effects/debris-smoke/index.ts +0 -102
- package/packages/effects/door_open_gold_flakes/assets/runtime/goldFlakes.v1.js +0 -397
- package/packages/effects/door_open_gold_flakes/door_open_gold_flakes.json +0 -498
- package/packages/effects/door_open_gold_flakes/index.ts +0 -11
- package/packages/effects/electric-arc/assets/textures/spark_4x4.webp +0 -0
- package/packages/effects/electric-arc/index.ts +0 -63
- package/packages/effects/energy-shield/effect.json +0 -7
- package/packages/effects/energy-shield/index.ts +0 -432
- package/packages/effects/explosion/assets/textures/baozha29.webp +0 -0
- package/packages/effects/explosion/assets/textures/glow01.webp +0 -0
- package/packages/effects/explosion/assets/textures/lizi01.webp +0 -0
- package/packages/effects/explosion/assets/textures/xulie_lizibaozha02_5x5.webp +0 -0
- package/packages/effects/explosion/index.ts +0 -115
- package/packages/effects/ground-tile-upgrade/effect.json +0 -6
- package/packages/effects/ground-tile-upgrade/index.ts +0 -410
- package/packages/effects/hit-flash/index.ts +0 -77
- package/packages/effects/laser-beam/assets/textures/laser_glow.webp +0 -0
- package/packages/effects/laser-beam/assets/textures/laser_noise.webp +0 -0
- package/packages/effects/laser-beam/index.ts +0 -6
- package/packages/effects/laser-beam-factory.ts +0 -146
- package/packages/effects/lumber-cart-suction/effect.json +0 -6
- package/packages/effects/lumber-cart-suction/index.ts +0 -399
- package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb +0 -0
- package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb.versions/.active +0 -1
- package/packages/effects/lumber-debris-scatter/assets/models/lumber_prop_model.glb.versions/1781589063890_upload.glb +0 -0
- package/packages/effects/lumber-debris-scatter/assets/runtime/solidParticleScatter.v1.js +0 -236
- package/packages/effects/lumber-debris-scatter/effect.json +0 -228
- package/packages/effects/lumber-debris-scatter/index.ts +0 -780
- package/packages/effects/lumber_vehicle_gear_spin/assets/runtime/gearSpin.v1.js +0 -202
- package/packages/effects/lumber_vehicle_gear_spin/index.ts +0 -11
- package/packages/effects/lumber_vehicle_gear_spin/lumber_vehicle_gear_spin.json +0 -338
- package/packages/effects/lumber_vehicle_upgrade_aura/assets/runtime/upgradeAura.v1.js +0 -353
- package/packages/effects/lumber_vehicle_upgrade_aura/index.ts +0 -13
- package/packages/effects/lumber_vehicle_upgrade_aura/lumber_vehicle_upgrade_aura.json +0 -365
- package/packages/effects/lumber_vehicle_wood_chips/assets/runtime/solidParticleScatter.v1.js +0 -310
- package/packages/effects/lumber_vehicle_wood_chips/index.ts +0 -11
- package/packages/effects/lumber_vehicle_wood_chips/lumber_vehicle_wood_chips.json +0 -335
- package/packages/effects/monster-hit/index.ts +0 -129
- package/packages/effects/player-upgrade/effect.json +0 -6
- package/packages/effects/player-upgrade/index.ts +0 -640
- package/packages/effects/pulse-laser-volley/assets/textures/bolt_guangshu.webp +0 -0
- package/packages/effects/pulse-laser-volley/index.ts +0 -215
- package/packages/effects/resource-collect-sparkles/effect.json +0 -6
- package/packages/effects/resource-collect-sparkles/index.ts +0 -254
- package/packages/effects/run-footstep-dust/assets/runtime/runFootstepDust.v1.js +0 -215
- package/packages/effects/run-footstep-dust/effect.json +0 -183
- package/packages/effects/run-footstep-dust/index.ts +0 -377
- package/packages/effects/space-shared.ts +0 -120
- package/packages/effects/thruster-flame/index.ts +0 -306
- package/packages/effects/treasure-attention/effect.json +0 -7
- package/packages/effects/treasure-attention/index.ts +0 -630
- package/packages/effects/tree-chop-dust/assets/textures/tree_chop_dust_atlas.png +0 -0
- package/packages/effects/tree-chop-dust/effect.json +0 -8
- package/packages/effects/tree-chop-dust/index.ts +0 -202
- package/packages/effects/tree-leaf-chop-burst/assets/runtime/particleEmitter.v1.js +0 -303
- package/packages/effects/tree-leaf-chop-burst/assets/textures/tree_leaf_chop_burst_leaf_atlas.png +0 -0
- package/packages/effects/tree-leaf-chop-burst/effect.json +0 -498
- package/packages/effects/tree-leaf-chop-burst/index.ts +0 -294
- package/packages/effects/tree_chop_dust_burst/assets/runtime/particleEmitter.v1.js +0 -318
- package/packages/effects/tree_chop_dust_burst/assets/textures/tree_chop_dust_burst_dust.png +0 -0
- package/packages/effects/tree_chop_dust_burst/index.ts +0 -13
- package/packages/effects/tree_chop_dust_burst/tree_chop_dust_burst.json +0 -412
- package/packages/effects/ufo-thread-flame/assets/textures/flame_flow.webp +0 -0
- package/packages/effects/ufo-thread-flame/assets/textures/flame_spike.webp +0 -0
- package/packages/effects/ufo-thread-flame/index.ts +0 -153
- package/packages/effects/vehicle-exhaust-smoke/assets/textures/vehicle_exhaust_smoke_atlas.png +0 -0
- package/packages/effects/vehicle-exhaust-smoke/effect.json +0 -8
- package/packages/effects/vehicle-exhaust-smoke/index.ts +0 -298
- package/packages/effects/vehicle-upgrade/effect.json +0 -6
- package/packages/effects/vehicle-upgrade/index.ts +0 -404
- package/packages/effects/weapon-trail/assets/textures/trail_wedge.png +0 -0
- package/packages/effects/weapon-trail/index.ts +0 -317
- package/packages/effects/wood-crusher-sawdust/assets/runtime/particleEmitter.v1.js +0 -312
- package/packages/effects/wood-crusher-sawdust/assets/textures/wood_crusher_sawdust_dust.png +0 -0
- package/packages/effects/wood-crusher-sawdust/assets/textures/wood_crusher_sawdust_fiber.png +0 -0
- package/packages/effects/wood-crusher-sawdust/index.ts +0 -43
- package/packages/effects/wood-crusher-sawdust/wood_crusher_sawdust.json +0 -592
- package/packages/effects/wood-cutter-sawdust/assets/runtime/particleEmitter.v1.js +0 -312
- package/packages/effects/wood-cutter-sawdust/assets/textures/wood_cutter_sawdust_chip.png +0 -0
- package/packages/effects/wood-cutter-sawdust/assets/textures/wood_cutter_sawdust_dust.png +0 -0
- package/packages/effects/wood-cutter-sawdust/index.ts +0 -43
- package/packages/effects/wood-cutter-sawdust/wood_cutter_sawdust.json +0 -592
- package/packages/effects/wood-sawdust-effect-factory.ts +0 -194
- package/packages/effects/wood_crusher_sawdust/assets/runtime/particleEmitter.v1.js +0 -318
- package/packages/effects/wood_crusher_sawdust/assets/textures/wood_crusher_sawdust_dust.png +0 -0
- package/packages/effects/wood_crusher_sawdust/assets/textures/wood_crusher_sawdust_fiber.png +0 -0
- package/packages/effects/wood_crusher_sawdust/index.ts +0 -29
- package/packages/effects/wood_crusher_sawdust/wood_crusher_sawdust.json +0 -592
- package/packages/effects/wood_cutter_sawdust/assets/runtime/particleEmitter.v1.js +0 -318
- package/packages/effects/wood_cutter_sawdust/assets/textures/wood_cutter_sawdust_chip.png +0 -0
- package/packages/effects/wood_cutter_sawdust/assets/textures/wood_cutter_sawdust_dust.png +0 -0
- package/packages/effects/wood_cutter_sawdust/index.ts +0 -29
- package/packages/effects/wood_cutter_sawdust/wood_cutter_sawdust.json +0 -592
- package/packages/effects/wood_peel_material_test/assets/runtime/woodPeelMaterialTest.v1.js +0 -196
- package/packages/effects/wood_peel_material_test/index.ts +0 -11
- package/packages/effects/wood_peel_material_test/wood_peel_material_test.json +0 -136
- package/packages/env.particle.forest_edge_fog/assets/runtime/particleEmitter.v1.js +0 -210
- package/packages/env.particle.forest_edge_fog/assets/textures/f12a23c4-b924-4322-a260-3d982428f1e8.png +0 -0
- package/packages/env.particle.forest_edge_fog/assets/textures/yuan.png +0 -0
- package/packages/env.particle.forest_edge_fog/effect.json +0 -854
- package/packages/env.particle.forest_edge_fog/media/preview.gif +0 -0
- package/packages/env.particle.forest_edge_fog/media/preview.mp4 +0 -0
- package/packages/env.particle.forest_edge_fog/media/preview.webm +0 -0
- package/packages/env.particle.forest_edge_fog/media/thumbnail.png +0 -0
- package/packages/env.particle.forest_edge_fog/metadata/description.json +0 -148
- package/packages/env.particle.forest_edge_fog/provenance/03-effect.original.json +0 -827
- package/packages/env.particle.forest_edge_fog/provenance/03-normalized-vfx-to-babylon-report.json +0 -196
- package/packages/env.particle.forest_edge_fog/provenance/04-preview-overrides.json +0 -432
- package/packages/env.particle.forest_edge_fog/provenance/04-preview-tuning-report.json +0 -28
- package/packages/env.particle.forest_edge_fog/provenance/asset-map.json +0 -124
- package/packages/env.particle.forest_edge_fog/provenance/lineage.json +0 -41
- package/packages/generation.ts +0 -14
- package/packages/index.ts +0 -14
- package/packages/legacy-particle-runtime.ts +0 -113
- package/packages/manifestRuntimePackage.ts +0 -519
- package/packages/registry.ts +0 -85
- package/packages/rendering.ts +0 -13
- package/packages/resource.particle.viscous_oil_suction/assets/runtime/top_disk_suction/particleEmitter.v1.js +0 -424
- package/packages/resource.particle.viscous_oil_suction/assets/textures/Glow ad.png +0 -0
- package/packages/resource.particle.viscous_oil_suction/effect.json +0 -1254
- package/packages/resource.particle.viscous_oil_suction/media/preview.gif +0 -0
- package/packages/resource.particle.viscous_oil_suction/media/preview.mp4 +0 -0
- package/packages/resource.particle.viscous_oil_suction/media/preview.webm +0 -0
- package/packages/resource.particle.viscous_oil_suction/media/thumbnail.png +0 -0
- package/packages/resource.particle.viscous_oil_suction/metadata/description.json +0 -122
- package/packages/resource.particle.viscous_oil_suction/provenance/03-effect.original.json +0 -1051
- package/packages/resource.particle.viscous_oil_suction/provenance/03-normalized-vfx-to-babylon-report.json +0 -200
- package/packages/resource.particle.viscous_oil_suction/provenance/04-preview-overrides.json +0 -581
- package/packages/resource.particle.viscous_oil_suction/provenance/04-preview-tuning-report.json +0 -28
- package/packages/resource.particle.viscous_oil_suction/provenance/asset-map.json +0 -111
- package/packages/resource.particle.viscous_oil_suction/provenance/lineage.json +0 -45
- package/packages/types.ts +0 -195
- package/tooling/check-dist-runtime.mjs +0 -166
- package/tooling/generate-index.mjs +0 -55
- package/tooling/test-guardrails.mjs +0 -157
- package/tooling/validate-boundary.mjs +0 -92
- package/tooling/validate-effects.mjs +0 -304
- package/tooling/validate.mjs +0 -53
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"schemaVersion": "vfx-asset-map/1.0",
|
|
3
|
-
"generatedAt": "2026-05-21T13:04:29.644Z",
|
|
4
|
-
"sourcePackage": "vfx-intermediate/cocos-babylon-packages/gas_town_oil_suction",
|
|
5
|
-
"policy": {
|
|
6
|
-
"runtimeAssetsRoot": "assets/",
|
|
7
|
-
"sourceAssetsRoot": "source/",
|
|
8
|
-
"note": "assets/ contains files loaded by Babylon runtime. source/cocos/assets/ preserves the original Cocos asset tree for traceability and reconversion."
|
|
9
|
-
},
|
|
10
|
-
"entries": [
|
|
11
|
-
{
|
|
12
|
-
"id": "glow_ad",
|
|
13
|
-
"kind": "texture",
|
|
14
|
-
"group": "textures",
|
|
15
|
-
"role": "babylon-runtime",
|
|
16
|
-
"runtimeUse": true,
|
|
17
|
-
"packagePath": "assets/textures/Glow ad.png",
|
|
18
|
-
"sourcePackagePath": "assets/textures/Glow ad.png",
|
|
19
|
-
"sourceArchivePath": "source/cocos/assets/ArtResources/Effect/GasTown_OilSuction/Glow ad.png",
|
|
20
|
-
"sourcePath": "gs://fps-vfx-library/packages/resource.particle.viscous_oil_suction/source/cocos/assets/ArtResources/Effect/GasTown_OilSuction/Glow ad.png",
|
|
21
|
-
"sourceId": "dd44b0a9-0998-4c24-ba2e-d6ac9d1bebb7@6c48a",
|
|
22
|
-
"usedBy": [],
|
|
23
|
-
"originalProjectPath": "assets/ArtResources/Effect/GasTown_OilSuction/Glow ad.png"
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"id": "asset",
|
|
27
|
-
"kind": "material",
|
|
28
|
-
"group": "materials",
|
|
29
|
-
"role": "source-evidence",
|
|
30
|
-
"runtimeUse": false,
|
|
31
|
-
"packagePath": "source/cocos/assets/ArtResources/Effect/GasTown_OilSuction/石油.mtl",
|
|
32
|
-
"sourcePackagePath": "assets/materials/石油.mtl",
|
|
33
|
-
"sourceArchivePath": "source/cocos/assets/ArtResources/Effect/GasTown_OilSuction/石油.mtl",
|
|
34
|
-
"sourcePath": "gs://fps-vfx-library/packages/resource.particle.viscous_oil_suction/source/cocos/assets/ArtResources/Effect/GasTown_OilSuction/石油.mtl",
|
|
35
|
-
"sourceId": "4aabf2b0-1d20-4e13-9384-ae47eb8522aa",
|
|
36
|
-
"usedBy": [],
|
|
37
|
-
"originalProjectPath": "assets/ArtResources/Effect/GasTown_OilSuction/石油.mtl"
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
"id": "particle_emitter_oil_suction_v1",
|
|
41
|
-
"kind": "script",
|
|
42
|
-
"group": "scripts",
|
|
43
|
-
"role": "babylon-runtime",
|
|
44
|
-
"runtimeUse": true,
|
|
45
|
-
"packagePath": "assets/runtime/gas_town_oil_suction/particleEmitter.v1.js",
|
|
46
|
-
"sourcePackagePath": "assets/runtime/gas_town_oil_suction/particleEmitter.v1.js",
|
|
47
|
-
"sourceArchivePath": null,
|
|
48
|
-
"sourcePath": null,
|
|
49
|
-
"sourceId": null,
|
|
50
|
-
"usedBy": []
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
"id": "02-normalized-vfx",
|
|
54
|
-
"kind": "raw",
|
|
55
|
-
"group": "raw",
|
|
56
|
-
"role": "source-evidence",
|
|
57
|
-
"runtimeUse": false,
|
|
58
|
-
"packagePath": "source/02-normalized-vfx.json",
|
|
59
|
-
"sourcePackagePath": "source/02-normalized-vfx.json",
|
|
60
|
-
"sourceArchivePath": null,
|
|
61
|
-
"sourcePath": "gs://fps-vfx-library/packages/resource.particle.viscous_oil_suction/source/02-normalized-vfx.json",
|
|
62
|
-
"sourceId": null,
|
|
63
|
-
"usedBy": []
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
"id": "01-source-dump",
|
|
67
|
-
"kind": "raw",
|
|
68
|
-
"group": "raw",
|
|
69
|
-
"role": "source-evidence",
|
|
70
|
-
"runtimeUse": false,
|
|
71
|
-
"packagePath": "source/01-source-dump.json",
|
|
72
|
-
"sourcePackagePath": "source/01-source-dump.json",
|
|
73
|
-
"sourceArchivePath": null,
|
|
74
|
-
"sourcePath": "gs://fps-vfx-library/packages/resource.particle.viscous_oil_suction/source/01-source-dump.json",
|
|
75
|
-
"sourceId": null,
|
|
76
|
-
"usedBy": []
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
"id": "asset",
|
|
80
|
-
"kind": "raw",
|
|
81
|
-
"group": "raw",
|
|
82
|
-
"role": "source-evidence",
|
|
83
|
-
"runtimeUse": false,
|
|
84
|
-
"packagePath": "source/raw/吸石油.prefab",
|
|
85
|
-
"sourcePackagePath": "source/raw/吸石油.prefab",
|
|
86
|
-
"sourceArchivePath": "source/cocos/assets/ArtResources/Effect/GasTown_OilSuction/吸石油.prefab",
|
|
87
|
-
"sourcePath": "gs://fps-vfx-library/packages/resource.particle.viscous_oil_suction/source/cocos/assets/ArtResources/Effect/GasTown_OilSuction/吸石油.prefab",
|
|
88
|
-
"sourceId": "29954e7e-d137-4c8b-a730-4f0320cbece8",
|
|
89
|
-
"usedBy": [],
|
|
90
|
-
"originalProjectPath": "assets/ArtResources/Effect/GasTown_OilSuction/吸石油.prefab"
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
"id": "asset.meta",
|
|
94
|
-
"kind": "raw",
|
|
95
|
-
"group": "raw",
|
|
96
|
-
"role": "source-evidence",
|
|
97
|
-
"runtimeUse": false,
|
|
98
|
-
"packagePath": "source/raw/吸石油.prefab.meta",
|
|
99
|
-
"sourcePackagePath": "source/raw/吸石油.prefab.meta",
|
|
100
|
-
"sourceArchivePath": "source/cocos/assets/ArtResources/Effect/GasTown_OilSuction/吸石油.prefab.meta",
|
|
101
|
-
"sourcePath": "gs://fps-vfx-library/packages/resource.particle.viscous_oil_suction/source/cocos/assets/ArtResources/Effect/GasTown_OilSuction/吸石油.prefab.meta",
|
|
102
|
-
"sourceId": "29954e7e-d137-4c8b-a730-4f0320cbece8",
|
|
103
|
-
"usedBy": [],
|
|
104
|
-
"originalProjectPath": "assets/ArtResources/Effect/GasTown_OilSuction/吸石油.prefab.meta"
|
|
105
|
-
}
|
|
106
|
-
],
|
|
107
|
-
"gcsPrefix": "gs://fps-vfx-library/packages/resource.particle.viscous_oil_suction",
|
|
108
|
-
"sourceArchivePrefix": "gs://fps-vfx-library/packages/resource.particle.viscous_oil_suction/source",
|
|
109
|
-
"fullProvenancePrefix": "gs://fps-vfx-library/packages/resource.particle.viscous_oil_suction/provenance",
|
|
110
|
-
"canonicalSource": "gcs"
|
|
111
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"schemaVersion": "vfx-library-lineage/1.0",
|
|
3
|
-
"savedAt": "2026-05-21T13:04:29.665Z",
|
|
4
|
-
"sourcePackage": "vfx-intermediate/cocos-babylon-packages/gas_town_oil_suction",
|
|
5
|
-
"sourceEffect": "03-effect.json",
|
|
6
|
-
"libraryPackage": "packages/resource.particle.viscous_oil_suction",
|
|
7
|
-
"effectId": "resource.particle.viscous_oil_suction",
|
|
8
|
-
"media": {
|
|
9
|
-
"previewVideo": "media/preview.webm",
|
|
10
|
-
"previewWebm": "media/preview.webm",
|
|
11
|
-
"previewMp4": "media/preview.mp4",
|
|
12
|
-
"previewGif": "media/preview.gif",
|
|
13
|
-
"thumbnail": "media/thumbnail.png",
|
|
14
|
-
"gcsUri": null
|
|
15
|
-
},
|
|
16
|
-
"recording": {
|
|
17
|
-
"provider": "browser-mediarecorder",
|
|
18
|
-
"recordedAt": "2026-05-21T13:04:30.575Z",
|
|
19
|
-
"mimeType": "video/webm;codecs=vp9",
|
|
20
|
-
"durationSec": 10,
|
|
21
|
-
"fps": 30,
|
|
22
|
-
"media": {
|
|
23
|
-
"previewVideo": "media/preview.webm",
|
|
24
|
-
"previewWebm": "media/preview.webm",
|
|
25
|
-
"previewMp4": "media/preview.mp4",
|
|
26
|
-
"previewGif": "media/preview.gif",
|
|
27
|
-
"thumbnail": "media/thumbnail.png",
|
|
28
|
-
"gcsUri": null
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
"description": {
|
|
32
|
-
"provider": "litellm",
|
|
33
|
-
"status": "described",
|
|
34
|
-
"model": "gemini-3.1-pro-preview",
|
|
35
|
-
"generatedAt": "2026-05-21T13:30:34.263Z"
|
|
36
|
-
},
|
|
37
|
-
"gcsPrefix": "gs://fps-vfx-library/packages/resource.particle.viscous_oil_suction",
|
|
38
|
-
"sourceArchivePrefix": "gs://fps-vfx-library/packages/resource.particle.viscous_oil_suction/source",
|
|
39
|
-
"fullProvenancePrefix": "gs://fps-vfx-library/packages/resource.particle.viscous_oil_suction/provenance",
|
|
40
|
-
"previousIds": [
|
|
41
|
-
"world.particle.gas_town_oil_suction",
|
|
42
|
-
"world.particle.viscous_oil_suction"
|
|
43
|
-
],
|
|
44
|
-
"renamedAt": "2026-05-21T13:39:08.485Z"
|
|
45
|
-
}
|
package/packages/types.ts
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
import type { Scene } from '@babylonjs/core/scene';
|
|
2
|
-
import type { Vector3 } from '@babylonjs/core/Maths/math.vector';
|
|
3
|
-
import type { TransformNode } from '@babylonjs/core/Meshes/transformNode';
|
|
4
|
-
import type { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh';
|
|
5
|
-
|
|
6
|
-
export type VfxDebugAnchor = 'playerRight' | 'player';
|
|
7
|
-
|
|
8
|
-
// ── 运行时外部信息(inputs)──────────────────────────────────────────────
|
|
9
|
-
// 与 params(设计期可调、保存)区分:inputs 是运行时由游戏逻辑提供的外部上下文,常动态。
|
|
10
|
-
// 值可为静态值或 provider(() => 值);动态目标(移动)用 provider 每帧取。见 docs/vfx-placement-design.md。
|
|
11
|
-
export type VfxInput<T> = T | (() => T);
|
|
12
|
-
export type VfxInputKey = 'aim' | 'normal' | 'endpoints' | 'target';
|
|
13
|
-
|
|
14
|
-
/** 调用方提供的 inputs(放在 VfxSpawnTransform.inputs)。 */
|
|
15
|
-
export interface VfxEffectInputs {
|
|
16
|
-
aim?: VfxInput<Vector3>; // 瞄准点(激光/定向武器)
|
|
17
|
-
normal?: VfxInput<Vector3>; // 表面法线(贴花/冲击)
|
|
18
|
-
endpoints?: Array<VfxInput<Vector3>>; // link/链式(≥2 端点)
|
|
19
|
-
target?: AbstractMesh; // target-material 类(改目标自身材质)
|
|
20
|
-
/** 运行时标量(throttle/intensity 等),值可静态或 provider;特效每帧读取做活改(G5)。 */
|
|
21
|
-
scalars?: Record<string, VfxInput<number>>;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** create() 收到的、已归一化为访问器的 inputs(provider 与静态值都变成可调用的函数)。 */
|
|
25
|
-
export interface VfxResolvedInputs {
|
|
26
|
-
aim?: () => Vector3;
|
|
27
|
-
normal?: () => Vector3;
|
|
28
|
-
endpoints?: Array<() => Vector3>;
|
|
29
|
-
target?: AbstractMesh;
|
|
30
|
-
scalars?: Record<string, () => number>;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export type VfxParamValue = number | string | VfxColorValue;
|
|
34
|
-
export type VfxParamValues = Record<string, VfxParamValue>;
|
|
35
|
-
|
|
36
|
-
export interface VfxColorValue {
|
|
37
|
-
r: number;
|
|
38
|
-
g: number;
|
|
39
|
-
b: number;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export type VfxParamKind =
|
|
43
|
-
| 'number'
|
|
44
|
-
| 'color'
|
|
45
|
-
| 'enum'
|
|
46
|
-
| 'opacity'
|
|
47
|
-
| 'lifetime'
|
|
48
|
-
| 'scale';
|
|
49
|
-
|
|
50
|
-
export interface VfxParamDefinitionBase {
|
|
51
|
-
key: string;
|
|
52
|
-
label: string;
|
|
53
|
-
kind: VfxParamKind;
|
|
54
|
-
description?: string;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export interface VfxNumberParamDefinition extends VfxParamDefinitionBase {
|
|
58
|
-
kind: 'number' | 'opacity' | 'lifetime' | 'scale';
|
|
59
|
-
min?: number;
|
|
60
|
-
max?: number;
|
|
61
|
-
step?: number;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export interface VfxColorParamDefinition extends VfxParamDefinitionBase {
|
|
65
|
-
kind: 'color';
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export interface VfxEnumParamOption {
|
|
69
|
-
value: string;
|
|
70
|
-
label: string;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface VfxEnumParamDefinition extends VfxParamDefinitionBase {
|
|
74
|
-
kind: 'enum';
|
|
75
|
-
options: VfxEnumParamOption[];
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export type VfxParamDefinition = VfxNumberParamDefinition | VfxColorParamDefinition | VfxEnumParamDefinition;
|
|
79
|
-
|
|
80
|
-
export interface VfxEffectPackageContext<PParams extends VfxParamValues = VfxParamValues> {
|
|
81
|
-
scene: Scene;
|
|
82
|
-
root: TransformNode;
|
|
83
|
-
position: Vector3;
|
|
84
|
-
rotationY: number;
|
|
85
|
-
renderingGroupId?: number;
|
|
86
|
-
params: PParams;
|
|
87
|
-
/**
|
|
88
|
-
* 解析后的三轴缩放(来自 spawnTransform.scale,默认 (1,1,1))。
|
|
89
|
-
* root 的缩放由 service 写好;但**几何不挂 root 的 world/detached 特效**(粒子/抛物池/世界坐标 emitter)
|
|
90
|
-
* root.scaling 作用不到,须自行把 ctx.scale 乘进几何尺寸/初速(G3)。
|
|
91
|
-
*/
|
|
92
|
-
scale: Vector3;
|
|
93
|
-
/** 运行时外部信息(已归一化为访问器)。link/target/定向武器/活改标量等按 required/optionalInputs 读取。 */
|
|
94
|
-
inputs?: VfxResolvedInputs;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export interface VfxEffectHandle {
|
|
98
|
-
root: TransformNode;
|
|
99
|
-
ready?: Promise<void>;
|
|
100
|
-
dispose(): void;
|
|
101
|
-
/** 可选:运行时活改 params(无须 dispose+replay,避免重置缓动/可见闪)。声明即纳入契约(G5)。 */
|
|
102
|
-
update?(params: Partial<VfxParamValues>): void;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export interface VfxEffectManifest {
|
|
106
|
-
id: string;
|
|
107
|
-
nameZh: string;
|
|
108
|
-
assets?: string[];
|
|
109
|
-
source?: string;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export interface VfxSpawnParamKeys {
|
|
113
|
-
offsetX?: string;
|
|
114
|
-
offsetY?: string;
|
|
115
|
-
offsetZ?: string;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/** 欧拉角(弧度)/ 三轴缩放的纯数据三元组。 */
|
|
119
|
-
export interface VfxVector3Like {
|
|
120
|
-
x: number;
|
|
121
|
-
y: number;
|
|
122
|
-
z: number;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export interface VfxSpawnTransform {
|
|
126
|
-
position?: Vector3;
|
|
127
|
-
/**
|
|
128
|
-
* 兼容别名:绕 Y 轴旋转(弧度)。
|
|
129
|
-
* 若同时给了 `rotation`,以 `rotation` 为准;否则回退到 `rotationY`。
|
|
130
|
-
*/
|
|
131
|
-
rotationY?: number;
|
|
132
|
-
/** 完整欧拉角旋转(弧度);给了就覆盖 `rotationY`。 */
|
|
133
|
-
rotation?: VfxVector3Like;
|
|
134
|
-
/** 等比缩放(number)或三轴缩放;默认 1。 */
|
|
135
|
-
scale?: number | VfxVector3Like;
|
|
136
|
-
/** 挂载点节点;给了就把特效 root parent 到它(特效随之跟随)。 */
|
|
137
|
-
parent?: TransformNode;
|
|
138
|
-
/**
|
|
139
|
-
* position/rotation/scale 的坐标系解释:
|
|
140
|
-
* - 给了 `parent` 时默认 `true`:按相对 parent 的 **local** transform 解释;
|
|
141
|
-
* - 没给 `parent` 时默认 `false`:按 **世界坐标** 解释(保持现状行为)。
|
|
142
|
-
*/
|
|
143
|
-
offsetIsLocal?: boolean;
|
|
144
|
-
renderingGroupId?: number;
|
|
145
|
-
/** 运行时外部信息(瞄准点/法线/端点/目标 mesh);值可为静态或 provider(动态每帧取)。 */
|
|
146
|
-
inputs?: VfxEffectInputs;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export interface VfxParamsFile {
|
|
150
|
-
schemaVersion: string;
|
|
151
|
-
effectId?: string;
|
|
152
|
-
updatedAt?: string | null;
|
|
153
|
-
params?: Partial<VfxParamValues>;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* 特效的放置本质(内禀标记)。决定系统/binding/面板怎么放它,不靠猜。见 docs/vfx-placement-design.md。
|
|
158
|
-
* - 'socket' local:挂对象命名挂点、随它走(parent + follow)。
|
|
159
|
-
* - 'world' global:放世界某点、不跟随(fire-and-forget,可按法线定向)。
|
|
160
|
-
* - 'screen' global:屏幕/相机层(后处理/相机扰动/DOM 全屏),无 3D transform。
|
|
161
|
-
* - 'target' 改目标自身材质/渲染态,没有可 spawn 的 root。
|
|
162
|
-
* - 'link' 连 ≥2 个端点(每帧重建几何),单 parent 表达不了。
|
|
163
|
-
*/
|
|
164
|
-
export type VfxPlacement = 'socket' | 'world' | 'screen' | 'target' | 'link';
|
|
165
|
-
|
|
166
|
-
export interface VfxEffectPackage<PParams extends VfxParamValues = VfxParamValues> {
|
|
167
|
-
id: string;
|
|
168
|
-
nameZh: string;
|
|
169
|
-
manifest?: VfxEffectManifest;
|
|
170
|
-
defaultParams: PParams;
|
|
171
|
-
debugAnchor?: VfxDebugAnchor;
|
|
172
|
-
spawnParams?: VfxSpawnParamKeys;
|
|
173
|
-
savedParams?: Partial<VfxParamValues>;
|
|
174
|
-
debugParams: VfxParamDefinition[];
|
|
175
|
-
/** 放置本质标记(默认 'world')。 */
|
|
176
|
-
placement?: VfxPlacement;
|
|
177
|
-
/** 声明**必需**的运行时 inputs(link 必须给 endpoints/aim、target 类必须给 target mesh);service 缺失时 warn。 */
|
|
178
|
-
requiredInputs?: VfxInputKey[];
|
|
179
|
-
/** 声明**可选**的运行时 inputs(给了就用、不给走默认,如定向武器的 aim:给了朝目标、不给走挂点朝向);不触发缺失 warn(G2)。 */
|
|
180
|
-
optionalInputs?: VfxInputKey[];
|
|
181
|
-
/**
|
|
182
|
-
* 几何空间:'local'=几何挂 root 子节点随它刚性变换;'world'=几何用世界坐标、root 仅作每帧采样源(拖尾)。
|
|
183
|
-
* 默认随 placement 推断('socket'→local,其余→world)。
|
|
184
|
-
*/
|
|
185
|
-
geometrySpace?: 'local' | 'world';
|
|
186
|
-
/**
|
|
187
|
-
* 构建特效。**约定(G6):root 的 transform(position/rotation/scaling/parent)归 service 独占** ——
|
|
188
|
-
* service 在 create() 后会二次 `applySpawnToRoot` 覆盖,create 内写 `root.position/rotation/scaling` 会被静默清掉。
|
|
189
|
-
* 需要内部局部偏移(如抬升)请用 root 下的**子 TransformNode** 承载,或声明 `spawnParams.offsetY` 走 service 存活通道。
|
|
190
|
-
* 几何挂 root 子树即随挂载跟随;world/拖尾类几何走世界坐标、读 ctx.scale 缩放。
|
|
191
|
-
*/
|
|
192
|
-
create(context: VfxEffectPackageContext<PParams>): VfxEffectHandle;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
export type VfxDebugOverrides = Record<string, Partial<VfxParamValues>>;
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// 新增特效 guardrail · Layer 2(构建产物禁运行时扫描,见 issue #3,最强一层)。
|
|
3
|
-
// `pnpm build` 之后扫 dist/,镜像消费方 Playable bundle 策略(lumber-order
|
|
4
|
-
// scripts/check-playable-asset-bundle.mjs 的 forbiddenTokens),把"会坑消费方"的重运行时
|
|
5
|
-
// 提前到库侧拦住 —— 即便它是被某个特效"间接"拉进来的(顺着 dist 的 chunk import 图归因到特效)。
|
|
6
|
-
//
|
|
7
|
-
// 用法:
|
|
8
|
-
// node tooling/check-dist-runtime.mjs # 扫 dist/
|
|
9
|
-
// node tooling/check-dist-runtime.mjs --dist <dir> # 换扫描目录(回归 fixture 用)
|
|
10
|
-
// 退出码:命中 → 1;干净 → 0。
|
|
11
|
-
import { readdirSync, statSync, readFileSync, existsSync } from 'node:fs';
|
|
12
|
-
import { resolve, dirname, join, relative } from 'node:path';
|
|
13
|
-
import { fileURLToPath } from 'node:url';
|
|
14
|
-
|
|
15
|
-
const LIB_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
16
|
-
const argv = process.argv.slice(2);
|
|
17
|
-
const distArg = argv.indexOf('--dist') >= 0 ? argv[argv.indexOf('--dist') + 1] : undefined;
|
|
18
|
-
const DIST = resolve(distArg ?? join(LIB_ROOT, 'dist'));
|
|
19
|
-
|
|
20
|
-
// 精确 token —— 类名/扩展名/MIME,绝不用宽松子串(如 `basis` 会误报 RingBasis 变量)。
|
|
21
|
-
// 与 lumber-order check-playable-asset-bundle.mjs 的 forbiddenTokens 对齐 + 补 draco/ktx2。
|
|
22
|
-
const SUBSTRING_TOKENS = [
|
|
23
|
-
'EXT_meshopt_compression', 'MeshoptDecoder', 'meshopt_decoder',
|
|
24
|
-
'KHR_draco_mesh_compression', 'DracoCompression', 'DracoDecoder', 'draco_decoder', 'draco_wasm_wrapper',
|
|
25
|
-
'KHR_texture_basisu', 'KhronosTextureContainer2', '_KTX2Decoder', 'MSCTranscoder', 'basis_transcoder',
|
|
26
|
-
'application/x-glb-brotli', 'brotli-dec-wasm',
|
|
27
|
-
'application/wasm', 'data:application/wasm',
|
|
28
|
-
'WebAssembly.Module', 'WebAssembly.instantiate',
|
|
29
|
-
];
|
|
30
|
-
// `.wasm` 资源 URL:要求路径分隔符(/),只拦真资源路径如 "./decoder.wasm"/"chunks/x.wasm",
|
|
31
|
-
// 不误报纯文件名字符串(错误消息 "physics.wasm" / debug 标签 "ringBurst.wasm" 无 /)。
|
|
32
|
-
const WASM_URL_RE = /['"][^'"]*\/[^'"/]*\.wasm(\?[^'"]*)?['"]/;
|
|
33
|
-
|
|
34
|
-
// 与 Layer 1 一致:扫描前剥注释(避免 dist 里残留的解释性注释/banner 误报)。
|
|
35
|
-
function stripComments(src) {
|
|
36
|
-
return src.replace(/\/\*[\s\S]*?\*\//g, '').replace(/(?<!:)\/\/[^\n]*/g, '');
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function tokensIn(rawContent) {
|
|
40
|
-
const content = stripComments(rawContent);
|
|
41
|
-
const hits = [];
|
|
42
|
-
for (const t of SUBSTRING_TOKENS) if (content.includes(t)) hits.push(t);
|
|
43
|
-
const m = content.match(WASM_URL_RE);
|
|
44
|
-
if (m) hits.push(m[0]);
|
|
45
|
-
return hits;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// dist 模块文件:.js + .mjs/.cjs(防止重运行时藏在非 .js chunk 里绕过)。
|
|
49
|
-
const DIST_MODULE_EXT = /\.(js|mjs|cjs)$/;
|
|
50
|
-
function jsFilesIn(dir, out = []) {
|
|
51
|
-
if (!existsSync(dir)) return out;
|
|
52
|
-
for (const e of readdirSync(dir)) {
|
|
53
|
-
const p = join(dir, e);
|
|
54
|
-
const s = statSync(p);
|
|
55
|
-
if (s.isDirectory()) jsFilesIn(p, out);
|
|
56
|
-
else if (DIST_MODULE_EXT.test(e)) out.push(p);
|
|
57
|
-
}
|
|
58
|
-
return out;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// 解析一个 dist 模块的相对 import(构 chunk 依赖图;裸包如 @babylonjs/* 不进图)。
|
|
62
|
-
function relImports(file) {
|
|
63
|
-
const src = readFileSync(file, 'utf8');
|
|
64
|
-
const specs = new Set();
|
|
65
|
-
let m;
|
|
66
|
-
const re = /\bfrom\s*['"]([^'"]+)['"]/g;
|
|
67
|
-
while ((m = re.exec(src))) specs.add(m[1]);
|
|
68
|
-
const side = /\bimport\s*['"]([^'"]+)['"]/g;
|
|
69
|
-
while ((m = side.exec(src))) specs.add(m[1]);
|
|
70
|
-
const dyn = /\bimport\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
71
|
-
while ((m = dyn.exec(src))) specs.add(m[1]);
|
|
72
|
-
const resolved = [];
|
|
73
|
-
for (const spec of specs) {
|
|
74
|
-
if (!spec.startsWith('.')) continue;
|
|
75
|
-
const target = resolve(dirname(file), spec);
|
|
76
|
-
const cands = [target, target + '.js', target + '.mjs', target + '.cjs',
|
|
77
|
-
join(target, 'index.js'), join(target, 'index.mjs'), join(target, 'index.cjs')];
|
|
78
|
-
for (const cand of cands) {
|
|
79
|
-
if (existsSync(cand) && statSync(cand).isFile()) { resolved.push(cand); break; }
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return resolved;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// dist/<dir>/index.{js,mjs,cjs} 取第一个存在的入口。
|
|
86
|
-
function indexEntry(dir) {
|
|
87
|
-
for (const ext of ['js', 'mjs', 'cjs']) {
|
|
88
|
-
const p = join(dir, `index.${ext}`);
|
|
89
|
-
if (existsSync(p)) return p;
|
|
90
|
-
}
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function reachableFrom(entry, importGraph) {
|
|
95
|
-
const seen = new Set();
|
|
96
|
-
const stack = [entry];
|
|
97
|
-
while (stack.length) {
|
|
98
|
-
const f = stack.pop();
|
|
99
|
-
if (seen.has(f)) continue;
|
|
100
|
-
seen.add(f);
|
|
101
|
-
for (const dep of importGraph.get(f) ?? []) if (!seen.has(dep)) stack.push(dep);
|
|
102
|
-
}
|
|
103
|
-
return seen;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// ── 主流程 ────────────────────────────────────────────────────────────────────
|
|
107
|
-
if (!existsSync(DIST)) {
|
|
108
|
-
console.error(`✗ dist 不存在:${DIST}(先 \`pnpm build\`)。`);
|
|
109
|
-
process.exit(1);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const allJs = jsFilesIn(DIST);
|
|
113
|
-
const importGraph = new Map(allJs.map((f) => [f, relImports(f)]));
|
|
114
|
-
const tokenByFile = new Map();
|
|
115
|
-
for (const f of allJs) {
|
|
116
|
-
const hits = tokensIn(readFileSync(f, 'utf8'));
|
|
117
|
-
if (hits.length) tokenByFile.set(f, [...new Set(hits)]);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// 入口 = dist/index.{js,mjs,cjs}(runtime 核心)+ 每个 dist/effects/<id>/index.{js,mjs,cjs}。
|
|
121
|
-
const entries = [];
|
|
122
|
-
const rootIndex = indexEntry(DIST);
|
|
123
|
-
if (rootIndex) entries.push({ label: 'runtime (index)', entry: rootIndex });
|
|
124
|
-
const effectsDist = join(DIST, 'effects');
|
|
125
|
-
if (existsSync(effectsDist)) {
|
|
126
|
-
for (const id of readdirSync(effectsDist)) {
|
|
127
|
-
const idx = indexEntry(join(effectsDist, id));
|
|
128
|
-
if (idx) entries.push({ label: id, entry: idx });
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// 归因:每个入口 → 它可达的、命中 token 的文件。
|
|
133
|
-
const findings = []; // {label, file, tokens}
|
|
134
|
-
const attributedFiles = new Set();
|
|
135
|
-
for (const { label, entry } of entries) {
|
|
136
|
-
const reach = reachableFrom(entry, importGraph);
|
|
137
|
-
for (const f of reach) {
|
|
138
|
-
if (tokenByFile.has(f)) {
|
|
139
|
-
attributedFiles.add(f);
|
|
140
|
-
findings.push({ label, file: f, tokens: tokenByFile.get(f) });
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
// 没被任何入口可达但仍命中的文件(孤儿,理论上不该有)。
|
|
145
|
-
for (const [f, tokens] of tokenByFile) {
|
|
146
|
-
if (!attributedFiles.has(f)) findings.push({ label: '(未归因/孤儿 chunk)', file: f, tokens });
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (findings.length === 0) {
|
|
150
|
-
console.log(`✅ Layer 2 dist 禁运行时扫描通过:${allJs.length} 个 js,0 命中(无 meshopt/draco/ktx2/brotli/wasm 运行时)。`);
|
|
151
|
-
process.exit(0);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
console.log(`❌ Layer 2 dist 禁运行时扫描:发现 ${findings.length} 处命中。\n`);
|
|
155
|
-
// 按特效聚合展示
|
|
156
|
-
const byLabel = {};
|
|
157
|
-
for (const f of findings) (byLabel[f.label] ??= []).push(f);
|
|
158
|
-
for (const [label, items] of Object.entries(byLabel)) {
|
|
159
|
-
console.log(` 特效/入口:${label}`);
|
|
160
|
-
for (const it of items) {
|
|
161
|
-
console.log(` ✗ ${relative(DIST, it.file)} ← ${it.tokens.join(', ')}`);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
console.log('\n修复:定位拉入该运行时的特效(多半是全量 glTF loader / 含 meshopt|draco|ktx2 的 GLB)。');
|
|
165
|
-
console.log(' 改用核心 loader、把 GLB 预解压成 plain、或用 ?url 内联的轻量资源。详见 Layer 1 提示与 #2 v0.1.1。');
|
|
166
|
-
process.exit(1);
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// 生成顶层 index.json:扫 packages/effects/<id>/,汇总 id/nameZh/kind/category/tags/media。
|
|
3
|
-
// 富检索字段(category/tags/media)优先取 description.json,避免与 manifest 双源。
|
|
4
|
-
import { readdirSync, statSync, readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
5
|
-
import { resolve, dirname, join } from 'node:path';
|
|
6
|
-
import { fileURLToPath } from 'node:url';
|
|
7
|
-
|
|
8
|
-
const LIB_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
9
|
-
const EFFECTS_DIR = join(LIB_ROOT, 'packages', 'effects');
|
|
10
|
-
|
|
11
|
-
function readJsonSafe(p) {
|
|
12
|
-
try { return JSON.parse(readFileSync(p, 'utf8')); } catch { return null; }
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const effects = [];
|
|
16
|
-
for (const entry of readdirSync(EFFECTS_DIR)) {
|
|
17
|
-
const dir = join(EFFECTS_DIR, entry);
|
|
18
|
-
if (!statSync(dir).isDirectory()) continue;
|
|
19
|
-
const indexPath = join(dir, 'index.ts');
|
|
20
|
-
if (!existsSync(indexPath)) continue;
|
|
21
|
-
|
|
22
|
-
const effectJson = readJsonSafe(join(dir, 'effect.json')) ?? {};
|
|
23
|
-
const desc = readJsonSafe(join(dir, 'description.json')) ?? {};
|
|
24
|
-
const indexSrc = readFileSync(indexPath, 'utf8');
|
|
25
|
-
const kind = /createManifestRuntimeEffectPackage|createDataDrivenEffectPackage/.test(indexSrc) ? 'data' : 'code';
|
|
26
|
-
|
|
27
|
-
const mediaDir = join(dir, 'media');
|
|
28
|
-
const media = {};
|
|
29
|
-
if (existsSync(mediaDir)) {
|
|
30
|
-
for (const f of readdirSync(mediaDir)) {
|
|
31
|
-
if (/thumbnail/.test(f)) media.thumbnail = `packages/effects/${entry}/media/${f}`;
|
|
32
|
-
else if (/preview\.(mp4|webm|gif)$/.test(f)) media.preview = `packages/effects/${entry}/media/${f}`;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
effects.push({
|
|
37
|
-
id: effectJson.id || entry,
|
|
38
|
-
dir: entry,
|
|
39
|
-
nameZh: effectJson.nameZh || desc.searchTitleZh || entry,
|
|
40
|
-
kind,
|
|
41
|
-
category: desc.semanticTags?.[0] || (effectJson.id?.split('.')[0]) || null,
|
|
42
|
-
tags: desc.searchKeywordsEn || desc.visualTags || effectJson.search?.tags || [],
|
|
43
|
-
media,
|
|
44
|
-
path: `packages/effects/${entry}`,
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
effects.sort((a, b) => a.id.localeCompare(b.id));
|
|
48
|
-
|
|
49
|
-
const out = {
|
|
50
|
-
schemaVersion: 'vfx-index/1.0',
|
|
51
|
-
count: effects.length,
|
|
52
|
-
effects,
|
|
53
|
-
};
|
|
54
|
-
writeFileSync(join(LIB_ROOT, 'index.json'), JSON.stringify(out, null, 2) + '\n');
|
|
55
|
-
console.log(`✅ index.json 生成:${effects.length} 个特效。`);
|