mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Issue 24 : Layers
!! NOT STABLE !! Initial implementation. No UI update yet. Check js/model/Piskel.js and js/model/Layer.js for an overview of the new API. Piskels can be saved on the existing service. Previous piskels cannot be loaded. This should be fixed soon.
This commit is contained in:
@ -32,5 +32,5 @@ ul, li {
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: rgba(50, 50, 50, 0.4);;
|
||||
background-color: rgba(50, 50, 50, 0.4);
|
||||
}
|
@ -19,7 +19,6 @@
|
||||
.tool-icon.selected {
|
||||
cursor: default;
|
||||
background-color: #444;
|
||||
cursor: normal;
|
||||
border: 1px gold solid;
|
||||
margin: 0;
|
||||
}
|
||||
@ -151,7 +150,7 @@
|
||||
}
|
||||
|
||||
|
||||
.palette .palette-color.transparent-color {
|
||||
.palette-color[data-color=TRANSPARENT] {
|
||||
position: relative;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
|
@ -1,10 +1,13 @@
|
||||
// TODO(grosbouddha): put under pskl namespace.
|
||||
var Constants = {
|
||||
DEFAULT_SIZE : {
|
||||
height : 32,
|
||||
width : 32
|
||||
DEFAULT : {
|
||||
HEIGHT : 32,
|
||||
WIDTH : 32,
|
||||
FPS : 12
|
||||
},
|
||||
|
||||
MODEL_VERSION : 1,
|
||||
|
||||
MAX_HEIGHT : 128,
|
||||
MAX_WIDTH : 128,
|
||||
|
||||
|
@ -4,43 +4,39 @@
|
||||
*/
|
||||
(function () {
|
||||
var ns = $.namespace("pskl");
|
||||
/**
|
||||
* FrameSheetModel instance.
|
||||
*/
|
||||
var frameSheet;
|
||||
/**
|
||||
* Main application controller
|
||||
*/
|
||||
ns.app = {
|
||||
|
||||
init : function () {
|
||||
var frameSize = this.readSizeFromURL_();
|
||||
frameSheet = new pskl.model.FrameSheet(frameSize.height, frameSize.width);
|
||||
frameSheet.addEmptyFrame();
|
||||
frameSheet.setCurrentFrameIndex(0);
|
||||
var size = this.readSizeFromURL_();
|
||||
var piskel = new pskl.model.Piskel(size.width, size.height, Constants.DEFAULT.FPS);
|
||||
|
||||
/**
|
||||
* True when piskel is running in static mode (no back end needed).
|
||||
* When started from APP Engine, appEngineToken_ (Boolean) should be set on window.pskl
|
||||
*/
|
||||
this.isStaticVersion = !pskl.appEngineToken_;
|
||||
var layer = new pskl.model.Layer("Default layer");
|
||||
var frame = new pskl.model.Frame(size.width, size.height);
|
||||
layer.addFrame(frame);
|
||||
|
||||
this.drawingController = new pskl.controller.DrawingController(frameSheet, $('#drawing-canvas-container'));
|
||||
piskel.addLayer(layer);
|
||||
|
||||
this.piskelController = new pskl.controller.PiskelController(piskel);
|
||||
|
||||
this.drawingController = new pskl.controller.DrawingController(this.piskelController, $('#drawing-canvas-container'));
|
||||
this.drawingController.init();
|
||||
|
||||
this.animationController = new pskl.controller.AnimatedPreviewController(frameSheet, $('#preview-canvas-container'));
|
||||
this.animationController = new pskl.controller.AnimatedPreviewController(this.piskelController, $('#preview-canvas-container'));
|
||||
this.animationController.init();
|
||||
|
||||
this.previewsController = new pskl.controller.PreviewFilmController(frameSheet, $('#preview-list'));
|
||||
this.previewsController = new pskl.controller.PreviewFilmController(this.piskelController, $('#preview-list'));
|
||||
this.previewsController.init();
|
||||
|
||||
this.settingsController = new pskl.controller.SettingsController(frameSheet);
|
||||
this.settingsController = new pskl.controller.SettingsController(this.piskelController);
|
||||
this.settingsController.init();
|
||||
|
||||
this.selectionManager = new pskl.selection.SelectionManager(frameSheet);
|
||||
this.selectionManager = new pskl.selection.SelectionManager(this.piskelController);
|
||||
this.selectionManager.init();
|
||||
|
||||
this.historyService = new pskl.service.HistoryService(frameSheet);
|
||||
this.historyService = new pskl.service.HistoryService(this.piskelController);
|
||||
this.historyService.init();
|
||||
|
||||
this.keyboardEventService = new pskl.service.KeyboardEventService();
|
||||
@ -49,7 +45,7 @@
|
||||
this.notificationController = new pskl.controller.NotificationController();
|
||||
this.notificationController.init();
|
||||
|
||||
this.localStorageService = new pskl.service.LocalStorageService(frameSheet);
|
||||
this.localStorageService = new pskl.service.LocalStorageService(this.piskelController);
|
||||
this.localStorageService.init();
|
||||
|
||||
this.imageUploadService = new pskl.service.ImageUploadService();
|
||||
@ -59,16 +55,13 @@
|
||||
this.toolController.init();
|
||||
|
||||
this.paletteController = new pskl.controller.PaletteController();
|
||||
this.paletteController.init(frameSheet);
|
||||
this.paletteController.init();
|
||||
|
||||
var drawingLoop = new pskl.rendering.DrawingLoop();
|
||||
drawingLoop.addCallback(this.render, this);
|
||||
drawingLoop.start();
|
||||
|
||||
// Init (event-delegated) bootstrap tooltips:
|
||||
$('body').tooltip({
|
||||
selector: '[rel=tooltip]'
|
||||
});
|
||||
this.initBootstrapTooltips_();
|
||||
|
||||
|
||||
/**
|
||||
@ -89,12 +82,18 @@
|
||||
}
|
||||
} else {
|
||||
if (pskl.framesheetData_ && pskl.framesheetData_.content) {
|
||||
frameSheet.load(pskl.framesheetData_.content);
|
||||
this.piskelController.load(pskl.framesheetData_.content);
|
||||
pskl.app.animationController.setFPS(pskl.framesheetData_.fps);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
initBootstrapTooltips_ : function () {
|
||||
$('body').tooltip({
|
||||
selector: '[rel=tooltip]'
|
||||
});
|
||||
},
|
||||
|
||||
render : function (delta) {
|
||||
this.drawingController.render(delta);
|
||||
this.animationController.render(delta);
|
||||
@ -115,7 +114,10 @@
|
||||
width : Math.min(width, Constants.MAX_WIDTH)
|
||||
};
|
||||
} else {
|
||||
size = Constants.DEFAULT_SIZE;
|
||||
size = {
|
||||
height : Constants.DEFAULT.HEIGHT,
|
||||
width : Constants.DEFAULT.WIDTH
|
||||
};
|
||||
}
|
||||
return size;
|
||||
},
|
||||
@ -141,10 +143,10 @@
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', Constants.PISKEL_SERVICE_URL + '/get?l=' + frameId, true);
|
||||
xhr.responseType = 'text';
|
||||
|
||||
var piskelController = this.piskelController;
|
||||
xhr.onload = function (e) {
|
||||
var res = JSON.parse(this.responseText);
|
||||
frameSheet.load(res.framesheet);
|
||||
piskelController.deserialize(JSON.stringify(res.framesheet));
|
||||
pskl.app.animationController.setFPS(res.fps);
|
||||
$.publish(Events.HIDE_NOTIFICATION);
|
||||
};
|
||||
@ -156,21 +158,15 @@
|
||||
xhr.send();
|
||||
},
|
||||
|
||||
loadFramesheet : function (framesheet) {
|
||||
frameSheet.load(framesheet);
|
||||
},
|
||||
|
||||
getFirstFrameAsPNGData_ : function () {
|
||||
var tmpSheet = new pskl.model.FrameSheet(frameSheet.getHeight(), frameSheet.getWidth());
|
||||
tmpSheet.addFrame(frameSheet.getFrameByIndex(0));
|
||||
return (new pskl.rendering.SpritesheetRenderer(tmpSheet)).renderAsImageDataSpritesheetPNG();
|
||||
throw 'getFirstFrameAsPNGData_ not implemented';
|
||||
},
|
||||
|
||||
// TODO(julz): Create package ?
|
||||
storeSheet : function (event) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
var formData = new FormData();
|
||||
formData.append('framesheet_content', frameSheet.serialize());
|
||||
formData.append('framesheet_content', this.piskelController.serialize());
|
||||
formData.append('fps_speed', $('#preview-fps').val());
|
||||
|
||||
if (this.isStaticVersion) {
|
||||
@ -179,12 +175,12 @@
|
||||
} else {
|
||||
// additional values only used with latest app-engine backend
|
||||
formData.append('name', $('#piskel-name').val());
|
||||
formData.append('frames', frameSheet.getFrameCount());
|
||||
// Get image/png data for first frame
|
||||
formData.append('frames', this.piskelController.getFrameCount());
|
||||
|
||||
// Get image/png data for first frame
|
||||
formData.append('preview', this.getFirstFrameAsPNGData_());
|
||||
|
||||
var imageData = (new pskl.rendering.SpritesheetRenderer(frameSheet)).renderAsImageDataSpritesheetPNG();
|
||||
var imageData = (new pskl.rendering.SpritesheetRenderer(this.piskelController)).renderAsImageDataSpritesheetPNG();
|
||||
formData.append('framesheet', imageData);
|
||||
|
||||
xhr.open('POST', "save", true);
|
||||
@ -214,25 +210,16 @@
|
||||
return false;
|
||||
},
|
||||
|
||||
uploadAsAnimatedGIF : function () {
|
||||
var fps = pskl.app.animationController.fps;
|
||||
var renderer = new pskl.rendering.SpritesheetRenderer(frameSheet);
|
||||
|
||||
renderer.renderAsImageDataAnimatedGIF(fps, function (imageData) {
|
||||
this.imageUploadService.upload(imageData, this.openWindow);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
uploadAsSpritesheetPNG : function () {
|
||||
var imageData = (new pskl.rendering.SpritesheetRenderer(frameSheet)).renderAsImageDataSpritesheetPNG();
|
||||
this.imageUploadService.upload(imageData, this.openWindow);
|
||||
var imageData = (new pskl.rendering.SpritesheetRenderer(this.piskelController)).renderAsImageDataSpritesheetPNG();
|
||||
this.imageUploadService.upload(imageData, this.openWindow.bind(this));
|
||||
},
|
||||
|
||||
openWindow : function (url) {
|
||||
var options = [
|
||||
"dialog=yes", "scrollbars=no", "status=no",
|
||||
"width=" + frameSheet.getWidth() * frameSheet.getFrameCount(),
|
||||
"height=" + frameSheet.getHeight()
|
||||
"width=" + this.piskelController.getWidth() * this.piskelController.getFrameCount(),
|
||||
"height=" + this.piskelController.getHeight()
|
||||
].join(",");
|
||||
|
||||
window.open(url, "piskel-export", options);
|
@ -1,7 +1,7 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller");
|
||||
ns.AnimatedPreviewController = function (framesheet, container, dpi) {
|
||||
this.framesheet = framesheet;
|
||||
ns.AnimatedPreviewController = function (piskelController, container, dpi) {
|
||||
this.piskelController = piskelController;
|
||||
this.container = container;
|
||||
|
||||
this.elapsedTime = 0;
|
||||
@ -39,11 +39,11 @@
|
||||
var index = Math.floor(this.elapsedTime / (1000/this.fps));
|
||||
if (index != this.currentIndex) {
|
||||
this.currentIndex = index;
|
||||
if (!this.framesheet.hasFrameAtIndex(this.currentIndex)) {
|
||||
if (!this.piskelController.hasFrameAt(this.currentIndex)) {
|
||||
this.currentIndex = 0;
|
||||
this.elapsedTime = 0;
|
||||
}
|
||||
this.renderer.render(this.framesheet.getFrameByIndex(this.currentIndex));
|
||||
this.renderer.render(this.piskelController.getFrameAt(this.currentIndex));
|
||||
}
|
||||
};
|
||||
|
||||
@ -52,8 +52,8 @@
|
||||
*/
|
||||
ns.AnimatedPreviewController.prototype.calculateDPI_ = function () {
|
||||
var previewSize = 200,
|
||||
framePixelHeight = this.framesheet.getCurrentFrame().getHeight(),
|
||||
framePixelWidth = this.framesheet.getCurrentFrame().getWidth();
|
||||
framePixelHeight = this.piskelController.getCurrentFrame().getHeight(),
|
||||
framePixelWidth = this.piskelController.getCurrentFrame().getWidth();
|
||||
// TODO (julz) : should have a utility to get a Size from framesheet easily (what about empty framesheets though ?)
|
||||
|
||||
//return pskl.PixelUtils.calculateDPIForContainer($(".preview-container"), framePixelHeight, framePixelWidth);
|
||||
|
@ -1,15 +1,15 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller");
|
||||
ns.DrawingController = function (framesheet, container) {
|
||||
ns.DrawingController = function (piskelController, container) {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
this.framesheet = framesheet;
|
||||
this.piskelController = piskelController;
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(framesheet.getCurrentFrame());
|
||||
this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(piskelController.getCurrentFrame());
|
||||
|
||||
/**
|
||||
* @private
|
||||
@ -36,7 +36,7 @@
|
||||
};
|
||||
|
||||
ns.DrawingController.prototype.init = function () {
|
||||
this.renderer.render(this.framesheet.getCurrentFrame());
|
||||
this.renderer.render(this.piskelController.getCurrentFrame());
|
||||
this.overlayRenderer.render(this.overlayFrame);
|
||||
|
||||
this.initMouseBehavior();
|
||||
@ -114,7 +114,7 @@
|
||||
this.currentToolBehavior.applyToolAt(
|
||||
coords.col, coords.row,
|
||||
this.getCurrentColor_(),
|
||||
this.framesheet.getCurrentFrame(),
|
||||
this.piskelController.getCurrentFrame(),
|
||||
this.overlayFrame,
|
||||
this.wrapEvtInfo_(event)
|
||||
);
|
||||
@ -135,7 +135,7 @@
|
||||
this.currentToolBehavior.moveToolAt(
|
||||
coords.col, coords.row,
|
||||
this.getCurrentColor_(),
|
||||
this.framesheet.getCurrentFrame(),
|
||||
this.piskelController.getCurrentFrame(),
|
||||
this.overlayFrame,
|
||||
this.wrapEvtInfo_(event)
|
||||
);
|
||||
@ -149,7 +149,7 @@
|
||||
this.currentToolBehavior.moveUnactiveToolAt(
|
||||
coords.col, coords.row,
|
||||
this.getCurrentColor_(),
|
||||
this.framesheet.getCurrentFrame(),
|
||||
this.piskelController.getCurrentFrame(),
|
||||
this.overlayFrame,
|
||||
this.wrapEvtInfo_(event)
|
||||
);
|
||||
@ -176,7 +176,7 @@
|
||||
this.currentToolBehavior.releaseToolAt(
|
||||
coords.col, coords.row,
|
||||
this.getCurrentColor_(),
|
||||
this.framesheet.getCurrentFrame(),
|
||||
this.piskelController.getCurrentFrame(),
|
||||
this.overlayFrame,
|
||||
this.wrapEvtInfo_(event)
|
||||
);
|
||||
@ -247,7 +247,7 @@
|
||||
};
|
||||
|
||||
ns.DrawingController.prototype.renderFrame = function () {
|
||||
var frame = this.framesheet.getCurrentFrame();
|
||||
var frame = this.piskelController.getCurrentFrame();
|
||||
var serializedFrame = frame.serialize();
|
||||
if (this.serializedFrame != serializedFrame) {
|
||||
if (!frame.isSameSize(this.overlayFrame)) {
|
||||
@ -278,8 +278,8 @@
|
||||
leftSectionWidth = $('.left-column').outerWidth(true),
|
||||
rightSectionWidth = $('.right-column').outerWidth(true),
|
||||
availableViewportWidth = $('#main-wrapper').width() - leftSectionWidth - rightSectionWidth,
|
||||
framePixelHeight = this.framesheet.getCurrentFrame().getHeight(),
|
||||
framePixelWidth = this.framesheet.getCurrentFrame().getWidth();
|
||||
framePixelHeight = this.piskelController.getCurrentFrame().getHeight(),
|
||||
framePixelWidth = this.piskelController.getCurrentFrame().getWidth();
|
||||
|
||||
if (pskl.UserSettings.get(pskl.UserSettings.SHOW_GRID)) {
|
||||
availableViewportWidth = availableViewportWidth - (framePixelWidth * Constants.GRID_STROKE_WIDTH);
|
||||
@ -300,7 +300,7 @@
|
||||
this.renderer.updateDPI(dpi);
|
||||
this.overlayRenderer.updateDPI(dpi);
|
||||
|
||||
var currentFrameHeight = this.framesheet.getCurrentFrame().getHeight();
|
||||
var currentFrameHeight = this.piskelController.getCurrentFrame().getHeight();
|
||||
var canvasHeight = currentFrameHeight * dpi;
|
||||
if (pskl.UserSettings.get(pskl.UserSettings.SHOW_GRID)) {
|
||||
canvasHeight += Constants.GRID_STROKE_WIDTH * currentFrameHeight;
|
||||
|
@ -3,6 +3,14 @@
|
||||
|
||||
ns.NotificationController = function () {};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.NotificationController.prototype.init = function() {
|
||||
$.subscribe(Events.SHOW_NOTIFICATION, $.proxy(this.displayMessage_, this));
|
||||
$.subscribe(Events.HIDE_NOTIFICATION, $.proxy(this.removeMessage_, this));
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@ -28,12 +36,4 @@
|
||||
message.remove();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.NotificationController.prototype.init = function() {
|
||||
$.subscribe(Events.SHOW_NOTIFICATION, $.proxy(this.displayMessage_, this));
|
||||
$.subscribe(Events.HIDE_NOTIFICATION, $.proxy(this.removeMessage_, this));
|
||||
};
|
||||
})();
|
||||
|
@ -1,9 +1,35 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller");
|
||||
|
||||
ns.PaletteController = function () {
|
||||
this.paletteRoot = null;
|
||||
this.paletteColors = [];
|
||||
ns.PaletteController = function () {};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.PaletteController.prototype.init = function() {
|
||||
var transparentColorPalette = $(".palette-color[data-color=TRANSPARENT]");
|
||||
transparentColorPalette.mouseup($.proxy(this.onPaletteColorClick_, this));
|
||||
|
||||
$.subscribe(Events.PRIMARY_COLOR_UPDATED, $.proxy(function(evt, color) {
|
||||
this.updateColorPicker_(color, $('#color-picker'));
|
||||
this.addColorToPalette_(color);
|
||||
}, this));
|
||||
|
||||
$.subscribe(Events.SECONDARY_COLOR_UPDATED, $.proxy(function(evt, color) {
|
||||
this.updateColorPicker_(color, $('#secondary-color-picker'));
|
||||
this.addColorToPalette_(color);
|
||||
}, this));
|
||||
|
||||
// Initialize colorpickers:
|
||||
var colorPicker = $('#color-picker');
|
||||
colorPicker.val(Constants.DEFAULT_PEN_COLOR);
|
||||
colorPicker.change({isPrimary : true}, $.proxy(this.onPickerChange_, this));
|
||||
|
||||
|
||||
var secondaryColorPicker = $('#secondary-color-picker');
|
||||
secondaryColorPicker.val(Constants.TRANSPARENT_COLOR);
|
||||
secondaryColorPicker.change({isPrimary : false}, $.proxy(this.onPickerChange_, this));
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@ -13,30 +39,11 @@
|
||||
var inputPicker = $(evt.target);
|
||||
if(evt.data.isPrimary) {
|
||||
$.publish(Events.PRIMARY_COLOR_SELECTED, [inputPicker.val()]);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$.publish(Events.SECONDARY_COLOR_SELECTED, [inputPicker.val()]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.PaletteController.prototype.addColorToPalette_ = function (color) {
|
||||
if (this.paletteColors.indexOf(color) == -1 && color != Constants.TRANSPARENT_COLOR) {
|
||||
this.paletteColors.push(color);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.PaletteController.prototype.addColorsToPalette_ = function (colors) {
|
||||
for(var color in colors) {
|
||||
this.addColorToPalette_(color);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@ -71,45 +78,6 @@
|
||||
colorPicker[0].color.fromString(color);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.PaletteController.prototype.init = function(framesheet) {
|
||||
|
||||
this.paletteRoot = $("#palette");
|
||||
this.framesheet = framesheet;
|
||||
|
||||
// Initialize palette:
|
||||
this.addColorsToPalette_(this.framesheet.getUsedColors());
|
||||
|
||||
$.subscribe(Events.FRAMESHEET_RESET, $.proxy(function(evt) {
|
||||
this.addColorsToPalette_(this.framesheet.getUsedColors());
|
||||
}, this));
|
||||
|
||||
this.paletteRoot.mouseup($.proxy(this.onPaletteColorClick_, this));
|
||||
|
||||
$.subscribe(Events.PRIMARY_COLOR_UPDATED, $.proxy(function(evt, color) {
|
||||
this.updateColorPicker_(color, $('#color-picker'));
|
||||
this.addColorToPalette_(color);
|
||||
}, this));
|
||||
|
||||
$.subscribe(Events.SECONDARY_COLOR_UPDATED, $.proxy(function(evt, color) {
|
||||
this.updateColorPicker_(color, $('#secondary-color-picker'));
|
||||
this.addColorToPalette_(color);
|
||||
}, this));
|
||||
|
||||
// Initialize colorpickers:
|
||||
var colorPicker = $('#color-picker');
|
||||
colorPicker.val(Constants.DEFAULT_PEN_COLOR);
|
||||
colorPicker.change({isPrimary : true}, $.proxy(this.onPickerChange_, this));
|
||||
|
||||
|
||||
var secondaryColorPicker = $('#secondary-color-picker');
|
||||
secondaryColorPicker.val(Constants.TRANSPARENT_COLOR);
|
||||
secondaryColorPicker.change({isPrimary : false}, $.proxy(this.onPickerChange_, this));
|
||||
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
|
125
js/controller/PiskelController.js
Normal file
125
js/controller/PiskelController.js
Normal file
@ -0,0 +1,125 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.controller');
|
||||
|
||||
ns.PiskelController = function (piskel) {
|
||||
this.setPiskel(piskel);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.setPiskel = function (piskel) {
|
||||
this.piskel = piskel;
|
||||
this.currentLayerIndex = 0;
|
||||
this.currentFrameIndex = 0;
|
||||
|
||||
$.publish(Events.FRAMESHEET_RESET);
|
||||
$.publish(Events.FRAME_SIZE_CHANGED);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.getHeight = function () {
|
||||
return this.piskel.getHeight();
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.getWidth = function () {
|
||||
return this.piskel.getWidth();
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.getCurrentLayer = function () {
|
||||
return this.piskel.getLayerAt(this.currentLayerIndex);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.getCurrentFrame = function () {
|
||||
var layer = this.getCurrentLayer();
|
||||
return layer.getFrameAt(this.currentFrameIndex);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.getFrameAt = function (index) {
|
||||
var frames = this.piskel.getLayers().map(function (l) {
|
||||
return l.getFrameAt(index);
|
||||
});
|
||||
return pskl.utils.FrameUtils.merge(frames);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.hasFrameAt = function (index) {
|
||||
return !!this.getCurrentLayer().getFrameAt(index);
|
||||
};
|
||||
|
||||
// backward from framesheet
|
||||
ns.PiskelController.prototype.getFrameByIndex =
|
||||
ns.PiskelController.prototype.getMergedFrameAt;
|
||||
|
||||
ns.PiskelController.prototype.addEmptyFrame = function () {
|
||||
var layers = this.piskel.getLayers();
|
||||
layers.forEach(function (l) {
|
||||
l.addFrame(this.createEmptyFrame_());
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.createEmptyFrame_ = function () {
|
||||
var w = this.piskel.getWidth(), h = this.piskel.getHeight();
|
||||
return new pskl.model.Frame(w, h);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.removeFrameAt = function (index) {
|
||||
var layers = this.piskel.getLayers();
|
||||
layers.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.setCurrentFrameIndex(this.currentFrameIndex - 1);
|
||||
}
|
||||
|
||||
$.publish(Events.FRAMESHEET_RESET);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.duplicateFrameAt = function (index) {
|
||||
var layers = this.piskel.getLayers();
|
||||
layers.forEach(function (l) {
|
||||
l.duplicateFrameAt(index);
|
||||
});
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.moveFrame = function (fromIndex, toIndex) {
|
||||
var layers = this.piskel.getLayers();
|
||||
layers.forEach(function (l) {
|
||||
l.moveFrame(fromIndex, toIndex);
|
||||
});
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.getFrameCount = function () {
|
||||
var layer = this.piskel.getLayerAt(0);
|
||||
return layer.length();
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.setCurrentFrameIndex = function (index) {
|
||||
this.currentFrameIndex = index;
|
||||
$.publish(Events.FRAMESHEET_RESET);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.setCurrentLayerIndex = function (index) {
|
||||
this.currentLayerIndex = index;
|
||||
$.publish(Events.FRAMESHEET_RESET);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.createLayer = function (name) {
|
||||
var layer = new pskl.model.Layer(name);
|
||||
for (var i = 0 ; i < this.getFrameCount() ; i++) {
|
||||
layer.addFrame(this.createEmptyFrame_());
|
||||
}
|
||||
this.piskel.addLayer(layer);
|
||||
this.setCurrentLayerIndex(this.piskel.getLayers().length - 1);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.serialize = function () {
|
||||
return pskl.utils.Serializer.serializePiskel(this.piskel);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.deserialize = function (json) {
|
||||
try {
|
||||
var piskel = pskl.utils.Serializer.deserializePiskel(json);
|
||||
this.setPiskel(piskel);
|
||||
} catch (e) {
|
||||
console.error('Failed to deserialize');
|
||||
console.error(e.stack);
|
||||
}
|
||||
};
|
||||
})();
|
@ -1,8 +1,8 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller");
|
||||
ns.PreviewFilmController = function (framesheet, container, dpi) {
|
||||
ns.PreviewFilmController = function (piskelController, container, dpi) {
|
||||
|
||||
this.framesheet = framesheet;
|
||||
this.piskelController = piskelController;
|
||||
this.container = container;
|
||||
this.dpi = this.calculateDPI_();
|
||||
|
||||
@ -19,8 +19,8 @@
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.addFrame = function () {
|
||||
this.framesheet.addEmptyFrame();
|
||||
this.framesheet.setCurrentFrameIndex(this.framesheet.getFrameCount() - 1);
|
||||
this.piskelController.addEmptyFrame();
|
||||
this.piskelController.setCurrentFrameIndex(this.piskelController.getFrameCount() - 1);
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
|
||||
@ -68,7 +68,7 @@
|
||||
// Manually remove tooltips since mouseout events were shortcut by the DOM refresh:
|
||||
$(".tooltip").remove();
|
||||
|
||||
var frameCount = this.framesheet.getFrameCount();
|
||||
var frameCount = this.piskelController.getFrameCount();
|
||||
|
||||
for (var i = 0, l = frameCount; i < l ; i++) {
|
||||
this.container.append(this.createPreviewTile_(i));
|
||||
@ -110,8 +110,8 @@
|
||||
var originFrameId = parseInt(ui.item.data("tile-number"), 10);
|
||||
var targetInsertionId = $('.preview-tile').index(ui.item);
|
||||
|
||||
this.framesheet.moveFrame(originFrameId, targetInsertionId);
|
||||
this.framesheet.setCurrentFrameIndex(targetInsertionId);
|
||||
this.piskelController.moveFrame(originFrameId, targetInsertionId);
|
||||
this.piskelController.setCurrentFrameIndex(targetInsertionId);
|
||||
|
||||
// TODO(grosbouddha): move localstorage request to the model layer?
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST);
|
||||
@ -123,13 +123,13 @@
|
||||
* TODO(vincz): clean this giant rendering function & remove listeners.
|
||||
*/
|
||||
ns.PreviewFilmController.prototype.createPreviewTile_ = function(tileNumber) {
|
||||
var currentFrame = this.framesheet.getFrameByIndex(tileNumber);
|
||||
var currentFrame = this.piskelController.getCurrentLayer().getFrameAt(tileNumber);
|
||||
|
||||
var previewTileRoot = document.createElement("li");
|
||||
var classname = "preview-tile";
|
||||
previewTileRoot.setAttribute("data-tile-number", tileNumber);
|
||||
|
||||
if (this.framesheet.getCurrentFrame() == currentFrame) {
|
||||
if (this.piskelController.getCurrentFrame() == currentFrame) {
|
||||
classname += " selected";
|
||||
}
|
||||
previewTileRoot.className = classname;
|
||||
@ -159,7 +159,7 @@
|
||||
|
||||
previewTileRoot.appendChild(canvasContainer);
|
||||
|
||||
if(tileNumber > 0 || this.framesheet.getFrameCount() > 1) {
|
||||
if(tileNumber > 0 || this.piskelController.getFrameCount() > 1) {
|
||||
// Add 'remove frame' button.
|
||||
var deleteButton = document.createElement("button");
|
||||
deleteButton.setAttribute('rel', 'tooltip');
|
||||
@ -186,28 +186,28 @@
|
||||
ns.PreviewFilmController.prototype.onPreviewClick_ = function (index, evt) {
|
||||
// has not class tile-action:
|
||||
if(!evt.target.classList.contains('tile-overlay')) {
|
||||
this.framesheet.setCurrentFrameIndex(index);
|
||||
this.piskelController.setCurrentFrameIndex(index);
|
||||
}
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.onDeleteButtonClick_ = function (index, evt) {
|
||||
this.framesheet.removeFrameByIndex(index);
|
||||
this.piskelController.removeFrameAt(index);
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.onAddButtonClick_ = function (index, evt) {
|
||||
this.framesheet.duplicateFrameByIndex(index);
|
||||
this.piskelController.duplicateFrameAt(index);
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model
|
||||
this.framesheet.setCurrentFrameIndex(index + 1);
|
||||
this.piskelController.setCurrentFrameIndex(index + 1);
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the preview DPI depending on the framesheet size
|
||||
* Calculate the preview DPI depending on the piskel size
|
||||
*/
|
||||
ns.PreviewFilmController.prototype.calculateDPI_ = function () {
|
||||
var curFrame = this.framesheet.getCurrentFrame(),
|
||||
var curFrame = this.piskelController.getCurrentFrame(),
|
||||
frameHeight = curFrame.getHeight(),
|
||||
frameWidth = curFrame.getWidth(),
|
||||
maxFrameDim = Math.max(frameWidth, frameHeight);
|
||||
|
@ -15,8 +15,8 @@
|
||||
var SEL_SETTING_CLS = 'has-expanded-drawer';
|
||||
var EXP_DRAWER_CLS = 'expanded';
|
||||
|
||||
ns.SettingsController = function (framesheet) {
|
||||
this.framesheet = framesheet;
|
||||
ns.SettingsController = function (piskelController) {
|
||||
this.piskelController = piskelController;
|
||||
this.drawerContainer = document.getElementById("drawer-container");
|
||||
this.settingsContainer = $('[data-pskl-controller=settings]');
|
||||
this.expanded = false;
|
||||
@ -48,7 +48,7 @@
|
||||
|
||||
ns.SettingsController.prototype.loadSetting = function (setting) {
|
||||
this.drawerContainer.innerHTML = pskl.utils.Template.get(settings[setting].template);
|
||||
(new settings[setting].controller(this.framesheet)).init();
|
||||
(new settings[setting].controller(this.piskelController)).init();
|
||||
|
||||
this.settingsContainer.addClass(EXP_DRAWER_CLS);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller.settings");
|
||||
ns.GifExportController = function (framesheet) {
|
||||
this.framesheet = framesheet;
|
||||
ns.GifExportController = function (piskelController) {
|
||||
this.piskelController = piskelController;
|
||||
};
|
||||
|
||||
ns.GifExportController.prototype.init = function () {
|
||||
@ -61,7 +61,7 @@
|
||||
};
|
||||
|
||||
ns.GifExportController.prototype.createRadioForDpi_ = function (dpi, template) {
|
||||
var label = dpi[0]*this.framesheet.getWidth() + "x" + dpi[0]*this.framesheet.getHeight();
|
||||
var label = dpi[0]*this.piskelController.getWidth() + "x" + dpi[0]*this.piskelController.getHeight();
|
||||
var value = dpi[0];
|
||||
var radioHTML = pskl.utils.Template.replace(template, {value : value, label : label});
|
||||
var radio = pskl.utils.Template.createFromHTML(radioHTML);
|
||||
@ -86,12 +86,12 @@
|
||||
var gif = new window.GIF({
|
||||
workers: 2,
|
||||
quality: 10,
|
||||
width: this.framesheet.getWidth()*dpi,
|
||||
height: this.framesheet.getHeight()*dpi
|
||||
width: this.piskelController.getWidth()*dpi,
|
||||
height: this.piskelController.getHeight()*dpi
|
||||
});
|
||||
|
||||
for (var i = 0; i < this.framesheet.frames.length; i++) {
|
||||
var frame = this.framesheet.frames[i];
|
||||
for (var i = 0; i < this.piskelController.getFrameCount(); i++) {
|
||||
var frame = this.piskelController.getFrameAt(i);
|
||||
var renderer = new pskl.rendering.CanvasRenderer(frame, dpi);
|
||||
gif.addFrame(renderer.render(), {
|
||||
delay: 1000 / fps
|
||||
|
@ -1,15 +1,28 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.model");
|
||||
|
||||
ns.Frame = function (pixels) {
|
||||
this.pixels = pixels;
|
||||
ns.Frame = function (width, height) {
|
||||
if (width && height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.pixels = ns.Frame.createEmptyPixelGrid_(width, height);
|
||||
this.previousStates = [this.getPixels()];
|
||||
this.stateIndex = 0;
|
||||
} else {
|
||||
throw 'Bad arguments in pskl.model.Frame constructor : ' + width + ', ' + height;
|
||||
}
|
||||
};
|
||||
|
||||
ns.Frame.createEmpty = function (width, height) {
|
||||
var pixels = ns.Frame.createEmptyPixelGrid_(width, height);
|
||||
return new ns.Frame(pixels);
|
||||
ns.Frame.fromPixelGrid = function (pixels) {
|
||||
if (pixels.length && pixels[0].length) {
|
||||
var w = pixels.length, h = pixels[0].length;
|
||||
var frame = new pskl.model.Frame(w, h);
|
||||
frame.setPixels(pixels);
|
||||
return frame;
|
||||
} else {
|
||||
throw 'Bad arguments in pskl.model.Frame.fromPixelGrid : ' + pixels;
|
||||
}
|
||||
};
|
||||
|
||||
ns.Frame.createEmptyPixelGrid_ = function (width, height) {
|
||||
@ -25,11 +38,13 @@
|
||||
};
|
||||
|
||||
ns.Frame.createEmptyFromFrame = function (frame) {
|
||||
return ns.Frame.createEmpty(frame.getWidth(), frame.getHeight());
|
||||
return new ns.Frame(frame.getWidth(), frame.getHeight());
|
||||
};
|
||||
|
||||
ns.Frame.prototype.clone = function () {
|
||||
return new ns.Frame(this.getPixels());
|
||||
var clone = new ns.Frame(this.width, this.height);
|
||||
clone.setPixels(this.getPixels());
|
||||
return clone;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -46,8 +61,6 @@
|
||||
this.pixels = this.clonePixels_(pixels);
|
||||
};
|
||||
|
||||
|
||||
|
||||
ns.Frame.prototype.clear = function () {
|
||||
var pixels = ns.Frame.createEmptyPixelGrid_(this.getWidth(), this.getHeight());
|
||||
this.setPixels(pixels);
|
||||
@ -77,12 +90,20 @@
|
||||
return this.pixels[col][row];
|
||||
};
|
||||
|
||||
ns.Frame.prototype.forEachPixel = function (callback) {
|
||||
for (var col = 0 ; col < this.getWidth() ; col++) {
|
||||
for (var row = 0 ; row < this.getHeight() ; row++) {
|
||||
callback(this.getPixel(col, row), col, row);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ns.Frame.prototype.getWidth = function () {
|
||||
return this.pixels.length;
|
||||
return this.width;
|
||||
};
|
||||
|
||||
ns.Frame.prototype.getHeight = function () {
|
||||
return this.pixels[0].length;
|
||||
return this.height;
|
||||
};
|
||||
|
||||
ns.Frame.prototype.containsPixel = function (col, row) {
|
||||
|
@ -23,14 +23,14 @@
|
||||
this.frames.push(frame);
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.getFrameCount = function () {
|
||||
return this.frames.length;
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.getCurrentFrame = function () {
|
||||
return this.frames[this.currentFrameIndex];
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.getFrameCount = function () {
|
||||
return this.frames.length;
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.setCurrentFrameIndex = function (index) {
|
||||
this.currentFrameIndex = index;
|
||||
$.publish(Events.CURRENT_FRAME_SET, [this.getCurrentFrame()]);
|
||||
@ -101,7 +101,7 @@
|
||||
|
||||
|
||||
ns.FrameSheet.prototype.hasFrameAtIndex = function(index) {
|
||||
return (index >= 0 && index < this.getFrameCount());
|
||||
return (index >= 0 && index < this.frames.length);
|
||||
};
|
||||
|
||||
ns.FrameSheet.prototype.getFrameByIndex = function(index) {
|
||||
@ -122,10 +122,9 @@
|
||||
}
|
||||
this.frames.splice(index, 1);
|
||||
|
||||
// Current frame index might not be valid anymore
|
||||
if (!this.hasFrameAtIndex(this.currentFrameIndex)) {
|
||||
// if not select last frame available
|
||||
this.setCurrentFrameIndex(this.getFrameCount() - 1);
|
||||
// Current frame index is impacted if the removed frame was before the current frame
|
||||
if (this.currentFrameIndex >= index) {
|
||||
this.setCurrentFrameIndex(this.currentFrameIndex - 1);
|
||||
}
|
||||
|
||||
$.publish(Events.FRAMESHEET_RESET);
|
||||
|
82
js/model/Layer.js
Normal file
82
js/model/Layer.js
Normal file
@ -0,0 +1,82 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.model');
|
||||
|
||||
ns.Layer = function (name) {
|
||||
if (!name) {
|
||||
throw 'Invalid arguments in Layer constructor : \'name\' is mandatory';
|
||||
} else {
|
||||
this.name = name;
|
||||
this.frames = [];
|
||||
}
|
||||
};
|
||||
|
||||
ns.Layer.prototype.getName = function () {
|
||||
return this.name;
|
||||
};
|
||||
|
||||
ns.Layer.prototype.getFrames = function () {
|
||||
return this.frames;
|
||||
};
|
||||
|
||||
ns.Layer.prototype.getFrameAt = function (index) {
|
||||
return this.frames[index];
|
||||
};
|
||||
|
||||
ns.Layer.prototype.addFrame = function (frame) {
|
||||
this.frames.push(frame);
|
||||
};
|
||||
|
||||
ns.Layer.prototype.addFrameAt = function (frame, index) {
|
||||
this.frames.splice(index, 0, frame);
|
||||
};
|
||||
|
||||
ns.Layer.prototype.removeFrame = function (frame) {
|
||||
var index = this.frames.indexOf(frame);
|
||||
this.removeFrameAt(index);
|
||||
};
|
||||
|
||||
ns.Layer.prototype.removeFrameAt = function (index) {
|
||||
if (this.frames[index]) {
|
||||
this.frames.splice(index, 1);
|
||||
} else {
|
||||
throw 'Invalid index in removeFrameAt : ' + index + ' (size : ' + this.length() + ')';
|
||||
}
|
||||
};
|
||||
|
||||
ns.Layer.prototype.moveFrame = function (fromIndex, toIndex) {
|
||||
var frame = this.frames.splice(fromIndex, 1)[0];
|
||||
this.frames.splice(toIndex, 0, frame);
|
||||
};
|
||||
|
||||
ns.Layer.prototype.swapFramesAt = function (fromIndex, toIndex) {
|
||||
var fromFrame = this.frames[fromIndex];
|
||||
var toFrame = this.frames[toIndex];
|
||||
if (fromFrame && toFrame) {
|
||||
this.frames[toIndex] = fromFrame;
|
||||
this.frames[fromIndex] = toFrame;
|
||||
} else {
|
||||
console.log('frames', this.frames);
|
||||
console.log('fromIndex', fromIndex, 'toIndex', toIndex);
|
||||
throw 'Frame not found in moveFrameAt';
|
||||
}
|
||||
};
|
||||
|
||||
ns.Layer.prototype.duplicateFrame = function (frame) {
|
||||
var index = this.frames.indexOf(frame);
|
||||
this.duplicateFrameAt();
|
||||
};
|
||||
|
||||
ns.Layer.prototype.duplicateFrameAt = function (index) {
|
||||
var frame = this.frames[index];
|
||||
if (frame) {
|
||||
var clone = frame.clone();
|
||||
this.addFrameAt(clone, index);
|
||||
} else {
|
||||
throw 'Frame not found in duplicateFrameAt';
|
||||
}
|
||||
};
|
||||
|
||||
ns.Layer.prototype.length = function () {
|
||||
return this.frames.length;
|
||||
};
|
||||
})();
|
66
js/model/Piskel.js
Normal file
66
js/model/Piskel.js
Normal file
@ -0,0 +1,66 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.model');
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Number} width
|
||||
* @param {Number} height
|
||||
*/
|
||||
ns.Piskel = function (width, height, fps) {
|
||||
if (width && height && fps) {
|
||||
/** @type {Array} */
|
||||
this.layers = [];
|
||||
|
||||
/** @type {Number} */
|
||||
this.fps = fps;
|
||||
|
||||
/** @type {Number} */
|
||||
this.width = width;
|
||||
|
||||
/** @type {Number} */
|
||||
this.height = height;
|
||||
} else {
|
||||
throw 'Missing arguments in Piskel constructor : ' + Array.prototype.join.call(arguments, ",");
|
||||
}
|
||||
};
|
||||
|
||||
ns.Piskel.prototype.getLayers = function () {
|
||||
return this.layers;
|
||||
};
|
||||
|
||||
ns.Piskel.prototype.getHeight = function () {
|
||||
return this.height;
|
||||
};
|
||||
|
||||
ns.Piskel.prototype.getWidth = function () {
|
||||
return this.width;
|
||||
};
|
||||
|
||||
ns.Piskel.prototype.getFps = function () {
|
||||
return this.fps;
|
||||
};
|
||||
|
||||
ns.Piskel.prototype.getLayers = function () {
|
||||
return this.layers;
|
||||
};
|
||||
|
||||
ns.Piskel.prototype.getLayerAt = function (index) {
|
||||
return this.layers[index];
|
||||
};
|
||||
|
||||
ns.Piskel.prototype.addLayer = function (layer) {
|
||||
this.layers.push(layer);
|
||||
};
|
||||
|
||||
ns.Piskel.prototype.removeLayer = function (layer) {
|
||||
var index = this.layers.indexOf(layer);
|
||||
if (index != -1) {
|
||||
this.layers.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
ns.Piskel.prototype.removeLayerAt = function (index) {
|
||||
this.layers.splice(index, 1);
|
||||
};
|
||||
|
||||
})();
|
@ -2,15 +2,15 @@
|
||||
|
||||
var ns = $.namespace("pskl.rendering");
|
||||
|
||||
ns.SpritesheetRenderer = function (framesheet) {
|
||||
this.framesheet = framesheet;
|
||||
ns.SpritesheetRenderer = function (piskelController) {
|
||||
this.piskelController = piskelController;
|
||||
};
|
||||
|
||||
ns.SpritesheetRenderer.prototype.renderAsImageDataSpritesheetPNG = function () {
|
||||
var canvas = this.createCanvas_();
|
||||
for (var i = 0 ; i < this.framesheet.getFrameCount() ; i++) {
|
||||
var frame = this.framesheet.getFrameByIndex(i);
|
||||
this.drawFrameInCanvas_(frame, canvas, i * this.framesheet.getWidth(), 0);
|
||||
for (var i = 0 ; i < this.piskelController.getFrameCount() ; i++) {
|
||||
var frame = this.piskelController.getFrameAt(i);
|
||||
this.drawFrameInCanvas_(frame, canvas, i * this.piskelController.getWidth(), 0);
|
||||
}
|
||||
return canvas.toDataURL("image/png");
|
||||
};
|
||||
@ -32,10 +32,10 @@
|
||||
};
|
||||
|
||||
ns.SpritesheetRenderer.prototype.createCanvas_ = function () {
|
||||
var frameCount = this.framesheet.getFrameCount();
|
||||
var frameCount = this.piskelController.getFrameCount();
|
||||
if (frameCount > 0){
|
||||
var width = frameCount * this.framesheet.getWidth();
|
||||
var height = this.framesheet.getHeight();
|
||||
var width = frameCount * this.piskelController.getWidth();
|
||||
var height = this.piskelController.getHeight();
|
||||
return pskl.CanvasUtils.createCanvas(width, height);
|
||||
} else {
|
||||
throw "Cannot render empty Spritesheet";
|
||||
|
@ -1,9 +1,9 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.selection");
|
||||
|
||||
ns.SelectionManager = function (framesheet) {
|
||||
ns.SelectionManager = function (piskelController) {
|
||||
|
||||
this.framesheet = framesheet;
|
||||
this.piskelController = piskelController;
|
||||
|
||||
this.currentSelection = null;
|
||||
};
|
||||
@ -52,10 +52,10 @@
|
||||
ns.SelectionManager.prototype.onCut_ = function(evt) {
|
||||
if(this.currentSelection) {
|
||||
// Put cut target into the selection:
|
||||
this.currentSelection.fillSelectionFromFrame(this.framesheet.getCurrentFrame());
|
||||
this.currentSelection.fillSelectionFromFrame(this.piskelController.getCurrentFrame());
|
||||
|
||||
var pixels = this.currentSelection.pixels;
|
||||
var currentFrame = this.framesheet.getCurrentFrame();
|
||||
var currentFrame = this.piskelController.getCurrentFrame();
|
||||
for(var i=0, l=pixels.length; i<l; i++) {
|
||||
try {
|
||||
currentFrame.setPixel(pixels[i].col, pixels[i].row, Constants.TRANSPARENT_COLOR);
|
||||
@ -73,7 +73,7 @@
|
||||
ns.SelectionManager.prototype.onPaste_ = function(evt) {
|
||||
if(this.currentSelection && this.currentSelection.hasPastedContent) {
|
||||
var pixels = this.currentSelection.pixels;
|
||||
var currentFrame = this.framesheet.getCurrentFrame();
|
||||
var currentFrame = this.piskelController.getCurrentFrame();
|
||||
for(var i=0, l=pixels.length; i<l; i++) {
|
||||
try {
|
||||
currentFrame.setPixel(
|
||||
@ -91,8 +91,8 @@
|
||||
* @private
|
||||
*/
|
||||
ns.SelectionManager.prototype.onCopy_ = function(evt) {
|
||||
if(this.currentSelection && this.framesheet.getCurrentFrame()) {
|
||||
this.currentSelection.fillSelectionFromFrame(this.framesheet.getCurrentFrame());
|
||||
if(this.currentSelection && this.piskelController.getCurrentFrame()) {
|
||||
this.currentSelection.fillSelectionFromFrame(this.piskelController.getCurrentFrame());
|
||||
}
|
||||
else {
|
||||
throw "Bad state for CUT callback in SelectionManager";
|
||||
|
@ -1,7 +1,7 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.service");
|
||||
ns.HistoryService = function (framesheet) {
|
||||
this.framesheet = framesheet;
|
||||
ns.HistoryService = function (piskelController) {
|
||||
this.piskelController = piskelController;
|
||||
};
|
||||
|
||||
ns.HistoryService.prototype.init = function () {
|
||||
@ -12,16 +12,16 @@
|
||||
};
|
||||
|
||||
ns.HistoryService.prototype.saveState = function () {
|
||||
this.framesheet.getCurrentFrame().saveState();
|
||||
this.piskelController.getCurrentFrame().saveState();
|
||||
};
|
||||
|
||||
ns.HistoryService.prototype.undo = function () {
|
||||
this.framesheet.getCurrentFrame().loadPreviousState();
|
||||
this.piskelController.getCurrentFrame().loadPreviousState();
|
||||
$.publish(Events.FRAMESHEET_RESET);
|
||||
};
|
||||
|
||||
ns.HistoryService.prototype.redo = function () {
|
||||
this.framesheet.getCurrentFrame().loadNextState();
|
||||
this.piskelController.getCurrentFrame().loadNextState();
|
||||
$.publish(Events.FRAMESHEET_RESET);
|
||||
};
|
||||
|
||||
|
@ -1,19 +1,19 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.service");
|
||||
|
||||
ns.LocalStorageService = function (framesheet_) {
|
||||
ns.LocalStorageService = function (piskelController) {
|
||||
|
||||
if(framesheet_ === undefined) {
|
||||
throw "Bad LocalStorageService initialization: <undefined frameSheet>";
|
||||
if(piskelController === undefined) {
|
||||
throw "Bad LocalStorageService initialization: <undefined piskelController>";
|
||||
}
|
||||
this.framesheet = framesheet_;
|
||||
this.piskelController = piskelController;
|
||||
this.localStorageThrottler_ = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.LocalStorageService.prototype.init = function(framesheet_) {
|
||||
ns.LocalStorageService.prototype.init = function(piskelController) {
|
||||
$.subscribe(Events.LOCALSTORAGE_REQUEST, $.proxy(this.persistToLocalStorageRequest_, this));
|
||||
};
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
ns.LocalStorageService.prototype.persistToLocalStorage_ = function() {
|
||||
|
||||
console.log('[LocalStorage service]: Snapshot stored');
|
||||
window.localStorage.snapShot = this.framesheet.serialize();
|
||||
window.localStorage.snapShot = this.piskelController.serialize();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -46,8 +46,8 @@
|
||||
*/
|
||||
ns.LocalStorageService.prototype.restoreFromLocalStorage_ = function() {
|
||||
|
||||
this.framesheet.deserialize(window.localStorage.snapShot);
|
||||
this.framesheet.setCurrentFrameIndex(0);
|
||||
this.piskelController.deserialize(window.localStorage.snapShot);
|
||||
this.piskelController.setCurrentFrameIndex(0);
|
||||
};
|
||||
|
||||
/**
|
||||
|
22
js/utils/FrameUtils.js
Normal file
22
js/utils/FrameUtils.js
Normal file
@ -0,0 +1,22 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.utils');
|
||||
|
||||
ns.FrameUtils = {
|
||||
merge : function (frames) {
|
||||
var merged = frames[0].clone();
|
||||
var w = merged.getWidth(), h = merged.getHeight();
|
||||
for (var i = 1 ; i < frames.length ; i++) {
|
||||
pskl.utils.FrameUtils.mergeFrames_(merged, frames[i]);
|
||||
}
|
||||
return merged;
|
||||
},
|
||||
|
||||
mergeFrames_ : function (frameA, frameB) {
|
||||
frameB.forEachPixel(function (p, col, row) {
|
||||
if (p != Constants.TRANSPARENT_COLOR) {
|
||||
frameA.setPixel(col, row, p);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
})();
|
64
js/utils/Serializer.js
Normal file
64
js/utils/Serializer.js
Normal file
@ -0,0 +1,64 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.utils');
|
||||
ns.Serializer = {
|
||||
serializePiskel : function (piskel) {
|
||||
var serializedLayers = piskel.getLayers().map(function (l) {
|
||||
return pskl.utils.Serializer.serializeLayer(l);
|
||||
});
|
||||
return JSON.stringify({
|
||||
modelVersion : Constants.MODEL_VERSION,
|
||||
piskel : {
|
||||
height : piskel.getHeight(),
|
||||
width : piskel.getWidth(),
|
||||
fps : piskel.getFps(),
|
||||
layers : serializedLayers
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
serializeLayer : function (layer) {
|
||||
var serializedFrames = layer.getFrames().map(function (f) {
|
||||
return f.serialize();
|
||||
});
|
||||
return JSON.stringify({
|
||||
name : layer.getName(),
|
||||
frames : serializedFrames
|
||||
});
|
||||
},
|
||||
|
||||
deserializePiskel : function (json) {
|
||||
var data = JSON.parse(json);
|
||||
if (data.modelVersion == Constants.MODEL_VERSION) {
|
||||
var pData = data.piskel;
|
||||
var layers = pData.layers.map(function (serializedLayer) {
|
||||
return pskl.utils.Serializer.deserializeLayer(serializedLayer);
|
||||
});
|
||||
var piskel = new pskl.model.Piskel(pData.width, pData.height, pData.fps);
|
||||
layers.forEach(function (layer) {
|
||||
piskel.addLayer(layer);
|
||||
});
|
||||
return piskel;
|
||||
} else {
|
||||
// pre-layer implementation adapter
|
||||
}
|
||||
},
|
||||
|
||||
deserializeLayer : function (json) {
|
||||
var lData = JSON.parse(json);
|
||||
var frames = lData.frames.map(function (serializedFrame) {
|
||||
return pskl.utils.Serializer.deserializeFrame(serializedFrame);
|
||||
});
|
||||
|
||||
var layer = new pskl.model.Layer(lData.name);
|
||||
frames.forEach(function (frame) {
|
||||
layer.addFrame(frame);
|
||||
});
|
||||
return layer;
|
||||
},
|
||||
|
||||
deserializeFrame : function (json) {
|
||||
var framePixelGrid = JSON.parse(json);
|
||||
return pskl.model.Frame.fromPixelGrid(framePixelGrid);
|
||||
}
|
||||
};
|
||||
})();
|
@ -13,9 +13,11 @@ exports.scripts = [
|
||||
|
||||
// Libraries
|
||||
"js/utils/core.js",
|
||||
"js/utils/Template.js",
|
||||
"js/utils/PixelUtils.js",
|
||||
"js/utils/CanvasUtils.js",
|
||||
"js/utils/FrameUtils.js",
|
||||
"js/utils/PixelUtils.js",
|
||||
"js/utils/Serializer.js",
|
||||
"js/utils/Template.js",
|
||||
"js/utils/UserSettings.js",
|
||||
"js/lib/jsColor_1_4_0/jscolor.js",
|
||||
|
||||
@ -24,7 +26,10 @@ exports.scripts = [
|
||||
|
||||
// Models
|
||||
"js/model/Frame.js",
|
||||
"js/model/FrameSheet.js",
|
||||
"js/model/Layer.js",
|
||||
"js/model/Piskel.js",
|
||||
|
||||
// Selection
|
||||
"js/selection/SelectionManager.js",
|
||||
"js/selection/BaseSelection.js",
|
||||
"js/selection/RectangularSelection.js",
|
||||
@ -36,6 +41,7 @@ exports.scripts = [
|
||||
"js/rendering/SpritesheetRenderer.js",
|
||||
|
||||
// Controllers
|
||||
"js/controller/PiskelController.js",
|
||||
"js/controller/DrawingController.js",
|
||||
"js/controller/PreviewFilmController.js",
|
||||
"js/controller/AnimatedPreviewController.js",
|
||||
@ -68,5 +74,5 @@ exports.scripts = [
|
||||
"js/drawingtools/ColorPicker.js",
|
||||
|
||||
// Application controller and initialization
|
||||
"js/piskel.js"
|
||||
"js/app.js"
|
||||
];
|
@ -8,8 +8,8 @@
|
||||
<input id="secondary-color-picker" class="secondary-color-picker color {hash:true}" type="text" value="" />
|
||||
</div>
|
||||
<div class="tool-icon tool-palette">
|
||||
<div id="palette" class="palette">
|
||||
<span class="tool-icon palette-color transparent-color" data-color="TRANSPARENT" title="Transparent"></span>
|
||||
<div>
|
||||
<span class="tool-icon palette-color" data-color="TRANSPARENT" title="Transparent"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user