Initial
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user