@tsparticles/preset-hyperspace 4.4.0 → 4.5.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.
@@ -1,21 +1,35 @@
1
- (function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
2
- /* Preset v4.4.0 */
3
- (function (global, factory) {
4
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
5
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
6
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.__tsParticlesInternals = global.__tsParticlesInternals || {}, global.__tsParticlesInternals.presets = global.__tsParticlesInternals.presets || {}, global.__tsParticlesInternals.presets.hyperspace = global.__tsParticlesInternals.presets.hyperspace || {})));
7
- })(this, (function (exports) { 'use strict';
8
-
9
- const generatedAttribute = "generated", defaultCompositeValue = "source-over", resizeEvent = "resize", visibilityChangeEvent = "visibilitychange", percentDenominator = 100, half = 0.5, millisecondsToSeconds = 1000, originPoint = {
10
- x: 0,
11
- y: 0,
12
- z: 0,
13
- }, defaultTransform = {
14
- a: 1,
15
- b: 0,
16
- c: 0,
17
- d: 1,
18
- }, randomColorValue = "random", double = 2, doublePI = Math.PI * double, defaultFps = 60, generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", defaultRetryCount = 0, squareExp = 2, spatialHashGridCellSize = 100, defaultRemoveQuantity = 1, defaultRatio = 1, defaultReduceFactor = 1, inverseFactorNumerator = 1, rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, empty = 0, quarter = 0.25, threeQuarter = half + quarter, minVelocity = 0, minDistance = 0, defaultTransformValue = 1, minimumSize = 0, zIndexFactorOffset = 1, defaultOpacity$1 = 1, removeDeleteCount = 1, removeMinIndex = 0, defaultFpsLimit = 120, minFpsLimit = 0, canvasFirstIndex = 0, loadRandomFactor = 10000, loadMinIndex = 0, one = 1, none = 0, decayOffset = 1, tryCountIncrement = 1, minZ = 0, minLimit = 0, countOffset = 1, minCount = 0, minIndex = 0, defaultDensityFactor = 1, deleteCount = 1, defaultAngle = 0, identity$1 = 1, minStrokeWidth = 0, lFactor = 1, lMin = 0, maxNits = 400, triple = 3, sextuple = 6, sNormalizedOffset = 1, phaseNumerator = 1, defaultRgbMin = 0, defaultVelocity = 0, defaultLoops = 0, defaultTime = 0, defaultZoom = 1;
1
+ (function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
2
+ (function (g) {
3
+ /* Preset v4.5.1 */
4
+ g.__tsParticlesInternals = g.__tsParticlesInternals || {};
5
+ g.__tsParticlesInternals.presets = g.__tsParticlesInternals.presets || {};
6
+ (function (exports) {
7
+ 'use strict';
8
+
9
+ const errorPrefix = "tsParticles - Error", codedErrorPattern = /^\[tsParticles Error (TSP-\d+)\]\s*/, fullMatchIndex = 0, codeIndex = 1;
10
+ const wrap = (fn) => (...args) => {
11
+ fn(...args);
12
+ }, _logger = {
13
+ debug: wrap(console.debug),
14
+ error: (message, ...optionalParams) => {
15
+ if (typeof message === "string") {
16
+ const match = codedErrorPattern.exec(message);
17
+ if (match?.[codeIndex]) {
18
+ console.error(`tsParticles - ${match[codeIndex]} - ${message.slice(match[fullMatchIndex].length)}`, ...optionalParams);
19
+ return;
20
+ }
21
+ }
22
+ console.error(`${errorPrefix} - ${message}`, ...optionalParams);
23
+ },
24
+ info: wrap(console.info),
25
+ log: wrap(console.log),
26
+ trace: wrap(console.trace),
27
+ verbose: wrap(console.log),
28
+ warning: wrap(console.warn),
29
+ };
30
+ function getLogger() {
31
+ return _logger;
32
+ }
19
33
 
20
34
  var MoveDirection;
21
35
  (function (MoveDirection) {
@@ -32,6 +46,17 @@
32
46
  MoveDirection["inside"] = "inside";
33
47
  })(MoveDirection || (MoveDirection = {}));
34
48
 
49
+ const generatedAttribute = "generated", fullPercent = "100%", defaultCompositeValue = "source-over", resizeEvent = "resize", visibilityChangeEvent = "visibilitychange", percentDenominator = 100, half = 0.5, millisecondsToSeconds = 1000, originPoint = {
50
+ x: 0,
51
+ y: 0,
52
+ z: 0,
53
+ }, defaultTransform = {
54
+ a: 1,
55
+ b: 0,
56
+ c: 0,
57
+ d: 1,
58
+ }, randomColorValue = "random", double = 2, doublePI = Math.PI * double, defaultFps = 60, defaultAlpha = 1, generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", defaultRetryCount = 0, squareExp = 2, spatialHashGridCellSize = 100, defaultRemoveQuantity = 1, defaultRatio = 1, defaultReduceFactor = 1, inverseFactorNumerator = 1, rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, empty = 0, quarter = 0.25, threeQuarter = half + quarter, minVelocity = 0, minDistance = 0, minRadius = 0, defaultTransformValue = 1, minimumSize = 0, zIndexFactorOffset = 1, defaultOpacity$1 = 1, removeDeleteCount = 1, removeMinIndex = 0, defaultFpsLimit = 120, minFpsLimit = 0, canvasFirstIndex = 0, loadRandomFactor = 10000, loadMinIndex = 0, one = 1, none = 0, decayOffset = 1, tryCountIncrement = 1, minZ = 0, minLimit = 0, countOffset = 1, minCount = 0, minIndex = 0, defaultDensityFactor = 1, deleteCount = 1, defaultAngle = 0, identity$1 = 1, minStrokeWidth = 0, lFactor = 1, lMin = 0, maxNits = 400, triple = 3, sextuple = 6, sNormalizedOffset = 1, phaseNumerator = 1, defaultRgbMin = 0, defaultVelocity = 0, defaultLoops = 0, defaultTime = 0, defaultZoom = 1;
59
+
35
60
  function getZ(source) {
36
61
  return "z" in source ? source.z : originPoint.z;
37
62
  }
@@ -147,6 +172,12 @@
147
172
  function isNumber(arg) {
148
173
  return typeof arg === "number";
149
174
  }
175
+ function isEnumValue(enumObject, arg) {
176
+ return Object.values(enumObject).some(enumValue => enumValue === arg);
177
+ }
178
+ function toEnumValue(enumObject, arg, defaultValue) {
179
+ return isEnumValue(enumObject, arg) ? arg : defaultValue;
180
+ }
150
181
  function isObject(arg) {
151
182
  return typeof arg === "object" && arg !== null;
152
183
  }
@@ -283,11 +314,61 @@
283
314
  };
284
315
  }
285
316
  function parseAlpha(input) {
286
- const defaultAlpha = 1;
287
317
  if (!input) {
288
318
  return defaultAlpha;
289
319
  }
290
- return input.endsWith("%") ? parseFloat(input) / percentDenominator : parseFloat(input);
320
+ return input.endsWith("%") ? Number.parseFloat(input) / percentDenominator : Number.parseFloat(input);
321
+ }
322
+
323
+ const ErrorCodes$2 = {
324
+ engineVersionMismatch: "TSP-1001",
325
+ particlePositionNotFound: "TSP-1002",
326
+ pluginRegisterAfterLoad: "TSP-1003",
327
+ offscreenCanvasUnsupported: "TSP-1101",
328
+ offscreenCanvasTransferFailed: "TSP-1102",
329
+ hdrEnableInvalid: "TSP-1201",
330
+ hdrModeInvalid: "TSP-1202",
331
+ hdrPeakNitsInvalid: "TSP-1203",
332
+ };
333
+
334
+ const messages = {
335
+ [ErrorCodes$2.engineVersionMismatch]: "The tsParticles version is different from the loaded plugins version. Engine version: {0}. Plugin version: {1}",
336
+ [ErrorCodes$2.particlePositionNotFound]: "a valid position cannot be found for particle",
337
+ [ErrorCodes$2.pluginRegisterAfterLoad]: "Register plugins can only be done before calling tsParticles.load()",
338
+ [ErrorCodes$2.offscreenCanvasUnsupported]: "OffscreenCanvas is required but not supported by this browser",
339
+ [ErrorCodes$2.offscreenCanvasTransferFailed]: "OffscreenCanvas transfer failed",
340
+ [ErrorCodes$2.hdrEnableInvalid]: 'Invalid HDR "enable" value: expected a boolean, got "{0}"',
341
+ [ErrorCodes$2.hdrModeInvalid]: 'Invalid HDR "mode" value: expected one of {0}, got "{1}"',
342
+ [ErrorCodes$2.hdrPeakNitsInvalid]: 'Invalid HDR "peakNits" value: expected a positive number, got "{0}"',
343
+ };
344
+
345
+ let registeredMessages;
346
+ const ensureRegisteredMessages = () => {
347
+ registeredMessages ??= new Map(Object.entries(messages));
348
+ return registeredMessages;
349
+ }, toStringValue$1 = (value) => String(value), format = (template, args) => {
350
+ return template.replace(/\{(\d+)\}/g, (match, index) => {
351
+ const arg = args[Number(index)];
352
+ return arg === undefined ? match : toStringValue$1(arg);
353
+ });
354
+ };
355
+ function addErrorMessages(extraMessages) {
356
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "production") {
357
+ return;
358
+ }
359
+ const catalog = ensureRegisteredMessages();
360
+ for (const [code, message] of Object.entries(extraMessages)) {
361
+ if (message !== undefined) {
362
+ catalog.set(code, message);
363
+ }
364
+ }
365
+ }
366
+ function getErrorMessage(code, ...args) {
367
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "production") {
368
+ return `[tsParticles Error ${code}] https://particles.js.org/errors/#${code}`;
369
+ }
370
+ const template = ensureRegisteredMessages().get(code) ?? `Unknown error code ${code}`;
371
+ return format(template, args);
291
372
  }
292
373
 
293
374
  var OutModeDirection;
@@ -304,7 +385,6 @@
304
385
  PixelMode["percent"] = "percent";
305
386
  })(PixelMode || (PixelMode = {}));
306
387
 
307
- const minRadius = 0;
308
388
  function isForbiddenKey(key) {
309
389
  return key === "__proto__" || key === "constructor" || key === "prototype";
310
390
  }
@@ -500,22 +580,84 @@
500
580
  element.removeEventListener(event, handler, removeOptions);
501
581
  }
502
582
  }
