This commit is contained in:
CDeenen
2021-02-04 05:03:34 +01:00
parent f0c1b0e1e0
commit f994e64fc7
17 changed files with 279 additions and 344 deletions

View File

@@ -40,6 +40,8 @@ let wsOpen = false; //Bool for checking if websocket has ever been o
let wsInterval; //Interval timer to detect disconnections
let WSconnected = false;
//let furnace = game.modules.get("furnace");
/*
* Analyzes the message received
*
@@ -51,6 +53,17 @@ async function analyzeWSmessage(msg){
//console.log("Received",data);
if (data.type == "connected" && data.data == "SD"){
/*
console.log(data);
const minimumSDversion = game.modules.get("MaterialDeck").data.minimumSDversion.replace('v','');
const minimumMSversion = game.modules.get("MaterialDeck").data.minimumMSversion;
console.log('SD',minimumSDversion,minimumMSversion)
if (data.SDversion < minimumSDversion) console.log('SD: nope')
else console.log('SD: yes');
if (data.MSversion < minimumMSversion) console.log('MS: nope')
else console.log('MS: yes');
*/
console.log("streamdeck connected to server");
streamDeck.resetImageBuffer();
}
@@ -133,7 +146,10 @@ async function analyzeWSmessage(msg){
*/
function startWebsocket() {
const address = game.settings.get(moduleName,'address');
ws = new WebSocket('ws://'+address+'/');
const url = address.startsWith('wss://') ? address : ('ws://'+address+'/');
ws = new WebSocket(url);
ws.onmessage = function(msg){
//console.log(msg);

View File

@@ -1,5 +1,19 @@
# Changelog Material Deck Module
### v1.2.2 - 07-01-2021
### v1.2.3 - 03-02-2021
Fixes:
<ul>
<li>Fixed some issues for the Shadow of the Demon Lord system</li>
</ul>
Other Changes:
<ul>
<li>Improved performance of the 'Playlist Configuration', 'Macro Configuration' and 'Soundboard Configuration' screens</li>
<li>Minor code clean-up</li>
</ul>
<b>Compatible server app and SD plugin:</b><br>
Material Server v1.0.2 (unchanged): https://github.com/CDeenen/MaterialServer/releases <br>
SD plugin v1.2.2 (unchanged): https://github.com/CDeenen/MaterialDeck_SD/releases<br>
### v1.2.2 - 02-02-2021
Additions:
<ul>
<li>Added a help button in the module configuration</li>

View File

@@ -2,7 +2,9 @@
"name": "MaterialDeck",
"title": "Material Deck",
"description": "Material Deck allows you to control Foundry using an Elgato Stream Deck",
"version": "1.2.2",
"version": "1.2.3",
"minimumSDversion": "1.2.2",
"minimumMSversion": "1.0.2",
"author": "CDeenen",
"esmodules": [
"./MaterialDeck.js"

View File

@@ -10,7 +10,7 @@ export class CombatTracker{
async updateAll(){
if (this.active == false) return;
for (let i=0; i<32; i++){
let data = streamDeck.buttonContext[i];
const data = streamDeck.buttonContext[i];
if (data == undefined || data.action != 'combattracker') continue;
await this.update(data.settings,data.context);
}

View File

@@ -13,7 +13,7 @@ export class ExternalModules{
}
if (this.active == false) return;
for (let i=0; i<32; i++){
let data = streamDeck.buttonContext[i];
const data = streamDeck.buttonContext[i];
if (data == undefined || data.action != 'external') continue;
await this.update(data.settings,data.context);
}
@@ -21,18 +21,15 @@ export class ExternalModules{
update(settings,context){
this.active = true;
let module = settings.module;
if (module == undefined) module = 'fxmaster';
const module = settings.module ? settings.module : 'fxmaster';
if (module == 'fxmaster') this.updateFxMaster(settings,context);
else if (module == 'gmscreen') this.updateGMScreen(settings,context);
}
keyPress(settings,context){
if (this.active == false) return;
let module = settings.module;
if (module == undefined) module = 'fxmaster';
const module = settings.module ? settings.module : 'fxmaster';
if (module == 'fxmaster')
this.keyPressFxMaster(settings,context);
@@ -254,7 +251,7 @@ export class ExternalModules{
const background = settings.gmScreenBackground ? settings.gmScreenBackground : '#000000';
let ring = 1;
let ringColor = '#00FF00'
const ringColor = '#00FF00'
let src = '';
let txt = '';

View File

@@ -10,7 +10,7 @@ export class MacroControl{
async updateAll(){
if (this.active == false) return;
for (let i=0; i<32; i++){
let data = streamDeck.buttonContext[i];
const data = streamDeck.buttonContext[i];
if (data == undefined || data.action != 'macro') continue;
await this.update(data.settings,data.context);
}
@@ -18,39 +18,28 @@ export class MacroControl{
update(settings,context){
this.active = true;
let mode = settings.macroMode;
let displayName = settings.displayName;
const mode = settings.macroMode ? settings.macroMode : 'hotbar';
const displayName = settings.displayName ? settings.displayName : false;
const displayIcon = settings.displayIcon ? settings.displayIcon : false;
let background = settings.background ? settings.background : '#000000';
let macroNumber = settings.macroNumber;
let background = settings.background;
let icon = false;
if (settings.displayIcon) icon = true;
let ringColor = "#000000";
let ring = 0;
if(macroNumber == undefined || isNaN(parseInt(macroNumber))){
macroNumber = 0;
}
if (mode == undefined) mode = 'hotbar';
if (displayName == undefined) displayName = false;
if (background == undefined) background = '#000000';
if (macroNumber == undefined || isNaN(parseInt(macroNumber))) macroNumber = 0;
macroNumber = parseInt(macroNumber);
if (mode == 'macroBoard') { //Macro board
let name = "";
let src = '';
if (settings.macroBoardMode == 'offset') { //Offset
let ringOffColor = settings.offRing;
if (ringOffColor == undefined) ringOffColor = '#000000';
let ringColor = "#000000";
let ring = 0;
let name = "";
let src = "";
let ringOnColor = settings.onRing;
if (ringOnColor == undefined) ringOnColor = '#00FF00';
if (mode == 'macroBoard') { //Macro board
if (settings.macroBoardMode == 'offset') { //Offset
const ringOffColor = settings.offRing ? settings.offRing : '#000000';
const ringOnColor = settings.onRing ? settings.onRing : '#00FF00';
let macroOffset = parseInt(settings.macroOffset);
if (macroOffset == undefined || isNaN(macroOffset)) macroOffset = 0;
if (macroOffset == parseInt(this.offset)) ringColor = ringOnColor;
else ringColor = ringOffColor;
ringColor = (macroOffset == parseInt(this.offset)) ? ringOnColor : ringOffColor;
ring = 2;
}
else { //Execute macro
@@ -58,38 +47,32 @@ export class MacroControl{
if (macroNumber < 0) macroNumber = 0;
var macroId = game.settings.get(MODULE.moduleName,'macroSettings').macros[macroNumber];
background = game.settings.get(MODULE.moduleName,'macroSettings').color[macroNumber];
if (background == undefined) background = '#000000';
src = "";
if (macroId != undefined){
let macro = game.macros._source.find(p => p._id == macroId);
if (macro != undefined) {
name += macro.name;
src += macro.img;
if (displayName) name += macro.name;
if (displayIcon) src += macro.img;
}
}
ring = 0;
}
if (icon) streamDeck.setIcon(context,src,background,ring,ringColor);
else streamDeck.setIcon(context, "", background,ring,ringColor);
if (displayName == 0) name = "";
streamDeck.setTitle(name,context);
}
else { //Macro Hotbar
let macroId
if (mode == 'hotbar') macroId = game.user.data.hotbar[macroNumber];
else {
let macros;
if (mode == 'customHotbar' && game.modules.get('custom-hotbar') != undefined) {
if (mode == 'customHotbar' && game.modules.get('custom-hotbar') != undefined)
macros = ui.customHotbar.macros;
}
else macros = game.macros.apps[0].macros;
else
macros = game.macros.apps[0].macros;
if (macroNumber > 9) macroNumber = 0;
for (let j=0; j<10; j++){
if (macros[j].key == macroNumber){
if (macros[j].macro == null) macroId == undefined;
else macroId = macros[j].macro._id;
}
if (macros[j].key == macroNumber)
macroId = (macros[j].macro == null) ? undefined : macros[j].macro._id;
}
}
let src = "";
@@ -98,36 +81,32 @@ export class MacroControl{
if (macroId != undefined){
let macro = game.macros._source.find(p => p._id == macroId);
if (macro != undefined) {
name += macro.name;
src += macro.img;
if (displayName) name += macro.name;
if (displayIcon) src += macro.img;
}
}
if (icon) streamDeck.setIcon(context,src,background);
else streamDeck.setIcon(context, "", background);
if (displayName == 0) name = "";
streamDeck.setTitle(name,context);
}
streamDeck.setIcon(context,src,background,ring,ringColor);
streamDeck.setTitle(name,context);
}
hotbar(macros){
for (let i=0; i<32; i++){
let data = streamDeck.buttonContext[i];
const data = streamDeck.buttonContext[i];
if (data == undefined || data.action != 'macro' || data.settings.macroMode == 'macroBoard') continue;
let context = data.context;
let mode = data.settings.macroMode;
let displayName = data.settings.displayName;
const context = data.context;
const mode = data.settings.macroMode ? data.settings.macroMode : 'hotbar';
const displayName = data.settings.displayName ? data.settings.displayName : false;
const displayIcon = data.settings.displayIcon ? data.settings.displayIcon : false;
let background = data.settings.background ? data.settings.background : '#000000';
let macroNumber = data.settings.macroNumber;
let background = data.settings.background;
if(macroNumber == undefined || isNaN(parseInt(macroNumber))) macroNumber = 1;
let src = "";
let name = "";
if(macroNumber == undefined || isNaN(parseInt(macroNumber))){
macroNumber = 1;
}
if (mode == undefined) mode = 'hotbar';
if (mode == 'Macro Board') continue;
if (displayName == undefined) displayName = false;
if (background == undefined) background = '#000000';
let macroId;
if (mode == 'hotbar'){
@@ -145,23 +124,18 @@ export class MacroControl{
let macro = undefined;
if (macroId != undefined) macro = game.macros._source.find(p => p._id == macroId);
if (macro != undefined && macro != null) {
name += macro.name;
src += macro.img;
if (displayName) name += macro.name;
if (displayIcon) src += macro.img;
}
streamDeck.setIcon(context,src,background);
if (displayName == 0) name = "";
streamDeck.setTitle(name,context);
}
}
keyPress(settings){
let mode = settings.macroMode;
if (mode == undefined) mode = 'hotbar';
const mode = settings.macroMode ? settings.macroMode : 'hotbar';
let macroNumber = settings.macroNumber;
if(macroNumber == undefined || isNaN(parseInt(macroNumber))){
macroNumber = 0;
}
if(macroNumber == undefined || isNaN(parseInt(macroNumber))) macroNumber = 0;
if (mode == 'hotbar' || mode == 'visibleHotbar' || mode == 'customHotbar')
this.executeHotbar(macroNumber,mode);

View File

@@ -6,7 +6,6 @@ export class playlistConfigForm extends FormApplication {
super(data, options);
this.data = data;
this.playlistNr;
this.updatePlaylistNr = false;
}
/**
@@ -26,7 +25,10 @@ export class playlistConfigForm extends FormApplication {
* Provide data to the template
*/
getData() {
//Get the playlist settings
let settings = game.settings.get(MODULE.moduleName,'playlists');
//Get values from the settings, and check if they are defined
let selectedPlaylists = settings.selectedPlaylist;
if (selectedPlaylists == undefined) selectedPlaylists = [];
let selectedPlaylistMode = settings.playlistMode;
@@ -36,17 +38,17 @@ export class playlistConfigForm extends FormApplication {
if (numberOfPlaylists == undefined) numberOfPlaylists = 9;
let playMode = settings.playMode;
if (playMode == undefined) playMode = 0;
let playlistData = [];
this.updatePlaylistNr = false;
//Create array to store all the data for each playlist
let playlistData = [];
for (let i=0; i<numberOfPlaylists; i++){
if (selectedPlaylists[i] == undefined) selectedPlaylists[i] = 'none';
if (selectedPlaylistMode[i] == undefined) selectedPlaylistMode[i] = 0;
let dataThis = {
iteration: i+1,
playlist: selectedPlaylists[i],
playlistMode: selectedPlaylistMode[i],
playlists: game.playlists.entities
playlistMode: selectedPlaylistMode[i]
}
playlistData.push(dataThis);
}
@@ -89,9 +91,8 @@ export class playlistConfigForm extends FormApplication {
numberOfPlaylists.on("change", event => {
this.playlistNr = event.target.value;
this.updatePlaylistNr = true;
this.data.playlistNumber=event.target.value;
this.updateSettings(this.data);
this.updateSettings(this.data,true);
});
selectedPlaylist.on("change", event => {
@@ -106,10 +107,11 @@ export class playlistConfigForm extends FormApplication {
this.updateSettings(this.data);
});
}
async updateSettings(settings){
async updateSettings(settings,render){
await game.settings.set(MODULE.moduleName,'playlists', settings);
if (MODULE.enableModule) playlistControl.updateAll();
this.render();
if (render) this.render();
}
}
@@ -125,16 +127,6 @@ export class macroConfigForm extends FormApplication {
* Default Options for this FormApplication
*/
static get defaultOptions() {
/*
let streamDeckModel = game.settings.get(MODULE.moduleName,'streamDeckModel');
let width;
if (streamDeckModel == 0)
width = 550;
else if (streamDeckModel == 1)
width= 1500;
else
width = 1400;
*/
return mergeObject(super.defaultOptions, {
id: "macro-config",
title: "Material Deck: "+game.i18n.localize("MaterialDeck.Sett.MacroConfig"),
@@ -147,19 +139,26 @@ export class macroConfigForm extends FormApplication {
* Provide data to the template
*/
getData() {
//Get the settings
var selectedMacros = game.settings.get(MODULE.moduleName,'macroSettings').macros;
var color = game.settings.get(MODULE.moduleName,'macroSettings').color;
var args = game.settings.get(MODULE.moduleName,'macroSettings').args;
//Check if the settings are defined
if (selectedMacros == undefined) selectedMacros = [];
if (color == undefined) color = [];
if (args == undefined) args = [];
let macroData = [];
let furnaceEnabled = false;
let furnace = game.modules.get("furnace");
if (furnace != undefined && furnace.active) furnaceEnabled = true;
let height = 95;
if (furnaceEnabled) height += 50;
//Check if the Furnace is installed and enabled
let furnaceEnabled = false;
let height = 95;
let furnace = game.modules.get("furnace");
if (furnace != undefined && furnace.active) {
furnaceEnabled = true;
height += 50;
}
//Check what SD model the user is using, and set the number of rows and columns to correspond
let streamDeckModel = game.settings.get(MODULE.moduleName,'streamDeckModel');
let iMax,jMax;
if (streamDeckModel == 0){
@@ -176,38 +175,34 @@ export class macroConfigForm extends FormApplication {
}
let iteration = 0;
let macroData = [];
for (let j=0; j<jMax; j++){
let macroThis = [];
for (let i=0; i<iMax; i++){
let colorThis = color[iteration];
if (colorThis != undefined){
let colorData = color[iteration];
if (colorData != undefined){
let colorCorrect = true;
if (colorThis[0] != '#') colorCorrect = false;
if (colorData[0] != '#') colorCorrect = false;
for (let k=0; k<6; k++){
if (parseInt(colorThis[k+1],16)>15)
if (parseInt(colorData[k+1],16)>15)
colorCorrect = false;
}
if (colorCorrect == false) colorThis = '#000000';
if (colorCorrect == false) colorData = '#000000';
}
else
colorThis = '#000000';
colorData = '#000000';
let dataThis = {
iteration: iteration+1,
macro: selectedMacros[iteration],
color: colorThis,
macros:game.macros,
args: args[iteration],
furnace: furnaceEnabled
color: colorData,
args: args[iteration]
}
macroThis.push(dataThis);
iteration++;
}
let data = {
dataThis: macroThis,
};
macroData.push(data);
macroData.push({dataThis: macroThis});
}
return {
@@ -215,6 +210,7 @@ export class macroConfigForm extends FormApplication {
macros: game.macros,
selectedMacros: selectedMacros,
macroData: macroData,
furnace: furnaceEnabled
}
}
@@ -258,7 +254,6 @@ export class macroConfigForm extends FormApplication {
async updateSettings(settings){
await game.settings.set(MODULE.moduleName,'macroSettings',settings);
if (MODULE.enableModule) macroControl.updateAll();
this.render();
}
}
@@ -267,10 +262,7 @@ export class macroConfigForm extends FormApplication {
export class soundboardConfigForm extends FormApplication {
constructor(data, options) {
super(data, options);
this.data = data;
this.playlists = [];
this.updatePlaylist = false;
this.update = false;
this.iMax;
this.jMax;
this.settings = {};
@@ -280,16 +272,6 @@ export class soundboardConfigForm extends FormApplication {
* Default Options for this FormApplication
*/
static get defaultOptions() {
/*
let streamDeckModel = game.settings.get(MODULE.moduleName,'streamDeckModel');
let width;
if (streamDeckModel == 0)
width = 550;
else if (streamDeckModel == 1)
width= 885;
else
width = 1400;
*/
return mergeObject(super.defaultOptions, {
id: "soundboard-config",
title: "Material Deck: "+game.i18n.localize("MaterialDeck.Sett.SoundboardConfig"),
@@ -299,27 +281,14 @@ export class soundboardConfigForm extends FormApplication {
});
}
getArray(data){
let array = [data.a,data.b,data.c,data.d,data.e,data.f,data.g,data.h];
return array;
}
/**
* Provide data to the template
*/
getData() {
if (this.update) {
this.update=false;
return {soundData: this.data};
}
//Get the settings
this.settings = game.settings.get(MODULE.moduleName,'soundboardSettings');
let playlists = [];
playlists.push({id:"none",name:game.i18n.localize("MaterialDeck.None")});
playlists.push({id:"FP",name:game.i18n.localize("MaterialDeck.FilePicker")})
for (let i=0; i<game.playlists.entities.length; i++){
playlists.push({id:game.playlists.entities[i]._id,name:game.playlists.entities[i].name});
}
//Check if all settings are defined
if (this.settings.sounds == undefined) this.settings.sounds = [];
if (this.settings.colorOn == undefined) this.settings.colorOn = [];
if (this.settings.colorOff == undefined) this.settings.colorOff = [];
@@ -329,8 +298,17 @@ export class soundboardConfigForm extends FormApplication {
if (this.settings.name == undefined) this.settings.name = [];
if (this.settings.selectedPlaylists == undefined) this.settings.selectedPlaylists = [];
if (this.settings.src == undefined) this.settings.src = [];
let soundData = [];
//Create the playlist array
let playlists = [];
playlists.push({id:"none",name:game.i18n.localize("MaterialDeck.None")});
playlists.push({id:"FP",name:game.i18n.localize("MaterialDeck.FilePicker")})
for (let i=0; i<game.playlists.entities.length; i++){
playlists.push({id:game.playlists.entities[i]._id,name:game.playlists.entities[i].name});
}
this.playlists = playlists;
//Check what SD model the user is using, and set the number of rows and columns to correspond
let streamDeckModel = game.settings.get(MODULE.moduleName,'streamDeckModel');
if (streamDeckModel == 0){
@@ -346,37 +324,54 @@ export class soundboardConfigForm extends FormApplication {
this.iMax = 8;
}
let iteration = 0;
let iteration = 0; //Sound number
let soundData = []; //Stores all the data for each sound
//Fill soundData. soundData is an array the size of jMax (nr of rows), with each array element containing an array the size of iMax (nr of columns)
for (let j=0; j<this.jMax; j++){
let soundsThis = [];
let soundsThis = []; //Stores row data
for (let i=0; i<this.iMax; i++){
//Each iteration gets the data for each sound
//If the volume is undefined for this sound, define it and set it to its default value
if (this.settings.volume[iteration] == undefined) this.settings.volume[iteration] = 50;
//Get the selected playlist and the sounds of that playlist
let selectedPlaylist;
let sounds = [];
if (this.settings.volume[iteration] == undefined) this.settings.volume[iteration] = 50;
if (this.settings.selectedPlaylists[iteration]==undefined) selectedPlaylist = 'none';
else if (this.settings.selectedPlaylists[iteration] == 'none') selectedPlaylist = 'none';
else if (this.settings.selectedPlaylists[iteration] == 'FP') selectedPlaylist = 'FP';
else {
//Get the playlist
const pl = game.playlists.entities.find(p => p._id == this.settings.selectedPlaylists[iteration]);
if (pl == undefined){
selectedPlaylist = 'none';
sounds = [];
}
else {
sounds = pl.sounds;
//Add the sound name and id to the sounds array
for (let i=0; i<pl.sounds.length; i++)
sounds.push({
name: pl.sounds[i].name,
id: pl.sounds[i]._id
});
//Get the playlist id
selectedPlaylist = pl._id;
}
}
//Determine whether the sound selector or file picker should be displayed
let styleSS = "";
let styleFP ="display:none";
if (selectedPlaylist == 'FP') {
styleSS = 'display:none';
styleFP = ''
}
//Create and fill the data object for this sound
let dataThis = {
iteration: iteration+1,
playlists: playlists,
selectedPlaylist: selectedPlaylist,
sound: this.settings.sounds[iteration],
sounds: sounds,
@@ -390,18 +385,20 @@ export class soundboardConfigForm extends FormApplication {
styleSS: styleSS,
styleFP: styleFP
}
//Push the data to soundsThis (row array)
soundsThis.push(dataThis);
iteration++;
}
let data = {
dataThis: soundsThis,
};
soundData.push(data);
//Push soundsThis (row array) to soundData (full data array)
soundData.push({dataThis: soundsThis});
}
this.data = soundData;
return {
soundData: this.data
soundData: soundData,
playlists
}
}
@@ -428,122 +425,105 @@ export class soundboardConfigForm extends FormApplication {
nameField.on("change",event => {
let id = event.target.id.replace('name','')-1;
let j = Math.floor(id/this.jMax);
let i = id % this.jMax;
this.data[j].dataThis[i].name=event.target.value;
this.update = true;
this.settings.name[id]=event.target.value;
this.updateSettings(this.settings);
});
if (playlistSelect.length > 0) {
playlistSelect.on("change", event => {
let id = event.target.id.replace('playlists','')-1;
let j = Math.floor(id/this.jMax);
let i = id % this.jMax;
this.data[j].dataThis[i].selectedPlaylist=event.target.value;
//Listener for when the playlist is changed
playlistSelect.on("change", event => {
//Get the sound number
const iteration = event.target.id.replace('playlists','');
//Get the selected playlist and the sounds of that playlist
let selectedPlaylist;
let sounds = [];
//let sounds = [];
if (event.target.value==undefined) selectedPlaylist = 'none';
else if (event.target.value == 'none') selectedPlaylist = 'none';
else if (event.target.value == 'FP') selectedPlaylist = 'FP';
else if (event.target.value == 'FP') {
selectedPlaylist = 'FP';
//Show the file picker
document.querySelector(`#fp${iteration}`).style='';
//Hide the sound selector
document.querySelector(`#ss${iteration}`).style='display:none';
}
else {
//Hide the file picker
document.querySelector(`#fp${iteration}`).style='display:none';
//Show the sound selector
document.querySelector(`#ss${iteration}`).style='';
const pl = game.playlists.entities.find(p => p._id == event.target.value);
selectedPlaylist = pl._id;
sounds = pl.sounds;
}
this.data[j].dataThis[i].sounds=sounds;
let styleSS = "";
let styleFP ="display:none";
if (selectedPlaylist == 'FP') {
styleSS = 'display:none';
styleFP = ''
}
this.data[j].dataThis[i].styleSS=styleSS;
this.data[j].dataThis[i].styleFP=styleFP;
this.update = true;
//Get the sound select element
let SSpicker = document.getElementById(`soundSelect${iteration}`);
this.settings.selectedPlaylists[id]=event.target.value;
//Empty ss element
SSpicker.options.length=0;
//Create new options and append them
let optionNone = document.createElement('option');
optionNone.value = "";
optionNone.innerHTML = game.i18n.localize("MaterialDeck.None");
SSpicker.appendChild(optionNone);
for (let i=0; i<pl.sounds.length; i++){
let newOption = document.createElement('option');
newOption.value = pl.sounds[i]._id;
newOption.innerHTML = pl.sounds[i].name;
SSpicker.appendChild(newOption);
}
}
//Save the new playlist to this.settings, and update the settings
this.settings.selectedPlaylists[iteration-1]=event.target.value;
this.updateSettings(this.settings);
});
}
soundSelect.on("change", event => {
let id = event.target.id.replace('soundSelect','')-1;
let j = Math.floor(id/this.jMax);
let i = id % this.jMax;
this.data[j].dataThis[i].sound=event.target.value;
this.update = true;
this.settings.sounds[id]=event.target.value;
this.updateSettings(this.settings);
});
soundFP.on("change",event => {
let id = event.target.id.replace('srcPath','')-1;
let j = Math.floor(id/this.jMax);
let i = id % this.jMax;
this.data[j].dataThis[i].srcPath=event.target.value;
this.update = true;
this.settings.src[id]=event.target.value;
this.updateSettings(this.settings);
});
imgFP.on("change",event => {
let id = event.target.id.replace('imgPath','')-1;
let j = Math.floor(id/this.jMax);
let i = id % this.jMax;
this.data[j].dataThis[i].imgPath=event.target.value;
this.update = true;
this.settings.img[id]=event.target.value;
this.updateSettings(this.settings);
});
onCP.on("change",event => {
let id = event.target.id.replace('colorOn','')-1;
let j = Math.floor(id/this.jMax);
let i = id % this.jMax;
this.data[j].dataThis[i].colorOn=event.target.value;
this.update = true;
this.settings.colorOn[id]=event.target.value;
this.updateSettings(this.settings);
});
offCP.on("change",event => {
let id = event.target.id.replace('colorOff','')-1;
let j = Math.floor(id/this.jMax);
let i = id % this.jMax;
this.data[j].dataThis[i].colorOff=event.target.value;
this.update = true;
this.settings.colorOff[id]=event.target.value;
this.updateSettings(this.settings);
});
playMode.on("change",event => {
let id = event.target.id.replace('playmode','')-1;
let j = Math.floor(id/this.jMax);
let i = id % this.jMax;
this.data[j].dataThis[i].mode=event.target.value;
this.update = true;
this.settings.mode[id]=event.target.value;
this.updateSettings(this.settings);
});
volume.on("change",event => {
let id = event.target.id.replace('volume','')-1;
let j = Math.floor(id/this.jMax);
let i = id % this.jMax;
this.data[j].dataThis[i].volume=event.target.value;
this.update = true;
this.settings.volume[id]=event.target.value;
this.updateSettings(this.settings);
});
@@ -552,7 +532,5 @@ export class soundboardConfigForm extends FormApplication {
async updateSettings(settings){
await game.settings.set(MODULE.moduleName,'soundboardSettings',settings);
if (MODULE.enableModule) soundboard.updateAll();
this.render();
}
}

View File

@@ -10,7 +10,7 @@ export class OtherControls{
async updateAll(){
if (this.active == false) return;
for (let i=0; i<32; i++){
let data = streamDeck.buttonContext[i];
const data = streamDeck.buttonContext[i];
if (data == undefined || data.action != 'other') continue;
await this.update(data.settings,data.context);
}

View File

@@ -11,7 +11,7 @@ export class PlaylistControl{
async updateAll(){
if (this.active == false) return;
for (let i=0; i<32; i++){
let data = streamDeck.buttonContext[i];
const data = streamDeck.buttonContext[i];
if (data == undefined || data.action != 'playlist') continue;
await this.update(data.settings,data.context);
}

View File

@@ -11,7 +11,7 @@ export class SceneControl{
async updateAll(){
if (this.active == false) return;
for (let i=0; i<32; i++){
let data = streamDeck.buttonContext[i];
const data = streamDeck.buttonContext[i];
if (data == undefined || data.action != 'scene') continue;
await this.update(data.settings,data.context);
}
@@ -29,7 +29,7 @@ export class SceneControl{
let src = "";
let name = "";
if (func == 'visible'){ //visible scenes
if (func == 'visible') { //visible scenes
let nr = parseInt(settings.sceneNr);
if (isNaN(nr) || nr < 1) nr = 1;
nr--;
@@ -37,10 +37,7 @@ export class SceneControl{
let scene = game.scenes.apps[0].scenes[nr];
if (scene != undefined){
if (scene.isView)
ringColor = ringOnColor;
else
ringColor = ringOffColor;
ringColor = scene.isView ? ringOnColor : ringOffColor;
if (settings.displaySceneName) name = scene.name;
if (settings.displaySceneIcon) src = scene.img;
if (scene.active) name += "\n(Active)";
@@ -81,10 +78,7 @@ export class SceneControl{
if (settings.sceneName == undefined || settings.sceneName == '') return;
let scene = game.scenes.apps[1].entities.find(p=>p.data.name == settings.sceneName);
if (scene != undefined){
if (scene.isView)
ringColor = ringOnColor;
else
ringColor = ringOffColor;
ringColor = scene.isView ? ringOnColor : ringOffColor;
if (settings.displaySceneName) name = scene.name;
if (settings.displaySceneIcon) src = scene.img;
if (scene.active) name += "\n(Active)";
@@ -167,8 +161,7 @@ export class SceneControl{
let scene = game.scenes.apps[1].entities.find(p=>p.data.name == settings.sceneName);
if (scene == undefined) return;
let viewFunc = settings.sceneViewFunction;
if (viewFunc == undefined) viewFunc = 'view';
const viewFunc = settings.sceneViewFunction ? settings.sceneViewFunction : 'view';
if (viewFunc == 'view'){
scene.view();

View File

@@ -13,7 +13,7 @@ export class SoundboardControl{
async updateAll(){
if (this.active == false) return;
for (let i=0; i<32; i++){
let data = streamDeck.buttonContext[i];
const data = streamDeck.buttonContext[i];
if (data == undefined || data.action != 'soundboard') continue;
await this.update(data.settings,data.context);
}
@@ -21,17 +21,13 @@ export class SoundboardControl{
update(settings,context){
this.active = true;
let mode = settings.soundboardMode;
if (mode == undefined) mode = 'playSound';
const mode = settings.soundboardMode ? settings.soundboardMode : 'playSound';
const background = settings.background ? settings.background : '#000000';
let ringColor = "#000000"
let txt = "";
let src = "";
let background = settings.background;
if (background == undefined) background = '#000000';
let ringColor = "#000000"
if (mode == 'playSound'){ //play sound
let soundNr = parseInt(settings.soundNr);
if (isNaN(soundNr)) soundNr = 1;
@@ -39,28 +35,23 @@ export class SoundboardControl{
soundNr += this.offset;
let soundboardSettings = game.settings.get(MODULE.moduleName, 'soundboardSettings');
if (this.activeSounds[soundNr]==false)
ringColor = soundboardSettings.colorOff[soundNr];
else
ringColor = soundboardSettings.colorOn[soundNr];
ringColor = (this.activeSounds[soundNr]==false) ? soundboardSettings.colorOff[soundNr] : soundboardSettings.colorOn[soundNr];
if (settings.displayName && soundboardSettings.name != undefined) txt = soundboardSettings.name[soundNr];
if (settings.displayIcon && soundboardSettings.img != undefined) src = soundboardSettings.img[soundNr];
streamDeck.setTitle(txt,context);
streamDeck.setIcon(context,src,background,2,ringColor);
}
else if (mode == 'offset') { //Offset
let ringOffColor = settings.offRing;
if (ringOffColor == undefined) ringOffColor = '#000000';
let ringOnColor = settings.onRing;
if (ringOnColor == undefined) ringOnColor = '#00FF00';
const ringOffColor = settings.offRing ? settings.offRing : '#000000';
const ringOnColor = settings.onRing ? settings.onRing : '#00FF00';
let offset = parseInt(settings.offset);
if (isNaN(offset)) offset = 0;
if (offset == this.offset) ringColor = ringOnColor;
else ringColor = ringOffColor;
streamDeck.setTitle(txt,context);
streamDeck.setIcon(context,"",background,2,ringColor);
}
@@ -68,7 +59,8 @@ export class SoundboardControl{
let src = 'modules/MaterialDeck/img/playlist/stop.png';
let soundPlaying = false;
for (let i=0; i<this.activeSounds.length; i++)
if (this.activeSounds[i]) soundPlaying = true;
if (this.activeSounds[i])
soundPlaying = true;
if (soundPlaying)
streamDeck.setIcon(context,src,settings.background,2,'#00FF00',true);
else
@@ -77,8 +69,8 @@ export class SoundboardControl{
}
keyPressDown(settings){
let mode = settings.soundboardMode;
if (mode == undefined) mode = 'playSound';
const mode = settings.soundboardMode ? settings.soundboardMode : 'playSound';
if (mode == 'playSound') { //Play sound
let soundNr = parseInt(settings.soundNr);
if (isNaN(soundNr)) soundNr = 1;
@@ -86,11 +78,9 @@ export class SoundboardControl{
soundNr += this.offset;
const playMode = game.settings.get(MODULE.moduleName,'soundboardSettings').mode[soundNr];
const repeat = (playMode > 0) ? true : false;
const play = (this.activeSounds[soundNr] == false) ? true : false;
let repeat = false;
if (playMode > 0) repeat = true;
let play = false;
if (this.activeSounds[soundNr] == false) play = true;
this.playSound(soundNr,repeat,play);
}
else if (mode == 'offset') { //Offset
@@ -109,9 +99,10 @@ export class SoundboardControl{
}
keyPressUp(settings){
let mode = settings.soundboardMode;
if (mode == undefined) mode = 'playSound';
const mode = settings.soundboardMode ? settings.soundboardMode : 'playSound';
if (mode != 'playSound') return;
let soundNr = parseInt(settings.soundNr);
if (isNaN(soundNr)) soundNr = 1;
soundNr--;
@@ -125,8 +116,7 @@ export class SoundboardControl{
async playSound(soundNr,repeat,play){
const soundBoardSettings = game.settings.get(MODULE.moduleName,'soundboardSettings');
let playlistId;
if (soundBoardSettings.selectedPlaylists != undefined) playlistId = soundBoardSettings.selectedPlaylists[soundNr];
const playlistId = (soundBoardSettings.selectedPlaylists != undefined) ? soundBoardSettings.selectedPlaylists[soundNr] : undefined;
let src;
if (playlistId == "" || playlistId == undefined) return;
if (playlistId == 'none') return;
@@ -134,7 +124,8 @@ export class SoundboardControl{
src = soundBoardSettings.src[soundNr];
const ret = await FilePicker.browse("data", src, {wildcard:true});
const files = ret.files;
if (files.length == 1) src = files;
if (files.length == 1)
src = files;
else {
let value = Math.floor(Math.random() * Math.floor(files.length));
src = files[value];

View File

@@ -10,37 +10,32 @@ export class TokenControl{
async update(tokenId){
if (this.active == false) return;
for (let i=0; i<32; i++){
let data = streamDeck.buttonContext[i];
const data = streamDeck.buttonContext[i];
if (data == undefined || data.action != 'token') continue;
await this.pushData(tokenId,data.settings,data.context);
}
}
async pushData(tokenId,settings,context,ring=0,ringColor='#000000'){
let name = false;
let icon = false;
let stats = settings.stats;
let background = "#000000";
const name = settings.displayName ? settings.displayName : false;
const icon = settings.displayIcon ? settings.displayIcon : false;
const background = settings.background ? settings.background : "#000000";
const system = settings.system ? settings.system : 'dnd5e';
if (settings.displayIcon) icon = true;
if (settings.displayName) name = true;
let system = settings.system;
if (system == undefined) system = 'dnd5e';
if (system == 'demonlord') stats = settings.statsDemonlord;
let stats = (system == 'demonlord') ? settings.statsDemonlord : settings.stats;
if (stats == undefined) stats = 'none';
if (settings.background) background = settings.background;
let tokenName = "";
let txt = "";
let iconSrc = "";
let overlay = false;
if (tokenId != undefined) {
let token = canvas.tokens.children[0].children.find(p => p.id == tokenId);
const token = canvas.tokens.children[0].children.find(p => p.id == tokenId);
tokenName = token.data.name;
if (name) txt += tokenName;
if (name && stats != 'none') txt += "\n";
iconSrc = token.data.img;
let actor = canvas.tokens.children[0].children.find(p => p.id == tokenId).actor;
if (stats == 'custom'){
const custom = settings.custom ? settings.custom : '';
let split = custom.split('[');
@@ -60,7 +55,7 @@ export class TokenControl{
}
}
else if (system == 'dnd5e' && game.system.id == 'dnd5e'){
let attributes = actor.data.data.attributes;
let attributes = token.actor.data.data.attributes;
if (stats == 'HP') {
txt += attributes.hp.value + "/" + attributes.hp.max;
}
@@ -102,11 +97,11 @@ export class TokenControl{
txt += speed;
}
else if (stats == 'Init') txt += attributes.init.total;
else if (stats == 'PassivePerception') txt += actor.data.data.skills.prc.passive;
else if (stats == 'PassiveInvestigation') txt += actor.data.data.skills.inv.passive;
else if (stats == 'PassivePerception') txt += token.actor.data.data.skills.prc.passive;
else if (stats == 'PassiveInvestigation') txt += token.actor.data.data.skills.inv.passive;
}
else if ((system == 'dnd3.5e' && game.system.id == 'D35E') || (system == 'pf1e' && game.system.id == 'pf1')){
let attributes = actor.data.data.attributes;
let attributes = token.actor.data.data.attributes;
if (stats == 'HP') txt += attributes.hp.value + "/" + attributes.hp.max;
else if (stats == 'TempHP') {
if (attributes.hp.temp == null) txt += '0';
@@ -137,7 +132,7 @@ export class TokenControl{
else if (stats == 'Init') txt += attributes.init.total;
}
else if (system == 'pf2e' && game.system.id == 'pf2e'){
let attributes = actor.data.data.attributes;
let attributes = token.actor.data.data.attributes;
if (stats == 'HP') txt += attributes.hp.value + "/" + attributes.hp.max;
else if (stats == 'TempHP') {
if (attributes.hp.temp == null) txt += '0';
@@ -161,11 +156,11 @@ export class TokenControl{
}
}
else if (system == 'demonlord' && game.system.id == 'demonlord'){
let characteristics = actor.data.data.characteristics;
if (statsDemonlord == 'HP') txt += characteristics.health.value + "/" + characteristics.health.max;
else if (statsDemonlord == 'AC') txt += characteristics.defense;
else if (statsDemonlord == 'Speed') txt += characteristics.speed;
else if (statsDemonlord == 'Init') txt += actor.data.data.fastturn ? "FAST" : "SLOW";
let characteristics = token.actor.data.data.characteristics;
if (stats == 'HP') txt += characteristics.health.value + "/" + characteristics.health.max;
else if (stats == 'AC') txt += characteristics.defense;
else if (stats == 'Speed') txt += characteristics.speed;
else if (stats == 'Init') txt += token.actor.data.data.fastturn ? "FAST" : "SLOW";
}
else {
//Other systems
@@ -210,8 +205,7 @@ export class TokenControl{
else if (settings.onClick == 'condition') { //toggle condition
ring = 1;
if ((system == 'dnd5e' && game.system.id == 'dnd5e') || (system == 'dnd3.5e' && game.system.id == 'D35E') || (system == 'pf1e' && game.system.id == 'pf1')){
let condition = settings.condition;
if (condition == undefined) condition = 'removeAll';
const condition = settings.condition ? settings.condition : 'removeAll';
if (condition == 'removeAll' && icon == false)
iconSrc = window.CONFIG.controlIcons.effects;
else if (icon == false) {
@@ -226,8 +220,7 @@ export class TokenControl{
}
}
else if (system == 'pf2e' && game.system.id == 'pf2e') {
let condition = settings.conditionPF2E;
if (condition == undefined) condition = 'removeAll';
const condition = settings.conditionPF2E ? settings.conditionPF2E : 'removeAll';
if (condition == 'removeAll' && icon == false)
iconSrc = window.CONFIG.controlIcons.effects;
else if (icon == false) {
@@ -242,8 +235,7 @@ export class TokenControl{
}
}
else if (system == 'demonlord' && game.system.id == 'demonlord'){
let condition = settings.conditionDemonlord;
if (condition == undefined) condition = 'removeAll';
const condition = settings.conditionDemonlord ? settings.conditionDemonlord : 'removeAll';
if (condition == 'removeAll' && icon == false)
iconSrc = window.CONFIG.controlIcons.effects;
else if (icon == false) {
@@ -321,27 +313,21 @@ export class TokenControl{
}
else if (settings.onClick == 'condition') { //toggle condition
if ((system == 'dnd5e' && game.system.id == 'dnd5e') || (system == 'dnd3.5e' && game.system.id == 'D35E') || (system == 'pf1e' && game.system.id == 'pf1')){
let condition = settings.condition;
if (condition == undefined) condition = 'removeAll';
const condition = settings.condition ? settings.condition : 'removeAll';
if (condition == 'removeAll' && icon == false)
iconSrc = window.CONFIG.controlIcons.effects;
else if (icon == false)
iconSrc = CONFIG.statusEffects.find(e => e.id === condition).icon;
}
else if (system == 'pf2e' && game.system.id == 'pf2e') {
let condition = settings.conditionPF2E;
if (condition == undefined) condition = 'removeAll';
const condition = settings.conditionPF2E ? settings.conditionPF2E : 'removeAll';
if (condition == 'removeAll' && icon == false)
iconSrc = window.CONFIG.controlIcons.effects;
else if (icon == false)
iconSrc = this.pf2eCondition(condition);
}
else if (system == 'demonlord' && game.system.id == 'demonlord'){
let condition = settings.conditionDemonlord;
if (condition == undefined) condition = 'removeAll';
const condition = settings.conditionDemonlord ? settings.conditionDemonlord : 'removeAll';
if (condition == 'removeAll' && icon == false)
iconSrc = window.CONFIG.controlIcons.effects;
else if (icon == false)
@@ -366,7 +352,6 @@ export class TokenControl{
iconSrc = "modules/MaterialDeck/img/black.png";
}
streamDeck.setIcon(context,iconSrc,background,ring,ringColor,overlay);
streamDeck.setTitle(txt,context);
}
@@ -374,14 +359,13 @@ export class TokenControl{
if (MODULE.selectedTokenId == undefined) return;
const tokenId = MODULE.selectedTokenId;
let onClick = settings.onClick;
if (onClick == undefined) onClick = 'doNothing';
const token = canvas.tokens.children[0].children.find(p => p.id == tokenId);
if (token == undefined) return;
let system = settings.system;
if (system == undefined) system = 'dnd5e';
let system = settings.system ? settings.system : 'dnd5e';
let onClick = (system == 'demonlord') ? settings.onClickDemonlord : settings.onClick;
if (onClick == undefined) onClick = 'doNothing';
if (onClick == 'doNothing') //Do nothing
return;
@@ -410,15 +394,10 @@ export class TokenControl{
}
else if (onClick == 'condition') { //Toggle condition
if ((system == 'dnd5e' && game.system.id == 'dnd5e') || (system == 'dnd3.5e' && game.system.id == 'D35E') || (system == 'pf1e' && game.system.id == 'pf1')){
let condition = settings.condition;
if (condition == undefined) condition = 'removeAll';
const condition = settings.condition ? settings.condition : 'removeAll';
if (condition == 'removeAll'){
const effects = token.actor.effects.entries;
for (let i=0; i<effects.length; i++){
const effect = CONFIG.statusEffects.find(e => e.icon === effects[i].data.icon);
await token.toggleEffect(effect)
}
for( let effect of token.actor.effects)
await effect.delete();
}
else {
const effect = CONFIG.statusEffects.find(e => e.id === condition);
@@ -426,14 +405,10 @@ export class TokenControl{
}
}
else if (system == 'pf2e' && game.system.id == 'pf2e'){
let condition = settings.conditionPF2E;
if (condition == undefined) condition = 'removeAll';
const condition = settings.conditionPF2E ? settings.conditionPF2E : 'removeAll';
if (condition == 'removeAll'){
const effects = token.actor.effects.entries;
for (let i=0; i<effects.length; i++){
const effect = this.pf2eCondition(condition);
await token.toggleEffect(effect)
}
for( let effect of token.actor.effects)
await effect.delete();
}
else {
const effect = this.pf2eCondition(condition);
@@ -441,15 +416,10 @@ export class TokenControl{
}
}
else if (system == 'demonlord' && game.system.id == 'demonlord'){
let condition = settings.conditionDemonlord;
if (condition == undefined) condition = 'removeAll';
const condition = settings.conditionDemonlord ? settings.conditionDemonlord : 'removeAll';
if (condition == 'removeAll'){
const effects = token.actor.effects.entries;
for (let i=0; i<effects.length; i++){
const effect = CONFIG.statusEffects.find(e => e.icon === effects[i].data.icon);
await token.toggleEffect(effect)
}
for( let effect of token.actor.effects)
await effect.delete();
}
else {
const effect = CONFIG.statusEffects.find(e => e.id === condition);
@@ -504,7 +474,7 @@ export class TokenControl{
})
}
else if (settings.onClick == 'wildcard') { //wildcard images
else if (onClick == 'wildcard') { //wildcard images
const method = settings.wildcardMethod ? settings.wildcardMethod : 'iterate';
let value = parseInt(settings.wildcardValue);
if (isNaN(value)) value = 1;
@@ -538,7 +508,7 @@ export class TokenControl{
iconSrc = images[imgNr];
token.update({img: iconSrc})
}
else if (settings.onClick == 'custom') {//custom onClick function
else if (onClick == 'custom') {//custom onClick function
const formula = settings.customOnClickFormula ? settings.customOnClickFormula : '';
if (formula == '') return;

View File

@@ -19,13 +19,13 @@
<select name="macros" class="macros-select" id="macros{{this.iteration}}" default="" style="max-width:140px;">
{{#select this.macro}}
<option value="">{{localize "MaterialDeck.None"}}</option>
{{#each macros}}
{{#each ../../macros}}
<option value="{{this._id}}">{{this.name}}</option>
{{/each}}
{{/select}}
</select>
</div>
{{#if this.furnace}}
{{#if ../../furnace}}
<label>{{localize "MaterialDeck.FurnaceArgs"}}</label>
<input type="text" name="args" id="args{{this.iteration}}" value="{{this.args}}">
{{/if}}

View File

@@ -25,7 +25,7 @@
<select name="selectedPlaylist" class="playlist-select" id="playlist{{this.iteration}}" default="">
{{#select this.playlist}}
<option value="">{{localize "MaterialDeck.None"}}</option>
{{#each this.playlists}}
{{#each ../playlists}}
<option value="{{this._id}}">{{this.name}}</option>
{{/each}}
{{/select}}

View File

@@ -26,7 +26,7 @@
<div>
<select name="playlist" class="playlist-select" default="" style="width:100%;" id="playlists{{this.iteration}}">
{{#select this.selectedPlaylist}}
{{#each playlists}}
{{#each ../../playlists}}
<option value="{{this.id}}">{{this.name}}</option>
{{/each}}
{{/select}}
@@ -36,17 +36,17 @@
<div style="text-align:center;">
{{localize "MaterialDeck.Sound"}}
</div>
<div class="form-fields" style={{this.styleSS}}>
<div class="form-fields" id="ss{{this.iteration}}" style="{{this.styleSS}}">
<select name="sounds" class="sounds-select" default="" style="width:100%;" id="soundSelect{{this.iteration}}">
{{#select this.sound}}
<option value="">{{localize "MaterialDeck.None"}}</option>
{{#each sounds}}
<option value="{{this._id}}">{{this.name}}</option>
<option value="{{this.id}}">{{this.name}}</option>
{{/each}}
{{/select}}
</select>
</div>
<div class="form-fields" style={{this.styleFP}}>
<div class="form-fields" id="fp{{this.iteration}}" style="{{this.styleFP}}">
<button type="button" class="file-picker" data-type="audio" data-target="src{{this.iteration}}" title="Browse Files" tabindex="-1">
<i class="fas fa-file-import fa-fw"></i>
</button>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 15 KiB