Implemented with history management.
This commit is contained in:
parent
e5d89104a1
commit
89629d2939
11 changed files with 129 additions and 45 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -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++;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue