@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,194 +0,0 @@
|
|
|
1
|
-
import { Vector3 } from '@babylonjs/core/Maths/math.vector';
|
|
2
|
-
import type { VfxColorValue, VfxEffectPackage, VfxParamValues } from '../types';
|
|
3
|
-
import {
|
|
4
|
-
cloneLegacyEmitters,
|
|
5
|
-
findEmitter,
|
|
6
|
-
setNestedValue,
|
|
7
|
-
startLegacyParticleRuntime,
|
|
8
|
-
type LegacyParticleEmitterConfig,
|
|
9
|
-
} from '../legacy-particle-runtime';
|
|
10
|
-
|
|
11
|
-
export interface WoodSawdustParams extends VfxParamValues {
|
|
12
|
-
lifetime: number;
|
|
13
|
-
scale: number;
|
|
14
|
-
initialHeight: number;
|
|
15
|
-
dustCount: number;
|
|
16
|
-
fragmentCount: number;
|
|
17
|
-
dustColor: VfxColorValue;
|
|
18
|
-
fragmentColor: VfxColorValue;
|
|
19
|
-
dustSize: number;
|
|
20
|
-
fragmentSize: number;
|
|
21
|
-
dustLifetime: number;
|
|
22
|
-
fragmentLifetime: number;
|
|
23
|
-
dustSpeed: number;
|
|
24
|
-
fragmentSpeed: number;
|
|
25
|
-
fragmentSpread: number;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
interface WoodSawdustPackageConfig {
|
|
29
|
-
id: string;
|
|
30
|
-
nameZh: string;
|
|
31
|
-
manifest: unknown;
|
|
32
|
-
runtimeUrl: string;
|
|
33
|
-
assetUrls: Record<string, string>;
|
|
34
|
-
sourceEmitters: unknown;
|
|
35
|
-
dustEmitterName: string;
|
|
36
|
-
fragmentEmitterName: string;
|
|
37
|
-
fragmentLabel: string;
|
|
38
|
-
fragmentSizeLabel: string;
|
|
39
|
-
fragmentColorLabel: string;
|
|
40
|
-
fragmentCountLabel: string;
|
|
41
|
-
fragmentSpeedLabel: string;
|
|
42
|
-
fragmentSpreadLabel: string;
|
|
43
|
-
defaultParams: WoodSawdustParams;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function createWoodSawdustEffectPackage(config: WoodSawdustPackageConfig): VfxEffectPackage<WoodSawdustParams> {
|
|
47
|
-
return {
|
|
48
|
-
id: config.id,
|
|
49
|
-
nameZh: config.nameZh,
|
|
50
|
-
manifest: config.manifest as any,
|
|
51
|
-
defaultParams: config.defaultParams,
|
|
52
|
-
debugAnchor: 'playerRight',
|
|
53
|
-
debugParams: [
|
|
54
|
-
{ key: 'lifetime', label: '生命周期', kind: 'lifetime', min: 0.08, max: 4, step: 0.01 },
|
|
55
|
-
{ key: 'scale', label: '整体缩放', kind: 'scale', min: 0.1, max: 4, step: 0.01 },
|
|
56
|
-
{ key: 'initialHeight', label: '初始高度', kind: 'number', min: -1, max: 3, step: 0.01 },
|
|
57
|
-
{ key: 'dustCount', label: '木粉数量', kind: 'number', min: 1, max: 180, step: 1 },
|
|
58
|
-
{ key: 'fragmentCount', label: config.fragmentCountLabel, kind: 'number', min: 0, max: 90, step: 1 },
|
|
59
|
-
{ key: 'dustColor', label: '木粉颜色', kind: 'color' },
|
|
60
|
-
{ key: 'fragmentColor', label: config.fragmentColorLabel, kind: 'color' },
|
|
61
|
-
{ key: 'dustSize', label: '木粉大小', kind: 'number', min: 0.2, max: 4, step: 0.01 },
|
|
62
|
-
{ key: 'fragmentSize', label: config.fragmentSizeLabel, kind: 'number', min: 0.2, max: 4, step: 0.01 },
|
|
63
|
-
{ key: 'dustLifetime', label: '木粉生命周期', kind: 'lifetime', min: 0.08, max: 3, step: 0.01 },
|
|
64
|
-
{ key: 'fragmentLifetime', label: `${config.fragmentLabel}生命周期`, kind: 'lifetime', min: 0.08, max: 2, step: 0.01 },
|
|
65
|
-
{ key: 'dustSpeed', label: '木粉喷散速度', kind: 'number', min: 0, max: 4, step: 0.01 },
|
|
66
|
-
{ key: 'fragmentSpeed', label: config.fragmentSpeedLabel, kind: 'number', min: 0, max: 8, step: 0.01 },
|
|
67
|
-
{ key: 'fragmentSpread', label: config.fragmentSpreadLabel, kind: 'number', min: 0, max: 4, step: 0.01 },
|
|
68
|
-
],
|
|
69
|
-
create({ scene, root, position, params }) {
|
|
70
|
-
root.position.copyFrom(position).addInPlace(new Vector3(0, params.initialHeight, 0));
|
|
71
|
-
const emitters = buildEmitters(config, params, root.position);
|
|
72
|
-
const runtime = startLegacyParticleRuntime({
|
|
73
|
-
scene,
|
|
74
|
-
runtimeUrl: config.runtimeUrl,
|
|
75
|
-
emitters,
|
|
76
|
-
assetUrls: config.assetUrls,
|
|
77
|
-
onError: (error) => console.error(`[VFX:${config.id}] legacy particle runtime failed`, error),
|
|
78
|
-
});
|
|
79
|
-
let disposed = false;
|
|
80
|
-
const disposeDelay = getDisposeDelaySeconds(params);
|
|
81
|
-
const disposeTimer = window.setTimeout(() => disposeAll(), disposeDelay * 1000);
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
root,
|
|
85
|
-
dispose() {
|
|
86
|
-
disposeAll();
|
|
87
|
-
},
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
function disposeAll(): void {
|
|
91
|
-
if (disposed) return;
|
|
92
|
-
disposed = true;
|
|
93
|
-
window.clearTimeout(disposeTimer);
|
|
94
|
-
runtime.dispose();
|
|
95
|
-
root.dispose();
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function buildEmitters(
|
|
102
|
-
config: WoodSawdustPackageConfig,
|
|
103
|
-
params: WoodSawdustParams,
|
|
104
|
-
origin: Vector3,
|
|
105
|
-
): LegacyParticleEmitterConfig[] {
|
|
106
|
-
const emitters = cloneLegacyEmitters(config.sourceEmitters);
|
|
107
|
-
const dust = findEmitter(emitters, config.dustEmitterName);
|
|
108
|
-
const fragment = findEmitter(emitters, config.fragmentEmitterName);
|
|
109
|
-
if (dust) {
|
|
110
|
-
applyCommonEmitterParams(dust, origin, params.scale, params.lifetime);
|
|
111
|
-
setNestedValue(dust, 'manualEmitCount', Math.round(params.dustCount));
|
|
112
|
-
setNestedValue(dust, 'renderColor.color', toLegacyColor(params.dustColor));
|
|
113
|
-
scaleEmitterSize(dust, params.dustSize);
|
|
114
|
-
scaleMaxLifetime(dust, params.dustLifetime);
|
|
115
|
-
setNestedValue(dust, 'maxEmitPower', params.dustSpeed);
|
|
116
|
-
}
|
|
117
|
-
if (fragment) {
|
|
118
|
-
applyCommonEmitterParams(fragment, origin, params.scale, params.lifetime);
|
|
119
|
-
setNestedValue(fragment, 'manualEmitCount', Math.round(params.fragmentCount));
|
|
120
|
-
setNestedValue(fragment, 'renderColor.color', toLegacyColor(params.fragmentColor));
|
|
121
|
-
scaleEmitterSize(fragment, params.fragmentSize);
|
|
122
|
-
scaleMaxLifetime(fragment, params.fragmentLifetime);
|
|
123
|
-
setNestedValue(fragment, 'maxEmitPower', params.fragmentSpeed);
|
|
124
|
-
scaleShapeSpread(fragment, params.fragmentSpread);
|
|
125
|
-
}
|
|
126
|
-
return emitters;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function applyCommonEmitterParams(
|
|
130
|
-
emitter: LegacyParticleEmitterConfig,
|
|
131
|
-
origin: Vector3,
|
|
132
|
-
scale: number,
|
|
133
|
-
lifetime: number,
|
|
134
|
-
): void {
|
|
135
|
-
setNestedValue(emitter, 'origin', { x: origin.x, y: origin.y, z: origin.z });
|
|
136
|
-
setNestedValue(emitter, 'effectScale', scale);
|
|
137
|
-
setNestedValue(emitter, 'runtime.stopAfterSeconds', Math.max(0.08, lifetime));
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function scaleEmitterSize(emitter: LegacyParticleEmitterConfig, sizeScale: number): void {
|
|
141
|
-
const baseMin = readNumber(emitter.minSize, 0.05);
|
|
142
|
-
const baseMax = readNumber(emitter.maxSize, baseMin);
|
|
143
|
-
emitter.minSize = baseMin * sizeScale;
|
|
144
|
-
emitter.maxSize = baseMax * sizeScale;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
function scaleMaxLifetime(emitter: LegacyParticleEmitterConfig, maxLifeTime: number): void {
|
|
148
|
-
const baseMin = readNumber(emitter.minLifeTime, maxLifeTime * 0.55);
|
|
149
|
-
const baseMax = Math.max(baseMin, readNumber(emitter.maxLifeTime, maxLifeTime));
|
|
150
|
-
const ratio = baseMax > 0 ? baseMin / baseMax : 0.55;
|
|
151
|
-
emitter.minLifeTime = Math.max(0.02, maxLifeTime * ratio);
|
|
152
|
-
emitter.maxLifeTime = Math.max(emitter.minLifeTime as number, maxLifeTime);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
function scaleShapeSpread(emitter: LegacyParticleEmitterConfig, spread: number): void {
|
|
156
|
-
scaleVectorAxes(emitter, 'shape.direction1', spread);
|
|
157
|
-
scaleVectorAxes(emitter, 'shape.direction2', spread);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function scaleVectorAxes(emitter: LegacyParticleEmitterConfig, path: string, scale: number): void {
|
|
161
|
-
const vector = readNestedObject(emitter, path);
|
|
162
|
-
if (!vector) return;
|
|
163
|
-
setNestedValue(emitter, path, {
|
|
164
|
-
...vector,
|
|
165
|
-
x: readNumber(vector.x, 0) * scale,
|
|
166
|
-
z: readNumber(vector.z, 0) * scale,
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function readNestedObject(target: Record<string, unknown>, path: string): Record<string, unknown> | null {
|
|
171
|
-
let cursor: unknown = target;
|
|
172
|
-
for (const part of path.split('.')) {
|
|
173
|
-
if (!cursor || typeof cursor !== 'object' || Array.isArray(cursor)) return null;
|
|
174
|
-
cursor = (cursor as Record<string, unknown>)[part];
|
|
175
|
-
}
|
|
176
|
-
return cursor && typeof cursor === 'object' && !Array.isArray(cursor)
|
|
177
|
-
? cursor as Record<string, unknown>
|
|
178
|
-
: null;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function toLegacyColor(color: VfxColorValue): { r: number; g: number; b: number; a: number } {
|
|
182
|
-
return { r: color.r, g: color.g, b: color.b, a: 1 };
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function getDisposeDelaySeconds(params: WoodSawdustParams): number {
|
|
186
|
-
return Math.max(0.08, params.lifetime)
|
|
187
|
-
+ Math.max(0.08, params.dustLifetime, params.fragmentLifetime)
|
|
188
|
-
+ 0.3;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function readNumber(value: unknown, fallback: number): number {
|
|
192
|
-
const next = Number(value);
|
|
193
|
-
return Number.isFinite(next) ? next : fallback;
|
|
194
|
-
}
|
|
@@ -1,318 +0,0 @@
|
|
|
1
|
-
export const runtimeId = "particleEmitter/v1";
|
|
2
|
-
|
|
3
|
-
export const runtimeContract = {
|
|
4
|
-
runtimeId,
|
|
5
|
-
kind: "particleEmitter",
|
|
6
|
-
emitterFields: {
|
|
7
|
-
capacity: "Maximum Babylon particle capacity.",
|
|
8
|
-
particleTexturePath: "Package-relative particle texture path used to load the Babylon ParticleSystem.particleTexture.",
|
|
9
|
-
blendMode: "Babylon particle blend mode label: ADD, STANDARD, MULTIPLY, or ONEONE.",
|
|
10
|
-
shape: "Emitter shape definition generated by the package build stage.",
|
|
11
|
-
spriteSheet: "Optional Babylon particle spritesheet settings for atlas-based particle textures.",
|
|
12
|
-
effectScale: "Spatial scale for the whole effect; scales emitter volume, particle size, velocity, and gravity together.",
|
|
13
|
-
renderColor: "Converted particle color inputs: one base color plus RGB/alpha intensity before writing Babylon color1/color2/colorDead.",
|
|
14
|
-
alphaKeys: "Color alpha gradients sampled over normalized particle lifetime.",
|
|
15
|
-
sizeKeys: "Size gradients sampled over normalized particle lifetime.",
|
|
16
|
-
},
|
|
17
|
-
runtimeBindings: {
|
|
18
|
-
"ParticleSystem.particleTexture": "Texture loaded from emitter.particleTexturePath through urlForPackagePath.",
|
|
19
|
-
"ParticleSystem.blendMode": "Mapped from emitter.blendMode.",
|
|
20
|
-
"ParticleSystem.manualEmitCount": "emitter.manualEmitCount when emitRate is 0.",
|
|
21
|
-
"ParticleSystem.emitRate": "emitter.emitRate for sustained emitters.",
|
|
22
|
-
"ParticleSystem.shape": "Mapped from emitter.shape.type and shape parameters, then scaled by emitter.effectScale.",
|
|
23
|
-
"ParticleSystem.spriteSheet": "Applied from emitter.spriteSheet when enabled.",
|
|
24
|
-
"ParticleSystem.colorGradient": "emitter.alphaKeys applied to the final ParticleSystem.color1.",
|
|
25
|
-
"ParticleSystem.sizeGradient": "emitter.sizeKeys multiplied by emitter.maxSize and emitter.effectScale.",
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const BABYLON_PARTICLE_UPDATE_SPEED_UNIT = 0.01;
|
|
30
|
-
|
|
31
|
-
function num(value, fallback = 0) {
|
|
32
|
-
const next = Number(value);
|
|
33
|
-
return Number.isFinite(next) ? next : fallback;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function readColor(BABYLON, value, fallback = new BABYLON.Color4(1, 1, 1, 1)) {
|
|
37
|
-
if (!value) return fallback;
|
|
38
|
-
return new BABYLON.Color4(num(value.r, fallback.r), num(value.g, fallback.g), num(value.b, fallback.b), num(value.a, fallback.a));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function applyRenderColorIntensity(BABYLON, color, renderColor = {}) {
|
|
42
|
-
const colorIntensity = Math.max(0, num(renderColor.colorIntensity, 1));
|
|
43
|
-
const alphaIntensity = Math.max(0, num(renderColor.alphaIntensity, colorIntensity));
|
|
44
|
-
return new BABYLON.Color4(
|
|
45
|
-
color.r * colorIntensity,
|
|
46
|
-
color.g * colorIntensity,
|
|
47
|
-
color.b * colorIntensity,
|
|
48
|
-
Math.min(1, color.a * alphaIntensity)
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function particleColors(BABYLON, emitter) {
|
|
53
|
-
const renderColor = emitter.renderColor;
|
|
54
|
-
const baseColor = readColor(BABYLON, renderColor?.color, new BABYLON.Color4(1, 1, 1, 1));
|
|
55
|
-
const color1 = applyRenderColorIntensity(BABYLON, baseColor, renderColor);
|
|
56
|
-
return {
|
|
57
|
-
color1,
|
|
58
|
-
color2: color1,
|
|
59
|
-
colorDead: new BABYLON.Color4(color1.r, color1.g, color1.b, 0),
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function readVec(BABYLON, value, fallback = new BABYLON.Vector3(0, 0, 0)) {
|
|
64
|
-
if (!value) return fallback;
|
|
65
|
-
return new BABYLON.Vector3(num(value.x, fallback.x), num(value.y, fallback.y), num(value.z, fallback.z));
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function blendMode(BABYLON, value) {
|
|
69
|
-
if (value === "STANDARD") return BABYLON.ParticleSystem.BLENDMODE_STANDARD;
|
|
70
|
-
if (value === "MULTIPLY") return BABYLON.ParticleSystem.BLENDMODE_MULTIPLY;
|
|
71
|
-
if (value === "ONEONE") return BABYLON.ParticleSystem.BLENDMODE_ONEONE;
|
|
72
|
-
return BABYLON.ParticleSystem.BLENDMODE_ADD;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function billboardMode(BABYLON, value) {
|
|
76
|
-
if (!value || BABYLON.ParticleSystem[value] === undefined) return undefined;
|
|
77
|
-
return BABYLON.ParticleSystem[value];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function effectScale(emitter) {
|
|
81
|
-
return Math.max(0.0001, num(emitter.effectScale, 1));
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function applyRenderOrder(system, emitter) {
|
|
85
|
-
system.renderingGroupId = Math.max(0, Math.round(num(emitter.renderingGroupId, 2)));
|
|
86
|
-
system.alphaIndex = num(emitter.alphaIndex, 100);
|
|
87
|
-
if ("forceDepthWrite" in system) {
|
|
88
|
-
system.forceDepthWrite = false;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function isDeterministic(emitter) {
|
|
93
|
-
return emitter?.deterministic !== false && emitter?.randomize !== true;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function midpoint(min, max) {
|
|
97
|
-
return (min + max) * 0.5;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function fract(value) {
|
|
101
|
-
return value - Math.floor(value);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function sequence01(index, axis) {
|
|
105
|
-
if (index === 0) return 0.5;
|
|
106
|
-
const strides = [0.618033988749895, 0.414213562373095, 0.732050807568877, 0.324717957244746, 0.754877666246693, 0.569840290998053];
|
|
107
|
-
return fract(0.5 + index * strides[axis % strides.length] + axis * 0.173205080756888);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function lerp(min, max, t) {
|
|
111
|
-
return min + (max - min) * t;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function applyDeterministicBoxEmitter(BABYLON, system, direction1, direction2, boxMin, boxMax) {
|
|
115
|
-
system.minEmitBox = boxMin;
|
|
116
|
-
system.maxEmitBox = boxMax;
|
|
117
|
-
system.direction1 = direction1;
|
|
118
|
-
system.direction2 = direction2;
|
|
119
|
-
|
|
120
|
-
let positionIndex = 0;
|
|
121
|
-
let directionIndex = 0;
|
|
122
|
-
|
|
123
|
-
system.startPositionFunction = (worldMatrix, positionToUpdate, _particle, isLocal) => {
|
|
124
|
-
const index = positionIndex;
|
|
125
|
-
positionIndex += 1;
|
|
126
|
-
const x = lerp(boxMin.x, boxMax.x, sequence01(index, 0));
|
|
127
|
-
const y = lerp(boxMin.y, boxMax.y, sequence01(index, 1));
|
|
128
|
-
const z = lerp(boxMin.z, boxMax.z, sequence01(index, 2));
|
|
129
|
-
if (isLocal) positionToUpdate.set(x, y, z);
|
|
130
|
-
else BABYLON.Vector3.TransformCoordinatesFromFloatsToRef(x, y, z, worldMatrix, positionToUpdate);
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
system.startDirectionFunction = (worldMatrix, directionToUpdate, _particle, isLocal) => {
|
|
134
|
-
const index = directionIndex;
|
|
135
|
-
directionIndex += 1;
|
|
136
|
-
const x = lerp(direction1.x, direction2.x, sequence01(index, 3));
|
|
137
|
-
const y = lerp(direction1.y, direction2.y, sequence01(index, 4));
|
|
138
|
-
const z = lerp(direction1.z, direction2.z, sequence01(index, 5));
|
|
139
|
-
if (isLocal) directionToUpdate.set(x, y, z);
|
|
140
|
-
else BABYLON.Vector3.TransformNormalFromFloatsToRef(x, y, z, worldMatrix, directionToUpdate);
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function applyCocosConeEmitFunctions(BABYLON, system, radius, angle, radiusRange, scale) {
|
|
145
|
-
const safeRadius = Math.max(0, radius * scale);
|
|
146
|
-
const innerSq = (safeRadius * Math.max(0, 1 - radiusRange)) ** 2;
|
|
147
|
-
const outerSq = safeRadius * safeRadius;
|
|
148
|
-
const halfAngle = Math.min(Math.PI, Math.max(0, angle));
|
|
149
|
-
const cosAngle = Math.cos(halfAngle);
|
|
150
|
-
|
|
151
|
-
system.startPositionFunction = (worldMatrix, positionToUpdate, _particle, isLocal) => {
|
|
152
|
-
const s = Math.random() * Math.PI * 2;
|
|
153
|
-
const r2 = innerSq + Math.random() * (outerSq - innerSq);
|
|
154
|
-
const r = Math.sqrt(Math.max(0, r2));
|
|
155
|
-
const lx = r * Math.cos(s);
|
|
156
|
-
const lz = r * Math.sin(s);
|
|
157
|
-
if (isLocal) positionToUpdate.set(lx, 0, lz);
|
|
158
|
-
else BABYLON.Vector3.TransformCoordinatesFromFloatsToRef(lx, 0, lz, worldMatrix, positionToUpdate);
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
system.startDirectionFunction = (worldMatrix, directionToUpdate, _particle, isLocal) => {
|
|
162
|
-
const phi = Math.random() * Math.PI * 2;
|
|
163
|
-
const cosTheta = 1 - Math.random() * (1 - cosAngle);
|
|
164
|
-
const sinTheta = Math.sqrt(Math.max(0, 1 - cosTheta * cosTheta));
|
|
165
|
-
const dx = sinTheta * Math.cos(phi);
|
|
166
|
-
const dy = cosTheta;
|
|
167
|
-
const dz = sinTheta * Math.sin(phi);
|
|
168
|
-
if (isLocal) directionToUpdate.set(dx, dy, dz);
|
|
169
|
-
else BABYLON.Vector3.TransformNormalFromFloatsToRef(dx, dy, dz, worldMatrix, directionToUpdate);
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function applyEmitterShape(BABYLON, system, emitter) {
|
|
174
|
-
const scale = effectScale(emitter);
|
|
175
|
-
const shape = emitter.shape || {};
|
|
176
|
-
const type = shape.type;
|
|
177
|
-
const radius = num(shape.radius, 1);
|
|
178
|
-
const radiusRange = Math.min(1, Math.max(0, num(shape.radiusRange, 1)));
|
|
179
|
-
const angle = num(shape.angle, Math.PI / 4);
|
|
180
|
-
const direction1 = readVec(BABYLON, shape.direction1, new BABYLON.Vector3(0, 1, 0));
|
|
181
|
-
const direction2 = readVec(BABYLON, shape.direction2, new BABYLON.Vector3(0, 1, 0));
|
|
182
|
-
const boxMin = readVec(BABYLON, shape.minEmitBox, new BABYLON.Vector3(-radius * 0.5, -radius * 0.5, -radius * 0.5)).scale(scale);
|
|
183
|
-
const boxMax = readVec(BABYLON, shape.maxEmitBox, new BABYLON.Vector3(radius * 0.5, radius * 0.5, radius * 0.5)).scale(scale);
|
|
184
|
-
|
|
185
|
-
if (type === "Box") {
|
|
186
|
-
if (isDeterministic(emitter)) applyDeterministicBoxEmitter(BABYLON, system, direction1, direction2, boxMin, boxMax);
|
|
187
|
-
else system.createBoxEmitter(direction1, direction2, boxMin, boxMax);
|
|
188
|
-
} else if (type === "SphereDirected") {
|
|
189
|
-
system.createDirectedSphereEmitter(radius * scale, direction1, direction2);
|
|
190
|
-
} else if (type === "Sphere") {
|
|
191
|
-
system.createSphereEmitter(radius * scale, radiusRange);
|
|
192
|
-
} else if (type === "Hemisphere") {
|
|
193
|
-
system.createHemisphericEmitter(radius * scale, radiusRange);
|
|
194
|
-
} else if (type === "Cone") {
|
|
195
|
-
const dirSpread = direction1.subtract(direction2).lengthSquared();
|
|
196
|
-
if (dirSpread < 1e-4) {
|
|
197
|
-
system.createConeEmitter(Math.max(0.001, radius * scale), angle);
|
|
198
|
-
applyCocosConeEmitFunctions(BABYLON, system, radius, angle, radiusRange, scale);
|
|
199
|
-
} else {
|
|
200
|
-
system.createDirectedConeEmitter(Math.max(0.001, radius * scale), angle, direction1, direction2);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
function applySpriteSheet(system, emitter) {
|
|
206
|
-
const spriteSheet = emitter.spriteSheet || {};
|
|
207
|
-
if (!spriteSheet.enabled) return;
|
|
208
|
-
const deterministic = isDeterministic(emitter);
|
|
209
|
-
|
|
210
|
-
system.isAnimationSheetEnabled = true;
|
|
211
|
-
system.spriteCellWidth = Math.max(1, Math.round(num(spriteSheet.cellWidth, 256)));
|
|
212
|
-
system.spriteCellHeight = Math.max(1, Math.round(num(spriteSheet.cellHeight, 256)));
|
|
213
|
-
system.startSpriteCellID = Math.max(0, Math.round(num(spriteSheet.startCellID, 0)));
|
|
214
|
-
system.endSpriteCellID = Math.max(system.startSpriteCellID, Math.round(num(spriteSheet.endCellID, system.startSpriteCellID)));
|
|
215
|
-
system.spriteCellChangeSpeed = Math.max(0, num(spriteSheet.cellChangeSpeed, 0));
|
|
216
|
-
system.spriteRandomStartCell = deterministic ? spriteSheet.randomStartCell === true && emitter.randomize === true : spriteSheet.randomStartCell !== false;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function addGradients(BABYLON, system, emitter, color1) {
|
|
220
|
-
const scale = effectScale(emitter);
|
|
221
|
-
for (const key of emitter.alphaKeys || []) {
|
|
222
|
-
const time = Math.min(1, Math.max(0, num(key.time, 0)));
|
|
223
|
-
const alpha = Math.min(1, Math.max(0, num(key.alpha, 1)));
|
|
224
|
-
system.addColorGradient?.(time, new BABYLON.Color4(color1.r, color1.g, color1.b, Math.min(1, color1.a * alpha)));
|
|
225
|
-
}
|
|
226
|
-
for (const key of emitter.sizeKeys || []) {
|
|
227
|
-
const time = Math.min(1, Math.max(0, num(key.time, 0)));
|
|
228
|
-
const size = Math.max(0.001, num(key.size, 1) * num(emitter.maxSize, 1) * scale);
|
|
229
|
-
system.addSizeGradient?.(time, size);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
function playbackSpeed(emitter) {
|
|
234
|
-
return Math.max(0.001, num(emitter.updateSpeed, BABYLON_PARTICLE_UPDATE_SPEED_UNIT) / BABYLON_PARTICLE_UPDATE_SPEED_UNIT);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
function runtimeDuration(emitter) {
|
|
238
|
-
return Math.max(0.1, num(emitter.runtime?.stopAfterSeconds, 3) / playbackSpeed(emitter));
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
export async function createParticleEmitterRuntime({ BABYLON, scene, emitter, index = 0, urlForPackagePath, shouldStart = false }) {
|
|
242
|
-
if (!BABYLON) throw new Error("createParticleEmitterRuntime requires BABYLON.");
|
|
243
|
-
if (!scene) throw new Error("createParticleEmitterRuntime requires scene.");
|
|
244
|
-
if (!emitter) throw new Error("createParticleEmitterRuntime requires emitter.");
|
|
245
|
-
|
|
246
|
-
const scale = effectScale(emitter);
|
|
247
|
-
const deterministic = isDeterministic(emitter);
|
|
248
|
-
const capacity = Math.max(1, Math.round(num(emitter.capacity, 100)));
|
|
249
|
-
const system = new BABYLON.ParticleSystem(`particle-emitter-${emitter.name || index}`, capacity, scene);
|
|
250
|
-
const root = new BABYLON.TransformNode(`particle-emitter-root-${emitter.name || index}`, scene);
|
|
251
|
-
root.position.copyFrom(readVec(BABYLON, emitter.origin, BABYLON.Vector3.Zero()));
|
|
252
|
-
root.rotation.y = num(emitter.rotationY, 0);
|
|
253
|
-
applyRenderOrder(system, emitter);
|
|
254
|
-
const textureUrl = urlForPackagePath ? urlForPackagePath(emitter.particleTexturePath) : emitter.particleTexturePath;
|
|
255
|
-
system.particleTexture = new BABYLON.Texture(textureUrl, scene);
|
|
256
|
-
system.particleTexture.hasAlpha = true;
|
|
257
|
-
system.emitter = root;
|
|
258
|
-
system.blendMode = blendMode(BABYLON, emitter.blendMode);
|
|
259
|
-
system.isLocal = emitter.isLocal === true;
|
|
260
|
-
const minSize = Math.max(0.001, num(emitter.minSize, 1) * scale);
|
|
261
|
-
const maxSize = Math.max(minSize, num(emitter.maxSize, minSize) * scale);
|
|
262
|
-
system.minSize = deterministic ? midpoint(minSize, maxSize) : minSize;
|
|
263
|
-
system.maxSize = deterministic ? system.minSize : maxSize;
|
|
264
|
-
const minScaleX = Math.max(0.001, num(emitter.minScaleX, 1));
|
|
265
|
-
const maxScaleX = Math.max(minScaleX, num(emitter.maxScaleX, minScaleX));
|
|
266
|
-
system.minScaleX = deterministic ? midpoint(minScaleX, maxScaleX) : minScaleX;
|
|
267
|
-
system.maxScaleX = deterministic ? system.minScaleX : maxScaleX;
|
|
268
|
-
const minScaleY = Math.max(0.001, num(emitter.minScaleY, 1));
|
|
269
|
-
const maxScaleY = Math.max(minScaleY, num(emitter.maxScaleY, minScaleY));
|
|
270
|
-
system.minScaleY = deterministic ? midpoint(minScaleY, maxScaleY) : minScaleY;
|
|
271
|
-
system.maxScaleY = deterministic ? system.minScaleY : maxScaleY;
|
|
272
|
-
const minLifeTime = Math.max(0.02, num(emitter.minLifeTime, 0.55));
|
|
273
|
-
const maxLifeTime = Math.max(minLifeTime, num(emitter.maxLifeTime, minLifeTime));
|
|
274
|
-
system.minLifeTime = deterministic ? midpoint(minLifeTime, maxLifeTime) : minLifeTime;
|
|
275
|
-
system.maxLifeTime = deterministic ? system.minLifeTime : maxLifeTime;
|
|
276
|
-
const minEmitPower = Math.max(0, num(emitter.minEmitPower, 1) * scale);
|
|
277
|
-
const maxEmitPower = Math.max(minEmitPower, num(emitter.maxEmitPower, minEmitPower) * scale);
|
|
278
|
-
system.minEmitPower = deterministic ? midpoint(minEmitPower, maxEmitPower) : minEmitPower;
|
|
279
|
-
system.maxEmitPower = deterministic ? system.minEmitPower : maxEmitPower;
|
|
280
|
-
system.updateSpeed = Math.max(0.00001, num(emitter.updateSpeed, BABYLON_PARTICLE_UPDATE_SPEED_UNIT));
|
|
281
|
-
system.gravity = readVec(BABYLON, emitter.gravity, new BABYLON.Vector3(0, -6, 0)).scale(scale);
|
|
282
|
-
system.emitRate = Math.max(0, num(emitter.emitRate, 0));
|
|
283
|
-
if (system.emitRate <= 0) system.manualEmitCount = Math.max(0, Math.round(num(emitter.manualEmitCount, 0)));
|
|
284
|
-
|
|
285
|
-
const colors = particleColors(BABYLON, emitter);
|
|
286
|
-
system.color1 = colors.color1;
|
|
287
|
-
system.color2 = colors.color2;
|
|
288
|
-
system.colorDead = colors.colorDead;
|
|
289
|
-
const minInitialRotation = num(emitter.minInitialRotation, 0);
|
|
290
|
-
const maxInitialRotation = Math.max(minInitialRotation, num(emitter.maxInitialRotation, minInitialRotation));
|
|
291
|
-
system.minInitialRotation = deterministic ? midpoint(minInitialRotation, maxInitialRotation) : minInitialRotation;
|
|
292
|
-
system.maxInitialRotation = deterministic ? system.minInitialRotation : maxInitialRotation;
|
|
293
|
-
const minAngularSpeed = num(emitter.minAngularSpeed, 0);
|
|
294
|
-
const maxAngularSpeed = Math.max(minAngularSpeed, num(emitter.maxAngularSpeed, minAngularSpeed));
|
|
295
|
-
system.minAngularSpeed = deterministic ? midpoint(minAngularSpeed, maxAngularSpeed) : minAngularSpeed;
|
|
296
|
-
system.maxAngularSpeed = deterministic ? system.minAngularSpeed : maxAngularSpeed;
|
|
297
|
-
|
|
298
|
-
const nextBillboardMode = billboardMode(BABYLON, emitter.billboardMode);
|
|
299
|
-
if (nextBillboardMode !== undefined) system.billboardMode = nextBillboardMode;
|
|
300
|
-
|
|
301
|
-
applyEmitterShape(BABYLON, system, emitter);
|
|
302
|
-
applySpriteSheet(system, emitter);
|
|
303
|
-
addGradients(BABYLON, system, emitter, system.color1);
|
|
304
|
-
|
|
305
|
-
const preview = {
|
|
306
|
-
start: () => system.start(),
|
|
307
|
-
stop: () => system.stop(),
|
|
308
|
-
dispose: () => {
|
|
309
|
-
system.dispose();
|
|
310
|
-
root.dispose();
|
|
311
|
-
},
|
|
312
|
-
isStarted: () => system.isStarted(),
|
|
313
|
-
duration: runtimeDuration(emitter),
|
|
314
|
-
system,
|
|
315
|
-
};
|
|
316
|
-
if (shouldStart) preview.start();
|
|
317
|
-
return preview;
|
|
318
|
-
}
|
|
Binary file
|
package/packages/effects/wood_crusher_sawdust/assets/textures/wood_crusher_sawdust_fiber.png
DELETED
|
Binary file
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import manifest from './wood_crusher_sawdust.json';
|
|
2
|
-
import runtimeUrl from './assets/runtime/particleEmitter.v1.js?url';
|
|
3
|
-
import dustTextureUrl from './assets/textures/wood_crusher_sawdust_dust.png?url';
|
|
4
|
-
import fiberTextureUrl from './assets/textures/wood_crusher_sawdust_fiber.png?url';
|
|
5
|
-
import { createManifestRuntimeEffectPackage } from '../../manifestRuntimePackage';
|
|
6
|
-
|
|
7
|
-
const packageDefinition = createManifestRuntimeEffectPackage({
|
|
8
|
-
id: 'wood_crusher_sawdust',
|
|
9
|
-
manifest,
|
|
10
|
-
assetUrls: {
|
|
11
|
-
'assets/runtime/particleEmitter.v1.js': runtimeUrl,
|
|
12
|
-
'assets/textures/wood_crusher_sawdust_dust.png': dustTextureUrl,
|
|
13
|
-
'assets/textures/wood_crusher_sawdust_fiber.png': fiberTextureUrl,
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
|
-
const packageManifest = packageDefinition.manifest ?? {
|
|
17
|
-
id: packageDefinition.id,
|
|
18
|
-
nameZh: packageDefinition.nameZh,
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const woodCrusherSawdustEffectPackage = {
|
|
22
|
-
...packageDefinition,
|
|
23
|
-
nameZh: '粉碎机木粉(去皮机)',
|
|
24
|
-
manifest: {
|
|
25
|
-
...packageManifest,
|
|
26
|
-
id: packageManifest.id,
|
|
27
|
-
nameZh: '粉碎机木粉(去皮机)',
|
|
28
|
-
},
|
|
29
|
-
};
|