custom-pixi-particles 8.8.0 → 8.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +37 -0
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.js +3 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/behaviour/BehaviourRegistry.d.ts +44 -0
  6. package/dist/lib/behaviour/BehaviourRegistry.js +50 -0
  7. package/dist/lib/behaviour/BehaviourRegistry.js.map +1 -0
  8. package/dist/lib/behaviour/EmitterBehaviours.d.ts +10 -8
  9. package/dist/lib/behaviour/EmitterBehaviours.js +11 -9
  10. package/dist/lib/behaviour/EmitterBehaviours.js.map +1 -1
  11. package/dist/lib/behaviour/IBehaviour.d.ts +41 -0
  12. package/dist/lib/behaviour/IBehaviour.js +2 -0
  13. package/dist/lib/behaviour/IBehaviour.js.map +1 -0
  14. package/dist/lib/behaviour/PlaceholderBehaviour.d.ts +21 -0
  15. package/dist/lib/behaviour/PlaceholderBehaviour.js +36 -0
  16. package/dist/lib/behaviour/PlaceholderBehaviour.js.map +1 -0
  17. package/dist/lib/behaviour/index.d.ts +2 -0
  18. package/dist/lib/behaviour/index.js +1 -0
  19. package/dist/lib/behaviour/index.js.map +1 -1
  20. package/dist/lib/effects/DissolveEffect.d.ts +2 -2
  21. package/dist/lib/effects/DissolveEffect.js +47 -44
  22. package/dist/lib/effects/DissolveEffect.js.map +1 -1
  23. package/dist/lib/effects/GhostEffect.js +5 -3
  24. package/dist/lib/effects/GhostEffect.js.map +1 -1
  25. package/dist/lib/effects/GlitchEffect.d.ts +2 -2
  26. package/dist/lib/effects/GlitchEffect.js +8 -15
  27. package/dist/lib/effects/GlitchEffect.js.map +1 -1
  28. package/dist/lib/effects/MagneticAssemblyEffect.d.ts +2 -2
  29. package/dist/lib/effects/MagneticAssemblyEffect.js +7 -13
  30. package/dist/lib/effects/MagneticAssemblyEffect.js.map +1 -1
  31. package/dist/lib/effects/MeltEffect.d.ts +7 -0
  32. package/dist/lib/effects/MeltEffect.js +151 -82
  33. package/dist/lib/effects/MeltEffect.js.map +1 -1
  34. package/dist/lib/effects/ShatterEffect.d.ts +2 -2
  35. package/dist/lib/effects/ShatterEffect.js +24 -33
  36. package/dist/lib/effects/ShatterEffect.js.map +1 -1
  37. package/dist/lib/emitter/Emitter.js +2 -2
  38. package/dist/lib/emitter/Emitter.js.map +1 -1
  39. package/dist/lib/parser/EmitterParser.d.ts +4 -2
  40. package/dist/lib/parser/EmitterParser.js +24 -6
  41. package/dist/lib/parser/EmitterParser.js.map +1 -1
  42. package/dist/lib/pixi/Renderer.d.ts +3 -4
  43. package/dist/lib/pixi/Renderer.js +8 -14
  44. package/dist/lib/pixi/Renderer.js.map +1 -1
  45. package/dist/lib/pixi/TestRenderer.d.ts +2 -3
  46. package/dist/lib/pixi/TestRenderer.js +5 -5
  47. package/dist/lib/pixi/TestRenderer.js.map +1 -1
  48. package/package.json +5 -2
package/README.md CHANGED
@@ -552,6 +552,43 @@ emitController: {
552
552
 
553
553
  Behaviours define how particles behave throughout their lifetime. Each behaviour has a `priority` (higher = processed first) and can be `enabled` or disabled.
554
554
 
555
+ #### Custom behaviours (IBehaviour)
556
+
557
+ You can add your own behaviours by implementing the **IBehaviour** interface (or extending the base **Behaviour** class) and registering them with **BehaviourRegistry**. Custom behaviours can then be used by name in your emitter config (e.g. from JSON or the editor).
558
+
559
+ ```javascript
560
+ import { Behaviour, BehaviourRegistry, customPixiParticles } from 'custom-pixi-particles'
561
+
562
+ // Extend Behaviour and implement required methods
563
+ class MyCustomBehaviour extends Behaviour {
564
+ enabled = true
565
+ priority = 0
566
+ getName() { return 'MyCustomBehaviour' }
567
+ getProps() { return { enabled: this.enabled, priority: this.priority, name: this.getName() } }
568
+ init(particle, model, turbulencePool) { /* ... */ }
569
+ apply(particle, deltaTime, model) { /* ... */ }
570
+ }
571
+
572
+ // Register so config can create it by name
573
+ BehaviourRegistry.register('MyCustomBehaviour', MyCustomBehaviour)
574
+
575
+ // Your emitter config can now include: { behaviours: [{ name: 'MyCustomBehaviour', ... }] }
576
+ ```
577
+
578
+ You can also add a custom behaviour instance at runtime: get the emitter from your renderer and call `emitter.behaviours.add(myCustomBehaviour)`.
579
+
580
+ ```javascript
581
+ // After creating the particle emitter
582
+ const particles = customPixiParticles.create({ textures, emitterConfig })
583
+ app.stage.addChild(particles)
584
+ particles.play()
585
+
586
+ // Add a custom behaviour at runtime
587
+ const myCustomBehaviour = new MyCustomBehaviour()
588
+ particles.emitter.behaviours.add(myCustomBehaviour)
589
+ // New and existing particles will use the new behaviour on the next update
590
+ ```
591
+
555
592
  #### Life Behaviour
556
593
  Controls particle lifetime.
557
594
 
package/dist/index.d.ts CHANGED
@@ -14,4 +14,7 @@ declare const customPixiParticles: {
14
14
  declare const _customPixiParticlesEditorOnly: {
15
15
  create(settings: ICustomPixiParticlesSettings): TestRenderer;
16
16
  };
17
+ export type { IBehaviour } from './lib/behaviour';
18
+ export { Behaviour, BehaviourRegistry } from './lib/behaviour';
19
+ export { Application, Assets } from 'pixi.js';
17
20
  export { Renderer, customPixiParticles, _customPixiParticlesEditorOnly, ICustomPixiParticlesSettings, ShatterEffect, DissolveEffect, MagneticAssemblyEffect, GhostEffect, GlitchEffect, MeltEffect, };
package/dist/index.js CHANGED
@@ -42,5 +42,8 @@ const _customPixiParticlesEditorOnly = {
42
42
  });
43
43
  },
