2012-08-31 12:45:07 +04:00
|
|
|
/**
|
|
|
|
* @require Constants
|
|
|
|
* @require Events
|
|
|
|
*/
|
|
|
|
(function () {
|
2013-07-15 01:04:42 +04:00
|
|
|
var ns = $.namespace("pskl");
|
2012-09-03 03:24:55 +04:00
|
|
|
/**
|
|
|
|
* Main application controller
|
|
|
|
*/
|
2013-07-15 01:04:42 +04:00
|
|
|
ns.app = {
|
2012-09-03 03:24:55 +04:00
|
|
|
|
2012-08-23 02:57:35 +04:00
|
|
|
init : function () {
|
2013-11-20 02:46:33 +04:00
|
|
|
this.shortcutService = new pskl.service.keyboard.ShortcutService();
|
|
|
|
this.shortcutService.init();
|
|
|
|
|
2013-09-22 23:02:43 +04:00
|
|
|
var size = this.readSizeFromURL_();
|
2013-10-01 00:00:31 +04:00
|
|
|
var piskel = new pskl.model.Piskel(size.width, size.height);
|
2013-07-15 01:04:42 +04:00
|
|
|
|
2013-09-26 00:43:21 +04:00
|
|
|
var layer = new pskl.model.Layer("Layer 1");
|
2013-09-22 23:02:43 +04:00
|
|
|
var frame = new pskl.model.Frame(size.width, size.height);
|
|
|
|
layer.addFrame(frame);
|
2013-08-04 20:27:32 +04:00
|
|
|
|
2013-09-22 23:02:43 +04:00
|
|
|
piskel.addLayer(layer);
|
|
|
|
|
|
|
|
this.piskelController = new pskl.controller.PiskelController(piskel);
|
2013-11-20 02:46:33 +04:00
|
|
|
this.piskelController.init();
|
2013-09-22 23:02:43 +04:00
|
|
|
|
2013-11-19 10:40:35 +04:00
|
|
|
this.paletteController = new pskl.controller.PaletteController();
|
|
|
|
this.paletteController.init();
|
2013-09-22 23:02:43 +04:00
|
|
|
|
2013-11-19 10:40:35 +04:00
|
|
|
this.drawingController = new pskl.controller.DrawingController(this.piskelController, this.paletteController, $('#drawing-canvas-container'));
|
2013-08-06 01:34:11 +04:00
|
|
|
this.drawingController.init();
|
2012-09-12 14:01:47 +04:00
|
|
|
|
2013-09-22 23:02:43 +04:00
|
|
|
this.animationController = new pskl.controller.AnimatedPreviewController(this.piskelController, $('#preview-canvas-container'));
|
2012-09-05 02:09:42 +04:00
|
|
|
this.animationController.init();
|
2013-09-30 23:22:58 +04:00
|
|
|
|
2013-11-02 02:11:11 +04:00
|
|
|
this.minimapController = new pskl.controller.MinimapController(this.piskelController, this.animationController, this.drawingController, $('#preview-canvas-container'));
|
|
|
|
this.minimapController.init();
|
|
|
|
|
2013-09-22 23:02:43 +04:00
|
|
|
this.previewsController = new pskl.controller.PreviewFilmController(this.piskelController, $('#preview-list'));
|
2012-09-05 02:09:42 +04:00
|
|
|
this.previewsController.init();
|
2013-09-30 23:22:58 +04:00
|
|
|
|
|
|
|
this.layersListController = new pskl.controller.LayersListController(this.piskelController);
|
|
|
|
this.layersListController.init();
|
2013-08-06 01:34:11 +04:00
|
|
|
|
2013-10-11 02:04:40 +04:00
|
|
|
this.settingsController = new pskl.controller.settings.SettingsController(this.piskelController);
|
2013-06-16 12:17:50 +04:00
|
|
|
this.settingsController.init();
|
2012-09-07 02:18:59 +04:00
|
|
|
|
2013-11-20 02:46:33 +04:00
|
|
|
this.toolController = new pskl.controller.ToolController();
|
|
|
|
this.toolController.init();
|
|
|
|
|
2013-09-22 23:02:43 +04:00
|
|
|
this.selectionManager = new pskl.selection.SelectionManager(this.piskelController);
|
2013-08-06 01:34:11 +04:00
|
|
|
this.selectionManager.init();
|
|
|
|
|
2013-09-22 23:02:43 +04:00
|
|
|
this.historyService = new pskl.service.HistoryService(this.piskelController);
|
2012-09-16 15:10:05 +04:00
|
|
|
this.historyService.init();
|
2012-09-11 01:26:12 +04:00
|
|
|
|
2012-09-16 16:41:47 +04:00
|
|
|
this.notificationController = new pskl.controller.NotificationController();
|
|
|
|
this.notificationController.init();
|
2012-09-16 15:50:40 +04:00
|
|
|
|
2013-09-22 23:02:43 +04:00
|
|
|
this.localStorageService = new pskl.service.LocalStorageService(this.piskelController);
|
2012-09-16 14:59:19 +04:00
|
|
|
this.localStorageService.init();
|
2012-09-03 03:24:55 +04:00
|
|
|
|
2013-09-07 19:50:43 +04:00
|
|
|
this.imageUploadService = new pskl.service.ImageUploadService();
|
|
|
|
this.imageUploadService.init();
|
|
|
|
|
2013-09-30 23:22:58 +04:00
|
|
|
|
2013-11-19 02:53:12 +04:00
|
|
|
this.cheatsheetService = new pskl.service.keyboard.CheatsheetService();
|
|
|
|
this.cheatsheetService.init();
|
|
|
|
|
2013-08-06 01:34:11 +04:00
|
|
|
|
|
|
|
var drawingLoop = new pskl.rendering.DrawingLoop();
|
|
|
|
drawingLoop.addCallback(this.render, this);
|
|
|
|
drawingLoop.start();
|
|
|
|
|
2013-09-22 23:02:43 +04:00
|
|
|
this.initBootstrapTooltips_();
|
2013-09-30 23:22:58 +04:00
|
|
|
|
2013-08-06 01:34:11 +04:00
|
|
|
/**
|
|
|
|
* 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_;
|
|
|
|
|
2013-07-15 01:04:42 +04:00
|
|
|
if (this.isStaticVersion) {
|
2013-10-10 02:06:11 +04:00
|
|
|
this.finishInitStatic_();
|
2012-08-30 03:16:13 +04:00
|
|
|
} else {
|
2013-10-10 02:06:11 +04:00
|
|
|
this.finishInitAppEngine_();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
finishInitStatic_ : function () {
|
|
|
|
var framesheetId = this.readFramesheetIdFromURL_();
|
|
|
|
if (framesheetId) {
|
|
|
|
$.publish(Events.SHOW_NOTIFICATION, [{
|
|
|
|
"content" : "Loading animation with id : [" + framesheetId + "]"
|
|
|
|
}]);
|
|
|
|
this.loadFramesheetFromService(framesheetId);
|
|
|
|
} else {
|
|
|
|
this.localStorageService.displayRestoreNotification();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
finishInitAppEngine_ : function () {
|
|
|
|
if (pskl.framesheetData_ && pskl.framesheetData_.content) {
|
2013-11-15 03:03:05 +04:00
|
|
|
pskl.utils.serialization.Deserializer.deserialize(pskl.framesheetData_.content, function (piskel) {
|
2013-11-14 02:39:43 +04:00
|
|
|
pskl.app.piskelController.setPiskel(piskel);
|
|
|
|
pskl.app.animationController.setFPS(pskl.framesheetData_.fps);
|
|
|
|
});
|
2012-08-30 03:16:13 +04:00
|
|
|
}
|
2012-09-09 01:59:44 +04:00
|
|
|
},
|
|
|
|
|
2013-09-22 23:02:43 +04:00
|
|
|
initBootstrapTooltips_ : function () {
|
|
|
|
$('body').tooltip({
|
|
|
|
selector: '[rel=tooltip]'
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2012-09-09 01:59:44 +04:00
|
|
|
render : function (delta) {
|
|
|
|
this.drawingController.render(delta);
|
|
|
|
this.animationController.render(delta);
|
|
|
|
this.previewsController.render(delta);
|
2013-08-04 20:27:32 +04:00
|
|
|
},
|
2013-09-30 23:22:58 +04:00
|
|
|
|
2012-09-16 20:48:32 +04:00
|
|
|
readSizeFromURL_ : function () {
|
2013-08-04 20:27:32 +04:00
|
|
|
var sizeParam = this.readUrlParameter_("size"),
|
|
|
|
size;
|
2012-09-16 20:48:32 +04:00
|
|
|
// parameter expected as size=64x48 => size=widthxheight
|
|
|
|
var parts = sizeParam.split("x");
|
|
|
|
if (parts && parts.length == 2 && !isNaN(parts[0]) && !isNaN(parts[1])) {
|
|
|
|
var width = parseInt(parts[0], 10),
|
2013-08-04 20:27:32 +04:00
|
|
|
height = parseInt(parts[1], 10);
|
|
|
|
|
2012-09-16 20:48:32 +04:00
|
|
|
size = {
|
|
|
|
height : Math.min(height, Constants.MAX_HEIGHT),
|
2012-09-17 01:47:37 +04:00
|
|
|
width : Math.min(width, Constants.MAX_WIDTH)
|
2012-09-16 20:48:32 +04:00
|
|
|
};
|
|
|
|
} else {
|
2013-09-22 23:02:43 +04:00
|
|
|
size = {
|
|
|
|
height : Constants.DEFAULT.HEIGHT,
|
|
|
|
width : Constants.DEFAULT.WIDTH
|
|
|
|
};
|
2012-09-16 20:48:32 +04:00
|
|
|
}
|
|
|
|
return size;
|
|
|
|
},
|
|
|
|
|
2013-08-04 20:27:32 +04:00
|
|
|
readFramesheetIdFromURL_ : function () {
|
2012-09-16 20:48:32 +04:00
|
|
|
return this.readUrlParameter_("frameId");
|
|
|
|
},
|
|
|
|
|
|
|
|
readUrlParameter_ : function (paramName) {
|
|
|
|
var searchString = window.location.search.substring(1),
|
2013-08-04 20:27:32 +04:00
|
|
|
i, val, params = searchString.split("&");
|
2012-09-16 20:48:32 +04:00
|
|
|
|
2013-08-04 20:27:32 +04:00
|
|
|
for (i = 0; i < params.length; i++) {
|
2012-09-16 20:48:32 +04:00
|
|
|
val = params[i].split("=");
|
|
|
|
if (val[0] == paramName) {
|
2013-08-10 16:28:10 +04:00
|
|
|
return window.unescape(val[1]);
|
2012-09-16 20:48:32 +04:00
|
|
|
}
|
2012-08-30 03:16:13 +04:00
|
|
|
}
|
2012-09-16 20:48:32 +04:00
|
|
|
return "";
|
2012-08-30 03:16:13 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
loadFramesheetFromService : function (frameId) {
|
|
|
|
var xhr = new XMLHttpRequest();
|
2013-10-10 02:06:11 +04:00
|
|
|
xhr.open('GET', Constants.STATIC.URL.GET + '?l=' + frameId, true);
|
2012-08-30 03:16:13 +04:00
|
|
|
xhr.responseType = 'text';
|
2013-08-04 20:27:32 +04:00
|
|
|
xhr.onload = function (e) {
|
2012-09-21 01:57:26 +04:00
|
|
|
var res = JSON.parse(this.responseText);
|
2013-11-15 03:03:05 +04:00
|
|
|
pskl.utils.serialization.Deserializer.deserialize(res.framesheet, function (piskel) {
|
2013-11-14 02:39:43 +04:00
|
|
|
pskl.app.piskelController.setPiskel(piskel);
|
|
|
|
pskl.app.animationController.setFPS(res.fps);
|
|
|
|
$.publish(Events.HIDE_NOTIFICATION);
|
|
|
|
});
|
2012-08-30 03:16:13 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
xhr.onerror = function () {
|
2012-09-03 03:24:55 +04:00
|
|
|
$.publish(Events.HIDE_NOTIFICATION);
|
2012-08-30 03:16:13 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
xhr.send();
|
2012-08-30 01:32:51 +04:00
|
|
|
},
|
2012-08-30 01:01:04 +04:00
|
|
|
|
2013-10-10 02:06:11 +04:00
|
|
|
storeSheet : function (event) {
|
|
|
|
if (this.isStaticVersion) {
|
|
|
|
this.storeSheetStatic_();
|
|
|
|
} else {
|
|
|
|
this.storeSheetAppEngine_();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(event) {
|
|
|
|
event.stopPropagation();
|
|
|
|
event.preventDefault();
|
|
|
|
}
|
|
|
|
return false;
|
2013-07-15 01:04:42 +04:00
|
|
|
},
|
|
|
|
|
2013-10-10 02:06:11 +04:00
|
|
|
storeSheetStatic_ : function () {
|
2012-08-30 03:16:13 +04:00
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
var formData = new FormData();
|
2013-09-22 23:02:43 +04:00
|
|
|
formData.append('framesheet_content', this.piskelController.serialize());
|
2012-08-31 12:45:07 +04:00
|
|
|
formData.append('fps_speed', $('#preview-fps').val());
|
2013-07-15 01:04:42 +04:00
|
|
|
|
2013-10-10 02:06:11 +04:00
|
|
|
xhr.open('POST', Constants.STATIC.URL.SAVE, true);
|
2013-09-30 23:22:58 +04:00
|
|
|
|
2013-10-10 02:06:11 +04:00
|
|
|
xhr.onload = function(e) {
|
|
|
|
if (this.status == 200) {
|
|
|
|
var baseUrl = window.location.href.replace(window.location.search, "");
|
|
|
|
window.location.href = baseUrl + "?frameId=" + this.responseText;
|
|
|
|
} else {
|
|
|
|
this.onerror(e);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
xhr.onerror = function(e) {
|
|
|
|
$.publish(Events.SHOW_NOTIFICATION, [{"content": "Saving failed ("+this.status+")"}]);
|
|
|
|
};
|
|
|
|
xhr.send(formData);
|
|
|
|
},
|
2013-07-15 01:04:42 +04:00
|
|
|
|
2013-10-10 02:06:11 +04:00
|
|
|
storeSheetAppEngine_ : function () {
|
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
var formData = new FormData();
|
|
|
|
formData.append('framesheet_content', this.piskelController.serialize());
|
|
|
|
formData.append('fps_speed', $('#preview-fps').val());
|
|
|
|
formData.append('name', $('#piskel-name').val());
|
|
|
|
formData.append('frames', this.piskelController.getFrameCount());
|
|
|
|
formData.append('preview', this.getFirstFrameAsPng());
|
|
|
|
formData.append('framesheet', this.getFramesheetAsPng());
|
2013-08-06 01:57:51 +04:00
|
|
|
|
2013-10-10 02:06:11 +04:00
|
|
|
xhr.open('POST', Constants.APPENGINE.URL.SAVE, true);
|
2013-09-30 23:22:58 +04:00
|
|
|
|
2013-08-06 01:57:51 +04:00
|
|
|
xhr.onload = function(e) {
|
2012-08-30 03:16:13 +04:00
|
|
|
if (this.status == 200) {
|
2013-10-10 02:06:11 +04:00
|
|
|
$.publish(Events.SHOW_NOTIFICATION, [{"content": "Successfully saved !"}]);
|
2013-07-15 01:04:42 +04:00
|
|
|
} else {
|
|
|
|
this.onerror(e);
|
2012-08-30 03:16:13 +04:00
|
|
|
}
|
|
|
|
};
|
2013-08-06 01:57:51 +04:00
|
|
|
xhr.onerror = function(e) {
|
|
|
|
$.publish(Events.SHOW_NOTIFICATION, [{"content": "Saving failed ("+this.status+")"}]);
|
2013-07-15 01:04:42 +04:00
|
|
|
};
|
2012-08-30 03:16:13 +04:00
|
|
|
xhr.send(formData);
|
2013-10-10 02:06:11 +04:00
|
|
|
},
|
2012-08-30 03:16:13 +04:00
|
|
|
|
2013-10-10 02:06:11 +04:00
|
|
|
getFirstFrameAsPng : function () {
|
|
|
|
var firstFrame = this.piskelController.getFrameAt(0);
|
2013-11-01 18:39:42 +04:00
|
|
|
var canvasRenderer = new pskl.rendering.CanvasRenderer(firstFrame, 1);
|
|
|
|
canvasRenderer.drawTransparentAs('rgba(0,0,0,0)');
|
|
|
|
var firstFrameCanvas = canvasRenderer.render().canvas;
|
2013-10-10 02:06:11 +04:00
|
|
|
return firstFrameCanvas.toDataURL("image/png");
|
|
|
|
},
|
|
|
|
|
|
|
|
getFramesheetAsPng : function () {
|
fix : reduce piskel model size
- Initial implementation : working but ...
- MODEL_VERSION has been bumped to 2
- The loading process is now theoretically asynchronous (loading images to
read the content of the layers), but for now, the asynchronous behaviour
is hidden behind a nasty hack, which is somehow similar to lazy loading.
When loading the piskel, a Piskel is created synchronously, with fake
empty frames, and as the images will get loaded, the fake frames will be
replaced by the actual frames.
I really don't like this, and the asynchronous nature of the loading
should be clearly expressed
- There is no backward compatible deserializer for the previous version of
the model (1)
- The Serializer utils is just badly designed. Serialization and
deserialization should be splitted into two different classes
- Saving & loading are still done in app.js and should be moved to
services
BUT : the size of the piskels is now pretty small. A piskel which was
using 890kB previously is now using only 10kB. Although it should be
noted, that after gzip there is no significant difference between this
version and the existing one. The only gains we can really expect with
this are : less disk space used on appengine, ability to reuse the
layers' pngs directly on piskel-website (but to be honest I can't see any
valid use case for this)
2013-11-08 03:44:24 +04:00
|
|
|
var renderer = new pskl.rendering.PiskelRenderer(this.piskelController);
|
|
|
|
var framesheetCanvas = renderer.renderAsCanvas();
|
2013-10-10 02:06:11 +04:00
|
|
|
return framesheetCanvas.toDataURL("image/png");
|
2012-09-20 02:43:39 +04:00
|
|
|
},
|
|
|
|
|
2013-06-13 18:31:09 +04:00
|
|
|
uploadAsSpritesheetPNG : function () {
|
2013-10-10 02:06:11 +04:00
|
|
|
var imageData = this.getFramesheetAsPng();
|
2013-09-22 23:02:43 +04:00
|
|
|
this.imageUploadService.upload(imageData, this.openWindow.bind(this));
|
2013-06-13 18:31:09 +04:00
|
|
|
},
|
|
|
|
|
2013-08-04 20:27:32 +04:00
|
|
|
openWindow : function (url) {
|
2013-06-13 18:31:09 +04:00
|
|
|
var options = [
|
|
|
|
"dialog=yes", "scrollbars=no", "status=no",
|
2013-09-22 23:02:43 +04:00
|
|
|
"width=" + this.piskelController.getWidth() * this.piskelController.getFrameCount(),
|
|
|
|
"height=" + this.piskelController.getHeight()
|
2013-06-13 18:31:09 +04:00
|
|
|
].join(",");
|
|
|
|
|
|
|
|
window.open(url, "piskel-export", options);
|
2012-08-23 02:57:35 +04:00
|
|
|
}
|
|
|
|
};
|
2012-09-03 03:24:55 +04:00
|
|
|
})();
|