2012-09-07 02:18:59 +04:00
|
|
|
(function () {
|
2014-04-17 03:27:49 +04:00
|
|
|
var ns = $.namespace('pskl.service');
|
|
|
|
|
2014-04-19 18:01:51 +04:00
|
|
|
var SNAPSHOT_PERIOD = 50;
|
2014-04-17 03:27:49 +04:00
|
|
|
|
2013-09-22 23:02:43 +04:00
|
|
|
ns.HistoryService = function (piskelController) {
|
2013-09-29 01:52:51 +04:00
|
|
|
this.piskelController = piskelController;
|
2014-04-17 03:27:49 +04:00
|
|
|
this.stateQueue = [];
|
|
|
|
this.currentIndex = -1;
|
2013-12-11 00:25:36 +04:00
|
|
|
this.saveState__b = this.saveState.bind(this);
|
2014-04-17 03:27:49 +04:00
|
|
|
|
|
|
|
this.lastEvent = -1;
|
2012-09-11 01:26:12 +04:00
|
|
|
};
|
2012-09-07 02:18:59 +04:00
|
|
|
|
2013-08-10 14:11:16 +04:00
|
|
|
ns.HistoryService.prototype.init = function () {
|
2013-09-29 01:52:51 +04:00
|
|
|
|
2014-04-17 03:27:49 +04:00
|
|
|
$.subscribe(Events.PISKEL_SAVE_STATE, this.saveState__b);
|
2013-11-20 02:46:33 +04:00
|
|
|
|
|
|
|
pskl.app.shortcutService.addShortcut('ctrl+Z', this.undo.bind(this));
|
|
|
|
pskl.app.shortcutService.addShortcut('ctrl+Y', this.redo.bind(this));
|
2013-08-10 14:11:16 +04:00
|
|
|
};
|
2012-09-07 02:18:59 +04:00
|
|
|
|
2014-04-17 03:27:49 +04:00
|
|
|
ns.HistoryService.prototype.saveState = function (evt, actionInfo) {
|
|
|
|
this.stateQueue = this.stateQueue.slice(0, this.currentIndex + 1);
|
|
|
|
this.currentIndex = this.currentIndex + 1;
|
|
|
|
|
|
|
|
var state = {
|
|
|
|
action : actionInfo,
|
|
|
|
frameIndex : this.piskelController.currentFrameIndex,
|
|
|
|
layerIndex : this.piskelController.currentLayerIndex
|
|
|
|
};
|
|
|
|
|
|
|
|
if (actionInfo.type === 'FULL' || this.currentIndex % SNAPSHOT_PERIOD === 0) {
|
|
|
|
state.piskel = this.piskelController.serialize(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.stateQueue.push(state);
|
2012-09-11 01:26:12 +04:00
|
|
|
};
|
2012-09-07 02:18:59 +04:00
|
|
|
|
2012-09-16 15:10:05 +04:00
|
|
|
ns.HistoryService.prototype.undo = function () {
|
2014-04-17 03:27:49 +04:00
|
|
|
var now = Date.now();
|
|
|
|
if ((Date.now() - this.lastEvent) > 50 && this.currentIndex > 0) {
|
|
|
|
this.currentIndex = this.currentIndex - 1;
|
|
|
|
this.loadState(this.currentIndex);
|
|
|
|
this.lastEvent = Date.now();
|
|
|
|
}
|
2012-09-11 01:26:12 +04:00
|
|
|
};
|
|
|
|
|
2012-09-16 15:10:05 +04:00
|
|
|
ns.HistoryService.prototype.redo = function () {
|
2014-04-17 03:27:49 +04:00
|
|
|
var now = Date.now();
|
|
|
|
if ((Date.now() - this.lastEvent) > 50 && this.currentIndex < this.stateQueue.length - 1) {
|
|
|
|
this.currentIndex = this.currentIndex + 1;
|
|
|
|
this.loadState(this.currentIndex);
|
|
|
|
this.lastEvent = Date.now();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
ns.HistoryService.prototype.loadState = function (index) {
|
|
|
|
// get nearest snaphot index
|
|
|
|
var snapshotIndex = -1;
|
|
|
|
for (var i = index ; i >= 0 ; i--) {
|
|
|
|
if (this.stateQueue[i].piskel) {
|
|
|
|
snapshotIndex = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (snapshotIndex === -1) {
|
|
|
|
throw 'Could not find previous SNAPSHOT saved in history stateQueue';
|
|
|
|
}
|
|
|
|
|
|
|
|
var serializedPiskel = this.stateQueue[snapshotIndex].piskel;
|
|
|
|
var targetState = this.stateQueue[index];
|
|
|
|
|
|
|
|
if (typeof serializedPiskel === "string") {
|
|
|
|
this.stateQueue[snapshotIndex].piskel = JSON.parse(serializedPiskel);
|
|
|
|
serializedPiskel = this.stateQueue[snapshotIndex].piskel;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.loadPiskel(serializedPiskel, this.onPiskelLoadedCallback.bind(this, index, snapshotIndex));
|
|
|
|
};
|
|
|
|
|
|
|
|
ns.HistoryService.prototype.onPiskelLoadedCallback = function (index, snapshotIndex, piskel) {
|
|
|
|
for (var i = snapshotIndex + 1 ; i <= index ; i++) {
|
|
|
|
var state = this.stateQueue[i];
|
2014-04-18 15:13:42 +04:00
|
|
|
this.setupState(state);
|
2014-04-17 03:27:49 +04:00
|
|
|
this.replayState(state);
|
|
|
|
}
|
|
|
|
|
2014-04-18 15:13:42 +04:00
|
|
|
var lastState = this.stateQueue[index];
|
|
|
|
this.setupState(lastState);
|
|
|
|
|
2013-09-29 02:01:18 +04:00
|
|
|
$.publish(Events.PISKEL_RESET);
|
2014-04-17 03:27:49 +04:00
|
|
|
};
|
|
|
|
|
2014-04-18 15:13:42 +04:00
|
|
|
ns.HistoryService.prototype.setupState = function (state) {
|
|
|
|
this.piskelController.setCurrentFrameIndex(state.frameIndex);
|
|
|
|
this.piskelController.setCurrentLayerIndex(state.layerIndex);
|
|
|
|
};
|
|
|
|
|
2014-04-17 03:27:49 +04:00
|
|
|
ns.HistoryService.prototype.loadPiskel = function (piskel, callback) {
|
|
|
|
var descriptor = this.piskelController.piskel.getDescriptor();
|
|
|
|
pskl.utils.serialization.Deserializer.deserialize(piskel, function (piskel) {
|
|
|
|
piskel.setDescriptor(descriptor);
|
2014-04-19 22:19:24 +04:00
|
|
|
this.piskelController.setPiskel(piskel);
|
2014-04-17 03:27:49 +04:00
|
|
|
callback(piskel);
|
2014-04-19 22:19:24 +04:00
|
|
|
}.bind(this));
|
2014-04-17 03:27:49 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
ns.HistoryService.prototype.replayState = function (state) {
|
|
|
|
var type = state.action.type;
|
|
|
|
if (type === 'DELETE_FRAME') {
|
|
|
|
this.piskelController.removeFrameAt(state.action.index);
|
|
|
|
} else if (type === 'ADD_FRAME') {
|
|
|
|
this.piskelController.addFrameAt(state.action.index);
|
|
|
|
} else if (type === 'DUPLICATE_FRAME') {
|
|
|
|
this.piskelController.duplicateFrameAt(state.action.index);
|
|
|
|
} else if (type === 'CREATE_LAYER') {
|
|
|
|
this.piskelController.createLayer(state.action.name);
|
|
|
|
} else if (type === 'REMOVE_LAYER') {
|
|
|
|
this.piskelController.removeCurrentLayer();
|
|
|
|
} else if (type === 'LAYER_UP') {
|
|
|
|
this.piskelController.moveLayerUp();
|
|
|
|
} else if (type === 'LAYER_DOWN') {
|
|
|
|
this.piskelController.moveLayerUp();
|
|
|
|
} else if (type === 'RENAME_LAYER') {
|
|
|
|
this.piskelController.renameLayerAt(state.action.index, state.action.name);
|
|
|
|
} else if (type === 'MOVE_FRAME') {
|
|
|
|
this.piskelController.moveFrame(state.action.from, state.action.to);
|
|
|
|
} else if (type === 'CREATE_LAYER') {
|
|
|
|
this.piskelController.createLayer();
|
|
|
|
} else if (type === 'TOOL') {
|
|
|
|
var action = state.action;
|
|
|
|
var layer = this.piskelController.getLayerAt(state.layerIndex);
|
|
|
|
var frame = layer.getFrameAt(state.frameIndex);
|
|
|
|
action.tool.replay(frame, action.replay);
|
|
|
|
}
|
2012-09-11 01:26:12 +04:00
|
|
|
};
|
|
|
|
|
2012-09-07 02:18:59 +04:00
|
|
|
})();
|