44
44
  };
45
+ export { Behaviour, BehaviourRegistry } from './lib/behaviour';
46
+ // Re-export so demos can use one import (avoids loading Pixi twice)
47
+ export { Application, Assets } from 'pixi.js';
45
48
  export { Renderer, customPixiParticles, _customPixiParticlesEditorOnly, ShatterEffect, DissolveEffect, MagneticAssemblyEffect, GhostEffect, GlitchEffect, MeltEffect, };
46
49
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,qBAAqB,CAAA;AAE1C,OAAO,YAAY,MAAM,yBAAyB,CAAA;AAClD,OAAO,EACL,cAAc,EACd,WAAW,EACX,YAAY,EACZ,sBAAsB,EACtB,UAAU,EACV,aAAa,GACd,MAAM,eAAe,CAAA;AAetB;;;;GAIG;AACH,MAAM,mBAAmB,GAAG;IAC1B,MAAM,CAAC,QAAsC;QAC3C,MAAM,EACJ,QAAQ,EACR,aAAa,EACb,qBAAqB,GAAG,CAAC,EACzB,0BAA0B,GAAG,CAAC,EAC9B,iBAAiB,GAAG,EAAE,EACtB,QAAQ,GAAG,IAAI,EACf,QAAQ,GAAG,IAAI,EACf,QAAQ,GAAG,IAAI,EACf,GAAG,GAAG,IAAI,EACV,IAAI,GAAG,IAAI,EACX,YAAY,GAAG,KAAK,EACpB,MAAM,GAAG,EAAE,EACX,MAAM,GAAG,EAAE,EACX,WAAW,GAAG,IAAI,GACnB,GAAG,QAAQ,CAAA;QACZ,OAAO,IAAI,QAAQ,CAAC;YAClB,QAAQ;YACR,qBAAqB;YACrB,0BAA0B;YAC1B,aAAa;YACb,iBAAiB;YACjB,QAAQ;YACR,QAAQ;YACR,QAAQ;YACR,GAAG;YACH,IAAI;YACJ,YAAY;YACZ,MAAM;YACN,MAAM;YACN,WAAW;SACZ,CAAC,CAAA;IACJ,CAAC;CACF,CAAA;AAED,MAAM,8BAA8B,GAAG;IACrC,MAAM,CAAC,QAAsC;QAC3C,MAAM,EACJ,QAAQ,EACR,aAAa,EACb,qBAAqB,GAAG,CAAC,EACzB,0BAA0B,GAAG,CAAC,EAC9B,iBAAiB,GAAG,EAAE,EACtB,MAAM,GAAG,EAAE,EACX,MAAM,GAAG,EAAE,EACX,WAAW,GAAG,IAAI,GACnB,GAAG,QAAQ,CAAA;QACZ,OAAO,IAAI,YAAY,CAAC;YACtB,QAAQ;YACR,qBAAqB;YACrB,0BAA0B;YAC1B,aAAa;YACb,iBAAiB;YACjB,MAAM;YACN,MAAM;YACN,WAAW;SACZ,CAAC,CAAA;IACJ,CAAC;CACF,CAAA;AAED,OAAO,EACL,QAAQ,EACR,mBAAmB,EACnB,8BAA8B,EAE9B,aAAa,EACb,cAAc,EACd,sBAAsB,EACtB,WAAW,EACX,YAAY,EACZ,UAAU,GACX,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,qBAAqB,CAAA;AAE1C,OAAO,YAAY,MAAM,yBAAyB,CAAA;AAClD,OAAO,EACL,cAAc,EACd,WAAW,EACX,YAAY,EACZ,sBAAsB,EACtB,UAAU,EACV,aAAa,GACd,MAAM,eAAe,CAAA;AAetB;;;;GAIG;AACH,MAAM,mBAAmB,GAAG;IAC1B,MAAM,CAAC,QAAsC;QAC3C,MAAM,EACJ,QAAQ,EACR,aAAa,EACb,qBAAqB,GAAG,CAAC,EACzB,0BAA0B,GAAG,CAAC,EAC9B,iBAAiB,GAAG,EAAE,EACtB,QAAQ,GAAG,IAAI,EACf,QAAQ,GAAG,IAAI,EACf,QAAQ,GAAG,IAAI,EACf,GAAG,GAAG,IAAI,EACV,IAAI,GAAG,IAAI,EACX,YAAY,GAAG,KAAK,EACpB,MAAM,GAAG,EAAE,EACX,MAAM,GAAG,EAAE,EACX,WAAW,GAAG,IAAI,GACnB,GAAG,QAAQ,CAAA;QACZ,OAAO,IAAI,QAAQ,CAAC;YAClB,QAAQ;YACR,qBAAqB;YACrB,0BAA0B;YAC1B,aAAa;YACb,iBAAiB;YACjB,QAAQ;YACR,QAAQ;YACR,QAAQ;YACR,GAAG;YACH,IAAI;YACJ,YAAY;YACZ,MAAM;YACN,MAAM;YACN,WAAW;SACZ,CAAC,CAAA;IACJ,CAAC;CACF,CAAA;AAED,MAAM,8BAA8B,GAAG;IACrC,MAAM,CAAC,QAAsC;QAC3C,MAAM,EACJ,QAAQ,EACR,aAAa,EACb,qBAAqB,GAAG,CAAC,EACzB,0BAA0B,GAAG,CAAC,EAC9B,iBAAiB,GAAG,EAAE,EACtB,MAAM,GAAG,EAAE,EACX,MAAM,GAAG,EAAE,EACX,WAAW,GAAG,IAAI,GACnB,GAAG,QAAQ,CAAA;QACZ,OAAO,IAAI,YAAY,CAAC;YACtB,QAAQ;YACR,qBAAqB;YACrB,0BAA0B;YAC1B,aAAa;YACb,iBAAiB;YACjB,MAAM;YACN,MAAM;YACN,WAAW;SACZ,CAAC,CAAA;IACJ,CAAC;CACF,CAAA;AAGD,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAE9D,oEAAoE;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAE7C,OAAO,EACL,QAAQ,EACR,mBAAmB,EACnB,8BAA8B,EAE9B,aAAa,EACb,cAAc,EACd,sBAAsB,EACtB,WAAW,EACX,YAAY,EACZ,UAAU,GACX,CAAA"}
@@ -0,0 +1,44 @@
1
+ import type { IBehaviour } from './IBehaviour';
2
+ type BehaviourConstructor = new () => IBehaviour;
3
+ /**
4
+ * Registry for custom behaviour classes. Register a class here so it can be
5
+ * created by name when loading emitter config (e.g. from JSON or the editor).
6
+ *
7
+ * @example
8
+ * import { Behaviour, BehaviourRegistry } from 'custom-pixi-particles'
9
+ *
10
+ * class MyCustomBehaviour extends Behaviour {
11
+ * enabled = true
12
+ * priority = 0
13
+ * getName() { return 'MyCustomBehaviour' }
14
+ * getProps() { return { enabled: this.enabled, priority: this.priority, name: this.getName() } }
15
+ * init(particle, model, turbulencePool) { ... }
16
+ * apply(particle, deltaTime, model) { ... }
17
+ * }
18
+ *
19
+ * BehaviourRegistry.register('MyCustomBehaviour', MyCustomBehaviour)
20
+ *
21
+ * // Now config can use: { behaviours: [{ name: 'MyCustomBehaviour', ... }] }
22
+ */
23
+ export declare const BehaviourRegistry: {
24
+ _behaviours: Map<string, BehaviourConstructor>;
25
+ /**
26
+ * Register a custom behaviour class by name. This name must match the string
27
+ * used in your emitter config (config.behaviours[].name).
28
+ */
29
+ register(name: string, BehaviourClass: BehaviourConstructor): void;
30
+ /**
31
+ * Unregister a custom behaviour by name.
32
+ */
33
+ unregister(name: string): boolean;
34
+ /**
35
+ * Get a registered behaviour constructor by name, or undefined if not registered.
36
+ * Used internally by EmitterParser when creating behaviours from config.
37
+ */
38
+ get(name: string): BehaviourConstructor | undefined;
39
+ /**
40
+ * Check if a name is registered (custom or built-in is not checked here).
41
+ */
42
+ has(name: string): boolean;
43
+ };
44
+ export {};
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Registry for custom behaviour classes. Register a class here so it can be
3
+ * created by name when loading emitter config (e.g. from JSON or the editor).
4
+ *
5
+ * @example
6
+ * import { Behaviour, BehaviourRegistry } from 'custom-pixi-particles'
7
+ *
8
+ * class MyCustomBehaviour extends Behaviour {
9
+ * enabled = true
10
+ * priority = 0
11
+ * getName() { return 'MyCustomBehaviour' }
12
+ * getProps() { return { enabled: this.enabled, priority: this.priority, name: this.getName() } }
13
+ * init(particle, model, turbulencePool) { ... }
14
+ * apply(particle, deltaTime, model) { ... }
15
+ * }
16
+ *
17
+ * BehaviourRegistry.register('MyCustomBehaviour', MyCustomBehaviour)
18
+ *
19
+ * // Now config can use: { behaviours: [{ name: 'MyCustomBehaviour', ... }] }
20
+ */
21
+ export const BehaviourRegistry = {
22
+ _behaviours: new Map(),
23
+ /**
24
+ * Register a custom behaviour class by name. This name must match the string
25
+ * used in your emitter config (config.behaviours[].name).
26
+ */
27
+ register(name, BehaviourClass) {
28
+ this._behaviours.set(name, BehaviourClass);
29
+ },
30
+ /**
31
+ * Unregister a custom behaviour by name.
32
+ */
33
+ unregister(name) {
34
+ return this._behaviours.delete(name);
35
+ },
36
+ /**
37
+ * Get a registered behaviour constructor by name, or undefined if not registered.
38
+ * Used internally by EmitterParser when creating behaviours from config.
39
+ */
40
+ get(name) {
41
+ return this._behaviours.get(name);
42
+ },
43
+ /**
44
+ * Check if a name is registered (custom or built-in is not checked here).
45
+ */
46
+ has(name) {
47
+ return this._behaviours.has(name);
48
+ },
49
+ };
50
+ //# sourceMappingURL=BehaviourRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BehaviourRegistry.js","sourceRoot":"","sources":["../../../src/lib/behaviour/BehaviourRegistry.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,WAAW,EAAE,IAAI,GAAG,EAAgC;IAEpD;;;OAGG;IACH,QAAQ,CAAC,IAAY,EAAE,cAAoC;QACzD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,cAAc,CAAC,CAAA;IAC5C,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,IAAY;QACrB,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACtC,CAAC;IAED;;;OAGG;IACH,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACnC,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACnC,CAAC;CACF,CAAA"}
@@ -1,29 +1,31 @@
1
+ import type { IBehaviour } from './IBehaviour';
1
2
  import Particle from '../Particle';
