From d5cdc8948495f3b03b9906d5937825def75a9479 Mon Sep 17 00:00:00 2001 From: Christopher Hampton Date: Wed, 18 Nov 2020 21:22:39 -0500 Subject: [PATCH 001/117] Compatability Fixes --- classes/MaskLayer.js | 2 +- classes/SimplefogConfig.js | 2 +- classes/SimplefogLayer.js | 6 +- js/controls.js | 202 +++++++++++++++++++------------------ js/simplefog.js | 10 +- module.json | 14 +-- 6 files changed, 124 insertions(+), 112 deletions(-) diff --git a/classes/MaskLayer.js b/classes/MaskLayer.js index 75f8741..add2fa8 100644 --- a/classes/MaskLayer.js +++ b/classes/MaskLayer.js @@ -159,7 +159,7 @@ export default class MaskLayer extends CanvasLayer { // Prevent calling update when no lights loaded if (!canvas.sight?.light?.los?.geometry) return; // Update sight layer - canvas.sight.update(); + canvas.sight.refresh(); } /** diff --git a/classes/SimplefogConfig.js b/classes/SimplefogConfig.js index d9e2992..c11f2e6 100644 --- a/classes/SimplefogConfig.js +++ b/classes/SimplefogConfig.js @@ -71,6 +71,6 @@ export default class SimplefogConfig extends FormApplication { } // Update sight layer - canvas.sight.update(); + canvas.sight.refresh(); } } diff --git a/classes/SimplefogLayer.js b/classes/SimplefogLayer.js index 4104dc7..982e849 100644 --- a/classes/SimplefogLayer.js +++ b/classes/SimplefogLayer.js @@ -35,7 +35,7 @@ export default class SimplefogLayer extends MaskLayer { // React to canvas zoom Hooks.on('canvasPan', (canvas, dimensions) => { // Scale blur filter radius to account for zooming - this.blur.blur = this.getSetting('blurRadius') * dimensions.scale; + //this.blur.blur = this.getSetting('blurRadius') * dimensions.scale; }); // React to changes to current scene @@ -194,14 +194,14 @@ export default class SimplefogLayer extends MaskLayer { // React to composite history change if (hasProperty(data, `flags.${this.layername}.history`)) { canvas[this.layername].renderStack(data.flags[this.layername].history); - canvas.sight.update(); + canvas.sight.refresh(); } // React to autoVisibility setting changes if ( hasProperty(data, `flags.${this.layername}.autoVisibility`) || hasProperty(data, `flags.${this.layername}.vThreshold`) ) { - canvas.sight.update(); + canvas.sight.refresh(); } // React to alpha/tint changes if (!game.user.isGM && hasProperty(data, `flags.${this.layername}.playerAlpha`)) { diff --git a/js/controls.js b/js/controls.js index ee2a731..80cf724 100644 --- a/js/controls.js +++ b/js/controls.js @@ -6,95 +6,97 @@ import BrushControls from '../classes/BrushControls.js'; */ Hooks.on('getSceneControlButtons', (controls) => { if (game.user.isGM) { - controls.push({ - name: 'simplefog', - title: game.i18n.localize('SIMPLEFOG.sf'), - icon: 'fas fa-cloud', - layer: 'SimplefogLayer', - tools: [ - { - name: 'simplefogtoggle', - title: game.i18n.localize('SIMPLEFOG.onoff'), - icon: 'fas fa-eye', - onClick: () => { - canvas.simplefog.toggle(); - canvas.sight.update(); + if (canvas != null) { + controls.push({ + name: 'simplefog', + title: game.i18n.localize('SIMPLEFOG.sf'), + icon: 'fas fa-cloud', + layer: 'SimplefogLayer', + tools: [ + { + name: 'simplefogtoggle', + title: game.i18n.localize('SIMPLEFOG.onoff'), + icon: 'fas fa-eye', + onClick: () => { + canvas.simplefog.toggle(); + canvas.sight.refresh(); + }, + active: canvas.simplefog.visible, + toggle: true, }, - active: canvas.simplefog.visible, - toggle: true, - }, - { - name: 'brush', - title: game.i18n.localize('SIMPLEFOG.brushTool'), - icon: 'fas fa-paint-brush', - }, - { - name: 'grid', - title: game.i18n.localize('SIMPLEFOG.gridTool'), - icon: 'fas fa-border-none', - }, - { - name: 'polygon', - title: game.i18n.localize('SIMPLEFOG.polygonTool'), - icon: 'fas fa-draw-polygon', - }, - { - name: 'box', - title: game.i18n.localize('SIMPLEFOG.boxTool'), - icon: 'far fa-square', - }, - { - name: 'ellipse', - title: game.i18n.localize('SIMPLEFOG.ellipseTool'), - icon: 'far fa-circle', - }, - // { - // name: "image", - // title: "Image Tool", - // icon: "far fa-image", - // }, - { - name: 'sceneConfig', - title: game.i18n.localize('SIMPLEFOG.sceneConfig'), - icon: 'fas fa-cog', - onClick: () => { - new SimplefogConfig().render(true); + { + name: 'brush', + title: game.i18n.localize('SIMPLEFOG.brushTool'), + icon: 'fas fa-paint-brush', }, - button: true, - }, - { - name: 'clearfog', - title: game.i18n.localize('SIMPLEFOG.reset'), - icon: 'fas fa-trash', - onClick: () => { - const dg = new Dialog({ - title: game.i18n.localize('SIMPLEFOG.reset'), - content: game.i18n.localize('SIMPLEFOG.confirmReset'), - buttons: { - reset: { - icon: '', - label: 'Reset', - callback: () => canvas.simplefog.resetMask(), - }, - blank: { - icon: '', - label: 'Blank', - callback: () => canvas.simplefog.blankMask(), - }, - cancel: { - icon: '', - label: 'Cancel', + { + name: 'grid', + title: game.i18n.localize('SIMPLEFOG.gridTool'), + icon: 'fas fa-border-none', + }, + { + name: 'polygon', + title: game.i18n.localize('SIMPLEFOG.polygonTool'), + icon: 'fas fa-draw-polygon', + }, + { + name: 'box', + title: game.i18n.localize('SIMPLEFOG.boxTool'), + icon: 'far fa-square', + }, + { + name: 'ellipse', + title: game.i18n.localize('SIMPLEFOG.ellipseTool'), + icon: 'far fa-circle', + }, + // { + // name: "image", + // title: "Image Tool", + // icon: "far fa-image", + // }, + { + name: 'sceneConfig', + title: game.i18n.localize('SIMPLEFOG.sceneConfig'), + icon: 'fas fa-cog', + onClick: () => { + new SimplefogConfig().render(true); + }, + button: true, + }, + { + name: 'clearfog', + title: game.i18n.localize('SIMPLEFOG.reset'), + icon: 'fas fa-trash', + onClick: () => { + const dg = new Dialog({ + title: game.i18n.localize('SIMPLEFOG.reset'), + content: game.i18n.localize('SIMPLEFOG.confirmReset'), + buttons: { + reset: { + icon: '', + label: 'Reset', + callback: () => canvas.simplefog.resetMask(), + }, + blank: { + icon: '', + label: 'Blank', + callback: () => canvas.simplefog.blankMask(), + }, + cancel: { + icon: '', + label: 'Cancel', + }, }, - }, - default: 'reset', - }); - dg.render(true); + default: 'reset', + }); + dg.render(true); + }, + button: true, }, - button: true, - }, - ], - activeTool: 'brush', - }); + ], + activeTool: 'brush', + }); + } } }); @@ -104,20 +106,22 @@ Hooks.on('getSceneControlButtons', (controls) => { */ Hooks.on('renderSceneControls', (controls) => { // Switching to layer - if (controls.activeControl === 'simplefog') { - // Open brush tools if not already open - if (!$('#simplefog-brush-controls').length) new BrushControls().render(true); - // Set active tool - const tool = controls.controls.find((control) => control.name === 'simplefog').activeTool; - canvas.simplefog.setActiveTool(tool); - } - // Switching away from layer - else { - // Clear active tool - canvas.simplefog.clearActiveTool(); - // Remove brush tools if open - const bc = $('#simplefog-brush-controls'); - if (bc) bc.remove(); + if (canvas != null) { + if (controls.activeControl == 'simplefog') { + // Open brush tools if not already open + if (!$('#simplefog-brush-controls').length) new BrushControls().render(true); + // Set active tool + const tool = controls.controls.find((control) => control.name === 'simplefog').activeTool; + canvas.simplefog.setActiveTool(tool); + } + // Switching away from layer + else { + // Clear active tool + canvas.simplefog.clearActiveTool(); + // Remove brush tools if open + const bc = $('#simplefog-brush-controls'); + if (bc) bc.remove(); + } } }); diff --git a/js/simplefog.js b/js/simplefog.js index 896847a..2bb2916 100644 --- a/js/simplefog.js +++ b/js/simplefog.js @@ -18,10 +18,18 @@ Hooks.once('canvasInit', () => { // Add SimplefogLayer to canvas const layerct = canvas.stage.children.length; canvas.simplefog = canvas.stage.addChildAt(new SimplefogLayer(), layerct); + canvas.simplefog.draw(); }); Hooks.on('canvasInit', () => { canvas.simplefog.init(); + + let theLayers = Canvas.layers; + theLayers.simplefog = SimplefogLayer; + + Object.defineProperty(Canvas, 'layers', {get: function() { + return theLayers + }}) }); /* @@ -37,7 +45,7 @@ Hooks.once('ready', () => { origUpdate.call(this, ...args); sightLayerUpdate(); }; - canvas.sight.update(); + canvas.sight.refresh(); } else { const origUpdate = canvas.sight.refresh; diff --git a/module.json b/module.json index 5d11fbe..a099c2a 100644 --- a/module.json +++ b/module.json @@ -2,8 +2,8 @@ "name": "simplefog", "title": "Simplefog - Manual Fog of War", "description": "Simplefog allows you to draw fog of war manually, optionally automatically hiding and revealing tokens underneath based on opacity. It provides a number of tools to quickly draw and erase fog in various shapes - brush, rectangles, ellipses, polygons or to reveal tiles you click/drag on the grid.", - "author": "Vance Cole", - "version": "0.1.11", + "author": "Vance Cole and Chris Hampton (Updates)", + "version": "0.1.12", "minimumCoreVersion": "0.6.4", "compatibleCoreVersion": "0.7.3", "esmodules": [ @@ -20,9 +20,9 @@ "path": "lang/en.json" } ], - "url": "https://github.com/VanceCole/simplefog", - "manifest": "https://raw.githubusercontent.com/VanceCole/simplefog/master/module.json", - "readme": "https://github.com/VanceCole/simplefog/blob/master/README.md", - "changelog": "https://github.com/VanceCole/simplefog/blob/master/changelog.md", - "download": "https://github.com/VanceCole/simplefog/releases/download/0.1.11/simplefog.zip" + "url": "https://github.com/crhampton1/simplefog", + "manifest": "https://raw.githubusercontent.com/crhampton1/simplefog/master/module.json", + "readme": "https://github.com/crhampton1/simplefog/blob/master/README.md", + "changelog": "https://github.com/crhampton1/simplefog/blob/master/changelog.md", + "download": "https://github.com/crhampton1/simplefog/releases/download/0.1.12/simplefog.zip" } \ No newline at end of file From 366fbee82ad38b039acdac559008c7c3615c2ba9 Mon Sep 17 00:00:00 2001 From: Christopher Hampton Date: Fri, 20 Nov 2020 19:27:13 -0500 Subject: [PATCH 002/117] Fixed layer not showing on top and brush controls showing too early --- classes/MaskLayer.js | 7 +++++++ classes/SimplefogLayer.js | 1 + js/controls.js | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/classes/MaskLayer.js b/classes/MaskLayer.js index add2fa8..e8eaa4f 100644 --- a/classes/MaskLayer.js +++ b/classes/MaskLayer.js @@ -31,6 +31,13 @@ export default class MaskLayer extends CanvasLayer { }; } + static get layerOptions() { + //@ts-ignore + return mergeObject(super.layerOptions, { + zIndex: 220, // Above imageFog + }); +} + /* -------------------------------------------- */ /* Init */ /* -------------------------------------------- */ diff --git a/classes/SimplefogLayer.js b/classes/SimplefogLayer.js index 982e849..6fa3215 100644 --- a/classes/SimplefogLayer.js +++ b/classes/SimplefogLayer.js @@ -10,6 +10,7 @@ import { hexObjsToArr, hexToPercent } from '../js/helpers.js'; export default class SimplefogLayer extends MaskLayer { constructor() { super('simplefog'); + // Register event listerenrs this._registerMouseListeners(); this._registerKeyboardListeners(); diff --git a/js/controls.js b/js/controls.js index 80cf724..9791764 100644 --- a/js/controls.js +++ b/js/controls.js @@ -107,7 +107,7 @@ Hooks.on('getSceneControlButtons', (controls) => { Hooks.on('renderSceneControls', (controls) => { // Switching to layer if (canvas != null) { - if (controls.activeControl == 'simplefog') { + if (controls.activeControl == 'simplefog' && controls.activeTool != undefined) { // Open brush tools if not already open if (!$('#simplefog-brush-controls').length) new BrushControls().render(true); // Set active tool From a1b6a526e0f2602ee77f71c4df3513b61e600031 Mon Sep 17 00:00:00 2001 From: Christopher Hampton Date: Fri, 20 Nov 2020 19:35:12 -0500 Subject: [PATCH 003/117] Fixed esc bug --- classes/MaskLayer.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/classes/MaskLayer.js b/classes/MaskLayer.js index e8eaa4f..55d2236 100644 --- a/classes/MaskLayer.js +++ b/classes/MaskLayer.js @@ -72,6 +72,9 @@ export default class MaskLayer extends CanvasLayer { this.blur.quality = this.getSetting('blurQuality'); this.filters = [this.blur]; + //So you can hit escape on the keyboard and it will bring up the menu + this._controlled = {} + this.maskTexture = MaskLayer.getMaskTexture(); this.layer.mask = new PIXI.Sprite(this.maskTexture); this.addChild(this.layer.mask); From 91d0b926b62d03d31d4b6e60b1214efc184f1204 Mon Sep 17 00:00:00 2001 From: Christopher Hampton Date: Fri, 20 Nov 2020 19:35:57 -0500 Subject: [PATCH 004/117] updated to 0.1.13 --- module.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.json b/module.json index a099c2a..d20a4b7 100644 --- a/module.json +++ b/module.json @@ -24,5 +24,5 @@ "manifest": "https://raw.githubusercontent.com/crhampton1/simplefog/master/module.json", "readme": "https://github.com/crhampton1/simplefog/blob/master/README.md", "changelog": "https://github.com/crhampton1/simplefog/blob/master/changelog.md", - "download": "https://github.com/crhampton1/simplefog/releases/download/0.1.12/simplefog.zip" + "download": "https://github.com/crhampton1/simplefog/releases/download/0.1.13/simplefog.zip" } \ No newline at end of file From 186d5d0cfcff8033bef3c5b82cdbd7d12bdd2e1f Mon Sep 17 00:00:00 2001 From: Christopher Hampton Date: Fri, 20 Nov 2020 19:41:34 -0500 Subject: [PATCH 005/117] Readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 685f7e5..6c5657f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ # Simplefog A module for [FoundryVTT](https://foundryvtt.com) that lets you draw fog of war manually. +# Update +It appears the original maintainer has abandoned the original project. I have taken it over and will continue to keep this running. This was under the MIT license and continues to be so. + ## Feature overview video [![Feature Overview](https://img.youtube.com/vi/gTt6FDQ7iQA/hqdefault.jpg)](https://www.youtube.com/watch?v=gTt6FDQ7iQA) From f2d32b683fbaeafa8b50ee7e0a0a0b40b2287dcd Mon Sep 17 00:00:00 2001 From: Christopher Hampton Date: Fri, 20 Nov 2020 19:45:05 -0500 Subject: [PATCH 006/117] Updated --- module.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module.json b/module.json index d20a4b7..72d70d1 100644 --- a/module.json +++ b/module.json @@ -3,9 +3,9 @@ "title": "Simplefog - Manual Fog of War", "description": "Simplefog allows you to draw fog of war manually, optionally automatically hiding and revealing tokens underneath based on opacity. It provides a number of tools to quickly draw and erase fog in various shapes - brush, rectangles, ellipses, polygons or to reveal tiles you click/drag on the grid.", "author": "Vance Cole and Chris Hampton (Updates)", - "version": "0.1.12", + "version": "0.1.13", "minimumCoreVersion": "0.6.4", - "compatibleCoreVersion": "0.7.3", + "compatibleCoreVersion": "0.7.7", "esmodules": [ "js/simplefog.js", "js/controls.js" From 012b3264400289270f0d925e8cdadb23d9cd9e65 Mon Sep 17 00:00:00 2001 From: Christopher Hampton Date: Mon, 23 Nov 2020 20:41:22 -0500 Subject: [PATCH 007/117] Updated Module --- module.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/module.json b/module.json index 72d70d1..b3e6ddf 100644 --- a/module.json +++ b/module.json @@ -20,9 +20,9 @@ "path": "lang/en.json" } ], - "url": "https://github.com/crhampton1/simplefog", - "manifest": "https://raw.githubusercontent.com/crhampton1/simplefog/master/module.json", - "readme": "https://github.com/crhampton1/simplefog/blob/master/README.md", - "changelog": "https://github.com/crhampton1/simplefog/blob/master/changelog.md", - "download": "https://github.com/crhampton1/simplefog/releases/download/0.1.13/simplefog.zip" + "url": "https://github.com/League-of-Foundry-Developers/simplefog", + "manifest": "https://raw.githubusercontent.com/League-of-Foundry-Developers/simplefog/master/module.json", + "readme": "https://github.com/League-of-Foundry-Developers/simplefog/blob/master/README.md", + "changelog": "https://github.com/League-of-Foundry-Developers/simplefog/blob/master/changelog.md", + "download": "https://github.com/League-of-Foundry-Developers/simplefog/releases/download/0.1.13/simplefog.zip" } \ No newline at end of file From 125fd916cbe8ae30882520d6281d2d4202cf3a0f Mon Sep 17 00:00:00 2001 From: Christopher Hampton Date: Mon, 23 Nov 2020 20:44:50 -0500 Subject: [PATCH 008/117] Forgot to update version --- module.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.json b/module.json index b3e6ddf..5f40e69 100644 --- a/module.json +++ b/module.json @@ -3,7 +3,7 @@ "title": "Simplefog - Manual Fog of War", "description": "Simplefog allows you to draw fog of war manually, optionally automatically hiding and revealing tokens underneath based on opacity. It provides a number of tools to quickly draw and erase fog in various shapes - brush, rectangles, ellipses, polygons or to reveal tiles you click/drag on the grid.", "author": "Vance Cole and Chris Hampton (Updates)", - "version": "0.1.13", + "version": "0.1.14", "minimumCoreVersion": "0.6.4", "compatibleCoreVersion": "0.7.7", "esmodules": [ From 44abef0f1af66d981dcd0c45169510fbcb2898b6 Mon Sep 17 00:00:00 2001 From: ardittristan <42787508+ardittristan@users.noreply.github.com> Date: Thu, 26 Nov 2020 02:48:22 +0100 Subject: [PATCH 009/117] fix manifest dl link --- module.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module.json b/module.json index 5f40e69..4d4e1e2 100644 --- a/module.json +++ b/module.json @@ -24,5 +24,5 @@ "manifest": "https://raw.githubusercontent.com/League-of-Foundry-Developers/simplefog/master/module.json", "readme": "https://github.com/League-of-Foundry-Developers/simplefog/blob/master/README.md", "changelog": "https://github.com/League-of-Foundry-Developers/simplefog/blob/master/changelog.md", - "download": "https://github.com/League-of-Foundry-Developers/simplefog/releases/download/0.1.13/simplefog.zip" -} \ No newline at end of file + "download": "https://github.com/League-of-Foundry-Developers/simplefog/releases/download/0.1.14/simplefog.zip" +} From 35848e942421de7a20b85147ab5f112c527a1965 Mon Sep 17 00:00:00 2001 From: Andrew Krigline Date: Sat, 28 Nov 2020 21:13:37 -0500 Subject: [PATCH 010/117] Update README.md --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6c5657f..c65865d 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,12 @@ A module for [FoundryVTT](https://foundryvtt.com) that lets you draw fog of war # Update It appears the original maintainer has abandoned the original project. I have taken it over and will continue to keep this running. This was under the MIT license and continues to be so. +### Installation +Use the following manifest URL to install this fork of the original module after you have uninstalled the original module. +``` +https://raw.githubusercontent.com/League-of-Foundry-Developers/simplefog/master/module.json +``` + ## Feature overview video [![Feature Overview](https://img.youtube.com/vi/gTt6FDQ7iQA/hqdefault.jpg)](https://www.youtube.com/watch?v=gTt6FDQ7iQA) @@ -50,4 +56,4 @@ Allows you to set various options which affect the entire layer for the current - Currently incompatible with the module "GM Scene Background" when a GM layer is active # Bugs and Feature Requests -Please ping me on discord @vance#1935 \ No newline at end of file +Please create a github issue on this repository. From 0ba54d43b4222fff79098d16181a64dbcdab39d0 Mon Sep 17 00:00:00 2001 From: akrigline Date: Sun, 11 Oct 2020 11:49:51 -0400 Subject: [PATCH 011/117] allow GMs to set an image overlay for fog layer --- README.md | 3 ++- classes/MaskLayer.js | 17 ++++++++++++-- classes/SimplefogConfig.js | 1 + classes/SimplefogLayer.js | 26 +++++++++++++++++---- docs/simplefog-options.png | Bin 555039 -> 555039 bytes js/helpers.js | 2 +- lang/en.json | 5 +++- module.json | 2 +- templates/scene-config.html | 44 ++++++++++++++++++++++++------------ 9 files changed, 74 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 6c5657f..f96a475 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,13 @@ Encounter Library did a review of Simplefog which explains how it works much bet - Click the orange handle to finish your drawing, or right click to cancel - Grid tool - Reveals any grid square you drag across, works for both Hex and Square grids +- Add an image to the Simplefog layer which overlays the selected tint for both GMs and Players. ![Tools Palette](docs/simplefog-tools.jpg?raw=true "Tools Palette") ## Scene Configuration Allows you to set various options which affect the entire layer for the current scene +- Set an image overlay for the fog on both player and GM screens. - Set the opacity of the entire fog layer for both players and GMs - Animate transitions in opacity, allowing for effects such as "Fade to Black" - Change tint of the fog for both player and GM, for example to indicate a green poison cloud @@ -44,7 +46,6 @@ Allows you to set various options which affect the entire layer for the current - Reveal only if entire token visible - Reveal if any part of token is visible - Brush Smoothing / Interpolation -- Image based fog import - Sepia / monochrome filters - Add indicator icon of player controlled icons hidden under fog - Currently incompatible with the module "GM Scene Background" when a GM layer is active diff --git a/classes/MaskLayer.js b/classes/MaskLayer.js index 55d2236..949c8a4 100644 --- a/classes/MaskLayer.js +++ b/classes/MaskLayer.js @@ -51,8 +51,10 @@ export default class MaskLayer extends CanvasLayer { * filters - Holds filters such as blur applied to the layer * layer.mask - PIXI Sprite wrapping the renderable mask * maskTexture - renderable texture that holds the actual mask data + * fogSprite - PIXI Sprite that holds the image applied over the fog color */ async maskInit() { + const d = canvas.dimensions; // Check if masklayer is flagged visible let v = this.getSetting('visible'); if (v === undefined) v = false; @@ -70,21 +72,32 @@ export default class MaskLayer extends CanvasLayer { this.blur.repeatEdgePixels = true; this.blur.blur = this.getSetting('blurRadius'); this.blur.quality = this.getSetting('blurQuality'); - this.filters = [this.blur]; //So you can hit escape on the keyboard and it will bring up the menu this._controlled = {} this.maskTexture = MaskLayer.getMaskTexture(); - this.layer.mask = new PIXI.Sprite(this.maskTexture); + this.maskSprite = new PIXI.Sprite(this.maskTexture); + + this.layer.mask = this.maskSprite; this.addChild(this.layer.mask); this.setFill(); + this.layer.filters = [this.blur]; + // Allow zIndex prop to function for items on this layer this.sortableChildren = true; // Render initial history stack this.renderStack(); + + // apply Texture Sprite to fog layer after we renderStack to prevent revealing the map + this.fogSprite = this.addChild(new PIXI.Sprite()); + this.fogSprite.position.set(d.sceneRect.x, d.sceneRect.y); + this.fogSprite.width = d.sceneRect.width; + this.fogSprite.height = d.sceneRect.height; + this.fogSprite.mask = this.maskSprite; + this.setFogTexture(); } /* -------------------------------------------- */ diff --git a/classes/SimplefogConfig.js b/classes/SimplefogConfig.js index c11f2e6..10c5cd4 100644 --- a/classes/SimplefogConfig.js +++ b/classes/SimplefogConfig.js @@ -36,6 +36,7 @@ export default class SimplefogConfig extends FormApplication { autoVisibility: canvas.simplefog.getSetting('autoVisibility'), autoVisGM: canvas.simplefog.getSetting('autoVisGM'), vThreshold: Math.round(canvas.simplefog.getSetting('vThreshold') * 100), + fogTextureFilePath: canvas.simplefog.getSetting('fogTextureFilePath'), }; } diff --git a/classes/SimplefogLayer.js b/classes/SimplefogLayer.js index 6fa3215..54e8255 100644 --- a/classes/SimplefogLayer.js +++ b/classes/SimplefogLayer.js @@ -5,7 +5,7 @@ import MaskLayer from './MaskLayer.js'; import { Layout } from '../libs/hexagons.js'; -import { hexObjsToArr, hexToPercent } from '../js/helpers.js'; +import { hexObjsToArr, hexToPercent, simplefogLog } from '../js/helpers.js'; export default class SimplefogLayer extends MaskLayer { constructor() { @@ -18,6 +18,7 @@ export default class SimplefogLayer extends MaskLayer { this.DEFAULTS = Object.assign(this.DEFAULTS, { gmAlpha: 0.6, gmTint: '0x000000', + fogTextureFilePath: '', playerAlpha: 1, playerTint: '0x000000', transition: true, @@ -141,6 +142,14 @@ export default class SimplefogLayer extends MaskLayer { return alpha; } + async setFogTexture(fogTextureFilePath = this.getSetting('fogTextureFilePath')) { + if (!fogTextureFilePath) return; + + const texture = await loadTexture(fogTextureFilePath); + + this.fogSprite.texture = texture; + } + /** * Sets the scene's alpha for the primary layer. * @param alpha {Number} 0-1 opacity representation @@ -148,10 +157,12 @@ export default class SimplefogLayer extends MaskLayer { */ async setAlpha(alpha, skip = false) { // If skip is false, do not transition and just set alpha immediately - if (skip || !this.getSetting('transition')) this.layer.alpha = alpha; + if (skip || !this.getSetting('transition')) { + this.alpha = alpha; + } // Loop until transition is complete else { - const start = this.layer.alpha; + const start = this.alpha; const dist = start - alpha; const fps = 60; const speed = this.getSetting('transitionSpeed'); @@ -162,11 +173,11 @@ export default class SimplefogLayer extends MaskLayer { // Delay 1 frame before updating again // eslint-disable-next-line no-await-in-loop await new Promise((resolve) => setTimeout(resolve, frame)); - this.layer.alpha -= rate; + this.alpha -= rate; f -= 1; } // Reset target alpha in case loop overshot a bit - this.layer.alpha = alpha; + this.alpha = alpha; } } @@ -213,6 +224,11 @@ export default class SimplefogLayer extends MaskLayer { } if (!game.user.isGM && hasProperty(data, `flags.${this.layername}.playerTint`)) canvas[this.layername].setTint(data.flags[this.layername].playerTint); if (game.user.isGM && hasProperty(data, `flags.${this.layername}.gmTint`)) canvas[this.layername].setTint(data.flags[this.layername].gmTint); + // React to texture changes + if (hasProperty(data, `flags.${this.layername}.fogTextureFilePath`)) { + simplefogLog('has fogTextureFilePath') + canvas[this.layername].setFogTexture(data.flags[this.layername].fogTextureFilePath); + } } /** diff --git a/docs/simplefog-options.png b/docs/simplefog-options.png index 04c07ffcbcb00b1a456f6dcd510abbeae43a9dc7..9e5dce3cd09b7c5105c757bc7fc94ccdc62e23fb 100644 GIT binary patch delta 365045 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