export class FoWHandler {
|
|
constructor() {
|
|
this.setHooks();
|
|
}
|
|
|
|
setHooks(){
|
|
Hooks.on("drawCanvasVisibility", ()=>{
|
|
this.init();
|
|
canvas.effects.visibility.explored.addChild(this.advancedFogContainer);
|
|
canvas.effects.visibility.explored.addChild(this.revealTokenContainer);
|
|
Hooks.callAll("levelsAdvancedFogInit", this.advancedFogContainer);
|
|
})
|
|
Hooks.on("deleteTile", (tile)=>{
|
|
this.removeTileFogMask(tile.id);
|
|
})
|
|
Hooks.on("createTile", (tile)=>{
|
|
this.createTileFogMask(tile.object);
|
|
})
|
|
Hooks.on("updateTile", (tile)=>{
|
|
this.createTileFogMask(tile.object);
|
|
})
|
|
Hooks.on("deleteToken", (token)=>{
|
|
this.removeBubble(token.id);
|
|
})
|
|
Hooks.on("createToken", (token)=>{
|
|
this.createTokenBubble(token.object);
|
|
})
|
|
Hooks.on("updateToken", (token, updates)=>{
|
|
this.createTokenBubble(token.object);
|
|
})
|
|
|
|
}
|
|
|
|
init() {
|
|
this.advancedFogContainer = new PIXI.Container();
|
|
this.advancedFogContainer.name = "advancedFogContainer";
|
|
this.revealTokenContainer = new PIXI.Container();
|
|
this.revealTokenContainer.name = "revealTokenContainer";
|
|
this.tiles = {};
|
|
this.bubbles = {};
|
|
}
|
|
|
|
createTokenBubble(token) {
|
|
if(!token) return;
|
|
if(!CONFIG.Levels.settings.get("revealTokenInFog")) return;
|
|
if(this.bubbles[token.id]){
|
|
this.revealTokenContainer.removeChild(this.bubbles[token.id]);
|
|
this.bubbles[token.id].destroy();
|
|
delete this.bubbles[token.id];
|
|
}
|
|
const bubble = new PIXI.Graphics();
|
|
bubble.beginFill(0xffffff);
|
|
bubble.drawCircle(0, 0, (Math.max(token.w, token.h)/2)*Math.SQRT2);
|
|
bubble.endFill();
|
|
bubble.token = token;
|
|
Object.defineProperty(bubble, "visible", {
|
|
get: () => {
|
|
return token.visible;
|
|
}
|
|
});
|
|
this.updateBubblePosition(bubble);
|
|
this.revealTokenContainer.addChild(bubble);
|
|
this.bubbles[token.id] = bubble;
|
|
return bubble;
|
|
}
|
|
|
|
lazyCreateBubble(token) {
|
|
if(!this.bubbles[token.id]){
|
|
this.createTokenBubble(token);
|
|
}
|
|
if(this.bubbles[token.id]){
|
|
this.updateBubblePosition(this.bubbles[token.id]);
|
|
}
|
|
}
|
|
|
|
updateBubblePosition(bubble, position) {
|
|
position ??= bubble.token.center;
|
|
bubble.position.set(position.x, position.y);
|
|
}
|
|
|
|
removeBubble(tokenId) {
|
|
if(!this.bubbles[tokenId]) return;
|
|
this.revealTokenContainer.removeChild(this.bubbles[tokenId]);
|
|
this.bubbles[tokenId].destroy();
|
|
delete this.bubbles[tokenId];
|
|
}
|
|
|
|
createTileFogMask(tile) {
|
|
if(!tile?.document?.overhead) return false;
|
|
if(this.tiles[tile.id]){
|
|
this.advancedFogContainer.removeChild(this.tiles[tile.id]);
|
|
try{
|
|
this.tiles[tile.id].destroy();
|
|
}
|
|
catch(e){}
|
|
delete this.tiles[tile.id];
|
|
}
|
|
if(!tile?.mesh?.texture) return;
|
|
const sprite = CONFIG.Levels.helpers.cloneTileMesh(tile);
|
|
Object.defineProperty(sprite, "visible", {
|
|
get: () => {
|
|
if(!CONFIG.Levels.currentToken) return false;
|
|
if(!tile.document.overhead) return false;
|
|
if(tile.document.flags?.levels?.noFogHide) return false;
|
|
if(!CONFIG.Levels.settings.get("fogHiding")) return false;
|
|
const bottom = tile.document.flags?.levels?.rangeBottom ?? -Infinity;
|
|
const top = tile.document.flags?.levels?.rangeTop ?? Infinity;
|
|
if(bottom == -Infinity && top == Infinity) return false;
|
|
const losH = CONFIG.Levels.currentToken.losHeight;
|
|
if(losH < bottom || losH > top) return false;
|
|
return tile.visible;
|
|
}
|
|
})
|
|
this.tiles[tile.id] = sprite;
|
|
this.advancedFogContainer.addChild(sprite);
|
|
return sprite;
|
|
}
|
|
|
|
lazyCreateTileFogMask(tile) {
|
|
if(!this.tiles[tile.id]){
|
|
this.createTileFogMask(tile);
|
|
}
|
|
}
|
|
|
|
removeTileFogMask(tileId) {
|
|
if(!this.tiles[tileId]) return;
|
|
this.advancedFogContainer.removeChild(this.tiles[tileId]);
|
|
this.tiles[tileId].destroy();
|
|
delete this.tiles[tileId];
|
|
}
|
|
}
|