Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cf2d3d8a34 | |||
| 8d943230ef | |||
| fc13f10f47 |
@@ -1,4 +1,12 @@
|
|||||||
## v1.1.0
|
## v1.1.0
|
||||||
|
### New features
|
||||||
|
- Draw outlines around Door Control icons to increase their visibility
|
||||||
|
- Execute a macro when someone interacts with a door
|
||||||
|
|
||||||
|
### Other
|
||||||
|
- Secret doors are now tinted black instead of dark grey.
|
||||||
|
- Setting hints will now be shown below the title of the setting (before it was above)
|
||||||
|
|
||||||
### New features
|
### New features
|
||||||
- Tint secret doors grey for the GM to differentiate them from regular doors
|
- Tint secret doors grey for the GM to differentiate them from regular doors
|
||||||
- Toggle doors between secret and normal with ctrl+click
|
- Toggle doors between secret and normal with ctrl+click
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ Makes doors smarter. Allows doors to synchronize across multiple scenes and send
|
|||||||
|
|
||||||
Door Control icons will be rendered the same size in every scene, regardless of the configured grid size. The size of the icons is configurable.
|
Door Control icons will be rendered the same size in every scene, regardless of the configured grid size. The size of the icons is configurable.
|
||||||
|
|
||||||
|
### Door Control Outline
|
||||||
|