503
- async function getItemsFromInitializer(container, map, initializers, force = false) {
504
- let res = map.get(container);
505
- if (!res || force) {
506
- res = await Promise.all([...initializers.values()].map(t => t(container)));
507
- map.set(container, res);
583
+ async function getItemsFromInitializer(container, initializers) {
584
+ return await Promise.all([...initializers.values()].map(t => t(container)));
585
+ }
586
+ async function getItemMapFromInitializer(container, initializers) {
587
+ const entries = await Promise.all([...initializers.entries()].map(([key, initializer]) => initializer(container).then(item => [key, item])));
588
+ return new Map(entries);
589
+ }
590
+ async function getDataFromUrl(data) {
591
+ const url = itemFromSingleOrMultiple(data.url, data.index);
592
+ if (!url) {
593
+ return data.fallback;
508
594
  }
509
- return res;
595
+ try {
596
+ const response = await fetch(url);
597
+ if (response.ok) {
598
+ const current = (await response.json());
599
+ if (isSourceOptionsValue(current)) {
600
+ return current;
601
+ }
602
+ getLogger().error("invalid configuration data while retrieving config file");
603
+ }
604
+ else {
605
+ getLogger().error(`${response.status.toString()} while retrieving config file`);
606
+ }
607
+ }
608
+ catch (error) {
609
+ getLogger().error(`error while retrieving config file: ${error}`);
610
+ }
611
+ return data.fallback;
510
612
  }
511
- async function getItemMapFromInitializer(container, map, initializers, force = false) {
512
- let res = map.get(container);
513
- if (!res || force) {
514
- const entries = await Promise.all([...initializers.entries()].map(([key, initializer]) => initializer(container).then(item => [key, item])));
515
- res = new Map(entries);
516
- map.set(container, res);
613
+ function isSourceOptionsValue(value) {
614
+ if (isArray(value)) {
615
+ return value.every((entry) => isObject(entry) && !isArray(entry));
517
616
  }
518
- return res;
617
+ return isObject(value) && !isArray(value);
618
+ }
619
+ function getCanvasFromContainer(domContainer) {
620
+ let canvasEl;
621
+ const documentSafe = safeDocument(), isCanvas = domContainer instanceof HTMLCanvasElement || domContainer.tagName.toLowerCase() === canvasTag;
622
+ if (isCanvas) {
623
+ canvasEl = domContainer;
624
+ canvasEl.dataset[generatedAttribute] ??= generatedFalse;
625
+ if (canvasEl.dataset[generatedAttribute] === generatedTrue) {
626
+ canvasEl.style.width ||= fullPercent;
627
+ canvasEl.style.height ||= fullPercent;
628
+ canvasEl.style.pointerEvents = "none";
629
+ canvasEl.style.setProperty("pointer-events", "none");
630
+ }
631
+ }
632
+ else {
633
+ const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
634
+ if (foundCanvas) {
635
+ canvasEl = foundCanvas;
636
+ canvasEl.dataset[generatedAttribute] = generatedFalse;
637
+ }
638
+ else {
639
+ canvasEl = documentSafe.createElement(canvasTag);
640
+ canvasEl.dataset[generatedAttribute] = generatedTrue;
641
+ domContainer.appendChild(canvasEl);
642
+ }
643
+ canvasEl.style.width ||= fullPercent;
644
+ canvasEl.style.height ||= fullPercent;
645
+ canvasEl.style.pointerEvents = "none";
646
+ canvasEl.style.setProperty("pointer-events", "none");
647
+ }
648
+ return canvasEl;
649
+ }
650
+ function getDomContainer(id, source) {
651
+ const documentSafe = safeDocument();
652
+ let domContainer = source ?? documentSafe.getElementById(id);
653
+ if (domContainer) {
654
+ return domContainer;
655
+ }
656
+ domContainer = documentSafe.createElement("canvas");
657
+ domContainer.id = id;
658
+ domContainer.dataset[generatedAttribute] = generatedTrue;
659
+ documentSafe.body.append(domContainer);
660
+ return domContainer;
519
661
  }
520
662
 
521
663
  class EventDispatcher {
@@ -525,12 +667,8 @@
525
667
  }
526
668
  addEventListener(type, listener) {
527
669
  this.removeEventListener(type, listener);
528
- let arr = this.#listeners.get(type);
529
- if (!arr) {
530
- arr = [];
531
- this.#listeners.set(type, arr);
532
- }
533
- arr.push(listener);
670
+ const arr = this.#listeners.get(type);
671
+ this.#listeners.set(type, arr ? [...arr, listener] : [listener]);
534
672
  }
535
673
  dispatchEvent(type, args) {
536
674
  const listeners = this.#listeners.get(type);
@@ -562,7 +700,7 @@
562
700
  this.#listeners.delete(type);
563
701
  }
564
702
  else {
565
- arr.splice(idx, deleteCount);
703
+ this.#listeners.set(type, [...arr.slice(minIndex, idx), ...arr.slice(idx + deleteCount)]);
566
704
  }
567
705
  }
568
706
  }
@@ -586,7 +724,6 @@
586
724
  class PluginManager {
587
725
  colorManagers = new Map();
588
726
  easingFunctions = new Map();
589
- effectDrawers = new Map();
590
727
  initializers = {
591
728
  effects: new Map(),
592
729
  shapes: new Map(),
@@ -595,8 +732,6 @@
595
732
  palettes = new Map();
596
733
  plugins = [];
597
734
  presets = new Map();
598
- shapeDrawers = new Map();
599
- updaters = new Map();
600
735
  #allLoadersSet = new Set();
601
736
  #configs = new Map();
602
737
  #engine;
@@ -614,57 +749,79 @@
614
749
  }
615
750
  return res;
616
751
  }
752
+ get initialized() {
753
+ return this.#initialized;
754
+ }
617
755
  addColorManager(name, manager) {
756
+ if (this.#initialized) {
757
+ return;
758
+ }
618
759
  this.colorManagers.set(name, manager);
619
760
  }
620
761
  addConfig(config) {
762
+ if (this.#initialized) {
763
+ return;
764
+ }
621
765
  const key = config.key ?? config.name ?? "default";
622
766
  this.#configs.set(key, config);
623
767
  this.#engine.dispatchEvent(EventType.configAdded, { data: { name: key, config } });
624
768
  }
625
769
  addEasing(name, easing) {
770
+ if (this.#initialized) {
771
+ return;
772
+ }
626
773
  if (this.easingFunctions.get(name)) {
627
774
  return;
628
775
  }
629
776
  this.easingFunctions.set(name, easing);
630
777
  }
631
778
  addEffect(effect, drawer) {
779
+ if (this.#initialized) {
780
+ return;
781
+ }
632
782
  this.initializers.effects.set(effect, drawer);
633
783
  }
634
784
  addPalette(name, palette) {
785
+ if (this.#initialized) {
786
+ return;
787
+ }
635
788
  this.palettes.set(name, palette);
636
789
  }
637
790
  addParticleUpdater(name, updaterInitializer) {
791
+ if (this.#initialized) {
792
+ return;
793
+ }
638
794
  this.initializers.updaters.set(name, updaterInitializer);
639
795
  }
640
796
  addPlugin(plugin) {
797
+ if (this.#initialized) {
798
+ return;
799
+ }
641
800
  if (this.getPlugin(plugin.id)) {
642
801
  return;
643
802
  }
644
803
  this.plugins.push(plugin);
645
804
  }
646
805
  addPreset(preset, options, override = false) {
806
+ if (this.#initialized) {
807
+ return;
808
+ }
647
809
  if (!(override || !this.getPreset(preset))) {
648
810
  return;
649
811
  }
650
812
  this.presets.set(preset, options);
651
813
  }
652
814
  addShape(shapes, drawer) {
815
+ if (this.#initialized) {
816
+ return;
817
+ }
653
818
  for (const shape of shapes) {
654
819
  this.initializers.shapes.set(shape, drawer);
655
820
  }
656
821
  }
657
- clearPlugins(container) {
658
- this.effectDrawers.delete(container);
659
- this.shapeDrawers.delete(container);
660
- this.updaters.delete(container);
661
- }
662
822
  getEasing(name) {
663
823
  return this.easingFunctions.get(name) ?? ((value) => value);
664
824
  }
665
- getEffectDrawers(container, force = false) {
666
- return getItemMapFromInitializer(container, this.effectDrawers, this.initializers.effects, force);
667
- }
668
825
  getPalette(name) {
669
826
  return this.palettes.get(name);
670
827
  }
@@ -674,12 +831,6 @@
674
831
  getPreset(preset) {
675
832
  return this.presets.get(preset);
676
833
  }
677
- async getShapeDrawers(container, force = false) {
678
- return getItemMapFromInitializer(container, this.shapeDrawers, this.initializers.shapes, force);
679
- }
680
- async getUpdaters(container, force = false) {
681
- return getItemsFromInitializer(container, this.updaters, this.initializers.updaters, force);
682
- }
683
834
  async init() {
684
835
  if (this.#initialized || this.#isRunningLoaders) {
685
836
  return;
@@ -698,16 +849,9 @@
698
849
  this.#initialized = true;
699
850
  }
700
851
  }
701
- loadParticlesOptions(container, options, ...sourceOptions) {
702
- const updaters = this.updaters.get(container);
703
- if (!updaters) {
704
- return;
705
- }
706
- updaters.forEach(updater => updater.loadOptions?.(options, ...sourceOptions));
707
- }
708
852
  async register(...loaders) {
709
853
  if (this.#initialized) {
710
- throw new Error("Register plugins can only be done before calling tsParticles.load()");
854
+ throw new Error(getErrorMessage(ErrorCodes$2.pluginRegisterAfterLoad));
711
855
  }
712
856
  for (const loader of loaders) {
713
857
  if (this.#isRunningLoaders) {
@@ -719,88 +863,15 @@
719
863
  }
720
864
  }
721
865
  async #runLoader(loader, executed, allLoaders) {
722
- if (executed.has(loader))
866
+ if (executed.has(loader)) {
723
867
  return;
868
+ }
724
869
  executed.add(loader);
725
870
  allLoaders.add(loader);
726
871
  await loader(this.#engine);
727
872
  }
728
873
  }
729
874
 
730
- const errorPrefix = "tsParticles - Error";
731
- const wrap = (fn) => (...args) => {
732
- fn(...args);
733
- }, _logger = {
734
- debug: wrap(console.debug),
735
- error: (message, ...optionalParams) => {
736
- console.error(`${errorPrefix} - ${message}`, ...optionalParams);
737
- },
738
- info: wrap(console.info),
739
- log: wrap(console.log),
740
- trace: wrap(console.trace),
741
- verbose: wrap(console.log),
742
- warning: wrap(console.warn),
743
- };
744
- function getLogger() {
745
- return _logger;
746
- }
747
-
748
- const fullPercent = "100%";
749
- async function getDataFromUrl(data) {
750
- const url = itemFromSingleOrMultiple(data.url, data.index);
751
- if (!url) {
752
- return data.fallback;
753
- }
754
- const response = await fetch(url);
755
- if (response.ok) {
756
- return (await response.json());
757
- }
758
- getLogger().error(`${response.status.toString()} while retrieving config file`);
759
- return data.fallback;
760
- }
761
- const getCanvasFromContainer = (domContainer) => {
762
- const documentSafe = safeDocument();
763
- let canvasEl;
764
- const isCanvas = domContainer instanceof HTMLCanvasElement || domContainer.tagName.toLowerCase() === canvasTag;
765
- if (isCanvas) {
766
- canvasEl = domContainer;
767
- canvasEl.dataset[generatedAttribute] ??= generatedFalse;
768
- if (canvasEl.dataset[generatedAttribute] === generatedTrue) {
769
- canvasEl.style.width ||= fullPercent;
770
- canvasEl.style.height ||= fullPercent;
771
- canvasEl.style.pointerEvents = "none";
772
- canvasEl.style.setProperty("pointer-events", "none");
773
- }
774
- }
775
- else {
776
- const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
777
- if (foundCanvas) {
778
- canvasEl = foundCanvas;
779
- canvasEl.dataset[generatedAttribute] = generatedFalse;
780
- }
781
- else {
782
- canvasEl = documentSafe.createElement(canvasTag);
783
- canvasEl.dataset[generatedAttribute] = generatedTrue;
784
- domContainer.appendChild(canvasEl);
785
- }
786
- canvasEl.style.width ||= fullPercent;
787
- canvasEl.style.height ||= fullPercent;
788
- canvasEl.style.pointerEvents = "none";
789
- canvasEl.style.setProperty("pointer-events", "none");
790
- }
791
- return canvasEl;
792
- }, getDomContainer = (id, source) => {
793
- const documentSafe = safeDocument();
794
- let domContainer = source ?? documentSafe.getElementById(id);
795
- if (domContainer) {
796
- return domContainer;
797
- }
798
- domContainer = documentSafe.createElement("canvas");
799
- domContainer.id = id;
800
- domContainer.dataset[generatedAttribute] = generatedTrue;
801
- documentSafe.body.append(domContainer);
802
- return domContainer;
803
- };
804
875
  class Engine {
805
876
  pluginManager = new PluginManager(this);
806
877
  #domArray = [];
@@ -810,7 +881,7 @@
810
881
  return this.#domArray;
811
882
  }
812
883
  get version() {
813
- return "4.4.0";
884
+ return "4.5.1";
814
885
  }
815
886
  addEventListener(type, listener) {
816
887
  this.#eventDispatcher.addEventListener(type, listener);
@@ -819,7 +890,7 @@
819
890
  if (this.version === pluginVersion) {
820
891
  return;
821
892
  }
822
- throw new Error(`The tsParticles version is different from the loaded plugins version. Engine version: ${this.version}. Plugin version: ${pluginVersion}`);
893
+ throw new Error(getErrorMessage(ErrorCodes$2.engineVersionMismatch, this.version, pluginVersion));
823
894
  }
824
895
  dispatchEvent(type, args) {
825
896
  this.#eventDispatcher.dispatchEvent(type, args);
@@ -1068,20 +1139,6 @@
1068
1139
  DrawLayer[DrawLayer["Foreground"] = 7] = "Foreground";
1069
1140
  })(DrawLayer || (DrawLayer = {}));
1070
1141
 
1071
- class OptionLoader {
1072
- load(data) {
1073
- if (isNull(data)) {
1074
- return;
1075
- }
1076
- this.doLoad(data);
1077
- }
1078
- }
1079
- function loadOptions(options, ...sourceOptionsArr) {
1080
- for (const sourceOptions of sourceOptionsArr) {
1081
- options.load(sourceOptions);
1082
- }
1083
- }
1084
-
1085
1142
  function loadProperty(obj, key, value) {
1086
1143
  if (value !== undefined) {
1087
1144
  obj[key] = value;
@@ -1113,6 +1170,20 @@
1113
1170
  }
1114
1171
  }
1115
1172
 
1173
+ class OptionLoader {
1174
+ load(data) {
1175
+ if (isNull(data)) {
1176
+ return;
1177
+ }
1178
+ this.doLoad(data);
1179
+ }
1180
+ }
1181
+ function loadOptions(options, ...sourceOptionsArr) {
1182
+ for (const sourceOptions of sourceOptionsArr) {
1183
+ options.load(sourceOptions);
1184
+ }
1185
+ }
1186
+
1116
1187
  class AnimationOptions extends OptionLoader {
1117
1188
  count = 0;
1118
1189
  decay = 0;
@@ -1263,15 +1334,14 @@
1263
1334
  peakNits = defaultPeakNits;
1264
1335
  doLoad(data) {
1265
1336
  if (data.enable !== undefined && !isBoolean(data.enable)) {
1266
- throw new Error(`Invalid HDR "enable" value: expected a boolean, got "${String(data.enable)}"`);
1337
+ throw new Error(getErrorMessage(ErrorCodes$2.hdrEnableInvalid, String(data.enable)));
1267
1338
  }
1268
- if (data.mode !== undefined &&
1269
- (typeof data.mode !== "string" || !Object.values(HdrMode).includes(data.mode))) {
1270
- throw new Error(`Invalid HDR "mode" value: expected one of ${Object.values(HdrMode).join(", ")}, got "${toStringValue(data.mode)}"`);
1339
+ if (data.mode !== undefined && !isEnumValue(HdrMode, data.mode)) {
1340
+ throw new Error(getErrorMessage(ErrorCodes$2.hdrModeInvalid, Object.values(HdrMode).join(", "), toStringValue(data.mode)));
1271
1341
  }
1272
1342
  if (data.peakNits !== undefined &&
1273
1343
  (!isNumber(data.peakNits) || !Number.isFinite(data.peakNits) || data.peakNits <= minPeakNits)) {
1274
- throw new Error(`Invalid HDR "peakNits" value: expected a positive number, got "${String(data.peakNits)}"`);
1344
+ throw new Error(getErrorMessage(ErrorCodes$2.hdrPeakNitsInvalid, String(data.peakNits)));
1275
1345
  }
1276
1346
  loadProperty(this, "enable", data.enable);
1277
1347
  loadProperty(this, "mode", data.mode);
@@ -1649,12 +1719,10 @@
1649
1719
  plugin.loadParticlesOptions(this.#container, this, data);
1650
1720
  }
1651
1721
  }
1652
- const updaters = this.#pluginManager.updaters.get(this.#container);
1653
- if (updaters) {
1654
- for (const updater of updaters) {
1655
- if (updater.loadOptions) {
1656
- updater.loadOptions(this, data);
1657
- }
1722
+ const updaters = this.#container.particleUpdaters;
1723
+ for (const updater of updaters) {
1724
+ if (updater.loadOptions) {
1725
+ updater.loadOptions(this, data);
1658
1726
  }
1659
1727
  }
1660
1728
  }
@@ -1987,9 +2055,9 @@
1987
2055
  const grayscaleValue = Math.round(lNormalized * rgbMax);
1988
2056
  return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
1989
2057
  }
1990
- const temp1 = lNormalized < half
2058
+ const temp2 = lNormalized < half
1991
2059
  ? lNormalized * (sNormalizedOffset + sNormalized)
1992
- : lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized - phaseThird));
2060
+ : lNormalized + sNormalized - lNormalized * sNormalized, temp1 = double * lNormalized - temp2, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp1, temp2, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp1, temp2, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp1, temp2, hNormalized - phaseThird));
1993
2061
  return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
1994
2062
  }
1995
2063
  function hslToRgbFloat(hsl) {
@@ -1998,9 +2066,9 @@
1998
2066
  const grayscaleValue = lNormalized * rgbMax;
1999
2067
  return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
2000
2068
  }
2001
- const temp1 = lNormalized < half
2069
+ const temp2 = lNormalized < half
2002
2070
  ? lNormalized * (sNormalizedOffset + sNormalized)
