diff --git a/src/js/Events.js b/src/js/Events.js index 75c37067..65f921f1 100644 --- a/src/js/Events.js +++ b/src/js/Events.js @@ -80,6 +80,8 @@ var Events = { CURRENT_COLORS_UPDATED : 'CURRENT_COLORS_UPDATED', + PERFORMANCE_REPORT_CHANGED : 'PERFORMANCE_REPORT_CHANGED', + // Tests MOUSE_EVENT : 'MOUSE_EVENT', KEYBOARD_EVENT : 'KEYBOARD_EVENT', diff --git a/src/js/app.js b/src/js/app.js index 83ce44a4..2959beb6 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -153,6 +153,13 @@ document.querySelector('#drawing-canvas-container')); this.fileDropperService.init(); + this.userWarningController = new pskl.controller.UserWarningController(this.piskelController); + this.userWarningController.init(); + + this.performanceReportService = new pskl.service.performance.PerformanceReportService( + this.piskelController, this.currentColorsService); + this.performanceReportService.init(); + this.drawingLoop = new pskl.rendering.DrawingLoop(); this.drawingLoop.addCallback(this.render, this); this.drawingLoop.start(); diff --git a/src/js/controller/UserWarningController.js b/src/js/controller/UserWarningController.js new file mode 100644 index 00000000..ae1b787f --- /dev/null +++ b/src/js/controller/UserWarningController.js @@ -0,0 +1,35 @@ +(function () { + var ns = $.namespace('pskl.controller'); + + ns.UserWarningController = function (piskelController, currentColorsService) { + this.piskelController = piskelController; + this.currentColorsService = currentColorsService; + this.isWarningDisplayed = false; + }; + + ns.UserWarningController.prototype.init = function () { + $.subscribe(Events.PERFORMANCE_REPORT_CHANGED, this.onPerformanceReportChanged_.bind(this)); + }; + + ns.UserWarningController.prototype.onPerformanceReportChanged_ = function (event, report) { + console.log(report); + + var shouldDisplayWarning = report.hasProblem(); + if (shouldDisplayWarning && !this.isWarningDisplayed) { + // show a notification + // show the warning bubble + $.publish(Events.SHOW_NOTIFICATION, [{ + 'content': 'performance problem notification', + 'hideDelay' : 5000 + }]); + console.log('should show a performance notification'); + this.isWarningDisplayed = true; + } + + if (!shouldDisplayWarning && this.isWarningDisplayed) { + // hide the warning bubble + console.log('should hide a performance notification'); + this.isWarningDisplayed = false; + } + }; +})(); diff --git a/src/js/service/performance/PerformanceReport.js b/src/js/service/performance/PerformanceReport.js new file mode 100644 index 00000000..2cdebf20 --- /dev/null +++ b/src/js/service/performance/PerformanceReport.js @@ -0,0 +1,45 @@ +(function () { + var ns = $.namespace('pskl.service.performance'); + + /** + * We consider that piskel should behave correctly for a sprite with the following specs: + * - 256*256 + * - 30 frames + * - 5 layers + * - 30 colors + * Based on these assumptions, as well as a few arbitrary hard limits we try to check + * if the provided sprite might present a performance issue. + * + * @param {Piskel} piskel the sprite to analyze + * @param {Number} colorsCount number of colors for the current sprite + * (not part of the piskel model so has to be provided separately). + */ + ns.PerformanceReport = function (piskel, colorsCount) { + var pixels = piskel.getWidth() * piskel.getHeight(); + this.resolution = pixels > (500 * 500); + + var layersCount = piskel.getLayers().length; + this.layers = layersCount > 25; + + var framesCount = piskel.getLayerAt(0).size(); + this.frames = framesCount > 100; + + this.colors = colorsCount > 100; + + var overallScore = (pixels / 2500) + (layersCount * 4) + framesCount + colorsCount; + this.overall = overallScore > 100; + }; + + ns.PerformanceReport.prototype.equals = function (report) { + return (report instanceof ns.PerformanceReport && + this.resolution == report.resolution && + this.layers == report.layers && + this.frames == report.frames && + this.colors == report.colors && + this.overall == report.overall); + }; + + ns.PerformanceReport.prototype.hasProblem = function () { + return this.resolution || this.layers || this.frames || this.colors || this.overall; + }; +})(); diff --git a/src/js/service/performance/PerformanceReportService.js b/src/js/service/performance/PerformanceReportService.js new file mode 100644 index 00000000..43a8ab8b --- /dev/null +++ b/src/js/service/performance/PerformanceReportService.js @@ -0,0 +1,25 @@ +(function () { + var ns = $.namespace('pskl.service.performance'); + + ns.PerformanceReportService = function (piskelController, currentColorsService) { + this.piskelController = piskelController; + this.currentColorsService = currentColorsService; + + this.currentReport = null; + }; + + ns.PerformanceReportService.prototype.init = function () { + $.subscribe(Events.HISTORY_STATE_SAVED, this.createReport_.bind(this)); + }; + + ns.PerformanceReportService.prototype.createReport_ = function () { + var report = new ns.PerformanceReport( + this.piskelController.getPiskel(), + this.currentColorsService.getCurrentColors().length); + + if (!report.equals(this.currentReport)) { + $.publish(Events.PERFORMANCE_REPORT_CHANGED, [report]); + this.currentReport = report; + } + }; +})(); diff --git a/src/piskel-script-list.js b/src/piskel-script-list.js index e5d6f605..4de8e3ff 100644 --- a/src/piskel-script-list.js +++ b/src/piskel-script-list.js @@ -115,6 +115,7 @@ "js/controller/NotificationController.js", "js/controller/TransformationsController.js", "js/controller/CanvasBackgroundController.js", + "js/controller/UserWarningController.js", // Settings sub-controllers "js/controller/settings/AbstractSettingController.js", @@ -181,6 +182,8 @@ "js/service/FileDropperService.js", "js/service/SelectedColorsService.js", "js/service/MouseStateService.js", + "js/service/performance/PerformanceReport.js", + "js/service/performance/PerformanceReportService.js", "js/service/storage/LocalStorageService.js", "js/service/storage/GalleryStorageService.js", "js/service/storage/DesktopStorageService.js",