Skip to content

Commit

Permalink
feat: improving dynamic imports
Browse files Browse the repository at this point in the history
  • Loading branch information
matteobruni committed Jan 23, 2024
1 parent 6dab9e9 commit 7674ee3
Show file tree
Hide file tree
Showing 43 changed files with 406 additions and 140 deletions.
4 changes: 3 additions & 1 deletion engine/src/Core/Container.ts
Expand Up @@ -496,6 +496,8 @@ export class Container {
}
}

await this.particles.initPlugins();

/* options settings */
this._options = loadContainerOptions(this._engine, this, this._initialSourceOptions, this.sourceOptions);
this.actualOptions = loadContainerOptions(this._engine, this, this._options);
Expand Down Expand Up @@ -540,7 +542,7 @@ export class Container {

this._engine.dispatchEvent(EventType.containerInit, { container: this });

this.particles.init();
await this.particles.init();
this.particles.setDensity();

for (const [, plugin] of this.plugins) {
Expand Down
43 changes: 16 additions & 27 deletions engine/src/Core/Engine.ts
Expand Up @@ -4,7 +4,7 @@
*/
import { errorPrefix, generatedAttribute } from "./Utils/Constants.js";
import { executeOnSingleOrMultiple, getLogger, itemFromSingleOrMultiple } from "../Utils/Utils.js";
import { Container } from "./Container.js";
import type { Container } from "./Container.js";
import type { CustomEventArgs } from "../Types/CustomEventArgs.js";
import type { CustomEventListener } from "../Types/CustomEventListener.js";
import { EventDispatcher } from "../Utils/EventDispatcher.js";
Expand Down Expand Up @@ -42,7 +42,7 @@ interface DataFromUrlParams {
url: SingleOrMultiple<string>;
}

type GenericInitializer<T> = (container: Container) => T;
type GenericInitializer<T> = (container: Container) => Promise<T>;

/**
* Alias for interactivity manager initializer function
Expand All @@ -69,16 +69,16 @@ interface Initializers {
* @param force -
* @returns the items from the given initializer
*/
function getItemsFromInitializer<TItem, TInitializer extends GenericInitializer<TItem>>(
async function getItemsFromInitializer<TItem, TInitializer extends GenericInitializer<TItem>>(
container: Container,
map: Map<Container, TItem[]>,
initializers: Map<string, TInitializer>,
force = false,
): TItem[] {
): Promise<TItem[]> {
let res = map.get(container);

if (!res || force) {
res = [...initializers.values()].map((t) => t(container));
res = await Promise.all([...initializers.values()].map((t) => t(container)));

map.set(container, res);
}
Expand Down Expand Up @@ -243,11 +243,7 @@ export class Engine {
* @param interactorInitializer - the interaction manager initializer
* @param refresh - if true the engine will refresh all the containers
*/
async addInteractor(
name: string,
interactorInitializer: (container: Container) => IInteractor,
refresh = true,
): Promise<void> {
async addInteractor(name: string, interactorInitializer: InteractorInitializer, refresh = true): Promise<void> {
this._initializers.interactors.set(name, interactorInitializer);

await this.refresh(refresh);
Expand All @@ -258,11 +254,7 @@ export class Engine {
* @param moverInitializer - the mover initializer
* @param refresh - if true the engine will refresh all the containers
*/
async addMover(
name: string,
moverInitializer: (container: Container) => IParticleMover,
refresh = true,
): Promise<void> {
async addMover(name: string, moverInitializer: MoverInitializer, refresh = true): Promise<void> {
this._initializers.movers.set(name, moverInitializer);

await this.refresh(refresh);
Expand All @@ -274,11 +266,7 @@ export class Engine {
* @param updaterInitializer - the particle updater initializer
* @param refresh - if true the engine will refresh all the containers
*/
async addParticleUpdater(
name: string,
updaterInitializer: (container: Container) => IParticleUpdater,
refresh = true,
): Promise<void> {
async addParticleUpdater(name: string, updaterInitializer: UpdaterInitializer, refresh = true): Promise<void> {
this._initializers.updaters.set(name, updaterInitializer);

await this.refresh(refresh);
Expand Down Expand Up @@ -422,12 +410,12 @@ export class Engine {
* @param force - if true reloads the interaction managers collection for the given container
* @returns the array of interaction managers for the given container
*/
getInteractors(container: Container, force = false): IInteractor[] {
return getItemsFromInitializer(container, this.interactors, this._initializers.interactors, force);
async getInteractors(container: Container, force = false): Promise<IInteractor[]> {
return await getItemsFromInitializer(container, this.interactors, this._initializers.interactors, force);
}

getMovers(container: Container, force = false): IParticleMover[] {
return getItemsFromInitializer(container, this.movers, this._initializers.movers, force);
async getMovers(container: Container, force = false): Promise<IParticleMover[]> {
return await getItemsFromInitializer(container, this.movers, this._initializers.movers, force);
}

/**
Expand Down Expand Up @@ -488,8 +476,8 @@ export class Engine {
* @param force - if true reloads the updater collection for the given container
* @returns the array of updaters for the given container
*/
getUpdaters(container: Container, force = false): IParticleUpdater[] {
return getItemsFromInitializer(container, this.updaters, this._initializers.updaters, force);
async getUpdaters(container: Container, force = false): Promise<IParticleUpdater[]> {
return await getItemsFromInitializer(container, this.updaters, this._initializers.updaters, force);
}

/**
Expand Down Expand Up @@ -578,7 +566,8 @@ export class Engine {
}

/* launch tsParticles */
const newItem = new Container(this, id, currentOptions);
const { Container } = await import("./Container.js"),
newItem = new Container(this, id, currentOptions);

if (oldIndex >= minIndex) {
const deleteCount = 0;
Expand Down
44 changes: 29 additions & 15 deletions engine/src/Core/Particles.ts
Expand Up @@ -6,6 +6,8 @@ import type { ICoordinates } from "./Interfaces/ICoordinates.js";
import type { IDelta } from "./Interfaces/IDelta.js";
import type { IDimension } from "./Interfaces/IDimension.js";
import type { IMouseData } from "./Interfaces/IMouseData.js";
import type { IParticleMover } from "./Interfaces/IParticleMover.js";
import type { IParticleUpdater } from "./Interfaces/IParticleUpdater.js";
import type { IParticlesDensity } from "../Options/Interfaces/Particles/Number/IParticlesDensity.js";
import type { IParticlesOptions } from "../Options/Interfaces/Particles/IParticlesOptions.js";
import { InteractionManager } from "./Utils/InteractionManager.js";
Expand Down Expand Up @@ -33,14 +35,14 @@ const qTreeRectangle = (canvasSize: IDimension): Rectangle => {
* Particles manager object
*/
export class Particles {
movers;
movers: IParticleMover[];

/**
* The quad tree used to search particles withing ranges
*/
quadTree;

updaters;
updaters: IParticleUpdater[];

/**
* All the particles used in canvas
Expand All @@ -54,6 +56,7 @@ export class Particles {
private _limit;
private _needsSort;
private _nextId;
private _pluginsInitialized;
private readonly _pool: Particle[];
private _resizeFactor?: IDimension;
private _zArray: Particle[];
Expand All @@ -75,13 +78,14 @@ export class Particles {
this._needsSort = false;
this._lastZIndex = 0;
this._interactionManager = new InteractionManager(engine, container);
this._pluginsInitialized = false;

const canvasSize = container.canvas.size;

this.quadTree = new QuadTree(qTreeRectangle(canvasSize), qTreeCapacity);

this.movers = this._engine.getMovers(container, true);
this.updaters = this._engine.getUpdaters(container, true);
this.movers = [];
this.updaters = [];
}

get count(): number {
Expand Down Expand Up @@ -136,6 +140,7 @@ export class Particles {
clear(): void {
this._array = [];
this._zArray = [];
this._pluginsInitialized = false;
}

destroy(): void {
Expand Down Expand Up @@ -187,17 +192,16 @@ export class Particles {
}

/* --------- tsParticles functions - particles ----------- */
init(): void {
async init(): Promise<void> {
const container = this._container,
options = container.actualOptions;

this._lastZIndex = 0;
this._needsSort = false;

let handled = false;
await this.initPlugins();

this.updaters = this._engine.getUpdaters(container, true);
this._interactionManager.init();
let handled = false;

for (const [, plugin] of container.plugins) {
if (plugin.particlesInitialization !== undefined) {
Expand All @@ -209,12 +213,6 @@ export class Particles {
}
}

this._interactionManager.init();

for (const [, pathGenerator] of container.pathGenerators) {
pathGenerator.init(container);
}

this.addManualParticles();

if (!handled) {
Expand All @@ -239,6 +237,22 @@ export class Particles {
}
}

async initPlugins(): Promise<void> {
if (this._pluginsInitialized) {
return;
}

const container = this._container;

this.movers = await this._engine.getMovers(container, true);
this.updaters = await this._engine.getUpdaters(container, true);
await this._interactionManager.init();

for (const [, pathGenerator] of container.pathGenerators) {
pathGenerator.init(container);
}
}

push(nb: number, mouse?: IMouseData, overrideOptions?: RecursivePartial<IParticlesOptions>, group?: string): void {
for (let i = 0; i < nb; i++) {
this.addParticle(mouse?.position, overrideOptions, group);
Expand All @@ -247,7 +261,7 @@ export class Particles {

async redraw(): Promise<void> {
this.clear();
this.init();
await this.init();

await this.draw({ value: 0, factor: 0 });
}
Expand Down
9 changes: 6 additions & 3 deletions engine/src/Core/Utils/InteractionManager.ts
Expand Up @@ -4,6 +4,7 @@ import type { Container } from "../Container.js";
import type { Engine } from "../Engine.js";
import type { IDelta } from "../Interfaces/IDelta.js";
import type { IExternalInteractor } from "../Interfaces/IExternalInteractor.js";
import type { IInteractor } from "../Interfaces/IInteractor.js";
import type { IParticlesInteractor } from "../Interfaces/IParticlesInteractor.js";
import { InteractorType } from "../../Enums/Types/InteractorType.js";
import type { Particle } from "../Particle.js";
Expand All @@ -25,7 +26,7 @@ export class InteractionManager {
* The interactors that are used for initialization
* @internal
*/
private readonly _interactors;
private _interactors: IInteractor[];

/**
* Registered particles interactions managers
Expand All @@ -43,7 +44,7 @@ export class InteractionManager {
private readonly container: Container,
) {
this._engine = engine;
this._interactors = engine.getInteractors(this.container, true);
this._interactors = [];
this._externalInteractors = [];
this._particleInteractors = [];
}
Expand All @@ -69,7 +70,9 @@ export class InteractionManager {
/**
* Initializes the interaction manager, loading all the engine registered managers into the container
*/
init(): void {
async init(): Promise<void> {
this._interactors = await this._engine.getInteractors(this.container, true);

this._externalInteractors = [];
this._particleInteractors = [];

Expand Down
11 changes: 9 additions & 2 deletions interactions/external/attract/src/index.ts
@@ -1,12 +1,19 @@
import { Attractor } from "./Attractor.js";
import type { Engine } from "@tsparticles/engine";

/**
* @param engine -
* @param refresh -
*/
export async function loadExternalAttractInteraction(engine: Engine, refresh = true): Promise<void> {
await engine.addInteractor("externalAttract", (container) => new Attractor(engine, container), refresh);
await engine.addInteractor(
"externalAttract",
async (container) => {
const { Attractor } = await import("./Attractor.js");

return new Attractor(engine, container);
},
refresh,
);
}

export * from "./Options/Classes/Attract.js";
Expand Down
11 changes: 9 additions & 2 deletions interactions/external/bounce/src/index.ts
@@ -1,12 +1,19 @@
import { Bouncer } from "./Bouncer.js";
import type { Engine } from "@tsparticles/engine";

/**
* @param engine -
* @param refresh -
*/
export async function loadExternalBounceInteraction(engine: Engine, refresh = true): Promise<void> {
await engine.addInteractor("externalBounce", (container) => new Bouncer(container), refresh);
await engine.addInteractor(
"externalBounce",
async (container) => {
const { Bouncer } = await import("./Bouncer.js");

return new Bouncer(container);
},
refresh,
);
}

export * from "./Options/Classes/Bounce.js";
Expand Down
11 changes: 9 additions & 2 deletions interactions/external/bubble/src/index.ts
@@ -1,12 +1,19 @@
import { Bubbler } from "./Bubbler.js";
import type { Engine } from "@tsparticles/engine";

/**
* @param engine -
* @param refresh -
*/
export async function loadExternalBubbleInteraction(engine: Engine, refresh = true): Promise<void> {
await engine.addInteractor("externalBubble", (container) => new Bubbler(container), refresh);
await engine.addInteractor(
"externalBubble",
async (container) => {
const { Bubbler } = await import("./Bubbler.js");

return new Bubbler(container);
},
refresh,
);
}

export * from "./Options/Classes/BubbleBase.js";
Expand Down
11 changes: 9 additions & 2 deletions interactions/external/connect/src/index.ts
@@ -1,12 +1,19 @@
import { Connector } from "./Connector.js";
import type { Engine } from "@tsparticles/engine";

/**
* @param engine -
* @param refresh -
*/
export async function loadExternalConnectInteraction(engine: Engine, refresh = true): Promise<void> {
await engine.addInteractor("externalConnect", (container) => new Connector(container), refresh);
await engine.addInteractor(
"externalConnect",
async (container) => {
const { Connector } = await import("./Connector.js");

return new Connector(container);
},
refresh,
);
}

export * from "./Options/Classes/Connect.js";
Expand Down

0 comments on commit 7674ee3

Please sign in to comment.