Implemented with history management.

This commit is contained in:
Grzegorz 2018-09-09 18:33:56 +02:00 committed by Julian Descottes
parent e5d89104a1
commit 89629d2939
11 changed files with 129 additions and 45 deletions

View file

@ -136,7 +136,8 @@
}
.preview-tile .tile-overlay.tile-count.toggled {
background-color: rgba(111, 215, 0, 0.6);
background-color: gold;
color: black;
}
.preview-tile .tile-overlay.delete-frame-action {

View file

@ -116,8 +116,7 @@
this.previewList.insertBefore(newtile, this.addFrameTile);
this.updateScrollerOverflows();
} else if (action == ACTION.TOGGLE) {
var frame = this.piskelController.getCurrentLayer().getFrameAt(index);
frame.toggled = !frame.toggled;
this.piskelController.toggleFrameAt(index);
}
this.flagForRedraw_();
@ -138,9 +137,8 @@
this.tiles[i].setAttribute('data-tile-number', i);
this.tiles[i].querySelector('.tile-count').innerHTML = (i + 1);
// Update toggle
var frame = this.piskelController.getCurrentLayer().getFrameAt(i);
if (frame.toggled) {
// Update visibility
if (this.piskelController.hasVisibleFrameAt(i)) {
this.tiles[i].querySelector('.tile-count').classList.add('toggled');
}

View file

@ -152,31 +152,35 @@
this.setCurrentFrameIndex(index + 1);
};
ns.PiskelController.prototype.toggleFrameAt = function (index) {
this.getLayers().forEach(function (l) {
l.toggleFrameAt(index);
});
};
ns.PiskelController.prototype.moveFrame = function (fromIndex, toIndex) {
this.getLayers().forEach(function (l) {
l.moveFrame(fromIndex, toIndex);
});
};
ns.PiskelController.prototype.getFrames = function () {
var layer = this.getCurrentLayer();
return layer.getFrames();
ns.PiskelController.prototype.hasVisibleFrameAt = function (index) {
var frame = this.getCurrentLayer().getFrameAt(index);
return frame ? frame.isVisible() : false;
};
ns.PiskelController.prototype.getToggledFrameIndexes = function () {
var frameIndexes = this.getFrames()
ns.PiskelController.prototype.getVisibleFrameIndexes = function () {
var frameIndexes = this.getCurrentLayer().getFrames()
/* Replace each frame with its index
or -1 if it's not toggled */
or -1 if it's not visible */
.map(
function(frame, idx) {
var idx;
idx += 1;
return (frame.toggled) ? idx - 1 : -1;
return (frame.visible) ? idx : -1;
})
/* Filter out untoggled frames */
/* Filter out invisible frames */
.filter(
function(frame) {
return frame >= 0;
function(index) {
return index >= 0;
});
return frameIndexes;
};

View file

@ -37,6 +37,7 @@
this.saveWrap_('moveLayerDown', true);
this.saveWrap_('removeCurrentLayer', true);
this.saveWrap_('setLayerOpacityAt', true);
this.saveWrap_('toggleFrameAt', true);
var shortcuts = pskl.service.keyboard.Shortcuts;
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.PREVIOUS_FRAME, this.selectPreviousFrame.bind(this));

View file

@ -281,7 +281,7 @@
return this.piskelController.getCurrentFrameIndex();
} else {
var index = Math.floor(this.elapsedTime / (1000 / this.fps));
var frameIndexes = this.piskelController.getToggledFrameIndexes();
var frameIndexes = this.piskelController.getVisibleFrameIndexes();
if (frameIndexes.length <= index) {
this.elapsedTime = 0;
index = (frameIndexes.length) ? frameIndexes[0] : this.piskelController.getCurrentFrameIndex();

View file

@ -9,7 +9,7 @@
this.version = 0;
this.pixels = ns.Frame.createEmptyPixelGrid_(width, height);
this.stateIndex = 0;
this.toggled = true;
this.visible = true;
} else {
throw 'Bad arguments in pskl.model.Frame constructor : ' + width + ', ' + height;
}
@ -152,4 +152,12 @@
ns.Frame.prototype.isSameSize = function (otherFrame) {
return this.getHeight() == otherFrame.getHeight() && this.getWidth() == otherFrame.getWidth();
};
ns.Frame.prototype.toggleVisibility = function () {
this.visible = !this.visible;
};
ns.Frame.prototype.isVisible = function () {
return this.visible;
};
})();

View file