2003
- : lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized - phaseThird));
2071
+ : lNormalized + sNormalized - lNormalized * sNormalized, temp1 = double * lNormalized - temp2, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp1, temp2, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp1, temp2, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp1, temp2, hNormalized - phaseThird));
2004
2072
  return { r: red, g: green, b: blue };
2005
2073
  }
2006
2074
  function hslaToRgba(hsla) {
@@ -2214,7 +2282,7 @@
2214
2282
  }
2215
2283
 
2216
2284
  async function loadBlendPlugin(engine) {
2217
- engine.checkVersion("4.4.0");
2285
+ engine.checkVersion("4.5.1");
2218
2286
  await engine.pluginManager.register(e => {
2219
2287
  e.pluginManager.addPlugin(new BlendPlugin());
2220
2288
  });
@@ -2251,7 +2319,7 @@
2251
2319
  }
2252
2320
 
2253
2321
  async function loadCircleShape(engine) {
2254
- engine.checkVersion("4.4.0");
2322
+ engine.checkVersion("4.5.1");
2255
2323
  await engine.pluginManager.register(e => {
2256
2324
  e.pluginManager.addShape(["circle"], () => {
2257
2325
  return Promise.resolve(new CircleDrawer());
@@ -2266,7 +2334,7 @@
2266
2334
  RgbIndexes[RgbIndexes["b"] = 3] = "b";
2267
2335
  RgbIndexes[RgbIndexes["a"] = 4] = "a";
2268
2336
  })(RgbIndexes$1 || (RgbIndexes$1 = {}));
2269
- const shorthandHexRegex = /^#?([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i, hexRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i, hexRadix = 16, defaultAlpha = 1, alphaFactor = 0xff;
2337
+ const shorthandHexRegex = /^#?([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i, hexRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i, hexRadix = 16, alphaFactor = 0xff;
2270
2338
  class HexColorManager {
2271
2339
  accepts(input) {
2272
2340
  return input.startsWith("#");
@@ -2299,7 +2367,7 @@
2299
2367
  }
2300
2368
 
2301
2369
  async function loadHexColorPlugin(engine) {
2302
- engine.checkVersion("4.4.0");
2370
+ engine.checkVersion("4.5.1");
2303
2371
  await engine.pluginManager.register(e => {
2304
2372
  e.pluginManager.addColorManager("hex", new HexColorManager());
2305
2373
  });
@@ -2339,7 +2407,7 @@
2339
2407
  if (!this.accepts(input)) {
2340
2408
  return;
2341
2409
  }
2342
- const result = hslRegex.exec(input), minLength = 4, defaultAlpha = 1, radix = 10;
2410
+ const result = hslRegex.exec(input), minLength = 4, radix = 10;
2343
2411
  return result
2344
2412
  ? hslaToRgba({
2345
2413
  a: result.length > minLength ? parseAlpha(result[HslIndexes.a]) : defaultAlpha,
@@ -2352,12 +2420,20 @@
2352
2420
  }
2353
2421
 
2354
2422
  async function loadHslColorPlugin(engine) {
2355
- engine.checkVersion("4.4.0");
2423
+ engine.checkVersion("4.5.1");
2356
2424
  await engine.pluginManager.register(e => {
2357
2425
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2358
2426
  });
2359
2427
  }
2360
2428
 
2429
+ const ErrorCodes$1 = {
2430
+ baseMoverNotLoaded: "TSP-3203",
2431
+ };
2432
+
2433
+ const ErrorMessages$1 = {
2434
+ [ErrorCodes$1.baseMoverNotLoaded]: "tsParticles Base Mover is not loaded",
2435
+ };
2436
+
2361
2437
  class MovePlugin {
2362
2438
  id = "move";
2363
2439
  #pluginManager;
@@ -2376,20 +2452,20 @@
2376
2452
  }
2377
2453
 
2378
2454
  async function loadMovePlugin(engine) {
2379
- engine.checkVersion("4.4.0");
2455
+ engine.checkVersion("4.5.1");
2456
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
2457
+ addErrorMessages(ErrorMessages$1);
2458
+ }
2380
2459
  await engine.pluginManager.register(e => {
2381
2460
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2382
2461
  movePluginManager.initializers.pathGenerators ??= new Map();
2383
- movePluginManager.pathGenerators ??= new Map();
2384
2462
  movePluginManager.addPathGenerator = (name, generator) => {
2463
+ if (movePluginManager.initialized) {
2464
+ return;
2465
+ }
2385
2466
  movePluginManager.initializers.pathGenerators ??= new Map();
2386
2467
  movePluginManager.initializers.pathGenerators.set(name, generator);
2387
2468
  };
2388
- movePluginManager.getPathGenerators = async (container, force = false) => {
2389
- movePluginManager.initializers.pathGenerators ??= new Map();
2390
- movePluginManager.pathGenerators ??= new Map();
2391
- return getItemMapFromInitializer(container, movePluginManager.pathGenerators, movePluginManager.initializers.pathGenerators, force);
2392
- };
2393
2469
  e.pluginManager.addPlugin(new MovePlugin(e.pluginManager));
2394
2470
  });
2395
2471
  }
@@ -2586,7 +2662,7 @@
2586
2662
  }
2587
2663
 
2588
2664
  async function loadOpacityUpdater(engine) {
2589
- engine.checkVersion("4.4.0");
2665
+ engine.checkVersion("4.5.1");
2590
2666
  await engine.pluginManager.register(e => {
2591
2667
  e.pluginManager.addParticleUpdater("opacity", container => {
2592
2668
  return Promise.resolve(new OpacityUpdater(container));
@@ -2595,70 +2671,60 @@
2595
2671
  }
2596
2672
 
2597
2673
  const boundsMin = 0;
2598
- function bounceHorizontal(data) {
2599
- if ((data.outMode !== OutMode.bounce && data.outMode !== OutMode.split) ||
2600
- (data.direction !== OutModeDirection.left && data.direction !== OutModeDirection.right)) {
2601
- return;
2602
- }
2603
- if (data.bounds.right < boundsMin && data.direction === OutModeDirection.left) {
2604
- data.particle.position.x = data.size + data.offset.x;
2605
- }
2606
- else if (data.bounds.left > data.canvasSize.width && data.direction === OutModeDirection.right) {
2607
- data.particle.position.x = data.canvasSize.width - data.size - data.offset.x;
2608
- }
2609
- const velocity = data.particle.velocity.x;
2610
- let bounced = false;
2611
- if (data.outOfCanvas &&
2612
- ((data.direction === OutModeDirection.right && velocity > minVelocity) ||
2613
- (data.direction === OutModeDirection.left && velocity < minVelocity))) {
2614
- const newVelocity = getRangeValue(data.particle.options.bounce.horizontal.value);
2615
- data.particle.velocity.x *= -newVelocity;
2616
- bounced = true;
2617
- }
2618
- if (!bounced) {
2619
- return;
2620
- }
2621
- const minPos = data.offset.x + data.size;
2622
- if (data.outOfCanvas && data.direction === OutModeDirection.right) {
2623
- data.particle.position.x = data.canvasSize.width - minPos;
2624
- }
2625
- else if (data.outOfCanvas && data.direction === OutModeDirection.left) {
2626
- data.particle.position.x = minPos;
2627
- }
2628
- if (data.outMode === OutMode.split) {
2629
- data.particle.destroy();
2630
- }
2631
- }
2632
- function bounceVertical(data) {
2633
- if ((data.outMode !== OutMode.bounce && data.outMode !== OutMode.split) ||
2634
- (data.direction !== OutModeDirection.bottom && data.direction !== OutModeDirection.top)) {
2674
+ const bounceAxisConfigs = {
2675
+ [OutModeDirection.left]: {
2676
+ axis: "x",
2677
+ canvas: "width",
2678
+ bounce: "horizontal",
2679
+ negativeEdge: "right",
2680
+ positiveEdge: "left",
2681
+ negative: true,
2682
+ },
2683
+ [OutModeDirection.right]: {
2684
+ axis: "x",
2685
+ canvas: "width",
2686
+ bounce: "horizontal",
2687
+ negativeEdge: "right",
2688
+ positiveEdge: "left",
2689
+ negative: false,
2690
+ },
2691
+ [OutModeDirection.top]: {
2692
+ axis: "y",
2693
+ canvas: "height",
2694
+ bounce: "vertical",
2695
+ negativeEdge: "bottom",
2696
+ positiveEdge: "top",
2697
+ negative: true,
2698
+ },
2699
+ [OutModeDirection.bottom]: {
2700
+ axis: "y",
2701
+ canvas: "height",
2702
+ bounce: "vertical",
2703
+ negativeEdge: "bottom",
2704
+ positiveEdge: "top",
2705
+ negative: false,
2706
+ },
2707
+ };
2708
+ function bounce(data) {
2709
+ if ((data.outMode !== OutMode.bounce && data.outMode !== OutMode.split) || !(data.direction in bounceAxisConfigs)) {
2635
2710
  return;
2636
2711
  }
2637
- if (data.bounds.bottom < boundsMin && data.direction === OutModeDirection.top) {
2638
- data.particle.position.y = data.size + data.offset.y;
2712
+ const config = bounceAxisConfigs[data.direction], bounds = data.bounds, canvasDim = data.canvasSize[config.canvas], position = data.particle.position, velocity = data.particle.velocity[config.axis];
2713
+ if (config.negative && bounds[config.negativeEdge] < boundsMin) {
2714
+ position[config.axis] = data.size + data.offset[config.axis];
2639
2715
  }
2640
- else if (data.bounds.top > data.canvasSize.height && data.direction === OutModeDirection.bottom) {
2641
- data.particle.position.y = data.canvasSize.height - data.size - data.offset.y;
2716
+ else if (!config.negative && bounds[config.positiveEdge] > canvasDim) {
2717
+ position[config.axis] = canvasDim - data.size - data.offset[config.axis];
2642
2718
  }
2643
- const velocity = data.particle.velocity.y;
2644
- let bounced = false;
2645
2719
  if (data.outOfCanvas &&
2646
- ((data.direction === OutModeDirection.bottom && velocity > minVelocity) ||
2647
- (data.direction === OutModeDirection.top && velocity < minVelocity))) {
2648
- const newVelocity = getRangeValue(data.particle.options.bounce.vertical.value);
2649
- data.particle.velocity.y *= -newVelocity;
2650
- bounced = true;
2720
+ ((config.negative && velocity < minVelocity) || (!config.negative && velocity > minVelocity))) {
2721
+ data.particle.velocity[config.axis] *= -getRangeValue(data.particle.options.bounce[config.bounce].value);
2651
2722
  }
2652
- if (!bounced) {
2723
+ else {
2653
2724
  return;
2654
2725
  }
2655
- const minPos = data.offset.y + data.size;
2656
- if (data.outOfCanvas && data.direction === OutModeDirection.bottom) {
2657
- data.particle.position.y = data.canvasSize.height - minPos;
2658
- }
2659
- else if (data.outOfCanvas && data.direction === OutModeDirection.top) {
2660
- data.particle.position.y = minPos;
2661
- }
2726
+ const minPos = data.offset[config.axis] + data.size;
2727
+ position[config.axis] = config.negative ? minPos : canvasDim - minPos;
2662
2728
  if (data.outMode === OutMode.split) {
2663
2729
  data.particle.destroy();
2664
2730
  }
@@ -2674,26 +2740,19 @@
2674
2740
  OutMode.bounce,
2675
2741
  OutMode.split,
2676
2742
  ];
2677
- this.#particleBouncePlugins = container.plugins.filter(p => p.particleBounce !== undefined);
2743
+ this.#particleBouncePlugins = container.plugins.filter(p => !!p.particleBounce);
2678
2744
  }
2679
2745
  update(particle, direction, delta, outMode) {
2680
2746
  if (!this.modes.includes(outMode)) {
2681
2747
  return;
2682
2748
  }
2683
- const container = this.#container;
2684
- let handled = false;
2685
2749
  for (const plugin of this.#particleBouncePlugins) {
2686
- handled = plugin.particleBounce?.(particle, delta, direction) ?? false;
2687
- if (handled) {
2688
- break;
2750
+ if (plugin.particleBounce?.(particle, delta, direction)) {
2751
+ return;
2689
2752
  }
2690
2753
  }
2691
- if (handled) {
2692
- return;
2693
- }
2694
- const pos = particle.getPosition(), offset = particle.offset, size = particle.getRadius(), bounds = calculateBounds(pos, size), canvasSize = container.canvas.size, outOfCanvas = !particle.isInsideCanvasForOutMode(outMode, direction);
2695
- bounceHorizontal({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
2696
- bounceVertical({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
2754
+ const pos = particle.getPosition(), offset = particle.offset, size = particle.getRadius(), bounds = calculateBounds(pos, size), canvasSize = this.#container.canvas.size, outOfCanvas = !particle.isInsideCanvasForOutMode(outMode, direction);
2755
+ bounce({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
2697
2756
  }
2698
2757
  }
2699
2758
 
@@ -2782,107 +2841,108 @@
2782
2841
  return;
2783
2842
  }
2784
2843
  const container = this.#container;
2785
- switch (particle.outType) {
2786
- case ParticleOutType.inside: {
2787
- const { x: vx, y: vy } = particle.velocity;
2788
- updateVector.setTo(originPoint);
2789
- updateVector.length = particle.moveCenter.radius;
2790
- updateVector.angle = particle.velocity.angle + Math.PI;
2791
- updateVector.addTo(particle.moveCenter);
2792
- const { dx, dy } = getDistances(particle.position, updateVector);
2793
- if ((vx <= minVelocity && dx >= minDistance) ||
2794
- (vy <= minVelocity && dy >= minDistance) ||
2795
- (vx >= minVelocity && dx <= minDistance) ||
2796
- (vy >= minVelocity && dy <= minDistance)) {
2797
- return;
2798
- }
2799
- particle.position.x = Math.floor(randomInRangeValue({
2800
- min: 0,
2801
- max: container.canvas.size.width,
2802
- }));
2803
- particle.position.y = Math.floor(randomInRangeValue({
2804
- min: 0,
2805
- max: container.canvas.size.height,
2806
- }));
2807
- const { dx: newDx, dy: newDy } = getDistances(particle.position, particle.moveCenter);
2808
- particle.direction = Math.atan2(-newDy, -newDx);
2809
- particle.velocity.angle = particle.direction;
2810
- particle.justWarped = true;
2811
- break;
2844
+ if (particle.outType === ParticleOutType.inside) {
2845
+ this.#applyOutModeInside(particle, container);
2846
+ }
2847
+ else {
2848
+ if (particle.isInsideCanvasForOutMode(outMode, direction)) {
2849
+ return;
2812
2850
  }
2813
- default: {
2814
- if (particle.isInsideCanvasForOutMode(outMode, direction)) {
2815
- return;
2816
- }
2817
- switch (particle.outType) {
2818
- case ParticleOutType.outside: {
2819
- particle.position.x =
2820
- Math.floor(randomInRangeValue({
2821
- min: -particle.moveCenter.radius,
2822
- max: particle.moveCenter.radius,
2823
- })) + particle.moveCenter.x;
2824
- particle.position.y =
2825
- Math.floor(randomInRangeValue({
2826
- min: -particle.moveCenter.radius,
2827
- max: particle.moveCenter.radius,
2828
- })) + particle.moveCenter.y;
2829
- const { dx, dy } = getDistances(particle.position, particle.moveCenter);
2830
- if (particle.moveCenter.radius) {
2831
- particle.direction = Math.atan2(dy, dx);
2832
- particle.velocity.angle = particle.direction;
2833
- }
2834
- particle.justWarped = true;
2835
- break;
2836
- }
2837
- case ParticleOutType.normal: {
2838
- const warp = particle.options.move.warp, canvasSize = container.canvas.size, newPos = {
2839
- bottom: canvasSize.height + particle.getRadius() + particle.offset.y,
2840
- left: -particle.getRadius() - particle.offset.x,
2841
- right: canvasSize.width + particle.getRadius() + particle.offset.x,
2842
- top: -particle.getRadius() - particle.offset.y,
2843
- }, sizeValue = particle.getRadius(), nextBounds = calculateBounds(particle.position, sizeValue);
2844
- if (direction === OutModeDirection.right && nextBounds.left > canvasSize.width + particle.offset.x) {
2845
- particle.position.x = newPos.left;
2846
- particle.initialPosition.x = particle.position.x;
2847
- if (!warp) {
2848
- particle.position.y = getRandom() * canvasSize.height;
2849
- particle.initialPosition.y = particle.position.y;
2850
- }
2851
- particle.justWarped = true;
2852
- }
2853
- else if (direction === OutModeDirection.left && nextBounds.right < -particle.offset.x) {
2854
- particle.position.x = newPos.right;
2855
- particle.initialPosition.x = particle.position.x;
2856
- if (!warp) {
2857
- particle.position.y = getRandom() * canvasSize.height;
2858
- particle.initialPosition.y = particle.position.y;
2859
- }
2860
- particle.justWarped = true;
2861
- }
2862
- if (direction === OutModeDirection.bottom && nextBounds.top > canvasSize.height + particle.offset.y) {
2863
- if (!warp) {
2864
- particle.position.x = getRandom() * canvasSize.width;
2865
- particle.initialPosition.x = particle.position.x;
2866
- }
2867
- particle.position.y = newPos.top;
2868
- particle.initialPosition.y = particle.position.y;
2869
- particle.justWarped = true;
2870
- }
2871
- else if (direction === OutModeDirection.top && nextBounds.bottom < -particle.offset.y) {
2872
- if (!warp) {
2873
- particle.position.x = getRandom() * canvasSize.width;
2874
- particle.initialPosition.x = particle.position.x;
2875
- }
2876
- particle.position.y = newPos.bottom;
2877
- particle.initialPosition.y = particle.position.y;
2878
- particle.justWarped = true;
2879
- }
2880
- break;
2881
- }
2882
- }
2883
- break;
2851
+ if (particle.outType === ParticleOutType.outside) {
2852
+ this.#applyParticleModeOutside(particle);
2884
2853
  }
2885
- }
2854
+ else {
2855
+ this.#applyOutModeNormal(particle, container, direction);
2856
+ }
2857
+ }
2858
+ }
2859
+ #applyOutModeInside(particle, container) {
2860
+ const { x: vx, y: vy } = particle.velocity;
2861
+ updateVector.setTo(originPoint);
2862
+ updateVector.length = particle.moveCenter.radius;
2863
+ updateVector.angle = particle.velocity.angle + Math.PI;
2864
+ updateVector.addTo(particle.moveCenter);
2865
+ const { dx, dy } = getDistances(particle.position, updateVector);
2866
+ if ((vx <= minVelocity && dx >= minDistance) ||
2867
+ (vy <= minVelocity && dy >= minDistance) ||
2868
+ (vx >= minVelocity && dx <= minDistance) ||
2869
+ (vy >= minVelocity && dy <= minDistance)) {
2870
+ return;
2871
+ }
2872
+ particle.position.x = Math.floor(randomInRangeValue({
2873
+ min: 0,
2874
+ max: container.canvas.size.width,
2875
+ }));
2876
+ particle.position.y = Math.floor(randomInRangeValue({
2877
+ min: 0,
2878
+ max: container.canvas.size.height,
2879
+ }));
2880
+ const { dx: newDx, dy: newDy } = getDistances(particle.position, particle.moveCenter);
2881
+ particle.direction = Math.atan2(-newDy, -newDx);
2882
+ particle.velocity.angle = particle.direction;
2883
+ particle.justWarped = true;
2884
+ }
2885
+ #applyOutModeNormal(particle, container, direction) {
2886
+ const warp = particle.options.move.warp, canvasSize = container.canvas.size, sizeValue = particle.getRadius(), newPos = {
2887
+ bottom: canvasSize.height + sizeValue + particle.offset.y,
2888
+ left: -sizeValue - particle.offset.x,
2889
+ right: canvasSize.width + sizeValue + particle.offset.x,
2890
+ top: -sizeValue - particle.offset.y,
2891
+ }, nextBounds = calculateBounds(particle.position, sizeValue);
2892
+ if (direction === OutModeDirection.right && nextBounds.left > canvasSize.width + particle.offset.x) {
2893
+ particle.position.x = newPos.left;
2894
+ particle.initialPosition.x = particle.position.x;
2895
+ if (!warp) {
2896
+ particle.position.y = getRandom() * canvasSize.height;
2897
+ particle.initialPosition.y = particle.position.y;
2898
+ }
2899
+ particle.justWarped = true;
2900
+ }
2901
+ else if (direction === OutModeDirection.left && nextBounds.right < -particle.offset.x) {
2902
+ particle.position.x = newPos.right;
2903
+ particle.initialPosition.x = particle.position.x;
2904
+ if (!warp) {
2905
+ particle.position.y = getRandom() * canvasSize.height;
2906
+ particle.initialPosition.y = particle.position.y;
2907
+ }
2908
+ particle.justWarped = true;
2909
+ }
2910
+ if (direction === OutModeDirection.bottom && nextBounds.top > canvasSize.height + particle.offset.y) {
2911
+ if (!warp) {
2912
+ particle.position.x = getRandom() * canvasSize.width;
2913
+ particle.initialPosition.x = particle.position.x;
2914
+ }
2915
+ particle.position.y = newPos.top;
2916
+ particle.initialPosition.y = particle.position.y;
2917
+ particle.justWarped = true;
2918
+ }
2919
+ else if (direction === OutModeDirection.top && nextBounds.bottom < -particle.offset.y) {
2920
+ if (!warp) {
2921
+ particle.position.x = getRandom() * canvasSize.width;
2922
+ particle.initialPosition.x = particle.position.x;
2923
+ }
2924
+ particle.position.y = newPos.bottom;
2925
+ particle.initialPosition.y = particle.position.y;
2926
+ particle.justWarped = true;
2927
+ }
2928
+ }
2929
+ #applyParticleModeOutside(particle) {
2930
+ particle.position.x =
2931
+ Math.floor(randomInRangeValue({
2932
+ min: -particle.moveCenter.radius,
2933
+ max: particle.moveCenter.radius,
2934
+ })) + particle.moveCenter.x;
2935
+ particle.position.y =
2936
+ Math.floor(randomInRangeValue({
2937
+ min: -particle.moveCenter.radius,
2938
+ max: particle.moveCenter.radius,
2939
+ })) + particle.moveCenter.y;
2940
+ const { dx, dy } = getDistances(particle.position, particle.moveCenter);
2941
+ if (particle.moveCenter.radius) {
2942
+ particle.direction = Math.atan2(dy, dx);
2943
+ particle.velocity.angle = particle.direction;
2944
+ }
2945
+ particle.justWarped = true;
2886
2946
  }
2887
2947
  }
2888
2948
 
@@ -2931,7 +2991,7 @@
2931
2991
  }
2932
2992
 
2933
2993
  async function loadOutModesUpdater(engine) {
2934
- engine.checkVersion("4.4.0");
2994
+ engine.checkVersion("4.5.1");
2935
2995
  await engine.pluginManager.register(e => {
2936
2996
  e.pluginManager.addParticleUpdater("outModes", container => {
2937
2997
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -2948,39 +3008,9 @@
2948
3008
  this.#pluginManager = pluginManager;
2949
3009
  }
2950
3010
  init(particle) {
2951
- const container = this.#container, options = particle.options, paint = itemFromSingleOrMultiple(options.paint, particle.id, options.reduceDuplicates), color = paint?.color, paintColor = color ?? undefined, fill = paint?.fill, stroke = paint?.stroke;
2952
- if (fill) {
2953
- const fillColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), fill.color);
2954
- particle.fillEnabled = fill.enable;
2955
- particle.fillOpacity = getRangeValue(fill.opacity);
2956
- particle.fillAnimation = fillColor.animation;
2957
- const fillHslColor = rangeColorToHsl(this.#pluginManager, fillColor);
2958
- if (fillHslColor) {
2959
- particle.fillColor = getHslAnimationFromHsl(fillHslColor, particle.fillAnimation, container.retina.reduceFactor);
2960
- }
2961
- }
2962
- else {
2963
- particle.fillEnabled = false;
2964
- particle.fillAnimation = undefined;
2965
- particle.fillColor = undefined;
2966
- particle.fillOpacity = defaultOpacity;
2967
- }
2968
- if (stroke) {
2969
- const strokeColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), stroke.color);
2970
- particle.strokeWidth = getRangeValue(stroke.width) * container.retina.pixelRatio;
2971
- particle.strokeOpacity = getRangeValue(stroke.opacity ?? defaultOpacity);
2972
- particle.strokeAnimation = strokeColor.animation;
2973
- const strokeHslColor = rangeColorToHsl(this.#pluginManager, strokeColor) ?? particle.getFillColor();
2974
- if (strokeHslColor) {
2975
- particle.strokeColor = getHslAnimationFromHsl(strokeHslColor, particle.strokeAnimation, container.retina.reduceFactor);
2976
- }
2977
- }
2978
- else {
2979
- particle.strokeAnimation = undefined;
2980
- particle.strokeColor = undefined;
2981
- particle.strokeOpacity = defaultOpacity;
2982
- particle.strokeWidth = 0;
2983
- }
3011
+ const container = this.#container, options = particle.options, paint = itemFromSingleOrMultiple(options.paint, particle.id, options.reduceDuplicates);
3012
+ this.#initFill(paint, particle, container);
3013
+ this.#initStroke(paint, particle, container);
2984
3014
  }
2985
3015
  isEnabled(particle) {
2986
3016
  const { fillAnimation, fillColor, strokeAnimation, strokeColor } = particle, fillEnabled = !!fillAnimation &&
@@ -2999,10 +3029,48 @@
2999
3029
  updateColor(particle.fillColor, delta, this.#container.hdr);
3000
3030
  updateColor(particle.strokeColor, delta, this.#container.hdr);
3001
3031
  }
3032
+ #initFill(paint, particle, container) {
3033
+ const fill = paint?.fill, color = paint?.color, paintColor = color ?? undefined;
3034
+ if (!fill) {
3035
+ particle.fillEnabled = false;
3036
+ particle.fillAnimation = undefined;
3037
+ particle.fillColor = undefined;
3038
+ particle.fillOpacity = defaultOpacity;
3039
+ return;
3040
+ }
3041
+ const fillColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), fill.color);
3042
+ particle.fillEnabled = fill.enable;
3043
+ particle.fillOpacity = getRangeValue(fill.opacity);
3044
+ particle.fillAnimation = fillColor.animation;
3045
+ const fillHslColor = rangeColorToHsl(this.#pluginManager, fillColor);
3046
+ if (!fillHslColor) {
3047
+ return;
3048
+ }
3049
+ particle.fillColor = getHslAnimationFromHsl(fillHslColor, particle.fillAnimation, container.retina.reduceFactor);
3050
+ }
3051
+ #initStroke(paint, particle, container) {
3052
+ const stroke = paint?.stroke, color = paint?.color, paintColor = color ?? undefined;
3053
+ if (!stroke) {
3054
+ particle.strokeAnimation = undefined;
3055
+ particle.strokeColor = undefined;
3056
+ particle.strokeOpacity = defaultOpacity;
3057
+ particle.strokeWidth = 0;
3058
+ return;
3059
+ }
3060
+ const strokeColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), stroke.color);
3061
+ particle.strokeWidth = getRangeValue(stroke.width) * container.retina.pixelRatio;
3062
+ particle.strokeOpacity = getRangeValue(stroke.opacity ?? defaultOpacity);
3063
+ particle.strokeAnimation = strokeColor.animation;
3064
+ const strokeHslColor = rangeColorToHsl(this.#pluginManager, strokeColor) ?? particle.getFillColor();
3065
+ if (!strokeHslColor) {
3066
+ return;
3067
+ }
3068
+ particle.strokeColor = getHslAnimationFromHsl(strokeHslColor, particle.strokeAnimation, container.retina.reduceFactor);
3069
+ }
3002
3070
  }
3003
3071
 
3004
3072
  async function loadPaintUpdater(engine) {
3005
- engine.checkVersion("4.4.0");
3073
+ engine.checkVersion("4.5.1");
3006
3074
  await engine.pluginManager.register(e => {
3007
3075
  e.pluginManager.addParticleUpdater("paint", container => {
3008
3076
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3044,7 +3112,7 @@
3044
3112
  if (!this.accepts(input)) {
3045
3113
  return;
3046
3114
  }
3047
- const result = rgbRegex.exec(input), radix = 10, minLength = 4, defaultAlpha = 1;
3115
+ const result = rgbRegex.exec(input), radix = 10, minLength = 4;
3048
3116
  return result
3049
3117
  ? {
3050
3118
  a: result.length > minLength ? parseAlpha(result[RgbIndexes.a]) : defaultAlpha,
@@ -3057,7 +3125,7 @@
3057
3125
  }
3058
3126
 
3059
3127
  async function loadRgbColorPlugin(engine) {
3060
- engine.checkVersion("4.4.0");
3128
+ engine.checkVersion("4.5.1");
3061
3129
  await engine.pluginManager.register(e => {
3062
3130
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3063
3131
  });
@@ -3142,7 +3210,7 @@
3142
3210
  }
3143
3211
 
3144
3212
  async function loadSizeUpdater(engine) {
3145
- engine.checkVersion("4.4.0");
3213
+ engine.checkVersion("4.5.1");
3146
3214
  await engine.pluginManager.register(e => {
3147
3215
  e.pluginManager.addParticleUpdater("size", container => {
3148
3216
  return Promise.resolve(new SizeUpdater(container));
@@ -3151,7 +3219,7 @@
3151
3219
  }
3152
3220
 
3153
3221
  async function loadBasic(engine) {
3154
- engine.checkVersion("4.4.0");
3222
+ engine.checkVersion("4.5.1");
3155
3223
  await engine.pluginManager.register(async (e) => {
3156
3224
  await Promise.all([
3157
3225
  loadBlendPlugin(e),
@@ -3260,6 +3328,8 @@
3260
3328
  autoPlay = true;
3261
3329
  direction;
3262
3330
  domId;
3331
+ draggable = false;
3332
+ draw = false;
3263
3333
  fill = true;
3264
3334
  life = new EmitterLife();
3265
3335
  name;
@@ -3283,6 +3353,8 @@
3283
3353
  }
3284
3354
  loadProperty(this, "direction", data.direction);
3285
3355
  loadProperty(this, "domId", data.domId);
3356
+ loadProperty(this, "draggable", data.draggable);
3357
+ loadProperty(this, "draw", data.draw);
3286
3358
  loadProperty(this, "fill", data.fill);
3287
3359
  this.life.load(data.life);
3288
3360
  loadProperty(this, "name", data.name);
@@ -3344,6 +3416,14 @@
3344
3416
  }
3345
3417
  }
3346
3418
 
3419
+ const ErrorCodes = {
3420
+ emittersPluginNotLoaded: "TSP-3101",
3421
+ };
3422
+
3423
+ const ErrorMessages = {
3424
+ [ErrorCodes.emittersPluginNotLoaded]: "tsParticles Emitters Plugin is not loaded",
3425
+ };
3426
+
3347
3427
  async function addEmittersShapesManager(e) {
3348
3428
  const { ShapeManager } = await Promise.resolve().then(function () { return ShapeManager$1; }), pluginManager = e.pluginManager;
3349
3429
  pluginManager.emitterShapeManager ??= new ShapeManager();
@@ -3379,6 +3459,8 @@
3379
3459
  this.fill = fill;
3380
3460
  this.options = options;
3381
3461
  }
3462
+ draw(_context) {
3463
+ }
3382
3464
  resize(position, size) {
3383
3465
  this.position = position;
3384
3466
  this.size = size;
@@ -3391,7 +3473,10 @@
3391
3473
  })(EmitterClickMode || (EmitterClickMode = {}));
3392
3474
 
3393
3475
  async function loadEmittersPluginSimple(engine) {
3394
- engine.checkVersion("4.4.0");
3476
+ engine.checkVersion("4.5.1");
3477
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
3478
+ addErrorMessages(ErrorMessages);
3479
+ }
3395
3480
  await engine.pluginManager.register(async (e) => {
3396
3481
  const instancesManager = await getEmittersInstancesManager(e);
3397
3482
  await addEmittersShapesManager(e);
@@ -3399,9 +3484,63 @@
3399
3484
  });
3400
3485
  }
3401
3486
 
3487
+ class EmittersPluginInstance {
3488
+ #container;
3489
+ #instancesManager;
3490
+ constructor(instancesManager, container) {
3491
+ this.#instancesManager = instancesManager;
3492
+ this.#container = container;
3493
+ this.#instancesManager.initContainer(container);
3494
+ }
3495
+ draw(context, _delta) {
3496
+ for (const emitter of this.#instancesManager.getArray(this.#container)) {
3497
+ emitter.draw(context);
3498
+ }
3499
+ }
3500
+ async init() {
3501
+ const emittersOptions = this.#container.actualOptions.emitters;
3502
+ if (isArray(emittersOptions)) {
3503
+ for (const emitterOptions of emittersOptions) {
3504
+ await this.#instancesManager.addEmitter(this.#container, emitterOptions);
3505
+ }
3506
+ }
3507
+ else {
3508
+ await this.#instancesManager.addEmitter(this.#container, emittersOptions);
3509
+ }
3510
+ }
3511
+ pause() {
3512
+ for (const emitter of this.#instancesManager.getArray(this.#container)) {
3513
+ emitter.pause();
3514
+ }
3515
+ }
3516
+ play() {
3517
+ for (const emitter of this.#instancesManager.getArray(this.#container)) {
3518
+ emitter.play();
3519
+ }
3520
+ }
3521
+ resize() {
3522
+ for (const emitter of this.#instancesManager.getArray(this.#container)) {
3523
+ emitter.resize();
3524
+ }
3525
+ }
3526
+ stop() {
3527
+ this.#instancesManager.clear(this.#container);
3528
+ }
3529
+ update(delta) {
3530
+ this.#instancesManager.getArray(this.#container).forEach(emitter => {
3531
+ emitter.update(delta);
3532
+ });
3533
+ }
3534
+ }
3535
+
3536
+ var EmittersPluginInstance$1 = /*#__PURE__*/Object.freeze({
3537
+ __proto__: null,
3538
+ EmittersPluginInstance: EmittersPluginInstance
3539
+ });
3540
+
3402
3541
  function ensureEmittersPluginLoaded(e) {
3403
3542
  if (!e.pluginManager.addEmitterShapeGenerator) {
3404
- throw new Error("tsParticles Emitters Plugin is not loaded");
3543
+ throw new Error(getErrorMessage(ErrorCodes.emittersPluginNotLoaded));
3405
3544
  }
3406
3545
  }
3407
3546
 
@@ -3417,12 +3556,16 @@
3417
3556
  return position + offset * (getRandom() - half);
3418
3557
  }
3419
3558
  function getRandomSize(sides) {
3420
- return Math.floor(getRandom() * sides);
3559
+ return toEnumValue(Sides, Math.floor(getRandom() * sides), Sides.BottomLeft);
3421
3560
  }
3422
3561
  class EmittersSquareShape extends EmitterShapeBase {
3423
3562
  constructor(position, size, fill, options) {
3424
3563
  super(position, size, fill, options);
3425
3564
  }
3565
+ draw(context) {
3566
+ const position = this.position, size = this.size, halfW = size.width * half, halfH = size.height * half;
3567
+ context.rect(position.x - halfW, position.y - halfH, size.width, size.height);
3568
+ }
3426
3569
  async init() {
3427
3570
  }
3428
3571
  randomPosition() {
@@ -3479,7 +3622,7 @@
3479
3622
  }
3480
3623
 
3481
3624
  async function loadEmittersShapeSquare(engine) {
3482
- engine.checkVersion("4.4.0");
3625
+ engine.checkVersion("4.5.1");
3483
3626
  await engine.pluginManager.register((e) => {
3484
3627
  ensureEmittersPluginLoaded(e);
3485
3628
  e.pluginManager.addEmitterShapeGenerator?.("square", new EmittersSquareShapeGenerator());
@@ -3561,7 +3704,7 @@
3561
3704
  particle.destroy();
3562
3705
  return;
3563
3706
  }
3564
- const widthRange = setRangeValue(minCanvasSize, canvasSize.width), heightRange = setRangeValue(minCanvasSize, canvasSize.width);
3707
+ const widthRange = setRangeValue(minCanvasSize, canvasSize.width), heightRange = setRangeValue(minCanvasSize, canvasSize.height);
3565
3708
  particle.position.x = randomInRangeValue(widthRange);
3566
3709
  particle.position.y = randomInRangeValue(heightRange);
3567
3710
  particle.spawning = true;
@@ -3623,7 +3766,7 @@
3623
3766
  }
3624
3767
 
3625
3768
  async function loadLifeUpdater(engine) {
3626
- engine.checkVersion("4.4.0");
3769
+ engine.checkVersion("4.5.1");
3627
3770
  await engine.pluginManager.register(e => {
3628
3771
  e.pluginManager.addParticleUpdater("life", container => {
3629
3772
  return Promise.resolve(new LifeUpdater(container));
@@ -3687,7 +3830,7 @@
3687
3830
  }
3688
3831
 
3689
3832
  async function loadTrailPlugin(engine) {
3690
- engine.checkVersion("4.4.0");
3833
+ engine.checkVersion("4.5.1");
3691
3834
  await engine.pluginManager.register(e => {
3692
3835
  e.pluginManager.addPlugin(new TrailPlugin(e.pluginManager));
3693
3836
  });
@@ -3839,21 +3982,28 @@
3839
3982
  });
3840
3983
  }
3841
3984
  clear() {
3985
+ const visited = new Set();
3842
3986
  for (const plugin of this.#canvasClearPlugins) {
3987
+ visited.add(plugin);
3843
3988
  if (plugin.canvasClear?.() ?? false) {
3844
- return;
3989
+ return plugin;
3845
3990
  }
3846
3991
  }
3847
3992
  for (const layer of Object.values(DrawLayer)) {
3848
3993
  if (typeof layer === "number") {
3849
3994
  for (const plugin of this.#getLayerPlugins(layer)) {
3995
+ if (visited.has(plugin)) {
3996
+ continue;
3997
+ }
3998
+ visited.add(plugin);
3850
3999
  if (plugin.canvasClear?.() ?? false) {
3851
- return;
4000
+ return plugin;
3852
4001
  }
3853
4002
  }
3854
4003
  }
3855
4004
  }
3856
4005
  this.canvasClear();
4006
+ return undefined;
3857
4007
  }
3858
4008
  destroy() {
3859
4009
  this.stop();
@@ -3931,8 +4081,7 @@
3931
4081
  });
3932
4082
  }
3933
4083
  drawParticles(delta) {
3934
- const { particles, actualOptions } = this.#container;
3935
- this.clear();
4084
+ const { particles, actualOptions } = this.#container, clearedPlugin = this.clear();
3936
4085
  particles.update(delta);
3937
4086
  this.draw(ctx => {
3938
4087
  const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
@@ -3954,7 +4103,9 @@
3954
4103
  }
3955
4104
  }
3956
4105
  for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
3957
- plugin.canvasPaint?.();
4106
+ if (plugin !== clearedPlugin) {
4107
+ plugin.canvasPaint?.();
4108
+ }
3958
4109
  }
3959
4110
  for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasSetup)) {
3960
4111
  plugin.drawSettingsSetup?.(ctx, delta);
@@ -3986,35 +4137,7 @@
3986
4137
  this.#layers[layer] = [];
3987
4138
  }
3988
4139
  }
3989
- for (const plugin of this.#container.plugins) {
3990
- if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
3991
- this.#colorPlugins.push(plugin);
3992
- }
3993
- if (plugin.drawParticle) {
3994
- this.#drawParticlePlugins.push(plugin);
3995
- }
3996
- if (plugin.drawParticleSetup) {
3997
- this.#drawParticlesSetupPlugins.push(plugin);
3998
- }
3999
- if (plugin.drawParticleCleanup) {
4000
- this.#drawParticlesCleanupPlugins.push(plugin);
4001
- }
4002
- if (plugin.canvasClear) {
4003
- this.#canvasClearPlugins.push(plugin);
4004
- }
4005
- if (plugin.canvasPaint) {
4006
- this.#getLayerPlugins(DrawLayer.BackgroundMask).push(plugin);
4007
- }
4008
- if (plugin.drawSettingsSetup) {
4009
- this.#getLayerPlugins(DrawLayer.CanvasSetup).push(plugin);
4010
- }
4011
- if (plugin.draw) {
4012
- this.#getLayerPlugins(DrawLayer.PluginContent).push(plugin);
4013
- }
4014
- if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
4015
- this.#getLayerPlugins(DrawLayer.CanvasCleanup).push(plugin);
4016
- }
4017
- }
4140
+ this.#initPluginsArray();
4018
4141
  }
4019
4142
  initUpdaters() {
4020
4143
  this.#preDrawUpdaters = [];
@@ -4223,6 +4346,45 @@
4223
4346
  this.#reusablePluginColors[sColorIndex] = sColor;
4224
4347
  return this.#reusablePluginColors;
4225
4348
  }
4349
+ #initLayerPlugin(plugin) {
4350
+ const layerMap = [
4351
+ [DrawLayer.BackgroundMask, !!plugin.canvasPaint],
4352
+ [DrawLayer.CanvasSetup, !!plugin.drawSettingsSetup],
4353
+ [DrawLayer.PluginContent, !!plugin.draw],
4354
+ [DrawLayer.CanvasCleanup, !!(plugin.clearDraw ?? plugin.drawSettingsCleanup)],
4355
+ ];
4356
+ for (const [layer, active] of layerMap) {
4357
+ if (active) {
4358
+ this.#layers[layer].push(plugin);
4359
+ }
4360
+ }
4361
+ }
4362
+ #initPluginsArray() {
4363
+ for (const plugin of this.#container.plugins) {
4364
+ if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
4365
+ this.#colorPlugins.push(plugin);
4366
+ }
4367
+ if (plugin.drawParticle) {
4368
+ this.#drawParticlePlugins.push(plugin);
4369
+ }
4370
+ if (plugin.drawParticleSetup) {
4371
+ this.#drawParticlesSetupPlugins.push(plugin);
4372
+ }
4373
+ if (plugin.drawParticleCleanup) {
4374
+ this.#drawParticlesCleanupPlugins.push(plugin);
4375
+ }
4376
+ if (plugin.canvasClear) {
4377
+ this.#canvasClearPlugins.push(plugin);
4378
+ }
4379
+ this.#initLayerPlugin(plugin);
4380
+ }
4381
+ }
4382
+ #isSupportedElement(element) {
4383
+ return ((typeof HTMLCanvasElement !== "undefined" && element instanceof HTMLCanvasElement) ||
4384
+ (typeof OffscreenCanvas !== "undefined" && element instanceof OffscreenCanvas) ||
4385
+ (typeof HTMLVideoElement !== "undefined" && element instanceof HTMLVideoElement) ||
4386
+ (typeof HTMLImageElement !== "undefined" && element instanceof HTMLImageElement));
4387
+ }
4226
4388
  #resolveBackgroundElement() {
4227
4389
  const background = this.#container.actualOptions.background;
4228
4390
  this.#backgroundElement = null;
@@ -4232,9 +4394,7 @@
4232
4394
  if (typeof background.element === "string") {
4233
4395
  if (typeof document !== "undefined") {
4234
4396
  const node = document.querySelector(background.element);
4235
- if ((typeof HTMLCanvasElement !== "undefined" && node instanceof HTMLCanvasElement) ||
4236
- (typeof HTMLVideoElement !== "undefined" && node instanceof HTMLVideoElement) ||
4237
- (typeof HTMLImageElement !== "undefined" && node instanceof HTMLImageElement)) {
4397
+ if (node && this.#isSupportedElement(node)) {
4238
4398
  this.#backgroundElement = node;
4239
4399
  }
4240
4400
  else if (node) {
@@ -4245,10 +4405,7 @@
4245
4405
  }
4246
4406
  }
4247
4407
  }
4248
- else if ((typeof HTMLCanvasElement !== "undefined" && background.element instanceof HTMLCanvasElement) ||
4249
- (typeof OffscreenCanvas !== "undefined" && background.element instanceof OffscreenCanvas) ||
4250
- (typeof HTMLVideoElement !== "undefined" && background.element instanceof HTMLVideoElement) ||
4251
- (typeof HTMLImageElement !== "undefined" && background.element instanceof HTMLImageElement)) {
4408
+ else if (this.#isSupportedElement(background.element)) {
4252
4409
  this.#backgroundElement = background.element;
4253
4410
  }
4254
4411
  }
@@ -4266,7 +4423,7 @@
4266
4423
  return transferredCanvas;
4267
4424
  }
4268
4425
  if (typeof canvas.transferControlToOffscreen !== "function") {
4269
- throw new TypeError("OffscreenCanvas is required but not supported by this browser");
4426
+ throw new TypeError(getErrorMessage(ErrorCodes$2.offscreenCanvasUnsupported));
4270
4427
  }
4271
4428
  try {
4272
4429
  const offscreenCanvas = canvas.transferControlToOffscreen();
@@ -4274,10 +4431,16 @@
4274
4431
  return offscreenCanvas;
4275
4432
  }
4276
4433
  catch {
4277
- throw new TypeError("OffscreenCanvas transfer failed");
4434
+ throw new TypeError(getErrorMessage(ErrorCodes$2.offscreenCanvasTransferFailed));
4278
4435
  }
4279
4436
  }, isHtmlCanvasElement = (canvas) => {
4280
4437
  return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
4438
+ }, getEffectiveColorSpace = (context) => {
4439
+ if (!context) {
4440
+ return undefined;
4441
+ }
4442
+ const colorInfo = context;
4443
+ return colorInfo.getContextAttributes?.().colorSpace ?? undefined;
4281
4444
  };
4282
4445
  function setStyle(canvas, style, important = false) {
4283
4446
  if (!style) {
@@ -4402,7 +4565,7 @@
4402
4565
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
4403
4566
  if (color) {
4404
4567
  const hdrOptions = container.actualOptions.hdr;
4405
- elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, hdrOptions.mode);
4568
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, toEnumValue(HdrMode, hdrOptions.mode, HdrMode.standard));
4406
4569
  }
4407
4570
  else {
4408
4571
  elementStyle.backgroundColor = "";
@@ -4522,11 +4685,11 @@
4522
4685
  const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
4523
4686
  safeMatchMedia("(color-gamut: p3)")?.matches &&
4524
4687
  safeMatchMedia("(dynamic-range: high)")?.matches;
4525
- container.hdr = canSupportHdr ?? false;
4526
- container.hdrMode = container.actualOptions.hdr.mode;
4688
+ container.hdrMode = toEnumValue(HdrMode, container.actualOptions.hdr.mode, HdrMode.standard);
4527
4689
  container.peakNits = container.actualOptions.hdr.peakNits;
4528
4690
  const renderCanvas = this.renderCanvas;
4529
4691
  if (!renderCanvas) {
4692
+ container.hdr = canSupportHdr ?? false;
4530
4693
  return;
4531
4694
  }
4532
4695
  this.render.setContextSettings({
@@ -4545,7 +4708,6 @@
4545
4708
  context = null;
4546
4709
  }
4547
4710
  if (canSupportHdr && !context) {
4548
- container.hdr = false;
4549
4711
  const sdrSettings = {
4550
4712
  alpha: true,
4551
4713
  desynchronized: true,
@@ -4561,11 +4723,16 @@
4561
4723
  }
4562
4724
  }
4563
4725
  this.render.setContext(context);
4726
+ if (context) {
4727
+ const effectiveColorSpace = getEffectiveColorSpace(context);
4728
+ if (effectiveColorSpace !== undefined) {
4729
+ container.hdr = effectiveColorSpace === "display-p3";
4730
+ }
4731
+ }
4564
4732
  }
4565
4733
  #initHdrListeners() {
4566
4734
  this.#removeHdrListeners();
4567
4735
  const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
4568
- this.#recreateRenderCanvas();
4569
4736
  this.#initContext();
4570
4737
  this.initBackground();
4571
4738
  }, listeners = [];
@@ -4601,16 +4768,6 @@
4601
4768
  element.style.setProperty(key, value, "important");
4602
4769
  }
4603
4770
  }
4604
- #recreateRenderCanvas() {
4605
- const renderCanvas = this.renderCanvas;
4606
- if (!renderCanvas) {
4607
- return;
4608
- }
4609
- if (this.domElement) {
4610
- return;
4611
- }
4612
- this.renderCanvas = new OffscreenCanvas(renderCanvas.width, renderCanvas.height);
4613
- }
4614
4771
  #removeHdrListeners() {
4615
4772
  if (!this.#hdrMediaListeners) {
4616
4773
  return;
@@ -4682,6 +4839,10 @@
4682
4839
  this.#manageListeners(true);
4683
4840
  }
4684
4841
  removeListeners() {
4842
+ if (this.#resizeTimeout !== undefined) {
4843
+ clearTimeout(this.#resizeTimeout);
4844
+ this.#resizeTimeout = undefined;
4845
+ }
4685
4846
  this.#manageListeners(false);
4686
4847
  }
4687
4848
  #handleVisibilityChange() {
@@ -4709,8 +4870,7 @@
4709
4870
  this.#resizeTimeout = undefined;
4710
4871
  }
4711
4872
  const handleResize = async () => {
4712
- const canvas = this.#container.canvas;
4713
- await canvas.windowResize();
4873
+ await this.#container.canvas.windowResize();
4714
4874
  };
4715
4875
  this.#resizeTimeout = setTimeout(() => void handleResize(), this.#container.actualOptions.resize.delay * millisecondsToSeconds);
4716
4876
  }
@@ -4738,8 +4898,8 @@
4738
4898
  }
4739
4899
  else if (!this.#resizeObserver && add && canvasEl) {
4740
4900
  this.#resizeObserver = new ResizeObserver((entries) => {
4741
- const entry = entries.find(e => e.target === canvasEl);
4742
- if (!entry) {
4901
+ const res = entries.some(e => e.target === canvasEl);
4902
+ if (!res) {
4743
4903
  return;
4744
4904
  }
4745
4905
  this.#handleWindowResize();
@@ -5003,10 +5163,10 @@
5003
5163
  return this.#modifiers.find(m => m.id === id);
5004
5164
  }
5005
5165
  getOpacity() {
5006
- const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, baseOpacity = getRangeValue(this.opacity?.value ?? defaultOpacity$1), modifierOpacity = this.#applyModifiers(undefined, m => m.opacity), opacity = modifierOpacity ?? baseOpacity, fillOpacity = this.fillOpacity ?? defaultOpacity$1, strokeOpacity = this.strokeOpacity ?? defaultOpacity$1;
5007
- this.#cachedOpacityData.fillOpacity = fillOpacity;
5166
+ const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, baseOpacity = getRangeValue(this.opacity?.value ?? defaultOpacity$1), modifierOpacity = this.#applyModifiers(undefined, m => m.opacity), opacity = modifierOpacity ?? baseOpacity;
5167
+ this.#cachedOpacityData.fillOpacity = this.fillOpacity ?? defaultOpacity$1;
5008
5168
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
5009
- this.#cachedOpacityData.strokeOpacity = strokeOpacity;
5169
+ this.#cachedOpacityData.strokeOpacity = this.strokeOpacity ?? defaultOpacity$1;
5010
5170
  return this.#cachedOpacityData;
5011
5171
  }
5012
5172
  getPosition() {
@@ -5253,7 +5413,7 @@
5253
5413
  #initPosition(position) {
5254
5414
  const container = this.#container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this.#calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
5255
5415
  if (!initialPosition) {
5256
- throw new Error("a valid position cannot be found for particle");
5416
+ throw new Error(getErrorMessage(ErrorCodes$2.particlePositionNotFound));
5257
5417
  }
5258
5418
  this.position = initialPosition;
5259
5419
  this.initialPosition = this.position.copy();
@@ -5302,6 +5462,12 @@
5302
5462
  this.#circlePoolIdx = 0;
5303
5463
  this.#rectanglePoolIdx = 0;
5304
5464
  }
5465
+ get cellSize() {
5466
+ return this.#cellSize;
5467
+ }
5468
+ set cellSize(value) {
5469
+ this.#pendingCellSize = value;
5470
+ }
5305
5471
  clear() {
5306
5472
  this.#cells.clear();
5307
5473
  const pendingCellSize = this.#pendingCellSize;
@@ -5325,40 +5491,46 @@
5325
5491
  const minCellX = Math.floor(bounds.minX / this.#cellSize), maxCellX = Math.floor(bounds.maxX / this.#cellSize), minCellY = Math.floor(bounds.minY / this.#cellSize), maxCellY = Math.floor(bounds.maxY / this.#cellSize);
5326
5492
  for (let cx = minCellX; cx <= maxCellX; cx++) {
5327
5493
  for (let cy = minCellY; cy <= maxCellY; cy++) {
5328
- const key = `${cx}_${cy}`, cellParticles = this.#cells.get(key);
5329
- if (!cellParticles) {
5330
- continue;
5331
- }
5332
- for (const p of cellParticles) {
5333
- if (check && !check(p)) {
5334
- continue;
5335
- }
5336
- if (range.contains(p.getPosition())) {
5337
- out.push(p);
5338
- }
5339
- }
5494
+ this.#queryCell(cx, cy, range, check, out);
5340
5495
  }
5341
5496
  }
5342
5497
  return out;
5343
5498
  }
5344
5499
  queryCircle(position, radius, check, out = []) {
5345
- const circle = this.#acquireCircle(position.x, position.y, radius), result = this.query(circle, check, out);
5346
- this.#releaseShapes();
5347
- return result;
5500
+ const circle = this.#acquireCircle(position.x, position.y, radius);
5501
+ try {
5502
+ return this.query(circle, check, out);
5503
+ }
5504
+ finally {
5505
+ this.#circlePoolIdx--;
5506
+ }
5348
5507
  }
5349
5508
  queryRectangle(position, size, check, out = []) {
5350
- const rect = this.#acquireRectangle(position.x, position.y, size.width, size.height), result = this.query(rect, check, out);
5351
- this.#releaseShapes();
5352
- return result;
5353
- }
5354
- setCellSize(cellSize) {
5355
- this.#pendingCellSize = cellSize;
5509
+ const rect = this.#acquireRectangle(position.x, position.y, size.width, size.height);
5510
+ try {
5511
+ return this.query(rect, check, out);
5512
+ }
5513
+ finally {
5514
+ this.#rectanglePoolIdx--;
5515
+ }
5356
5516
  }
5357
5517
  #acquireCircle(x, y, r) {
5358
- return (this.#circlePool[this.#circlePoolIdx++] ??= new Circle(x, y, r)).reset(x, y, r);
5518
+ const idx = this.#circlePoolIdx++;
5519
+ let circle = this.#circlePool[idx];
5520
+ if (!circle) {
5521
+ circle = new Circle(x, y, r);
5522
+ this.#circlePool[idx] = circle;
5523
+ }
5524
+ return circle.reset(x, y, r);
5359
5525
  }
5360
5526
  #acquireRectangle(x, y, w, h) {
5361
- return (this.#rectanglePool[this.#rectanglePoolIdx++] ??= new Rectangle(x, y, w, h)).reset(x, y, w, h);
5527
+ const idx = this.#rectanglePoolIdx++;
5528
+ let rectangle = this.#rectanglePool[idx];
5529
+ if (!rectangle) {
5530
+ rectangle = new Rectangle(x, y, w, h);
5531
+ this.#rectanglePool[idx] = rectangle;
5532
+ }
5533
+ return rectangle.reset(x, y, w, h);
5362
5534
  }
5363
5535
  #cellKeyFromCoords(x, y) {
5364
5536
  const cellX = Math.floor(x / this.#cellSize), cellY = Math.floor(y / this.#cellSize);
@@ -5385,17 +5557,27 @@
5385
5557
  }
5386
5558
  return null;
5387
5559
  }
5388
- #releaseShapes() {
5389
- this.#circlePoolIdx = 0;
5390
- this.#rectanglePoolIdx = 0;
5560
+ #queryCell(cx, cy, range, check, out) {
5561
+ const cellParticles = this.#cells.get(`${cx}_${cy}`);
5562
+ if (!cellParticles) {
5563
+ return;
5564
+ }
5565
+ for (const p of cellParticles) {
5566
+ if (check && !check(p)) {
5567
+ continue;
5568
+ }
5569
+ if (range.contains(p.getPosition())) {
5570
+ out.push(p);
5571
+ }
5572
+ }
5391
5573
  }
5392
5574
  }
5393
5575
 
5394
5576
  class ParticlesManager {
5395
5577
  checkParticlePositionPlugins;
5396
- grid;
5397
5578
  #array;
5398
5579
  #container;
5580
+ #grid;
5399
5581
  #groupLimits;
5400
5582
  #limit;
5401
5583
  #nextId;
@@ -5419,7 +5601,7 @@
5419
5601
  this.#groupLimits = new Map();
5420
5602
  this.#particleBuckets = new Map();
5421
5603
  this.#zBuckets = this.#createBuckets(this.#container.zLayers);
5422
- this.grid = new SpatialHashGrid(spatialHashGridCellSize);
5604
+ this.#grid = new SpatialHashGrid(spatialHashGridCellSize);
5423
5605
  this.checkParticlePositionPlugins = [];
5424
5606
  this.#particleResetPlugins = [];
5425
5607
  this.#particleUpdatePlugins = [];
@@ -5430,23 +5612,12 @@
5430
5612
  get count() {
5431
5613
  return this.#array.length;
5432
5614
  }
5615
+ get grid() {
5616
+ return this.#grid;
5617
+ }
5433
5618
  addParticle(position, overrideOptions, group, initializer) {
5434
- const limitMode = this.#container.actualOptions.particles.number.limit.mode, limit = group === undefined ? this.#limit : (this.#groupLimits.get(group) ?? this.#limit), currentCount = this.count;
5435
- if (limit > minLimit) {
5436
- switch (limitMode) {
5437
- case LimitMode.delete: {
5438
- const countToRemove = currentCount + countOffset - limit;
5439
- if (countToRemove > minCount) {
5440
- this.removeQuantity(countToRemove);
5441
- }
5442
- break;
5443
- }
5444
- case LimitMode.wait:
5445
- if (currentCount >= limit) {
5446
- return;
5447
- }
5448
- break;
5449
- }
5619
+ if (this.#checkAndApplyLimits(group, this.count)) {
5620
+ return;
5450
5621
  }
5451
5622
  try {
5452
5623
  const particle = this.#pool.pop() ?? new Particle(this.#pluginManager, this.#container);
@@ -5510,7 +5681,7 @@
5510
5681
  return this.#array[index];
5511
5682
  }
5512
5683
  async init() {
5513
- const container = this.#container, options = container.actualOptions;
5684
+ const container = this.#container;
5514
5685
  this.checkParticlePositionPlugins = [];
5515
5686
  this.#updatePlugins = [];
5516
5687
  this.#particleUpdatePlugins = [];
@@ -5519,59 +5690,16 @@
5519
5690
  this.#postParticleUpdatePlugins = [];
5520
5691
  this.#particleBuckets.clear();
5521
5692
  this.#resetBuckets(container.zLayers);
5522
- this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
5523
- for (const plugin of container.plugins) {
5524
- if (plugin.redrawInit) {
5525
- await plugin.redrawInit();
5526
- }
5527
- if (plugin.checkParticlePosition) {
5528
- this.checkParticlePositionPlugins.push(plugin);
5529
- }
5530
- if (plugin.update) {
5531
- this.#updatePlugins.push(plugin);
5532
- }
5533
- if (plugin.particleUpdate) {
5534
- this.#particleUpdatePlugins.push(plugin);
5535
- }
5536
- if (plugin.postUpdate) {
5537
- this.#postUpdatePlugins.push(plugin);
5538
- }
5539
- if (plugin.particleReset) {
5540
- this.#particleResetPlugins.push(plugin);
5541
- }
5542
- if (plugin.postParticleUpdate) {
5543
- this.#postParticleUpdatePlugins.push(plugin);
5544
- }
5545
- }
5546
- await this.#container.initDrawersAndUpdaters();
5547
- for (const drawer of this.#container.effectDrawers.values()) {
5548
- await drawer.init?.(container);
5549
- }
5550
- for (const drawer of this.#container.shapeDrawers.values()) {
5551
- await drawer.init?.(container);
5552
- }
5553
- let handled = false;
5554
- for (const plugin of container.plugins) {
5555
- handled = plugin.particlesInitialization?.() ?? handled;
5556
- if (handled) {
5557
- break;
5558
- }
5559
- }
5560
- if (!handled) {
5561
- const particlesOptions = options.particles, groups = particlesOptions.groups;
5562
- for (const group in groups) {
5563
- const groupOptions = groups[group];
5564
- if (!groupOptions) {
5565
- continue;
5566
- }
5567
- for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
5568
- this.addParticle(undefined, groupOptions, group);
5569
- }
5570
- }
5571
- for (let i = this.count; i < particlesOptions.number.value; i++) {
5572
- this.addParticle();
5693
+ this.#grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
5694
+ this.#applyLimits(container.actualOptions.particles);
5695
+ const particlesOptions = container.actualOptions.particles, groups = particlesOptions.groups;
5696
+ for (const group in groups) {
5697
+ const groupData = groups[group];
5698
+ if (groupData) {
5699
+ this.#applyLimits(loadParticlesOptions(this.#pluginManager, this.#container, groupData), group, groupData);
5573
5700
  }
5574
5701
  }
5702
+ await this.#initPlugins();
5575
5703
  }
5576
5704
  push(nb, position, overrideOptions, group) {
5577
5705
  for (let i = 0; i < nb; i++) {
@@ -5586,13 +5714,13 @@
5586
5714
  remove(particle, group, override) {
5587
5715
  this.removeAt(this.#array.indexOf(particle), undefined, group, override);
5588
5716
  }
5589
- removeAt(index, quantity = defaultRemoveQuantity, group, override) {
5717
+ removeAt(index, quantity = defaultRemoveQuantity, group, override, matchGroup = true) {
5590
5718
  if (index < minIndex || index > this.count) {
5591
5719
  return;
5592
5720
  }
5593
5721
  let deleted = 0;
5594
5722
  for (let i = index; deleted < quantity && i < this.count; i++) {
5595
- if (this.#removeParticle(i, group, override)) {
5723
+ if (this.#removeParticle(i, group, override, matchGroup)) {
5596
5724
  i--;
5597
5725
  deleted++;
5598
5726
  }
@@ -5623,7 +5751,7 @@
5623
5751
  this.#resizeFactor = factor;
5624
5752
  }
5625
5753
  update(delta) {
5626
- this.grid.clear();
5754
+ this.#grid.clear();
5627
5755
  for (const plugin of this.#updatePlugins) {
5628
5756
  plugin.update?.(delta);
5629
5757
  }
@@ -5634,7 +5762,7 @@
5634
5762
  this.#updateParticlesPhase2(delta, particlesToDelete);
5635
5763
  if (particlesToDelete.size) {
5636
5764
  for (const particle of particlesToDelete) {
5637
- this.remove(particle);
5765
+ this.remove(particle, particle.group);
5638
5766
  }
5639
5767
  }
5640
5768
  this.#resizeFactor = undefined;
@@ -5645,12 +5773,7 @@
5645
5773
  #applyDensity(options, pluginsCount, group, groupOptions) {
5646
5774
  const numberOptions = options.number;
5647
5775
  if (!numberOptions.density.enable) {
5648
- if (group === undefined) {
5649
- this.#limit = numberOptions.limit.value;
5650
- }
5651
- else if (groupOptions?.number.limit.value ?? numberOptions.limit.value) {
5652
- this.#groupLimits.set(group, groupOptions?.number.limit.value ?? numberOptions.limit.value);
5653
- }
5776
+ this.#applyLimits(options, group, groupOptions);
5654
5777
  return;
5655
5778
  }
5656
5779
  const densityFactor = this.#initDensityFactor(numberOptions.density), optParticlesNumber = numberOptions.value, optParticlesLimit = numberOptions.limit.value > minLimit ? numberOptions.limit.value : optParticlesNumber, particlesNumber = Math.min(optParticlesNumber, optParticlesLimit) * densityFactor + pluginsCount, particlesCount = Math.min(this.count, this.filter(t => t.group === group).length);
@@ -5658,7 +5781,10 @@
5658
5781
  this.#limit = numberOptions.limit.value * densityFactor;
5659
5782
  }
5660
5783
  else {
5661
- this.#groupLimits.set(group, numberOptions.limit.value * densityFactor);
5784
+ this.#groupLimits.set(group, {
5785
+ limit: numberOptions.limit.value * densityFactor,
5786
+ mode: toEnumValue(LimitMode, numberOptions.limit.mode, LimitMode.delete),
5787
+ });
5662
5788
  }
5663
5789
  if (particlesCount < particlesNumber) {
5664
5790
  this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
@@ -5667,6 +5793,55 @@
5667
5793
  this.removeQuantity(particlesCount - particlesNumber, group);
5668
5794
  }
5669
5795
  }
5796
+ #applyLimits(options, group, groupOptions) {
5797
+ if (group === undefined) {
5798
+ this.#limit = options.number.limit.value;
5799
+ const groups = this.#container.actualOptions.particles.groups;
5800
+ for (const existingGroup of this.#groupLimits.keys()) {
5801
+ if (!(existingGroup in groups)) {
5802
+ this.#groupLimits.delete(existingGroup);
5803
+ }
5804
+ }
5805
+ }
5806
+ else {
5807
+ const limitValue = groupOptions?.number?.limit?.value ?? options.number.limit.value;
5808
+ if (limitValue > minLimit) {
5809
+ this.#groupLimits.set(group, {
5810
+ limit: limitValue,
5811
+ mode: toEnumValue(LimitMode, groupOptions?.number?.limit?.mode ?? options.number.limit.mode, LimitMode.delete),
5812
+ });
5813
+ }
5814
+ else {
5815
+ this.#groupLimits.delete(group);
5816
+ }
5817
+ }
5818
+ }
5819
+ #checkAndApplyLimits(group, currentCount) {
5820
+ const globalLimit = this.#limit, globalMode = this.#container.actualOptions.particles.number.limit.mode;
5821
+ if (globalLimit > minLimit && globalMode === LimitMode.wait && currentCount >= globalLimit) {
5822
+ return true;
5823
+ }
5824
+ const groupLimitEntry = group === undefined ? undefined : this.#groupLimits.get(group);
5825
+ if (groupLimitEntry && groupLimitEntry.limit > minLimit && groupLimitEntry.mode === LimitMode.wait) {
5826
+ const groupCount = this.filter(t => t.group === group).length;
5827
+ if (groupCount >= groupLimitEntry.limit) {
5828
+ return true;
5829
+ }
5830
+ }
5831
+ if (groupLimitEntry && groupLimitEntry.limit > minLimit && groupLimitEntry.mode === LimitMode.delete) {
5832
+ const groupCountToRemove = this.filter(t => t.group === group).length + countOffset - groupLimitEntry.limit;
5833
+ if (groupCountToRemove > minCount) {
5834
+ this.removeQuantity(groupCountToRemove, group);
5835
+ }
5836
+ }
5837
+ if (globalLimit > minLimit && globalMode === LimitMode.delete) {
5838
+ const globalCountToRemove = this.count + countOffset - globalLimit;
5839
+ if (globalCountToRemove > minCount) {
5840
+ this.#removeAny(globalCountToRemove);
5841
+ }
5842
+ }
5843
+ return false;
5844
+ }
5670
5845
  #createBuckets(zLayers) {
5671
5846
  const bucketCount = Math.max(Math.floor(zLayers), one);
5672
5847
  return Array.from({ length: bucketCount }, () => []);
@@ -5689,6 +5864,70 @@
5689
5864
  }
5690
5865
  return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
5691
5866
  }
5867
+ async #initDrawersAndUpdaters() {
5868
+ const container = this.#container;
5869
+ await container.initDrawersAndUpdaters();
5870
+ for (const drawer of container.effectDrawers.values()) {
5871
+ await drawer.init?.(container);
5872
+ }
5873
+ for (const drawer of container.shapeDrawers.values()) {
5874
+ await drawer.init?.(container);
5875
+ }
5876
+ }
5877
+ async #initPlugins() {
5878
+ await this.#initPluginsArrays();
5879
+ await this.#initDrawersAndUpdaters();
5880
+ let handled = false;
5881
+ const container = this.#container;
5882
+ for (const plugin of container.plugins) {
5883
+ handled = plugin.particlesInitialization?.() ?? handled;
5884
+ if (handled) {
5885
+ break;
5886
+ }
5887
+ }
5888
+ if (handled) {
5889
+ return;
5890
+ }
5891
+ const particlesOptions = container.actualOptions.particles, groups = particlesOptions.groups;
5892
+ for (const group in groups) {
5893
+ const groupOptions = groups[group];
5894
+ if (!groupOptions) {
5895
+ continue;
5896
+ }
5897
+ for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
5898
+ this.addParticle(undefined, groupOptions, group);
5899
+ }
5900
+ }
5901
+ for (let i = this.count; i < particlesOptions.number.value; i++) {
5902
+ this.addParticle();
5903
+ }
5904
+ }
5905
+ async #initPluginsArrays() {
5906
+ const container = this.#container;
5907
+ for (const plugin of container.plugins) {
5908
+ if (plugin.redrawInit) {
5909
+ await plugin.redrawInit();
5910
+ }
5911
+ if (plugin.checkParticlePosition) {
5912
+ this.checkParticlePositionPlugins.push(plugin);
5913
+ }
5914
+ if (plugin.update) {
5915
+ this.#updatePlugins.push(plugin);
5916
+ }
5917
+ if (plugin.particleUpdate) {
5918
+ this.#particleUpdatePlugins.push(plugin);
5919
+ }
5920
+ if (plugin.postUpdate) {
5921
+ this.#postUpdatePlugins.push(plugin);
5922
+ }
5923
+ if (plugin.particleReset) {
5924
+ this.#particleResetPlugins.push(plugin);
5925
+ }
5926
+ if (plugin.postParticleUpdate) {
5927
+ this.#postParticleUpdatePlugins.push(plugin);
5928
+ }
5929
+ }
5930
+ }
5692
5931
  #insertParticleIntoBucket(particle) {
