diff --git a/src/module/controls.js b/src/module/controls.js index 53c1adc1..162c5b24 100644 --- a/src/module/controls.js +++ b/src/module/controls.js @@ -42,8 +42,7 @@ function getSceneControlButtons(controls) { title: "CONTROLS.SaveMacro", icon: "fas fa-save", onClick: () => { - let flags = canvas.scene.getFlag("fxmaster", "effects"); - if (!flags) flags = {}; + let flags = canvas.scene?.getFlag("fxmaster", "effects") ?? {}; let objs = Object.values(flags); let img = "icons/svg/windmill.svg"; let name = "Weather"; @@ -66,11 +65,13 @@ function getSceneControlButtons(controls) { title: "CONTROLS.InvertMask", icon: "fas fa-mask", onClick: () => { - const invert = canvas.scene.getFlag("fxmaster", "invert"); - canvas.scene.setFlag("fxmaster", "invert", !invert); + if (canvas.scene) { + const invert = canvas.scene.getFlag("fxmaster", "invert") ?? false; + canvas.scene.setFlag("fxmaster", "invert", !invert); + } }, visible: game.user.isGM, - active: canvas.scene?.getFlag("fxmaster", "invert"), + active: canvas.scene?.getFlag("fxmaster", "invert") ?? false, toggle: true, }, { @@ -92,8 +93,10 @@ function getSceneControlButtons(controls) { title: game.i18n.localize("FXMASTER.Delete"), content: game.i18n.localize("FXMASTER.DeleteConfirm"), yes: () => { - filterManager.removeAll(); - canvas.scene.unsetFlag("fxmaster", "effects"); + if (canvas.scene) { + filterManager.removeAll(); + canvas.scene.unsetFlag("fxmaster", "effects"); + } }, defaultYes: true, }); diff --git a/src/module/filterEffects/FilterManager.js b/src/module/filterEffects/FilterManager.js index 3dfb0c49..e3ee6ab7 100644 --- a/src/module/filterEffects/FilterManager.js +++ b/src/module/filterEffects/FilterManager.js @@ -35,6 +35,9 @@ class FilterManager { * @returns {Promise} A promise that resolves as soon as the filters have been updated */ async update({ skipFading = false } = {}) { + if (!canvas.scene) { + return; + } this.filterInfos = canvas.scene.getFlag("fxmaster", "filters") ?? {}; this.filteredLayers = canvas.scene.getFlag("fxmaster", "filteredLayers") ?? this.filteredLayers; @@ -133,6 +136,9 @@ class FilterManager { * @returns {Promise} A promise that resolves when the filter has been removed from the scene's fxmaster flags */ async removeFilter(name) { + if (!canvas.scene) { + return; + } const filter = this.filters[name]; if (filter === undefined) return; await filter.stop(); @@ -148,6 +154,9 @@ class FilterManager { * flags */ async removeAll() { + if (!canvas.scene) { + return; + } await canvas.scene.unsetFlag("fxmaster", "filters"); } diff --git a/src/module/filterEffects/applications/filters-config.js b/src/module/filterEffects/applications/filters-config.js index 248c46fc..a7f557fb 100644 --- a/src/module/filterEffects/applications/filters-config.js +++ b/src/module/filterEffects/applications/filters-config.js @@ -25,12 +25,12 @@ export class FiltersConfig extends FormApplication { * @return {Object} The data provided to the template when rendering the form */ getData() { - const currentFilters = canvas.scene.getFlag("fxmaster", "filters") ?? {}; + const currentFilters = canvas.scene?.getFlag("fxmaster", "filters") ?? {}; const activeFilters = Object.fromEntries( Object.values(currentFilters).map((filter) => [filter.type, filter.options]), ); - const filteredLayers = canvas.scene.getFlag("fxmaster", "filteredLayers") ?? { + const filteredLayers = canvas.scene?.getFlag("fxmaster", "filteredLayers") ?? { background: true, foreground: true, tokens: true, @@ -102,6 +102,9 @@ export class FiltersConfig extends FormApplication { * @private */ async _updateObject(_, formData) { + if (!canvas.scene) { + return; + } const filtersDB = CONFIG.fxmaster.filters; const filters = Object.fromEntries( diff --git a/src/module/fxmaster.js b/src/module/fxmaster.js index 44d33886..11e92fc8 100644 --- a/src/module/fxmaster.js +++ b/src/module/fxmaster.js @@ -89,7 +89,8 @@ Hooks.on("updateScene", (scene, data) => { if ( !game.settings.get("fxmaster", "enable") || game.settings.get("fxmaster", "disableAll") || - !isOnTargetMigration() + !isOnTargetMigration() || + scene !== canvas.scene ) { return; } @@ -110,7 +111,7 @@ Hooks.on("updateScene", (scene, data) => { }); Hooks.on("dropCanvasData", async (canvas, data) => { - if (!(canvas.activeLayer instanceof SpecialsLayer)) return; + if (!(canvas.activeLayer instanceof SpecialsLayer) || !canvas.scene) return; if (data.type !== "SpecialEffect") return; await new Promise((resolve) => { @@ -160,15 +161,24 @@ Hooks.on("hotbarDrop", (hotbar, data) => { }; }); -Hooks.on("updateDrawing", () => { +Hooks.on("updateDrawing", (drawing) => { + if (drawing.parent !== canvas.scene) { + return; + } canvas.fxmaster.updateMask(); }); -Hooks.on("createDrawing", () => { +Hooks.on("createDrawing", (drawing) => { + if (drawing.parent !== canvas.scene) { + return; + } canvas.fxmaster.updateMask(); }); -Hooks.on("deleteDrawing", () => { +Hooks.on("deleteDrawing", (drawing) => { + if (drawing.parent !== canvas.scene) { + return; + } canvas.fxmaster.updateMask(); }); diff --git a/src/module/hooks.js b/src/module/hooks.js index 1c31224d..024315b8 100644 --- a/src/module/hooks.js +++ b/src/module/hooks.js @@ -17,6 +17,9 @@ export const registerHooks = function () { * @param {{name: string, type: string, options: object}} parameters The parameters that define the named weather effect */ async function onSwitchWeather(parameters) { + if (!canvas.scene) { + return; + } const newEffect = { [parameters.name]: { type: parameters.type, options: parameters.options } }; let flags = (await canvas.scene.getFlag("fxmaster", "effects")) ?? {}; diff --git a/src/module/weatherEffects/WeatherLayer.js b/src/module/weatherEffects/WeatherLayer.js index a995a67f..399b546f 100644 --- a/src/module/weatherEffects/WeatherLayer.js +++ b/src/module/weatherEffects/WeatherLayer.js @@ -40,7 +40,7 @@ export class WeatherLayer extends CanvasLayer { * @type {boolean} */ get shouldMaskToScene() { - return !!canvas.scene.img; + return !!canvas.scene?.img; } _createInvertedMask() { @@ -114,7 +114,7 @@ export class WeatherLayer extends CanvasLayer { } updateMask() { - if (!this.weather) return; + if (!this.weather || !canvas.scene) return; if (this.weather.mask) { this.weather.removeChild(this.weather.mask); @@ -158,6 +158,9 @@ export class WeatherLayer extends CanvasLayer { } async drawWeather({ soft = false } = {}) { + if (!canvas.scene) { + return; + } if (!this.weather) { this.weather = this.addChild(new PIXI.Container()); if (this._sceneMaskFilter) { diff --git a/src/module/weatherEffects/applications/weather-config.js b/src/module/weatherEffects/applications/weather-config.js index d7d62f29..a9cb6291 100644 --- a/src/module/weatherEffects/applications/weather-config.js +++ b/src/module/weatherEffects/applications/weather-config.js @@ -29,7 +29,7 @@ export class WeatherConfig extends FormApplication { * @return {Object} The data provided to the template when rendering the form */ getData() { - const currentEffects = canvas.scene.getFlag("fxmaster", "effects") ?? {}; + const currentEffects = canvas.scene?.getFlag("fxmaster", "effects") ?? {}; const activeEffects = Object.fromEntries( Object.values(currentEffects).map((effect) => [effect.type, effect.options]),