@ -110,6 +110,15 @@
}
};
ns.Layer.prototype.toggleFrameAt = function (index) {
var frame = this.frames[index];
if (frame) {
frame.toggleVisibility();
} else {
console.error('Frame not found in toggleFrameAt (at %s)', index);
}
};
ns.Layer.prototype.size = function () {
return this.frames.length;
};

View file

@ -36,6 +36,7 @@
var descriptor = new pskl.model.piskel.Descriptor(name, description);
this.piskel_ = new pskl.model.Piskel(piskelData.width, piskelData.height, piskelData.fps, descriptor);
this.hiddenFrames = piskelData.hiddenFrames || [];
this.layersToLoad_ = piskelData.layers.length;
piskelData.layers.forEach(this.deserializeLayer.bind(this));
@ -73,7 +74,14 @@
image.src = chunk.base64PNG;
return deferred.promise;
})).then(function () {
frames.forEach(layer.addFrame.bind(layer));
var hiddenFrames = this.hiddenFrames;
frames.forEach(function (frame) {
layer.addFrame(frame);
var currentIndex = layer.getFrames().length - 1;
if (hiddenFrames.indexOf(currentIndex) != -1) {
frame.visible = false;
}
});
this.layers_[index] = layer;
this.onLayerLoaded_();
}.bind(this)).catch(function (error) {

View file

@ -21,6 +21,16 @@
var serializedLayers = piskel.getLayers().map(function (l) {
return pskl.utils.serialization.Serializer.serializeLayer(l);
});
var frames = pskl.app.piskelController.getLayerAt(0).getFrames();
var hiddenFrames = frames.map(function (frame, index) {
if (frame.visible) {
return -1;
}
return index;
}).filter(function (frameIndex) {
return frameIndex !== -1;
});
return JSON.stringify({
modelVersion : Constants.MODEL_VERSION,
piskel : {
@ -29,7 +39,8 @@
fps : pskl.app.piskelController.getFPS(),
height : piskel.getHeight(),
width : piskel.getWidth(),
layers : serializedLayers
layers : serializedLayers,
hiddenFrames : hiddenFrames,
}
});
},

View file

@ -36,23 +36,36 @@
// Layers meta
var layerCount = arr16[6];
// Layers meta
var serializedHiddenFramesLength = arr16[7];
var currentIndex = 8;
/********/
/* DATA */
/********/
// Descriptor name
var descriptorName = '';
for (i = 0; i < descriptorNameLength; i++) {
descriptorName += String.fromCharCode(arr16[7 + i]);
descriptorName += String.fromCharCode(arr16[currentIndex + i]);
}
currentIndex += descriptorNameLength;
// Descriptor description
var descriptorDescription = '';
for (i = 0; i < descriptorDescriptionLength; i++) {
descriptorDescription = String.fromCharCode(arr16[7 + descriptorNameLength + i]);
descriptorDescription = String.fromCharCode(arr16[8 + descriptorNameLength + i]);
}
currentIndex += descriptorDescriptionLength;
// Hidden frames
var serializedHiddenFrames = '';
for (i = 0; i < serializedHiddenFramesLength; i++) {
serializedHiddenFrames = String.fromCharCode(arr16[8 + descriptorNameLength + i]);
}
var hiddenFrames = serializedHiddenFrames.split('-');
currentIndex += serializedHiddenFramesLength;
// Layers
var layerStartIndex = 7 + descriptorNameLength + descriptorDescriptionLength;
var layers = [];
var layer;
for (i = 0; i < layerCount; i++) {
@ -60,27 +73,27 @@
var frames = [];
// Meta
var layerNameLength = arr16[layerStartIndex];
var opacity = arr16[layerStartIndex + 1] / 65535;
var frameCount = arr16[layerStartIndex + 2];
var dataUriLengthFirstHalf = arr16[layerStartIndex + 3];
var dataUriLengthSecondHalf = arr16[layerStartIndex + 4];
var layerNameLength = arr16[currentIndex];
var opacity = arr16[currentIndex + 1] / 65535;
var frameCount = arr16[currentIndex + 2];
var dataUriLengthFirstHalf = arr16[currentIndex + 3];
var dataUriLengthSecondHalf = arr16[currentIndex + 4];
var dataUriLength = (dataUriLengthSecondHalf >>> 0) | (dataUriLengthFirstHalf << 16 >>> 0);
// Name
var layerName = '';
for (j = 0; j < layerNameLength; j++) {
layerName += String.fromCharCode(arr16[layerStartIndex + 5 + j]);
layerName += String.fromCharCode(arr16[currentIndex + 5 + j]);
}
// Data URI
var dataUri = '';
for (j = 0; j < dataUriLength; j++) {
dataUri += String.fromCharCode(arr8[(layerStartIndex + 5 + layerNameLength) * 2 + j]);
dataUri += String.fromCharCode(arr8[(currentIndex + 5 + layerNameLength) * 2 + j]);
}
dataUri = 'data:image/png;base64,' + dataUri;
layerStartIndex += Math.ceil(5 + layerNameLength + (dataUriLength / 2));
currentIndex += Math.ceil(5 + layerNameLength + (dataUriLength / 2));
layer.name = layerName;
layer.opacity = opacity;
@ -99,6 +112,10 @@
var frames = pskl.utils.FrameUtils.createFramesFromSpritesheet(this, layer.frameCount);
frames.forEach(function (frame) {
layer.model.addFrame(frame);
var currentIndex = layer.model.getFrames().length - 1;
if (hiddenFrames.indexOf(currentIndex) != -1) {
frame.visible = false;
}
});
loadedLayers++;

View file

@ -101,7 +101,22 @@
framesData.push({uri: dataUri, length: dataUriLength});
}
var bytes = ns.ArrayBufferSerializer.calculateRequiredBytes(piskel, framesData);
var frames = pskl.app.piskelController.getLayerAt(0).getFrames();
var hiddenFrames = frames.map(function (frame, index) {
if (frame.visible) {
return -1;
}
return index;
}).filter(function (frameIndex) {
return frameIndex !== -1;
});
var serializedHiddenFrames = hiddenFrames.join('-');
var bytes = ns.ArrayBufferSerializer.calculateRequiredBytes(
piskel,
framesData,
serializedHiddenFrames
);
var buffer = new ArrayBuffer(bytes);
var arr8 = new Uint8Array(buffer);
@ -130,21 +145,33 @@
// Layers meta
arr16[6] = piskel.getLayers().length;
// Frames meta
arr16[7] = serializedHiddenFrames.length;
var currentIndex = 8;
/********/
/* DATA */
/********/
// Descriptor name
for (i = 0; i < descriptorNameLength; i++) {
arr16[7 + i] = descriptorName.charCodeAt(i);
arr16[currentIndex + i] = descriptorName.charCodeAt(i);
}
currentIndex = currentIndex + descriptorNameLength;
// Descriptor description
for (i = 0; i < descriptorDescriptionLength; i++) {
arr16[7 + descriptorNameLength + i] = descriptorDescription.charCodeAt(i);
arr16[currentIndex + i] = descriptorDescription.charCodeAt(i);
}
currentIndex = currentIndex + descriptorDescriptionLength;
// Hidden frames
for (i = 0; i < serializedHiddenFrames.length; i++) {
arr16[currentIndex + i] = serializedHiddenFrames.charCodeAt(i);
}
currentIndex = currentIndex + serializedHiddenFrames.length;
// Layers
var layerStartIndex = 7 + descriptorNameLength + descriptorDescriptionLength;
for (i = 0, layers = piskel.getLayers(); i < layers.length; i++) {
var layer = layers[i];
var frames = layer.getFrames();
@ -158,23 +185,23 @@
dataUriLength = framesData[i].length;
// Meta
arr16[layerStartIndex] = layerNameLength;
arr16[layerStartIndex + 1] = Math.floor(opacity * 65535);
arr16[layerStartIndex + 2] = frameCount;
arr16[layerStartIndex + 3] = ((dataUriLength & 0xffff0000) >> 16) >>> 0; // Upper 16
arr16[layerStartIndex + 4] = ((dataUriLength & 0x0000ffff)) >>> 0; // Lower 16
arr16[currentIndex] = layerNameLength;
arr16[currentIndex + 1] = Math.floor(opacity * 65535);
arr16[currentIndex + 2] = frameCount;
arr16[currentIndex + 3] = ((dataUriLength & 0xffff0000) >> 16) >>> 0; // Upper 16
arr16[currentIndex + 4] = ((dataUriLength & 0x0000ffff)) >>> 0; // Lower 16
// Name
for (j = 0; j < layerNameLength; j++) {
arr16[layerStartIndex + 5 + j] = layerName.charCodeAt(j);
arr16[currentIndex + 5 + j] = layerName.charCodeAt(j);
}
// Data URI
for (j = 0; j < dataUriLength; j++) {
arr8[(layerStartIndex + 5 + layerNameLength) * 2 + j] = dataUri.charCodeAt(j);
arr8[(currentIndex + 5 + layerNameLength) * 2 + j] = dataUri.charCodeAt(j);
}
layerStartIndex += Math.ceil(5 + layerNameLength + (dataUriLength / 2));
currentIndex += Math.ceil(5 + layerNameLength + (dataUriLength / 2));
}
return buffer;