5693
5932
  const bucketIndex = this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
5694
5933
  if (!bucket) {
@@ -5697,12 +5936,15 @@
5697
5936
  bucket.push(particle);
5698
5937
  this.#particleBuckets.set(particle.id, bucketIndex);
5699
5938
  }
5700
- #removeParticle(index, group, override) {
5939
+ #removeAny(quantity) {
5940
+ this.removeAt(minIndex, quantity, undefined, undefined, false);
5941
+ }
5942
+ #removeParticle(index, group, override, matchGroup = true) {
5701
5943
  const particle = this.#array[index];
5702
5944
  if (!particle) {
5703
5945
  return false;
5704
5946
  }
5705
- if (particle.group !== group) {
5947
+ if (matchGroup && particle.group !== group) {
5706
5948
  return false;
5707
5949
  }
5708
5950
  this.#array.splice(index, deleteCount);
@@ -5789,7 +6031,7 @@
5789
6031
  particlesToDelete.add(particle);
5790
6032
  continue;
5791
6033
  }
5792
- this.grid.insert(particle);
6034
+ this.#grid.insert(particle);
5793
6035
  }
5794
6036
  return particlesToDelete;
5795
6037
  }
@@ -5876,6 +6118,7 @@
5876
6118
  started;
5877
6119
  zLayers;
