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 { .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 { .preview-tile .tile-overlay.delete-frame-action {

View file

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

View file

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

View file

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

View file

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

View file

@ -9,7 +9,7 @@
this.version = 0; this.version = 0;
this.pixels = ns.Frame.createEmptyPixelGrid_(width, height); this.pixels = ns.Frame.createEmptyPixelGrid_(width, height);
this.stateIndex = 0; this.stateIndex = 0;
this.toggled = true; this.visible = true;
} else { } else {
throw 'Bad arguments in pskl.model.Frame constructor : ' + width + ', ' + height; throw 'Bad arguments in pskl.model.Frame constructor : ' + width + ', ' + height;
} }
@ -152,4 +152,12 @@
ns.Frame.prototype.isSameSize = function (otherFrame) { ns.Frame.prototype.isSameSize = function (otherFrame) {
return this.getHeight() == otherFrame.getHeight() && this.getWidth() == otherFrame.getWidth(); 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 () { ns.Layer.prototype.size = function () {
return this.frames.length; return this.frames.length;
}; };

View file

@ -36,6 +36,7 @@
var descriptor = new pskl.model.piskel.Descriptor(name, description); var descriptor = new pskl.model.piskel.Descriptor(name, description);
this.piskel_ = new pskl.model.Piskel(piskelData.width, piskelData.height, piskelData.fps, descriptor); this.piskel_ = new pskl.model.Piskel(piskelData.width, piskelData.height, piskelData.fps, descriptor);
this.hiddenFrames = piskelData.hiddenFrames || [];
this.layersToLoad_ = piskelData.layers.length; this.layersToLoad_ = piskelData.layers.length;
piskelData.layers.forEach(this.deserializeLayer.bind(this)); piskelData.layers.forEach(this.deserializeLayer.bind(this));
@ -73,7 +74,14 @@
image.src = chunk.base64PNG; image.src = chunk.base64PNG;
return deferred.promise; return deferred.promise;
})).then(function () { })).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.layers_[index] = layer;
this.onLayerLoaded_(); this.onLayerLoaded_();
}.bind(this)).catch(function (error) { }.bind(this)).catch(function (error) {

View file

@ -21,6 +21,16 @@
var serializedLayers = piskel.getLayers().map(function (l) { var serializedLayers = piskel.getLayers().map(function (l) {
return pskl.utils.serialization.Serializer.serializeLayer(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({ return JSON.stringify({
modelVersion : Constants.MODEL_VERSION, modelVersion : Constants.MODEL_VERSION,
piskel : { piskel : {
@ -29,7 +39,8 @@
fps : pskl.app.piskelController.getFPS(), fps : pskl.app.piskelController.getFPS(),
height : piskel.getHeight(), height : piskel.getHeight(),
width : piskel.getWidth(), width : piskel.getWidth(),
layers : serializedLayers layers : serializedLayers,
hiddenFrames : hiddenFrames,
} }
}); });
}, },

View file

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

View file

@ -101,7 +101,22 @@
framesData.push({uri: dataUri, length: dataUriLength}); 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 buffer = new ArrayBuffer(bytes);
var arr8 = new Uint8Array(buffer); var arr8 = new Uint8Array(buffer);
@ -130,21 +145,33 @@
// Layers meta // Layers meta
arr16[6] = piskel.getLayers().length; arr16[6] = piskel.getLayers().length;
// Frames meta
arr16[7] = serializedHiddenFrames.length;
var currentIndex = 8;
/********/ /********/
/* DATA */ /* DATA */
/********/ /********/
// Descriptor name // Descriptor name
for (i = 0; i < descriptorNameLength; i++) { for (i = 0; i < descriptorNameLength; i++) {
arr16[7 + i] = descriptorName.charCodeAt(i); arr16[currentIndex + i] = descriptorName.charCodeAt(i);
} }
currentIndex = currentIndex + descriptorNameLength;
// Descriptor description // Descriptor description
for (i = 0; i < descriptorDescriptionLength; i++) { 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 // Layers
var layerStartIndex = 7 + descriptorNameLength + descriptorDescriptionLength;
for (i = 0, layers = piskel.getLayers(); i < layers.length; i++) { for (i = 0, layers = piskel.getLayers(); i < layers.length; i++) {
var layer = layers[i]; var layer = layers[i];
var frames = layer.getFrames(); var frames = layer.getFrames();
@ -158,23 +185,23 @@
dataUriLength = framesData[i].length; dataUriLength = framesData[i].length;
// Meta // Meta
arr16[layerStartIndex] = layerNameLength; arr16[currentIndex] = layerNameLength;
arr16[layerStartIndex + 1] = Math.floor(opacity * 65535); arr16[currentIndex + 1] = Math.floor(opacity * 65535);
arr16[layerStartIndex + 2] = frameCount; arr16[currentIndex + 2] = frameCount;
arr16[layerStartIndex + 3] = ((dataUriLength & 0xffff0000) >> 16) >>> 0; // Upper 16 arr16[currentIndex + 3] = ((dataUriLength & 0xffff0000) >> 16) >>> 0; // Upper 16
arr16[layerStartIndex + 4] = ((dataUriLength & 0x0000ffff)) >>> 0; // Lower 16 arr16[currentIndex + 4] = ((dataUriLength & 0x0000ffff)) >>> 0; // Lower 16
// Name // Name
for (j = 0; j < layerNameLength; j++) { for (j = 0; j < layerNameLength; j++) {
arr16[layerStartIndex + 5 + j] = layerName.charCodeAt(j); arr16[currentIndex + 5 + j] = layerName.charCodeAt(j);
} }
// Data URI // Data URI
for (j = 0; j < dataUriLength; j++) { 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; return buffer;