import { moduleName, sendWS, tokenControl, macroControl, combatTracker, playlistControl, soundboard, otherControls, externalModules, sceneControl } from "../MaterialDeck.js"; export class StreamDeck{ constructor() { this.pluginId; this.tokenHealthContext; this.tokenNameContext; this.tokenACContext; this.buttonContext = []; this.playlistTrackBuffer = []; this.playlistSelector = 0; this.trackSelector = 0; for (let i=0; i<23; i++) this.playlistTrackBuffer[i] = {state: 3, name: ""}; this.playlistBuffer = []; for (let i=0; i<3; i++) this.playlistBuffer[i] = {state: 3, name: ""}; this.counter = 0; let canvasBox = document.createElement('div'); canvasBox.id = 'sdCanvasBox'; document.body.appendChild(canvasBox); // adds the canvas to the body element this.syllableRegex = /[^aeiouy]*[aeiouy]+(?:[^aeiouy]*$|[^aeiouy](?=[^aeiouy]))?/gi; this.imageBuffer = []; this.imageBufferCounter = 0; } setScreen(action){ } //getButtonContext newDevice(iteration,device) { if (this.buttonContext[iteration] == undefined) { const deckSize = device.size.columns*device.size.rows; let buttons = []; for (let i=0; i0){ txtArray[counter] = ''; counter++; } let txtArrayTemp = txtArrayOriginal[i].split(" "); for (let j=0; j 10){ let syllables = this.syllabify(txtNewPart); for (let j=0; j j) newTxtArray[counter] += '-'; counter++; j++; } else { newTxtArray[counter] = syllables[j]; if (syllables.length > j) newTxtArray[counter] += '-'; counter++; } } } else{ newTxtArray[counter] = txtNewPart; counter++; } if (counter == 1 && newTxtArray[0] == "") counter = 0; } for (let i=0; i 0) txtNew += "\n"; if (i 31) this.counter = 0; let ctx = canvas.getContext("2d"); ctx.filter = "none"; let margin = 0; ctx.fillStyle = background; ctx.fillRect(0, 0, canvas.width, canvas.height); if (data.ring != undefined && data.ring > 0){ ctx.fillStyle = background; ctx.fillRect(0, 0, canvas.width, canvas.height); margin = 10; if (data.ring == 2) { ctx.fillStyle = data.ringColor; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = background; ctx.fillRect(margin, margin, canvas.width-2*margin, canvas.height-2*margin); } } else { } if (uses != undefined && uses.heart != undefined && (uses.available > 0 || uses.maximum != undefined)) { const percentage = 102*uses.available/uses.maximum; ctx.fillStyle = uses.heart; ctx.fillRect(0, 121,144,-percentage); } if (format == 'icon' && url != ""){ ctx.font = '600 90px "Font Awesome 5 Free"'; ctx.fillStyle = "#545454"; var elm = document.createElement('i'); elm.className = url; elm.style.display = 'none'; canvas.appendChild(elm); var content = window.getComputedStyle( elm, ':before' ).getPropertyValue('content') canvas.removeChild(elm); const iconMeasurement = ctx.measureText(content[1]); const horOffset = (144-iconMeasurement.width)/2; const vertOffset = 144-(iconMeasurement.actualBoundingBoxAscent-iconMeasurement.actualBoundingBoxDescent)/2; ctx.fillText(content[1], horOffset, vertOffset); } 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'); img.onload = () => { if (format == 'color') ctx.filter = "opacity(0)"; if (data.overlay == true) ctx.filter = "brightness(" + game.settings.get(moduleName,'imageBrightness') + "%)"; //ctx.filter = "brightness(0) saturate(100%) invert(38%) sepia(62%) saturate(2063%) hue-rotate(209deg) brightness(90%) contrast(95%)"; var imageAspectRatio = img.width / img.height; var canvasAspectRatio = canvas.width / canvas.height; var renderableHeight, renderableWidth, xStart, yStart; // If image's aspect ratio is less than canvas's we fit on height // and place the image centrally along width if(imageAspectRatio < canvasAspectRatio) { renderableHeight = canvas.height; renderableWidth = img.width * (renderableHeight / img.height); xStart = (canvas.width - renderableWidth) / 2; yStart = 0; } // If image's aspect ratio is greater than canvas's we fit on width // and place the image centrally along height else if(imageAspectRatio > canvasAspectRatio) { renderableWidth = canvas.width renderableHeight = img.height * (renderableWidth / img.width); xStart = 0; yStart = (canvas.height - renderableHeight) / 2; } // Happy path - keep aspect ratio else { renderableHeight = canvas.height; renderableWidth = canvas.width; xStart = 0; yStart = 0; } ctx.drawImage(img, xStart+margin, yStart+margin, renderableWidth - 2*margin, renderableHeight - 2*margin); if (uses != undefined && uses.heart == undefined) { let txt = ''; let noMaxUses = false; if (uses.available != undefined) { txt = uses.available; if (uses.maximum != undefined) txt = uses.available + '/' + uses.maximum; if (uses.maximum == undefined ) { uses.maximum = 1; noMaxUses = true; } } ctx.beginPath(); ctx.lineWidth = 4; let green = Math.ceil(255*(uses.available/uses.maximum)); let red = 255-green; green = green.toString(16); if (green.length == 1) green = "0"+green; red = red.toString(16); if (red.length == 1) red = "0"+red; if (noMaxUses) ctx.strokeStyle = "#c000000"; else if (uses.available == 0) ctx.strokeStyle = "#c80000"; else ctx.strokeStyle = "#"+red.toString(16)+green.toString(16)+"00"; const rect = {height:35, paddingSides:20, paddingBottom: 4} ctx.rect(rect.paddingSides, 144-rect.height-rect.paddingBottom,144-2*rect.paddingSides,rect.height); ctx.globalAlpha = 0.5; ctx.fillRect(rect.paddingSides, 144-rect.height-rect.paddingBottom,144-2*rect.paddingSides,rect.height); ctx.globalAlpha = 1; ctx.fillStyle = "white"; ctx.font = "24px Arial"; ctx.fillText(txt, (canvas.width - ctx.measureText(txt).width) / 2, 144-rect.height-rect.paddingBottom+25); ctx.stroke(); } if (data.options.clock != undefined) { if (data.options.clock != false && data.options.clock != 'none') { const hourAngle = (data.options.clock.hours+data.options.clock.minutes/60)*Math.PI/6; const minuteAngle = data.options.clock.minutes*Math.PI/30; ctx.translate(72,72); //Draw outer circle ctx.beginPath(); ctx.lineWidth = 6; ctx.strokeStyle = "gray"; ctx.arc(0,0, 50, 0, 2 * Math.PI); ctx.stroke(); //Draw hour marks ctx.fillStyle = "gray"; ctx.beginPath(); for (let i=0; i<12; i++) { ctx.fillRect(-2,40,4,10); const angle = 2*Math.PI/12; ctx.rotate(angle); } //Draw hour arm ctx.rotate(Math.PI + hourAngle); ctx.rotate(0); ctx.fillRect(-4,0,8,30); ctx.stroke(); // ctx.rotate 8*Math.PI/12; ctx.beginPath(); ctx.rotate(-hourAngle + minuteAngle); ctx.fillStyle = "lightgray"; ctx.fillRect(-2,0,4,40); ctx.rotate(2*Math.PI/12); ctx.stroke(); //Draw inner circle ctx.beginPath(); ctx.arc(0,0, 5, 0, 2 * Math.PI); ctx.fill(); } } var dataURL = canvas.toDataURL(); canvas.remove(); const nr = this.addToImageBuffer(dataURL,data); this.setImage(dataURL,data.context,device,nr,this.getImageBufferId(data)); }; img.src = resImageURL; } getImageBufferId(data){ return data.url+data.background+data.ring+data.ringColor+data.overlay+data.uses?.available+data.uses?.maximum; } addToImageBuffer(img,data){ const id = this.getImageBufferId(data); const maxBufferSize = game.settings.get(moduleName,'imageBuffer'); if (maxBufferSize == 0) return false; if (this.imageBufferCounter > maxBufferSize) this.imageBufferCounter = 0; const newData = { id: id, img: img } if (this.imageBuffer[this.imageBufferCounter] == undefined) this.imageBuffer.push(newData); else this.imageBuffer[this.imageBufferCounter] = newData; this.imageBufferCounter++; return this.imageBufferCounter - 1; } checkImageBuffer(data){ if (game.settings.get(moduleName,'imageBuffer') == 0) return false; const id = this.getImageBufferId(data); for (let i=0; i