5878
6120
  #delay;
6121
+ #delayResolve;
5879
6122
  #delayTimeout;
5880
6123
  #delta = { value: 0, factor: 0 };
5881
6124
  #dispatchCallback;
@@ -5965,7 +6208,6 @@
5965
6208
  this.shapeDrawers = new Map();
5966
6209
  this.particleUpdaters = [];
5967
6210
  this.plugins.length = 0;
5968
- this.#pluginManager.clearPlugins(this);
5969
6211
  this.destroyed = true;
5970
6212
  this.#onDestroy(remove);
5971
6213
  this.dispatchEvent(EventType.containerDestroyed);
@@ -6018,31 +6260,14 @@
6018
6260
  await this.initDrawersAndUpdaters();
6019
6261
  this.#options = loadContainerOptions(this.#pluginManager, this, this.#initialSourceOptions, this.sourceOptions);
6020
6262
  this.actualOptions = loadContainerOptions(this.#pluginManager, this, this.#options);
6021
- this.plugins.length = 0;
6022
- this.particleDestroyedPlugins.length = 0;
6023
- this.particleCreatedPlugins.length = 0;
6024
- this.particlePositionPlugins.length = 0;
6025
- for (const [plugin, containerPlugin] of allContainerPlugins) {
6026
- if (plugin.needsPlugin(this.actualOptions)) {
6027
- this.plugins.push(containerPlugin);
6028
- if (containerPlugin.particleCreated) {
6029
- this.particleCreatedPlugins.push(containerPlugin);
6030
- }
6031
- if (containerPlugin.particleDestroyed) {
6032
- this.particleDestroyedPlugins.push(containerPlugin);
6033
- }
6034
- if (containerPlugin.particlePosition) {
6035
- this.particlePositionPlugins.push(containerPlugin);
6036
- }
6037
- }
6038
- }
6263
+ this.#initPlugins(allContainerPlugins);
6039
6264
  this.retina.init();
6040
6265
  this.canvas.init();
6041
6266
  this.updateActualOptions();
6042
6267
  this.canvas.initBackground();
6043
6268
  this.canvas.resize();
6044
6269
  const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
6045
- this.hdrMode = hdrOptions.mode;
6270
+ this.hdrMode = toEnumValue(HdrMode, hdrOptions.mode, HdrMode.standard);
6046
6271
  this.peakNits = hdrOptions.peakNits;
6047
6272
  this.zLayers = zLayers;
6048
6273
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
@@ -6063,9 +6288,9 @@
6063
6288
  }