|
||||||
|
|
||||||
|
Door Control icons will be rendered with an outline to improve their visibility on bright backgrounds.
|
||||||
|
|
||||||
### Tint Secret Doors
|
### Tint Secret Doors
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
23
lang/en.json
23
lang/en.json
@@ -1,6 +1,10 @@
|
|||||||
{
|
{
|
||||||
"smart-doors": {
|
"smart-doors": {
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"doorControlOutline": {
|
||||||
|
"name": "Door Control Outline",
|
||||||
|
"hint": "Draw outlines around Door Control icons to increase their visiblity"
|
||||||
|
},
|
||||||
"doorControlSizeFactor": {
|
"doorControlSizeFactor": {
|
||||||
"name": "Door Control Size Factor",
|
"name": "Door Control Size Factor",
|
||||||
"hint": "Defines by which factor the size of the door control icons should be scaled up"
|
"hint": "Defines by which factor the size of the door control icons should be scaled up"
|
||||||
@@ -13,6 +17,10 @@
|
|||||||
"name": "Locked Door Alert",
|
"name": "Locked Door Alert",
|
||||||
"hint": "Send a message in chat when a player tried to open a locked door"
|
"hint": "Send a message in chat when a player tried to open a locked door"
|
||||||
},
|
},
|
||||||
|
"macros": {
|
||||||
|
"name": "Door Interaction Macros",
|
||||||
|
"hint": "Trigger a macro when a door is being interacted with"
|
||||||
|
},
|
||||||
"synchronizedDoors": {
|
"synchronizedDoors": {
|
||||||
"name": "Synchronized Doors",
|
"name": "Synchronized Doors",
|
||||||
"hint": "Synchronize the state of configured doors"
|
"hint": "Synchronize the state of configured doors"
|
||||||
@@ -23,7 +31,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ui": {
|
"ui": {
|
||||||
|
"form": {
|
||||||
|
"macroExecuteEverywhere": {
|
||||||
|
"name": "Execute on all clients",
|
||||||
|
"hint": "If disabled the macro will be executed on the GMs client"
|
||||||
|
},
|
||||||
|
"macroName": {
|
||||||
|
"name": "Macro Name",
|
||||||
|
"hint": "The name of the macro that should be executed when this door is interacted with. No macro is executed if left blank."
|
||||||
|
},
|
||||||
|
"macroArguments": {
|
||||||
|
"name": "Marco Parameters",
|
||||||
|
"hint": "The parameters passed to the macro. Any JSON string is valid."
|
||||||
|
}
|
||||||
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
|
"argsInvalidJson": "The macro arguments must be valid JSON. See console for details.",
|
||||||
"migrating": "Migrating Smart Doors to version {version}. Please don't close the application.",
|
"migrating": "Migrating Smart Doors to version {version}. Please don't close the application.",
|
||||||
"migrationDone": "Smart Doors successfully migrated to version {version}.",
|
"migrationDone": "Smart Doors successfully migrated to version {version}.",
|
||||||
"unknownVersion": "Smart Doors migration failed with the error: Unkown Version {version}. Please report this to the Smart Doors issue tracker. To prevent possible data loss don't use this plugin until this error is fixed."
|
"unknownVersion": "Smart Doors migration failed with the error: Unkown Version {version}. Please report this to the Smart Doors issue tracker. To prevent possible data loss don't use this plugin until this error is fixed."
|
||||||
|
|||||||
152
lib/outline_filter/outline_filter.js
Normal file
152
lib/outline_filter/outline_filter.js
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
This is a modified version of the PIXI outline filter (https://github.com/pixijs/pixi-filters/tree/master/filters/outline)
|
||||||
|
and is licensed under the MIT license.
|
||||||
|
|
||||||
|
The MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2013-2017 Mathew Groves, Chad Engler
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
const vertex = `attribute vec2 aVertexPosition;
|
||||||
|
attribute vec2 aTextureCoord;
|
||||||
|
|
||||||
|
uniform mat3 projectionMatrix;
|
||||||
|
|
||||||
|
varying vec2 vTextureCoord;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);
|
||||||
|
vTextureCoord = aTextureCoord;
|
||||||
|
}`
|
||||||
|
|
||||||
|
const fragment = `varying vec2 vTextureCoord;
|
||||||
|
uniform sampler2D uSampler;
|
||||||
|
|
||||||
|
uniform vec2 thickness;
|
||||||
|
uniform vec4 outlineColor;
|
||||||
|
uniform vec4 filterClamp;
|
||||||
|
|
||||||
|
const float DOUBLE_PI = 3.14159265358979323846264 * 2.;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
vec4 ownColor = texture2D(uSampler, vTextureCoord);
|
||||||
|
vec4 curColor;
|
||||||
|
float maxAlpha = 0.;
|
||||||
|
vec2 displaced;
|
||||||
|
for (float angle = 0.; angle <= DOUBLE_PI; angle += \${angleStep}) {
|
||||||
|
displaced.x = vTextureCoord.x + thickness.x * cos(angle);
|
||||||
|
displaced.y = vTextureCoord.y + thickness.y * sin(angle);
|
||||||
|
curColor = texture2D(uSampler, clamp(displaced, filterClamp.xy, filterClamp.zw));
|
||||||
|
maxAlpha = max(maxAlpha, curColor.a);
|
||||||
|
}
|
||||||
|
float resultAlpha = max(maxAlpha, ownColor.a);
|
||||||
|
// Original line:
|
||||||
|
// gl_FragColor = vec4((ownColor.rgb + outlineColor.rgb * (1. - ownColor.a)) * resultAlpha, resultAlpha);
|
||||||
|
gl_FragColor = vec4(ownColor.rgb + outlineColor.rgb * (resultAlpha - ownColor.a), resultAlpha);
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OutlineFilter, originally by mishaa
|
||||||
|
* http://www.html5gamedevs.com/topic/10640-outline-a-sprite-change-certain-colors/?p=69966
|
||||||
|
* http://codepen.io/mishaa/pen/emGNRB<br>
|
||||||
|
* 
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
* @extends PIXI.Filter
|
||||||
|
* @memberof PIXI.filters
|
||||||
|
* @see {@link https://www.npmjs.com/package/@pixi/filter-outline|@pixi/filter-outline}
|
||||||
|
* @see {@link https://www.npmjs.com/package/pixi-filters|pixi-filters}
|
||||||
|
* @param {number} [thickness=1] The tickness of the outline. Make it 2 times more for resolution 2
|
||||||
|
* @param {number} [color=0x000000] The color of the outline.
|
||||||
|
* @param {number} [quality=0.1] The quality of the outline from `0` to `1`, using a higher quality
|
||||||
|
* setting will result in slower performance and more accuracy.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* someSprite.filters = [new OutlineFilter(2, 0x99ff99)];
|
||||||
|
*/
|
||||||
|
class OutlineFilter extends PIXI.Filter {
|
||||||
|
|
||||||
|
constructor(thickness = 1, color = 0x000000, quality = 0.1) {
|
||||||
|
const samples = Math.max(
|
||||||
|
quality * OutlineFilter.MAX_SAMPLES,
|
||||||
|
OutlineFilter.MIN_SAMPLES
|
||||||
|
);
|
||||||
|
const angleStep = (Math.PI * 2 / samples).toFixed(7);
|
||||||
|
|
||||||
|
super(vertex, fragment.replace(/\$\{angleStep\}/, angleStep));
|
||||||
|
this.uniforms.thickness = new Float32Array([0, 0]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The thickness of the outline.
|
||||||
|
* @member {number}
|
||||||
|
* @default 1
|
||||||
|
*/
|
||||||
|
this.thickness = thickness;
|
||||||
|
|
||||||
|
this.uniforms.outlineColor = new Float32Array([0, 0, 0, 1]);
|
||||||
|
this.color = color;
|
||||||
|
|
||||||
|
this.quality = quality;
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(filterManager, input, output, clear) {
|
||||||
|
this.uniforms.thickness[0] = this.thickness / input._frame.width;
|
||||||
|
this.uniforms.thickness[1] = this.thickness / input._frame.height;
|
||||||
|
|
||||||
|
filterManager.applyFilter(this, input, output, clear);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The color of the glow.
|
||||||
|
* @member {number}
|
||||||
|
* @default 0x000000
|
||||||
|
*/
|
||||||
|
get color() {
|
||||||
|
return PIXI.utils.rgb2hex(this.uniforms.outlineColor);
|
||||||
|
}
|
||||||
|
set color(value) {
|
||||||
|
PIXI.utils.hex2rgb(value, this.uniforms.outlineColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum number of samples for rendering outline.
|
||||||
|
* @static
|
||||||
|
* @member {number} MIN_SAMPLES
|
||||||
|
* @memberof PIXI.filters.OutlineFilter
|
||||||
|
* @default 1
|
||||||
|
*/
|
||||||
|
OutlineFilter.MIN_SAMPLES = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum number of samples for rendering outline.
|
||||||
|
* @static
|
||||||
|
* @member {number} MAX_SAMPLES
|
||||||
|
* @memberof PIXI.filters.OutlineFilter
|
||||||
|
* @default 100
|
||||||
|
*/
|
||||||
|
OutlineFilter.MAX_SAMPLES = 100;
|
||||||
|
|
||||||
|
export { OutlineFilter };
|
||||||
@@ -10,15 +10,6 @@ export function hookDoorControlReposition() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hookDoorControlDraw() {
|
|
||||||
const originalHandler = DoorControl.prototype.draw
|
|
||||||
DoorControl.prototype.draw = async function () {
|
|
||||||
const result = await originalHandler.call(this)
|
|
||||||
onDoorControlPostDraw.call(this)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the size of all door controls in relation to the grid size so it'll have a constant percieved size
|
// Set the size of all door controls in relation to the grid size so it'll have a constant percieved size
|
||||||
export function onCanvasReady(currentCanvas) {
|
export function onCanvasReady(currentCanvas) {
|
||||||
const doors = currentCanvas.controls.doors.children
|
const doors = currentCanvas.controls.doors.children
|
||||||
@@ -26,7 +17,7 @@ export function onCanvasReady(currentCanvas) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set the size of the door control in relation to the grid size so it'll have a constant percieved size
|
// Set the size of the door control in relation to the grid size so it'll have a constant percieved size
|
||||||
function onDoorControlPostDraw() {
|
export function onDoorControlPostDraw() {
|
||||||
// If the canvas isn't ready we'll do this after the "canvasReady" event is fired instead
|
// If the canvas isn't ready we'll do this after the "canvasReady" event is fired instead
|
||||||
if (!canvas.ready)
|
if (!canvas.ready)
|
||||||
return
|
return
|
||||||
|
|||||||
24
src/features/door_control_outline.js
Normal file
24
src/features/door_control_outline.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import {settingsKey} from "../settings.js"
|
||||||
|
import {OutlineFilter} from "../../lib/outline_filter/outline_filter.js"
|
||||||
|
|
||||||
|
export function onDoorControlPostDraw() {
|
||||||
|
if (!game.settings.get(settingsKey, "doorControlOutline"))
|
||||||
|
return
|
||||||
|
|
||||||
|
const types = CONST.WALL_DOOR_TYPES
|
||||||
|
if (this.wall.data.door === types.NONE)
|
||||||
|
return
|
||||||
|
|
||||||
|
// Remove all OutlineFilters from current filters
|
||||||
|
let pixiFilters = this.icon.filters || []
|
||||||
|
pixiFilters = pixiFilters.filter(pixiFilter => !(pixiFilter instanceof OutlineFilter))
|
||||||
|
|
||||||
|
let outlineFilter;
|
||||||
|
if (this.wall.data.door === types.SECRET && game.settings.get(settingsKey, "highlightSecretDoors"))
|
||||||
|
outlineFilter = new OutlineFilter(1, 0xFFFFFF)
|
||||||
|
else
|
||||||
|
outlineFilter = new OutlineFilter(1, 0x000000)
|
||||||
|
|
||||||
|
pixiFilters.push(outlineFilter)
|
||||||
|
this.icon.filters = pixiFilters
|
||||||
|
}
|
||||||
55
src/features/execute_macro.js
Normal file
55
src/features/execute_macro.js
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import {settingsKey} from "../settings.js"
|
||||||
|
import {textInput, checkboxInput, injectSettings} from "../form.js"
|
||||||
|
|
||||||
|
// Inject settings for synchronized doors
|
||||||
|
export function onRederWallConfig(wallConfig, html, data) {
|
||||||
|
if (data.isDoor && game.settings.get(settingsKey, "macros")) {
|
||||||
|
|
||||||
|
const settings = [
|
||||||
|
textInput("macroName", data.object.flags.smartdoors?.macro?.name),
|
||||||
|
textInput("macroArguments", JSON.stringify(data.object.flags.smartdoors?.macro?.args ?? undefined)),
|
||||||
|
checkboxInput("macroExecuteEverywhere", data.object.flags.smartdoors?.macro?.executeEverywhere),
|
||||||
|
]
|
||||||
|
|
||||||
|
injectSettings(html, settings)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check data input by the user for validity
|
||||||
|
export async function onWallConfigPreUpdate(event, formData) {
|
||||||
|
const args = formData.macroArguments || "null"
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check if args can be converted to JSON
|
||||||
|
JSON.parse(args)
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
ui.notifications.error(game.i18n.localize("smart-doors.ui.messages.argsInvalidJson"))
|
||||||
|
// Rethrow the error to stop the update and prevent the dialog from closing
|
||||||
|
throw(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The JSON is valid. Assign "null" instead of an empty string if necessary
|
||||||
|
formData.macroArguments = args
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store our custom data from the WallConfig dialog
|
||||||
|
export async function onWallConfigUpdate(event, formData) {
|
||||||
|
let ids = this.options.editTargets;
|
||||||
|
if (ids.length == 0) {
|
||||||
|
ids = [this.object.data._id];
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateData = {flags: {smartdoors: {macro: {
|
||||||
|
name: formData.macroName,
|
||||||
|
args: JSON.parse(formData.macroArguments),
|
||||||
|
executeEverywhere: formData.macroExecuteEverywhere
|
||||||
|
}}}}
|
||||||
|
|
||||||
|
// Update all the edited walls
|
||||||
|
const updateDataset = ids.reduce((dataset, id) => {
|
||||||
|
dataset.push({_id: id, ...updateData})
|
||||||
|
return dataset
|
||||||
|
}, [])
|
||||||
|
return canvas.scene.updateEmbeddedEntity("Wall", updateDataset)
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import {settingsKey} from "../settings.js"
|
import {settingsKey} from "../settings.js"
|
||||||
|
|
||||||
const SECRET_DOOR_TINT = 0x222222
|
const SECRET_DOOR_TINT = 0x000000
|
||||||
|
|
||||||
// Tint all secret doors dark grey
|
// Tint all secret doors dark grey
|
||||||
export function onCanvasReady(currentCanvas) {
|
export function onCanvasReady(currentCanvas) {
|
||||||
|
|||||||
@@ -18,9 +18,6 @@ export function onRederWallConfig(wallConfig, html, data) {
|
|||||||
// Fill the injected input fields with values
|
// Fill the injected input fields with values
|
||||||
const input = (name) => html.find(`input[name="${name}"]`)
|
const input = (name) => html.find(`input[name="${name}"]`)
|
||||||
input("synchronizationGroup").prop("value", smartdoorsData?.synchronizationGroup)
|
input("synchronizationGroup").prop("value", smartdoorsData?.synchronizationGroup)
|
||||||
|
|
||||||
// Recalculate config window height
|
|
||||||
wallConfig.setPosition({height: "auto"})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
38
src/form.js
Normal file
38
src/form.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
function formEntry(name, input) {
|
||||||
|
return `
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="${name}">${game.i18n.localize(`smart-doors.ui.form.${name}.name`)}</label>
|
||||||
|
${input}
|
||||||
|
</div>
|
||||||
|
<p class="notes">${game.i18n.localize(`smart-doors.ui.form.${name}.hint`)}</p>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
export function injectSettings(html, settings) {
|
||||||
|
html.find(".form-group").last().after(settings.join(""))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function textInput(name, value) {
|
||||||
|
return formEntry(name, `<input type="text" name="${escapeHtml(name)}" value="${escapeHtml(value ?? "")}"/>`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectInput(name, values) {
|
||||||
|
// TODO Set selected option
|
||||||
|
let html = `<select name="${name}">`
|
||||||
|
html += values.reduce((html, value) => html + `<option value="${escapeHtml(value)}">${game.i18n.localize(`smart-doors.ui.form.${name}.options.${value}`)}</option>`, "")
|
||||||
|
html += "</select>"
|
||||||
|
return formEntry(name, html)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function checkboxInput(name, checked) {
|
||||||
|
return formEntry(name, `<input type="checkbox" name="${escapeHtml(name)}" value="true" ${checked ? "checked" : ""}/>`)
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeHtml(unsafe) {
|
||||||
|
return unsafe
|
||||||
|
.replace(/&/g, "&")
|
||||||
|
.replace(/</g, "<")
|
||||||
|
.replace(/>/g, ">")
|
||||||
|
.replace(/"/g, """)
|
||||||
|
.replace(/'/g, "'");
|
||||||
|
}
|
||||||
32
src/main.js
32
src/main.js
@@ -1,6 +1,8 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import * as DoorControlIconScale from "./features/door_control_icon_scale.js"
|
import * as DoorControlIconScale from "./features/door_control_icon_scale.js"
|
||||||
|
import * as DoorControlOutline from "./features/door_control_outline.js"
|
||||||
|
import * as ExecuteMacro from "./features/execute_macro.js"
|
||||||
import * as HighlightSecretDoors from "./features/highlight_secret_doors.js"
|
import * as HighlightSecretDoors from "./features/highlight_secret_doors.js"
|
||||||
import * as LockedDoorAlert from "./features/locked_door_alert.js"
|
import * as LockedDoorAlert from "./features/locked_door_alert.js"
|
||||||
import * as SynchronizedDoors from "./features/synchronized_doors.js"
|
import * as SynchronizedDoors from "./features/synchronized_doors.js"
|
||||||
@@ -13,7 +15,7 @@ Hooks.once("init", () => {
|
|||||||
registerSettings()
|
registerSettings()
|
||||||
hookDoorEvents()
|
hookDoorEvents()
|
||||||
hookWallConfigUpdate()
|
hookWallConfigUpdate()
|
||||||
DoorControlIconScale.hookDoorControlDraw()
|
hookDoorControlDraw()
|
||||||
DoorControlIconScale.hookDoorControlReposition()
|
DoorControlIconScale.hookDoorControlReposition()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -24,21 +26,43 @@ Hooks.once("ready", () => {
|
|||||||
Hooks.on("renderChatMessage", LockedDoorAlert.onRenderChatMessage)
|
Hooks.on("renderChatMessage", LockedDoorAlert.onRenderChatMessage)
|
||||||
|
|
||||||
Hooks.on("canvasReady", DoorControlIconScale.onCanvasReady)
|
Hooks.on("canvasReady", DoorControlIconScale.onCanvasReady)
|
||||||
|
|
||||||
Hooks.on("canvasReady", HighlightSecretDoors.onCanvasReady)
|
Hooks.on("canvasReady", HighlightSecretDoors.onCanvasReady)
|
||||||
|
|
||||||
Hooks.on("updateWall", HighlightSecretDoors.onUpdateWall)
|
Hooks.on("updateWall", HighlightSecretDoors.onUpdateWall)
|
||||||
|
|
||||||
// Inject our custom settings into the WallConfig dialog
|
// Inject our custom settings into the WallConfig dialog
|
||||||
Hooks.on("renderWallConfig", SynchronizedDoors.onRederWallConfig)
|
Hooks.on("renderWallConfig", (wallConfig, html, data) => {
|
||||||
|
SynchronizedDoors.onRederWallConfig(wallConfig, html, data)
|
||||||
|
ExecuteMacro.onRederWallConfig(wallConfig, html, data)
|
||||||
|
|
||||||
|
// Recalculate config window position and height
|
||||||
|
wallConfig.element[0].style.top = "" // This forces foundry to re-calculate the top position
|
||||||
|
wallConfig.setPosition({height: "auto"})
|
||||||
|
})
|
||||||
|
|
||||||
// Hook the update function of the WallConfig dialog so we can store our custom data
|
// Hook the update function of the WallConfig dialog so we can store our custom data
|
||||||
function hookWallConfigUpdate() {
|
function hookWallConfigUpdate() {
|
||||||
// Replace the original function with our custom one
|
// Replace the original function with our custom one
|
||||||
const originalHandler = WallConfig.prototype._updateObject;
|
const originalHandler = WallConfig.prototype._updateObject;
|
||||||
WallConfig.prototype._updateObject = async function (event, formData) {
|
WallConfig.prototype._updateObject = async function (event, formData) {
|
||||||
|
await ExecuteMacro.onWallConfigPreUpdate.call(this, event, formData)
|
||||||
|
|
||||||
await originalHandler.call(this, event, formData)
|
await originalHandler.call(this, event, formData)
|
||||||
return SynchronizedDoors.onWallConfigUpdate.call(this, event, formData)
|
|
||||||
|
return Promise.all([
|
||||||
|
SynchronizedDoors.onWallConfigUpdate.call(this, event, formData),
|
||||||
|
ExecuteMacro.onWallConfigUpdate.call(this, event, formData),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hookDoorControlDraw() {
|
||||||
|
const originalHandler = DoorControl.prototype.draw
|
||||||
|
DoorControl.prototype.draw = async function () {
|
||||||
|
const result = await originalHandler.call(this)
|
||||||
|
DoorControlIconScale.onDoorControlPostDraw.call(this)
|
||||||
|
DoorControlOutline.onDoorControlPostDraw.call(this)
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,15 @@ export function registerSettings() {
|
|||||||
default: 1.5,
|
default: 1.5,
|
||||||
onChange: () => location.reload()
|
onChange: () => location.reload()
|
||||||
})
|
})
|
||||||
|
game.settings.register(settingsKey, "doorControlOutline", {
|
||||||
|
name: "smart-doors.settings.doorControlOutline.name",
|
||||||
|
hint: "smart-doors.settings.doorControlOutline.hint",
|
||||||
|
scope: "client",
|
||||||
|
config: true,
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
onChange: () => location.reload(),
|
||||||
|
})
|
||||||
game.settings.register(settingsKey, "highlightSecretDoors", {
|
game.settings.register(settingsKey, "highlightSecretDoors", {
|
||||||
name: "smart-doors.settings.highlightSecretDoors.name",
|
name: "smart-doors.settings.highlightSecretDoors.name",
|
||||||
hint: "smart-doors.settings.highlightSecretDoors.hint",
|
hint: "smart-doors.settings.highlightSecretDoors.hint",
|
||||||
@@ -54,4 +63,12 @@ export function registerSettings() {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
})
|
})
|
||||||
|
game.settings.register(settingsKey, "macros", {
|
||||||
|
name: "smart-doors.settings.macros.name",
|
||||||
|
hint: "smart-doors.settings.macros.hint",
|
||||||
|
scope: "world",
|
||||||
|
config: true,
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user