asciibird/src/ascii.js

826 lines
25 KiB
JavaScript
Raw Normal View History

2021-08-04 03:21:06 +00:00
import LZString from 'lz-string';
import store from './store';
// 0 => 'white',
// 1 => 'black',
// 2 => 'navy',
// 3 => 'green',
// 4 => 'red',
// 5 => 'brown',
// 6 => 'purple',
// 7 => 'olive',
// 8 => 'yellow', # dark yellow
// 9 => 'lime', # ltgreen
// 10 => 'teal',
// 11 => 'cyan',
// 12 => 'blue', # ltblue,
// 13 => 'fuchsia', # pink
// 14 => 'grey',
// 15 => 'lightgrey',
export const mircColours99 = [
'rgb(255,255,255)',
'rgb(0,0,0)',
'rgb(0,0,127)',
'rgb(0,147,0)',
'rgb(255,0,0)',
'rgb(127,0,0)',
'rgb(156,0,156)',
'rgb(252,127,0)',
'rgb(255,255,0)',
'rgb(0,252,0)',
'rgb(0,147,147)',
'rgb(0,255,255)',
'rgb(0,0,252)',
'rgb(255,0,255)',
'rgb(127,127,127)',
'rgb(210,210,210)',
"#470000",
"#472100",
"#474700",
"#324700",
"#004700",
"#00472c",
"#004747",
"#002747",
"#000047",
"#2e0047",
"#470047",
"#47002a",
"#740000",
"#743a00",
"#747400",
"#517400",
"#007400",
"#007449",
"#007474",
"#004074",
"#000074",
"#4b0074",
"#740074",
"#740045",
"#b50000",
"#b56300",
"#b5b500",
"#7db500",
"#00b500",
"#00b571",
"#00b5b5",
"#0063b5",
"#0000b5",
"#7500b5",
"#b500b5",
"#b5006b",
"#ff0000",
"#ff8c00",
"#ffff00",
"#b2ff00",
"#00ff00",
"#00ffa0",
"#00ffff",
"#008cff",
"#0000ff",
"#a500ff",
"#ff00ff",
"#ff0098",
"#ff5959",
"#ffb459",
"#ffff71",
"#cfff60",
"#6fff6f",
"#65ffc9",
"#6dffff",
"#59b4ff",
"#5959ff",
"#c459ff",
"#ff66ff",
"#ff59bc",
"#ff9c9c",
"#ffd39c",
"#ffff9c",
"#e2ff9c",
"#9cff9c",
"#9cffdb",
"#9cffff",
"#9cd3ff",
"#9c9cff",
"#dc9cff",
"#ff9cff",
"#ff94d3",
"#000000",
"#131313",
"#282828",
"#363636",
"#4d4d4d",
"#656565",
"#818181",
"#9f9f9f",
"#bcbcbc",
"#e2e2e2",
"#ffffff",
2021-08-04 03:21:06 +00:00
];
2021-08-12 01:52:40 +00:00
// How big the brush size can get
export const maxBrushSize = 15;
// Chars that end up in the toolbar
export const charCodes = [' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-',
'.', '/',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A',
'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e',
'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '{', '|', '}', '~', 'Ç', 'ü', 'é', 'â', 'ä', 'à', 'å', 'ç', 'ê', 'ë', 'è',
'ï', 'î', 'ì', 'Ä', 'Å', 'É', 'æ', 'Æ', 'ô', 'ö', 'ò', 'û', 'ù', 'ÿ', 'Ö', 'Ü', 'ø', '£',
'Ø', '×', 'ƒ', 'á', 'í', 'ó', 'ú', 'ñ', 'Ñ', 'ª', 'º', '¿', '®', '¬', '½', '¼', '¡', '«',
'»', 'Á', 'Â', 'À', '©', '¢', '¥', 'ã', 'Ã', '¤', 'ð', 'Ð', 'Ê', 'Ë', 'È', 'ı', 'Í', 'Î',
'Ï', '¦', 'Ì', 'Ó', 'ß', 'Ô', 'Ò', 'õ', 'Õ', 'µ', 'þ', 'Þ', 'Ú', 'Û', 'Ù', 'ý', 'Ý', '¸',
'°', '¨', '·', '¯', '´', '≡', '±', '‗', '¶', '§', '÷',
'⁰', '¹', '³', '²', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹', '⁺', '⁻', '⁼', '⁽', '⁾',
'₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉', '₊', '₋', '₌', '₍', '₎',
2021-12-04 03:47:31 +00:00
'¼', '½', '¾', '⅓', '⅔', '⅕', '⅖', '⅗', '⅘', '⅙', '⅚', '⅛', '⅜', '⅝', '⅞', '⅟', '⅒', '⅑', '',
'└', '┐', '┘', '┌', '│', '┤', '├', '┴', '┬', '─', '┼',
'╚', '╗', '╝', '╔', '║', '╣', '╠', '╩', '╦', '═', '╬',
'╰', '╮', '╯', '╭', '', '╲', '',
'▘', '▖', '▝', '▗', '▚',
'▏', '▎', '▍', '▌', '▋', '▊', '▉',
'▁', '▂', '▃', '▄', '▅', '▆', '▇', '▀', '▔', '░', '▒', '▓', '█',
];
// Toolbar icons
export const toolbarIcons = [{
name: 'default',
icon: 'mouse-pointer',
fa: 'fas',
},
{
name: 'select',
icon: 'square',
fa: 'far',
},
{
name: 'text',
icon: 'font',
fa: 'fas',
},
{
name: 'fill',
icon: 'fill-drip',
fa: 'fas',
},
{
name: 'brush',
icon: 'paint-brush',
fa: 'fas',
},
{
name: 'dropper',
icon: 'eye-dropper',
fa: 'fas',
},
{
name: 'eraser',
icon: 'eraser',
fa: 'fas',
},
{
name: 'fill-eraser',
icon: 'fill',
fa: 'fas',
},
];
2021-08-04 03:21:06 +00:00
export const emptyBlock = {
bg: null,
fg: null,
char: null,
};
export const create2DArray = (rows) => {
const arr = [];
for (let i = 0; i < rows; i++) {
arr[i] = [];
}
return arr;
};
// Width and height of the ASCII blocks
// they seem to be 8x15 in asciiblaster
export const blockWidth = 8;
export const blockHeight = 15;
// Limits for undo and brush histories
2021-11-06 00:59:17 +00:00
export const maxBrushHistory = 200;
export const maxUndoHistory = 200;
export const tabLimit = 20;
export const parseMircAscii = async (content, title) => {
2021-08-04 02:47:17 +00:00
const MIRC_MAX_COLOURS = mircColours99.length;
// The current state of the Colours
let curBlock = {
2021-08-04 03:21:06 +00:00
...emptyBlock,
2021-08-04 02:47:17 +00:00
};
2021-08-04 03:21:06 +00:00
const contents = content;
const filename = title;
2021-08-04 02:47:17 +00:00
// set asciiImport as the entire file contents as a string
const asciiImport = contents
2021-08-04 03:21:06 +00:00
.split('\u0003\u0003')
.join('\u0003')
.split('\u000F').join('')
.split('\u0003\n')
.join('\n')
.split('\u0002\u0003')
.join('\u0003');
2021-08-04 02:47:17 +00:00
// This will end up in the asciibirdMeta
const finalAscii = {
title: filename,
// key: store.getters.nextTabValue,
// blockWidth: blockWidth * store.getters.blockSizeMultiplier,
// blockHeight: blockHeight * store.getters.blockSizeMultiplier,
2021-08-14 06:41:42 +00:00
blocks: [{
label: filename,
visible: true,
data: create2DArray(asciiImport.split('\n').length),
width: false, // defined in: switch (curChar) case "\n":
height: asciiImport.split('\n').length,
2021-08-14 06:41:42 +00:00
}],
2021-08-04 02:47:17 +00:00
history: [],
redo: [],
2021-10-16 05:16:21 +00:00
imageOverlay: {
url: null,
opacity: 95,
position: 'centered',
size: 100,
repeatx: true,
repeaty: true,
visible: false,
2021-10-23 00:23:02 +00:00
stretched: false,
2021-10-16 05:16:21 +00:00
},
x: blockWidth * 35, // the dragable ascii canvas x
y: blockHeight * 2, // the dragable ascii canvas y
2021-08-14 06:41:42 +00:00
selectedLayer: 0,
2021-08-04 02:47:17 +00:00
};
// Turn the entire ascii string into an array
2021-08-04 03:21:06 +00:00
let asciiStringArray = asciiImport.split('');
const linesArray = asciiImport.split('\n');
2021-08-04 02:47:17 +00:00
// The proper X and Y value of the block inside the ASCII
let asciiX = 0;
let asciiY = 0;
// used to determine colours
let colourChar1 = null;
let colourChar2 = null;
let parsedColour = null;
// This variable just counts the amount of colour and char codes to minus
// to get the real width
let widthOfColCodes = 0;
// Better for colourful asciis
let maxWidthLoop = 0;
// Used before the loop, better for plain text
let maxWidthFound = 0;
for (let i = 0; i < linesArray.length; i++) {
if (linesArray[i].length > maxWidthFound) {
maxWidthFound = linesArray[i].length;
}
2021-08-04 02:47:17 +00:00
}
while (asciiStringArray.length) {
const curChar = asciiStringArray[0];
// Defining a small finite state machine
// to detect the colour code
switch (curChar) {
2021-08-04 03:21:06 +00:00
case '\n':
2021-08-04 02:47:17 +00:00
// Reset the colours here on a new line
2021-08-04 03:21:06 +00:00
curBlock = {
...emptyBlock,
};
2021-08-04 02:47:17 +00:00
if (linesArray[asciiY] && linesArray[asciiY].length > maxWidthLoop) {
maxWidthLoop = linesArray[asciiY].length;
}
2021-08-04 02:47:17 +00:00
// the Y value of the ascii
asciiY++;
2021-08-04 02:47:17 +00:00
// Calculate widths mirc asciis vs plain text
if (!finalAscii.blocks[0].width && widthOfColCodes > 0) {
finalAscii.blocks[0].width = maxWidthLoop - widthOfColCodes;
2021-08-04 02:47:17 +00:00
}
if (!finalAscii.blocks[0].width && widthOfColCodes === 0) {
2021-08-04 02:47:17 +00:00
// Plain text
finalAscii.blocks[0].width = maxWidthFound;
2021-08-04 02:47:17 +00:00
}
2021-08-04 02:47:17 +00:00
// Resets the X value
asciiX = 0;
2021-08-04 02:47:17 +00:00
asciiStringArray.shift();
widthOfColCodes = 0;
break;
2021-08-04 03:21:06 +00:00
case '\u0003':
2021-08-04 02:47:17 +00:00
// Remove the colour char
asciiStringArray.shift();
widthOfColCodes++;
2021-08-04 02:47:17 +00:00
// Attempt to work out bg
colourChar1 = `${asciiStringArray[0]}`;
colourChar2 = `${asciiStringArray[1]}`;
parsedColour = parseInt(`${colourChar1}${colourChar2}`);
// Work out the 01, 02 double digit codes
if (parseInt(colourChar1) === 0 && parseInt(colourChar2) >= 0) {
asciiStringArray.shift();
}
2021-08-04 03:21:06 +00:00
if (Number.isNaN(parsedColour)) {
2021-08-04 02:47:17 +00:00
curBlock.bg = parseInt(colourChar1);
widthOfColCodes += 1;
asciiStringArray.shift();
2021-08-04 02:47:17 +00:00
} else if (parsedColour <= MIRC_MAX_COLOURS && parsedColour >= 0) {
curBlock.fg = parseInt(parsedColour);
widthOfColCodes += parsedColour.toString().length;
asciiStringArray = asciiStringArray.slice(
parsedColour.toString().length,
2021-08-04 03:21:06 +00:00
asciiStringArray.length,
2021-08-04 02:47:17 +00:00
);
}
// No background colour
2021-08-04 03:21:06 +00:00
if (asciiStringArray[0] !== ',') {
break;
2021-08-04 02:47:17 +00:00
} else {
// Remove , from array
widthOfColCodes += 1;
asciiStringArray.shift();
}
2021-08-04 02:47:17 +00:00
// Attempt to work out bg
colourChar1 = `${asciiStringArray[0]}`;
colourChar2 = `${asciiStringArray[1]}`;
parsedColour = parseInt(`${colourChar1}${colourChar2}`);
if (
!Number.isNaN(colourChar1) &&
!Number.isNaN(colourChar2) &&
parseInt(colourChar2) > parseInt(colourChar1) &&
!Number.isNaN(parsedColour) &&
parseInt(parsedColour) < 10
2021-08-04 02:47:17 +00:00
) {
parsedColour = parseInt(colourChar2);
widthOfColCodes += 1;
asciiStringArray.shift();
2021-08-04 02:47:17 +00:00
}
if (
parseInt(colourChar2) === parseInt(colourChar1) &&
parseInt(parsedColour) < 10
2021-08-04 02:47:17 +00:00
) {
parsedColour = parseInt(colourChar1);
asciiStringArray.shift();
asciiStringArray.shift();
widthOfColCodes += 2;
curBlock.bg = parseInt(colourChar1);
break;
2021-08-04 02:47:17 +00:00
}
2021-08-04 03:21:06 +00:00
if (Number.isNaN(parsedColour)) {
2021-08-04 02:47:17 +00:00
curBlock.bg = parseInt(colourChar1);
widthOfColCodes += 1;
asciiStringArray.shift();
2021-08-04 02:47:17 +00:00
} else if (parsedColour <= MIRC_MAX_COLOURS && parsedColour >= 0) {
curBlock.bg = parseInt(parsedColour);
widthOfColCodes += parsedColour.toString().length;
asciiStringArray = asciiStringArray.slice(
parsedColour.toString().length,
2021-08-04 03:21:06 +00:00
asciiStringArray.length,
2021-08-04 02:47:17 +00:00
);
break;
2021-08-04 02:47:17 +00:00
}
2021-08-04 02:47:17 +00:00
break;
2021-08-04 02:47:17 +00:00
default:
curBlock.char = curChar;
asciiStringArray.shift();
asciiX++;
2021-08-03 04:59:12 +00:00
2021-08-14 06:41:42 +00:00
finalAscii.blocks[0].data[asciiY][asciiX - 1] = {
2021-08-04 03:21:06 +00:00
...curBlock,
2021-08-04 02:47:17 +00:00
};
break;
} // End Switch
} // End loop charPos
finalAscii.blocks = [...fillNullBlocks(finalAscii.blocks[0].height, finalAscii.blocks[0]
.width, finalAscii.blocks)];
2021-08-15 00:15:36 +00:00
// Store the ASCII and ensure we have no null blocks
2021-08-04 02:47:17 +00:00
finalAscii.blocks = LZString.compressToUTF16(
2021-08-04 03:21:06 +00:00
JSON.stringify(finalAscii.blocks),
2021-08-04 02:47:17 +00:00
);
2021-08-04 02:47:17 +00:00
// We need to also store in the first undo history the original state
finalAscii.history.push(finalAscii.blocks);
2021-08-07 06:10:52 +00:00
// Save ASCII to storage
2021-08-04 03:21:06 +00:00
store.commit('newAsciibirdMeta', finalAscii);
2021-08-04 02:47:17 +00:00
return true;
};
// Creates new blank ASCII
2021-08-04 02:47:17 +00:00
export const createNewAscii = (forms) => {
2021-08-04 03:21:06 +00:00
const newAscii = {
2021-08-04 02:47:17 +00:00
title: forms.createAscii.title,
history: [],
redo: [],
x: 247, // the dragable ascii canvas x
y: 24, // the dragable ascii canvas y
2021-08-14 06:41:42 +00:00
blocks: [{
label: forms.createAscii.title,
visible: true,
data: create2DArray(forms.createAscii.height),
width: forms.createAscii.width,
height: forms.createAscii.height,
2021-08-14 06:41:42 +00:00
}],
2021-10-16 05:16:21 +00:00
imageOverlay: {
url: null,
opacity: 95,
position: 'centered',
size: 100,
repeatx: true,
repeaty: true,
visible: false,
2021-10-23 00:23:02 +00:00
stretched: false,
2021-10-16 05:16:21 +00:00
},
2021-08-14 06:41:42 +00:00
selectedLayer: 0,
2021-08-04 02:47:17 +00:00
};
// Push all the default ASCII blocks
for (let x = 0; x < newAscii.blocks[0].width; x++) {
for (let y = 0; y < newAscii.blocks[0].height; y++) {
2021-08-14 06:41:42 +00:00
newAscii.blocks[0].data[y].push({
2021-08-04 03:21:06 +00:00
...emptyBlock,
});
2021-08-04 02:47:17 +00:00
}
}
2021-08-04 03:21:06 +00:00
newAscii.blocks = LZString.compressToUTF16(JSON.stringify(newAscii.blocks));
newAscii.history.push(newAscii.blocks);
store.commit('newAsciibirdMeta', newAscii);
2021-08-06 01:51:58 +00:00
store.commit('closeModal', 'new-ascii');
2021-08-04 02:47:17 +00:00
return true;
2021-08-04 03:21:06 +00:00
};
// Converts ASCIIBIRD blocks to mIRC colours
export const exportMirc = () => {
const {
currentAscii
} = store.getters;
2021-08-28 03:20:59 +00:00
const {
currentAsciiLayersWidthHeight
} = store.getters;
const blocks = mergeLayers();
const output = [];
2021-08-14 06:41:42 +00:00
let curBlock = false;
2021-09-04 00:21:53 +00:00
let pushString = '';
2021-08-28 03:20:59 +00:00
let prevBlock = {
bg: -1,
fg: -1
};
2021-09-04 05:16:27 +00:00
for (let y = 0; y <= currentAsciiLayersWidthHeight.height - 1; y++) {
2021-08-14 22:51:45 +00:00
2021-09-04 05:16:27 +00:00
for (let x = 0; x <= currentAsciiLayersWidthHeight.width - 1; x++) {
2021-08-28 03:20:59 +00:00
curBlock = {
...blocks[y][x]
};
2021-08-14 22:51:45 +00:00
// If we have a difference between our previous block
// we'll put a colour codes and continue as normal
if (curBlock.bg !== prevBlock.bg || curBlock.fg !== prevBlock.fg) {
2021-08-14 22:51:45 +00:00
curBlock = {
2021-08-28 03:20:59 +00:00
...blocks[y][x]
2021-08-14 22:51:45 +00:00
};
const zeroPad = (num, places) => String(num).padStart(places, '0');
2021-08-28 03:20:59 +00:00
if (curBlock.fg === null && curBlock.bg === null) {
2021-09-04 00:21:53 +00:00
output.push('\u0003');
2021-08-28 03:20:59 +00:00
} else {
2021-09-04 00:21:53 +00:00
if (curBlock.bg === null && curBlock.fg !== null) {
2021-10-09 00:47:16 +00:00
pushString = `\u0003\u0003${zeroPad(curBlock.fg, 2)}`;
2021-09-04 00:21:53 +00:00
}
if (curBlock.bg !== null && curBlock.fg !== null) {
2021-10-09 00:47:16 +00:00
pushString = `\u0003${zeroPad(curBlock.fg, 2)},${zeroPad(curBlock.bg, 2)}`;
2021-09-04 00:21:53 +00:00
}
2021-10-23 00:37:25 +00:00
if (curBlock.bg !== null && curBlock.fg === null) {
pushString = `\u000300,${zeroPad(curBlock.bg, 2)}`;
}
2021-09-04 00:21:53 +00:00
output.push(pushString);
2021-08-28 03:20:59 +00:00
}
2021-09-04 00:21:53 +00:00
}
// null .chars will end up as space
output.push(curBlock.char ?? ' ');
2021-09-04 00:21:53 +00:00
prevBlock = {
...blocks[y][x]
};
}
// We can never have a -1 colour code so we'll always
// write one at the start of each line
prevBlock = {
bg: -1,
fg: -1
};
// New line except for the very last line
2021-08-28 03:20:59 +00:00
if (blocks[y] && y < blocks[y].length - 1) {
output.push('\n');
}
}
// Download to a txt file
// Check if txt already exists and append it
const filename = currentAscii.title.slice(currentAscii.title.length - 3) === 'txt' ?
currentAscii.title :
`${currentAscii.title}.txt`;
return {
filename,
output
}
}
// Download a string to a file with a filename
export const downloadFile = (content, filename, contentType) => {
const a = document.createElement('a');
const file = new Blob([content], {
type: contentType
});
a.href = URL.createObjectURL(file);
a.download = filename;
a.click();
URL.revokeObjectURL(a.href);
};
export const checkForGetRequest = async () => {
const asciiUrlCdn = new URL(location.href).searchParams.get('ascii');
if (asciiUrlCdn) {
const res = await fetch(`https://ascii.jewbird.live/${asciiUrlCdn}`, {
method: 'GET',
headers: {
Accept: 'text/plain',
},
});
const asciiData = await res.text();
parseMircAscii(asciiData, asciiUrlCdn);
return;
}
const asciiUrl = new URL(location.href).searchParams.get('ircwatch');
if (asciiUrl) {
const res = await fetch(`https://irc.watch/ascii/txt/${asciiUrl}`, {
method: 'GET',
headers: {
Accept: 'text/plain',
},
});
const asciiData = await res.text();
parseMircAscii(asciiData, asciiUrl);
return;
}
const haxAscii = new URL(location.href).searchParams.get('haxAscii');
if (haxAscii) {
const res = await fetch(`https://art.h4x.life/${haxAscii}`, {
method: 'GET',
headers: {
Accept: 'text/plain',
},
});
// Considers paths
const asciiName = haxAscii.split('/').pop();
const asciiData = await res.text();
parseMircAscii(asciiData, asciiName);
}
}
2021-08-04 02:47:17 +00:00
// Hashing algo to detect duplicate brushes
2021-08-06 11:00:35 +00:00
// from https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript
export const cyrb53 = function (str, seed = 1337) {
let h1 = 0xdeadbeef ^ seed,
h2 = 0x41c6ce57 ^ seed;
for (let i = 0, ch; i < str.length; i++) {
ch = str.charCodeAt(i);
h1 = Math.imul(h1 ^ ch, 2654435761);
h2 = Math.imul(h2 ^ ch, 1597334677);
}
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
};
2021-08-07 06:10:52 +00:00
// Mostly plain text asciis wont have all their blocks
// so this will fix that
export const fillNullBlocks = function (height, width, layerData = null) {
2021-08-12 01:52:40 +00:00
// Probably used on irc import to make the blocks proper,
// especially with plain text ascii
2021-08-15 00:15:36 +00:00
if (layerData === null) {
var layers = [...store.getters.currentAsciiLayers]
} else {
var layers = [...layerData]
2021-08-12 01:52:40 +00:00
}
2021-08-15 00:15:36 +00:00
for (let i = 0; i <= layers.length - 1; i++) {
let blocks = layers[i].data;
for (let y = 0; y < height; y++) {
// New row
if (!blocks[y]) {
blocks[y] = [];
for (let x = 0; x < width; x++) {
2021-08-12 01:52:40 +00:00
blocks[y][x] = {
...emptyBlock
};
2021-08-07 02:41:47 +00:00
}
2021-08-15 00:15:36 +00:00
} else {
// no new rows but new cols
for (let x = 0; x < width; x++) {
if (blocks[y] && !blocks[y][x]) {
blocks[y][x] = {
...emptyBlock
};
}
}
2021-08-07 02:41:47 +00:00
}
}
2021-08-15 00:15:36 +00:00
// Update layer with new blocks
layers[i].data = [...blocks]
layers[i].width = width
layers[i].height = height
2021-08-07 02:41:47 +00:00
}
2021-08-15 00:15:36 +00:00
return layers
2021-08-07 02:41:47 +00:00
}
2021-08-07 06:10:52 +00:00
// Sometimes if we copy blocks the initial Y values will be null
// and cause an error when trying to calculate width
2021-08-12 01:52:40 +00:00
// So we get the longest x length
2021-08-07 02:41:47 +00:00
export const getBlocksWidth = function (blocks) {
2021-08-12 01:52:40 +00:00
let maxWidth = 0;
2021-08-07 02:41:47 +00:00
2021-08-12 01:52:40 +00:00
for (let y = 0; y < blocks.length; y++) {
2021-08-07 02:41:47 +00:00
if (!blocks[y]) {
continue
}
2021-08-12 01:52:40 +00:00
if (blocks[y] && blocks[y].length > maxWidth) {
maxWidth = blocks[y].length
2021-08-07 02:41:47 +00:00
}
}
2021-08-12 01:52:40 +00:00
return maxWidth
2021-08-07 02:41:47 +00:00
}
2021-08-07 06:10:52 +00:00
// This removes the null blocks from our copy and paste
// to make sure it's centered better
2021-08-07 02:41:47 +00:00
export const filterNullBlocks = function (blocks) {
let newBlocks = [];
let y;
blocks = blocks.filter(function (item) {
return item !== null
});
for (y = 0; y < blocks.length; y++) {
newBlocks[y] = (blocks[y].filter(function (item) {
return item !== null
}))
}
return newBlocks
}
2021-08-14 06:41:42 +00:00
// Function to check if the left and top values are visible on the screen
export const checkVisible = function (bottom, top) {
var viewHeight = Math.max(
document.documentElement.clientHeight,
window.innerHeight
);
return !(bottom < 0 || top - viewHeight >= 0);
}
export const mergeLayers = function (blocks = null) {
let mergedLayers = [];
// Position of the meta array
let x = 0;
let y = 0;
let z = 0;
// Draws the actual rectangle
let canvasX = 0;
let canvasY = 0;
let curBlock = null;
for (y = 0; y < store.getters.currentAsciiLayers[0].height + 1; y++) {
canvasY = blockHeight * y;
if (!mergedLayers[y]) {
mergedLayers[y] = [];
}
for (x = 0; x < store.getters.currentAsciiLayers[0].width + 1; x++) {
canvasX = blockWidth * x;
curBlock = {
...emptyBlock
};
// Loop layers
for (z = store.getters.currentAsciiLayers.length - 1; z >= 0; z--) {
if (store.getters.currentAsciiLayers[z].visible === false) {
continue;
}
if (
store.getters.currentAsciiLayers[z] &&
store.getters.currentAsciiLayers[z].data &&
store.getters.currentAsciiLayers[z].data[y] &&
store.getters.currentAsciiLayers[z].data[y][x]
) {
2021-08-28 02:41:31 +00:00
if (curBlock.char === null) {
curBlock.char = store.getters.currentAsciiLayers[z].data[y][x].char;
}
2021-08-28 02:41:31 +00:00
if (curBlock.fg === null) {
curBlock.fg = store.getters.currentAsciiLayers[z].data[y][x].fg;
}
2021-08-28 02:41:31 +00:00
if (curBlock.bg === null) {
curBlock.bg = store.getters.currentAsciiLayers[z].data[y][x].bg;
}
2021-08-28 02:41:31 +00:00
continue;
}
break;
}
2021-08-28 02:41:31 +00:00
mergedLayers[y][x] = {
...curBlock
}
}
}
2021-10-09 00:47:16 +00:00
return mergedLayers;
}
// Splash screen ascii encoded
export const splashAscii = JSON.parse(LZString.decompressFromEncodedURIComponent(
2021-11-27 00:57:36 +00:00
"NrDeCICMHNwLgIwBpwDNZwAwoMYAsBDAJ3nAAJwBfJCGeZNDbcfY0i62jB9eZ1knHJUaUbil5ZchQcM5j6EptLZCOouoiV8Vs9V0WMdLGexEGtRqSdVyN4q-1NrzCy5Ke39bnspt7XTV9jATN5IO1rUJdwhw9dMPtDeP9Ei2Co5zt0yM8A2OS-aOyfXISYpPcirO8Ix3KSupTi2rjqr0C2kJrOwu6Ogqr+-MqMvLTS+tSKnKmW3qHMgdGy6caupZHZ5p7BsYbWvs2JpvatyZ3l7bOTjfGZi5uH0+Hbo-v194OF-bXDxY+-1+8z2qxBKzmuwhl3OL2Ozzu31BkKuj1eCK+fx+YKh13RnwBSOhTwJwNxaPhpJxqLhgOxKNhiKxyJhb0JzOJ+KB1MZmPBeMp3IZbLJNKZ-IpdJZJKFrIx7IltKJAqlnMF9LlcgAukgwJLlfqOSqDUqjYbFeLyaaLXyrZaxbaHQq7Y7ec6naK3Z6RTyfcL5d6A76g-6qaHZTKNZHpVyo7GY+qE6rjWbrS73V7g2HNRH42rk+b04Hs9H8yb7Znw3HE2XUxW-TnqwW0x6s7maynigBhJsNADyvbWADlB8UAOKjrIAJUntgAgrPZAAVRekADKq5Dmo3SYaABlN+AAJKHgCyh4Aoof2x8AGKHge7tYzp82jOkBevrI72vdw8nr9bAA38iyzR8QNse9AMrTUV2g0gAAlL2vTcADsAFcABtMMoHU9RbQQMOw+C4CInCIJg0tO1AqsSJLPNqNbWiKIbKjCyYxs6JvctXVYhj2Mo-iCL4jsBJE5t6y3NjhKkoTJPo0SZIUiTeNkxT5O4utVOUnj3zUlS9J0rTDM0t9i1MmjOJY-TdPMlCuPs6yjLMttHMYwT1O0iyOOkjS3LEmzjLshyQqc7zZAAdWQuirzogBpfylPC8TbNc0L3LCPCMsClzmOy5zLN8rzEr89KAoKny5OKsqkpK6qwrqkzGuChqatK1qOvy5KcsKqqmra+quuatLOvK7qKo8gyWqGgb+tG2rZumsbhry5bFpGmb5vazadrWrbBr23aFv2uaju2w6LuOs6Dquy7zoWrK7pu+6Xuet7Tqej7bu+16vt+pafvegH-o2z7gaB0HAb+iHVqh8HoYR+GkchkHYdRqzrsRlGYYxsHsaxtGcaKgncbh-HkcJkniYp0n0ep8mGcpmn6aZxnaaJvrmc5tmWfZqnudZ2jHrJwW+a5zz+Yl8Wpp5gWxdlqWFZl0XedVuW1cVlX1e1zX5cpgAWSIAFZUq13WNeVvWrYt03rZ1y2baCpXbcd3K7fN+2Xc9p2zYd723dd3qPeDv2Q69sOffd0Po-DmPI8DyqI4D-2g7j5Ok92YW6ZTxO09T2OC-jnPJsL9O89z0v86LjOK+r8uS7ryva7Lpu3UNqwTcbruW+7que-7vvB+boeG4H4fx9HkeUt7ifp7HyfZ56xeJrnqel4XjfV+X8ad5WqPW63zf18Pk-j7Plfz939ahd1THpYPy+94To+L9fq+TvvmeX-fu-na-0+35P2LgA-4AB2Y2D9AHX33v-R+0Dn4gKATXb+SD66IPgcAuBH8-7z3Qdg32kCf54wIbAqB+CYG4Kwb-EhlCyHUIoWvbUt9iEMO3qgwh7DSFEJFqwlBGDkF4PoQgqhLDhF0M+uAjuulJGSE7rQ7h2cBEiKhu3WRHD+FoOUYozR4ieFiIURzJRujtHqPIfozh8iLGMIMZLHRNjP6WI0aYoRmCmH4RMVwqxbCnGeJ8Y4sxrj7E4OsY1VRGA5HphkeE5xojAleLdAADggb4gJRigk0PTGE+AETvGpLsfEwRsSJZZLgDktuyT-EuLSQUrRhj8l+JCQ03JVT6l5JiXouJTS+FtJSS0pEWc6ntI8ZUoprS+nVzKWyEpkz5RROyUMwZvTRkLLgHM0pKyHGNJ6W+JJUjjK7LUUsjp1TZprJmcYxZIzjljIkRUzJdynTTI2cE5pyyjnDK2eMq5HzXnXOeRk35PzulfM+W875lzGkDNsf83hhS-nvIhYC96ZzpEPOBWC0F8LwVwAOdE-ZaK4VArZLi+Z+K9k7IJbU6FCKcWUoJCS9ZNLNlIoRgy85-w2W6U5Uyl56KsWYqJVS5lfLBUXOpdi4VhLEUiulVK8VArZVCt5egqFkqlUAplfKllaqxU6rAXSjlBqFjcopeShVWrNUmvTFap0NrNVIwyOyn4jrbIup5Rq4lRrBh2s9Wa7VyqqU+vlEG3VAbQ0evVbCyN5iulyr1TU8NUbE0xu2ea+Nsbo2dNTf6m+7jFXJqzSCnNSb0kloTTYkNhq-WJK9ZUSt5bGr1r2G6syLaixto9B2r0XaRQ9szVLPtpJB1AmHQ22aTa621osBOot9qw2lpTbOuN86x3ZrnRGgtJy13Lo3QuwtGLi2LoPeuziqqV0Zs3TclRU7j07rLRevdEsZ1uGfZoV93BR0PudTeoIn7Rh-vSABnwQHf0-o-WB+gIHwPVt7RBxAUGgYIfg3BhASHUMofPdu-tV7RWPpw-mvDKzmB82I8TUj+7+WHoo7h1dS7sMwqPZRk90Yz27to7e+jNKUXGW42+XjkS4P8ao1uujuq0PiZQ2hzDonCPuvvR-CTMGAyKcOa2jDbGv2aaw5ehj1GCPsc0ORiWRmDImd0mZuTjGaNaZkwZ6z2nZMSuk2tVj8nbM2Y4zpyzenWVwfffAfzyGlNDsk+psWKm8VOY3QAF0PHgQ8ABTOz70LNvlS+mdLTpMtumy2yXL8p8teai25zzNjCv-HKwsSrgxqsOeSwjWrFhGtuGa4Z-GrW-Akfa91ymHXjBdY03VjzTG71Wf05p1zY2LWjZ8+mob833MLbBhF0languObTc5kbBWesDb22R3bB3euHb6n16w+3Ztbc60di7xmTt3eO4927+GGv3dM298zH3jJnZ+19tLf2MsA+Ey9ubi2welbHZNy7g3wfbaK5tymgWkd+ZR+t79aPm2hYx0tuHZWgc5au+NnH9nMa-ae1N+GZPnufZhxDmr+O8sM6pVTm7rPocldx-Vlnp2mfw+B7pkTdPifjahWRSIYuaVPOMlLvjgm5fY4sEJt0Su2Qq+Daj1T1qNeRa1wrl92vVvtqx5rztYWKeE-O2zh71PvOC858N363Prfm-Jzz13zv2dTad+92nUNvc045yToXsPHe84qxb0Hweo-2+F9NuBUOJYS8D0TkPKfo9B5j6nxGK3GXFZdzb-77ufcF8B0XgPVvi8V-L27kv-Pvth6qw3h3afM-p-61X+vZfO+14J13wvPfGd99LwPzjefPfj7txnqfIvmGaCTxgCXY-J8t+n3HvnzGfPI712+43OvTfb+gyb7tZuJ+V5rx3-vF-h9X6y03yo-vbcvYf5f8-p+Bcg4j5-oft-v+95HwSZ-a-V-D3EAj-X3VfSPVvKAiAr-e9BPMA5PNfDbOvbFNXAkNA-VA-d6QLSAw-PfY-LAoLI-WDQg9DUg2A-PSgt-R-d-Wgmg+gpfBAqg5fJA+rXAlfDg1g5vLg2PdgngrPPgwQigzpUXLCTCcXMQ3SefeARfBHRAoQg2ODGXATQgjAhYNQ7ghQvmLfYg9XUgqTJmHPJ1THfQ3fQ3ffXQkLUw6wywkdMw3PI3Gw-Akg2w9HVwzQ4QlgrQ5gpg6gxgug-whguQnwgI4IvwsIrwzw3wyI3NTGaQmI+QqI0IlAiI6IgyHQ5wvQ9w3g8mIwjZPIoKAw8Lew4w-9E-AdEo11A3Bw21cotI5IjfBIkIoIlI1oxo+olo9ohombJo8ItonojowIoYzOWfBfSQqwWQ-o0fVI7o6YqYsVDQyoRYzGHApImlDI8wmtcgxHao0o6dXYlZDYmorY7IgQi3QLZYtwS4zQa4mA8Azg7wvorozogY2Y9fV4l4uY544Y+Y5A74mY5keAt4v4j4n4-4p0W4+ASE1ZOo4Etg-GaE6Ex4p9A4slU4-XbYxAo4vYtvfg3E6E5Qx5WEz494r40EgEsE8k34+E+4vE6Ah4tYyksk5k0kqBIEkkkElkzksVQk8pVQ4kpk1kmxREgUik81aEi40U6k05JQqU8E+Uqkvk9
2021-08-14 06:41:42 +00:00
));
2021-08-04 03:21:06 +00:00
export default createNewAscii;