mirror of https://github.com/piskelapp/piskel.git
336 lines
9.9 KiB
JavaScript
336 lines
9.9 KiB
JavaScript
(function () {
|
|
var ns = $.namespace('pskl.controller.piskel');
|
|
|
|
ns.PiskelController = function (piskel) {
|
|
if (piskel) {
|
|
this.setPiskel(piskel);
|
|
} else {
|
|
throw 'A piskel instance is mandatory for instanciating PiskelController';
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Set the current piskel. Will reset the selected frame and layer unless specified
|
|
* @param {Object} piskel
|
|
* @param {Object} options:
|
|
* preserveState {Boolean} if true, keep the selected frame and layer
|
|
* noSnapshot {Boolean} if true, do not save a snapshot in the piskel
|
|
* history for this call to setPiskel
|
|
*/
|
|
ns.PiskelController.prototype.setPiskel = function (piskel, options) {
|
|
this.piskel = piskel;
|
|
options = options || {};
|
|
if (!options.preserveState) {
|
|
this.currentLayerIndex = 0;
|
|
this.currentFrameIndex = 0;
|
|
}
|
|
|
|
this.layerIdCounter = 1;
|
|
};
|
|
|
|
ns.PiskelController.prototype.init = function () {
|
|
};
|
|
|
|
ns.PiskelController.prototype.getHeight = function () {
|
|
return this.piskel.getHeight();
|
|
};
|
|
|
|
ns.PiskelController.prototype.getWidth = function () {
|
|
return this.piskel.getWidth();
|
|
};
|
|
|
|
ns.PiskelController.prototype.getFPS = function () {
|
|
return this.piskel.fps;
|
|
};
|
|
|
|
ns.PiskelController.prototype.setFPS = function (fps) {
|
|
if (typeof fps !== 'number') {
|
|
return;
|
|
}
|
|
this.piskel.fps = fps;
|
|
$.publish(Events.FPS_CHANGED);
|
|
};
|
|
|
|
ns.PiskelController.prototype.getLayers = function () {
|
|
return this.piskel.getLayers();
|
|
};
|
|
|
|
ns.PiskelController.prototype.getCurrentLayer = function () {
|
|
return this.getLayerAt(this.currentLayerIndex);
|
|
};
|
|
|
|
ns.PiskelController.prototype.getLayerAt = function (index) {
|
|
return this.piskel.getLayerAt(index);
|
|
};
|
|
|
|
ns.PiskelController.prototype.hasLayerAt = function (index) {
|
|
return !!this.getLayerAt(index);
|
|
};
|
|
|
|
// FIXME ?? No added value compared to getLayerAt ??
|
|
// Except normalizing to null if undefined ?? ==> To merge
|
|
ns.PiskelController.prototype.getLayerByIndex = function (index) {
|
|
var layers = this.getLayers();
|
|
if (layers[index]) {
|
|
return layers[index];
|
|
} else {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
ns.PiskelController.prototype.getCurrentFrame = function () {
|
|
var layer = this.getCurrentLayer();
|
|
return layer.getFrameAt(this.currentFrameIndex);
|
|
};
|
|
|
|
ns.PiskelController.prototype.getCurrentLayerIndex = function () {
|
|
return this.currentLayerIndex;
|
|
};
|
|
|
|
ns.PiskelController.prototype.getCurrentFrameIndex = function () {
|
|
return this.currentFrameIndex;
|
|
};
|
|
|
|
ns.PiskelController.prototype.getPiskel = function () {
|
|
return this.piskel;
|
|
};
|
|
|
|
ns.PiskelController.prototype.isTransparent = function () {
|
|
return this.getLayers().some(function (l) {
|
|
return l.isTransparent();
|
|
});
|
|
};
|
|
|
|
ns.PiskelController.prototype.renderFrameAt = function (index, preserveOpacity) {
|
|
return pskl.utils.LayerUtils.flattenFrameAt(this.getLayers(), index, preserveOpacity);
|
|
};
|
|
|
|
ns.PiskelController.prototype.hasFrameAt = function (index) {
|
|
return !!this.getCurrentLayer().getFrameAt(index);
|
|
};
|
|
|
|
ns.PiskelController.prototype.addFrame = function () {
|
|
this.addFrameAt(this.getFrameCount());
|
|
};
|
|
|
|
ns.PiskelController.prototype.addFrameAtCurrentIndex = function () {
|
|
this.addFrameAt(this.currentFrameIndex + 1);
|
|
};
|
|
|
|
ns.PiskelController.prototype.addFrameAt = function (index) {
|
|
this.getLayers().forEach(function (l) {
|
|
l.addFrameAt(this.createEmptyFrame_(), index);
|
|
}.bind(this));
|
|
|
|
this.setCurrentFrameIndex(index);
|
|
};
|
|
|
|
ns.PiskelController.prototype.createEmptyFrame_ = function () {
|
|
var w = this.piskel.getWidth();
|
|
var h = this.piskel.getHeight();
|
|
return new pskl.model.Frame(w, h);
|
|
};
|
|
|
|
ns.PiskelController.prototype.removeFrameAt = function (index) {
|
|
this.getLayers().forEach(function (l) {
|
|
l.removeFrameAt(index);
|
|
});
|
|
// Current frame index is impacted if the removed frame was before the current frame
|
|
if (this.currentFrameIndex >= index && this.currentFrameIndex > 0) {
|
|
this.setCurrentFrameIndex(this.currentFrameIndex - 1);
|
|
}
|
|
};
|
|
|
|
ns.PiskelController.prototype.duplicateCurrentFrame = function () {
|
|
this.duplicateFrameAt(this.currentFrameIndex);
|
|
};
|
|
|
|
ns.PiskelController.prototype.duplicateFrameAt = function (index) {
|
|
this.getLayers().forEach(function (l) {
|
|
l.duplicateFrameAt(index);
|
|
});
|
|
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.hasVisibleFrameAt = function (index) {
|
|
var frame = this.getCurrentLayer().getFrameAt(index);
|
|
return frame ? frame.isVisible() : false;
|
|
};
|
|
|
|
ns.PiskelController.prototype.getVisibleFrameIndexes = function () {
|
|
var frameIndexes = this.getCurrentLayer().getFrames()
|
|
/* Replace each frame with its index
|
|
or -1 if it's not visible */
|
|
.map(
|
|
function(frame, idx) {
|
|
return (frame.visible) ? idx : -1;
|
|
})
|
|
/* Filter out invisible frames */
|
|
.filter(
|
|
function(index) {
|
|
return index >= 0;
|
|
});
|
|
return frameIndexes;
|
|
};
|
|
|
|
ns.PiskelController.prototype.getFrameCount = function () {
|
|
return this.piskel.getFrameCount();
|
|
};
|
|
|
|
ns.PiskelController.prototype.setCurrentFrameIndex = function (index) {
|
|
if (this.hasFrameAt(index)) {
|
|
this.currentFrameIndex = index;
|
|
} else {
|
|
window.console.error('Could not set current frame index to ' + index);
|
|
}
|
|
};
|
|
|
|
ns.PiskelController.prototype.selectNextFrame = function () {
|
|
var nextIndex = this.currentFrameIndex + 1;
|
|
if (nextIndex < this.getFrameCount()) {
|
|
this.setCurrentFrameIndex(nextIndex);
|
|
}
|
|
};
|
|
|
|
ns.PiskelController.prototype.selectPreviousFrame = function () {
|
|
var nextIndex = this.currentFrameIndex - 1;
|
|
if (nextIndex >= 0) {
|
|
this.setCurrentFrameIndex(nextIndex);
|
|
}
|
|
};
|
|
|
|
ns.PiskelController.prototype.setCurrentLayerIndex = function (index) {
|
|
if (this.hasLayerAt(index)) {
|
|
this.currentLayerIndex = index;
|
|
} else {
|
|
window.console.error('Could not set current layer index to ' + index);
|
|
}
|
|
};
|
|
|
|
ns.PiskelController.prototype.selectLayer = function (layer) {
|
|
var index = this.getLayers().indexOf(layer);
|
|
if (index != -1) {
|
|
this.setCurrentLayerIndex(index);
|
|
}
|
|
};
|
|
|
|
ns.PiskelController.prototype.renameLayerAt = function (index, name) {
|
|
var layer = this.getLayerByIndex(index);
|
|
if (layer) {
|
|
layer.setName(name);
|
|
}
|
|
};
|
|
|
|
ns.PiskelController.prototype.setLayerOpacityAt = function (index, opacity) {
|
|
var layer = this.getLayerByIndex(index);
|
|
if (layer) {
|
|
layer.setOpacity(opacity);
|
|
}
|
|
};
|
|
|
|
ns.PiskelController.prototype.mergeDownLayerAt = function (index) {
|
|
var layer = this.getLayerByIndex(index);
|
|
var downLayer = this.getLayerByIndex(index - 1);
|
|
if (layer && downLayer) {
|
|
var mergedLayer = pskl.utils.LayerUtils.mergeLayers(layer, downLayer);
|
|
this.removeLayerAt(index);
|
|
this.piskel.addLayerAt(mergedLayer, index);
|
|
this.removeLayerAt(index - 1);
|
|
this.selectLayer(mergedLayer);
|
|
}
|
|
};
|
|
|
|
ns.PiskelController.prototype.generateLayerName_ = function () {
|
|
var name = 'Layer ' + this.layerIdCounter;
|
|
while (this.hasLayerForName_(name)) {
|
|
this.layerIdCounter++;
|
|
name = 'Layer ' + this.layerIdCounter;
|
|
}
|
|
return name;
|
|
};
|
|
|
|
ns.PiskelController.prototype.duplicateCurrentLayer = function () {
|
|
var layer = this.getCurrentLayer();
|
|
var clone = pskl.utils.LayerUtils.clone(layer);
|
|
var currentLayerIndex = this.getCurrentLayerIndex();
|
|
this.piskel.addLayerAt(clone, currentLayerIndex + 1);
|
|
this.setCurrentLayerIndex(currentLayerIndex + 1);
|
|
};
|
|
|
|
ns.PiskelController.prototype.createLayer = function (name) {
|
|
if (!name) {
|
|
name = this.generateLayerName_();
|
|
}
|
|
if (!this.hasLayerForName_(name)) {
|
|
var layer = new pskl.model.Layer(name);
|
|
for (var i = 0 ; i < this.getFrameCount() ; i++) {
|
|
layer.addFrame(this.createEmptyFrame_());
|
|
}
|
|
var currentLayerIndex = this.getCurrentLayerIndex();
|
|
this.piskel.addLayerAt(layer, currentLayerIndex + 1);
|
|
this.setCurrentLayerIndex(currentLayerIndex + 1);
|
|
} else {
|
|
throw 'Layer name should be unique';
|
|
}
|
|
};
|
|
|
|
ns.PiskelController.prototype.hasLayerForName_ = function (name) {
|
|
return this.piskel.getLayersByName(name).length > 0;
|
|
};
|
|
|
|
ns.PiskelController.prototype.moveLayerUp = function (toTop) {
|
|
var layer = this.getCurrentLayer();
|
|
this.piskel.moveLayerUp(layer, toTop);
|
|
this.selectLayer(layer);
|
|
};
|
|
|
|
ns.PiskelController.prototype.moveLayerDown = function (toBottom) {
|
|
var layer = this.getCurrentLayer();
|
|
this.piskel.moveLayerDown(layer, toBottom);
|
|
this.selectLayer(layer);
|
|
};
|
|
|
|
ns.PiskelController.prototype.removeCurrentLayer = function () {
|
|
var currentLayerIndex = this.getCurrentLayerIndex();
|
|
this.removeLayerAt(currentLayerIndex);
|
|
};
|
|
|
|
ns.PiskelController.prototype.removeLayerAt = function (index) {
|
|
if (!this.hasLayerAt(index)) {
|
|
return;
|
|
}
|
|
|
|
var layer = this.getLayerAt(index);
|
|
this.piskel.removeLayer(layer);
|
|
|
|
// Update the selected layer if needed.
|
|
if (this.getCurrentLayerIndex() === index) {
|
|
this.setCurrentLayerIndex(Math.max(0, index - 1));
|
|
}
|
|
};
|
|
|
|
ns.PiskelController.prototype.serialize = function () {
|
|
return pskl.utils.serialization.Serializer.serialize(this.piskel);
|
|
};
|
|
|
|
/**
|
|
* Check if the current sprite is empty. Emptiness here means no pixel has been filled
|
|
* on any layer or frame for the current sprite.
|
|
*/
|
|
ns.PiskelController.prototype.isEmpty = function () {
|
|
return pskl.app.currentColorsService.getCurrentColors().length === 0;
|
|
};
|
|
})();
|