This commit is contained in:
2025-01-04 00:34:03 +01:00
parent 41829408dc
commit 0ca14bbc19
18111 changed files with 1871397 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
/**
* An interface for defining particle-based weather effects
* @param {PIXI.Container} parent The parent container within which the effect is rendered
* @param {object} [options] Options passed to the getParticleEmitters method which can be used to customize
* values of the emitter configuration.
* @interface
*/
class ParticleEffect extends FullCanvasObjectMixin(PIXI.Container) {
constructor(options={}) {
super();
/**
* The array of emitters which are active for this particle effect
* @type {PIXI.particles.Emitter[]}
*/
this.emitters = this.getParticleEmitters(options);
}
/* -------------------------------------------- */
/**
* Create an emitter instance which automatically updates using the shared PIXI.Ticker
* @param {PIXI.particles.EmitterConfigV3} config The emitter configuration
* @returns {PIXI.particles.Emitter} The created Emitter instance
*/
createEmitter(config) {
config.autoUpdate = true;
config.emit = false;
return new PIXI.particles.Emitter(this, config);
}
/* -------------------------------------------- */
/**
* Get the particle emitters which should be active for this particle effect.
* This base class creates a single emitter using the explicitly provided configuration.
* Subclasses can override this method for more advanced configurations.
* @param {object} [options={}] Options provided to the ParticleEffect constructor which can be used to customize
* configuration values for created emitters.
* @returns {PIXI.particles.Emitter[]}
*/
getParticleEmitters(options={}) {
if ( foundry.utils.isEmpty(options) ) {
throw new Error("The base ParticleEffect class may only be used with an explicitly provided configuration");
}
return [this.createEmitter(/** @type {PIXI.particles.EmitterConfigV3} */ options)];
}
/* -------------------------------------------- */
/** @override */
destroy(...args) {
for ( const e of this.emitters ) e.destroy();
this.emitters = [];
super.destroy(...args);
}
/* -------------------------------------------- */
/**
* Begin animation for the configured emitters.
*/
play() {
for ( let e of this.emitters ) {
e.emit = true;
}
}
/* -------------------------------------------- */
/**
* Stop animation for the configured emitters.
*/
stop() {
for ( let e of this.emitters ) {
e.emit = false;
}
}
}

View File

@@ -0,0 +1,74 @@
/**
* A full-screen weather effect which renders gently falling autumn leaves.
* @extends {ParticleEffect}
*/
class AutumnLeavesWeatherEffect extends ParticleEffect {
/** @inheritdoc */
static label = "WEATHER.AutumnLeaves";
/**
* Configuration for the particle emitter for falling leaves
* @type {PIXI.particles.EmitterConfigV3}
*/
static LEAF_CONFIG = {
lifetime: {min: 10, max: 10},
behaviors: [
{
type: "alpha",
config: {
alpha: {
list: [{time: 0, value: 0.9}, {time: 1, value: 0.5}]
}
}
},
{
type: "moveSpeed",
config: {
speed: {
list: [{time: 0, value: 20}, {time: 1, value: 60}]
},
minMult: 0.6
}
},
{
type: "scale",
config: {
scale: {
list: [{time: 0, value: 0.2}, {time: 1, value: 0.4}]
},
minMult: 0.5
}
},
{
type: "rotation",
config: {accel: 0, minSpeed: 100, maxSpeed: 200, minStart: 0, maxStart: 365}
},
{
type: "textureRandom",
config: {
textures: Array.fromRange(6).map(n => `ui/particles/leaf${n + 1}.png`)
}
}
]
};
/* -------------------------------------------- */
/** @inheritdoc */
getParticleEmitters() {
const d = canvas.dimensions;
const maxParticles = (d.width / d.size) * (d.height / d.size) * 0.25;
const config = foundry.utils.deepClone(this.constructor.LEAF_CONFIG);
config.maxParticles = maxParticles;
config.frequency = config.lifetime.min / maxParticles;
config.behaviors.push({
type: "spawnShape",
config: {
type: "rect",
data: {x: d.sceneRect.x, y: d.sceneRect.y, w: d.sceneRect.width, h: d.sceneRect.height}
}
});
return [this.createEmitter(config)];
}
}