From 98f59fecf17b7c831e72636a400ea948758bf066 Mon Sep 17 00:00:00 2001 From: jdescottes Date: Thu, 19 Jun 2014 23:33:57 +0200 Subject: [PATCH] Feature : add onion skin option New option in application settings : onion skin. You can choose the overlay to display now : - no overlay - onion skin (default) - layer preview (previous default) Available in Application Settings panel. Only one overlay can be used at the same time. The onion skin overlay is driven by a new OnionSkinRenderer maanged by the drawing. The drawing controller is responsible for instanciating and 'choosing' the overlay renderer. When switching to a new overlay, other overlays are cleared and flushed (they cache their rendering frame, flush empties the cache). NB : flush is only available on LayersRenderer and OnionSkinRenderer for now. --- src/css/style.css | 9 ++- src/js/Constants.js | 4 + src/js/controller/DrawingController.js | 18 ++++- .../settings/ApplicationSettingsController.js | 12 +-- src/js/rendering/OnionSkinRenderer.js | 77 +++++++++++++++++++ src/js/rendering/layer/LayersRenderer.js | 5 +- src/js/utils/UserSettings.js | 4 +- src/piskel-script-list.js | 1 + src/templates/settings/application.html | 12 +++ 9 files changed, 129 insertions(+), 13 deletions(-) create mode 100644 src/js/rendering/OnionSkinRenderer.js diff --git a/src/css/style.css b/src/css/style.css index d12c3093..0cb64084 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -136,12 +136,14 @@ body { background: url(../img/canvas_background/lowcont_dark_canvas_background.png) repeat; } -.layers-canvas { +.layers-canvas, +.canvas.onion-skin-canvas { opacity: 0.2; } .canvas.canvas-overlay, -.canvas.layers-canvas { +.canvas.layers-canvas, +.canvas.onion-skin-canvas { position: absolute; top: 0; left: 0; @@ -157,7 +159,8 @@ body { .canvas.layers-below-canvas {z-index: 7;} .canvas.drawing-canvas {z-index: 8;} .canvas.layers-above-canvas {z-index: 9;} -.canvas.canvas-overlay {z-index: 10;} +.canvas.onion-skin-canvas {z-index: 10;} +.canvas.canvas-overlay {z-index: 11;} /** * Animated preview styles. diff --git a/src/js/Constants.js b/src/js/Constants.js index c6662aa2..65b00fe7 100644 --- a/src/js/Constants.js +++ b/src/js/Constants.js @@ -19,6 +19,10 @@ var Constants = { DEFAULT_PEN_COLOR : '#000000', TRANSPARENT_COLOR : 'rgba(0, 0, 0, 0)', + OVERLAY_ONION_SKIN : 'onion-skin', + OVERLAY_LAYER_PREVIEW : 'layer-preview', + OVERLAY_DISABLED : 'no-overlay', + NO_PALETTE_ID : '__no-palette', CURRENT_COLORS_PALETTE_ID : '__current-colors', MANAGE_PALETTE_ID : '__manage-palettes', diff --git a/src/js/controller/DrawingController.js b/src/js/controller/DrawingController.js index 65560ca6..9ccdb1c4 100644 --- a/src/js/controller/DrawingController.js +++ b/src/js/controller/DrawingController.js @@ -32,13 +32,15 @@ this.overlayRenderer = new pskl.rendering.frame.CachedFrameRenderer(this.container, renderingOptions, ["canvas-overlay"]); this.renderer = new pskl.rendering.frame.CachedFrameRenderer(this.container, renderingOptions, ["drawing-canvas"]); + this.onionSkinRenderer = new pskl.rendering.OnionSkinRenderer(this.container, renderingOptions, piskelController); this.layersRenderer = new pskl.rendering.layer.LayersRenderer(this.container, renderingOptions, piskelController); this.compositeRenderer = new pskl.rendering.CompositeRenderer(); this.compositeRenderer .add(this.overlayRenderer) .add(this.renderer) - .add(this.layersRenderer); + .add(this.layersRenderer) + .add(this.onionSkinRenderer); // State of drawing controller: this.isClicked = false; @@ -111,6 +113,12 @@ ns.DrawingController.prototype.onUserSettingsChange_ = function (evt, settingsName, settingsValue) { if(settingsName == pskl.UserSettings.SHOW_GRID) { console.warn('DrawingController:onUserSettingsChange_ not implemented !'); + } else if (settingsName == pskl.UserSettings.OVERLAY) { + this.onionSkinRenderer.clear(); + this.onionSkinRenderer.flush(); + this.layersRenderer.clear(); + this.layersRenderer.flush(); + this.render(); } }; @@ -311,7 +319,13 @@ this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(currentFrame); } - this.layersRenderer.render(); + var overlaySetting = pskl.UserSettings.get(pskl.UserSettings.OVERLAY); + if (overlaySetting === Constants.OVERLAY_ONION_SKIN) { + this.onionSkinRenderer.render(); + } else if (overlaySetting === Constants.OVERLAY_LAYER_PREVIEW) { + this.layersRenderer.render(); + } + this.renderer.render(currentFrame); this.overlayRenderer.render(this.overlayFrame); }; diff --git a/src/js/controller/settings/ApplicationSettingsController.js b/src/js/controller/settings/ApplicationSettingsController.js index f4bf2863..746dc66e 100644 --- a/src/js/controller/settings/ApplicationSettingsController.js +++ b/src/js/controller/settings/ApplicationSettingsController.js @@ -18,9 +18,9 @@ $('#grid-width').val(gridWidth); $('#grid-width').change(this.onGridWidthChange.bind(this)); - var tiledPreview = pskl.UserSettings.get(pskl.UserSettings.TILED_PREVIEW); - $('#tiled-preview').prop('checked', tiledPreview); - $('#tiled-preview').change(this.onTiledPreviewChange.bind(this)); + var overlay = pskl.UserSettings.get(pskl.UserSettings.OVERLAY); + $('#overlay').val(overlay); + $('#overlay').change(this.onOverlayChange.bind(this)); // Handle canvas background changes: $('#background-picker-wrapper').click(this.onBackgroundClick.bind(this)); @@ -31,9 +31,9 @@ pskl.UserSettings.set(pskl.UserSettings.GRID_WIDTH, parseInt(width, 10)); }; - ns.ApplicationSettingsController.prototype.onTiledPreviewChange = function (evt) { - var checked = $('#tiled-preview').prop('checked'); - pskl.UserSettings.set(pskl.UserSettings.TILED_PREVIEW, checked); + ns.ApplicationSettingsController.prototype.onOverlayChange = function (evt) { + var overlay = $('#overlay').val(); + pskl.UserSettings.set(pskl.UserSettings.OVERLAY, overlay); }; ns.ApplicationSettingsController.prototype.onBackgroundClick = function (evt) { diff --git a/src/js/rendering/OnionSkinRenderer.js b/src/js/rendering/OnionSkinRenderer.js new file mode 100644 index 00000000..a4a27b93 --- /dev/null +++ b/src/js/rendering/OnionSkinRenderer.js @@ -0,0 +1,77 @@ +(function () { + var ns = $.namespace('pskl.rendering'); + + ns.OnionSkinRenderer = function (container, renderingOptions, piskelController) { + pskl.rendering.CompositeRenderer.call(this); + + this.piskelController = piskelController; + + // Do not use CachedFrameRenderers here, since the caching will be performed in the render method of LayersRenderer + this.renderer = new pskl.rendering.frame.FrameRenderer(container, renderingOptions, ["onion-skin-canvas"]); + + this.add(this.renderer); + + this.serializedRendering = ''; + }; + + pskl.utils.inherit(pskl.rendering.OnionSkinRenderer, pskl.rendering.CompositeRenderer); + + ns.OnionSkinRenderer.prototype.render = function () { + var offset = this.getOffset(); + var size = this.getDisplaySize(); + var layers = this.piskelController.getLayers(); + var currentFrameIndex = this.piskelController.getCurrentFrameIndex(); + + var frames = []; + this.addFrameAtIndexToArray_(currentFrameIndex - 1, frames); + this.addFrameAtIndexToArray_(currentFrameIndex + 1, frames); + + var serializedRendering = [ + this.getZoom(), + this.getGridWidth(), + offset.x, + offset.y, + size.width, + size.height, + frames.map(function (f) { + return f.getHash(); + }).join('-'), + layers.length + ].join("-"); + + + if (this.serializedRendering != serializedRendering) { + this.serializedRendering = serializedRendering; + + if (frames.length > 0) { + this.clear(); + var mergedFrame = pskl.utils.FrameUtils.merge(frames); + this.renderer.render(mergedFrame); + } + } + }; + + ns.OnionSkinRenderer.prototype.addFrameAtIndexToArray_ = function (frameIndex, frames) { + var layer = this.piskelController.getCurrentLayer(); + if (this.piskelController.hasFrameAt(frameIndex)) { + frames.push(layer.getFrameAt(frameIndex)); + } + }; + + /** + * See @pskl.rendering.frame.CachedFrameRenderer + * Same issue : FrameRenderer setDisplaySize destroys the canvas + * @param {Number} width + * @param {Number} height + */ + ns.OnionSkinRenderer.prototype.setDisplaySize = function (width, height) { + var size = this.getDisplaySize(); + if (size.width !== width || size.height !== height) { + this.superclass.setDisplaySize.call(this, width, height); + } + }; + + ns.OnionSkinRenderer.prototype.flush = function () { + this.serializedRendering = ''; + }; +})(); \ No newline at end of file diff --git a/src/js/rendering/layer/LayersRenderer.js b/src/js/rendering/layer/LayersRenderer.js index 2c5763a1..3b46b980 100644 --- a/src/js/rendering/layer/LayersRenderer.js +++ b/src/js/rendering/layer/LayersRenderer.js @@ -58,7 +58,6 @@ } }; - /** * See @pskl.rendering.frame.CachedFrameRenderer * Same issue : FrameRenderer setDisplaySize destroys the canvas @@ -78,4 +77,8 @@ }); return pskl.utils.FrameUtils.merge(frames); }; + + ns.LayersRenderer.prototype.flush = function () { + this.serializedRendering = ''; + }; })(); diff --git a/src/js/utils/UserSettings.js b/src/js/utils/UserSettings.js index 35464349..f9cd3a5c 100644 --- a/src/js/utils/UserSettings.js +++ b/src/js/utils/UserSettings.js @@ -6,12 +6,14 @@ CANVAS_BACKGROUND : 'CANVAS_BACKGROUND', SELECTED_PALETTE : 'SELECTED_PALETTE', TILED_PREVIEW : 'TILED_PREVIEW', + OVERLAY : 'OVERLAY', KEY_TO_DEFAULT_VALUE_MAP_ : { 'GRID_WIDTH' : 0, 'CANVAS_BACKGROUND' : 'lowcont-dark-canvas-background', 'SELECTED_PALETTE' : Constants.CURRENT_COLORS_PALETTE_ID, - 'TILED_PREVIEW' : false + 'TILED_PREVIEW' : false, + 'OVERLAY' : Constants.OVERLAY_ONION_SKIN }, /** diff --git a/src/piskel-script-list.js b/src/piskel-script-list.js index 2b4dacbe..cbdc0061 100644 --- a/src/piskel-script-list.js +++ b/src/piskel-script-list.js @@ -60,6 +60,7 @@ "js/rendering/CompositeRenderer.js", "js/rendering/layer/LayersRenderer.js", "js/rendering/frame/FrameRenderer.js", + "js/rendering/OnionSkinRenderer.js", "js/rendering/frame/TiledFrameRenderer.js", "js/rendering/frame/CachedFrameRenderer.js", "js/rendering/CanvasRenderer.js", diff --git a/src/templates/settings/application.html b/src/templates/settings/application.html index ed2b07bc..77f6ca06 100644 --- a/src/templates/settings/application.html +++ b/src/templates/settings/application.html @@ -29,6 +29,18 @@ + +
+ Overlay: +
+
+ + +