6064
6289
  async initDrawersAndUpdaters() {
6065
6290
  const pluginManager = this.#pluginManager;
6066
- this.effectDrawers = await pluginManager.getEffectDrawers(this, true);
6067
- this.shapeDrawers = await pluginManager.getShapeDrawers(this, true);
6068
- this.particleUpdaters = await pluginManager.getUpdaters(this, true);
6291
+ this.effectDrawers = await getItemMapFromInitializer(this, pluginManager.initializers.effects);
6292
+ this.shapeDrawers = await getItemMapFromInitializer(this, pluginManager.initializers.shapes);
6293
+ this.particleUpdaters = await getItemsFromInitializer(this, pluginManager.initializers.updaters);
6069
6294
  }
6070
6295
  pause() {
6071
6296
  if (!guardCheck(this)) {
@@ -6132,7 +6357,10 @@
6132
6357
  await this.init();
6133
6358
  this.started = true;
6134
6359
  await new Promise(resolve => {
6360
+ this.#delayResolve = resolve;
6135
6361
  const start = async () => {
6362
+ this.#delayTimeout = undefined;
6363
+ this.#delayResolve = undefined;
6136
6364
  this.#eventListeners.addListeners();
6137
6365
  for (const plugin of this.plugins) {
6138
6366
  await plugin.start?.();
@@ -6148,9 +6376,11 @@
6148
6376
  if (!guardCheck(this) || !this.started) {
6149
6377
  return;
6150
6378
  }
6151
- if (this.#delayTimeout) {
6379
+ if (this.#delayTimeout !== undefined) {
6152
6380
  clearTimeout(this.#delayTimeout);
6153
6381
  this.#delayTimeout = undefined;
6382
+ this.#delayResolve?.();
6383
+ this.#delayResolve = undefined;
6154
6384
  }
6155
6385
  this.#firstStart = true;
6156
6386
  this.started = false;
@@ -6176,6 +6406,27 @@
6176
6406
  }
6177
6407
  return refresh;
6178
6408
  }
6409
+ #initPlugins(allContainerPlugins) {
6410
+ this.plugins.length = 0;
6411
+ this.particleDestroyedPlugins.length = 0;
6412
+ this.particleCreatedPlugins.length = 0;
6413
+ this.particlePositionPlugins.length = 0;
6414
+ for (const [plugin, containerPlugin] of allContainerPlugins) {
6415
+ if (!plugin.needsPlugin(this.actualOptions)) {
6416
+ continue;
6417
+ }
6418
+ this.plugins.push(containerPlugin);
6419
+ if (containerPlugin.particleCreated) {
6420
+ this.particleCreatedPlugins.push(containerPlugin);
6421
+ }
6422
+ if (containerPlugin.particleDestroyed) {
6423
+ this.particleDestroyedPlugins.push(containerPlugin);
6424
+ }
6425
+ if (containerPlugin.particlePosition) {
6426
+ this.particlePositionPlugins.push(containerPlugin);
6427
+ }
6428
+ }
6429
+ }
6179
6430
  #nextFrame(timestamp) {
6180
6431
  try {
6181
6432
  if (!this.#smooth &&
@@ -6452,11 +6703,11 @@
6452
6703
  }
6453
6704
  }
6454
6705
  async #init() {
6455
- const availablePathGenerators = await this.#pluginManager.getPathGenerators?.(this.#container, true);
6456
- if (!availablePathGenerators) {
6706
+ const pluginManager = this.#pluginManager;
6707
+ if (!pluginManager.initializers.pathGenerators) {
6457
6708
  return;
6458
6709
  }
6459
- this.availablePathGenerators = availablePathGenerators;
6710
+ this.availablePathGenerators = await getItemMapFromInitializer(this.#container, pluginManager.initializers.pathGenerators);
6460
6711
  this.pathGenerators = new Map();
6461
6712
  for (const pathGenerator of this.pathGenerators.values()) {
6462
6713
  pathGenerator.init();
@@ -6469,55 +6720,6 @@
6469
6720
  MovePluginInstance: MovePluginInstance
6470
6721
  });
6471
6722
 
6472
- class EmittersPluginInstance {
6473
- #container;
6474
- #instancesManager;
6475
- constructor(instancesManager, container) {
6476
- this.#instancesManager = instancesManager;
6477
- this.#container = container;
6478
- this.#instancesManager.initContainer(container);
6479
- }
6480
- async init() {
6481
- const emittersOptions = this.#container.actualOptions.emitters;
6482
- if (isArray(emittersOptions)) {
6483
- for (const emitterOptions of emittersOptions) {
6484
- await this.#instancesManager.addEmitter(this.#container, emitterOptions);
6485
- }
6486
- }
6487
- else {
6488
- await this.#instancesManager.addEmitter(this.#container, emittersOptions);
6489
- }
6490
- }
6491
- pause() {
6492
- for (const emitter of this.#instancesManager.getArray(this.#container)) {
6493
- emitter.pause();
6494
- }
6495
- }
6496
- play() {
6497
- for (const emitter of this.#instancesManager.getArray(this.#container)) {
6498
- emitter.play();
6499
- }
6500
- }
6501
- resize() {
6502
- for (const emitter of this.#instancesManager.getArray(this.#container)) {
6503
- emitter.resize();
6504
- }
6505
- }
6506
- stop() {
6507
- this.#instancesManager.clear(this.#container);
6508
- }
6509
- update(delta) {
6510
- this.#instancesManager.getArray(this.#container).forEach(emitter => {
6511
- emitter.update(delta);
6512
- });
6513
- }
6514
- }
6515
-
6516
- var EmittersPluginInstance$1 = /*#__PURE__*/Object.freeze({
6517
- __proto__: null,
6518
- EmittersPluginInstance: EmittersPluginInstance
6519
- });
6520
-
6521
6723
  const shapeGenerators = new Map();
6522
6724
  class ShapeManager {
6523
6725
  addShapeGenerator(name, generator) {
@@ -6547,14 +6749,21 @@
6547
6749
  this.#pluginManager = pluginManager;
6548
6750
  }
6549
6751
  async addEmitter(container, options, position) {
6550
- const emitterOptions = new Emitter();
6551
- emitterOptions.load(options);
6552
- const { EmitterInstance } = await Promise.resolve().then(function () { return EmitterInstance$1; }), emitter = new EmitterInstance(this.#pluginManager, container, (emitter) => {
6553
- this.removeEmitter(container, emitter);
6554
- }, emitterOptions, position);
6555
- await emitter.init();
6556
- this.getArray(container).push(emitter);
6557
- return emitter;
6752
+ return this.addEmitters(container, [{ options, position }]).then(t => t[defaultIndex]);
6753
+ }
6754
+ async addEmitters(container, emitters) {
6755
+ const { EmitterInstance } = await Promise.resolve().then(function () { return EmitterInstance$1; }), res = [];
6756
+ for (const { options, position } of emitters) {
6757
+ const emitterOptions = new Emitter();
6758
+ emitterOptions.load(options);
6759
+ const emitter = new EmitterInstance(this.#pluginManager, container, (emitter) => {
6760
+ this.removeEmitter(container, emitter);
6761
+ }, emitterOptions, position);
6762
+ await emitter.init();
6763
+ this.getArray(container).push(emitter);
6764
+ res.push(emitter);
6765
+ }
6766
+ return res;
6558
6767
  }
6559
6768
  clear(container) {
6560
6769
  this.initContainer(container);
@@ -6581,6 +6790,7 @@
6581
6790
  : array.find(t => t.name === idxOrName);
6582
6791
  };
6583
6792
  container.addEmitter = async (options, position) => this.addEmitter(container, options, position);
6793
+ container.addEmitters = async (emitters) => this.addEmitters(container, emitters);
6584
6794
  container.removeEmitter = (idxOrName) => {
6585
6795
  const emitter = container.getEmitter?.(idxOrName);
6586
6796
  if (emitter) {
@@ -6601,7 +6811,7 @@
6601
6811
  };
6602
6812
  }
6603
6813
  removeEmitter(container, emitter) {
6604
- const index = this.getArray(container).indexOf(emitter), minIndex = 0, deleteCount = 1;
6814
+ const index = this.getArray(container).indexOf(emitter), deleteCount = 1;
6605
6815
  if (index >= minIndex) {
6606
6816
  this.getArray(container).splice(index, deleteCount);
6607
6817
  }
@@ -6737,6 +6947,7 @@
6737
6947
  #particlesOptions;
6738
6948
  #paused;
6739
6949
  #pluginManager;
6950
+ #positionOverride = false;
6740
6951
  #removeCallback;
6741
6952
  #resizeObserver;
6742
6953
  #shape;
@@ -6813,6 +7024,31 @@
6813
7024
  });
6814
7025
  this.play();
6815
7026
  }
7027
+ draw(context) {
7028
+ if (!this.options.draw || !this.#shape) {
7029
+ return;
7030
+ }
7031
+ const container = this.#container, fillEnabled = this.options.spawn.fill?.enable ?? true;
7032
+ context.save();
7033
+ context.beginPath();
7034
+ if (fillEnabled) {
7035
+ context.fillStyle = this.spawnFillColor
7036
+ ? getStyleFromHsl(this.spawnFillColor, container.hdr, this.spawnFillOpacity ?? defaultOpacity$1, container.peakNits, container.hdrMode)
7037
+ : getStyleFromRgb({ r: 0, g: 0, b: 0 }, container.hdr, defaultOpacity$1, container.peakNits, container.hdrMode);
7038
+ }
7039
+ if (this.spawnStrokeColor) {
7040
+ context.strokeStyle = getStyleFromHsl(this.spawnStrokeColor, container.hdr, this.spawnStrokeOpacity ?? defaultOpacity$1, container.peakNits, container.hdrMode);
7041
+ context.lineWidth = this.spawnStrokeWidth ?? defaultStrokeWidth;
7042
+ }
7043
+ this.#shape.draw?.(context);
7044
+ if (fillEnabled) {
7045
+ context.fill();
7046
+ }
7047
+ if (this.spawnStrokeColor) {
7048
+ context.stroke();
7049
+ }
7050
+ context.restore();
7051
+ }
6816
7052
  externalPause() {
6817
7053
  this.#paused = true;
6818
7054
  this.pause();
@@ -6850,11 +7086,14 @@
6850
7086
  }
6851
7087
  }
