Skip to content

Commit

Permalink
feat: moved more code out from engine to specific plugins, added new …
Browse files Browse the repository at this point in the history
…method to interactors
  • Loading branch information
matteobruni committed Aug 5, 2022
1 parent cd23778 commit c3aab68
Show file tree
Hide file tree
Showing 23 changed files with 132 additions and 56 deletions.
7 changes: 7 additions & 0 deletions engine/src/Core/Interfaces/IInteractor.ts
@@ -1,5 +1,7 @@
import type { IInteractivity } from "../../Options/Interfaces/Interactivity/IInteractivity";
import type { IOptions } from "../../Options/Interfaces/IOptions";
import type { IParticlesOptions } from "../../Options/Interfaces/Particles/IParticlesOptions";
import type { Interactivity } from "../../Options/Classes/Interactivity/Interactivity";
import type { InteractorType } from "../../Enums/Types/InteractorType";
import type { Options } from "../../Options/Classes/Options";
import type { Particle } from "../Particle";
Expand All @@ -10,6 +12,11 @@ import type { RecursivePartial } from "../../Types/RecursivePartial";
* @category Interfaces
*/
export interface IInteractor {
loadInteractivityOptions?: (
options: Interactivity,
...sources: RecursivePartial<IInteractivity | undefined>[]
) => void;

loadOptions?: (options: Options, ...sources: (RecursivePartial<IOptions> | undefined)[]) => void;

loadParticlesOptions?: (
Expand Down
2 changes: 1 addition & 1 deletion engine/src/Core/Particle.ts
Expand Up @@ -327,7 +327,7 @@ export class Particle implements IParticle {
particlesOptions.load(overrideOptions);
particlesOptions.load(this.shapeData?.particles);

this.interactivity = new Interactivity();
this.interactivity = new Interactivity(engine, container);

this.interactivity.load(container.actualOptions.interactivity);
this.interactivity.load(particlesOptions.interactivity);
Expand Down
26 changes: 25 additions & 1 deletion engine/src/Options/Classes/Interactivity/Interactivity.ts
@@ -1,3 +1,5 @@
import type { Container } from "../../../Core/Container";
import type { Engine } from "../../../engine";
import { Events } from "./Events/Events";
import { HoverMode } from "../../../Enums/Modes/HoverMode";
import type { IInteractivity } from "../../Interfaces/Interactivity/IInteractivity";
Expand All @@ -11,11 +13,21 @@ import type { RecursivePartial } from "../../../Types/RecursivePartial";
* @category Options
*/
export class Interactivity implements IInteractivity, IOptionLoader<IInteractivity> {
[name: string]: unknown;

readonly #container;

detectsOn: InteractivityDetect | keyof typeof InteractivityDetect;

readonly #engine;

events;
modes;

constructor() {
constructor(engine: Engine, container?: Container) {
this.#engine = engine;
this.#container = container;

this.detectsOn = InteractivityDetect.window;
this.events = new Events();
this.modes = new Modes();
Expand Down Expand Up @@ -61,5 +73,17 @@ export class Interactivity implements IInteractivity, IOptionLoader<IInteractivi
this.events.onHover.mode = [this.events.onHover.mode, HoverMode.slow];
}
}

if (this.#container) {
const interactors = this.#engine.plugins.interactors.get(this.#container);

if (interactors) {
for (const interactor of interactors) {
if (interactor.loadInteractivityOptions) {
interactor.loadInteractivityOptions(this, data);
}
}
}
}
}
}
4 changes: 0 additions & 4 deletions engine/src/Options/Classes/Interactivity/Modes/Modes.ts
Expand Up @@ -5,7 +5,6 @@ import { Connect } from "./Connect";
import { Grab } from "./Grab";
import type { IModes } from "../../../Interfaces/Interactivity/Modes/IModes";
import type { IOptionLoader } from "../../../Interfaces/IOptionLoader";
import { Light } from "./Light";
import { Push } from "./Push";
import type { RecursivePartial } from "../../../../Types/RecursivePartial";
import { Remove } from "./Remove";
Expand All @@ -23,7 +22,6 @@ export class Modes implements IModes, IOptionLoader<IModes> {
bubble;
connect;
grab;
light;
push;
remove;
repulse;
Expand All @@ -36,7 +34,6 @@ export class Modes implements IModes, IOptionLoader<IModes> {
this.bubble = new Bubble();
this.connect = new Connect();
this.grab = new Grab();
this.light = new Light();
this.push = new Push();
this.remove = new Remove();
this.repulse = new Repulse();
Expand All @@ -53,7 +50,6 @@ export class Modes implements IModes, IOptionLoader<IModes> {
this.bubble.load(data.bubble);
this.connect.load(data.connect);
this.grab.load(data.grab);
this.light.load(data.light);
this.push.load(data.push);
this.remove.load(data.remove);
this.repulse.load(data.repulse);
Expand Down
2 changes: 1 addition & 1 deletion engine/src/Options/Classes/Options.ts
Expand Up @@ -58,7 +58,7 @@ export class Options implements IOptions, IOptionLoader<IOptions> {
this.detectRetina = true;
this.duration = 0;
this.fpsLimit = 120;
this.interactivity = new Interactivity();
this.interactivity = new Interactivity(engine, container);
this.manualParticles = [];
this.motion = new Motion();
this.particles = loadParticlesOptions(this.#engine, this.#container);
Expand Down
2 changes: 2 additions & 0 deletions engine/src/Options/Interfaces/Interactivity/IInteractivity.ts
Expand Up @@ -8,6 +8,8 @@ import type { InteractivityDetect } from "../../../Enums/InteractivityDetect";
* @category Options
*/
export interface IInteractivity {
[name: string]: unknown;

/**
* @deprecated use the new detectsOn instead
*/
Expand Down
2 changes: 0 additions & 2 deletions engine/src/Options/Interfaces/Interactivity/Modes/IModes.ts
Expand Up @@ -3,7 +3,6 @@ import type { IBounce } from "./IBounce";
import type { IBubble } from "./IBubble";
import type { IConnect } from "./IConnect";
import type { IGrab } from "./IGrab";
import type { ILight } from "./ILight";
import type { IPush } from "./IPush";
import type { IRemove } from "./IRemove";
import type { IRepulse } from "./IRepulse";
Expand All @@ -20,7 +19,6 @@ export interface IModes {
bubble: IBubble;
connect: IConnect;
grab: IGrab;
light: ILight;
push: IPush;
remove: IRemove;
repulse: IRepulse;
Expand Down
4 changes: 0 additions & 4 deletions engine/src/bundle.ts
Expand Up @@ -75,10 +75,6 @@ export * from "./Options/Classes/Interactivity/Modes/Connect";
export * from "./Options/Classes/Interactivity/Modes/ConnectLinks";
export * from "./Options/Classes/Interactivity/Modes/Grab";
export * from "./Options/Classes/Interactivity/Modes/GrabLinks";
export * from "./Options/Classes/Interactivity/Modes/Light";
export * from "./Options/Classes/Interactivity/Modes/LightArea";
export * from "./Options/Classes/Interactivity/Modes/LightGradient";
export * from "./Options/Classes/Interactivity/Modes/LightShadow";
export * from "./Options/Classes/Interactivity/Modes/Modes";
export * from "./Options/Classes/Interactivity/Modes/Push";
export * from "./Options/Classes/Interactivity/Modes/Remove";
Expand Down
8 changes: 0 additions & 8 deletions engine/src/index.ts
Expand Up @@ -106,10 +106,6 @@ export * from "./Options/Classes/Interactivity/Modes/Connect";
export * from "./Options/Classes/Interactivity/Modes/ConnectLinks";
export * from "./Options/Classes/Interactivity/Modes/Grab";
export * from "./Options/Classes/Interactivity/Modes/GrabLinks";
export * from "./Options/Classes/Interactivity/Modes/Light";
export * from "./Options/Classes/Interactivity/Modes/LightArea";
export * from "./Options/Classes/Interactivity/Modes/LightGradient";
export * from "./Options/Classes/Interactivity/Modes/LightShadow";
export * from "./Options/Classes/Interactivity/Modes/Modes";
export * from "./Options/Classes/Interactivity/Modes/Push";
export * from "./Options/Classes/Interactivity/Modes/Remove";
Expand Down Expand Up @@ -187,10 +183,6 @@ export * from "./Options/Interfaces/Interactivity/Modes/IConnect";
export * from "./Options/Interfaces/Interactivity/Modes/IConnectLinks";
export * from "./Options/Interfaces/Interactivity/Modes/IGrab";
export * from "./Options/Interfaces/Interactivity/Modes/IGrabLinks";
export * from "./Options/Interfaces/Interactivity/Modes/ILight";
export * from "./Options/Interfaces/Interactivity/Modes/ILightArea";
export * from "./Options/Interfaces/Interactivity/Modes/ILightGradient";
export * from "./Options/Interfaces/Interactivity/Modes/ILightShadow";
export * from "./Options/Interfaces/Interactivity/Modes/IModeDiv";
export * from "./Options/Interfaces/Interactivity/Modes/IModes";
export * from "./Options/Interfaces/Interactivity/Modes/IPush";
Expand Down
7 changes: 3 additions & 4 deletions interactions/light/src/ExternalLighter.ts
@@ -1,6 +1,5 @@
import { ExternalInteractorBase, HoverMode, isInArray, rangeColorToRgb } from "tsparticles-engine";
import type { LightContainer } from "./Types";
import type { Particle } from "tsparticles-engine";
import type { LightContainer, LightParticle } from "./Types";
import { drawLight } from "./Utils";

export class ExternalLighter extends ExternalInteractorBase {
Expand Down Expand Up @@ -33,7 +32,7 @@ export class ExternalLighter extends ExternalInteractorBase {
}
}

isEnabled(particle?: Particle): boolean {
isEnabled(particle?: LightParticle): boolean {
const container = this.container as LightContainer,
mouse = container.interactivity.mouse,
interactivity = particle?.interactivity ?? container.actualOptions.interactivity,
Expand All @@ -45,7 +44,7 @@ export class ExternalLighter extends ExternalInteractorBase {

const res = isInArray(HoverMode.light, events.onHover.mode);

if (res) {
if (res && interactivity.modes.light) {
const lightGradient = interactivity.modes.light.area.gradient;

container.canvas.mouseLight = {
Expand Down
@@ -1,8 +1,7 @@
import type { ILight } from "../../../Interfaces/Interactivity/Modes/ILight";
import type { IOptionLoader } from "../../../Interfaces/IOptionLoader";
import type { IOptionLoader, RecursivePartial } from "tsparticles-engine";
import type { ILight } from "../Interfaces/ILight";
import { LightArea } from "./LightArea";
import { LightShadow } from "./LightShadow";
import type { RecursivePartial } from "../../../../Types/RecursivePartial";

export class Light implements ILight, IOptionLoader<ILight> {
area;
Expand Down
@@ -1,7 +1,6 @@
import type { ILightArea } from "../../../Interfaces/Interactivity/Modes/ILightArea";
import type { IOptionLoader } from "../../../Interfaces/IOptionLoader";
import type { IOptionLoader, RecursivePartial } from "tsparticles-engine";
import type { ILightArea } from "../Interfaces/ILightArea";
import { LightGradient } from "./LightGradient";
import type { RecursivePartial } from "../../../../Types/RecursivePartial";

export class LightArea implements ILightArea, IOptionLoader<ILightArea> {
gradient;
Expand Down
@@ -1,7 +1,6 @@
import type { ILightGradient } from "../../../Interfaces/Interactivity/Modes/ILightGradient";
import type { IOptionLoader } from "../../../Interfaces/IOptionLoader";
import { OptionsColor } from "../../OptionsColor";
import type { RecursivePartial } from "../../../../Types/RecursivePartial";
import type { IOptionLoader, RecursivePartial } from "tsparticles-engine";
import type { ILightGradient } from "../Interfaces/ILightGradient";
import { OptionsColor } from "tsparticles-engine";

export class LightGradient implements ILightGradient, IOptionLoader<ILightGradient> {
start;
Expand Down
10 changes: 10 additions & 0 deletions interactions/light/src/Options/Classes/LightOptions.ts
@@ -0,0 +1,10 @@
import type { Options, ParticlesOptions } from "tsparticles-engine";
import type { LightInteractivity } from "../../Types";

export type LightOptions = Options & {
interactivity?: LightInteractivity;
};

export type LightParticlesOptions = ParticlesOptions & {
interactivity?: LightInteractivity;
};
@@ -1,7 +1,6 @@
import type { ILightShadow } from "../../../Interfaces/Interactivity/Modes/ILightShadow";
import type { IOptionLoader } from "../../../Interfaces/IOptionLoader";
import { OptionsColor } from "../../OptionsColor";
import type { RecursivePartial } from "../../../../Types/RecursivePartial";
import type { IOptionLoader, RecursivePartial } from "tsparticles-engine";
import type { ILightShadow } from "../Interfaces/ILightShadow";
import { OptionsColor } from "tsparticles-engine";

export class LightShadow implements ILightShadow, IOptionLoader<ILightShadow> {
color;
Expand Down
@@ -1,4 +1,4 @@
import type { IOptionsColor } from "../../IOptionsColor";
import type { IOptionsColor } from "tsparticles-engine";

export interface ILightGradient {
start: string | IOptionsColor;
Expand Down
10 changes: 10 additions & 0 deletions interactions/light/src/Options/Interfaces/ILightOptions.ts
@@ -0,0 +1,10 @@
import type { IOptions, IParticlesOptions } from "tsparticles-engine";
import type { LightInteractivity } from "../../Types";

export type ILightOptions = IOptions & {
interactivity?: LightInteractivity;
};

export type ILightParticlesOptions = IParticlesOptions & {
interactivity?: LightInteractivity;
};
@@ -1,4 +1,4 @@
import type { IOptionsColor } from "../../IOptionsColor";
import type { IOptionsColor } from "tsparticles-engine";

export interface ILightShadow {
color: string | IOptionsColor;
Expand Down
38 changes: 32 additions & 6 deletions interactions/light/src/ParticlesLighter.ts
@@ -1,11 +1,16 @@
import { HoverMode, ParticlesInteractorBase, isInArray, rangeColorToRgb } from "tsparticles-engine";
import type { LightContainer, LightParticle } from "./Types";
import type { Particle } from "tsparticles-engine";
import { HoverMode, Modes, ParticlesInteractorBase, isInArray, rangeColorToRgb } from "tsparticles-engine";
import type { IInteractivity, Interactivity, RecursivePartial } from "tsparticles-engine";
import type { LightContainer, LightInteractivity, LightParticle } from "./Types";
import { Light } from "./Options/Classes/Light";
import { drawParticleShadow } from "./Utils";

export class ParticlesLighter extends ParticlesInteractorBase {
readonly #container;

constructor(container: LightContainer) {
super(container);

this.#container = container;
}

clear(): void {
Expand All @@ -16,8 +21,8 @@ export class ParticlesLighter extends ParticlesInteractorBase {
// do nothing
}

async interact(particle: Particle): Promise<void> {
const container = this.container,
async interact(particle: LightParticle): Promise<void> {
const container = this.#container,
options = container.actualOptions;

if (options.interactivity.events.onHover.enable && container.interactivity.status === "mousemove") {
Expand All @@ -43,7 +48,7 @@ export class ParticlesLighter extends ParticlesInteractorBase {

const res = isInArray(HoverMode.light, events.onHover.mode);

if (res) {
if (res && interactivity.modes.light) {
const shadowOptions = interactivity.modes.light.shadow;

particle.lightShadow = rangeColorToRgb(shadowOptions.color);
Expand All @@ -52,6 +57,27 @@ export class ParticlesLighter extends ParticlesInteractorBase {
return res;
}

loadInteractivityOptions(
options: Interactivity & LightInteractivity,
...sources: RecursivePartial<(IInteractivity & LightInteractivity) | undefined>[]
): void {
for (const source of sources) {
if (!source?.modes?.light) {
continue;
}

if (!options.modes) {
options.modes = new Modes();
}

if (!options.modes.light) {
options.modes.light = new Light();
}

options.modes.light.load(source.modes.light);
}
}

reset(): void {
// do nothing
}
Expand Down
12 changes: 12 additions & 0 deletions interactions/light/src/Types.ts
@@ -1,11 +1,23 @@
import type { Container, IRgb, Particle } from "tsparticles-engine";
import type { LightOptions, LightParticlesOptions } from "./Options/Classes/LightOptions";
import type { Light } from "./Options/Classes/Light";

export type LightInteractivity = {
modes?: {
light?: Light;
};
};

export type LightContainer = Container & {
actualOptions: LightOptions;
canvas: {
mouseLight?: { start?: IRgb; stop?: IRgb };
};
interactivity?: LightInteractivity;
};

export type LightParticle = Particle & {
interactivity?: LightInteractivity;
lightShadow?: IRgb;
options: LightParticlesOptions;
};

0 comments on commit c3aab68

Please sign in to comment.