const LayerList = (() => { let layerList = document.getElementById("layers-menu"); let layerListEntry = layerList.firstElementChild; let renamingLayer = false; let dragStartLayer; // Binding the right click menu Events.on("mousedown", layerList, openOptionsMenu); // Binding the add layer button to the right function Events.on('click',"add-layer-button", addLayer, false); // Listening to the switch mode event so I can change the layout Events.onCustom("switchedToAdvanced", showMenu); Events.onCustom("switchedToBasic", hideMenu); // Making the layers list sortable new Sortable(layerList, { animation: 100, filter: ".layer-button", draggable: ".layers-menu-entry", onStart: layerDragStart, onEnd: layerDragDrop }); function showMenu() { layerList.style.display = "inline-block"; document.getElementById('layer-button').style.display = 'inline-block'; } function hideMenu() { if (EditorState.documentCreated()) { // Selecting the current layer currFile.currentLayer.selectLayer(); // Flatten the layers flatten(true); } layerList.style.display = "none"; document.getElementById('layer-button').style.display = 'none'; } function addLayer(id, saveHistory = true) { // layers.length - 3 let index = currFile.layers.length - 3; // Creating a new canvas let newCanvas = document.createElement("canvas"); // Setting up the new canvas currFile.canvasView.append(newCanvas); Layer.maxZIndex+=2; newCanvas.style.zIndex = Layer.maxZIndex; newCanvas.classList.add("drawingCanvas"); if (!layerListEntry) return console.warn('skipping adding layer because no document'); // Clone the default layer let toAppend = layerListEntry.cloneNode(true); // Setting the default name for the layer toAppend.getElementsByTagName('p')[0].innerHTML = "Layer " + Layer.layerCount; // Removing the selected class toAppend.classList.remove("selected-layer"); // Adding the layer to the list Layer.layerCount++; // Creating a layer object let newLayer = new Layer(currFile.canvasSize[0], currFile.canvasSize[1], newCanvas, toAppend); newLayer.context.fillStyle = currFile.currentLayer.context.fillStyle; newLayer.copyData(currFile.currentLayer); currFile.layers.splice(index, 0, newLayer); // Insert it before the Add layer button layerList.insertBefore(toAppend, layerList.childNodes[0]); if (id != null && typeof(id) == "string") { newLayer.setID(id); } // Basically "if I'm not adding a layer because redo() is telling meto do so", then I can save the history if (saveHistory) { new HistoryState().AddLayer(newLayer, index); } return newLayer; } /** Merges topLayer onto belowLayer * * @param {*} belowLayer The layer on the bottom of the layer stack * @param {*} topLayer The layer on the top of the layer stack */ function mergeLayers(belowLayer, topLayer) { // Copying the above content on the layerBelow let belowImageData = belowLayer.getImageData(0, 0, belowLayer.canvas.width, belowLayer.canvas.height); let toMergeImageData = topLayer.getImageData(0, 0, topLayer.canvas.width, topLayer.canvas.height); for (let i=0; i newIndex) { for (let i=newIndex; ioldIndex; i--) { getLayerByID(layerList.children[i].id).canvas.style.zIndex = getLayerByID(layerList.children[i - 1].id).canvas.style.zIndex; } } getLayerByID(layerList.children[oldIndex].id).canvas.style.zIndex = movedZIndex; Events.simulateMouseEvent(window, "mouseup"); } /** Saves the layer that is being moved when the dragging starts * * @param {*} event */ function layerDragStart(event) { dragStartLayer = getLayerByID(layerList.children[event.oldIndex].id); } // Finds a layer given its id function getLayerByID(id) { for (let i=0; i=0; i--) { LayerList.getLayerByID(menuEntries[i].id).canvas.style.zIndex++; } Layer.maxZIndex+=2; // Creating a new canvas let newCanvas = document.createElement("canvas"); // Setting up the new canvas currFile.canvasView.append(newCanvas); newCanvas.style.zIndex = parseInt(currFile.currentLayer.canvas.style.zIndex) + 2; newCanvas.classList.add("drawingCanvas"); if (!layerListEntry) return console.warn('skipping adding layer because no document'); // Clone the default layer let toAppend = currFile.currentLayer.menuEntry.cloneNode(true); // Setting the default name for the layer toAppend.getElementsByTagName('p')[0].innerHTML += " copy"; // Removing the selected class toAppend.classList.remove("selected-layer"); // Adding the layer to the list Layer.layerCount++; // Creating a layer object let newLayer = new Layer(currFile.canvasSize[0], currFile.canvasSize[1], newCanvas, toAppend); newLayer.context.fillStyle = currFile.currentLayer.context.fillStyle; newLayer.copyData(currFile.currentLayer); currFile.layers.splice(layerIndex, 0, newLayer); // Insert it before the Add layer button layerList.insertBefore(toAppend, currFile.currentLayer.menuEntry); // Copy the layer content newLayer.context.putImageData(currFile.currentLayer.context.getImageData( 0, 0, currFile.canvasSize[0], currFile.canvasSize[1]), 0, 0); newLayer.updateLayerPreview(); // Basically "if I'm not adding a layer because redo() is telling meto do so", then I can save the history if (saveHistory) { new HistoryState().DuplicateLayer(newLayer, currFile.currentLayer); } } function deleteLayer(saveHistory = true) { // Cannot delete all the layers if (currFile.layers.length != 4) { let layerIndex = currFile.layers.indexOf(currFile.currentLayer); let toDelete = currFile.layers[layerIndex]; let previousSibling = toDelete.menuEntry.previousElementSibling; // Adding the ids to the unused ones Layer.unusedIDs.push(toDelete.id); // Selecting the next layer if (layerIndex != (currFile.layers.length - 4)) { currFile.layers[layerIndex + 1].selectLayer(); } // or the previous one if the next one doesn't exist else { currFile.layers[layerIndex - 1].selectLayer(); } // Deleting canvas and entry toDelete.canvas.remove(); toDelete.menuEntry.remove(); // Removing the layer from the list currFile.layers.splice(layerIndex, 1); if (saveHistory) { new HistoryState().DeleteLayer(toDelete, previousSibling, layerIndex); } } // Closing the menu closeOptionsMenu(); } function merge(saveHistory = true) { // Saving the layer that should be merged let toMerge = currFile.currentLayer; let toMergeIndex = currFile.layers.indexOf(toMerge); // Getting layer below let layerBelow = LayerList.getLayerByID(currFile.currentLayer.menuEntry.nextElementSibling.id); // If I have something to merge with if (layerBelow != null) { // Selecting that layer layerBelow.selectLayer(); if (saveHistory) { new HistoryState().MergeLayer(toMergeIndex, toMerge, layerBelow.context.getImageData(0, 0, currFile.canvasSize[0], currFile.canvasSize[1]), layerBelow); } LayerList.mergeLayers(currFile.currentLayer.context, toMerge.context); // Deleting the above layer toMerge.canvas.remove(); toMerge.menuEntry.remove(); currFile.layers.splice(toMergeIndex, 1); // Updating the layer preview currFile.currentLayer.updateLayerPreview(); } } function flatten(onlyVisible) { if (!onlyVisible) { // Selecting the first layer let firstLayer = layerList.firstElementChild; let nToFlatten = layerList.childElementCount - 1; LayerList.getLayerByID(firstLayer.id).selectLayer(); for (let i = 0; i < nToFlatten; i++) { merge(); } new HistoryState().FlattenAll(nToFlatten); } else { // Getting all the visible layers let visibleLayers = []; let nToFlatten = 0; for (let i=0; i (a.canvas.style.zIndex > b.canvas.style.zIndex) ? -1 : 1); // Selecting the last visible layer (the only one that won't get deleted) visibleLayers[visibleLayers.length - 1].selectLayer(); // Merging all the layer but the last one for (let i=0; i