mirror of
https://github.com/Investigamer/cardconjurer.git
synced 2025-07-27 05:14:53 -05:00
1387 lines
63 KiB
JavaScript
1387 lines
63 KiB
JavaScript
//URL Params
|
|
var params = new URLSearchParams(window.location.search);
|
|
//To save the server from being overloaded? Maybe?
|
|
function fixUri(input) {
|
|
var prefix = 'https://card-conjurer.storage.googleapis.com';//'https://raw.githubusercontent.com/ImKyle4815/cardconjurer/remake';
|
|
if (input.includes(prefix) || input.includes('http') || input.includes('data:image') || window.location.href.includes('localhost')) {
|
|
return input;
|
|
} else {
|
|
return prefix + input; //input.replace('/img/frames', prefix + '/img/frames');
|
|
}
|
|
}
|
|
//card object
|
|
var card = {width:1500, height:2100, marginX:0, marginY:0, frames:[], artSource:fixUri('/img/blank.png'), artX:0, artY:0, artZoom:1, setSymbolSource:fixUri('/img/blank.png'), setSymbolX:0, setSymbolY:0, setSymbolZoom:1, watermarkSource:fixUri('/img/blank.png'), watermarkX:0, watermarkY:0, watermarkZoom:1, watermarkLeft:'none', watermarkRight:'none', watermarkOpacity:0.4, version:'', manaSymbols:[]};
|
|
//core images/masks
|
|
const black = new Image(); black.crossOrigin = 'anonymous'; black.src = fixUri('/img/black.png');
|
|
const blank = new Image(); blank.crossOrigin = 'anonymous'; blank.src = fixUri('/img/blank.png');
|
|
const right = new Image(); right.crossOrigin = 'anonymous'; right.src = fixUri('/img/frames/maskRightHalf.png');
|
|
const middle = new Image(); middle.crossOrigin = 'anonymous'; middle.src = fixUri('/img/frames/maskMiddleThird.png');
|
|
const corner = new Image(); corner.crossOrigin = 'anonymous'; corner.src = fixUri('/img/frames/cornerCutout.png');
|
|
//art
|
|
art = new Image(); art.crossOrigin = 'anonymous'; art.src = blank.src;
|
|
art.onerror = function() {if (!this.src.includes('/img/blank.png')) {this.src = fixUri('/img/blank.png');}}
|
|
art.onload = artEdited;
|
|
//set symbol
|
|
setSymbol = new Image(); setSymbol.crossOrigin = 'anonymous'; setSymbol.src = blank.src;
|
|
setSymbol.onerror = function() {if (!this.src.includes('/img/blank.png')) {this.src = fixUri('/img/blank.png');}}
|
|
setSymbol.onload = setSymbolEdited;
|
|
//watermark
|
|
watermark = new Image(); watermark.crossOrigin = 'anonymous'; watermark.src = blank.src;
|
|
watermark.onerror = function() {if (!this.src.includes('/img/blank.png')) {this.src = fixUri('/img/blank.png');}}
|
|
watermark.onload = watermarkEdited;
|
|
//preview canvas
|
|
var previewCanvas = document.querySelector('#previewCanvas');
|
|
var previewContext = previewCanvas.getContext('2d');
|
|
var canvasList = [];
|
|
//frame/mask picker stuff
|
|
var availableFrames = [];
|
|
var selectedFrameIndex = 0;
|
|
var selectedMaskIndex = 0;
|
|
var selectedTextIndex = 0;
|
|
//for imports
|
|
var scryfallArt;
|
|
var scryfallCard;
|
|
//for text
|
|
var savedTextXPosition = 0;
|
|
//for misc
|
|
var date = new Date();
|
|
//to avoid rerunning special scripts (planeswalker, saga, etc...)
|
|
var loadedVersions = [];
|
|
//Card Object managament
|
|
async function resetCardIrregularities({canvas = [1500, 2100, 0, 0], resetOthers = true} = {}) {
|
|
//misc details
|
|
card.margins = false;
|
|
//rotation
|
|
if (card.landscape) {
|
|
previewContext.scale(5/7, 7/5);
|
|
previewContext.rotate(Math.PI / 2);
|
|
previewContext.translate(0, -card.width / 2);
|
|
card.landscape = false;
|
|
}
|
|
//card size
|
|
card.width = canvas[0];
|
|
card.height = canvas[1];
|
|
card.marginX = canvas[2];
|
|
card.marginY = canvas[3];
|
|
//canvases
|
|
canvasList.forEach(name => {
|
|
if (window[name + 'Canvas'].width != card.width * (1 + card.marginX) || window[name + 'Canvas'].height != card.height * (1 + card.marginY)) {
|
|
sizeCanvas(name);
|
|
}
|
|
});
|
|
if (resetOthers) {
|
|
//bottom info
|
|
await loadBottomInfo({
|
|
midLeft: {text:'{elemidinfo-set}*{elemidinfo-language} {savex}{fontbelerenbsc}{fontsize' + scaleHeight(0.001) + '}{upinline' + scaleHeight(0.0005) + '}\uFFEE{elemidinfo-artist}', x:0.0647, y:0.9548, width:0.8707, height:0.0171, oneLine:true, font:'gothammedium', size:0.0171, color:'white', outlineWidth:0.003},
|
|
topLeft: {text:'{elemidinfo-number} {loadx}{elemidinfo-rarity}', x:0.0647, y:0.9377, width:0.8707, height:0.0171, oneLine:true, font:'gothammedium', size:0.0171, color:'white', outlineWidth:0.003},
|
|
bottomLeft: {text:'NOT FOR SALE', x:0.0647, y:0.9719, width:0.8707, height:0.0143, oneLine:true, font:'gothammedium', size:0.0143, color:'white', outlineWidth:0.003},
|
|
wizards: {name:'wizards', text:'{ptshift0,0.0172}\u2122 & \u00a9 ' + date.getFullYear() + ' Wizards of the Coast', x:0.0647, y:0.9377, width:0.8707, height:0.0167, oneLine:true, font:'mplantin', size:0.0162, color:'white', align:'right', outlineWidth:0.003},
|
|
bottomRight: {text:'{ptshift0,0.0172}CardConjurer.com', x:0.0647, y:0.9548, width:0.8707, height:0.0143, oneLine:true, font:'mplantin', size:0.0143, color:'white', align:'right', outlineWidth:0.003}
|
|
});
|
|
//onload
|
|
card.onload = null;
|
|
}
|
|
}
|
|
//Canvas management
|
|
function sizeCanvas(name, width = Math.round(card.width * (1 + 2 * card.marginX)), height = Math.round(card.height * (1 + 2 * card.marginY))) {
|
|
if (!window[name + 'Canvas']) {
|
|
window[name + 'Canvas'] = document.createElement('canvas');
|
|
window[name + 'Context'] = window[name + 'Canvas'].getContext('2d');
|
|
canvasList[canvasList.length] = name;
|
|
}
|
|
window[name + 'Canvas'].width = width;
|
|
window[name + 'Canvas'].height = height;
|
|
// var label = document.createElement('p');
|
|
// label.innerHTML = name;
|
|
// window[name + 'Canvas'].style = 'width: 20rem; height: 28rem; border: 1px solid red;';
|
|
// document.body.appendChild(window[name + 'Canvas']);
|
|
// document.body.appendChild(label);
|
|
}
|
|
//create main canvases
|
|
sizeCanvas('card');
|
|
sizeCanvas('frame');
|
|
sizeCanvas('frameMasking');
|
|
sizeCanvas('text');
|
|
sizeCanvas('paragraph');
|
|
sizeCanvas('line');
|
|
sizeCanvas('watermark');
|
|
sizeCanvas('bottomInfo');
|
|
//Scaling
|
|
function scaleX(input) {
|
|
return Math.round((input + card.marginX) * card.width);
|
|
}
|
|
function scaleWidth(input) {
|
|
return Math.round(input * card.width);
|
|
}
|
|
function scaleY(input) {
|
|
return Math.round((input + card.marginY) * card.height);
|
|
}
|
|
function scaleHeight(input) {
|
|
return Math.round(input * card.height);
|
|
}
|
|
//Other nifty functions
|
|
function getElementIndex(element) {
|
|
return Array.prototype.indexOf.call(element.parentElement.children, element);
|
|
}
|
|
//UI
|
|
function toggleCreatorTabs(event, target) {
|
|
Array.from(document.querySelector('#creator-menu-sections').children).forEach(element => element.classList.add('hidden'));
|
|
document.querySelector('#creator-menu-' + target).classList.remove('hidden');
|
|
selectSelectable(event);
|
|
}
|
|
function selectSelectable(event) {
|
|
var eventTarget = event.target.closest('.selectable');
|
|
Array.from(eventTarget.parentElement.children).forEach(element => element.classList.remove('selected'));
|
|
eventTarget.classList.add('selected');
|
|
}
|
|
function dragStart(event) {
|
|
Array.from(document.querySelectorAll('.dragging')).forEach(element => element.classList.remove('dragging'));
|
|
event.target.closest('.draggable').classList.add('dragging');
|
|
}
|
|
function dragEnd(event) {
|
|
Array.from(document.querySelectorAll('.dragging')).forEach(element => element.classList.remove('dragging'));
|
|
}
|
|
function touchMove(event) {
|
|
if (event.target.nodeName != 'H4') {
|
|
event.preventDefault();
|
|
}
|
|
var clientX = event.touches[0].clientX;
|
|
var clientY = event.touches[0].clientY;
|
|
Array.from(document.querySelector('.dragging').parentElement.children).forEach(element => {
|
|
var elementBounds = element.getBoundingClientRect();
|
|
if (clientY > elementBounds.top && clientY < elementBounds.bottom) {
|
|
dragOver(element, false);
|
|
}
|
|
})
|
|
}
|
|
function dragOver(event, drag=true) {
|
|
var eventTarget;
|
|
if (drag) {
|
|
eventTarget = event.target.closest('.draggable');
|
|
} else {
|
|
eventTarget = event;
|
|
}
|
|
var movingElement = document.querySelector('.dragging');
|
|
if (document.querySelector('.dragging') && !eventTarget.classList.contains('dragging') && eventTarget.parentElement == movingElement.parentElement) {
|
|
var parentElement = eventTarget.parentElement;
|
|
var elements = document.createDocumentFragment();
|
|
var movingElementPassed = false;
|
|
var movingElementOldIndex = -1;
|
|
var movingElementNewIndex = -1;
|
|
Array.from(parentElement.children).forEach((element, index) => {
|
|
if (element == eventTarget) {
|
|
movingElementNewIndex = index;
|
|
if(movingElementPassed) {
|
|
elements.appendChild(element.cloneNode(true));
|
|
elements.appendChild(movingElement.cloneNode(true));
|
|
} else {
|
|
elements.appendChild(movingElement.cloneNode(true));
|
|
elements.appendChild(element.cloneNode(true));
|
|
}
|
|
} else if(element != movingElement) {
|
|
elements.appendChild(element.cloneNode(true));
|
|
} else {
|
|
movingElementOldIndex = index;
|
|
movingElementPassed = true;
|
|
}
|
|
});
|
|
Array.from(elements.children).forEach(element => {
|
|
element.ondragstart = dragStart;
|
|
element.ontouchstart = dragStart;
|
|
element.ondragend = dragEnd;
|
|
element.ontouchend = dragEnd;
|
|
element.ondragover = dragOver;
|
|
element.ontouchmove = touchMove;
|
|
element.onclick = frameElementClicked;
|
|
element.children[3].onclick = removeFrame;
|
|
})
|
|
parentElement.innerHTML = null;
|
|
parentElement.appendChild(elements);
|
|
if (movingElementNewIndex >= 0) {
|
|
var originalMovingElement = card.frames[movingElementOldIndex];
|
|
card.frames.splice(movingElementOldIndex, 1);
|
|
card.frames.splice(movingElementNewIndex, 0, originalMovingElement);
|
|
drawFrames();
|
|
}
|
|
}
|
|
}
|
|
function toggleCollapse(event) {
|
|
event.target.closest('.collapsible').classList.toggle('collapsed');
|
|
}
|
|
//Mana Symbols
|
|
var manaSymbols = [];
|
|
loadManaSymbols(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', 'w', 'u', 'b', 'r', 'g', 'c', 'x', 'y', 'z', 't', 'untap', 'e', 'snow', 'chaos']);
|
|
loadManaSymbols(['wu', 'wb', 'ub', 'ur', 'br', 'bg', 'rg', 'rw', 'gw', 'gu', '2w', '2u', '2b', '2r', '2g', 'wp', 'up', 'bp', 'rp', 'gp'], [1.2, 1.2]);
|
|
loadManaSymbols(['bar.png', 'whitebar.png']);
|
|
loadManaSymbols(['chaos'], [1, 10.2]);
|
|
function loadManaSymbols(manaSymbolPaths, size = [1, 1]) {
|
|
manaSymbolPaths.forEach(item => {
|
|
var manaSymbol = {};
|
|
if (typeof item == 'string') {
|
|
manaSymbol.name = item.split('.')[0];
|
|
manaSymbol.path = item;
|
|
} else {
|
|
manaSymbol.name = item[0].split('.')[0];
|
|
manaSymbol.path = item[0];
|
|
}
|
|
if (manaSymbol.name.includes('/')) {
|
|
manaSymbol.name = manaSymbol.name.split('/');
|
|
manaSymbol.name = manaSymbol.name[manaSymbol.name.length - 1];
|
|
}
|
|
if (typeof item != 'string') {
|
|
manaSymbol.back = item[1];
|
|
manaSymbol.backs = item[2];
|
|
for (var i = 0; i < item[2]; i ++) {
|
|
loadManaSymbols([manaSymbol.path.replace(manaSymbol.name, 'back' + i + item[1])])
|
|
}
|
|
}
|
|
manaSymbol.width = size[0];
|
|
manaSymbol.height = size[1];
|
|
manaSymbol.image = new Image();
|
|
manaSymbol.image.crossOrigin = 'anonymous';
|
|
var manaSymbolPath = '/img/manaSymbols/' + manaSymbol.path;
|
|
if (!manaSymbolPath.includes('.png')) {
|
|
manaSymbolPath += '.svg';
|
|
}
|
|
manaSymbol.image.src = fixUri(manaSymbolPath);
|
|
manaSymbols.push(manaSymbol);
|
|
});
|
|
}
|
|
function findManaSymbolIndex(string) {
|
|
return manaSymbols.findIndex(element => element.name == string);
|
|
}
|
|
//FRAME TAB
|
|
function drawFrames() {
|
|
frameContext.clearRect(0, 0, frameCanvas.width, frameCanvas.height);
|
|
var frameToDraw = card.frames.slice().reverse();
|
|
frameToDraw.forEach(item => {
|
|
if (item.image) {
|
|
frameContext.globalCompositeOperation = item.mode || 'source-over';
|
|
frameContext.globalAlpha = item.opacity / 100 || 1;
|
|
if (item.opacity == 0) {
|
|
frameContext.globalAlpha = 0;
|
|
}
|
|
var bounds = item.bounds || {};
|
|
var ogBounds = item.ogBounds || bounds;
|
|
frameX = Math.round(scaleX(bounds.x || 0));
|
|
frameY = Math.round(scaleY(bounds.y || 0));
|
|
frameWidth = Math.round(scaleWidth(bounds.width || 1));
|
|
frameHeight = Math.round(scaleHeight(bounds.height || 1));
|
|
frameMaskingContext.globalCompositeOperation = 'source-over';
|
|
frameMaskingContext.drawImage(black, 0, 0, frameMaskingCanvas.width, frameMaskingCanvas.height);
|
|
frameMaskingContext.globalCompositeOperation = 'source-in';
|
|
item.masks.forEach(mask => frameMaskingContext.drawImage(mask.image, scaleX((bounds.x || 0) - (ogBounds.x || 0) - ((ogBounds.x || 0) * ((bounds.width || 1) / (ogBounds.width || 1) - 1))), scaleY((bounds.y || 0) - (ogBounds.y || 0) - ((ogBounds.y || 0) * ((bounds.height || 1) / (ogBounds.height || 1) - 1))), scaleWidth((bounds.width || 1) / (ogBounds.width || 1)), scaleHeight((bounds.height || 1) / (ogBounds.height || 1))));
|
|
frameMaskingContext.drawImage(item.image, frameX, frameY, frameWidth, frameHeight);
|
|
if (item.erase) {frameContext.globalCompositeOperation = 'destination-out';}
|
|
frameContext.drawImage(frameMaskingCanvas, 0, 0, frameCanvas.width, frameCanvas.height);
|
|
}
|
|
});
|
|
drawCard();
|
|
}
|
|
function loadFramePacks(framePackOptions = []) {
|
|
document.querySelector('#selectFramePack').innerHTML = null;
|
|
framePackOptions.forEach(item => {
|
|
var framePackOption = document.createElement('option');
|
|
framePackOption.innerHTML = item.name;
|
|
if (item.value == 'disabled') {
|
|
framePackOption.disabled = true;
|
|
} else {
|
|
framePackOption.value = item.value;
|
|
}
|
|
document.querySelector('#selectFramePack').appendChild(framePackOption);
|
|
});
|
|
loadScript("/js/frames/pack" + document.querySelector('#selectFramePack').value + ".js");
|
|
}
|
|
function loadFramePack(frameOptions = availableFrames) {
|
|
document.querySelector('#frame-picker').innerHTML = null;
|
|
frameOptions.forEach(item => {
|
|
var frameOption = document.createElement('div');
|
|
frameOption.classList = 'frame-option hidden';
|
|
frameOption.onclick = frameOptionClicked;
|
|
var frameOptionImage = document.createElement('img');
|
|
frameOption.appendChild(frameOptionImage);
|
|
frameOptionImage.onload = function() {
|
|
this.parentElement.classList.remove('hidden');
|
|
}
|
|
if (!item.noThumb && !item.src.includes('/img/black.png')) {
|
|
frameOptionImage.src = fixUri(item.src.replace('.png', 'Thumb.png').replace('.svg', 'Thumb.png'));
|
|
} else {
|
|
frameOptionImage.src = fixUri(item.src);
|
|
}
|
|
document.querySelector('#frame-picker').appendChild(frameOption);
|
|
|
|
})
|
|
document.querySelector('#frame-picker').children[0].click();
|
|
}
|
|
function frameOptionClicked(event) {
|
|
var clickedFrameOption = event.target.closest('.frame-option');
|
|
if (document.querySelector('.frame-option.selected')) {
|
|
document.querySelector('.frame-option.selected').classList.remove('selected');
|
|
}
|
|
clickedFrameOption.classList.add('selected');
|
|
selectedFrameIndex = getElementIndex(clickedFrameOption);
|
|
document.querySelector('#mask-picker').innerHTML = '<div class="mask-option selected" onclick="maskOptionClicked(event)"><img src="' + black.src + '"><p>No Mask</p></div>';
|
|
selectedMaskIndex = 0;
|
|
document.querySelector('#selectedPreview').innerHTML = '(Selected: ' + availableFrames[selectedFrameIndex].name + ', No Mask)';
|
|
if (availableFrames[selectedFrameIndex].masks) {
|
|
availableFrames[selectedFrameIndex].masks.forEach(item => {
|
|
var maskOption = document.createElement('div');
|
|
maskOption.classList = 'mask-option hidden';
|
|
maskOption.onclick = maskOptionClicked;
|
|
var maskOptionImage = document.createElement('img');
|
|
maskOption.appendChild(maskOptionImage);
|
|
maskOptionImage.onload = function() {
|
|
this.parentElement.classList.remove('hidden');
|
|
}
|
|
maskOptionImage.src = fixUri(item.src.replace('.png', 'Thumb.png').replace('.svg', 'Thumb.png'));
|
|
maskOptionLabel = document.createElement('p');
|
|
maskOptionLabel.innerHTML = item.name;
|
|
maskOption.appendChild(maskOptionLabel);
|
|
document.querySelector('#mask-picker').appendChild(maskOption);
|
|
});
|
|
}
|
|
}
|
|
function maskOptionClicked(event) {
|
|
var clickedMaskOption = event.target.closest('.mask-option');
|
|
document.querySelector('.mask-option.selected').classList.remove('selected');
|
|
clickedMaskOption.classList.add('selected');
|
|
selectedMaskIndex = getElementIndex(clickedMaskOption);
|
|
var selectedMaskName = 'No Mask'
|
|
if (selectedMaskIndex > 0) {selectedMaskName = availableFrames[selectedFrameIndex].masks[selectedMaskIndex - 1].name;}
|
|
document.querySelector('#selectedPreview').innerHTML = '(Selected: ' + availableFrames[selectedFrameIndex].name + ', ' + selectedMaskName + ')';
|
|
}
|
|
function addFrame(additionalMasks = [], loadingFrame = false) {
|
|
var frameToAdd = JSON.parse(JSON.stringify(availableFrames[selectedFrameIndex]));
|
|
var maskThumbnail = true;
|
|
if (!loadingFrame) {
|
|
if (frameToAdd.masks && selectedMaskIndex > 0) {
|
|
frameToAdd.masks = frameToAdd.masks.slice(selectedMaskIndex - 1, selectedMaskIndex);
|
|
} else {
|
|
frameToAdd.masks = [];
|
|
maskThumbnail = false;
|
|
}
|
|
additionalMasks.forEach(item => frameToAdd.masks.push(item));
|
|
} else {
|
|
frameToAdd = loadingFrame;
|
|
if (frameToAdd.masks.length == 0 || (frameToAdd.masks[0].src.includes('/img/frames/mask'))) {
|
|
maskThumbnail = false;
|
|
}
|
|
}
|
|
frameToAdd.masks.forEach(item => {
|
|
item.image = new Image();
|
|
item.image.crossOrigin = 'anonymous';
|
|
item.image.src = blank.src;
|
|
item.image.onload = drawFrames;
|
|
item.image.src = fixUri(item.src);
|
|
});
|
|
frameToAdd.image = new Image();
|
|
frameToAdd.image.crossOrigin = 'anonymous'
|
|
frameToAdd.image.src = blank.src;
|
|
frameToAdd.image.onload = drawFrames;
|
|
frameToAdd.image.src = fixUri(frameToAdd.src);
|
|
if (!loadingFrame) {
|
|
card.frames.unshift(frameToAdd);
|
|
}
|
|
var frameElement = document.createElement('div');
|
|
frameElement.classList = 'draggable frame-element';
|
|
frameElement.draggable = 'true';
|
|
frameElement.ondragstart = dragStart;
|
|
frameElement.ondragend = dragEnd;
|
|
frameElement.ondragover = dragOver;
|
|
frameElement.ontouchstart = dragStart;
|
|
frameElement.ontouchend = dragEnd;
|
|
frameElement.ontouchmove = touchMove;
|
|
frameElement.onclick = frameElementClicked;
|
|
var frameElementImage = document.createElement('img');
|
|
if (frameToAdd.noThumb || frameToAdd.src.includes('/img/black.png')) {
|
|
frameElementImage.src = fixUri(frameToAdd.src);
|
|
} else {
|
|
frameElementImage.src = fixUri(frameToAdd.src.replace('.png', 'Thumb.png'));
|
|
}
|
|
frameElement.appendChild(frameElementImage);
|
|
var frameElementMask = document.createElement('img');
|
|
if (maskThumbnail) {
|
|
frameElementMask.src = fixUri(frameToAdd.masks[0].src.replace('.png', 'Thumb.png'));
|
|
} else {
|
|
frameElementMask.src = black.src;
|
|
}
|
|
frameElement.appendChild(frameElementMask);
|
|
var frameElementLabel = document.createElement('h4');
|
|
frameElementLabel.innerHTML = frameToAdd.name;
|
|
frameToAdd.masks.forEach(item => frameElementLabel.innerHTML += ', ' + item.name);
|
|
frameElement.appendChild(frameElementLabel);
|
|
var frameElementClose = document.createElement('h4');
|
|
frameElementClose.innerHTML = 'X';
|
|
frameElementClose.classList = 'frame-element-close';
|
|
frameElementClose.onclick = removeFrame;
|
|
frameElement.appendChild(frameElementClose);
|
|
document.querySelector('#frame-list').prepend(frameElement);
|
|
bottomInfoEdited();
|
|
}
|
|
function removeFrame(event) {
|
|
card.frames.splice(getElementIndex(event.target.parentElement), 1);
|
|
event.target.parentElement.remove();
|
|
drawFrames();
|
|
bottomInfoEdited();
|
|
}
|
|
function frameElementClicked(event) {
|
|
if (!event.target.classList.contains('frame-element-close')) {
|
|
var selectedFrameElement = event.target.closest('.frame-element');
|
|
var selectedFrame = card.frames[Array.from(selectedFrameElement.parentElement.children).indexOf(selectedFrameElement)];
|
|
document.querySelector('#frame-element-editor').classList.add('opened');
|
|
selectedFrame.bounds = selectedFrame.bounds || {};
|
|
if (selectedFrame.ogBounds == undefined) {
|
|
selectedFrame.ogBounds = JSON.parse(JSON.stringify(selectedFrame.bounds));
|
|
}
|
|
document.querySelector('#frame-editor-x').value = scaleWidth(selectedFrame.bounds.x || 0);
|
|
document.querySelector('#frame-editor-x').onchange = (event) => {selectedFrame.bounds.x = (event.target.value / card.width); drawFrames();}
|
|
document.querySelector('#frame-editor-y').value = scaleHeight(selectedFrame.bounds.y || 0);
|
|
document.querySelector('#frame-editor-y').onchange = (event) => {selectedFrame.bounds.y = (event.target.value / card.height); drawFrames();}
|
|
document.querySelector('#frame-editor-width').value = scaleWidth(selectedFrame.bounds.width || 1);
|
|
document.querySelector('#frame-editor-width').onchange = (event) => {selectedFrame.bounds.width = (event.target.value / card.width); drawFrames();}
|
|
document.querySelector('#frame-editor-height').value = scaleHeight(selectedFrame.bounds.height || 1);
|
|
document.querySelector('#frame-editor-height').onchange = (event) => {selectedFrame.bounds.height = (event.target.value / card.height); drawFrames();}
|
|
document.querySelector('#frame-editor-opacity').value = selectedFrame.opacity || 100;
|
|
document.querySelector('#frame-editor-opacity').onchange = (event) => {selectedFrame.opacity = event.target.value; drawFrames();}
|
|
document.querySelector('#frame-editor-erase').checked = selectedFrame.erase || false;
|
|
document.querySelector('#frame-editor-erase').onchange = (event) => {selectedFrame.erase = event.target.checked; drawFrames();}
|
|
}
|
|
}
|
|
function uploadFrameOption(imageSource) {
|
|
var uploadedFrame = {name:'Uploaded Image', src:imageSource, noThumb:true}
|
|
availableFrames.push(uploadedFrame);
|
|
loadFramePack();
|
|
}
|
|
//TEXT TAB
|
|
var writingText;
|
|
function loadTextOptions(textObject) {
|
|
var oldCardText = card.text || {};
|
|
card.text = textObject;
|
|
document.querySelector('#text-options').innerHTML = null;
|
|
Object.entries(card.text).forEach(item => {
|
|
if (oldCardText[item[0]]) {
|
|
card.text[item[0]].text = oldCardText[item[0]].text;
|
|
}
|
|
var textOptionElement = document.createElement('h4');
|
|
textOptionElement.innerHTML = item[1].name;
|
|
textOptionElement.classList = 'selectable text-option'
|
|
textOptionElement.onclick = textOptionClicked;
|
|
document.querySelector('#text-options').appendChild(textOptionElement);
|
|
});
|
|
document.querySelector('#text-options').firstChild.click();
|
|
drawTextBuffer();
|
|
}
|
|
function textOptionClicked(event) {
|
|
selectedTextIndex = getElementIndex(event.target);
|
|
document.querySelector('#text-editor').value = Object.entries(card.text)[selectedTextIndex][1].text;
|
|
selectSelectable(event);
|
|
}
|
|
function textboxEditor() {
|
|
var selectedTextbox = card.text[Object.keys(card.text)[selectedTextIndex]];
|
|
document.querySelector('#textbox-editor').classList.add('opened');
|
|
document.querySelector('#textbox-editor-x').value = scaleWidth(selectedTextbox.x || 0);
|
|
document.querySelector('#textbox-editor-x').onchange = (event) => {selectedTextbox.x = (event.target.value / card.width); textEdited();}
|
|
document.querySelector('#textbox-editor-y').value = scaleHeight(selectedTextbox.y || 0);
|
|
document.querySelector('#textbox-editor-y').onchange = (event) => {selectedTextbox.y = (event.target.value / card.height); textEdited();}
|
|
document.querySelector('#textbox-editor-width').value = scaleWidth(selectedTextbox.width || 1);
|
|
document.querySelector('#textbox-editor-width').onchange = (event) => {selectedTextbox.width = (event.target.value / card.width); textEdited();}
|
|
document.querySelector('#textbox-editor-height').value = scaleHeight(selectedTextbox.height || 1);
|
|
document.querySelector('#textbox-editor-height').onchange = (event) => {selectedTextbox.height = (event.target.value / card.height); textEdited();}
|
|
}
|
|
function textEdited() {
|
|
card.text[Object.keys(card.text)[selectedTextIndex]].text = document.querySelector('#text-editor').value;
|
|
drawTextBuffer();
|
|
}
|
|
function drawTextBuffer() {
|
|
clearTimeout(writingText);
|
|
writingText = setTimeout(drawText, 500);
|
|
}
|
|
async function drawText() {
|
|
textContext.clearRect(0, 0, textCanvas.width, textCanvas.height);
|
|
for (var textObject of Object.entries(card.text)) {
|
|
await writeText(textObject[1], textContext);
|
|
continue;
|
|
}
|
|
drawCard();
|
|
}
|
|
function writeText(textObject, targetContext) {
|
|
//Most bits of info about text loaded, with defaults when needed
|
|
var textX = scaleX(textObject.x) || scaleX(0);
|
|
var textY = scaleY(textObject.y) || scaleY(0);
|
|
var textWidth = scaleWidth(textObject.width) || scaleWidth(1);
|
|
var textHeight = scaleHeight(textObject.height) || scaleHeight(1);
|
|
var startingTextSize = scaleHeight(textObject.size) || scaleHeight(0.038);
|
|
var textFontHeightRatio = 0.7;
|
|
var textBounded = textObject.bounded || true;
|
|
var textOneLine = textObject.oneLine || false;
|
|
var textManaCost = textObject.manaCost || false;
|
|
var textManaSpacing = scaleWidth(textObject.manaSpacing) || 0;
|
|
//Buffers the canvases accordingly
|
|
var canvasMargin = 300;
|
|
paragraphCanvas.width = textWidth + 2 * canvasMargin;
|
|
paragraphCanvas.height = textHeight + 2 * canvasMargin;
|
|
lineCanvas.width = textWidth + 2 * canvasMargin;
|
|
lineCanvas.height = startingTextSize + 2 * canvasMargin;
|
|
//Preps the text string
|
|
var splitString = '6GJt7eL8';
|
|
var rawText = textObject.text
|
|
if (params.get('copyright') != null && textObject.name == 'wizards' && card.margins) {
|
|
rawText = params.get('copyright'); //so people using CC for custom card games can customize their copyright info
|
|
}
|
|
var splitText = rawText.replace(/\n/g, '{line}').replace('{flavor}', '{lns}{bar}{lns}{fixtextalign}{i}').replace(/{/g, splitString + '{').replace(/}/g, '}' + splitString).replace(/ /g, splitString + ' ' + splitString).split(splitString);
|
|
splitText = splitText.filter(item => item);
|
|
// if (textManaCost && textObject.arcStart > 0) {
|
|
// splitText.reverse();
|
|
// }
|
|
if (textObject.manaCost) {
|
|
splitText = splitText.filter(item => item != ' ');
|
|
}
|
|
splitText.push('');
|
|
//Manages the redraw loop
|
|
var drawingText = true;
|
|
//Repeatedly tries to draw the text at smaller and smaller sizes until it fits
|
|
outerloop: while (drawingText) {
|
|
//Rest of the text info loaded that may have been changed by a previous attempt at drawing the text
|
|
var textColor = textObject.color || 'black';
|
|
var textFont = textObject.font || 'mplantin';
|
|
var textAlign = textObject.align || 'left';
|
|
var textShadowColor = textObject.shadow || 'black';
|
|
var textShadowOffsetX = scaleWidth(textObject.shadowX) || 0;
|
|
var textShadowOffsetY = scaleHeight(textObject.shadowY) || 0;
|
|
var textShadowBlur = scaleHeight(textObject.shadowBlur) || 0;
|
|
var textArcRadius = scaleHeight(textObject.arcRadius) || 0;
|
|
if (textArcRadius > 0) {
|
|
//Buffers the canvases accordingly
|
|
var canvasMargin = 300 + textArcRadius;
|
|
paragraphCanvas.width = textWidth + 2 * canvasMargin;
|
|
paragraphCanvas.height = textHeight + 2 * canvasMargin;
|
|
lineCanvas.width = textWidth + 2 * canvasMargin;
|
|
lineCanvas.height = startingTextSize + 2 * canvasMargin;
|
|
}
|
|
var textArcStart = textObject.arcStart || 0;
|
|
//Variables for tracking text position/size/font
|
|
var currentX = 0;
|
|
var startingCurrentX = 0;
|
|
var currentY = 0;
|
|
var lineY = 0;
|
|
var newLine = false;
|
|
var textFontExtension = '';
|
|
var textFontStyle = textObject.fontStyle || '';
|
|
var manaPlacementCounter = 0;
|
|
var realTextAlign = textAlign;
|
|
//variables that track various... things?
|
|
var newLineSpacing = 0;
|
|
var textSize = startingTextSize;
|
|
var ptShift = [0, 0];
|
|
var permaShift = [0, 0];
|
|
//Finish prepping canvases
|
|
paragraphContext.clearRect(0, 0, paragraphCanvas.width, paragraphCanvas.height);
|
|
lineContext.clearRect(0, 0, lineCanvas.width, lineCanvas.height);
|
|
lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
|
|
lineContext.fillStyle = textColor;
|
|
lineContext.shadowColor = textShadowColor;
|
|
lineContext.shadowOffsetX = textShadowOffsetX;
|
|
lineContext.shadowOffsetY = textShadowOffsetY;
|
|
lineContext.shadowBlur = textShadowBlur;
|
|
lineContext.strokeStyle = textObject.outlineColor || 'black';
|
|
var textOutlineWidth = scaleHeight(textObject.outlineWidth) || 0;
|
|
lineContext.lineWidth = textOutlineWidth;
|
|
//Begin looping through words/codes
|
|
innerloop: for (word of splitText) {
|
|
var wordToWrite = word;
|
|
if (wordToWrite.includes('{') && wordToWrite.includes('}') || textManaCost) {
|
|
var possibleCode = wordToWrite.toLowerCase().replace('{', '').replace('}', '');
|
|
wordToWrite = null;
|
|
if (possibleCode == 'line') {
|
|
newLine = true;
|
|
newLineSpacing = textSize * 0.35;
|
|
} else if (possibleCode == 'lns' || possibleCode == 'linenospace') {
|
|
newLine = true;
|
|
} else if (possibleCode == 'bar') {
|
|
var barWidth = textWidth * 0.95;
|
|
var barHeight = scaleHeight(0.002);
|
|
var barImageName = 'bar';
|
|
var barDistance = 0.45;
|
|
realTextAlign = textAlign;
|
|
textAlign = 'left';
|
|
if (textColor == 'white') {
|
|
barImageName = 'whitebar';
|
|
}
|
|
if (card.version == 'cartoony') {
|
|
barImageName = 'cflavor';
|
|
barWidth = scaleWidth(0.8547);
|
|
barHeight = scaleHeight(0.0458);
|
|
barDistance = -0.23;
|
|
newLineSpacing = textSize * -0.23;
|
|
textSize -= scaleHeight(0.0086);
|
|
}
|
|
lineContext.drawImage(manaSymbols[findManaSymbolIndex(barImageName)].image, canvasMargin + (textWidth - barWidth) / 2, canvasMargin + barDistance * textSize, barWidth, barHeight);
|
|
} else if (possibleCode == 'i') {
|
|
if (textFont == 'mplantin') {
|
|
textFontExtension = 'i';
|
|
textFontStyle = '';
|
|
} else {
|
|
textFontExtension = '';
|
|
textFontStyle = 'italic ';
|
|
}
|
|
lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
|
|
} else if (possibleCode == '/i') {
|
|
textFontExtension = '';
|
|
textFontStyle = '';
|
|
lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
|
|
} else if (possibleCode == 'left') {
|
|
textAlign = 'left';
|
|
} else if (possibleCode == 'center') {
|
|
textAlign = 'center';
|
|
} else if (possibleCode == 'right') {
|
|
textAlign = 'right';
|
|
} else if (possibleCode.includes('fontcolor')) {
|
|
textColor = possibleCode.replace('fontcolor', '');
|
|
lineContext.fillStyle = textColor;
|
|
} else if (possibleCode.includes('fontsize')) {
|
|
textSize += parseInt(possibleCode.replace('fontsize', '')) || 0;
|
|
lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
|
|
} else if (possibleCode.includes('font')) {
|
|
textFont = word.replace('{font', '').replace('}', '');
|
|
textFontExtension = '';
|
|
textFontStyle = '';
|
|
lineContext.font = textFontStyle + textSize + 'px ' + textFont + textFontExtension;
|
|
} else if (possibleCode.includes('outlinecolor')) {
|
|
lineContext.strokeStyle = possibleCode.replace('outlinecolor', '');
|
|
} else if (possibleCode.includes('outline')) {
|
|
textOutlineWidth = parseInt(possibleCode.replace('outline', ''));
|
|
lineContext.lineWidth = textOutlineWidth;
|
|
} else if (possibleCode.includes('upinline')) {
|
|
lineY -= parseInt(possibleCode.replace('upinline', '')) || 0;
|
|
} else if (possibleCode.includes('up') && possibleCode != 'up') {
|
|
currentY -= parseInt(possibleCode.replace('up', '')) || 0;
|
|
} else if (possibleCode.includes('down')) {
|
|
currentY += parseInt(possibleCode.replace('down', '')) || 0;
|
|
} else if (possibleCode.includes('left')) {
|
|
currentX -= parseInt(possibleCode.replace('left', '')) || 0;
|
|
} else if (possibleCode.includes('right')) {
|
|
currentX += parseInt(possibleCode.replace('right', '')) || 0;
|
|
} else if (possibleCode.includes('shadow')) {
|
|
if (possibleCode.includes('color')) {
|
|
textShadowColor = possibleCode.replace('shadowcolor', '');
|
|
lineContext.shadowColor = textShadowColor;
|
|
} else if (possibleCode.includes('blur')) {
|
|
textShadowBlur = parseInt(possibleCode.replace('shadowblur', '')) || 0;
|
|
lineContext.shadowBlur = textShadowBlur
|
|
} else if (possibleCode.includes('shadowx')) {
|
|
textShadowOffsetX = parseInt(possibleCode.replace('shadowx', '')) || 0;
|
|
lineContext.shadowOffsetX = textShadowOffsetX;
|
|
} else if (possibleCode.includes('shadowy')) {
|
|
textShadowOffsetY = parseInt(possibleCode.replace('shadowy', '')) || 0;
|
|
lineContext.shadowOffsetY = textShadowOffsetY;
|
|
} else {
|
|
textShadowOffsetX = parseInt(possibleCode.replace('shadow', '')) || 0;
|
|
textShadowOffsetY = textShadowOffsetX;
|
|
lineContext.shadowOffsetX = textShadowOffsetX;
|
|
lineContext.shadowOffsetY = textShadowOffsetY;
|
|
}
|
|
} else if (possibleCode == 'planechase') {
|
|
var planechaseHeight = textSize * 1.8;
|
|
lineContext.drawImage(manaSymbols[findManaSymbolIndex('chaos')].image, currentX + canvasMargin, canvasMargin, planechaseHeight * 1.2, planechaseHeight);
|
|
currentX += planechaseHeight * 1.3;
|
|
startingCurrentX += planechaseHeight * 1.3;
|
|
} else if (possibleCode.includes('elemid')) {
|
|
if (document.querySelector('#' + word.replace('{elemid', '').replace('}', ''))) {
|
|
wordToWrite = document.querySelector('#' + word.replace('{elemid', '').replace('}', '')).value || '';
|
|
}
|
|
} else if (possibleCode == 'savex') {
|
|
savedTextXPosition = currentX;
|
|
} else if (possibleCode == 'loadx') {
|
|
if (savedTextXPosition > currentX) {
|
|
currentX = savedTextXPosition;
|
|
}
|
|
} else if (possibleCode.includes('ptshift')) {
|
|
if (card.frames.findIndex(element => element.name.toLowerCase().includes('power/toughness')) >= 0 || card.version.includes('planeswalker') || card.version == 'commanderLegends' || card.version == 'm21') {
|
|
ptShift[0] = scaleWidth(parseFloat(possibleCode.replace('ptshift', '').split(',')[0]));
|
|
ptShift[1] = scaleHeight(parseFloat(possibleCode.split(',')[1]));
|
|
}
|
|
} else if (possibleCode.includes('permashift')) {
|
|
permaShift = [parseFloat(possibleCode.replace('permashift', '').split(',')[0]), parseFloat(possibleCode.split(',')[1])];
|
|
} else if (possibleCode.includes('arcradius')) {
|
|
textArcRadius = parseInt(possibleCode.replace('arcradius', '')) || 0;
|
|
} else if (possibleCode.includes('arcstart')) {
|
|
textArcStart = parseFloat(possibleCode.replace('arcstart', '')) || 0;
|
|
} else if (possibleCode.includes('fixtextalign')) {
|
|
textAlign = realTextAlign;
|
|
} else if (findManaSymbolIndex(possibleCode.replace('/', '')) > -1 || findManaSymbolIndex(possibleCode.replace('/', '').split('').reverse().join('')) > -1) {
|
|
possibleCode = possibleCode.replace('/', '')
|
|
var manaSymbol;
|
|
if (textObject.manaPrefix && (findManaSymbolIndex(textObject.manaPrefix + possibleCode) != -1 || findManaSymbolIndex(textObject.manaPrefix + possibleCode.split('').reverse().join('')) != -1)) {
|
|
manaSymbol = manaSymbols[findManaSymbolIndex(textObject.manaPrefix + possibleCode)] || manaSymbols[findManaSymbolIndex(textObject.manaPrefix + possibleCode.split('').reverse().join(''))];
|
|
} else {
|
|
manaSymbol = manaSymbols[findManaSymbolIndex(possibleCode)] || manaSymbols[findManaSymbolIndex(possibleCode.split('').reverse().join(''))];
|
|
}
|
|
var manaSymbolSpacing = textSize * 0.04 + textManaSpacing;
|
|
var manaSymbolWidth = manaSymbol.width * textSize * 0.78;
|
|
var manaSymbolHeight = manaSymbol.height * textSize * 0.78;
|
|
var manaSymbolX = currentX + canvasMargin + manaSymbolSpacing;
|
|
var manaSymbolY = canvasMargin + textSize * 0.34 - manaSymbolHeight / 2;
|
|
if (textObject.manaPlacement) {
|
|
manaSymbolX = scaleWidth(textObject.manaPlacement.x[manaPlacementCounter] || 0) + canvasMargin;
|
|
manaSymbolY = canvasMargin;
|
|
currentY = scaleHeight(textObject.manaPlacement.y[manaPlacementCounter] || 0);
|
|
manaPlacementCounter ++;
|
|
newLine = true;
|
|
} else if (textObject.manaLayout) {
|
|
var layoutOption = 0;
|
|
var manaSymbolCount = splitText.length - 1;
|
|
while (textObject.manaLayout[layoutOption].max < manaSymbolCount && layoutOption < textObject.manaLayout.length - 1) {
|
|
layoutOption ++;
|
|
}
|
|
var manaLayout = textObject.manaLayout[layoutOption];
|
|
if (manaLayout.pos[manaPlacementCounter] == undefined) {
|
|
manaLayout.pos[manaPlacementCounter] = [0, 0];
|
|
}
|
|
manaSymbolX = scaleWidth(manaLayout.pos[manaPlacementCounter][0] || 0) + canvasMargin;
|
|
manaSymbolY = canvasMargin;
|
|
currentY = scaleHeight(manaLayout.pos[manaPlacementCounter][1] || 0);
|
|
manaPlacementCounter ++;
|
|
manaSymbolWidth *= manaLayout.size;
|
|
manaSymbolHeight *= manaLayout.size;
|
|
newLine = true;
|
|
}
|
|
if (textObject.manaImageScale) {
|
|
currentX -= (textObject.manaImageScale - 1) * manaSymbolWidth;
|
|
manaSymbolX -= (textObject.manaImageScale - 1) / 2 * manaSymbolWidth;
|
|
manaSymbolY -= (textObject.manaImageScale - 1) / 2 * manaSymbolHeight;
|
|
manaSymbolWidth *= textObject.manaImageScale;
|
|
manaSymbolHeight *= textObject.manaImageScale;
|
|
}
|
|
//fake shadow begins
|
|
var fakeShadow = lineCanvas.cloneNode();
|
|
var fakeShadowContext = fakeShadow.getContext('2d');
|
|
fakeShadowContext.clearRect(0, 0, fakeShadow.width, fakeShadow.height);
|
|
var backImage = null;
|
|
if (manaSymbol.backs) {
|
|
backImage = manaSymbols[findManaSymbolIndex('back' + Math.floor(Math.random() * manaSymbol.backs) + manaSymbol.back)].image;
|
|
}
|
|
if (textArcRadius > 0) {
|
|
if (manaSymbol.backs) {
|
|
fakeShadowContext.drawImageArc(backImage, manaSymbolX, manaSymbolY, manaSymbolWidth, manaSymbolHeight, textArcRadius, textArcStart, currentX);
|
|
}
|
|
fakeShadowContext.drawImageArc(manaSymbol.image, manaSymbolX, manaSymbolY, manaSymbolWidth, manaSymbolHeight, textArcRadius, textArcStart, currentX);
|
|
} else {
|
|
if (manaSymbol.backs) {
|
|
fakeShadowContext.drawImage(backImage, manaSymbolX, manaSymbolY, manaSymbolWidth, manaSymbolHeight);
|
|
}
|
|
fakeShadowContext.drawImage(manaSymbol.image, manaSymbolX, manaSymbolY, manaSymbolWidth, manaSymbolHeight);
|
|
}
|
|
lineContext.drawImage(fakeShadow, 0, 0);
|
|
//fake shadow ends (thanks, safari)
|
|
currentX += manaSymbolWidth + manaSymbolSpacing * 2;
|
|
} else {
|
|
wordToWrite = word;
|
|
}
|
|
}
|
|
if (wordToWrite && lineContext.measureText(wordToWrite).width + currentX >= textWidth && textArcRadius == 0) {
|
|
if (textOneLine && startingTextSize > 1) {
|
|
//doesn't fit... try again at a smaller text size?
|
|
startingTextSize -= 1;
|
|
continue outerloop;
|
|
}
|
|
newLine = true;
|
|
}
|
|
if ((newLine && !textOneLine) || splitText.indexOf(word) == splitText.length - 1) {
|
|
var horizontalAdjust = 0
|
|
if (textAlign == 'center') {
|
|
horizontalAdjust = (textWidth - currentX) / 2;
|
|
} else if (textAlign == 'right') {
|
|
horizontalAdjust = textWidth - currentX;
|
|
}
|
|
paragraphContext.drawImage(lineCanvas, horizontalAdjust, currentY);
|
|
lineY = 0;
|
|
lineContext.clearRect(0, 0, lineCanvas.width, lineCanvas.height);
|
|
currentX = startingCurrentX;
|
|
currentY += textSize + newLineSpacing;
|
|
newLineSpacing = 0;
|
|
newLine = false;
|
|
}
|
|
if (wordToWrite && (currentX != 0 || wordToWrite != ' ') && !textManaCost) {
|
|
if (textArcRadius > 0) {
|
|
lineContext.fillTextArc(wordToWrite, currentX + canvasMargin, canvasMargin + textSize * textFontHeightRatio + lineY, textArcRadius, textArcStart, currentX, textOutlineWidth);
|
|
} else {
|
|
if (textOutlineWidth >= 1) {
|
|
lineContext.strokeText(wordToWrite, currentX + canvasMargin, canvasMargin + textSize * textFontHeightRatio + lineY);
|
|
}
|
|
lineContext.fillText(wordToWrite, currentX + canvasMargin, canvasMargin + textSize * textFontHeightRatio + lineY);
|
|
}
|
|
currentX += lineContext.measureText(wordToWrite).width;
|
|
}
|
|
if (currentY > textHeight && textBounded && !textOneLine && startingTextSize > 1 && textArcRadius == 0) {
|
|
//doesn't fit... try again at a smaller text size?
|
|
startingTextSize -= 1;
|
|
continue outerloop;
|
|
}
|
|
if (splitText.indexOf(word) == splitText.length - 1) {
|
|
//should manage vertical centering here
|
|
var verticalAdjust = 0;
|
|
if (!textObject.noVerticalCenter) {
|
|
verticalAdjust = (textHeight - currentY + textSize * 0.15) / 2;
|
|
}
|
|
targetContext.drawImage(paragraphCanvas, textX - canvasMargin + ptShift[0] + permaShift[0], textY - canvasMargin + verticalAdjust + ptShift[1] + permaShift[1]);
|
|
drawingText = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
CanvasRenderingContext2D.prototype.fillTextArc = function(text, x, y, radius, startRotation, distance = 0, outlineWidth = 0) {
|
|
this.save();
|
|
this.translate(x - distance + scaleWidth(0.5), y + radius);
|
|
this.rotate(startRotation + widthToAngle(distance, radius));
|
|
for (var i = 0; i < text.length; i++) {
|
|
var letter = text[i];
|
|
if (outlineWidth >= 1) {
|
|
this.strokeText(letter, 0, -radius);
|
|
}
|
|
this.fillText(letter, 0, -radius);
|
|
this.rotate(widthToAngle(this.measureText(letter).width, radius));
|
|
}
|
|
this.restore();
|
|
}
|
|
CanvasRenderingContext2D.prototype.drawImageArc = function(image, x, y, width, height, radius, startRotation, distance = 0) {
|
|
this.save();
|
|
this.translate(x - distance + scaleWidth(0.5), y + radius);
|
|
this.rotate(startRotation + widthToAngle(distance, radius));
|
|
this.drawImage(image, 0, -radius, width, height);
|
|
this.restore();
|
|
}
|
|
function widthToAngle(width, radius) {
|
|
return width / radius;
|
|
}
|
|
//ART TAB
|
|
function uploadArt(imageSource, otherParams) {
|
|
art.src = imageSource;
|
|
if (otherParams && otherParams == 'autoFit') {
|
|
art.onload = function() {
|
|
autoFitArt();
|
|
art.onload = artEdited;
|
|
};
|
|
}
|
|
}
|
|
function artEdited() {
|
|
card.artSource = art.src;
|
|
card.artX = document.querySelector('#art-x').value / card.width;
|
|
card.artY = document.querySelector('#art-y').value / card.height;
|
|
card.artZoom = document.querySelector('#art-zoom').value / 100;
|
|
drawCard();
|
|
}
|
|
function autoFitArt() {
|
|
if (art.width / art.height > scaleWidth(card.artBounds.width) / scaleHeight(card.artBounds.height)) {
|
|
document.querySelector('#art-y').value = Math.round(scaleY(card.artBounds.y) - scaleHeight(card.marginY));
|
|
document.querySelector('#art-zoom').value = (scaleHeight(card.artBounds.height) / art.height * 100).toFixed(1);
|
|
document.querySelector('#art-x').value = Math.round(scaleX(card.artBounds.x) - (document.querySelector('#art-zoom').value / 100 * art.width - scaleWidth(card.artBounds.width)) / 2 - scaleWidth(card.marginX));
|
|
} else {
|
|
document.querySelector('#art-x').value = Math.round(scaleX(card.artBounds.x) - scaleWidth(card.marginX));
|
|
document.querySelector('#art-zoom').value = (scaleWidth(card.artBounds.width) / art.width * 100).toFixed(1);
|
|
document.querySelector('#art-y').value = Math.round(scaleY(card.artBounds.y) - (document.querySelector('#art-zoom').value / 100 * art.height - scaleHeight(card.artBounds.height)) / 2 - scaleHeight(card.marginY));
|
|
}
|
|
artEdited();
|
|
}
|
|
function artFromScryfall(scryfallResponse) {
|
|
scryfallArt = scryfallResponse.data;
|
|
document.querySelector('#art-index').value = 1;
|
|
document.querySelector('#art-index').max = scryfallArt.length;
|
|
changeArtIndex();
|
|
}
|
|
function changeArtIndex() {
|
|
if (scryfallArt[document.querySelector('#art-index').value - 1].image_uris) {
|
|
uploadArt(scryfallArt[document.querySelector('#art-index').value - 1].image_uris.art_crop, "autoFit");
|
|
artistEdited(scryfallArt[document.querySelector('#art-index').value - 1].artist);
|
|
}
|
|
}
|
|
//SET SYMBOL TAB
|
|
function uploadSetSymbol(imageSource, otherParams) {
|
|
setSymbol.src = imageSource;
|
|
if (otherParams && otherParams == 'resetSetSymbol') {
|
|
setSymbol.onload = function() {
|
|
resetSetSymbol();
|
|
setSymbol.onload = setSymbolEdited;
|
|
};
|
|
}
|
|
}
|
|
function setSymbolEdited() {
|
|
card.setSymbolSource = setSymbol.src;
|
|
card.setSymbolX = document.querySelector('#setSymbol-x').value / card.width;
|
|
card.setSymbolY = document.querySelector('#setSymbol-y').value / card.height;
|
|
card.setSymbolZoom = document.querySelector('#setSymbol-zoom').value / 100;
|
|
drawCard();
|
|
}
|
|
function resetSetSymbol() {
|
|
document.querySelector('#setSymbol-x').value = Math.round(scaleX(card.setSymbolBounds.x));
|
|
document.querySelector('#setSymbol-y').value = Math.round(scaleY(card.setSymbolBounds.y));
|
|
var setSymbolZoom;
|
|
if (setSymbol.width / setSymbol.height > scaleWidth(card.setSymbolBounds.width) / scaleHeight(card.setSymbolBounds.height)) {
|
|
setSymbolZoom = (scaleWidth(card.setSymbolBounds.width) / setSymbol.width * 100).toFixed(1);
|
|
} else {
|
|
setSymbolZoom = (scaleHeight(card.setSymbolBounds.height) / setSymbol.height * 100).toFixed(1);
|
|
}
|
|
document.querySelector('#setSymbol-zoom').value = setSymbolZoom;
|
|
if (card.setSymbolBounds.horizontal == 'center') {
|
|
document.querySelector('#setSymbol-x').value = Math.round(scaleX(card.setSymbolBounds.x) - (setSymbol.width * setSymbolZoom / 100) / 2 - scaleWidth(card.marginX));
|
|
} else if (card.setSymbolBounds.horizontal == 'right') {
|
|
document.querySelector('#setSymbol-x').value = Math.round(scaleX(card.setSymbolBounds.x) - (setSymbol.width * setSymbolZoom / 100) - scaleWidth(card.marginX));
|
|
}
|
|
if (card.setSymbolBounds.vertical == 'center') {
|
|
document.querySelector('#setSymbol-y').value = Math.round(scaleY(card.setSymbolBounds.y) - (setSymbol.height * setSymbolZoom / 100) / 2 - scaleHeight(card.marginY));
|
|
} else if (card.setSymbolBounds.vertical == 'bottom') {
|
|
document.querySelector('#setSymbol-y').value = Math.round(scaleY(card.setSymbolBounds.y) - (setSymbol.height * setSymbolZoom / 100) - scaleHeight(card.marginY));
|
|
}
|
|
setSymbolEdited();
|
|
}
|
|
function fetchSetSymbol() {
|
|
var setCode = document.querySelector('#set-symbol-code').value.toLowerCase() || 'cmd';
|
|
var setRarity = document.querySelector('#set-symbol-rarity').value.toLowerCase() || 'c';
|
|
if (setCode == 'cc') {
|
|
uploadSetSymbol('/img/setSymbols/cc-' + setRarity + '.png', 'resetSetSymbol');
|
|
} else {
|
|
imageURL('http://gatherer.wizards.com/Handlers/Image.ashx?type=symbol&set=' + setCode + '&size=large&rarity=' + setRarity, uploadSetSymbol, 'resetSetSymbol');
|
|
}
|
|
}
|
|
//WATERMARK TAB
|
|
function uploadWatermark(imageSource, otherParams) {
|
|
watermark.src = imageSource;
|
|
if (otherParams && otherParams == 'resetWatermark') {
|
|
watermark.onload = function() {
|
|
resetWatermark();
|
|
watermark.onload = watermarkEdited;
|
|
};
|
|
}
|
|
}
|
|
function watermarkEdited() {
|
|
card.watermarkSource = watermark.src;
|
|
card.watermarkX = document.querySelector('#watermark-x').value / card.width;
|
|
card.watermarkY = document.querySelector('#watermark-y').value / card.height;
|
|
card.watermarkZoom = document.querySelector('#watermark-zoom').value / 100;
|
|
card.watermarkLeft = document.querySelector('#watermark-left').value;
|
|
card.watermarkRight = document.querySelector('#watermark-right').value;
|
|
card.watermarkOpacity = document.querySelector('#watermark-opacity').value / 100;
|
|
watermarkContext.globalCompositeOperation = 'source-over';
|
|
watermarkContext.globalAlpha = 1;
|
|
watermarkContext.clearRect(0, 0, watermarkCanvas.width, watermarkCanvas.height);
|
|
if (card.watermarkLeft != 'none' && !card.watermarkSource.includes('/blank.png') && card.watermarkZoom > 0) {
|
|
if (card.watermarkRight != 'none') {
|
|
watermarkContext.drawImage(right, scaleX(0), scaleY(0), scaleWidth(1), scaleHeight(1));
|
|
watermarkContext.globalCompositeOperation = 'source-in';
|
|
if (card.watermarkRight == 'default') {
|
|
watermarkContext.drawImage(watermark, scaleX(card.watermarkX), scaleY(card.watermarkY), watermark.width * card.watermarkZoom, watermark.height * card.watermarkZoom);
|
|
} else {
|
|
watermarkContext.fillStyle = card.watermarkRight;
|
|
watermarkContext.fillRect(0, 0, watermarkCanvas.width, watermarkCanvas.height);
|
|
}
|
|
watermarkContext.globalCompositeOperation = 'destination-over';
|
|
}
|
|
if (card.watermarkLeft == 'default') {
|
|
watermarkContext.drawImage(watermark, scaleX(card.watermarkX), scaleY(card.watermarkY), watermark.width * card.watermarkZoom, watermark.height * card.watermarkZoom);
|
|
} else {
|
|
watermarkContext.fillStyle = card.watermarkLeft;
|
|
watermarkContext.fillRect(0, 0, watermarkCanvas.width, watermarkCanvas.height);
|
|
}
|
|
watermarkContext.globalCompositeOperation = 'destination-in';
|
|
watermarkContext.drawImage(watermark, scaleX(card.watermarkX), scaleY(card.watermarkY), watermark.width * card.watermarkZoom, watermark.height * card.watermarkZoom);
|
|
watermarkContext.globalAlpha = card.watermarkOpacity;
|
|
watermarkContext.fillRect(0, 0, watermarkCanvas.width, watermarkCanvas.height);
|
|
}
|
|
drawCard();
|
|
}
|
|
function resetWatermark() {
|
|
var watermarkZoom;
|
|
if (watermark.width / watermark.height > scaleWidth(card.watermarkBounds.width) / scaleHeight(card.watermarkBounds.height)) {
|
|
watermarkZoom = (scaleWidth(card.watermarkBounds.width) / watermark.width * 100).toFixed(1);
|
|
} else {
|
|
watermarkZoom = (scaleHeight(card.watermarkBounds.height) / watermark.height * 100).toFixed(1);
|
|
}
|
|
document.querySelector('#watermark-zoom').value = watermarkZoom;
|
|
document.querySelector('#watermark-x').value = Math.round(scaleX(card.watermarkBounds.x) - watermark.width * watermarkZoom / 200 - scaleWidth(card.marginX));
|
|
document.querySelector('#watermark-y').value = Math.round(scaleY(card.watermarkBounds.y) - watermark.height * watermarkZoom / 200 - scaleHeight(card.marginY));
|
|
watermarkEdited();
|
|
}
|
|
//svg cropper
|
|
function getSetSymbolWatermark(setCode, targetImage = watermark) {
|
|
xhttp = new XMLHttpRequest();
|
|
xhttp.open('GET', 'https://raw.githubusercontent.com/andrewgioia/keyrune/4073ac89bb943978c29be504275e6f3160a07255/svg/' + setCode + '.svg', true);
|
|
xhttp.overrideMimeType('image/svg+xml');
|
|
xhttp.onload = function(event) {
|
|
if (this.readyState == 4 && this.status == 200) {
|
|
var svg = document.body.appendChild(xhttp.responseXML.documentElement);
|
|
var box = svg.getBBox(svg);
|
|
svg.setAttribute('viewBox', [box.x, box.y, box.width, box.height].join(' '));
|
|
svg.setAttribute('width', box.width);
|
|
svg.setAttribute('height', box.height);
|
|
uploadWatermark('data:image/svg+xml,' + encodeURIComponent(svg.outerHTML), 'resetWatermark');
|
|
svg.remove();
|
|
} else if (this.status == 404) {
|
|
throw new Error('woopsie');
|
|
}
|
|
}
|
|
xhttp.send();
|
|
}
|
|
//Bottom Info Tab
|
|
async function loadBottomInfo(textObjects = []) {
|
|
await bottomInfoContext.clearRect(0, 0, bottomInfoCanvas.width, bottomInfoCanvas.height);
|
|
card.bottomInfo = null;
|
|
card.bottomInfo = textObjects;
|
|
await bottomInfoEdited();
|
|
bottomInfoEdited();
|
|
}
|
|
async function bottomInfoEdited() {
|
|
await bottomInfoContext.clearRect(0, 0, bottomInfoCanvas.width, bottomInfoCanvas.height);
|
|
card.infoNumber = document.querySelector('#info-number').value;
|
|
card.infoRarity = document.querySelector('#info-rarity').value;
|
|
card.infoSet = document.querySelector('#info-set').value;
|
|
card.infoLanguage = document.querySelector('#info-language').value;
|
|
card.infoArtist = document.querySelector('#info-artist').value;
|
|
for (var textObject of Object.entries(card.bottomInfo)) {
|
|
await writeText(textObject[1], bottomInfoContext);
|
|
continue;
|
|
}
|
|
drawCard();
|
|
}
|
|
function artistEdited(value) {
|
|
document.querySelector('#art-artist').value = value;
|
|
document.querySelector('#info-artist').value = value;
|
|
bottomInfoEdited();
|
|
}
|
|
//DRAWING THE CARD (putting it all together)
|
|
function drawCard() {
|
|
cardContext.globalCompositeOperation = 'source-over';
|
|
cardContext.clearRect(0, 0, cardCanvas.width, cardCanvas.height);
|
|
cardContext.drawImage(art, scaleX(card.artX), scaleY(card.artY), art.width * card.artZoom, art.height * card.artZoom);
|
|
cardContext.drawImage(frameCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
|
|
if (card.version.includes('planeswalker') && typeof planeswalkerCanvas !== "undefined") {
|
|
cardContext.drawImage(planeswalkerCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
|
|
}
|
|
cardContext.drawImage(watermarkCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
|
|
if (card.version.includes('saga') && typeof sagaCanvas !== "undefined") {
|
|
cardContext.drawImage(sagaCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
|
|
}
|
|
cardContext.drawImage(textCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
|
|
cardContext.drawImage(setSymbol, scaleX(card.setSymbolX), scaleY(card.setSymbolY), setSymbol.width * card.setSymbolZoom, setSymbol.height * card.setSymbolZoom)
|
|
cardContext.drawImage(bottomInfoCanvas, 0, 0, cardCanvas.width, cardCanvas.height);
|
|
cardContext.globalCompositeOperation = 'destination-out';
|
|
if (card.marginX == 0 && card.marginY == 0) {
|
|
cardContext.drawImage(corner, 0, 0, scaleWidth(59/1500), scaleWidth(59/1500));
|
|
cardContext.rotate(Math.PI / 2);
|
|
cardContext.drawImage(corner, 0, -card.width, scaleWidth(59/1500), scaleWidth(59/1500));
|
|
cardContext.rotate(Math.PI / 2);
|
|
cardContext.drawImage(corner, -card.width, -card.height, scaleWidth(59/1500), scaleWidth(59/1500));
|
|
cardContext.rotate(Math.PI / 2);
|
|
cardContext.drawImage(corner, -card.height, 0, scaleWidth(59/1500), scaleWidth(59/1500));
|
|
cardContext.rotate(Math.PI / 2);
|
|
}
|
|
previewContext.clearRect(0, 0, previewCanvas.width, previewCanvas.height);
|
|
previewContext.drawImage(cardCanvas, 0, 0, previewCanvas.width, previewCanvas.height);
|
|
}
|
|
//DOWNLOADING
|
|
async function downloadCard() {
|
|
if (card.infoArtist.replace(/ /g, '') == '' && !card.artSource.includes('/img/blank.png') && !card.artZoom == 0) {
|
|
notify('You must credit an artist before downloading!');
|
|
} else {
|
|
var download = document.createElement('a');
|
|
var imageName = card.text.title.text;
|
|
if (card.text.nickname) {
|
|
imageName = card.text.nickname.text + ' (' + imageName + ')'
|
|
}
|
|
download.download = imageName + '.png';
|
|
download.href = cardCanvas.toDataURL();
|
|
document.body.appendChild(download);
|
|
await download.click();
|
|
download.remove();
|
|
}
|
|
}
|
|
//IMPORT/SAVE TAB
|
|
function importCard(cardObject) {
|
|
scryfallCard = cardObject.data;
|
|
document.querySelector('#import-index').value = 1;
|
|
document.querySelector('#import-index').max = scryfallCard.length;
|
|
changeCardIndex();
|
|
}
|
|
function changeCardIndex() {
|
|
var cardToImport = scryfallCard[document.querySelector('#import-index').value - 1];
|
|
//text
|
|
if (card.text.title) {card.text.title.text = cardToImport.name || '';}
|
|
if (card.text.nickname) {card.text.nickname.text = cardToImport.flavor_name || '';}
|
|
if (card.text.mana) {card.text.mana.text = cardToImport.mana_cost || '';}
|
|
if (card.text.type) {card.text.type.text = cardToImport.type_line || '';}
|
|
if (card.text.rules) {
|
|
var rulesText = (cardToImport.oracle_text || '').replace('(', '{i}(').replace(')', '){/i}');
|
|
var rulesTextCounter = 1;
|
|
while (rulesText.includes('"')) {
|
|
if (rulesTextCounter % 2) {
|
|
rulesText = rulesText.replace('"', '\u201c');
|
|
} else {
|
|
rulesText = rulesText.replace('"', '\u201d');
|
|
}
|
|
rulesTextCounter ++;
|
|
}
|
|
card.text.rules.text = rulesText;
|
|
if (cardToImport.flavor_text) {
|
|
var flavorText = cardToImport.flavor_text;
|
|
var flavorTextCounter = 1;
|
|
while (flavorText.includes('*') || flavorText.includes('"')) {
|
|
if (flavorTextCounter % 2) {
|
|
flavorText = flavorText.replace('*', '{/i}');
|
|
flavorText = flavorText.replace('"', '\u201c');
|
|
} else {
|
|
flavorText = flavorText.replace('*', '{i}');
|
|
flavorText = flavorText.replace('"', '\u201d');
|
|
}
|
|
flavorTextCounter ++;
|
|
}
|
|
card.text.rules.text += '{flavor}' + flavorText.replace('\n', '{lns}');
|
|
}
|
|
}
|
|
if (card.text.pt) {card.text.pt.text = cardToImport.power + '/' + cardToImport.toughness || '';}
|
|
if (card.text.pt && card.text.pt.text == undefined + '/' + undefined) {card.text.pt.text = '';}
|
|
if (card.version.includes('planeswalker')) {
|
|
card.text.loyalty.text = cardToImport.loyalty || '';
|
|
var planeswalkerAbilities = cardToImport.oracle_text.split('\n');
|
|
while (planeswalkerAbilities.length > 4) {
|
|
var newAbility = planeswalkerAbilities[planeswalkerAbilities.length - 2] + '\n' + planeswalkerAbilities.pop();
|
|
planeswalkerAbilities[planeswalkerAbilities.length - 1] = newAbility;
|
|
}
|
|
for (var i = 0; i < 4; i ++) {
|
|
if (planeswalkerAbilities[i]) {
|
|
var planeswalkerAbility = planeswalkerAbilities[i].replace(': ', 'splitstring').split('splitstring');
|
|
if (!planeswalkerAbility[1]) {
|
|
planeswalkerAbility = ['', '{permashift' + scaleWidth(-0.04) + ',0}' + planeswalkerAbility[0]];
|
|
}
|
|
card.text['ability' + i].text = planeswalkerAbility[1].replace('(', '{i}(').replace(')', '){/i}');
|
|
if (card.version == 'planeswalkerTall') {
|
|
document.querySelector('#planeswalker-height-' + i).value = Math.round(scaleHeight(0.3572) / planeswalkerAbilities.length);
|
|
} else {
|
|
document.querySelector('#planeswalker-height-' + i).value = Math.round(scaleHeight(0.2915) / planeswalkerAbilities.length);
|
|
}
|
|
document.querySelector('#planeswalker-cost-' + i).value = planeswalkerAbility[0].replace('\u2212', '-');
|
|
} else {
|
|
card.text['ability' + i].text = '';
|
|
document.querySelector('#planeswalker-height-' + i).value = 0;
|
|
}
|
|
}
|
|
planeswalkerEdited();
|
|
} else if (card.version.includes('saga')) {
|
|
card.text.ability0.text = cardToImport.oracle_text.replace('(', '{i}(').replace(')', '){/i}') || '';
|
|
}
|
|
document.querySelector('#text-editor').value = card.text[Object.keys(card.text)[selectedTextIndex]].text;
|
|
textEdited();
|
|
//art
|
|
scryfallArt = scryfallCard;
|
|
document.querySelector('#art-name').value = cardToImport.name;
|
|
document.querySelector('#art-index').value = 1;
|
|
document.querySelector('#art-index').max = scryfallArt.length;
|
|
changeArtIndex();
|
|
//set symbol
|
|
document.querySelector('#set-symbol-code').value = cardToImport.set;
|
|
document.querySelector('#set-symbol-rarity').value = cardToImport.rarity.slice(0, 1);
|
|
fetchSetSymbol();
|
|
}
|
|
function loadAvailableCards(cardKeys = JSON.parse(localStorage.getItem('cardKeys'))) {
|
|
if (!cardKeys) {
|
|
cardKeys = [];
|
|
cardKeys.sort();
|
|
localStorage.setItem('cardKeys', JSON.stringify(cardKeys));
|
|
}
|
|
document.querySelector('#load-card-options').innerHTML = '<option selected="selected" disabled>None selected</option>';
|
|
cardKeys.forEach(item => {
|
|
var cardKeyOption = document.createElement('option');
|
|
cardKeyOption.innerHTML = item;
|
|
document.querySelector('#load-card-options').appendChild(cardKeyOption);
|
|
});
|
|
}
|
|
function saveCard(saveFromFile) {
|
|
var cardKeys = JSON.parse(localStorage.getItem('cardKeys')) || [];
|
|
var cardKey, cardToSave;
|
|
if (saveFromFile) {
|
|
cardKey = saveFromFile.key;
|
|
} else {
|
|
cardKey = card.text.title.text || 'unnamed';
|
|
}
|
|
if (!saveFromFile) {
|
|
cardKey = prompt('Enter the name you would like to save your card under:', cardKey);
|
|
if (!cardKey) {return null;}
|
|
}
|
|
if (cardKeys.includes(cardKey)) {
|
|
if (!confirm('Would you like to overwrite your card previously saved as "' + cardKey + '"?\n(Clicking "cancel" will affix a version number)')) {
|
|
var originalCardKey = cardKey;
|
|
var cardKeyNumber = 1;
|
|
while (cardKeys.includes(cardKey)) {
|
|
cardKey = originalCardKey + ' (' + cardKeyNumber + ')';
|
|
cardKeyNumber ++;
|
|
}
|
|
}
|
|
}
|
|
if (saveFromFile) {
|
|
cardToSave = saveFromFile.data;
|
|
} else {
|
|
cardToSave = JSON.parse(JSON.stringify(card));
|
|
cardToSave.frames.forEach(frame => {
|
|
delete frame.image;
|
|
frame.masks.forEach(mask => delete mask.image);
|
|
});
|
|
}
|
|
try {
|
|
localStorage.setItem(cardKey, JSON.stringify(cardToSave));
|
|
if (!cardKeys.includes(cardKey)) {
|
|
cardKeys.push(cardKey);
|
|
cardKeys.sort();
|
|
localStorage.setItem('cardKeys', JSON.stringify(cardKeys));
|
|
loadAvailableCards(cardKeys);
|
|
}
|
|
} catch (error) {
|
|
notify('You have exceeded your 5MB of local storage, and your card has failed to save. If you would like to continue saving cards, please download all saved cards, then delete all saved cards to free up space.<br><br>Local storage is most often exceeded by uploading large images directly from your computer. If possible/convenient, using a URL avoids the need to save these large images.<br><br>Apologies for the inconvenience.');
|
|
}
|
|
}
|
|
async function loadCard(selectedCardKey) {
|
|
document.querySelector('#frame-list').innerHTML = null;
|
|
card = {};
|
|
card = JSON.parse(localStorage.getItem(selectedCardKey));
|
|
if (card) {
|
|
document.querySelector('#info-number').value = card.infoNumber;
|
|
document.querySelector('#info-rarity').value = card.infoRarity;
|
|
document.querySelector('#info-set').value = card.infoSet;
|
|
document.querySelector('#info-language').value = card.infoLanguage;
|
|
artistEdited(card.infoArtist);
|
|
document.querySelector('#text-editor').value = card.text[Object.keys(card.text)[selectedTextIndex]].text;
|
|
loadTextOptions(card.text);
|
|
document.querySelector('#art-x').value = scaleX(card.artX);
|
|
document.querySelector('#art-y').value = scaleY(card.artY);
|
|
document.querySelector('#art-zoom').value = card.artZoom * 100;
|
|
uploadArt(card.artSource);
|
|
document.querySelector('#setSymbol-x').value = scaleX(card.setSymbolX);
|
|
document.querySelector('#setSymbol-y').value = scaleY(card.setSymbolY);
|
|
document.querySelector('#setSymbol-zoom').value = card.setSymbolZoom * 100;
|
|
uploadSetSymbol(card.setSymbolSource);
|
|
document.querySelector('#watermark-x').value = scaleX(card.watermarkX);
|
|
document.querySelector('#watermark-y').value = scaleY(card.watermarkY);
|
|
document.querySelector('#watermark-zoom').value = card.watermarkZoom * 100;
|
|
document.querySelector('#watermark-left').value = card.watermarkLeft;
|
|
document.querySelector('#watermark-right').value = card.watermarkRight;
|
|
document.querySelector('#watermark-opacity').value = card.watermarkOpacity * 100;
|
|
uploadWatermark(card.watermarkSource);
|
|
card.frames.reverse();
|
|
await card.frames.forEach(item => addFrame([], item));
|
|
card.frames.reverse();
|
|
if (card.onload) {
|
|
await loadScript(card.onload);
|
|
if (card.version.includes('planeswalker')) {
|
|
setTimeout(function(){
|
|
fixPlaneswalkerInputs(invertPlaneswalkerColors(true));
|
|
}, 1000);
|
|
}
|
|
}
|
|
card.manaSymbols.forEach(item => loadScript(item));
|
|
//canvases
|
|
var canvasesResized = false;
|
|
canvasList.forEach(name => {
|
|
if (window[name + 'Canvas'].width != card.width * (1 + card.marginX) || window[name + 'Canvas'].height != card.height * (1 + card.marginY)) {
|
|
sizeCanvas(name);
|
|
canvasesResized = true;
|
|
}
|
|
});
|
|
if (canvasesResized) {
|
|
drawTextBuffer();
|
|
drawFrames();
|
|
bottomInfoEdited();
|
|
watermarkEdited();
|
|
}
|
|
} else {
|
|
notify(selectedCardKey + ' failed to load.')
|
|
}
|
|
}
|
|
function deleteCard() {
|
|
var keyToDelete = document.querySelector('#load-card-options').value;
|
|
if (keyToDelete) {
|
|
var cardKeys = JSON.parse(localStorage.getItem('cardKeys'));
|
|
cardKeys.splice(cardKeys.indexOf(keyToDelete), 1);
|
|
cardKeys.sort();
|
|
localStorage.setItem('cardKeys', JSON.stringify(cardKeys));
|
|
localStorage.removeItem(keyToDelete);
|
|
loadAvailableCards(cardKeys);
|
|
}
|
|
}
|
|
function deleteSavedCards() {
|
|
if (confirm('WARNING:\n\nALL of your saved cards will be deleted! If you would like to save these cards, please make sure you have downloaded them first. There is no way to undo this.\n\n(Press "OK" to delete your cards)')) {
|
|
var cardKeys = JSON.parse(localStorage.getItem('cardKeys'));
|
|
cardKeys.forEach(key => localStorage.removeItem(key));
|
|
localStorage.setItem('cardKeys', JSON.stringify([]));
|
|
loadAvailableCards([]);
|
|
}
|
|
}
|
|
async function downloadSavedCards() {
|
|
var cardKeys = JSON.parse(localStorage.getItem('cardKeys'));
|
|
if (cardKeys) {
|
|
var allSavedCards = [];
|
|
cardKeys.forEach(item => {
|
|
allSavedCards.push({key:item, data:JSON.parse(localStorage.getItem(item))});
|
|
});
|
|
var download = document.createElement('a');
|
|
download.href = URL.createObjectURL(new Blob([JSON.stringify(allSavedCards)], {type:'text'}));
|
|
download.download = 'saved-cards.cardconjurer';
|
|
document.body.appendChild(download);
|
|
await download.click();
|
|
download.remove();
|
|
}
|
|
}
|
|
function uploadSavedCards(event) {
|
|
var reader = new FileReader();
|
|
reader.onload = function () {
|
|
JSON.parse(reader.result).forEach(item => saveCard(item));
|
|
}
|
|
reader.readAsText(event.target.files[0]);
|
|
}
|
|
//TUTORIAL TAB
|
|
function loadTutorialVideo() {
|
|
var video = document.querySelector('.video > iframe');
|
|
if (video.src == '') {
|
|
video.src = 'https://www.youtube-nocookie.com/embed/UrNk6I55S0Q?rel=0';
|
|
}
|
|
}
|
|
//Various loaders
|
|
function imageURL(url, destination, otherParams) {
|
|
var imageurl = url;
|
|
if (params.get('noproxy') != '') {
|
|
imageurl = 'https://cors-anywhere.herokuapp.com/' + url;
|
|
}
|
|
destination(imageurl, otherParams);
|
|
}
|
|
async function imageLocal(event, destination, otherParams) {
|
|
var reader = new FileReader();
|
|
reader.onload = function () {
|
|
destination(reader.result, otherParams);
|
|
}
|
|
reader.onerror = function () {
|
|
destination('/img/blank.png', otherParams);
|
|
}
|
|
await reader.readAsDataURL(event.target.files[0]);
|
|
}
|
|
function loadScript(scriptPath) {
|
|
var script = document.createElement('script');
|
|
script.setAttribute('type', 'text/javascript');
|
|
script.setAttribute('src', scriptPath);
|
|
if (typeof script != 'undefined') {
|
|
document.querySelectorAll('head')[0].appendChild(script);
|
|
}
|
|
}
|
|
//SCRYFALL STUFF MAY BE CHANGED IN THE FUTURE
|
|
function fetchScryfallData(cardName, callback = console.log) {
|
|
var xhttp = new XMLHttpRequest();
|
|
xhttp.onreadystatechange = function() {
|
|
if (this.readyState == 4 && this.status == 200) {
|
|
callback(JSON.parse(this.responseText));
|
|
// JSON.parse(this.responseText);
|
|
} else if (this.readyState == 4 && this.status == 404) {
|
|
notify('No cards found for "' + cardName + '"');
|
|
}
|
|
}
|
|
xhttp.open('GET', 'https://api.scryfall.com/cards/search?order=released&unique=art&q=name%3D' + cardName.replace(/ /g, '_'), true);
|
|
xhttp.send();
|
|
}
|
|
//Initialization
|
|
document.querySelector('#info-number').value = date.getFullYear();
|
|
loadScript('/js/frames/groupStandard-2.js');
|
|
loadAvailableCards();
|