party-js
Version:
A JavaScript library to brighten up your user's site experience with visual effects!
167 lines (166 loc) • 6.08 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModuleBuilder = void 0;
var components_1 = require("../components");
/**
* Represents a builder for particle modules. Returns an evaluatable module
* function, that can be consumed by emitters.
*
* @remarks
* Not all properties can be driven. TypeScript will validate this at compile time,
* but no internal validation is performed due to performance reasons. Also, note
* that the driving factor is "lifetime" by default.
*
* @example
* ```ts
* new ModuleBuilder()
* .drive("size")
* .by((t) => t * 2)
* .through("lifetime")
* .build();
* ```
*/
var ModuleBuilder = /** @class */ (function () {
function ModuleBuilder() {
/**
* The factor driving the built function.
*
* @defaultValue "lifetime"
*/
this.factor = "lifetime";
this.isRelative = false;
}
/**
* Specifies the key in the particle that should be driven.
*
* @remarks
* Note that not all of a particle's properties are drivable through modules. If you
* need full control of a particle inside of a module, you can use a module function directly.
*
* @returns The chained builder instance.
*/
ModuleBuilder.prototype.drive = function (key) {
this.driverKey = key;
return this;
};
/**
* Specifies the factor to drive the evaluated value by. Supports "lifetime" and "size".
*
* @returns The chained builder instance.
*/
ModuleBuilder.prototype.through = function (factor) {
this.factor = factor;
return this;
};
/**
* Specifies the value to drive the module behaviour by. This can be a constant,
* a spline or an evaluable function. Note that in the last case, the driving
* factor is passed as a parameter.
*
* @returns The chained builder instance.
*/
ModuleBuilder.prototype.by = function (driver) {
this.driverValue = driver;
return this;
};
/**
* Specifies that the module function is supposed to act relative to the
* properties initial value.
*
* @remarks
* Note that this is only possible if an "initial*" property exists on the
* particle object. The operation applied to the initial and new value
* is dependant on their type:
* - `Vector`: Both vectors are added.
* - `number`: Both numbers are multiplied.
*
* For more advanced relative customizations, consider using the particle
* object in the driver value function instead, like:
* ```ts
* .by((t, p) => p.initialSize + t * 2);
* ```
*/
ModuleBuilder.prototype.relative = function (isRelative) {
if (isRelative === void 0) { isRelative = true; }
this.isRelative = isRelative;
return this;
};
/**
* Consumes the builder and returns an evaluatable module function.
*
* @remarks
* Note that you need to specify the driving key and value, otherwise an error
* will be thrown.
*/
ModuleBuilder.prototype.build = function () {
var _this = this;
if (typeof this.driverKey === "undefined") {
throw new Error("No driving key was provided in the module builder. Did you forget a '.drive()' call?");
}
if (typeof this.driverValue === "undefined") {
throw new Error("No driving value was provided in the module builder. Did you forget a '.through()' call?");
}
return function (particle) {
updateDrivenProperty(particle, _this.driverKey, evaluateModuleDriver(_this.driverValue, calculateModuleFactor(_this.factor, particle), particle), _this.isRelative);
};
};
return ModuleBuilder;
}());
exports.ModuleBuilder = ModuleBuilder;
/**
* Evaluates the module driver using a specified factor.
*/
function evaluateModuleDriver(driver, factor, particle) {
if (typeof driver === "object" && "evaluate" in driver) {
return driver.evaluate(factor);
}
if (typeof driver === "function") {
return driver(factor, particle);
}
return driver;
}
/**
* Calculates a module factor using a specified particle as context.
*/
function calculateModuleFactor(factor, particle) {
switch (factor) {
case "lifetime":
return particle.initialLifetime - particle.lifetime;
case "relativeLifetime":
return ((particle.initialLifetime - particle.lifetime) /
particle.initialLifetime);
case "size":
return particle.size;
default:
throw new Error("Invalid driving factor '" + factor + "'.");
}
}
/**
* Updates a driven property of a particle using the specified value.
*
* @remarks
* If the operation is marked as relative, the function infers the new value
* through the value's type. Note that relative properties must have a
* corresponding "initial*" value in the particle's properties.
*/
function updateDrivenProperty(particle, key, value, relative) {
if (relative === void 0) { relative = false; }
if (!relative) {
particle[key] = value;
}
else {
var initial = particle["initial" + key[0].toUpperCase() + key.substr(1)];
if (typeof initial === "undefined") {
throw new Error("Unable to use relative chaining with key '" + key + "'; no initial value exists.");
}
if (value instanceof components_1.Vector) {
updateDrivenProperty(particle, key, initial.add(value));
}
else if (typeof value === "number") {
updateDrivenProperty(particle, key, initial * value);
}
else {
throw new Error("Unable to use relative chaining with particle key '" + key + "'; no relative operation for '" + value + "' could be inferred.");
}
}
}