90 lines
3.2 KiB
JavaScript
90 lines
3.2 KiB
JavaScript
import BaseLightSource from "./base-light-source.mjs";
|
|
import PointEffectSourceMixin from "./point-effect-source.mjs";
|
|
|
|
/**
|
|
* A specialized subclass of the BaseLightSource which renders a source of light as a point-based effect.
|
|
* @extends {BaseLightSource}
|
|
* @mixes {PointEffectSourceMixin}
|
|
*/
|
|
export default class PointLightSource extends PointEffectSourceMixin(BaseLightSource) {
|
|
|
|
/** @override */
|
|
static effectsCollection = "lightSources";
|
|
|
|
/* -------------------------------------------- */
|
|
/* Source Suppression Management */
|
|
/* -------------------------------------------- */
|
|
|
|
/**
|
|
* Update darkness suppression according to darkness sources collection.
|
|
*/
|
|
#updateDarknessSuppression() {
|
|
this.suppression.darkness = canvas.effects.testInsideDarkness({x: this.x, y: this.y}, this.elevation);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
/* Light Source Initialization */
|
|
/* -------------------------------------------- */
|
|
|
|
/** @inheritDoc */
|
|
_initialize(data) {
|
|
super._initialize(data);
|
|
Object.assign(this.data, {
|
|
radius: Math.max(this.data.dim ?? 0, this.data.bright ?? 0)
|
|
});
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/** @inheritDoc */
|
|
_createShapes() {
|
|
this.#updateDarknessSuppression();
|
|
super._createShapes();
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/** @inheritDoc */
|
|
_configure(changes) {
|
|
this.ratio = Math.clamp(Math.abs(this.data.bright) / this.data.radius, 0, 1);
|
|
super._configure(changes);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/** @inheritDoc */
|
|
_getPolygonConfiguration() {
|
|
return Object.assign(super._getPolygonConfiguration(), {useThreshold: true, includeDarkness: true});
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
/* Visibility Testing */
|
|
/* -------------------------------------------- */
|
|
|
|
/**
|
|
* Test whether this LightSource provides visibility to see a certain target object.
|
|
* @param {object} config The visibility test configuration
|
|
* @param {CanvasVisibilityTest[]} config.tests The sequence of tests to perform
|
|
* @param {PlaceableObject} config.object The target object being tested
|
|
* @returns {boolean} Is the target object visible to this source?
|
|
*/
|
|
testVisibility({tests, object}={}) {
|
|
if ( !(this.data.vision && this._canDetectObject(object)) ) return false;
|
|
return tests.some(test => this.shape.contains(test.point.x, test.point.y));
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/**
|
|
* Can this LightSource theoretically detect a certain object based on its properties?
|
|
* This check should not consider the relative positions of either object, only their state.
|
|
* @param {PlaceableObject} target The target object being tested
|
|
* @returns {boolean} Can the target object theoretically be detected by this vision source?
|
|
*/
|
|
_canDetectObject(target) {
|
|
const tgt = target?.document;
|
|
const isInvisible = ((tgt instanceof TokenDocument) && tgt.hasStatusEffect(CONFIG.specialStatusEffects.INVISIBLE));
|
|
return !isInvisible;
|
|
}
|
|
}
|