From dce419d7c3d8fb092e6922bd691d1903d2a32967 Mon Sep 17 00:00:00 2001 From: CDeenen Date: Mon, 20 Dec 2021 03:41:38 +0100 Subject: [PATCH] v1.4.7 --- MaterialDeck.js | 19 +++- README.md | 2 +- changelog.md | 17 ++++ lang/en.json | 5 +- module.json | 8 +- src/external.js | 178 ++++++++++++------------------------ src/misc.js | 92 ++++++++++++++++++- src/othercontrols.js | 34 ++++++- src/playlist.js | 6 ++ src/settings.js | 30 ++++-- src/streamDeck.js | 40 ++++++-- src/systems/wfrp4e.js | 2 +- src/token.js | 10 +- templates/deviceConfig.html | 41 +++++++++ 14 files changed, 325 insertions(+), 159 deletions(-) create mode 100644 templates/deviceConfig.html diff --git a/MaterialDeck.js b/MaterialDeck.js index c546e21..916ae96 100644 --- a/MaterialDeck.js +++ b/MaterialDeck.js @@ -59,7 +59,7 @@ let WSconnected = false; async function analyzeWSmessage(msg){ if (enableModule == false) return; const data = JSON.parse(msg); -// console.log("Received",data); + //console.log("Received",data); if (data.type == "connected" && data.data == "SD"){ const msg = { @@ -109,15 +109,20 @@ async function analyzeWSmessage(msg){ } } + if (data.type == 'newDevice') { + streamDeck.newDevice(data.iteration,data.device); + return; + } + if (data == undefined || data.payload == undefined) return; - //console.log("Received",data); const action = data.action; const event = data.event; const context = data.context; const coordinates = data.payload.coordinates; const settings = data.payload.settings; const device = data.device; - + const name = data.deviceName; + const type = data.deviceType; if (data.data == 'init'){ @@ -125,7 +130,9 @@ async function analyzeWSmessage(msg){ if (event == 'willAppear' || event == 'didReceiveSettings'){ if (coordinates == undefined) return; streamDeck.setScreen(action); - await streamDeck.setContext(device,data.size,data.deviceIteration,action,context,coordinates,settings); + await streamDeck.setContext(device,data.size,data.deviceIteration,action,context,coordinates,settings,name,type); + + if (game.settings.get(moduleName, 'devices')?.[device]?.enable == false) return; if (action == 'token'){ tokenControl.active = true; @@ -153,6 +160,8 @@ async function analyzeWSmessage(msg){ } else if (event == 'keyDown'){ + if (game.settings.get(moduleName, 'devices')?.[device]?.enable == false) return; + if (action == 'token') tokenControl.keyPress(settings); else if (action == 'macro') @@ -172,6 +181,8 @@ async function analyzeWSmessage(msg){ } else if (event == 'keyUp'){ + if (game.settings.get(moduleName, 'devices')?.[device]?.enable == false) return; + if (action == 'soundboard'){ soundboard.keyPressUp(settings); } diff --git a/README.md b/README.md index 931e2b8..bb3eb42 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ Instructions and more info can be found in the { - canvas.scene.setFlag("fxmaster", "effects", newEffects); - }); - - } - else if (type == 'colorize') { - const color = (settings.fxMasterColorizeColor == undefined) ? '#000000' : settings.fxMasterColorizeColor; - const filters = canvas.scene.getFlag("fxmaster", "filters"); - let newFilters = {}; - if (filters != undefined){ - const filterObjects = Object.keys(filters); - for (let i=0; i { - canvas.scene.setFlag("fxmaster", "filters", newFilters); - }); + Hooks.call("fxmaster.switchWeather", { + name: `core_${effect}`, + type: effect, + options, + }); } else if (type == 'filters') { const filter = (settings.fxMasterFilter == undefined) ? 'underwater' : settings.fxMasterFilter; - const filters = canvas.scene.getFlag("fxmaster", "filters"); - let newFilters = {}; - let exists = false; - if (filters != undefined){ - const filterObjects = Object.keys(filters); - for (let i=0; i { - canvas.scene.setFlag("fxmaster", "filters", newFilters); - }); + + FXMASTER.filters.switch(`core_${filter}`, filter, options); } else if (type == 'clear'){ canvas.scene.unsetFlag("fxmaster", "filters"); @@ -280,18 +226,6 @@ export class ExternalModules{ } } - findWeatherEffect(effect){ - const effects = canvas.scene.getFlag("fxmaster", "effects"); - if (effects == undefined) return undefined; - - const weatherIds = Object.keys(effects); - for (let i = 0; i < weatherIds.length; ++i) { - const weather = effects[weatherIds[i]].type; - if (weather === effect) return weatherIds[i]; - } - return undefined; - } - ////////////////////////////////////////////////////////////////////////////////////////////////////////////// //GM Screen ////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/misc.js b/src/misc.js index 3d27cfd..81d2018 100644 --- a/src/misc.js +++ b/src/misc.js @@ -1,15 +1,17 @@ -import {sdVersion, msVersion, moduleName, getPermission, enableModule} from "../MaterialDeck.js"; +import {sdVersion, msVersion, moduleName, getPermission, enableModule, streamDeck} from "../MaterialDeck.js"; import {macroControl,soundboard,playlistControl} from "../MaterialDeck.js"; export function compatibleCore(compatibleVersion){ - let coreVersion = game.data.version; + let coreVersion = game.version == undefined ? game.data.version : `0.${game.version}`; coreVersion = coreVersion.split("."); compatibleVersion = compatibleVersion.split("."); if (compatibleVersion[0] > coreVersion[0]) return false; + if (compatibleVersion[0] < coreVersion[0]) return true; if (compatibleVersion[1] > coreVersion[1]) return false; + if (compatibleVersion[1] < coreVersion[1]) return true; if (compatibleVersion[2] > coreVersion[2]) return false; return true; -} + } export class playlistConfigForm extends FormApplication { constructor(data, options) { @@ -1185,4 +1187,88 @@ export class downloadUtility extends FormApplication { document.getElementById(elementId).innerHTML = 'Error'; } } +} + +export class deviceConfig extends FormApplication { + constructor(data, options) { + super(data, options); + + this.devices = []; + } + + /** + * Default Options for this FormApplication + */ + static get defaultOptions() { + return mergeObject(super.defaultOptions, { + id: "MD_DeviceConfig", + title: "Material Deck: " + game.i18n.localize("MaterialDeck.DeviceConfig.Title"), + template: "./modules/MaterialDeck/templates/deviceConfig.html", + width: 500, + height: "auto" + }); + } + + /** + * Provide data to the template + */ + getData() { + this.devices = []; + const dConfig = game.settings.get(moduleName, 'devices'); + + for (let d of streamDeck.buttonContext) { + let type; + if (d.type == 0) type = 'Stream Deck'; + else if (d.type == 1) type = 'Stream Deck Mini'; + else if (d.type == 2) type = 'Stream Deck XL'; + else if (d.type == 3) type = 'Stream Deck Mobile'; + else if (d.type == 4) type = 'Corsair G Keys'; + + const name = d.name; + const id = d.device; + let enable; + if (dConfig?.[id] == undefined) enable = true; + else enable = dConfig?.[id].enable; + + const device = { + id, + name, + type, + en: enable + } + this.devices.push(device); + } + + return { + devices: this.devices + } + } + + /** + * Update on form submit + * @param {*} event + * @param {*} formData + */ + async _updateObject(event, formData) { + + } + + activateListeners(html) { + super.activateListeners(html); + + html.find("input[name='enable']").on('change', (event) => { + const id = event.currentTarget.id; + for (let d of this.devices) { + if (d.id == id) { + let dConfig = game.settings.get(moduleName, 'devices'); + delete dConfig[id]; + dConfig[id] = {enable: event.currentTarget.checked} + + game.settings.set(moduleName, 'devices', dConfig); + } + } + }) + } + + } \ No newline at end of file diff --git a/src/othercontrols.js b/src/othercontrols.js index 0bcf063..0c70564 100644 --- a/src/othercontrols.js +++ b/src/othercontrols.js @@ -7,6 +7,8 @@ export class OtherControls{ this.active = false; this.rollData = {}; this.rollOption = 'dialog'; + this.controlsOffset = 0; + this.toolsOffset = 0; } setRollOption(option) { @@ -225,7 +227,9 @@ export class OtherControls{ const control = settings.control ? settings.control : 'dispControls'; const tool = settings.tool ? settings.tool : 'open'; let background = settings.background ? settings.background : '#000000'; - let ringColor = '#000000' + let ringColor = '#000000'; + const ringOffColor = settings.offRing ? settings.offRing : '#000000'; + const ringOnColor = settings.onRing ? settings.onRing : '#00FF00'; let txt = ""; let src = ""; const activeControl = ui.controls.activeControl; @@ -235,6 +239,7 @@ export class OtherControls{ let controlNr = parseInt(settings.controlNr); if (isNaN(controlNr)) controlNr = 1; controlNr--; + controlNr += this.controlsOffset; const selectedControl = ui.controls.controls[controlNr]; @@ -255,6 +260,7 @@ export class OtherControls{ let controlNr = parseInt(settings.controlNr); if (isNaN(controlNr)) controlNr = 1; controlNr--; + controlNr += this.toolsOffset; const selectedControl = ui.controls.controls.find(c => c.name == ui.controls.activeControl); if (selectedControl != undefined){ @@ -275,6 +281,18 @@ export class OtherControls{ } } } + else if (control == 'controlsOffset') { + const display = settings.controlsOffsetDisplay ? settings.controlsOffsetDisplay : false; + const offsetType = settings.controlsOffsetType ? settings.controlsOffsetType : 'absoluteOffset'; + if (display) txt = `${this.controlsOffset}`; + if (offsetType == 'absoluteOffset') ringColor = (this.controlsOffset == settings.controlsOffset) ? ringOnColor : ringOffColor; + } + else if (control == 'toolsOffset') { + const display = settings.controlsOffsetDisplay ? settings.controlsOffsetDisplay : false; + const offsetType = settings.controlsOffsetType ? settings.controlsOffsetType : 'absoluteOffset'; + if (display) txt = `${this.toolsOffset}`; + if (offsetType == 'absoluteOffset') ringColor = (this.toolsOffset == settings.controlsOffset) ? ringOnColor : ringOffColor; + } else { // specific control/tool const selectedControl = ui.controls.controls.find(c => c.name == control); if (selectedControl != undefined){ @@ -370,6 +388,16 @@ export class OtherControls{ } } } + else if (control == 'controlsOffset') { + const offsetType = settings.controlsOffsetType ? settings.controlsOffsetType : 'absoluteOffset'; + if (offsetType == 'absoluteOffset') this.controlsOffset = parseInt(settings.controlsOffset); + else if (offsetType == 'relativeOffset') this.controlsOffset += parseInt(settings.controlsOffset); + } + else if (control == 'toolsOffset') { + const offsetType = settings.controlsOffsetType ? settings.controlsOffsetType : 'absoluteOffset'; + if (offsetType == 'absoluteOffset') this.toolsOffset = parseInt(settings.controlsOffset); + else if (offsetType == 'relativeOffset') this.toolsOffset += parseInt(settings.controlsOffset); + } else { //select control const selectedControl = ui.controls.controls.find(c => c.name == control); if (selectedControl != undefined){ @@ -588,6 +616,7 @@ export class OtherControls{ else if (nr == 'items') name = game.i18n.localize("SIDEBAR.TabItems"); else if (nr == 'journal') name = game.i18n.localize("SIDEBAR.TabJournal"); else if (nr == 'tables') name = game.i18n.localize("SIDEBAR.TabTables"); + else if (nr == 'cards') name = game.i18n.localize("SIDEBAR.TabCards"); else if (nr == 'playlists') name = game.i18n.localize("SIDEBAR.TabPlaylists"); else if (nr == 'compendium') name = game.i18n.localize("SIDEBAR.TabCompendium"); else if (nr == 'settings') name = game.i18n.localize("SIDEBAR.TabSettings"); @@ -600,10 +629,11 @@ export class OtherControls{ if (nr == 'chat') icon = window.CONFIG.ChatMessage.sidebarIcon; else if (nr == 'combat') icon = window.CONFIG.Combat.sidebarIcon; else if (nr == 'scenes') icon = window.CONFIG.Scene.sidebarIcon; - else if (nr == 'actors') icon = window.CONFIG.Actor.sidebarIcon; + else if (nr == 'actors') icon = "fas fa-users"; else if (nr == 'items') icon = window.CONFIG.Item.sidebarIcon; else if (nr == 'journal') icon = window.CONFIG.JournalEntry.sidebarIcon; else if (nr == 'tables') icon = window.CONFIG.RollTable.sidebarIcon; + else if (nr == 'cards') icon = "fas fa-id-badge"; else if (nr == 'playlists') icon = window.CONFIG.Playlist.sidebarIcon; else if (nr == 'compendium') icon = "fas fa-atlas"; else if (nr == 'settings') icon = "fas fa-cogs"; diff --git a/src/playlist.js b/src/playlist.js index ab36827..f786381 100644 --- a/src/playlist.js +++ b/src/playlist.js @@ -229,6 +229,12 @@ export class PlaylistControl{ } } } + else if (playlistType == 'playNext') { + this.getPlaylist(playlistNr).playNext(); + } + else if (playlistType == 'playPrev') { + this.getPlaylist(playlistNr).playNext(null,{direction:-1}); + } else if (playlistType == 'offset'){ if (playlistMode == 'playlist') { this.playlistOffset = parseInt(settings.offset); diff --git a/src/settings.js b/src/settings.js index be35e20..9610d13 100644 --- a/src/settings.js +++ b/src/settings.js @@ -1,5 +1,5 @@ import * as MODULE from "../MaterialDeck.js"; -import { playlistConfigForm, macroConfigForm, soundboardConfigForm, downloadUtility } from "./misc.js"; +import { playlistConfigForm, macroConfigForm, soundboardConfigForm, downloadUtility, deviceConfig } from "./misc.js"; let userPermissions = {}; const defaultEnable = [true,true,true,true]; @@ -133,6 +133,27 @@ export const registerSettings = async function() { restricted: false }); + game.settings.registerMenu(MODULE.moduleName, 'downloadUtility',{ + name: "MaterialDeck.DownloadUtility.Title", + label: "MaterialDeck.DownloadUtility.Title", + type: downloadUtility, + restricted: false + }); + + game.settings.registerMenu(MODULE.moduleName, 'deviceConfig',{ + name: "MaterialDeck.DeviceConfig.Title", + label: "MaterialDeck.DeviceConfig.Title", + type: deviceConfig, + restricted: false + }); + + game.settings.register(MODULE.moduleName, 'devices', { + name: "devices", + scope: "client", + type: Object, + config: false + }); + game.settings.registerMenu(MODULE.moduleName, 'permissionConfig',{ name: "MaterialDeck.Sett.Permission", label: "MaterialDeck.Sett.Permission", @@ -147,13 +168,6 @@ export const registerSettings = async function() { config: false }); - game.settings.registerMenu(MODULE.moduleName, 'downloadUtility',{ - name: "MaterialDeck.DownloadUtility.Title", - label: "MaterialDeck.DownloadUtility.Title", - type: downloadUtility, - restricted: false - }); - /** * Playlist soundboard */ diff --git a/src/streamDeck.js b/src/streamDeck.js index 8482eba..bf2eb67 100644 --- a/src/streamDeck.js +++ b/src/streamDeck.js @@ -34,7 +34,26 @@ export class StreamDeck{ } - setContext(device,size,iteration,action,context,coordinates = {column:0,row:0},settings){ + //getButtonContext + + newDevice(iteration,device) { + if (this.buttonContext[iteration] == undefined) { + const deckSize = device.size.columns*device.size.rows; + let buttons = []; + for (let i=0; i 31) this.counter = 0; @@ -413,6 +432,7 @@ export class StreamDeck{ if (format != 'jpg' && format != 'jpeg' && format != 'png' && format != 'PNG' && format != 'webm' && format != 'webp' && format != 'gif' && format != 'svg') url = "modules/MaterialDeck/img/transparant.png"; //if (url == "") url = "modules/MaterialDeck/img/transparant.png" + let resImageURL = url; let img = new Image(); img.setAttribute('crossorigin', 'anonymous'); diff --git a/src/systems/wfrp4e.js b/src/systems/wfrp4e.js index 6588b2f..eefaee2 100644 --- a/src/systems/wfrp4e.js +++ b/src/systems/wfrp4e.js @@ -125,7 +125,7 @@ export class wfrp4e { getItemUses(item) { - console.log("getItemUses(" , item , ")") + //console.log("getItemUses(" , item , ")") if ( item.type == 'ammunition') { return {available: item.data.data.quantity.value}; } diff --git a/src/token.js b/src/token.js index 5c0a197..abb2765 100644 --- a/src/token.js +++ b/src/token.js @@ -1,5 +1,6 @@ import * as MODULE from "../MaterialDeck.js"; import {streamDeck, macroControl, otherControls, tokenHelper} from "../MaterialDeck.js"; +import { compatibleCore } from "./misc.js"; export class TokenControl{ constructor(){ @@ -625,7 +626,8 @@ export class TokenControl{ animation.speed = animationSpeed; } data.lightAnimation = animation; - token.update(data); + if (compatibleCore('0.8.1')) token.document.update(data); + else token.update(data); } else if (onClick == 'initiative'){ tokenHelper.toggleInitiative(token); @@ -663,7 +665,8 @@ export class TokenControl{ else return; iconSrc = images[imgNr]; - token.update({img: iconSrc}) + if (compatibleCore('0.8.1')) token.document.update({img: iconSrc}); + else token.update({img: iconSrc}) } else if (onClick == 'macro') { //call a macro const settingsNew = { @@ -806,7 +809,8 @@ export class TokenControl{ if (path != '') path += '.'; path += targetArray[i][j]; } - await token.update({[path]:value}) + if (compatibleCore('0.8.1')) await token.document.update({[path]:value}); + else await token.update({[path]:value}) this.update(token.id); } diff --git a/templates/deviceConfig.html b/templates/deviceConfig.html new file mode 100644 index 0000000..4497ac7 --- /dev/null +++ b/templates/deviceConfig.html @@ -0,0 +1,41 @@ +
+ + + + + + + + + + + {{#each devices as |d|}} + + + + + + + {{/each}} + +
{{localize "MaterialDeck.Name"}}{{localize "MaterialDeck.Type"}}{{localize "MaterialDeck.Id"}}{{localize "MaterialDeck.Perm.ENABLE.ENABLE.label"}}
{{d.name}}{{d.type}}
+ + + +
\ No newline at end of file