mirror of
https://github.com/lospec/pixel-editor.git
synced 2023-08-10 21:12:51 +03:00
Finished implementing layers
Updated readme with the features that should be implemented.
This commit is contained in:
parent
a860677488
commit
75a6b7ade7
@ -12,6 +12,11 @@ The next version is mostly focused on adding missing essential features and port
|
|||||||
|
|
||||||
Suggestions / Planned features:
|
Suggestions / Planned features:
|
||||||
|
|
||||||
|
- Line tool
|
||||||
|
- Resize canvas
|
||||||
|
- Snap brush preview to pixel grid
|
||||||
|
- Move selection with arrows
|
||||||
|
|
||||||
- Custom color picker
|
- Custom color picker
|
||||||
- custom code without dependencies
|
- custom code without dependencies
|
||||||
- more features such as sliders / color modes
|
- more features such as sliders / color modes
|
||||||
@ -23,8 +28,6 @@ Suggestions / Planned features:
|
|||||||
- Stack colors when too many
|
- Stack colors when too many
|
||||||
- Fix popups
|
- Fix popups
|
||||||
|
|
||||||
- Copy/paste
|
|
||||||
- Add as selection
|
|
||||||
- Show colors which would need to be added to palette
|
- Show colors which would need to be added to palette
|
||||||
|
|
||||||
- Palette option remove unused colors
|
- Palette option remove unused colors
|
||||||
|
@ -18,10 +18,6 @@ function getCursorPosition(e) {
|
|||||||
return [x,y];
|
return [x,y];
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: apply the function below to every getCursorPosition call
|
|
||||||
|
|
||||||
// TODO: FIX THIS BELOW
|
|
||||||
|
|
||||||
//get cursor position relative to canvas
|
//get cursor position relative to canvas
|
||||||
function getCursorPositionRelative(e, layer) {
|
function getCursorPositionRelative(e, layer) {
|
||||||
var x;
|
var x;
|
||||||
|
@ -162,17 +162,47 @@ function HistoryStateDeleteLayer(layerData, before, index) {
|
|||||||
saveHistoryState(this);
|
saveHistoryState(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
function HistoryStateMoveLayer(layer1, layer2) {
|
function HistoryStateMoveTwoLayers(layer, oldIndex, newIndex) {
|
||||||
this.layer1 = layer1;
|
this.layer = layer;
|
||||||
this.layer2 = layer2;
|
this.oldIndex = oldIndex;
|
||||||
|
this.newIndex = newIndex;
|
||||||
|
|
||||||
this.undo = function() {
|
this.undo = function() {
|
||||||
swapLayerEntries(layer1, layer2, false);
|
layer.canvas.style.zIndex = oldIndex;
|
||||||
redoStates.push(this);
|
redoStates.push(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.redo = function() {
|
this.redo = function() {
|
||||||
swapLayerEntries(layer1, layer2, false);
|
layer.canvas.style.zIndex = newIndex;
|
||||||
|
undoStates.push(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
saveHistoryState(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
function HistoryStateMoveLayer(afterToDrop, toDrop, static, nMoved) {
|
||||||
|
this.beforeToDrop = afterToDrop;
|
||||||
|
this.toDrop = toDrop;
|
||||||
|
|
||||||
|
this.undo = function() {
|
||||||
|
toDrop.menuEntry.remove();
|
||||||
|
|
||||||
|
if (afterToDrop != null) {
|
||||||
|
layerList.insertBefore(toDrop.menuEntry, afterToDrop)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
layerList.append(toDrop.menuEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i=0; i<nMoved; i++) {
|
||||||
|
undo();
|
||||||
|
}
|
||||||
|
|
||||||
|
redoStates.push(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.redo = function() {
|
||||||
|
moveLayers(toDrop.menuEntry.id, static.menuEntry.id, true);
|
||||||
undoStates.push(this);
|
undoStates.push(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
80
js/_layer.js
80
js/_layer.js
@ -5,28 +5,9 @@
|
|||||||
the layers they created? That'd be cool, even for the app users, that could just double click on a lospec
|
the layers they created? That'd be cool, even for the app users, that could just double click on a lospec
|
||||||
file for it to be opened right in the pixel editor
|
file for it to be opened right in the pixel editor
|
||||||
|
|
||||||
HISTORY:
|
|
||||||
- Save merge layers
|
|
||||||
- Save flatten layers
|
|
||||||
|
|
||||||
OPTIONAL:
|
OPTIONAL:
|
||||||
|
|
||||||
1 - Fix issues
|
1 - Fix issues
|
||||||
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)
|
|
||||||
|
|
||||||
THINGS TO TEST:
|
|
||||||
|
|
||||||
1 - Undo / redo
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
MORE TODO LIST:
|
|
||||||
|
|
||||||
- Resize canvas (must make a simple editor to preview the changes)
|
|
||||||
- Resize sprite
|
|
||||||
- Refactor the code so that every instance of "canvas" and "context" is replaced by currentLayer.canvas
|
|
||||||
and currentLayer.context
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let layerList;
|
let layerList;
|
||||||
@ -125,6 +106,7 @@ class Layer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
layerDragStart(element) {
|
layerDragStart(element) {
|
||||||
|
layerList.children[layerList.childElementCount - 2].setAttribute("draggable", "true");
|
||||||
layerDragSource = this;
|
layerDragSource = this;
|
||||||
element.dataTransfer.effectAllowed = 'move';
|
element.dataTransfer.effectAllowed = 'move';
|
||||||
element.dataTransfer.setData('text/html', this.id);
|
element.dataTransfer.setData('text/html', this.id);
|
||||||
@ -168,6 +150,7 @@ class Layer {
|
|||||||
|
|
||||||
layerDragEnd(element) {
|
layerDragEnd(element) {
|
||||||
this.classList.remove('layerdragover');
|
this.classList.remove('layerdragover');
|
||||||
|
layerList.children[layerList.childElementCount - 2].setAttribute("draggable", "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resizes canvas
|
// Resizes canvas
|
||||||
@ -462,19 +445,14 @@ function renameLayer(event) {
|
|||||||
|
|
||||||
// Swaps two layer entries in the layer menu
|
// Swaps two layer entries in the layer menu
|
||||||
function moveLayers(toDropLayer, staticLayer, saveHistory = true) {
|
function moveLayers(toDropLayer, staticLayer, saveHistory = true) {
|
||||||
let entry1 = document.getElementById(toDropLayer);
|
|
||||||
let entry2 = document.getElementById(staticLayer);
|
|
||||||
|
|
||||||
let toDrop = getLayerByID(toDropLayer);
|
let toDrop = getLayerByID(toDropLayer);
|
||||||
let static = getLayerByID(staticLayer);
|
let static = getLayerByID(staticLayer);
|
||||||
let layerCopy = layers;
|
let layerCopy = layers;
|
||||||
let tmpZIndex;
|
|
||||||
|
|
||||||
let after2 = entry2.nextSibling;
|
let beforeToDrop = toDrop.menuEntry.nextElementSibling;
|
||||||
let parent = entry1.parentNode;
|
let nMoved = 0;
|
||||||
|
|
||||||
layerCopy.sort((a, b) => (a.canvas.style.zIndex > b.canvas.style.zIndex) ? 1 : -1);
|
layerCopy.sort((a, b) => (a.canvas.style.zIndex > b.canvas.style.zIndex) ? 1 : -1);
|
||||||
console.log(layerCopy.map(a => a.canvas.style.zIndex));
|
|
||||||
|
|
||||||
let toDropIndex = layerCopy.indexOf(toDrop);
|
let toDropIndex = layerCopy.indexOf(toDrop);
|
||||||
let staticIndex = layerCopy.indexOf(static);
|
let staticIndex = layerCopy.indexOf(static);
|
||||||
@ -482,17 +460,30 @@ function moveLayers(toDropLayer, staticLayer, saveHistory = true) {
|
|||||||
layerList.insertBefore(toDrop.menuEntry, static.menuEntry);
|
layerList.insertBefore(toDrop.menuEntry, static.menuEntry);
|
||||||
|
|
||||||
if (toDropIndex < staticIndex) {
|
if (toDropIndex < staticIndex) {
|
||||||
console.log("UO");
|
|
||||||
let tmp = toDrop.canvas.style.zIndex;
|
let tmp = toDrop.canvas.style.zIndex;
|
||||||
let tmp2;
|
let tmp2;
|
||||||
|
|
||||||
for (let i=toDropIndex+1; i<=staticIndex; i++) {
|
for (let i=toDropIndex+1; i<=staticIndex; i++) {
|
||||||
tmp2 = layerCopy[i].canvas.style.zIndex;
|
tmp2 = layerCopy[i].canvas.style.zIndex;
|
||||||
|
|
||||||
|
if (saveHistory) {
|
||||||
|
new HistoryStateMoveTwoLayers(layerCopy[i], tmp2, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
layerCopy[i].canvas.style.zIndex = tmp;
|
layerCopy[i].canvas.style.zIndex = tmp;
|
||||||
tmp = tmp2;
|
tmp = tmp2;
|
||||||
|
nMoved++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveHistory) {
|
||||||
|
new HistoryStateMoveTwoLayers(toDrop, toDrop.canvas.style.zIndex, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
toDrop.canvas.style.zIndex = tmp;
|
toDrop.canvas.style.zIndex = tmp;
|
||||||
|
|
||||||
|
if (saveHistory) {
|
||||||
|
new HistoryStateMoveLayer(beforeToDrop, toDrop, static, nMoved);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// BUG QUI
|
// BUG QUI
|
||||||
@ -501,35 +492,26 @@ function moveLayers(toDropLayer, staticLayer, saveHistory = true) {
|
|||||||
|
|
||||||
for (let i=toDropIndex-1; i>staticIndex; i--) {
|
for (let i=toDropIndex-1; i>staticIndex; i--) {
|
||||||
tmp2 = layerCopy[i].canvas.style.zIndex;
|
tmp2 = layerCopy[i].canvas.style.zIndex;
|
||||||
|
|
||||||
|
if (saveHistory) {
|
||||||
|
new HistoryStateMoveTwoLayers(layerCopy[i], tmp2, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
layerCopy[i].canvas.style.zIndex = tmp;
|
layerCopy[i].canvas.style.zIndex = tmp;
|
||||||
tmp = tmp2;
|
tmp = tmp2;
|
||||||
|
nMoved++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveHistory) {
|
||||||
|
new HistoryStateMoveTwoLayers(toDrop, toDrop.canvas.style.zIndex, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
toDrop.canvas.style.zIndex = tmp;
|
toDrop.canvas.style.zIndex = tmp;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
console.log("id1: " + toDrop + ", id2: " + static);
|
|
||||||
|
|
||||||
tmpZIndex = layer1.canvas.style.zIndex;
|
|
||||||
layer1.canvas.style.zIndex = layer2.canvas.style.zIndex;
|
|
||||||
layer2.canvas.style.zIndex = tmpZIndex;
|
|
||||||
|
|
||||||
parent.insertBefore(entry2, entry1);
|
|
||||||
|
|
||||||
if (after2) {
|
|
||||||
if (after2 == entry1) {
|
|
||||||
parent.prepend(entry1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
parent.insertBefore(entry1, after2);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
parent.appendChild(entry1);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
if (saveHistory) {
|
if (saveHistory) {
|
||||||
new HistoryStateMoveLayer(toDrop, static);
|
new HistoryStateMoveLayer(beforeToDrop, toDrop, static, nMoved);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
var currentMouseEvent;
|
var currentMouseEvent;
|
||||||
// TODO: replace every position calculation with lastMousePos
|
|
||||||
var lastMousePos;
|
var lastMousePos;
|
||||||
|
|
||||||
//mousedown - start drawing
|
//mousedown - start drawing
|
||||||
@ -75,7 +74,6 @@ window.addEventListener("mouseup", function (mouseEvent) {
|
|||||||
|
|
||||||
if (currentTool.name == 'eyedropper' && mouseEvent.target.className == 'drawingCanvas') {
|
if (currentTool.name == 'eyedropper' && mouseEvent.target.className == 'drawingCanvas') {
|
||||||
var cursorLocation = getCursorPosition(mouseEvent);
|
var cursorLocation = getCursorPosition(mouseEvent);
|
||||||
// TODO: adjust so that if the picked colour is transparent, the underlying layer is checked
|
|
||||||
var selectedColor = getEyedropperColor(cursorLocation);
|
var selectedColor = getEyedropperColor(cursorLocation);
|
||||||
var newColor = rgbToHex(selectedColor[0],selectedColor[1],selectedColor[2]);
|
var newColor = rgbToHex(selectedColor[0],selectedColor[1],selectedColor[2]);
|
||||||
|
|
||||||
@ -96,8 +94,9 @@ window.addEventListener("mouseup", function (mouseEvent) {
|
|||||||
|
|
||||||
//set current color
|
//set current color
|
||||||
|
|
||||||
// TODO: set it for all the layers
|
for (let i=2; i<layers.length; i++) {
|
||||||
context.fillStyle = '#'+newColor;
|
layers[i].context.fillStyle = '#' + newColor;
|
||||||
|
}
|
||||||
|
|
||||||
//make color selected
|
//make color selected
|
||||||
colors[i].parentElement.classList.add('selected');
|
colors[i].parentElement.classList.add('selected');
|
||||||
|
@ -41,11 +41,6 @@ function newPixel (width, height, palette) {
|
|||||||
canvas = currentLayer.canvas;
|
canvas = currentLayer.canvas;
|
||||||
context = currentLayer.context;
|
context = currentLayer.context;
|
||||||
canvas.style.zIndex = 2;
|
canvas.style.zIndex = 2;
|
||||||
|
|
||||||
// TODO: clean layers before creating a new pixel
|
|
||||||
// Devo togliere tutte le entries tranne la prima
|
|
||||||
// Devo pulire la preview della prima entry
|
|
||||||
// Devo cancellare tutte le tele tranne quella con id pixel-canvas
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adding the checkerboard behind it
|
// Adding the checkerboard behind it
|
||||||
|
@ -98,8 +98,6 @@ function drawRect(x, y) {
|
|||||||
vfxContext.rect(startX, startY, x - startX, y - startY);
|
vfxContext.rect(startX, startY, x - startX, y - startY);
|
||||||
|
|
||||||
vfxContext.stroke();
|
vfxContext.stroke();
|
||||||
|
|
||||||
// TODO: make the rect blink from black to white in case of dark backgrounds
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyChanges() {
|
function applyChanges() {
|
||||||
|
@ -1,10 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<!--todo: credit RECTANGULAR SELECTION ICON BY https://www.flaticon.com/authors/pixel-perfect or
|
|
||||||
design an original icon (this is just a placeholder)
|
|
||||||
|
|
||||||
Must also credit this guy for the rectangle tool
|
|
||||||
Icons made by <a href="https://www.flaticon.com/authors/freepik" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon"> www.flaticon.com</a>
|
|
||||||
-->
|
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
|
Loading…
Reference in New Issue
Block a user