mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Merge pull request #168 from juliandescottes/feature-undo-redo
Feature undo redo
This commit is contained in:
commit
98aad13f1e
3
.gitignore
vendored
3
.gitignore
vendored
@ -16,6 +16,9 @@ npm-debug.log
|
|||||||
build/*.js
|
build/*.js
|
||||||
build/*.css
|
build/*.css
|
||||||
|
|
||||||
|
# diffs
|
||||||
|
diff.txt
|
||||||
|
|
||||||
# Closure compiler generated JS binary.
|
# Closure compiler generated JS binary.
|
||||||
build/closure/closure_compiled_binary.js
|
build/closure/closure_compiled_binary.js
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tool-rectangle-select .drawing-canvas-container:hover {
|
.tool-rectangle-select .drawing-canvas-container:hover {
|
||||||
cursor: url(../img/icons/select.png) 15 15, pointer;
|
cursor: crosshair;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tool-shape-select .drawing-canvas-container:hover {
|
.tool-shape-select .drawing-canvas-container:hover {
|
||||||
|
@ -32,6 +32,7 @@ var Events = {
|
|||||||
* Number of frames, content of frames, color used for the palette may have changed.
|
* Number of frames, content of frames, color used for the palette may have changed.
|
||||||
*/
|
*/
|
||||||
PISKEL_RESET: "PISKEL_RESET",
|
PISKEL_RESET: "PISKEL_RESET",
|
||||||
|
PISKEL_SAVE_STATE: "PISKEL_SAVE_STATE",
|
||||||
|
|
||||||
PISKEL_SAVED: "PISKEL_SAVED",
|
PISKEL_SAVED: "PISKEL_SAVED",
|
||||||
|
|
||||||
|
@ -30,7 +30,10 @@
|
|||||||
|
|
||||||
piskel.addLayer(layer);
|
piskel.addLayer(layer);
|
||||||
|
|
||||||
this.piskelController = new pskl.controller.PiskelController(piskel);
|
this.corePiskelController = new pskl.controller.piskel.PiskelController(piskel);
|
||||||
|
this.corePiskelController.init();
|
||||||
|
|
||||||
|
this.piskelController = new pskl.controller.piskel.PublicPiskelController(this.corePiskelController);
|
||||||
this.piskelController.init();
|
this.piskelController.init();
|
||||||
|
|
||||||
this.paletteController = new pskl.controller.PaletteController();
|
this.paletteController = new pskl.controller.PaletteController();
|
||||||
@ -69,7 +72,7 @@
|
|||||||
this.selectionManager = new pskl.selection.SelectionManager(this.piskelController);
|
this.selectionManager = new pskl.selection.SelectionManager(this.piskelController);
|
||||||
this.selectionManager.init();
|
this.selectionManager.init();
|
||||||
|
|
||||||
this.historyService = new pskl.service.HistoryService(this.piskelController);
|
this.historyService = new pskl.service.HistoryService(this.corePiskelController);
|
||||||
this.historyService.init();
|
this.historyService.init();
|
||||||
|
|
||||||
this.notificationController = new pskl.controller.NotificationController();
|
this.notificationController = new pskl.controller.NotificationController();
|
||||||
|
@ -157,8 +157,8 @@
|
|||||||
// Warning : do not call setCurrentButton here
|
// Warning : do not call setCurrentButton here
|
||||||
// mousemove do not have the correct mouse button information on all browsers
|
// mousemove do not have the correct mouse button information on all browsers
|
||||||
this.currentToolBehavior.moveToolAt(
|
this.currentToolBehavior.moveToolAt(
|
||||||
coords.x,
|
coords.x | 0,
|
||||||
coords.y,
|
coords.y | 0,
|
||||||
this.getCurrentColor_(event),
|
this.getCurrentColor_(event),
|
||||||
currentFrame,
|
currentFrame,
|
||||||
this.overlayFrame,
|
this.overlayFrame,
|
||||||
@ -175,6 +175,7 @@
|
|||||||
event
|
event
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
$.publish(Events.CURSOR_MOVED, [coords.x, coords.y]);
|
||||||
this.previousMousemoveTime = currentTime;
|
this.previousMousemoveTime = currentTime;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -44,15 +44,15 @@
|
|||||||
this.piskelController.setCurrentLayerIndex(parseInt(index, 10));
|
this.piskelController.setCurrentLayerIndex(parseInt(index, 10));
|
||||||
} else if (el.classList.contains('edit-icon')) {
|
} else if (el.classList.contains('edit-icon')) {
|
||||||
index = el.parentNode.dataset.layerIndex;
|
index = el.parentNode.dataset.layerIndex;
|
||||||
var layer = this.piskelController.getLayerByIndex(parseInt(index, 10));
|
this.renameLayerAt_(index);
|
||||||
this.renameLayer_(layer);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.LayersListController.prototype.renameLayer_ = function (layer) {
|
ns.LayersListController.prototype.renameLayerAt_ = function (index) {
|
||||||
var newName = window.prompt("Please enter the layer name", layer.getName());
|
var layer = this.piskelController.getLayerAt(index);
|
||||||
if (newName) {
|
var name = window.prompt("Please enter the layer name", layer.getName());
|
||||||
layer.setName(newName);
|
if (name) {
|
||||||
|
this.piskelController.renameLayerAt(index, name);
|
||||||
this.renderLayerList_();
|
this.renderLayerList_();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
(function () {
|
(function () {
|
||||||
var ns = $.namespace('pskl.controller');
|
var ns = $.namespace('pskl.controller.piskel');
|
||||||
|
|
||||||
ns.PiskelController = function (piskel) {
|
ns.PiskelController = function (piskel) {
|
||||||
if (piskel) {
|
if (piskel) {
|
||||||
@ -15,16 +15,9 @@
|
|||||||
this.currentFrameIndex = 0;
|
this.currentFrameIndex = 0;
|
||||||
|
|
||||||
this.layerIdCounter = 1;
|
this.layerIdCounter = 1;
|
||||||
|
|
||||||
$.publish(Events.FRAME_SIZE_CHANGED);
|
|
||||||
$.publish(Events.PISKEL_RESET);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PiskelController.prototype.init = function () {
|
ns.PiskelController.prototype.init = function () {
|
||||||
pskl.app.shortcutService.addShortcut('up', this.selectPreviousFrame.bind(this));
|
|
||||||
pskl.app.shortcutService.addShortcut('down', this.selectNextFrame.bind(this));
|
|
||||||
pskl.app.shortcutService.addShortcut('n', this.addFrameAtCurrentIndex.bind(this));
|
|
||||||
pskl.app.shortcutService.addShortcut('shift+n', this.duplicateCurrentFrame.bind(this));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PiskelController.prototype.getHeight = function () {
|
ns.PiskelController.prototype.getHeight = function () {
|
||||||
@ -51,7 +44,11 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ns.PiskelController.prototype.getCurrentLayer = function () {
|
ns.PiskelController.prototype.getCurrentLayer = function () {
|
||||||
return this.piskel.getLayerAt(this.currentLayerIndex);
|
return this.getLayerAt(this.currentLayerIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PiskelController.prototype.getLayerAt = function (index) {
|
||||||
|
return this.piskel.getLayerAt(index);
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PiskelController.prototype.getCurrentFrame = function () {
|
ns.PiskelController.prototype.getCurrentFrame = function () {
|
||||||
@ -59,6 +56,19 @@
|
|||||||
return layer.getFrameAt(this.currentFrameIndex);
|
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.getFrameAt = function (index) {
|
ns.PiskelController.prototype.getFrameAt = function (index) {
|
||||||
var frames = this.getLayers().map(function (l) {
|
var frames = this.getLayers().map(function (l) {
|
||||||
return l.getFrameAt(index);
|
return l.getFrameAt(index);
|
||||||
@ -79,12 +89,9 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ns.PiskelController.prototype.addFrameAt = function (index) {
|
ns.PiskelController.prototype.addFrameAt = function (index) {
|
||||||
var layers = this.getLayers();
|
this.getLayers().forEach(function (l) {
|
||||||
layers.forEach(function (l) {
|
|
||||||
l.addFrameAt(this.createEmptyFrame_(), index);
|
l.addFrameAt(this.createEmptyFrame_(), index);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
$.publish(Events.PISKEL_RESET);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PiskelController.prototype.createEmptyFrame_ = function () {
|
ns.PiskelController.prototype.createEmptyFrame_ = function () {
|
||||||
@ -93,16 +100,13 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ns.PiskelController.prototype.removeFrameAt = function (index) {
|
ns.PiskelController.prototype.removeFrameAt = function (index) {
|
||||||
var layers = this.getLayers();
|
this.getLayers().forEach(function (l) {
|
||||||
layers.forEach(function (l) {
|
|
||||||
l.removeFrameAt(index);
|
l.removeFrameAt(index);
|
||||||
});
|
});
|
||||||
// Current frame index is impacted if the removed frame was before the current frame
|
// Current frame index is impacted if the removed frame was before the current frame
|
||||||
if (this.currentFrameIndex >= index && this.currentFrameIndex > 0) {
|
if (this.currentFrameIndex >= index && this.currentFrameIndex > 0) {
|
||||||
this.setCurrentFrameIndex(this.currentFrameIndex - 1);
|
this.setCurrentFrameIndex(this.currentFrameIndex - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$.publish(Events.PISKEL_RESET);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PiskelController.prototype.duplicateCurrentFrame = function () {
|
ns.PiskelController.prototype.duplicateCurrentFrame = function () {
|
||||||
@ -110,17 +114,13 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ns.PiskelController.prototype.duplicateFrameAt = function (index) {
|
ns.PiskelController.prototype.duplicateFrameAt = function (index) {
|
||||||
var layers = this.getLayers();
|
this.getLayers().forEach(function (l) {
|
||||||
layers.forEach(function (l) {
|
|
||||||
l.duplicateFrameAt(index);
|
l.duplicateFrameAt(index);
|
||||||
});
|
});
|
||||||
|
|
||||||
$.publish(Events.PISKEL_RESET);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PiskelController.prototype.moveFrame = function (fromIndex, toIndex) {
|
ns.PiskelController.prototype.moveFrame = function (fromIndex, toIndex) {
|
||||||
var layers = this.getLayers();
|
this.getLayers().forEach(function (l) {
|
||||||
layers.forEach(function (l) {
|
|
||||||
l.moveFrame(fromIndex, toIndex);
|
l.moveFrame(fromIndex, toIndex);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -132,7 +132,6 @@
|
|||||||
|
|
||||||
ns.PiskelController.prototype.setCurrentFrameIndex = function (index) {
|
ns.PiskelController.prototype.setCurrentFrameIndex = function (index) {
|
||||||
this.currentFrameIndex = index;
|
this.currentFrameIndex = index;
|
||||||
$.publish(Events.PISKEL_RESET);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PiskelController.prototype.selectNextFrame = function () {
|
ns.PiskelController.prototype.selectNextFrame = function () {
|
||||||
@ -151,7 +150,6 @@
|
|||||||
|
|
||||||
ns.PiskelController.prototype.setCurrentLayerIndex = function (index) {
|
ns.PiskelController.prototype.setCurrentLayerIndex = function (index) {
|
||||||
this.currentLayerIndex = index;
|
this.currentLayerIndex = index;
|
||||||
$.publish(Events.PISKEL_RESET);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PiskelController.prototype.selectLayer = function (layer) {
|
ns.PiskelController.prototype.selectLayer = function (layer) {
|
||||||
@ -161,6 +159,13 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ns.PiskelController.prototype.renameLayerAt = function (index, name) {
|
||||||
|
var layer = this.getLayerByIndex(index);
|
||||||
|
if (layer) {
|
||||||
|
layer.setName(name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ns.PiskelController.prototype.getLayerByIndex = function (index) {
|
ns.PiskelController.prototype.getLayerByIndex = function (index) {
|
||||||
var layers = this.getLayers();
|
var layers = this.getLayers();
|
||||||
if (layers[index]) {
|
if (layers[index]) {
|
||||||
@ -190,6 +195,7 @@
|
|||||||
}
|
}
|
||||||
this.piskel.addLayer(layer);
|
this.piskel.addLayer(layer);
|
||||||
this.setCurrentLayerIndex(this.piskel.getLayers().length - 1);
|
this.setCurrentLayerIndex(this.piskel.getLayers().length - 1);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw 'Layer name should be unique';
|
throw 'Layer name should be unique';
|
||||||
}
|
}
|
||||||
@ -219,11 +225,7 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PiskelController.prototype.serialize = function () {
|
ns.PiskelController.prototype.serialize = function (expanded) {
|
||||||
return pskl.utils.Serializer.serializePiskel(this.piskel);
|
return pskl.utils.Serializer.serializePiskel(this.piskel, expanded);
|
||||||
};
|
|
||||||
|
|
||||||
ns.PiskelController.prototype.load = function (data) {
|
|
||||||
this.deserialize(JSON.stringify(data));
|
|
||||||
};
|
};
|
||||||
})();
|
})();
|
143
src/js/controller/piskel/PublicPiskelController.js
Normal file
143
src/js/controller/piskel/PublicPiskelController.js
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
(function () {
|
||||||
|
var ns = $.namespace('pskl.controller.piskel');
|
||||||
|
|
||||||
|
ns.PublicPiskelController = function (piskelController) {
|
||||||
|
this.piskelController = piskelController;
|
||||||
|
pskl.utils.wrap(this, this.piskelController);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.init = function () {
|
||||||
|
pskl.app.shortcutService.addShortcut('up', this.selectPreviousFrame.bind(this));
|
||||||
|
pskl.app.shortcutService.addShortcut('down', this.selectNextFrame.bind(this));
|
||||||
|
pskl.app.shortcutService.addShortcut('n', this.addFrameAtCurrentIndex.bind(this));
|
||||||
|
pskl.app.shortcutService.addShortcut('shift+n', this.duplicateCurrentFrame.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.setPiskel = function (piskel) {
|
||||||
|
this.piskelController.setPiskel(piskel);
|
||||||
|
|
||||||
|
$.publish(Events.FRAME_SIZE_CHANGED);
|
||||||
|
$.publish(Events.PISKEL_RESET);
|
||||||
|
$.publish(Events.PISKEL_SAVE_STATE, {
|
||||||
|
type : pskl.service.HistoryService.SNAPSHOT
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.addFrame = function () {
|
||||||
|
this.addFrameAt(this.getFrameCount());
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.addFrameAtCurrentIndex = function () {
|
||||||
|
this.addFrameAt(this.getCurrentFrameIndex());
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.addFrameAt = function (index) {
|
||||||
|
this.raiseSaveStateEvent_(this.piskelController.addFrameAt, [index]);
|
||||||
|
this.piskelController.addFrameAt(index);
|
||||||
|
$.publish(Events.PISKEL_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.removeFrameAt = function (index) {
|
||||||
|
this.raiseSaveStateEvent_(this.piskelController.removeFrameAt, [index]);
|
||||||
|
this.piskelController.removeFrameAt(index);
|
||||||
|
$.publish(Events.PISKEL_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.duplicateCurrentFrame = function () {
|
||||||
|
this.piskelController.duplicateFrameAt(this.getCurrentFrameIndex());
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.raiseSaveStateEvent_ = function (fn, args) {
|
||||||
|
$.publish(Events.PISKEL_SAVE_STATE, {
|
||||||
|
type : pskl.service.HistoryService.REPLAY,
|
||||||
|
scope : this,
|
||||||
|
replay : {
|
||||||
|
fn : fn,
|
||||||
|
args : args
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.replay = function (frame, replayData) {
|
||||||
|
replayData.fn.apply(this.piskelController, replayData.args);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.duplicateFrameAt = function (index) {
|
||||||
|
this.raiseSaveStateEvent_(this.piskelController.duplicateFrameAt, [index]);
|
||||||
|
this.piskelController.duplicateFrameAt(index);
|
||||||
|
$.publish(Events.PISKEL_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.moveFrame = function (fromIndex, toIndex) {
|
||||||
|
this.raiseSaveStateEvent_(this.piskelController.moveFrame, [fromIndex, toIndex]);
|
||||||
|
this.piskelController.moveFrame(fromIndex, toIndex);
|
||||||
|
$.publish(Events.PISKEL_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.setCurrentFrameIndex = function (index) {
|
||||||
|
this.piskelController.setCurrentFrameIndex(index);
|
||||||
|
$.publish(Events.PISKEL_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.selectNextFrame = function () {
|
||||||
|
this.piskelController.selectNextFrame();
|
||||||
|
$.publish(Events.PISKEL_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.selectPreviousFrame = function () {
|
||||||
|
this.piskelController.selectPreviousFrame();
|
||||||
|
$.publish(Events.PISKEL_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.setCurrentLayerIndex = function (index) {
|
||||||
|
this.piskelController.setCurrentLayerIndex(index);
|
||||||
|
$.publish(Events.PISKEL_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.selectLayer = function (layer) {
|
||||||
|
this.piskelController.selectLayer(layer);
|
||||||
|
$.publish(Events.PISKEL_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.renameLayerAt = function (index, name) {
|
||||||
|
this.raiseSaveStateEvent_(this.piskelController.renameLayerAt, [index, name]);
|
||||||
|
this.piskelController.renameLayerAt(index, name);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.createLayer = function (name) {
|
||||||
|
this.raiseSaveStateEvent_(this.piskelController.createLayer, [name]);
|
||||||
|
this.piskelController.createLayer(name);
|
||||||
|
$.publish(Events.PISKEL_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.moveLayerUp = function () {
|
||||||
|
this.raiseSaveStateEvent_(this.piskelController.moveLayerUp, []);
|
||||||
|
this.piskelController.moveLayerUp();
|
||||||
|
$.publish(Events.PISKEL_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.moveLayerDown = function () {
|
||||||
|
this.raiseSaveStateEvent_(this.piskelController.moveLayerDown, []);
|
||||||
|
this.piskelController.moveLayerDown();
|
||||||
|
$.publish(Events.PISKEL_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.removeCurrentLayer = function () {
|
||||||
|
this.raiseSaveStateEvent_(this.piskelController.removeCurrentLayer, []);
|
||||||
|
this.piskelController.removeCurrentLayer();
|
||||||
|
$.publish(Events.PISKEL_RESET);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.getCurrentLayerIndex = function () {
|
||||||
|
return this.piskelController.currentLayerIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.getCurrentFrameIndex = function () {
|
||||||
|
return this.piskelController.currentFrameIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PublicPiskelController.prototype.getPiskel = function () {
|
||||||
|
return this.piskelController.piskel;
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
@ -56,7 +56,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ns.PngExportController.prototype.getPiskelName_ = function () {
|
ns.PngExportController.prototype.getPiskelName_ = function () {
|
||||||
return this.piskelController.piskel.getDescriptor().name;
|
return this.piskelController.getPiskel().getDescriptor().name;
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.PngExportController.prototype.getFramesheetAsBase64Png = function () {
|
ns.PngExportController.prototype.getFramesheetAsBase64Png = function () {
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
layers.push(layer);
|
layers.push(layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
var piskel = pskl.model.Piskel.fromLayers(layers, this.piskelController.piskel.getDescriptor());
|
var piskel = pskl.model.Piskel.fromLayers(layers, this.piskelController.getPiskel().getDescriptor());
|
||||||
pskl.app.piskelController.setPiskel(piskel);
|
pskl.app.piskelController.setPiskel(piskel);
|
||||||
$.publish(Events.CLOSE_SETTINGS_DRAWER);
|
$.publish(Events.CLOSE_SETTINGS_DRAWER);
|
||||||
};
|
};
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
this.status = $('#save-status');
|
this.status = $('#save-status');
|
||||||
|
|
||||||
var descriptor = this.piskelController.piskel.getDescriptor();
|
var descriptor = this.piskelController.getPiskel().getDescriptor();
|
||||||
this.nameInput.val(descriptor.name);
|
this.nameInput.val(descriptor.name);
|
||||||
this.descriptionInput.val(descriptor.description);
|
this.descriptionInput.val(descriptor.description);
|
||||||
|
|
||||||
@ -46,7 +46,7 @@
|
|||||||
var isPublic = !!this.isPublicCheckbox.prop('checked');
|
var isPublic = !!this.isPublicCheckbox.prop('checked');
|
||||||
|
|
||||||
var descriptor = new pskl.model.piskel.Descriptor(name, description, isPublic);
|
var descriptor = new pskl.model.piskel.Descriptor(name, description, isPublic);
|
||||||
this.piskelController.piskel.setDescriptor(descriptor);
|
this.piskelController.getPiskel().setDescriptor(descriptor);
|
||||||
|
|
||||||
this.beforeSaving_();
|
this.beforeSaving_();
|
||||||
pskl.app.store({
|
pskl.app.store({
|
||||||
|
@ -6,16 +6,17 @@
|
|||||||
(function() {
|
(function() {
|
||||||
var ns = $.namespace("pskl.drawingtools");
|
var ns = $.namespace("pskl.drawingtools");
|
||||||
|
|
||||||
ns.BaseTool = function() {};
|
ns.BaseTool = function() {
|
||||||
|
this.toolId = "tool-base";
|
||||||
|
};
|
||||||
|
|
||||||
ns.BaseTool.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {};
|
ns.BaseTool.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {};
|
||||||
|
|
||||||
ns.BaseTool.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {
|
ns.BaseTool.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {};
|
||||||
$.publish(Events.CURSOR_MOVED, [col, row]);
|
|
||||||
};
|
ns.BaseTool.prototype.replay = Constants.ABSTRACT_FUNCTION;
|
||||||
|
|
||||||
ns.BaseTool.prototype.moveUnactiveToolAt = function(col, row, color, frame, overlay, event) {
|
ns.BaseTool.prototype.moveUnactiveToolAt = function(col, row, color, frame, overlay, event) {
|
||||||
$.publish(Events.CURSOR_MOVED, [col, row]);
|
|
||||||
|
|
||||||
if (overlay.containsPixel(col, row)) {
|
if (overlay.containsPixel(col, row)) {
|
||||||
if (!isNaN(this.highlightedPixelCol) &&
|
if (!isNaN(this.highlightedPixelCol) &&
|
||||||
@ -49,6 +50,14 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ns.BaseTool.prototype.raiseSaveStateEvent = function (replayData) {
|
||||||
|
$.publish(Events.PISKEL_SAVE_STATE, {
|
||||||
|
type : pskl.service.HistoryService.REPLAY,
|
||||||
|
scope : this,
|
||||||
|
replay : replayData
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
ns.BaseTool.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) {};
|
ns.BaseTool.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) {};
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
var ns = $.namespace("pskl.drawingtools");
|
var ns = $.namespace("pskl.drawingtools");
|
||||||
|
|
||||||
ns.Eraser = function() {
|
ns.Eraser = function() {
|
||||||
|
this.superclass.constructor.call(this);
|
||||||
this.toolId = "tool-eraser";
|
this.toolId = "tool-eraser";
|
||||||
this.helpText = "Eraser tool";
|
this.helpText = "Eraser tool";
|
||||||
};
|
};
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ns.Move.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {
|
ns.Move.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {
|
||||||
$.publish(Events.CURSOR_MOVED, [col, row]);
|
|
||||||
var colDiff = col - this.startCol, rowDiff = row - this.startRow;
|
var colDiff = col - this.startCol, rowDiff = row - this.startRow;
|
||||||
this.shiftFrame(colDiff, rowDiff, frame, this.frameClone);
|
this.shiftFrame(colDiff, rowDiff, frame, this.frameClone);
|
||||||
};
|
};
|
||||||
@ -53,5 +52,14 @@
|
|||||||
*/
|
*/
|
||||||
ns.Move.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) {
|
ns.Move.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) {
|
||||||
this.moveToolAt(col, row, color, frame, overlay);
|
this.moveToolAt(col, row, color, frame, overlay);
|
||||||
|
|
||||||
|
this.raiseSaveStateEvent({
|
||||||
|
colDiff : col - this.startCol,
|
||||||
|
rowDiff : row - this.startRow
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.Move.prototype.replay = function(frame, replayData) {
|
||||||
|
this.shiftFrame(replayData.colDiff, replayData.rowDiff, frame, frame.clone());
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
@ -17,8 +17,17 @@
|
|||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
ns.PaintBucket.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
|
ns.PaintBucket.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
|
||||||
|
|
||||||
pskl.PixelUtils.paintSimilarConnectedPixelsFromFrame(frame, col, row, color);
|
pskl.PixelUtils.paintSimilarConnectedPixelsFromFrame(frame, col, row, color);
|
||||||
|
|
||||||
|
this.raiseSaveStateEvent({
|
||||||
|
col : col,
|
||||||
|
row : row,
|
||||||
|
color : color
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.PaintBucket.prototype.replay = function (frame, replayData) {
|
||||||
|
pskl.PixelUtils.paintSimilarConnectedPixelsFromFrame(frame, replayData.col, replayData.row, replayData.color);
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
@ -49,7 +49,24 @@
|
|||||||
}
|
}
|
||||||
var coords = this.getCoordinates_(col, row, event);
|
var coords = this.getCoordinates_(col, row, event);
|
||||||
this.draw_(coords.col, coords.row, color, frame);
|
this.draw_(coords.col, coords.row, color, frame);
|
||||||
|
|
||||||
$.publish(Events.DRAG_END, [col, row]);
|
$.publish(Events.DRAG_END, [col, row]);
|
||||||
|
this.raiseSaveStateEvent({
|
||||||
|
col : col,
|
||||||
|
row : row,
|
||||||
|
startCol : this.startCol,
|
||||||
|
startRow : this.startRow,
|
||||||
|
color : color
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
ns.ShapeTool.prototype.replay = function(frame, replayData) {
|
||||||
|
this.startCol = replayData.startCol;
|
||||||
|
this.startRow = replayData.startRow;
|
||||||
|
this.draw_(replayData.col, replayData.row, replayData.color, frame);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
this.previousCol = null;
|
this.previousCol = null;
|
||||||
this.previousRow = null;
|
this.previousRow = null;
|
||||||
|
|
||||||
|
this.pixels = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
pskl.utils.inherit(ns.SimplePen, ns.BaseTool);
|
pskl.utils.inherit(ns.SimplePen, ns.BaseTool);
|
||||||
@ -21,18 +22,19 @@
|
|||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
ns.SimplePen.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
|
ns.SimplePen.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
|
||||||
if (frame.containsPixel(col, row)) {
|
frame.setPixel(col, row, color);
|
||||||
frame.setPixel(col, row, color);
|
|
||||||
}
|
|
||||||
this.previousCol = col;
|
this.previousCol = col;
|
||||||
this.previousRow = row;
|
this.previousRow = row;
|
||||||
|
this.pixels.push({
|
||||||
|
col : col,
|
||||||
|
row : row
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
ns.SimplePen.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {
|
ns.SimplePen.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {
|
||||||
$.publish(Events.CURSOR_MOVED, [col, row]);
|
|
||||||
if((Math.abs(col - this.previousCol) > 1) || (Math.abs(row - this.previousRow) > 1)) {
|
if((Math.abs(col - this.previousCol) > 1) || (Math.abs(row - this.previousRow) > 1)) {
|
||||||
// The pen movement is too fast for the mousemove frequency, there is a gap between the
|
// The pen movement is too fast for the mousemove frequency, there is a gap between the
|
||||||
// current point and the previously drawn one.
|
// current point and the previously drawn one.
|
||||||
@ -40,7 +42,7 @@
|
|||||||
var interpolatedPixels = this.getLinePixels_(col, this.previousCol, row, this.previousRow);
|
var interpolatedPixels = this.getLinePixels_(col, this.previousCol, row, this.previousRow);
|
||||||
for(var i=0, l=interpolatedPixels.length; i<l; i++) {
|
for(var i=0, l=interpolatedPixels.length; i<l; i++) {
|
||||||
var coords = interpolatedPixels[i];
|
var coords = interpolatedPixels[i];
|
||||||
this.applyToolAt(coords.col, coords.row, color, frame, overlay);
|
this.applyToolAt(coords.col, coords.row, color, frame, overlay, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -50,4 +52,20 @@
|
|||||||
this.previousCol = col;
|
this.previousCol = col;
|
||||||
this.previousRow = row;
|
this.previousRow = row;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ns.SimplePen.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) {
|
||||||
|
this.raiseSaveStateEvent({
|
||||||
|
pixels : this.pixels.slice(0),
|
||||||
|
color : color
|
||||||
|
});
|
||||||
|
this.pixels = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.SimplePen.prototype.replay = function (frame, replayData) {
|
||||||
|
var pixels = replayData.pixels;
|
||||||
|
pixels.forEach(function (pixel) {
|
||||||
|
frame.setPixel(pixel.col, pixel.row, replayData.color);
|
||||||
|
});
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
@ -37,8 +37,6 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ns.Stroke.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {
|
ns.Stroke.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {
|
||||||
$.publish(Events.CURSOR_MOVED, [col, row]);
|
|
||||||
|
|
||||||
overlay.clear();
|
overlay.clear();
|
||||||
|
|
||||||
// When the user moussemove (before releasing), we dynamically compute the
|
// When the user moussemove (before releasing), we dynamically compute the
|
||||||
@ -65,18 +63,25 @@
|
|||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
ns.Stroke.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) {
|
ns.Stroke.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) {
|
||||||
// If the stroke tool is released outside of the canvas, we cancel the stroke:
|
// The user released the tool to draw a line. We will compute the pixel coordinate, impact
|
||||||
// TODO: Mutualize this check in common method
|
// the model and draw them in the drawing canvas (not the fake overlay anymore)
|
||||||
if(frame.containsPixel(col, row)) {
|
var strokePoints = this.getLinePixels_(this.startCol, col, this.startRow, row);
|
||||||
// The user released the tool to draw a line. We will compute the pixel coordinate, impact
|
for(var i = 0; i< strokePoints.length; i++) {
|
||||||
// the model and draw them in the drawing canvas (not the fake overlay anymore)
|
// Change model:
|
||||||
var strokePoints = this.getLinePixels_(this.startCol, col, this.startRow, row);
|
frame.setPixel(strokePoints[i].col, strokePoints[i].row, color);
|
||||||
for(var i = 0; i< strokePoints.length; i++) {
|
|
||||||
// Change model:
|
|
||||||
frame.setPixel(strokePoints[i].col, strokePoints[i].row, color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// For now, we are done with the stroke tool and don't need an overlay anymore:
|
// For now, we are done with the stroke tool and don't need an overlay anymore:
|
||||||
overlay.clear();
|
overlay.clear();
|
||||||
|
|
||||||
|
this.raiseSaveStateEvent({
|
||||||
|
pixels : strokePoints,
|
||||||
|
color : color
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.Stroke.prototype.replay = function(frame, replayData) {
|
||||||
|
replayData.pixels.forEach(function (pixel) {
|
||||||
|
frame.setPixel(pixel.col, pixel.row, replayData.color);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
var ns = $.namespace("pskl.drawingtools");
|
var ns = $.namespace("pskl.drawingtools");
|
||||||
|
|
||||||
ns.VerticalMirrorPen = function() {
|
ns.VerticalMirrorPen = function() {
|
||||||
|
this.superclass.constructor.call(this);
|
||||||
|
|
||||||
this.toolId = "tool-vertical-mirror-pen";
|
this.toolId = "tool-vertical-mirror-pen";
|
||||||
this.helpText = "vertical mirror pen tool";
|
this.helpText = "vertical mirror pen tool";
|
||||||
|
|
||||||
this.swap = null;
|
this.swap = null;
|
||||||
this.mirroredPreviousCol = null;
|
|
||||||
this.mirroredPreviousRow = null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pskl.utils.inherit(ns.VerticalMirrorPen, ns.SimplePen);
|
pskl.utils.inherit(ns.VerticalMirrorPen, ns.SimplePen);
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
// Select's first point coordinates (set in applyToolAt)
|
// Select's first point coordinates (set in applyToolAt)
|
||||||
this.startCol = null;
|
this.startCol = null;
|
||||||
this.startRow = null;
|
this.startRow = null;
|
||||||
|
|
||||||
|
this.selection = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
pskl.utils.inherit(ns.BaseSelect, ns.BaseTool);
|
pskl.utils.inherit(ns.BaseSelect, ns.BaseTool);
|
||||||
@ -48,11 +50,9 @@
|
|||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
ns.BaseSelect.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {
|
ns.BaseSelect.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {
|
||||||
$.publish(Events.CURSOR_MOVED, [col, row]);
|
|
||||||
if(this.mode == "select") {
|
if(this.mode == "select") {
|
||||||
this.onSelect_(col, row, color, frame, overlay);
|
this.onSelect_(col, row, color, frame, overlay);
|
||||||
}
|
} else if(this.mode == "moveSelection") {
|
||||||
else if(this.mode == "moveSelection") {
|
|
||||||
this.onSelectionDrag_(col, row, color, frame, overlay);
|
this.onSelectionDrag_(col, row, color, frame, overlay);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -75,7 +75,6 @@
|
|||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
ns.BaseSelect.prototype.moveUnactiveToolAt = function(col, row, color, frame, overlay, event) {
|
ns.BaseSelect.prototype.moveUnactiveToolAt = function(col, row, color, frame, overlay, event) {
|
||||||
$.publish(Events.CURSOR_MOVED, [col, row]);
|
|
||||||
if (overlay.containsPixel(col, row)) {
|
if (overlay.containsPixel(col, row)) {
|
||||||
if(overlay.getPixel(col, row) != Constants.SELECTION_TRANSPARENT_COLOR) {
|
if(overlay.getPixel(col, row) != Constants.SELECTION_TRANSPARENT_COLOR) {
|
||||||
// We're hovering the selection, show the move tool:
|
// We're hovering the selection, show the move tool:
|
||||||
@ -97,31 +96,13 @@
|
|||||||
* For each pixel in the selection draw it in white transparent on the tool overlay
|
* For each pixel in the selection draw it in white transparent on the tool overlay
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
ns.BaseSelect.prototype.drawSelectionOnOverlay_ = function (selection, overlay) {
|
ns.BaseSelect.prototype.drawSelectionOnOverlay_ = function (overlay) {
|
||||||
var pixels = selection.pixels;
|
var pixels = this.selection.pixels;
|
||||||
for(var i=0, l=pixels.length; i<l; i++) {
|
for(var i=0, l=pixels.length; i<l; i++) {
|
||||||
overlay.setPixel(pixels[i].col, pixels[i].row, Constants.SELECTION_TRANSPARENT_COLOR);
|
overlay.setPixel(pixels[i].col, pixels[i].row, Constants.SELECTION_TRANSPARENT_COLOR);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Move the overlay frame filled with semi-transparent pixels that represent the selection.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ns.BaseSelect.prototype.shiftOverlayFrame_ = function (colDiff, rowDiff, overlayFrame, reference) {
|
|
||||||
var color;
|
|
||||||
for (var col = 0 ; col < overlayFrame.getWidth() ; col++) {
|
|
||||||
for (var row = 0 ; row < overlayFrame.getHeight() ; row++) {
|
|
||||||
if (reference.containsPixel(col - colDiff, row - rowDiff)) {
|
|
||||||
color = reference.getPixel(col - colDiff, row - rowDiff);
|
|
||||||
} else {
|
|
||||||
color = Constants.TRANSPARENT_COLOR;
|
|
||||||
}
|
|
||||||
overlayFrame.setPixel(col, row, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// The list of callbacks to implement by specialized tools to implement the selection creation behavior.
|
// The list of callbacks to implement by specialized tools to implement the selection creation behavior.
|
||||||
/** @protected */
|
/** @protected */
|
||||||
@ -135,9 +116,6 @@
|
|||||||
// The list of callbacks that define the drag'n drop behavior of the selection.
|
// The list of callbacks that define the drag'n drop behavior of the selection.
|
||||||
/** @private */
|
/** @private */
|
||||||
ns.BaseSelect.prototype.onSelectionDragStart_ = function (col, row, color, frame, overlay) {
|
ns.BaseSelect.prototype.onSelectionDragStart_ = function (col, row, color, frame, overlay) {
|
||||||
// Since we will move the overlayFrame in which the current selection is rendered,
|
|
||||||
// we clone it to have a reference for the later shifting process.
|
|
||||||
this.overlayFrameReference = overlay.clone();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @private */
|
/** @private */
|
||||||
@ -147,11 +125,10 @@
|
|||||||
|
|
||||||
var colDiff = col - this.startCol, rowDiff = row - this.startRow;
|
var colDiff = col - this.startCol, rowDiff = row - this.startRow;
|
||||||
|
|
||||||
// Shifting selection on overlay frame:
|
this.selection.move(deltaCol, deltaRow);
|
||||||
this.shiftOverlayFrame_(colDiff, rowDiff, overlay, this.overlayFrameReference);
|
|
||||||
|
|
||||||
// Update selection model:
|
overlay.clear();
|
||||||
$.publish(Events.SELECTION_MOVE_REQUEST, [deltaCol, deltaRow]);
|
this.drawSelectionOnOverlay_(overlay);
|
||||||
|
|
||||||
this.lastCol = col;
|
this.lastCol = col;
|
||||||
this.lastRow = row;
|
this.lastRow = row;
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
this.helpText = "Rectangle selection tool";
|
this.helpText = "Rectangle selection tool";
|
||||||
|
|
||||||
ns.BaseSelect.call(this);
|
ns.BaseSelect.call(this);
|
||||||
|
this.hasSelection = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
pskl.utils.inherit(ns.RectangleSelect, ns.BaseSelect);
|
pskl.utils.inherit(ns.RectangleSelect, ns.BaseSelect);
|
||||||
@ -20,9 +21,16 @@
|
|||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
ns.RectangleSelect.prototype.onSelectStart_ = function (col, row, color, frame, overlay) {
|
ns.RectangleSelect.prototype.onSelectStart_ = function (col, row, color, frame, overlay) {
|
||||||
$.publish(Events.DRAG_START, [col, row]);
|
if (this.hasSelection) {
|
||||||
// Drawing the first point of the rectangle in the fake overlay canvas:
|
this.hasSelection = false;
|
||||||
overlay.setPixel(col, row, color);
|
overlay.clear();
|
||||||
|
$.publish(Events.SELECTION_DISMISSED);
|
||||||
|
} else {
|
||||||
|
this.hasSelection = true;
|
||||||
|
$.publish(Events.DRAG_START, [col, row]);
|
||||||
|
// Drawing the first point of the rectangle in the fake overlay canvas:
|
||||||
|
overlay.setPixel(col, row, color);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,23 +40,20 @@
|
|||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
ns.RectangleSelect.prototype.onSelect_ = function (col, row, color, frame, overlay) {
|
ns.RectangleSelect.prototype.onSelect_ = function (col, row, color, frame, overlay) {
|
||||||
overlay.clear();
|
if (this.hasSelection) {
|
||||||
if(this.startCol == col &&this.startRow == row) {
|
overlay.clear();
|
||||||
$.publish(Events.SELECTION_DISMISSED);
|
this.selection = new pskl.selection.RectangularSelection(
|
||||||
} else {
|
|
||||||
var selection = new pskl.selection.RectangularSelection(
|
|
||||||
this.startCol, this.startRow, col, row);
|
this.startCol, this.startRow, col, row);
|
||||||
$.publish(Events.SELECTION_CREATED, [selection]);
|
$.publish(Events.SELECTION_CREATED, [this.selection]);
|
||||||
this.drawSelectionOnOverlay_(selection, overlay);
|
this.drawSelectionOnOverlay_(overlay);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
ns.RectangleSelect.prototype.onSelectEnd_ = function (col, row, color, frame, overlay) {
|
ns.RectangleSelect.prototype.onSelectEnd_ = function (col, row, color, frame, overlay) {
|
||||||
this.onSelect_(col, row, color, frame, overlay);
|
if (this.hasSelection) {
|
||||||
$.publish(Events.DRAG_END, [col, row]);
|
this.onSelect_(col, row, color, frame, overlay);
|
||||||
|
$.publish(Events.DRAG_END, [col, row]);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -9,12 +9,12 @@
|
|||||||
ns.ShapeSelect = function() {
|
ns.ShapeSelect = function() {
|
||||||
this.toolId = "tool-shape-select";
|
this.toolId = "tool-shape-select";
|
||||||
this.helpText = "Shape selection tool";
|
this.helpText = "Shape selection tool";
|
||||||
|
|
||||||
ns.BaseSelect.call(this);
|
ns.BaseSelect.call(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
pskl.utils.inherit(ns.ShapeSelect, ns.BaseSelect);
|
pskl.utils.inherit(ns.ShapeSelect, ns.BaseSelect);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For the shape select tool, you just need to click one time to create a selection.
|
* For the shape select tool, you just need to click one time to create a selection.
|
||||||
* So we jsut need to implement onSelectStart_ (no need for onSelect_ & onSelectEnd_)
|
* So we jsut need to implement onSelectStart_ (no need for onSelect_ & onSelectEnd_)
|
||||||
@ -24,13 +24,13 @@
|
|||||||
// Clean previous selection:
|
// Clean previous selection:
|
||||||
$.publish(Events.SELECTION_DISMISSED);
|
$.publish(Events.SELECTION_DISMISSED);
|
||||||
overlay.clear();
|
overlay.clear();
|
||||||
|
|
||||||
// From the pixel cliked, get shape using an algorithm similar to the paintbucket one:
|
// From the pixel cliked, get shape using an algorithm similar to the paintbucket one:
|
||||||
var pixels = pskl.PixelUtils.getSimilarConnectedPixelsFromFrame(frame, col, row);
|
var pixels = pskl.PixelUtils.getSimilarConnectedPixelsFromFrame(frame, col, row);
|
||||||
var selection = new pskl.selection.ShapeSelection(pixels);
|
this.selection = new pskl.selection.ShapeSelection(pixels);
|
||||||
|
|
||||||
$.publish(Events.SELECTION_CREATED, [selection]);
|
$.publish(Events.SELECTION_CREATED, [this.selection]);
|
||||||
this.drawSelectionOnOverlay_(selection, overlay);
|
this.drawSelectionOnOverlay_(overlay);
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
(function () {
|
(function () {
|
||||||
var ns = $.namespace("pskl.model");
|
var ns = $.namespace("pskl.model");
|
||||||
|
var __idCounter = 0;
|
||||||
ns.Frame = function (width, height) {
|
ns.Frame = function (width, height) {
|
||||||
if (width && height) {
|
if (width && height) {
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
|
this.id = __idCounter++;
|
||||||
|
this.version = 0;
|
||||||
this.pixels = ns.Frame.createEmptyPixelGrid_(width, height);
|
this.pixels = ns.Frame.createEmptyPixelGrid_(width, height);
|
||||||
this.previousStates = [this.getPixels()];
|
this.previousStates = [this.getPixels()];
|
||||||
this.stateIndex = 0;
|
this.stateIndex = 0;
|
||||||
@ -59,6 +60,7 @@
|
|||||||
*/
|
*/
|
||||||
ns.Frame.prototype.setPixels = function (pixels) {
|
ns.Frame.prototype.setPixels = function (pixels) {
|
||||||
this.pixels = this.clonePixels_(pixels);
|
this.pixels = this.clonePixels_(pixels);
|
||||||
|
this.version++;
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.Frame.prototype.clear = function () {
|
ns.Frame.prototype.clear = function () {
|
||||||
@ -78,13 +80,17 @@
|
|||||||
return clonedPixels;
|
return clonedPixels;
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.Frame.prototype.serialize = function () {
|
ns.Frame.prototype.getHash = function () {
|
||||||
return JSON.stringify(this.pixels);
|
return [this.id, this.version].join('-');
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.Frame.prototype.setPixel = function (col, row, color) {
|
ns.Frame.prototype.setPixel = function (col, row, color) {
|
||||||
if (this.containsPixel(col, row)) {
|
if (this.containsPixel(col, row)) {
|
||||||
this.pixels[col][row] = color;
|
var p = this.pixels[col][row];
|
||||||
|
if (p !== color) {
|
||||||
|
this.pixels[col][row] = color;
|
||||||
|
this.version++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -36,9 +36,10 @@
|
|||||||
this.getGridWidth(),
|
this.getGridWidth(),
|
||||||
offset.x, offset.y,
|
offset.x, offset.y,
|
||||||
size.width, size.height,
|
size.width, size.height,
|
||||||
frame.serialize()
|
frame.getHash()
|
||||||
].join('-');
|
].join('-');
|
||||||
if (this.serializedFrame != serializedFrame) {
|
if (this.serializedFrame != serializedFrame) {
|
||||||
|
// console.log('rendering')
|
||||||
this.serializedFrame = serializedFrame;
|
this.serializedFrame = serializedFrame;
|
||||||
this.superclass.render.call(this, frame);
|
this.superclass.render.call(this, frame);
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
var offset = this.getOffset();
|
var offset = this.getOffset();
|
||||||
var size = this.getDisplaySize();
|
var size = this.getDisplaySize();
|
||||||
var layers = this.piskelController.getLayers();
|
var layers = this.piskelController.getLayers();
|
||||||
var currentFrameIndex = this.piskelController.currentFrameIndex;
|
var currentFrameIndex = this.piskelController.getCurrentFrameIndex();
|
||||||
var currentLayerIndex = this.piskelController.currentLayerIndex;
|
var currentLayerIndex = this.piskelController.getCurrentLayerIndex();
|
||||||
|
|
||||||
var serializedRendering = [
|
var serializedRendering = [
|
||||||
this.getZoom(),
|
this.getZoom(),
|
||||||
|
@ -23,12 +23,9 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ns.BaseSelection.prototype.fillSelectionFromFrame = function (targetFrame) {
|
ns.BaseSelection.prototype.fillSelectionFromFrame = function (targetFrame) {
|
||||||
var pixelWithCopiedColor;
|
this.pixels.forEach(function (pixel) {
|
||||||
for(var i=0, l=this.pixels.length; i<l; i++) {
|
pixel.color = targetFrame.getPixel(pixel.col, pixel.row);
|
||||||
pixelWithCopiedColor = this.pixels[i];
|
});
|
||||||
pixelWithCopiedColor.copiedColor =
|
|
||||||
targetFrame.getPixel(pixelWithCopiedColor.col, pixelWithCopiedColor.row);
|
|
||||||
}
|
|
||||||
this.hasPastedContent = true;
|
this.hasPastedContent = true;
|
||||||
};
|
};
|
||||||
})();
|
})();
|
@ -1,6 +1,11 @@
|
|||||||
(function () {
|
(function () {
|
||||||
var ns = $.namespace("pskl.selection");
|
var ns = $.namespace("pskl.selection");
|
||||||
|
|
||||||
|
var SELECTION_REPLAY = {
|
||||||
|
PASTE : 'REPLAY_PASTE',
|
||||||
|
ERASE : 'REPLAY_ERASE'
|
||||||
|
};
|
||||||
|
|
||||||
ns.SelectionManager = function (piskelController) {
|
ns.SelectionManager = function (piskelController) {
|
||||||
|
|
||||||
this.piskelController = piskelController;
|
this.piskelController = piskelController;
|
||||||
@ -17,6 +22,7 @@
|
|||||||
pskl.app.shortcutService.addShortcut('ctrl+X', this.cut.bind(this));
|
pskl.app.shortcutService.addShortcut('ctrl+X', this.cut.bind(this));
|
||||||
pskl.app.shortcutService.addShortcut('ctrl+C', this.copy.bind(this));
|
pskl.app.shortcutService.addShortcut('ctrl+C', this.copy.bind(this));
|
||||||
pskl.app.shortcutService.addShortcut('del', this.erase.bind(this));
|
pskl.app.shortcutService.addShortcut('del', this.erase.bind(this));
|
||||||
|
pskl.app.shortcutService.addShortcut('back', this.onBackPressed_.bind(this));
|
||||||
|
|
||||||
$.subscribe(Events.TOOL_SELECTED, $.proxy(this.onToolSelected_, this));
|
$.subscribe(Events.TOOL_SELECTED, $.proxy(this.onToolSelected_, this));
|
||||||
};
|
};
|
||||||
@ -27,6 +33,7 @@
|
|||||||
ns.SelectionManager.prototype.cleanSelection_ = function() {
|
ns.SelectionManager.prototype.cleanSelection_ = function() {
|
||||||
if(this.currentSelection) {
|
if(this.currentSelection) {
|
||||||
this.currentSelection.reset();
|
this.currentSelection.reset();
|
||||||
|
this.currentSelection = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -47,16 +54,29 @@
|
|||||||
this.cleanSelection_();
|
this.cleanSelection_();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ns.SelectionManager.prototype.onBackPressed_ = function(evt) {
|
||||||
|
if (this.currentSelection) {
|
||||||
|
this.erase();
|
||||||
|
} else {
|
||||||
|
return true; // bubble
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ns.SelectionManager.prototype.erase = function () {
|
ns.SelectionManager.prototype.erase = function () {
|
||||||
var pixels = this.currentSelection.pixels;
|
var pixels = this.currentSelection.pixels;
|
||||||
var currentFrame = this.piskelController.getCurrentFrame();
|
var currentFrame = this.piskelController.getCurrentFrame();
|
||||||
for(var i=0, l=pixels.length; i<l; i++) {
|
for(var i=0, l=pixels.length; i<l; i++) {
|
||||||
try {
|
currentFrame.setPixel(pixels[i].col, pixels[i].row, Constants.TRANSPARENT_COLOR);
|
||||||
currentFrame.setPixel(pixels[i].col, pixels[i].row, Constants.TRANSPARENT_COLOR);
|
|
||||||
} catch(e) {
|
|
||||||
// Catching out of frame's bound pixels without testing
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$.publish(Events.PISKEL_SAVE_STATE, {
|
||||||
|
type : pskl.service.HistoryService.REPLAY,
|
||||||
|
scope : this,
|
||||||
|
replay : {
|
||||||
|
type : SELECTION_REPLAY.ERASE,
|
||||||
|
pixels : JSON.parse(JSON.stringify(pixels.slice(0)))
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.SelectionManager.prototype.cut = function() {
|
ns.SelectionManager.prototype.cut = function() {
|
||||||
@ -74,18 +94,30 @@
|
|||||||
if(this.currentSelection && this.currentSelection.hasPastedContent) {
|
if(this.currentSelection && this.currentSelection.hasPastedContent) {
|
||||||
var pixels = this.currentSelection.pixels;
|
var pixels = this.currentSelection.pixels;
|
||||||
var currentFrame = this.piskelController.getCurrentFrame();
|
var currentFrame = this.piskelController.getCurrentFrame();
|
||||||
for(var i=0, l=pixels.length; i<l; i++) {
|
|
||||||
try {
|
$.publish(Events.PISKEL_SAVE_STATE, {
|
||||||
currentFrame.setPixel(
|
type : pskl.service.HistoryService.REPLAY,
|
||||||
pixels[i].col, pixels[i].row,
|
scope : this,
|
||||||
pixels[i].copiedColor);
|
replay : {
|
||||||
} catch(e) {
|
type : SELECTION_REPLAY.PASTE,
|
||||||
// Catching out of frame's bound pixels without testing
|
pixels : JSON.parse(JSON.stringify(pixels.slice(0)))
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
|
pixels.forEach(function (pixel) {
|
||||||
|
currentFrame.setPixel(pixel.col,pixel.row,pixel.color);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ns.SelectionManager.prototype.replay = function (frame, replayData) {
|
||||||
|
var pixels = replayData.pixels;
|
||||||
|
pixels.forEach(function (pixel) {
|
||||||
|
var color = replayData.type === SELECTION_REPLAY.PASTE ? pixel.color : Constants.TRANSPARENT_COLOR;
|
||||||
|
frame.setPixel(pixel.col, pixel.row, color);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
ns.SelectionManager.prototype.copy = function() {
|
ns.SelectionManager.prototype.copy = function() {
|
||||||
if(this.currentSelection && this.piskelController.getCurrentFrame()) {
|
if(this.currentSelection && this.piskelController.getCurrentFrame()) {
|
||||||
this.currentSelection.fillSelectionFromFrame(this.piskelController.getCurrentFrame());
|
this.currentSelection.fillSelectionFromFrame(this.piskelController.getCurrentFrame());
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ns.AppEngineStorageService.prototype.prepareFormData_ = function () {
|
ns.AppEngineStorageService.prototype.prepareFormData_ = function () {
|
||||||
var piskel = this.piskelController.piskel;
|
var piskel = this.piskelController.getPiskel();
|
||||||
var descriptor = piskel.getDescriptor();
|
var descriptor = piskel.getDescriptor();
|
||||||
|
|
||||||
var formData = new FormData();
|
var formData = new FormData();
|
||||||
|
@ -1,35 +1,136 @@
|
|||||||
(function () {
|
(function () {
|
||||||
var ns = $.namespace("pskl.service");
|
var ns = $.namespace('pskl.service');
|
||||||
|
|
||||||
|
var SNAPSHOT_PERIOD = 50;
|
||||||
|
var LOAD_STATE_INTERVAL = 50;
|
||||||
|
|
||||||
ns.HistoryService = function (piskelController) {
|
ns.HistoryService = function (piskelController) {
|
||||||
this.piskelController = piskelController;
|
this.piskelController = piskelController;
|
||||||
this.saveState__b = this.saveState.bind(this);
|
this.stateQueue = [];
|
||||||
|
this.currentIndex = -1;
|
||||||
|
this.saveState__b = this.onSaveStateEvent.bind(this);
|
||||||
|
|
||||||
|
this.lastLoadState = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.HistoryService.prototype.init = function () {
|
ns.HistoryService.SNAPSHOT = 'SNAPSHOT';
|
||||||
|
ns.HistoryService.REPLAY = 'REPLAY';
|
||||||
|
|
||||||
$.subscribe(Events.PISKEL_RESET, this.saveState__b);
|
ns.HistoryService.prototype.init = function () {
|
||||||
$.subscribe(Events.TOOL_RELEASED, this.saveState__b);
|
$.subscribe(Events.PISKEL_SAVE_STATE, this.saveState__b);
|
||||||
|
|
||||||
pskl.app.shortcutService.addShortcut('ctrl+Z', this.undo.bind(this));
|
pskl.app.shortcutService.addShortcut('ctrl+Z', this.undo.bind(this));
|
||||||
pskl.app.shortcutService.addShortcut('ctrl+Y', this.redo.bind(this));
|
pskl.app.shortcutService.addShortcut('ctrl+Y', this.redo.bind(this));
|
||||||
|
|
||||||
|
this.saveState({
|
||||||
|
type : ns.HistoryService.SNAPSHOT
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.HistoryService.prototype.saveState = function () {
|
ns.HistoryService.prototype.onSaveStateEvent = function (evt, stateInfo) {
|
||||||
this.piskelController.getCurrentFrame().saveState();
|
this.saveState(stateInfo);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.HistoryService.prototype.saveState = function (stateInfo) {
|
||||||
|
this.stateQueue = this.stateQueue.slice(0, this.currentIndex + 1);
|
||||||
|
this.currentIndex = this.currentIndex + 1;
|
||||||
|
|
||||||
|
var state = {
|
||||||
|
action : stateInfo,
|
||||||
|
frameIndex : this.piskelController.currentFrameIndex,
|
||||||
|
layerIndex : this.piskelController.currentLayerIndex
|
||||||
|
};
|
||||||
|
|
||||||
|
if (stateInfo.type === ns.HistoryService.SNAPSHOT || this.currentIndex % SNAPSHOT_PERIOD === 0) {
|
||||||
|
state.piskel = this.piskelController.serialize(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.stateQueue.push(state);
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.HistoryService.prototype.undo = function () {
|
ns.HistoryService.prototype.undo = function () {
|
||||||
this.piskelController.getCurrentFrame().loadPreviousState();
|
this.loadState(this.currentIndex - 1);
|
||||||
$.unsubscribe(Events.PISKEL_RESET, this.saveState__b);
|
|
||||||
$.publish(Events.PISKEL_RESET);
|
|
||||||
$.subscribe(Events.PISKEL_RESET, this.saveState__b);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.HistoryService.prototype.redo = function () {
|
ns.HistoryService.prototype.redo = function () {
|
||||||
this.piskelController.getCurrentFrame().loadNextState();
|
this.loadState(this.currentIndex + 1);
|
||||||
$.unsubscribe(Events.PISKEL_RESET, this.saveState__b);
|
};
|
||||||
|
|
||||||
|
ns.HistoryService.prototype.isLoadStateAllowed_ = function (index) {
|
||||||
|
var timeOk = (Date.now() - this.lastLoadState) > LOAD_STATE_INTERVAL;
|
||||||
|
var indexInRange = index >= 0 && index < this.stateQueue.length;
|
||||||
|
return timeOk && indexInRange;
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.HistoryService.prototype.getPreviousSnapshotIndex_ = function (index) {
|
||||||
|
while (this.stateQueue[index] && !this.stateQueue[index].piskel) {
|
||||||
|
index = index - 1;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.HistoryService.prototype.loadState = function (index) {
|
||||||
|
if (this.isLoadStateAllowed_(index)) {
|
||||||
|
this.lastLoadState = Date.now();
|
||||||
|
|
||||||
|
var snapshotIndex = this.getPreviousSnapshotIndex_(index);
|
||||||
|
if (snapshotIndex < 0) {
|
||||||
|
throw 'Could not find previous SNAPSHOT saved in history stateQueue';
|
||||||
|
}
|
||||||
|
|
||||||
|
var piskelSnapshot = this.getSnapshotFromState_(snapshotIndex);
|
||||||
|
this.loadPiskel(piskelSnapshot, this.onPiskelLoadedCallback.bind(this, index, snapshotIndex));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.HistoryService.prototype.getSnapshotFromState_ = function (stateIndex) {
|
||||||
|
var state = this.stateQueue[stateIndex];
|
||||||
|
var piskelSnapshot = state.piskel;
|
||||||
|
|
||||||
|
// If the snapshot is stringified, parse it and backup the result for faster access next time
|
||||||
|
// FIXME : Memory consumption might go crazy if we keep unpacking big piskels indefinitely
|
||||||
|
// ==> should ensure I remove some of them :)
|
||||||
|
if (typeof piskelSnapshot === "string") {
|
||||||
|
piskelSnapshot = JSON.parse(piskelSnapshot);
|
||||||
|
state.piskel = piskelSnapshot;
|
||||||
|
}
|
||||||
|
|
||||||
|
return piskelSnapshot;
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.HistoryService.prototype.loadPiskel = function (piskel, callback) {
|
||||||
|
var descriptor = this.piskelController.piskel.getDescriptor();
|
||||||
|
pskl.utils.serialization.Deserializer.deserialize(piskel, function (deserializedPiskel) {
|
||||||
|
deserializedPiskel.setDescriptor(descriptor);
|
||||||
|
this.piskelController.setPiskel(deserializedPiskel);
|
||||||
|
callback(deserializedPiskel);
|
||||||
|
}.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.HistoryService.prototype.onPiskelLoadedCallback = function (index, snapshotIndex, piskel) {
|
||||||
|
for (var i = snapshotIndex + 1 ; i <= index ; i++) {
|
||||||
|
var state = this.stateQueue[i];
|
||||||
|
this.setupState(state);
|
||||||
|
this.replayState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastState = this.stateQueue[index];
|
||||||
|
this.setupState(lastState);
|
||||||
|
this.currentIndex = index;
|
||||||
$.publish(Events.PISKEL_RESET);
|
$.publish(Events.PISKEL_RESET);
|
||||||
$.subscribe(Events.PISKEL_RESET, this.saveState__b);
|
};
|
||||||
|
|
||||||
|
ns.HistoryService.prototype.setupState = function (state) {
|
||||||
|
this.piskelController.setCurrentFrameIndex(state.frameIndex);
|
||||||
|
this.piskelController.setCurrentLayerIndex(state.layerIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.HistoryService.prototype.replayState = function (state) {
|
||||||
|
var action = state.action;
|
||||||
|
var type = action.type;
|
||||||
|
var layer = this.piskelController.getLayerAt(state.layerIndex);
|
||||||
|
var frame = layer.getFrameAt(state.frameIndex);
|
||||||
|
action.scope.replay(frame, action.replay);
|
||||||
};
|
};
|
||||||
|
|
||||||
})();
|
})();
|
@ -2,7 +2,7 @@
|
|||||||
var ns = $.namespace('pskl.service');
|
var ns = $.namespace('pskl.service');
|
||||||
|
|
||||||
ns.SavedStatusService = function (piskelController) {
|
ns.SavedStatusService = function (piskelController) {
|
||||||
this.piskelController_ = piskelController;
|
this.piskelController = piskelController;
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.SavedStatusService.prototype.init = function () {
|
ns.SavedStatusService.prototype.init = function () {
|
||||||
@ -15,7 +15,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ns.SavedStatusService.prototype.onPiskelReset = function () {
|
ns.SavedStatusService.prototype.onPiskelReset = function () {
|
||||||
var piskel = this.piskelController_.piskel;
|
var piskel = this.piskelController.getPiskel();
|
||||||
// A first PISKEL_RESET is triggered during the load of a new Piskel, it should be ignored
|
// A first PISKEL_RESET is triggered during the load of a new Piskel, it should be ignored
|
||||||
// putting a firstResetDone flag as a nasty workaround for this
|
// putting a firstResetDone flag as a nasty workaround for this
|
||||||
if (piskel.firstResetDone_) {
|
if (piskel.firstResetDone_) {
|
||||||
@ -34,7 +34,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ns.SavedStatusService.prototype.updateDirtyStatus = function (status) {
|
ns.SavedStatusService.prototype.updateDirtyStatus = function (status) {
|
||||||
var piskel = this.piskelController_.piskel;
|
var piskel = this.piskelController.getPiskel();
|
||||||
if (piskel.isDirty_ !== status) {
|
if (piskel.isDirty_ !== status) {
|
||||||
// Redraw piskel name only if dirty status actually changed
|
// Redraw piskel name only if dirty status actually changed
|
||||||
piskel.isDirty_ = status;
|
piskel.isDirty_ = status;
|
||||||
@ -43,7 +43,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ns.SavedStatusService.prototype.updatePiskelName = function () {
|
ns.SavedStatusService.prototype.updatePiskelName = function () {
|
||||||
var piskel = this.piskelController_.piskel;
|
var piskel = this.piskelController.getPiskel();
|
||||||
var name = piskel.getDescriptor().name;
|
var name = piskel.getDescriptor().name;
|
||||||
if (piskel.isDirty_) {
|
if (piskel.isDirty_) {
|
||||||
$('.piskel-name').html(name + ' *');
|
$('.piskel-name').html(name + ' *');
|
||||||
@ -53,7 +53,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ns.SavedStatusService.prototype.onBeforeUnload = function (evt) {
|
ns.SavedStatusService.prototype.onBeforeUnload = function (evt) {
|
||||||
var piskel = this.piskelController_.piskel;
|
var piskel = this.piskelController.getPiskel();
|
||||||
if (piskel.isDirty_) {
|
if (piskel.isDirty_) {
|
||||||
var confirmationMessage = "Your Piskel seems to have unsaved changes";
|
var confirmationMessage = "Your Piskel seems to have unsaved changes";
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
(function () {
|
(function () {
|
||||||
var specialKeys = {
|
var specialKeys = {
|
||||||
191 : "?",
|
191 : "?",
|
||||||
|
8 : "back",
|
||||||
27 : "esc",
|
27 : "esc",
|
||||||
38 : "up",
|
38 : "up",
|
||||||
40 : "down",
|
40 : "down",
|
||||||
|
@ -12,6 +12,13 @@
|
|||||||
$(document.body).keydown($.proxy(this.onKeyUp_, this));
|
$(document.body).keydown($.proxy(this.onKeyUp_, this));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a keyboard shortcut
|
||||||
|
* @param {String} rawKey (case insensitive) key can be a meta (optional) + [a-z0-9] or
|
||||||
|
* a special key (check list of supported keys in KeycodeTranslator)
|
||||||
|
* eg. 'ctrl+A', 'del'
|
||||||
|
* @param {Function} callback should return true to let the original event perform its default action
|
||||||
|
*/
|
||||||
ns.ShortcutService.prototype.addShortcut = function (rawKey, callback) {
|
ns.ShortcutService.prototype.addShortcut = function (rawKey, callback) {
|
||||||
var parsedKey = this.parseKey_(rawKey.toLowerCase());
|
var parsedKey = this.parseKey_(rawKey.toLowerCase());
|
||||||
|
|
||||||
@ -78,8 +85,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(cb) {
|
if(cb) {
|
||||||
cb(charkey);
|
var bubble = cb(charkey);
|
||||||
evt.preventDefault();
|
if (bubble !== true) {
|
||||||
|
evt.preventDefault();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,5 +47,13 @@ if (typeof Function.prototype.bind !== "function") {
|
|||||||
extendedObject.prototype.superclass = inheritFrom.prototype;
|
extendedObject.prototype.superclass = inheritFrom.prototype;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ns.wrap = function (wrapper, wrappedObject) {
|
||||||
|
for (var prop in wrappedObject) {
|
||||||
|
if (typeof wrappedObject[prop] === 'function' && typeof wrapper[prop] === 'undefined') {
|
||||||
|
wrapper[prop] = wrappedObject[prop].bind(wrappedObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
@ -29,11 +29,11 @@
|
|||||||
this.piskel_ = new pskl.model.Piskel(piskelData.width, piskelData.height, descriptor);
|
this.piskel_ = new pskl.model.Piskel(piskelData.width, piskelData.height, descriptor);
|
||||||
|
|
||||||
this.layersToLoad_ = piskelData.layers.length;
|
this.layersToLoad_ = piskelData.layers.length;
|
||||||
|
if (piskelData.expanded) {
|
||||||
piskelData.layers.forEach(function (serializedLayer) {
|
piskelData.layers.forEach(this.loadExpandedLayer.bind(this));
|
||||||
var layer = this.deserializeLayer(serializedLayer);
|
} else {
|
||||||
this.piskel_.addLayer(layer);
|
piskelData.layers.forEach(this.deserializeLayer.bind(this));
|
||||||
}.bind(this));
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ns.Deserializer.prototype.deserializeLayer = function (layerString) {
|
ns.Deserializer.prototype.deserializeLayer = function (layerString) {
|
||||||
@ -48,11 +48,8 @@
|
|||||||
image.onload = function () {
|
image.onload = function () {
|
||||||
// 5 - extract the frames from the loaded image
|
// 5 - extract the frames from the loaded image
|
||||||
var frames = pskl.utils.LayerUtils.createFromImage(image, layerData.frameCount);
|
var frames = pskl.utils.LayerUtils.createFromImage(image, layerData.frameCount);
|
||||||
|
|
||||||
// 6 - add each image to the layer
|
// 6 - add each image to the layer
|
||||||
frames.forEach(layer.addFrame.bind(layer));
|
this.addFramesToLayer(frames, layer);
|
||||||
|
|
||||||
this.onLayerLoaded_();
|
|
||||||
}.bind(this);
|
}.bind(this);
|
||||||
|
|
||||||
// 3 - set the source of the image
|
// 3 - set the source of the image
|
||||||
@ -62,6 +59,24 @@
|
|||||||
return layer;
|
return layer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ns.Deserializer.prototype.loadExpandedLayer = function (layerData) {
|
||||||
|
var layer = new pskl.model.Layer(layerData.name);
|
||||||
|
var frames = layerData.grids.map(function (grid) {
|
||||||
|
return pskl.model.Frame.fromPixelGrid(grid);
|
||||||
|
});
|
||||||
|
this.addFramesToLayer(frames, layer);
|
||||||
|
|
||||||
|
// 4 - return a pointer to the new layer instance
|
||||||
|
return layer;
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.Deserializer.prototype.addFramesToLayer = function (frames, layer) {
|
||||||
|
frames.forEach(layer.addFrame.bind(layer));
|
||||||
|
|
||||||
|
this.piskel_.addLayer(layer);
|
||||||
|
this.onLayerLoaded_();
|
||||||
|
};
|
||||||
|
|
||||||
ns.Deserializer.prototype.onLayerLoaded_ = function () {
|
ns.Deserializer.prototype.onLayerLoaded_ = function () {
|
||||||
this.layersToLoad_ = this.layersToLoad_ - 1;
|
this.layersToLoad_ = this.layersToLoad_ - 1;
|
||||||
if (this.layersToLoad_ === 0) {
|
if (this.layersToLoad_ === 0) {
|
||||||
|
@ -2,30 +2,35 @@
|
|||||||
var ns = $.namespace('pskl.utils');
|
var ns = $.namespace('pskl.utils');
|
||||||
|
|
||||||
ns.Serializer = {
|
ns.Serializer = {
|
||||||
serializePiskel : function (piskel) {
|
serializePiskel : function (piskel, expanded) {
|
||||||
var serializedLayers = piskel.getLayers().map(function (l) {
|
var serializedLayers = piskel.getLayers().map(function (l) {
|
||||||
return pskl.utils.Serializer.serializeLayer(l);
|
return pskl.utils.Serializer.serializeLayer(l, expanded);
|
||||||
});
|
});
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
modelVersion : Constants.MODEL_VERSION,
|
modelVersion : Constants.MODEL_VERSION,
|
||||||
piskel : {
|
piskel : {
|
||||||
height : piskel.getHeight(),
|
height : piskel.getHeight(),
|
||||||
width : piskel.getWidth(),
|
width : piskel.getWidth(),
|
||||||
layers : serializedLayers
|
layers : serializedLayers,
|
||||||
|
expanded : expanded
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
serializeLayer : function (layer) {
|
serializeLayer : function (layer, expanded) {
|
||||||
var frames = layer.getFrames();
|
var frames = layer.getFrames();
|
||||||
var renderer = new pskl.rendering.FramesheetRenderer(frames);
|
var renderer = new pskl.rendering.FramesheetRenderer(frames);
|
||||||
var base64PNG = renderer.renderAsCanvas().toDataURL();
|
var layerToSerialize = {
|
||||||
|
|
||||||
return JSON.stringify({
|
|
||||||
name : layer.getName(),
|
name : layer.getName(),
|
||||||
base64PNG : base64PNG,
|
|
||||||
frameCount : frames.length
|
frameCount : frames.length
|
||||||
});
|
};
|
||||||
|
if (expanded) {
|
||||||
|
layerToSerialize.grids = frames.map(function (f) {return f.pixels;});
|
||||||
|
return layerToSerialize;
|
||||||
|
} else {
|
||||||
|
layerToSerialize.base64PNG = renderer.renderAsCanvas().toDataURL();
|
||||||
|
return JSON.stringify(layerToSerialize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
@ -65,7 +65,8 @@
|
|||||||
"js/rendering/PiskelRenderer.js",
|
"js/rendering/PiskelRenderer.js",
|
||||||
|
|
||||||
// Controllers
|
// Controllers
|
||||||
"js/controller/PiskelController.js",
|
"js/controller/piskel/PiskelController.js",
|
||||||
|
"js/controller/piskel/PublicPiskelController.js",
|
||||||
"js/controller/CursorCoordinatesController.js",
|
"js/controller/CursorCoordinatesController.js",
|
||||||
"js/controller/DrawingController.js",
|
"js/controller/DrawingController.js",
|
||||||
"js/controller/PreviewFilmController.js",
|
"js/controller/PreviewFilmController.js",
|
||||||
|
Loading…
Reference in New Issue
Block a user