6852
7088
  resize() {
6853
- const initialPosition = this.#initialPosition, container = this.#container;
6854
- this.position =
6855
- initialPosition && isPointInside(initialPosition, container.canvas.size, Vector.origin)
6856
- ? initialPosition
6857
- : this.#calcPosition();
7089
+ const container = this.#container;
7090
+ if (!this.#positionOverride) {
7091
+ const initialPosition = this.#initialPosition;
7092
+ this.position =
7093
+ initialPosition && isPointInside(initialPosition, container.canvas.size, Vector.origin)
7094
+ ? initialPosition
7095
+ : this.#calcPosition();
7096
+ }
6858
7097
  this.#size = this.#calcSize();
6859
7098
  this.size =
6860
7099
  this.#size.mode === PixelMode.percent
@@ -6865,6 +7104,11 @@
6865
7104
  : { width: this.#size.width, height: this.#size.height };
6866
7105
  this.#shape?.resize(this.position, this.size);
6867
7106
  }
7107
+ setPosition(position) {
7108
+ this.#positionOverride = true;
7109
+ this.position = { ...position };
7110
+ this.#shape?.resize(this.position, this.size);
7111
+ }
6868
7112
  update(delta) {
6869
7113
  if (this.#paused) {
6870
7114
  return;
@@ -6890,8 +7134,10 @@
6890
7134
  this.#lifeCount--;
6891
7135
  }
6892
7136
  if (this.#lifeCount > minLifeCount || this.#immortal) {
6893
- this.position = this.#calcPosition();
6894
- this.#shape?.resize(this.position, this.size);
7137
+ if (!this.#positionOverride) {
7138
+ this.position = this.#calcPosition();
7139
+ this.#shape?.resize(this.position, this.size);
7140
+ }
6895
7141
  this.#spawnDelay = container.retina.reduceFactor
6896
7142
  ? (getRangeValue(this.options.life.delay ?? defaultLifeDelay) * millisecondsToSeconds) /
6897
7143
  container.retina.reduceFactor
@@ -7060,6 +7306,7 @@
7060
7306
  exports.loadHyperspacePreset = loadHyperspacePreset;
7061
7307
  exports.tsParticles = tsParticles;
7062
7308
 
7063
- }));
7309
+ })(g.__tsParticlesInternals.presets.hyperspace = g.__tsParticlesInternals.presets.hyperspace || {});
7310
+ })(typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : self);
7311
+
7064
7312
  Object.assign(globalThis.window || globalThis, { loadHyperspacePreset: (globalThis.__tsParticlesInternals.presets.hyperspace || {}).loadHyperspacePreset });
7065
- delete (globalThis.window || globalThis).tsparticlesInternalExports;