2
3
  import Model from '../Model';
3
4
  import TurbulencePool from '../util/turbulencePool';
4
5
  /**
5
- * EmitterBehaviours class manages the behaviour of particles
6
+ * EmitterBehaviours class manages the behaviour of particles.
7
+ * Accepts built-in behaviours and custom behaviours that implement IBehaviour.
6
8
  */
7
9
  export default class EmitterBehaviours {
8
- behaviours: any;
10
+ behaviours: IBehaviour[];
9
11
  /**
10
12
  * Gets all the enabled behaviours
11
13
  *
12
14
  * @return {any[]} The enabled behaviours
13
15
  */
14
- getAll: () => any;
16
+ getAll: () => IBehaviour[];
15
17
  /**
16
18
  * Clears all the stored behaviours
17
19
  */
18
20
  clear: () => void;
19
21
  /**
20
- * Adds a behaviour
22
+ * Adds a behaviour (built-in or custom implementing IBehaviour).
21
23
  *
22
- * @param {any} behaviour The behaviour to add
24
+ * @param {IBehaviour} behaviour The behaviour to add
23
25
  *
24
- * @return {any} The added behaviour
26
+ * @return {IBehaviour} The added behaviour
25
27
  */
26
- add: (behaviour: any) => any;
28
+ add: (behaviour: IBehaviour) => IBehaviour;
27
29
  /**
28
30
  * Checks if there are no behaviours stored
29
31
  *
@@ -37,7 +39,7 @@ export default class EmitterBehaviours {
37
39
  *
38
40
  * @return {any | null} The behaviour with the given name or null if not found
39
41
  */
40
- getByName: (name: string) => any;
42
+ getByName: (name: string) => IBehaviour | null;
41
43
  /**
42
44
  * Removes a behaviour by name
43
45
  *
@@ -1,7 +1,8 @@
1
1
  // src/lib/behaviour/EmitterBehaviours.ts
2
2
  // tslint:disable:prefer-for-of
3
3
  /**
4
- * EmitterBehaviours class manages the behaviour of particles
4
+ * EmitterBehaviours class manages the behaviour of particles.
5
+ * Accepts built-in behaviours and custom behaviours that implement IBehaviour.
5
6
  */
6
7
  export default class EmitterBehaviours {
7
8
  constructor() {
@@ -23,11 +24,11 @@ export default class EmitterBehaviours {
23
24
  this.behaviours = [];
24
25
  };
25
26
  /**
26
- * Adds a behaviour
27
+ * Adds a behaviour (built-in or custom implementing IBehaviour).
27
28
  *
28
- * @param {any} behaviour The behaviour to add
29
+ * @param {IBehaviour} behaviour The behaviour to add
29
30
  *
30
- * @return {any} The added behaviour
31
+ * @return {IBehaviour} The added behaviour
31
32
  */
32
33
  this.add = (behaviour) => {
33
34
  if (this.getByName(behaviour.getName()) !== null) {
@@ -108,8 +109,9 @@ export default class EmitterBehaviours {
108
109
  */
109
110
  this.update = (deltaTime) => {
110
111
  for (let i = 0; i < this.behaviours.length; ++i) {
111
- if (this.behaviours[i].update)
112
- this.behaviours[i].update(deltaTime);
112
+ const updateFn = this.behaviours[i].update;
113
+ if (updateFn)
114
+ updateFn(deltaTime);
113
115
  }
114
116
  };
115
117
  /**
@@ -119,9 +121,9 @@ export default class EmitterBehaviours {
119
121
  */
120
122
  this.onParticleRemoved = (particle) => {
121
123
  for (let i = 0; i < this.behaviours.length; ++i) {
122
- if (typeof this.behaviours[i].onParticleRemoved === 'function') {
123
- this.behaviours[i].onParticleRemoved(particle);
124
- }
124
+ const onRemoved = this.behaviours[i].onParticleRemoved;
125
+ if (onRemoved)
126
+ onRemoved(particle);
125
127
  }
126
128
  };
127
129
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EmitterBehaviours.js","sourceRoot":"","sources":["../../../src/lib/behaviour/EmitterBehaviours.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EmitterBehaviours.js","sourceRoot":"","sources":["../../../src/lib/behaviour/EmitterBehaviours.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import type Particle from '../Particle';
2
+ import type Model from '../Model';
3
+ import type TurbulencePool from '../util/turbulencePool';
4
+ import type BehaviourParser from '../parser/BehaviourParser';
5
+ /**
6
+ * Interface that any behaviour must implement to work with the particle emitter.
7
+ * Use this for custom behaviours: implement IBehaviour (or extend Behaviour) and
8
+ * register your class with BehaviourRegistry so it can be used by name in config.
9
+ *
10
+ * @example
11
+ * // Custom behaviour implementing the interface
12
+ * class MyCustomBehaviour extends Behaviour {
13
+ * enabled = true
14
+ * priority = 0
15
+ * getName() { return 'MyCustomBehaviour' }
16
+ * getProps() { return { enabled: this.enabled, priority: this.priority, name: this.getName() } }
17
+ * init(particle, model, turbulencePool) { ... }
18
+ * apply(particle, deltaTime, model) { ... }
19
+ * }
20
+ * BehaviourRegistry.register('MyCustomBehaviour', MyCustomBehaviour)
21
+ */
22
+ export interface IBehaviour {
23
+ /** Whether this behaviour is active */
24
+ enabled: boolean;
25
+ /** Higher priority behaviours run first (default 0) */
26
+ priority: number;
27
+ /** Unique name used in config and registry (e.g. 'MyCustomBehaviour') */
28
+ getName(): string;
29
+ /** Parser for serializing/deserializing this behaviour (default: new BehaviourParser(this)) */
30
+ getParser(): BehaviourParser;
31
+ /** Plain object of configurable properties for save/load (must include enabled, priority, name) */
32
+ getProps(): Record<string, unknown>;
33
+ /** Called once per particle when it is created */
34
+ init(particle: Particle, model: Model, turbulencePool: TurbulencePool): void;
35
+ /** Called every frame per particle */
36
+ apply(particle: Particle, deltaTime: number, model: Model): void;
37
+ /** Optional: called once per frame (not per particle) */
38
+ update?(deltaTime: number): void;
39
+ /** Optional: called when a particle is removed */
40
+ onParticleRemoved?(particle: Particle): void;
41
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=IBehaviour.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IBehaviour.js","sourceRoot":"","sources":["../../../src/lib/behaviour/IBehaviour.ts"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ import type { IBehaviour } from './IBehaviour';
2
+ import type Particle from '../Particle';
3
+ import type Model from '../Model';
4
+ import type TurbulencePool from '../util/turbulencePool';
5
+ import BehaviourParser from '../parser/BehaviourParser';
6
+ /**
7
+ * Placeholder for unknown/custom behaviour names (e.g. when the editor loads
8
+ * a config that references a behaviour not registered in this context).
9
+ * No-ops in init/apply but preserves config for save/load.
10
+ */
11
+ export default class PlaceholderBehaviour implements IBehaviour {
12
+ enabled: boolean;
13
+ priority: number;
14
+ name: string;
15
+ constructor(name: string);
16
+ getName(): string;
17
+ getParser(): BehaviourParser;
18
+ getProps(): Record<string, unknown>;
19
+ init(_particle: Particle, _model: Model, _turbulencePool: TurbulencePool): void;
20
+ apply(_particle: Particle, _deltaTime: number, _model: Model): void;
21
+ }
@@ -0,0 +1,36 @@
1
+ import BehaviourParser from '../parser/BehaviourParser';
2
+ /**
3
+ * Placeholder for unknown/custom behaviour names (e.g. when the editor loads
4
+ * a config that references a behaviour not registered in this context).
5
+ * No-ops in init/apply but preserves config for save/load.
6
+ */
7
+ export default class PlaceholderBehaviour {
8
+ constructor(name) {
9
+ this.enabled = true;
10
+ this.priority = 0;
11
+ this.name = '';
12
+ this.name = name;
13
+ }
14
+ getName() {
15
+ return this.name;
16
+ }
17
+ getParser() {
18
+ return new BehaviourParser(this);
19
+ }
20
+ getProps() {
21
+ const props = {};
22
+ for (const key of Object.keys(this)) {
23
+ if (typeof this[key] !== 'function') {
24
+ props[key] = this[key];
25
+ }
26
+ }
27
+ return props;
28
+ }
29
+ init(_particle, _model, _turbulencePool) {
30
+ // no-op
31
+ }
32
+ apply(_particle, _deltaTime, _model) {
33
+ // no-op
34
+ }
35
+ }
36
+ //# sourceMappingURL=PlaceholderBehaviour.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlaceholderBehaviour.js","sourceRoot":"","sources":["../../../src/lib/behaviour/PlaceholderBehaviour.ts"],"names":[],"mappings":"AAIA,OAAO,eAAe,MAAM,2BAA2B,CAAA;AAEvD;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,oBAAoB;IAKvC,YAAY,IAAY;QAJxB,YAAO,GAAG,IAAI,CAAA;QACd,aAAQ,GAAG,CAAC,CAAA;QACZ,SAAI,GAAG,EAAE,CAAA;QAGP,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,IAAI,CAAA;IAClB,CAAC;IAED,SAAS;QACP,OAAO,IAAI,eAAe,CAAC,IAAI,CAAC,CAAA;IAClC,CAAC;IAED,QAAQ;QACN,MAAM,KAAK,GAA4B,EAAE,CAAA;QACzC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,IAAI,OAAQ,IAAY,CAAC,GAAG,CAAC,KAAK,UAAU,EAAE,CAAC;gBAC7C,KAAK,CAAC,GAAG,CAAC,GAAI,IAAY,CAAC,GAAG,CAAC,CAAA;YACjC,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,CAAC,SAAmB,EAAE,MAAa,EAAE,eAA+B;QACtE,QAAQ;IACV,CAAC;IAED,KAAK,CAAC,SAAmB,EAAE,UAAkB,EAAE,MAAa;QAC1D,QAAQ;IACV,CAAC;CACF"}
@@ -21,4 +21,6 @@ import LightEffectBehaviour from './LightEffectBehaviour';
21
21
  import StretchBehaviour from './StretchBehaviour';
22
22
  import TemperatureBehaviour from './TemperatureBehaviour';
23
23
  import MoveToPointBehaviour from './MoveToPointBehaviour';
24
+ export type { IBehaviour } from './IBehaviour';
25
+ export { BehaviourRegistry } from './BehaviourRegistry';
24
26
  export { EmitterBehaviours, Behaviour, SpawnBehaviour, LifeBehaviour, PositionBehaviour, ColorBehaviour, SizeBehaviour, AngularVelocityBehaviour, EmitDirectionBehaviour, RotationBehaviour, TurbulenceBehaviour, CollisionBehaviour, AttractionRepulsionBehaviour, NoiseBasedMotionBehaviour, ForceFieldsBehaviour, TimelineBehaviour, GroupingBehaviour, SoundReactiveBehaviour, LightEffectBehaviour, StretchBehaviour, TemperatureBehaviour, BehaviourNames, MoveToPointBehaviour, };
@@ -21,5 +21,6 @@ import LightEffectBehaviour from './LightEffectBehaviour';
21
21
  import StretchBehaviour from './StretchBehaviour';
22
22
  import TemperatureBehaviour from './TemperatureBehaviour';
23
23
  import MoveToPointBehaviour from './MoveToPointBehaviour';
24
+ export { BehaviourRegistry } from './BehaviourRegistry';
24
25
  export { EmitterBehaviours, Behaviour, SpawnBehaviour, LifeBehaviour, PositionBehaviour, ColorBehaviour, SizeBehaviour, AngularVelocityBehaviour, EmitDirectionBehaviour, RotationBehaviour, TurbulenceBehaviour, CollisionBehaviour, AttractionRepulsionBehaviour, NoiseBasedMotionBehaviour, ForceFieldsBehaviour, TimelineBehaviour, GroupingBehaviour, SoundReactiveBehaviour, LightEffectBehaviour, StretchBehaviour, TemperatureBehaviour, BehaviourNames, MoveToPointBehaviour, };
25
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/behaviour/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAC7C,OAAO,iBAAiB,MAAM,qBAAqB,CAAA;AACnD,OAAO,SAAS,MAAM,aAAa,CAAA;AACnC,OAAO,aAAa,MAAM,iBAAiB,CAAA;AAC3C,OAAO,iBAAiB,MAAM,qBAAqB,CAAA;AACnD,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAC7C,OAAO,4BAA4B,MAAM,gCAAgC,CAAA;AACzE,OAAO,aAAa,MAAM,iBAAiB,CAAA;AAC3C,OAAO,wBAAwB,MAAM,4BAA4B,CAAA;AACjE,OAAO,sBAAsB,MAAM,0BAA0B,CAAA;AAC7D,OAAO,iBAAiB,MAAM,qBAAqB,CAAA;AACnD,OAAO,mBAAmB,MAAM,uBAAuB,CAAA;AACvD,OAAO,kBAAkB,MAAM,sBAAsB,CAAA;AACrD,OAAO,yBAAyB,MAAM,6BAA6B,CAAA;AACnE,OAAO,oBAAoB,MAAM,wBAAwB,CAAA;AACzD,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAC7C,OAAO,iBAAiB,MAAM,qBAAqB,CAAA;AACnD,OAAO,iBAAiB,MAAM,qBAAqB,CAAA;AACnD,OAAO,sBAAsB,MAAM,0BAA0B,CAAA;AAC7D,OAAO,oBAAoB,MAAM,wBAAwB,CAAA;AACzD,OAAO,gBAAgB,MAAM,oBAAoB,CAAA;AACjD,OAAO,oBAAoB,MAAM,wBAAwB,CAAA;AACzD,OAAO,oBAAoB,MAAM,wBAAwB,CAAA;AAEzD,OAAO,EACL,iBAAiB,EACjB,SAAS,EACT,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,wBAAwB,EACxB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,4BAA4B,EAC5B,yBAAyB,EACzB,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,oBAAoB,GACrB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/behaviour/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAC7C,OAAO,iBAAiB,MAAM,qBAAqB,CAAA;AACnD,OAAO,SAAS,MAAM,aAAa,CAAA;AAEnC,OAAO,aAAa,MAAM,iBAAiB,CAAA;AAC3C,OAAO,iBAAiB,MAAM,qBAAqB,CAAA;AACnD,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAC7C,OAAO,4BAA4B,MAAM,gCAAgC,CAAA;AACzE,OAAO,aAAa,MAAM,iBAAiB,CAAA;AAC3C,OAAO,wBAAwB,MAAM,4BAA4B,CAAA;AACjE,OAAO,sBAAsB,MAAM,0BAA0B,CAAA;AAC7D,OAAO,iBAAiB,MAAM,qBAAqB,CAAA;AACnD,OAAO,mBAAmB,MAAM,uBAAuB,CAAA;AACvD,OAAO,kBAAkB,MAAM,sBAAsB,CAAA;AACrD,OAAO,yBAAyB,MAAM,6BAA6B,CAAA;AACnE,OAAO,oBAAoB,MAAM,wBAAwB,CAAA;AACzD,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAC7C,OAAO,iBAAiB,MAAM,qBAAqB,CAAA;AACnD,OAAO,iBAAiB,MAAM,qBAAqB,CAAA;AACnD,OAAO,sBAAsB,MAAM,0BAA0B,CAAA;AAC7D,OAAO,oBAAoB,MAAM,wBAAwB,CAAA;AACzD,OAAO,gBAAgB,MAAM,oBAAoB,CAAA;AACjD,OAAO,oBAAoB,MAAM,wBAAwB,CAAA;AACzD,OAAO,oBAAoB,MAAM,wBAAwB,CAAA;AAGzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAEvD,OAAO,EACL,iBAAiB,EACjB,SAAS,EACT,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,wBAAwB,EACxB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,4BAA4B,EAC5B,yBAAyB,EACzB,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,oBAAoB,GACrB,CAAA"}
@@ -1,4 +1,4 @@
1
- import { ParticleContainer, Sprite } from 'pixi.js';
1
+ import { Container, Sprite } from 'pixi.js';
2
2
  export type DissolveDirection = 'left-to-right' | 'right-to-left' | 'top-to-bottom' | 'bottom-to-top' | 'center-out';
3
3
  export interface IDissolveEffectOptions {
4
4
  pixelSize?: number;
@@ -10,7 +10,7 @@ export interface IDissolveEffectOptions {
10
10
  direction?: DissolveDirection;
11
11
  windAngle?: number;
12
12
  }
13
- export default class DissolveEffect extends ParticleContainer {
13
+ export default class DissolveEffect extends Container {
14
14
  private sourceSprite;
15
15
  private fragments;
16
16
  private isProcessing;
@@ -7,26 +7,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { ParticleContainer, Sprite, Texture, Ticker } from 'pixi.js';
10
+ import { Container, Sprite, Texture, Ticker } from 'pixi.js';
11
11
  import ParticlePool from '../ParticlePool';
12
- export default class DissolveEffect extends ParticleContainer {
12
+ export default class DissolveEffect extends Container {
13
13
  constructor(sourceSprite, options = {}) {
14
14
  var _a, _b, _c, _d, _e, _f, _g, _h;
15
- // Determine bounds to set container size
16
- const bounds = sourceSprite.getLocalBounds();
17
- const pixelSize = (_a = options.pixelSize) !== null && _a !== void 0 ? _a : 2;
18
- const maxParticles = Math.ceil((bounds.width * bounds.height) / (pixelSize * pixelSize));
19
- super(maxParticles, {
20
- vertices: true,
21
- position: true,
22
- uvs: true,
23
- alpha: true,
24
- tint: true,
25
- });
15
+ super();
26
16
  this.sourceSprite = sourceSprite;
27
17
  this.fragments = [];
28
18
  this.isProcessing = false;
29
19
  this.progress = 0;
20
+ const pixelSize = (_a = options.pixelSize) !== null && _a !== void 0 ? _a : 2;
30
21
  this.options = {
31
22
  pixelSize,
32
23
  edgeSoftness: (_b = options.edgeSoftness) !== null && _b !== void 0 ? _b : 0.2,
@@ -35,34 +26,48 @@ export default class DissolveEffect extends ParticleContainer {
35
26
  lifetime: (_e = options.lifetime) !== null && _e !== void 0 ? _e : 1.5,
36
27
  fadeOutDuration: (_f = options.fadeOutDuration) !== null && _f !== void 0 ? _f : 0.5,
37
28
  direction: (_g = options.direction) !== null && _g !== void 0 ? _g : 'left-to-right',
38
- windAngle: ((_h = options.windAngle) !== null && _h !== void 0 ? _h : -45) * (Math.PI / 180), // Support degrees from UI
29
+ windAngle: ((_h = options.windAngle) !== null && _h !== void 0 ? _h : -45) * (Math.PI / 180),
39
30
  };
31
+ // Copy transforms from source
40
32
  this.x = sourceSprite.x;
41
33
  this.y = sourceSprite.y;
42
34
  this.rotation = sourceSprite.rotation;
35
+ this.scale.copyFrom(sourceSprite.scale);
36
+ this.pivot.copyFrom(sourceSprite.pivot);
43
37
  }
44
38
  prepare() {
45
39
  const texture = this.sourceSprite.texture;
46
- if (!texture || !texture.valid)
40
+ if (!texture || !texture.source) {
41
+ console.warn('DissolveEffect: Texture source not found.');
47
42
  return;
48
- const canvas = document.createElement('canvas');
43
+ }
44
+ // In Pixi v8, 'resource' is the most reliable path to the raw image data.
45
+ // It can be an HTMLImageElement, HTMLCanvasElement, or ImageBitmap.
46
+ const sourceElement = texture.source.resource;
47
+ if (!sourceElement) {
48
+ console.warn('DissolveEffect: Could not find valid resource on texture.source.');
49
+ return;
50
+ }
49
51
  const { width, height } = texture.frame;
52
+ const canvas = document.createElement('canvas');
50
53
  canvas.width = width;
51
54
  canvas.height = height;
52
- const ctx = canvas.getContext('2d');
53
- const baseTex = texture.baseTexture.resource;
54
- if (baseTex && (baseTex.source || baseTex.data)) {
55
- // tslint:disable-next-line:max-line-length
56
- ctx.drawImage(baseTex.source || baseTex.data, texture.frame.x, texture.frame.y, width, height, 0, 0, width, height);
55
+ const ctx = canvas.getContext('2d', { willReadFrequently: true });
56
+ // Draw the specific frame (important for Spritesheets/Atlases)
57
+ try {
58
+ ctx.drawImage(sourceElement, texture.frame.x, texture.frame.y, texture.frame.width, texture.frame.height, 0, 0, width, height);
59
+ }
60
+ catch (e) {
61
+ console.error('DissolveEffect: Failed to draw texture to canvas. This is likely a CORS issue.', e);
62
+ return;
57
63
  }
58
64
  const imgData = ctx.getImageData(0, 0, width, height).data;
59
65
  const { pixelSize, edgeSoftness, direction } = this.options;
60
66
  const anchorX = this.sourceSprite.anchor.x;
61
67
  const anchorY = this.sourceSprite.anchor.y;
62
- const scale = this.sourceSprite.scale.x;
63
68
  for (let py = 0; py < height; py += pixelSize) {
64
69
  for (let px = 0; px < width; px += pixelSize) {
65
- const i = (py * width + px) * 4;
70
+ const i = (Math.floor(py) * width + Math.floor(px)) * 4;
66
71
  if (imgData[i + 3] < 10)
67
72
  continue;
68
73
  let spatialFactor = 0;
@@ -87,11 +92,11 @@ export default class DissolveEffect extends ParticleContainer {
87
92
  }
88
93
  const activationThreshold = spatialFactor * (1 - edgeSoftness) + Math.random() * edgeSoftness;
89
94
  const sprite = new Sprite(Texture.WHITE);
90
- sprite.width = sprite.height = pixelSize * scale;
95
+ sprite.width = sprite.height = pixelSize;
91
96
  // tslint:disable-next-line:no-bitwise
92
97
  sprite.tint = (imgData[i] << 16) | (imgData[i + 1] << 8) | imgData[i + 2];
93
- const lx = (px - width * anchorX) * scale;
94
- const ly = (py - height * anchorY) * scale;
98
+ const lx = px - width * anchorX;
99
+ const ly = py - height * anchorY;
95
100
  const p = ParticlePool.global.pop();
96
101
  p.reset();
97
102
  p.x = lx;
@@ -106,6 +111,8 @@ export default class DissolveEffect extends ParticleContainer {
106
111
  initialY: ly,
107
112
  });
108
113
  this.addChild(sprite);
114
+ sprite.x = lx;
115
+ sprite.y = ly;
109
116
  }
110
117
  }
111
118
  this.sourceSprite.visible = false;
@@ -113,6 +120,10 @@ export default class DissolveEffect extends ParticleContainer {
113
120
  start() {
114
121
  return __awaiter(this, void 0, void 0, function* () {
115
122
  this.prepare();
123
+ if (this.fragments.length === 0) {
124
+ this.finish();
125
+ return;
126
+ }
116
127
  this.isProcessing = true;
117
128
  return new Promise((resolve) => {
118
129
  this.dissolveResolve = resolve;
@@ -129,9 +140,10 @@ export default class DissolveEffect extends ParticleContainer {
129
140
  if (!this.isProcessing)
130
141
  return;
131
142
  const dt = Ticker.shared.deltaMS / 1000;
132
- // progress moves from 0 to 1.2 to ensure all thresholds are met
133
- this.progress += dt * 0.6;
134
- // Iterate backwards so we can safely splice the array
143
+ this.progress += dt * 0.7;
144
+ const { windAngle, driftStrength, noiseIntensity, fadeOutDuration } = this.options;
145
+ const windX = Math.cos(windAngle) * driftStrength;
146
+ const windY = Math.sin(windAngle) * driftStrength;
135
147
  for (let i = this.fragments.length - 1; i >= 0; i--) {
136
148
  const f = this.fragments[i];
137
149
  const p = f.particle;
@@ -140,30 +152,21 @@ export default class DissolveEffect extends ParticleContainer {
140
152
  }
141
153
  if (f.isActive) {
142
154
  p.lifeTime += dt;
143
- // Movement
144
- const windX = Math.cos(this.options.windAngle) * this.options.driftStrength;
145
- const windY = Math.sin(this.options.windAngle) * this.options.driftStrength;
146
- const noiseX = (Math.random() - 0.5) * this.options.noiseIntensity;
147
- const noiseY = (Math.random() - 0.5) * this.options.noiseIntensity;
148
- p.x += (windX + noiseX) * dt;
149
- p.y += (windY + noiseY) * dt;
155
+ const nx = (Math.random() - 0.5) * noiseIntensity;
156
+ const ny = (Math.random() - 0.5) * noiseIntensity;
157
+ p.x += (windX + nx) * dt;
158
+ p.y += (windY + ny) * dt;
150
159
  f.sprite.x = p.x;
151
160
  f.sprite.y = p.y;
152
- // Alpha Fade
153
161
  const lifeProg = p.lifeTime / p.maxLifeTime;
154
- const fadeThreshold = 1 - this.options.fadeOutDuration / p.maxLifeTime;
162
+ const fadeThreshold = 1 - fadeOutDuration / p.maxLifeTime;
155
163
  if (lifeProg > fadeThreshold) {
156
164
  f.sprite.alpha = Math.max(0, 1 - (lifeProg - fadeThreshold) / (1 - fadeThreshold));
157
165
  }
158
- // REMOVAL LOGIC: Check if lifetime ended
159
166
  if (p.lifeTime >= p.maxLifeTime || f.sprite.alpha <= 0) {
160
167
  this.removeFragment(i);
161
168
  }
162
169
  }
163
- else {
164
- f.sprite.x = f.initialX;
165
- f.sprite.y = f.initialY;
166
- }
167
170
  }
168
171
  if (this.fragments.length === 0) {
169
172
  this.finish();
@@ -187,7 +190,7 @@ export default class DissolveEffect extends ParticleContainer {
187
190
  }
188
191
  destroy(options) {
189
192
  Ticker.shared.remove(this.update, this);
190
- this.fragments.forEach((f, i) => {
193
+ this.fragments.forEach((f) => {
191
194
  if (f.particle)
192
195
  ParticlePool.global.push(f.particle);
193
196
  });