diff --git a/README.md b/README.md index 51a84a1..f53be1f 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,14 @@ This module adds a toggleable mode for GMs that ... - increases the brightness of the scene, - reveals the fog of war, and -- shows all tokens even if they wouldn't be visible normally from the perspective of the selected token. +- shows all tokens even if they wouldn't be visible normally from the perspective of the controlled token(s). Tokens that wouldn't be visible normally are highlighted by a hatched overlay. ![demo](demo.png) -The mode is toggled by a keybinding (default: `CTRL+G`) or by right-clicking the lighting controls button. The light bulb icon of this button indicates whether it's active (: inactive; : active). +The mode can be toggled by a keybinding (default: `CTRL+G`), by right-clicking the lighting controls button, or with a script macro. The light bulb icon of the lighting controls button indicates whether it's active (: inactive; : active). + +```js +game.settings.set("gm-vision", "active", !game.settings.get("gm-vision", "active")); +``` diff --git a/demo.png b/demo.png index b8a2b2a..bc8615a 100644 Binary files a/demo.png and b/demo.png differ diff --git a/module.json b/module.json index 6871c5f..c72f24b 100644 --- a/module.json +++ b/module.json @@ -8,7 +8,7 @@ "email": "dev7355608@gmail.com" } ], - "version": "1.1.0", + "version": "1.1.1", "compatibility": { "minimum": "10", "verified": "12" @@ -16,18 +16,10 @@ "scripts": [ "script.js" ], - "relationships": { - "requires": [ - { - "id": "lib-wrapper", - "type": "module" - } - ] - }, "url": "https://github.com/dev7355608/gm-vision", "manifest": "https://github.com/dev7355608/gm-vision/releases/latest/download/module.json", - "download": "https://github.com/dev7355608/gm-vision/releases/download/v1.1.0/module.zip", - "changelog": "https://github.com/dev7355608/gm-vision/releases/tag/v1.1.0", + "download": "https://github.com/dev7355608/gm-vision/releases/download/v1.1.1/module.zip", + "changelog": "https://github.com/dev7355608/gm-vision/releases/tag/v1.1.1", "bugs": "https://github.com/dev7355608/gm-vision/issues", "readme": "https://raw.githubusercontent.com/dev7355608/gm-vision/main/README.md", "license": "https://raw.githubusercontent.com/dev7355608/gm-vision/main/LICENSE" diff --git a/script.js b/script.js index a2fae06..c6d1c77 100644 --- a/script.js +++ b/script.js @@ -13,7 +13,13 @@ Hooks.once("init", () => { } active = value; - canvas.perception.update({ refreshVision: true }, true); + + if (foundry.utils.isNewerVersion(game.version, 12)) { + canvas.perception.update({ refreshVision: true }); + } else { + canvas.perception.update({ refreshVision: true }, true); + } + ui.controls.initialize(); } }); @@ -59,66 +65,47 @@ Hooks.once("init", () => { return; } - lighting.addEventListener("contextmenu", (event) => { + lighting.addEventListener("contextmenu", event => { event.preventDefault(); game.settings.set("gm-vision", "active", !active); }); }); + let revealFog; + Hooks.on("drawCanvasVisibility", layer => { - layer.gmVision = layer.addChild( + revealFog = layer.addChild( new PIXI.LegacyGraphics() .beginFill(0xFFFFFF) - .drawShape(canvas.dimensions.rect.clone()) + .drawShape(canvas.dimensions.rect) .endFill()); - layer.gmVision.visible = false; + revealFog.visible = false; }); - Hooks.on("sightRefresh", layer => { - layer.gmVision.visible = active; + Hooks.on("sightRefresh", () => { + revealFog.visible = active; canvas.effects.illumination.filter.uniforms.gmVision = active; }); - if (foundry.utils.isNewerVersion(11, game.version)) { - libWrapper.register( - "gm-vision", - "CanvasVisibility.prototype.restrictVisibility", - function (wrapped) { - for (const token of canvas.tokens.placeables) { - token.gmVisible = false; - } - - return wrapped(); - }, - libWrapper.WRAPPER, - { perf_mode: libWrapper.PERF_FAST } - ); - } - - libWrapper.register( - "gm-vision", - "Token.prototype.isVisible", - function (wrapped) { + CONFIG.Token.objectClass = class extends CONFIG.Token.objectClass { + /** @override */ + get isVisible() { + // Fixes #9521 in V10 this.detectionFilter = undefined; - const visible = wrapped(); + const visible = super.isVisible; if (!visible && active || visible && this.document.hidden) { - this.detectionFilter = filter; - this.gmVisible = true; + this.detectionFilter = hatchFilter; return true; } - this.gmVisible = false; - return visible; - }, - libWrapper.WRAPPER, - { perf_mode: libWrapper.PERF_FAST } - ); + } + }; - class GMVisionDetectionFilter extends AbstractBaseFilter { + class HatchFilter extends AbstractBaseFilter { /** @override */ static vertexShader = `\ attribute vec2 aVertexPosition; @@ -164,16 +151,21 @@ Hooks.once("init", () => { origin: { x: 0, y: 0 }, thickness: 1 }; - } - const filter = GMVisionDetectionFilter.create(); + /** @override */ + apply(filterManager, input, output, clearMode, currentState) { + const uniforms = this.uniforms; + const worldTransform = currentState.target.worldTransform; - Hooks.on("canvasPan", (canvas, { x, y, scale }) => { - const { width, height } = canvas.app.screen; - filter.uniforms.origin.x = width / 2 - x * scale; - filter.uniforms.origin.y = height / 2 - y * scale; - filter.uniforms.thickness = (canvas.dimensions.size / 25) * scale; - }); + uniforms.origin.x = worldTransform.tx; + uniforms.origin.y = worldTransform.ty; + uniforms.thickness = canvas.dimensions.size / 25 * canvas.stage.scale.x; + + super.apply(filterManager, input, output, clearMode, currentState); + } + } + + const hatchFilter = HatchFilter.create(); VisualEffectsMaskingFilter.defaultUniforms.gmVision = false; VisualEffectsMaskingFilter.POST_PROCESS_TECHNIQUES.GM_VISION = { @@ -181,33 +173,23 @@ Hooks.once("init", () => { glsl: `if (gmVision) finalColor.rgb = sqrt(finalColor.rgb) * 0.5 + 0.5;` }; - libWrapper.register( - "gm-vision", - "VisualEffectsMaskingFilter.fragmentHeader", - function (wrapped, filterMode) { - let header = wrapped(filterMode); + VisualEffectsMaskingFilter.fragmentHeader = (wrapped => function (filterMode) { + let header = wrapped.call(this, filterMode); - if (filterMode === VisualEffectsMaskingFilter.FILTER_MODES.ILLUMINATION) { - header += "\nuniform bool gmVision;\n"; - } + if (filterMode === VisualEffectsMaskingFilter.FILTER_MODES.ILLUMINATION) { + header += "\nuniform bool gmVision;\n"; + } - return header; - }, - libWrapper.WRAPPER - ); - - libWrapper.register( - "gm-vision", - "VisualEffectsMaskingFilter.fragmentShader", - function (wrapped, filterMode, postProcessModes = []) { - if (filterMode === VisualEffectsMaskingFilter.FILTER_MODES.ILLUMINATION) { - postProcessModes = [...postProcessModes, "GM_VISION"]; - } + return header; + })(VisualEffectsMaskingFilter.fragmentHeader); + + VisualEffectsMaskingFilter.fragmentShader = (wrapped => function (filterMode, postProcessModes = []) { + if (filterMode === VisualEffectsMaskingFilter.FILTER_MODES.ILLUMINATION) { + postProcessModes = [...postProcessModes, "GM_VISION"]; + } - return wrapped(filterMode, postProcessModes); - }, - libWrapper.WRAPPER - ); + return wrapped.call(this, filterMode, postProcessModes); + })(VisualEffectsMaskingFilter.fragmentShader); }; if (foundry.utils.isNewerVersion(game.version, 11)) {