2023-02-17 11:06:01 +01:00

267 lines
11 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Particles = void 0;
const InteractionManager_1 = require("./Utils/InteractionManager");
const Particle_1 = require("./Particle");
const Point_1 = require("./Utils/Point");
const QuadTree_1 = require("./Utils/QuadTree");
const Rectangle_1 = require("./Utils/Rectangle");
const NumberUtils_1 = require("../Utils/NumberUtils");
class Particles {
constructor(engine, container) {
this.container = container;
this._engine = engine;
this.nextId = 0;
this.array = [];
this.zArray = [];
this.pool = [];
this.limit = 0;
this.needsSort = false;
this.lastZIndex = 0;
this.interactionManager = new InteractionManager_1.InteractionManager(this._engine, container);
const canvasSize = this.container.canvas.size;
this.quadTree = new QuadTree_1.QuadTree(new Rectangle_1.Rectangle(-canvasSize.width / 4, -canvasSize.height / 4, (canvasSize.width * 3) / 2, (canvasSize.height * 3) / 2), 4);
this.movers = this._engine.plugins.getMovers(container, true);
this.updaters = this._engine.plugins.getUpdaters(container, true);
}
get count() {
return this.array.length;
}
addManualParticles() {
const container = this.container, options = container.actualOptions;
for (const particle of options.manualParticles) {
this.addParticle((0, NumberUtils_1.calcPositionFromSize)({
size: container.canvas.size,
position: particle.position,
}), particle.options);
}
}
addParticle(position, overrideOptions, group, initializer) {
const container = this.container, options = container.actualOptions, limit = options.particles.number.limit;
if (limit > 0) {
const countToRemove = this.count + 1 - limit;
if (countToRemove > 0) {
this.removeQuantity(countToRemove);
}
}
return this._pushParticle(position, overrideOptions, group, initializer);
}
clear() {
this.array = [];
this.zArray = [];
}
destroy() {
this.array = [];
this.zArray = [];
this.movers = [];
this.updaters = [];
}
async draw(delta) {
const container = this.container, canvasSize = this.container.canvas.size;
this.quadTree = new QuadTree_1.QuadTree(new Rectangle_1.Rectangle(-canvasSize.width / 4, -canvasSize.height / 4, (canvasSize.width * 3) / 2, (canvasSize.height * 3) / 2), 4);
container.canvas.clear();
await this.update(delta);
if (this.needsSort) {
this.zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
this.lastZIndex = this.zArray[this.zArray.length - 1].position.z;
this.needsSort = false;
}
for (const [, plugin] of container.plugins) {
container.canvas.drawPlugin(plugin, delta);
}
for (const p of this.zArray) {
p.draw(delta);
}
}
handleClickMode(mode) {
this.interactionManager.handleClickMode(mode);
}
init() {
var _a;
const container = this.container, options = container.actualOptions;
this.lastZIndex = 0;
this.needsSort = false;
let handled = false;
this.updaters = this._engine.plugins.getUpdaters(container, true);
this.interactionManager.init();
for (const [, plugin] of container.plugins) {
if (plugin.particlesInitialization !== undefined) {
handled = plugin.particlesInitialization();
}
if (handled) {
break;
}
}
this.interactionManager.init();
for (const [, pathGenerator] of container.pathGenerators) {
pathGenerator.init(container);
}
this.addManualParticles();
if (!handled) {
for (const group in options.particles.groups) {
const groupOptions = options.particles.groups[group];
for (let i = this.count, j = 0; j < ((_a = groupOptions.number) === null || _a === void 0 ? void 0 : _a.value) && i < options.particles.number.value; i++, j++) {
this.addParticle(undefined, groupOptions, group);
}
}
for (let i = this.count; i < options.particles.number.value; i++) {
this.addParticle();
}
}
}
push(nb, mouse, overrideOptions, group) {
this.pushing = true;
for (let i = 0; i < nb; i++) {
this.addParticle(mouse === null || mouse === void 0 ? void 0 : mouse.position, overrideOptions, group);
}
this.pushing = false;
}
async redraw() {
this.clear();
this.init();
await this.draw({ value: 0, factor: 0 });
}
remove(particle, group, override) {
this.removeAt(this.array.indexOf(particle), undefined, group, override);
}
removeAt(index, quantity = 1, group, override) {
if (index < 0 || index > this.count) {
return;
}
let deleted = 0;
for (let i = index; deleted < quantity && i < this.count; i++) {
const particle = this.array[i];
if (!particle || particle.group !== group) {
continue;
}
particle.destroy(override);
this.array.splice(i--, 1);
const zIdx = this.zArray.indexOf(particle);
this.zArray.splice(zIdx, 1);
this.pool.push(particle);
deleted++;
this._engine.dispatchEvent("particleRemoved", {
container: this.container,
data: {
particle,
},
});
}
}
removeQuantity(quantity, group) {
this.removeAt(0, quantity, group);
}
setDensity() {
const options = this.container.actualOptions;
for (const group in options.particles.groups) {
this._applyDensity(options.particles.groups[group], 0, group);
}
this._applyDensity(options.particles, options.manualParticles.length);
}
async update(delta) {
var _a, _b;
const container = this.container, particlesToDelete = [];
for (const [, pathGenerator] of container.pathGenerators) {
pathGenerator.update();
}
for (const [, plugin] of container.plugins) {
(_a = plugin.update) === null || _a === void 0 ? void 0 : _a.call(plugin, delta);
}
for (const particle of this.array) {
const resizeFactor = container.canvas.resizeFactor;
if (resizeFactor && !particle.ignoresResizeRatio) {
particle.position.x *= resizeFactor.width;
particle.position.y *= resizeFactor.height;
particle.initialPosition.x *= resizeFactor.width;
particle.initialPosition.y *= resizeFactor.height;
}
particle.ignoresResizeRatio = false;
await this.interactionManager.reset(particle);
for (const [, plugin] of this.container.plugins) {
if (particle.destroyed) {
break;
}
(_b = plugin.particleUpdate) === null || _b === void 0 ? void 0 : _b.call(plugin, particle, delta);
}
for (const mover of this.movers) {
if (mover.isEnabled(particle)) {
mover.move(particle, delta);
}
}
if (particle.destroyed) {
particlesToDelete.push(particle);
continue;
}
this.quadTree.insert(new Point_1.Point(particle.getPosition(), particle));
}
for (const particle of particlesToDelete) {
this.remove(particle);
}
await this.interactionManager.externalInteract(delta);
for (const particle of this.array) {
for (const updater of this.updaters) {
updater.update(particle, delta);
}
if (!particle.destroyed && !particle.spawning) {
await this.interactionManager.particlesInteract(particle, delta);
}
}
delete container.canvas.resizeFactor;
}
_applyDensity(options, manualCount, group) {
var _a;
if (!((_a = options.number.density) === null || _a === void 0 ? void 0 : _a.enable)) {
return;
}
const numberOptions = options.number, densityFactor = this._initDensityFactor(numberOptions.density), optParticlesNumber = numberOptions.value, optParticlesLimit = numberOptions.limit > 0 ? numberOptions.limit : optParticlesNumber, particlesNumber = Math.min(optParticlesNumber, optParticlesLimit) * densityFactor + manualCount, particlesCount = Math.min(this.count, this.array.filter((t) => t.group === group).length);
this.limit = numberOptions.limit * densityFactor;
if (particlesCount < particlesNumber) {
this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
}
else if (particlesCount > particlesNumber) {
this.removeQuantity(particlesCount - particlesNumber, group);
}
}
_initDensityFactor(densityOptions) {
const container = this.container;
if (!container.canvas.element || !densityOptions.enable) {
return 1;
}
const canvas = container.canvas.element, pxRatio = container.retina.pixelRatio;
return (canvas.width * canvas.height) / (densityOptions.factor * pxRatio ** 2 * densityOptions.area);
}
_pushParticle(position, overrideOptions, group, initializer) {
try {
let particle = this.pool.pop();
if (particle) {
particle.init(this.nextId, position, overrideOptions, group);
}
else {
particle = new Particle_1.Particle(this._engine, this.nextId, this.container, position, overrideOptions, group);
}
let canAdd = true;
if (initializer) {
canAdd = initializer(particle);
}
if (!canAdd) {
return;
}
this.array.push(particle);
this.zArray.push(particle);
this.nextId++;
this._engine.dispatchEvent("particleAdded", {
container: this.container,
data: {
particle,
},
});
return particle;
}
catch (e) {
console.warn(`error adding particle: ${e}`);
return;
}
}
}
exports.Particles = Particles;