Implemented visibility option

Fixed all the bugs in the add layer feature, now it's also possible to toggle the visibility of a layer. Next step: locking layers.
This commit is contained in:
unsettledgames
2020-06-18 23:24:37 +02:00
parent 6cf6f86a91
commit 750414d63a
2 changed files with 87 additions and 42 deletions

View File

@@ -1,6 +1,7 @@
/** TODO LIST FOR LAYERS /** TODO LIST FOR LAYERS
GENERAL REQUIREMENTS: GENERAL REQUIREMENTS:
- The user shouldn't be able to draw on a hidden or locked layer
- Must delete the selected layer when right clicking on a layer and selecting that option - Must delete the selected layer when right clicking on a layer and selecting that option
* We should think about selecting more than one layer at once. * We should think about selecting more than one layer at once.
* Rename layer * Rename layer
@@ -8,7 +9,7 @@
* Flatten visible option * Flatten visible option
* Flatten everything option * Flatten everything option
- Must move a layer when dragging it in the layer list (https://codepen.io/retrofuturistic/pen/tlbHE) - Must move a layer when dragging it in the layer list (https://codepen.io/retrofuturistic/pen/tlbHE)
- When the user clicks on the eye icon, the layer becomes transparent - When the user clicks on the eye icon, the icon must be changed and always be shown
- When the user clicks on the lock icon, the layer is locked - When the user clicks on the lock icon, the layer is locked
- When a layer is locked or not visible, the corresponding icons are always shown - When a layer is locked or not visible, the corresponding icons are always shown
- When saving an artwork, the layers must be flattened to a temporary layer, which is then exported and deleted - When saving an artwork, the layers must be flattened to a temporary layer, which is then exported and deleted
@@ -33,6 +34,12 @@
2 - Add a Replace feature so that people can replace a colour without editing the one in the palette 2 - Add a Replace feature so that people can replace a colour without editing the one in the palette
(right click->replace colour in layers? in that case we'd have to implement multiple layers selection) (right click->replace colour in layers? in that case we'd have to implement multiple layers selection)
THINGS TO TEST:
1 - Undo / redo
2 - Copy / cut / paste selection
3 - Colour picking from underlying layer
4 - File export
*/ */
/* /*
@@ -44,8 +51,8 @@
// Will probably need a class to handle all the html stuff // Will probably need a class to handle all the html stuff
let layerList = document.getElementById("layers-menu"); let layerList;
let layerListEntry = layerList.firstElementChild; let layerListEntry;
let layerCount = 1; let layerCount = 1;
let maxZIndex = 3; let maxZIndex = 3;
@@ -71,18 +78,12 @@ on('click',"add-layer-button", function(){
// Creating a layer object // Creating a layer object
let newLayer = new Layer(currentLayer.canvasSize[0], currentLayer.canvasSize[1], newCanvas, toAppend); let newLayer = new Layer(currentLayer.canvasSize[0], currentLayer.canvasSize[1], newCanvas, toAppend);
newLayer.initialize(); newLayer.context.fillStyle = currentLayer.context.fillStyle;
newLayer.copyData(currentLayer); newLayer.copyData(currentLayer);
layers.push(newLayer); layers.splice(layers.length - 3, 0, newLayer);
console.log("Vera tela: " + currentLayer.canvas);
console.log("Tela: " + newLayer.canvas);
// Binding functions
toAppend.onclick = newLayer.select;
// Insert it before the Add layer button // Insert it before the Add layer button
layerList.insertBefore(toAppend, layerList.childNodes[layerList.childElementCount - 1]); layerList.insertBefore(toAppend, layerList.childNodes[0]);
}, false); }, false);
/** Handler class for a single canvas (a single layer) /** Handler class for a single canvas (a single layer)
@@ -91,7 +92,8 @@ on('click',"add-layer-button", function(){
* @param height Canvas height * @param height Canvas height
* @param canvas HTML canvas element * @param canvas HTML canvas element
*/ */
function Layer(width, height, canvas, menuEntry) { class Layer {
constructor(width, height, canvas, menuEntry) {
this.canvasSize = [width, height]; this.canvasSize = [width, height];
this.canvas = canvas; this.canvas = canvas;
this.context = this.canvas.getContext('2d'); this.context = this.canvas.getContext('2d');
@@ -99,8 +101,18 @@ function Layer(width, height, canvas, menuEntry) {
this.isVisible = true; this.isVisible = true;
this.isLocked = false; this.isLocked = false;
this.menuEntry = menuEntry; this.menuEntry = menuEntry;
if (menuEntry != null) {
menuEntry.onclick = () => this.select();
menuEntry.getElementsByTagName("button")[0].onclick = () => this.toggleLock();
menuEntry.getElementsByTagName("button")[1].onclick = () => this.toggleVisibility();
}
this.initialize();
}
// Initializes the canvas // Initializes the canvas
this.initialize = function() { initialize() {
var maxHorizontalZoom = Math.floor(window.innerWidth/this.canvasSize[0]*0.75); var maxHorizontalZoom = Math.floor(window.innerWidth/this.canvasSize[0]*0.75);
var maxVerticalZoom = Math.floor(window.innerHeight/this.canvasSize[1]*0.75); var maxVerticalZoom = Math.floor(window.innerHeight/this.canvasSize[1]*0.75);
@@ -122,63 +134,95 @@ function Layer(width, height, canvas, menuEntry) {
this.context.imageSmoothingEnabled = false; this.context.imageSmoothingEnabled = false;
this.context.mozImageSmoothingEnabled = false; this.context.mozImageSmoothingEnabled = false;
}; }
// Resizes canvas // Resizes canvas
this.resize = function() { resize() {
let newWidth = (this.canvas.width * zoom) + 'px'; let newWidth = (this.canvas.width * zoom) + 'px';
let newHeight = (this.canvas.height *zoom)+ 'px'; let newHeight = (this.canvas.height *zoom)+ 'px';
this.canvas.style.width = newWidth; this.canvas.style.width = newWidth;
this.canvas.style.height = newHeight; this.canvas.style.height = newHeight;
}; }
// Copies the otherCanvas' position and size // Copies the otherCanvas' position and size
this.copyData = function(otherCanvas) { copyData(otherCanvas) {
this.canvas.style.width = otherCanvas.canvas.style.width; this.canvas.style.width = otherCanvas.canvas.style.width;
this.canvas.style.height = otherCanvas.canvas.style.height; this.canvas.style.height = otherCanvas.canvas.style.height;
this.canvas.style.left = otherCanvas.canvas.style.left; this.canvas.style.left = otherCanvas.canvas.style.left;
this.canvas.style.top = otherCanvas.canvas.style.top; this.canvas.style.top = otherCanvas.canvas.style.top;
}; }
this.select = function() { select() {
// Deselecting the old layer // Deselecting the old layer
currentLayer.deselect(); currentLayer.deselect();
// Selecting the current layer // Selecting the current layer
this.isSelected = true; this.isSelected = true;
menuEntry.classList.add("selected-layer"); this.menuEntry.classList.add("selected-layer");
currentLayer = getLayerByName(menuEntry.getElementsByTagName("p")[0].innerHTML); currentLayer = getLayerByName(this.menuEntry.getElementsByTagName("p")[0].innerHTML);
} }
this.deselect = function() { toggleLock() {
if (this.isLocked) {
this.unlock();
}
else {
this.lock();
}
}
toggleVisibility() {
console.log(this);
if (this.isVisible) {
this.hide();
}
else {
this.show();
}
}
deselect() {
this.isSelected = false; this.isSelected = false;
menuEntry.classList.remove("selected-layer"); this.menuEntry.classList.remove("selected-layer");
} }
this.lock = function() { lock() {
this.isLocked = true; this.isLocked = true;
} }
this.unlock = function() { unlock() {
this.isLocked = false; this.isLocked = false;
} }
this.show = function() { show() {
this.isVisible = true; this.isVisible = true;
this.canvas.style.visibility = "visible";
// Changing icon
this.menuEntry.getElementsByClassName("default-icon")[1].style.display = "inline-block";
this.menuEntry.getElementsByClassName("edited-icon")[1].style.display = "none";
} }
this.hide = function() { hide() {
this.isVisible = false; this.isVisible = false;
this.canvas.style.visibility = "hidden";
// Changing icon
this.menuEntry.getElementsByClassName("default-icon")[1].style.display = "none";
this.menuEntry.getElementsByClassName("edited-icon")[1].style.display = "inline-block";
} }
} }
// Finds a layer given its name // Finds a layer given its name
function getLayerByName(name) { function getLayerByName(name) {
for (let i=0; i<layers.length; i++) { for (let i=0; i<layers.length; i++) {
if (layers[i].menuEntry != null) {
if (layers[i].menuEntry.getElementsByTagName("p")[0].innerHTML == name) { if (layers[i].menuEntry.getElementsByTagName("p")[0].innerHTML == name) {
return layers[i]; return layers[i];
} }
} }
}
return null; return null;
} }

View File

@@ -1,18 +1,19 @@
function newPixel (width, height, palette) { function newPixel (width, height, palette) {
// Setting the current layer layerList = document.getElementById("layers-menu");
layerListEntry = layerList.firstElementChild;
console.log("Layer entry: " + layerListEntry);
// Setting up the current layer
currentLayer = new Layer(width, height, canvas, layerListEntry); currentLayer = new Layer(width, height, canvas, layerListEntry);
currentLayer.initialize();
// Adding the checkerboard behind it // Adding the checkerboard behind it
checkerBoard = new Layer(width, height, checkerBoardCanvas); checkerBoard = new Layer(width, height, checkerBoardCanvas);
checkerBoard.initialize();
// Creating the vfx layer on top of everything // Creating the vfx layer on top of everything
VFXLayer = new Layer(width, height, VFXCanvas); VFXLayer = new Layer(width, height, VFXCanvas);
VFXLayer.initialize();
// Tmp layer to draw previews on
TMPLayer = new Layer(width, height, TMPCanvas); TMPLayer = new Layer(width, height, TMPCanvas);
TMPLayer.initialize();
canvasSize = currentLayer.canvasSize; canvasSize = currentLayer.canvasSize;