2020-06-20 00:31:36 +03:00
|
|
|
let firstPixel = true;
|
|
|
|
|
2020-12-31 15:05:51 +03:00
|
|
|
/** Creates a new, empty file
|
|
|
|
*
|
|
|
|
* @param {*} width Start width of the canvas
|
|
|
|
* @param {*} height Start height of the canvas
|
|
|
|
* @param {*} editorMode The editor mode chosen by the user (advanced or basic)
|
|
|
|
* @param {*} fileContent If fileContent != null, then the newPixel is being called from the open menu
|
|
|
|
*/
|
2020-07-21 00:33:17 +03:00
|
|
|
function newPixel (width, height, editorMode, fileContent = null) {
|
2020-12-31 15:05:51 +03:00
|
|
|
// Saving the editor mode
|
2020-07-21 00:33:17 +03:00
|
|
|
pixelEditorMode = editorMode;
|
|
|
|
|
2020-12-31 15:05:51 +03:00
|
|
|
// The palette is empty, at the beginning
|
2020-06-27 14:29:28 +03:00
|
|
|
currentPalette = [];
|
2020-12-31 15:05:51 +03:00
|
|
|
|
|
|
|
// If this is the first pixel I'm creating since the app has started
|
2020-06-20 00:31:36 +03:00
|
|
|
if (firstPixel) {
|
2020-12-31 15:05:51 +03:00
|
|
|
// I configure the layers elements
|
2020-06-20 00:31:36 +03:00
|
|
|
layerListEntry = layerList.firstElementChild;
|
|
|
|
|
2020-12-31 15:05:51 +03:00
|
|
|
// Creating the first layer
|
2020-06-20 23:49:02 +03:00
|
|
|
currentLayer = new Layer(width, height, canvas, layerListEntry);
|
2020-07-21 17:01:00 +03:00
|
|
|
currentLayer.canvas.style.zIndex = 2;
|
2020-06-20 00:31:36 +03:00
|
|
|
}
|
|
|
|
else {
|
2020-12-31 15:05:51 +03:00
|
|
|
// If it's not the first Pixel, I have to reset the app
|
|
|
|
|
|
|
|
// Deleting all the extra layers and canvases, leaving only one
|
2020-06-20 23:49:02 +03:00
|
|
|
let nLayers = layers.length;
|
2020-09-26 12:51:18 +03:00
|
|
|
for (let i=2; i < layers.length - nAppLayers; i++) {
|
2020-06-20 23:49:02 +03:00
|
|
|
let currentEntry = layers[i].menuEntry;
|
|
|
|
let associatedLayer;
|
|
|
|
|
|
|
|
if (currentEntry != null) {
|
|
|
|
// Getting the associated layer
|
|
|
|
associatedLayer = getLayerByID(currentEntry.id);
|
|
|
|
|
|
|
|
// Deleting its canvas
|
|
|
|
associatedLayer.canvas.remove();
|
|
|
|
|
|
|
|
// Adding the id to the unused ones
|
|
|
|
unusedIDs.push(currentEntry.id);
|
|
|
|
// Removing the entry from the menu
|
|
|
|
currentEntry.remove();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Removing the old layers from the list
|
2020-09-26 12:51:18 +03:00
|
|
|
for (let i=2; i<nLayers - nAppLayers; i++) {
|
2020-06-20 23:49:02 +03:00
|
|
|
layers.splice(2, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setting up the current layer
|
|
|
|
layers[1] = new Layer(width, height, layers[1].canvas, layers[1].menuEntry);
|
|
|
|
currentLayer = layers[1];
|
2020-09-22 12:34:36 +03:00
|
|
|
currentLayer.canvas.style.zIndex = 2;
|
|
|
|
|
2020-12-31 15:05:51 +03:00
|
|
|
// Updating canvas size to the new size
|
2020-09-22 12:34:36 +03:00
|
|
|
for (let i=0; i<nLayers; i++) {
|
|
|
|
layers[i].canvasSize = [width, height];
|
|
|
|
}
|
2020-06-20 00:31:36 +03:00
|
|
|
}
|
2020-06-19 00:24:37 +03:00
|
|
|
|
2020-03-04 16:36:40 +03:00
|
|
|
// Adding the checkerboard behind it
|
2020-03-04 17:46:25 +03:00
|
|
|
checkerBoard = new Layer(width, height, checkerBoardCanvas);
|
2019-03-31 17:32:49 +03:00
|
|
|
|
2020-03-04 16:36:40 +03:00
|
|
|
// Creating the vfx layer on top of everything
|
2020-03-04 17:46:25 +03:00
|
|
|
VFXLayer = new Layer(width, height, VFXCanvas);
|
2020-03-04 16:36:40 +03:00
|
|
|
|
2020-06-19 00:24:37 +03:00
|
|
|
// Tmp layer to draw previews on
|
2020-09-25 10:25:27 +03:00
|
|
|
TMPLayer = new Layer(width, height, TMPCanvas);
|
|
|
|
|
|
|
|
// Pixel grid
|
|
|
|
pixelGrid = new Layer(width, height, pixelGridCanvas);
|
2020-12-31 15:05:51 +03:00
|
|
|
// Setting the general canvasSize
|
2019-03-31 17:32:49 +03:00
|
|
|
canvasSize = currentLayer.canvasSize;
|
2019-03-31 18:15:03 +03:00
|
|
|
|
2020-06-20 23:49:02 +03:00
|
|
|
if (firstPixel) {
|
2020-09-09 07:15:22 +03:00
|
|
|
// Cloning the entry so that when I change something on the first layer, those changes aren't
|
2020-06-20 23:49:02 +03:00
|
|
|
// propagated to the other ones
|
|
|
|
layerListEntry = layerListEntry.cloneNode(true);
|
|
|
|
// Adding the first layer and the checkerboard to the list of layers
|
|
|
|
layers.push(checkerBoard);
|
|
|
|
layers.push(currentLayer);
|
|
|
|
layers.push(VFXLayer);
|
|
|
|
layers.push(TMPLayer);
|
2020-09-26 12:51:18 +03:00
|
|
|
layers.push(pixelGrid);
|
2020-06-20 23:49:02 +03:00
|
|
|
}
|
2020-04-15 03:01:31 +03:00
|
|
|
|
2019-03-27 02:20:54 +03:00
|
|
|
//remove current palette
|
|
|
|
colors = document.getElementsByClassName('color-button');
|
|
|
|
while (colors.length > 0) {
|
|
|
|
colors[0].parentElement.remove();
|
|
|
|
}
|
2020-04-15 03:01:31 +03:00
|
|
|
|
2019-03-27 02:20:54 +03:00
|
|
|
//add colors from selected palette
|
2021-02-19 00:28:52 +03:00
|
|
|
var selectedPalette;
|
|
|
|
if (!firstPixel)
|
|
|
|
var selectedPalette = getText('palette-button');
|
|
|
|
else
|
|
|
|
var selectedPalette = getText('palette-button-splash');
|
2020-12-31 15:05:51 +03:00
|
|
|
|
|
|
|
// If the user selected a palette and isn't opening a file, I load the selected palette
|
2020-06-28 17:57:19 +03:00
|
|
|
if (selectedPalette != 'Choose a palette...' && fileContent == null) {
|
2020-04-15 03:01:31 +03:00
|
|
|
|
2019-03-27 02:20:54 +03:00
|
|
|
//if this palette isnt the one specified in the url, then reset the url
|
|
|
|
if (!palettes[selectedPalette].specified)
|
|
|
|
history.pushState(null, null, '/pixel-editor/app');
|
2021-02-19 00:28:52 +03:00
|
|
|
|
2020-12-31 15:05:51 +03:00
|
|
|
//fill the palette with specified colours
|
2019-03-27 02:20:54 +03:00
|
|
|
createColorPalette(palettes[selectedPalette].colors,true);
|
|
|
|
}
|
2020-12-31 15:05:51 +03:00
|
|
|
// Otherwise, I just generate 2 semirandom colours
|
2020-06-28 17:57:19 +03:00
|
|
|
else if (fileContent == null) {
|
|
|
|
//this wasn't a specified palette, so reset the url
|
|
|
|
history.pushState(null, null, '/pixel-editor/app');
|
2020-04-15 03:01:31 +03:00
|
|
|
|
2020-06-28 17:57:19 +03:00
|
|
|
//generate default colors
|
|
|
|
var fg = hslToRgb(Math.floor(Math.random()*255), 230,70);
|
|
|
|
var bg = hslToRgb(Math.floor(Math.random()*255), 230,170);
|
2020-04-15 03:01:31 +03:00
|
|
|
|
2020-06-28 17:57:19 +03:00
|
|
|
//convert colors to hex
|
|
|
|
var defaultForegroundColor = rgbToHex(fg.r,fg.g,fg.b);
|
|
|
|
var defaultBackgroundColor = rgbToHex(bg.r,bg.g,bg.b);
|
2020-04-15 03:01:31 +03:00
|
|
|
|
2020-06-28 17:57:19 +03:00
|
|
|
//add colors to palette
|
|
|
|
addColor(defaultForegroundColor).classList.add('selected');
|
|
|
|
addColor(defaultBackgroundColor);
|
2020-04-15 03:01:31 +03:00
|
|
|
|
2019-03-27 02:20:54 +03:00
|
|
|
//set current drawing color as foreground color
|
2019-03-31 17:32:49 +03:00
|
|
|
currentLayer.context.fillStyle = '#'+defaultForegroundColor;
|
2020-03-07 01:21:42 +03:00
|
|
|
currentGlobalColor = '#' + defaultForegroundColor;
|
2019-03-27 02:20:54 +03:00
|
|
|
selectedPalette = 'none';
|
|
|
|
}
|
2020-04-15 03:01:31 +03:00
|
|
|
|
2020-06-28 17:57:19 +03:00
|
|
|
//fill background of canvas with bg color
|
|
|
|
fillCheckerboard();
|
2020-09-26 12:51:18 +03:00
|
|
|
fillPixelGrid();
|
2020-06-28 17:57:19 +03:00
|
|
|
|
2019-03-27 02:20:54 +03:00
|
|
|
//reset undo and redo states
|
|
|
|
undoStates = [];
|
|
|
|
redoStates = [];
|
2020-04-15 03:01:31 +03:00
|
|
|
|
2020-12-31 15:05:51 +03:00
|
|
|
// Closing the "New Pixel dialogue"
|
2019-03-27 02:20:54 +03:00
|
|
|
closeDialogue();
|
2020-12-31 15:05:51 +03:00
|
|
|
// Updating the cursor of the current tool
|
2020-04-15 03:01:31 +03:00
|
|
|
currentTool.updateCursor();
|
|
|
|
|
2020-12-31 15:05:51 +03:00
|
|
|
// The user is now able to export the Pixel
|
2020-06-27 14:29:28 +03:00
|
|
|
document.getElementById('export-button').classList.remove('disabled');
|
2019-03-27 02:20:54 +03:00
|
|
|
documentCreated = true;
|
2020-04-15 03:01:31 +03:00
|
|
|
|
2020-12-31 15:05:51 +03:00
|
|
|
// This is not the first Pixel anymore
|
2020-06-20 23:49:02 +03:00
|
|
|
firstPixel = false;
|
2020-06-28 17:57:19 +03:00
|
|
|
|
2021-04-25 13:57:28 +03:00
|
|
|
// Now, if I opened an LPE file
|
2020-06-28 17:57:19 +03:00
|
|
|
if (fileContent != null) {
|
2020-12-31 15:05:51 +03:00
|
|
|
// I add every layer the file had in it
|
2020-06-28 17:57:19 +03:00
|
|
|
for (let i=0; i<fileContent['nLayers']; i++) {
|
|
|
|
let layerData = fileContent['layer' + i];
|
|
|
|
let layerImage = fileContent['layer' + i + 'ImageData'];
|
|
|
|
|
|
|
|
if (layerData != null) {
|
|
|
|
// Setting id
|
|
|
|
let createdLayer = addLayer(layerData.id, false);
|
|
|
|
// Setting name
|
|
|
|
createdLayer.menuEntry.getElementsByTagName("p")[0].innerHTML = layerData.name;
|
|
|
|
|
|
|
|
// Adding the image (I can do that because they're sorted by increasing z-index)
|
|
|
|
let img = new Image();
|
|
|
|
img.onload = function() {
|
|
|
|
createdLayer.context.drawImage(img, 0, 0);
|
|
|
|
createdLayer.updateLayerPreview();
|
|
|
|
|
|
|
|
if (i == (fileContent['nLayers'] - 1)) {
|
|
|
|
createPaletteFromLayers();
|
|
|
|
}
|
2020-09-09 07:15:22 +03:00
|
|
|
};
|
2020-06-28 17:57:19 +03:00
|
|
|
|
|
|
|
img.src = layerImage;
|
|
|
|
|
|
|
|
// Setting visibility and lock options
|
|
|
|
if (!layerData.isVisible) {
|
|
|
|
createdLayer.hide();
|
|
|
|
}
|
|
|
|
if (layerData.isLocked) {
|
|
|
|
createdLayer.lock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Deleting the default layer
|
|
|
|
deleteLayer(false);
|
|
|
|
}
|
2020-07-21 00:33:17 +03:00
|
|
|
|
2020-12-31 15:05:51 +03:00
|
|
|
// Applying the correct editor mode
|
2020-07-21 00:33:17 +03:00
|
|
|
if (pixelEditorMode == 'Basic') {
|
2021-04-25 13:41:36 +03:00
|
|
|
switchMode(false);
|
2020-07-21 00:33:17 +03:00
|
|
|
}
|
|
|
|
else {
|
2021-04-25 13:41:36 +03:00
|
|
|
switchMode(false);
|
2020-07-21 00:33:17 +03:00
|
|
|
}
|
2021-04-25 13:41:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function newFromTemplate(preset, x, y) {
|
|
|
|
if (preset != '') {
|
|
|
|
setText('palette-button-splash', presets[preset].palette);
|
|
|
|
setText('palette-button', presets[preset].palette);
|
2021-04-25 13:57:28 +03:00
|
|
|
|
2021-04-25 13:41:36 +03:00
|
|
|
x = presets[preset].width;
|
|
|
|
y = presets[preset].height;
|
|
|
|
}
|
|
|
|
|
|
|
|
newPixel(x, y, pixelEditorMode == 'Advanced' ? 'Basic' : 'Advanced');
|
2020-06-20 23:49:02 +03:00
|
|
|
}
|