From 9dc7afee612193617e4c5a737b3299201e188802 Mon Sep 17 00:00:00 2001 From: Vince Date: Sat, 8 Sep 2012 18:44:06 +0200 Subject: [PATCH 1/9] Moving drawing canvas code from piskel.js to drawingController.js --- js/Events.js | 7 ++ js/controller/DrawingController.js | 167 ++++++++++++++++++++++++ js/controller/PreviewFilmController.js | 13 +- js/piskel.js | 168 ++----------------------- js/rendering/FrameRenderer.js | 2 +- 5 files changed, 192 insertions(+), 165 deletions(-) diff --git a/js/Events.js b/js/Events.js index 2a1545b8..df4dfb89 100644 --- a/js/Events.js +++ b/js/Events.js @@ -22,6 +22,13 @@ Events = { */ REFRESH: "REFRESH", + /** + * Temporary event to bind the redraw of right preview film to the canvas. + * This redraw should be driven by model updates. + * TODO(vincz): Remove. + */ + REDRAW_PREVIEWFILM: "REDRAW_PREVIEWFILM", + /** * The framesheet was reseted and is now probably drastically different. * Number of frames, content of frames, color used for the palette may have changed. diff --git a/js/controller/DrawingController.js b/js/controller/DrawingController.js index f6043669..66559fc1 100644 --- a/js/controller/DrawingController.js +++ b/js/controller/DrawingController.js @@ -19,8 +19,175 @@ this.renderer.init(this.frame); this.overlayRenderer.init(this.frame); + + // State of drawing controller: + this.isClicked = false; + this.isRightClicked = false; + this.previousMousemoveTime = 0; + this.currentToolBehavior = null; + this.primaryColor = Constants.DEFAULT_PEN_COLOR; + this.secondaryColor = Constants.TRANSPARENT_COLOR; + + this.initMouseBehavior(); + + $.subscribe(Events.TOOL_SELECTED, $.proxy(function(evt, toolBehavior) { + + console.log("Tool selected: ", toolBehavior); + this.currentToolBehavior = toolBehavior; + }, this)); + + $.subscribe(Events.COLOR_SELECTED, $.proxy(function(evt, color, isPrimary) { + console.log("Color selected: ", color); + if (isPrimary) { + this.primaryColor = color; + } else { + this.secondaryColor = color; + } + }, this)); }; + ns.DrawingController.prototype.initMouseBehavior = function() { + var body = $('body'); + this.container.mousedown($.proxy(this.onMousedown_, this)); + this.container.mousemove($.proxy(this.onMousemove_, this)); + body.mouseup($.proxy(this.onMouseup_, this)); + + // Deactivate right click: + this.container.contextmenu(this.onCanvasContextMenu_); + }; + + /** + * @private + */ + ns.DrawingController.prototype.onMousedown_ = function (event) { + this.isClicked = true; + + if(event.button == 2) { // right click + this.isRightClicked = true; + $.publish(Events.CANVAS_RIGHT_CLICKED); + } + + var spriteCoordinate = this.getSpriteCoordinate(event); + //console.log("mousedown: col: " + spriteCoordinate.col + " - row: " + spriteCoordinate.row); + + this.currentToolBehavior.applyToolAt( + spriteCoordinate.col, + spriteCoordinate.row, + this.getCurrentColor_(), + this + ); + + $.publish(Events.LOCALSTORAGE_REQUEST); + }; + + /** + * @private + */ + ns.DrawingController.prototype.onMousemove_ = function (event) { + var currentTime = new Date().getTime(); + // Throttling of the mousemove event: + if ((currentTime - this.previousMousemoveTime) > 40 ) { + var spriteCoordinate = this.getSpriteCoordinate(event); + if (this.isClicked) { + + this.currentToolBehavior.moveToolAt( + spriteCoordinate.col, + spriteCoordinate.row, + this.getCurrentColor_(), + this + ); + + //console.log("mousemove: col: " + spriteCoordinate.col + " - row: " + spriteCoordinate.row); + + // TODO(vincz): Find a way to move that to the model instead of being at the interaction level. + // Eg when drawing, it may make sense to have it here. However for a non drawing tool, + // you don't need to draw anything when mousemoving and you request useless localStorage. + $.publish(Events.LOCALSTORAGE_REQUEST); + } else { + // debug mode to see the selected pixel + // this.clearOverlay(); + // this.overlayFrame.setPixel( spriteCoordinate.col,spriteCoordinate.row, "#ff0000"); + // this.renderOverlay(); + } + this.previousMousemoveTime = currentTime; + } + }; + + /** + * @private + */ + ns.DrawingController.prototype.onMouseup_ = function (event) { + if(this.isClicked || this.isRightClicked) { + // A mouse button was clicked on the drawing canvas before this mouseup event, + // the user was probably drawing on the canvas. + // Note: The mousemove movement (and the mouseup) may end up outside + // of the drawing canvas. + if(this.isRightClicked) { + $.publish(Events.CANVAS_RIGHT_CLICK_RELEASED); + } + + + this.isClicked = false; + this.isRightClicked = false; + var spriteCoordinate = this.getSpriteCoordinate(event); + console.log("mousemove: col: " + spriteCoordinate.col + " - row: " + spriteCoordinate.row); + this.currentToolBehavior.releaseToolAt( + spriteCoordinate.col, + spriteCoordinate.row, + this.getCurrentColor_(), + this + ); + + $.publish(Events.TOOL_RELEASED); + + // TODO: Remove that when we have the centralized redraw loop + $.publish(Events.REDRAW_PREVIEWFILM); + } + }, + + /** + * @private + */ + ns.DrawingController.prototype.getRelativeCoordinates = function (clientX, clientY) { + var canvasPageOffset = this.container.offset(); + return { + x : clientX - canvasPageOffset.left, + y : clientY - canvasPageOffset.top + } + }; + + /** + * @private + */ + ns.DrawingController.prototype.getSpriteCoordinate = function(event) { + var coords = this.getRelativeCoordinates(event.clientX, event.clientY); + return { + "col" : (coords.x - coords.x % this.dpi) / this.dpi, + "row" : (coords.y - coords.y % this.dpi) / this.dpi + } + }; + + /** + * @private + */ + ns.DrawingController.prototype.getCurrentColor_ = function () { + if(this.isRightClicked) { + return this.secondaryColor; + } else { + return this.primaryColor; + } + }; + + /** + * @private + */ + ns.DrawingController.prototype.onCanvasContextMenu_ = function (event) { + event.preventDefault(); + event.stopPropagation(); + event.cancelBubble = true; + return false; + }; + ns.DrawingController.prototype.updateDPI = function (newDPI) { this.renderer.updateDPI(newDPI); this.overlayRenderer.updateDPI(newDPI); diff --git a/js/controller/PreviewFilmController.js b/js/controller/PreviewFilmController.js index 75383df0..7d7a2fe6 100644 --- a/js/controller/PreviewFilmController.js +++ b/js/controller/PreviewFilmController.js @@ -5,6 +5,10 @@ this.dpi = dpi; this.framesheet = framesheet; this.container = container; + + $.subscribe(Events.REDRAW_PREVIEWFILM, $.proxy(function(evt) { + this.createPreviews() + }, this)); }; ns.PreviewFilmController.prototype.init = function() { @@ -28,7 +32,7 @@ for (var i = 0, l = frameCount; i < l ; i++) { this.container.append(this.createInterstitialTile_(i)); - this.container.append(this.createPreviewTile_(i)); + this.container.append(this.createPreviewTile_(i, this.framesheet)); } this.container.append(this.createInterstitialTile_(frameCount)); @@ -142,7 +146,7 @@ * @private * TODO(vincz): clean this giant rendering function & remove listeners. */ - ns.PreviewFilmController.prototype.createPreviewTile_ = function(tileNumber) { + ns.PreviewFilmController.prototype.createPreviewTile_ = function(tileNumber, framesheet) { var currentFrame = this.framesheet.getFrameByIndex(tileNumber); //var width = frame.getWidth() * this.dpi, // height = frame.getHeight() * this.dpi; @@ -183,7 +187,8 @@ canvasPreviewDuplicateAction.innerHTML = "dup" canvasPreviewDuplicateAction.addEventListener('click', function(evt) { - piskel.duplicateFrame(tileNumber); + framesheet.duplicateFrameByIndex(tileNumber); + $.publish('SET_ACTIVE_FRAME', [tileNumber + 1]); }); //this.renderer.render(this.framesheet.getFrameByIndex(tileNumber), canvasPreview); @@ -191,7 +196,7 @@ // TODO(vincz): Eventually optimize this part by not recreating a FrameRenderer. Note that the real optim // is to make this update function (#createPreviewTile) less aggressive. var renderingOptions = {"dpi": this.dpi }; - var currentFrameRenderer = new pskl.rendering.FrameRenderer(canvasContainer, renderingOptions, "tile-view"); + var currentFrameRenderer = new pskl.rendering.FrameRenderer($(canvasContainer), renderingOptions, "tile-view"); currentFrameRenderer.init(currentFrame); previewTileRoot.appendChild(canvasContainer); diff --git a/js/piskel.js b/js/piskel.js index af4f7a79..fde522b4 100644 --- a/js/piskel.js +++ b/js/piskel.js @@ -24,23 +24,8 @@ $.namespace("pskl"); // Animated canvas preview: previewAnimationCanvasDpi = 8, - // DOM references: - drawingAreaContainer, - drawingAreaCanvas, - previewCanvas, - - // States: - isClicked = false, - isRightClicked = false, - activeFrameIndex = -1, - animIndex = 0, - - primaryColor = Constants.DEFAULT_PEN_COLOR, - secondaryColor = Constants.TRANSPARENT_COLOR, - + activeFrameIndex = -1, currentFrame = null; - currentToolBehavior = null, - previousMousemoveTime = 0; /** * Main application controller @@ -56,7 +41,7 @@ $.namespace("pskl"); this.drawingController = new pskl.controller.DrawingController( frameSheet.getFrameByIndex(0), - $('#drawing-canvas-container')[0], + $('#drawing-canvas-container'), drawingCanvasDpi ); @@ -64,7 +49,7 @@ $.namespace("pskl"); this.animationController = new pskl.controller.AnimatedPreviewController( frameSheet, - $('#preview-canvas-container')[0], + $('#preview-canvas-container'), previewAnimationCanvasDpi ); @@ -91,6 +76,10 @@ $.namespace("pskl"); this.finishInit(); pskl.LocalStorageService.displayRestoreNotification(); } + + $.subscribe('SET_ACTIVE_FRAME', function(evt, frameId) { + piskel.setActiveFrameAndRedraw(frameId); + }); }, /** @@ -118,27 +107,12 @@ $.namespace("pskl"); finishInit : function () { - $.subscribe(Events.TOOL_SELECTED, function(evt, toolBehavior) { - console.log("Tool selected: ", toolBehavior); - currentToolBehavior = toolBehavior; - }); - - $.subscribe(Events.COLOR_SELECTED, function(evt, color, isPrimary) { - console.log("Color selected: ", color); - if (isPrimary) { - primaryColor = color; - } else { - secondaryColor = color; - } - }); + $.subscribe(Events.REFRESH, function() { piskel.setActiveFrameAndRedraw(0); }); - // TODO: Move this into their service or behavior files: - this.initDrawingArea(); - pskl.ToolSelector.init(); pskl.Palette.init(frameSheet); }, @@ -202,132 +176,6 @@ $.namespace("pskl"); return frameSheet.getFrameByIndex(activeFrameIndex); }, - initDrawingArea : function() { - drawingAreaContainer = $('#drawing-canvas-container')[0]; - document.body.addEventListener('mouseup', this.onMouseup.bind(this)); - drawingAreaContainer.addEventListener('mousedown', this.onMousedown.bind(this)); - drawingAreaContainer.addEventListener('mousemove', this.onMousemove.bind(this)); - document.body.addEventListener('contextmenu', this.onCanvasContextMenu); - }, - - removeFrame: function(frameIndex) { - frameSheet.removeFrameByIndex(frameIndex); - var activeFrameIndex = frameIndex ? frameIndex - 1 : 0; - this.setActiveFrameAndRedraw(activeFrameIndex); - }, - - duplicateFrame: function(frameIndex) { - frameSheet.duplicateFrameByIndex(frameIndex); - this.setActiveFrameAndRedraw(frameIndex + 1); - }, - - getCurrentColor : function () { - if(isRightClicked) { - return secondaryColor; - } else { - return primaryColor; - } - }, - - onMousedown : function (event) { - isClicked = true; - - if(event.button == 2) { // right click - isRightClicked = true; - $.publish(Events.CANVAS_RIGHT_CLICKED); - } - - var spriteCoordinate = this.getSpriteCoordinate(event); - currentToolBehavior.applyToolAt( - spriteCoordinate.col, - spriteCoordinate.row, - this.getCurrentColor(), - this.drawingController - ); - - $.publish(Events.LOCALSTORAGE_REQUEST); - }, - - onMousemove : function (event) { - var currentTime = new Date().getTime(); - // Throttling of the mousemove event: - if ((currentTime - previousMousemoveTime) > 40 ) { - var spriteCoordinate = this.getSpriteCoordinate(event); - if (isClicked) { - - currentToolBehavior.moveToolAt( - spriteCoordinate.col, - spriteCoordinate.row, - this.getCurrentColor(), - this.drawingController - ); - - // TODO(vincz): Find a way to move that to the model instead of being at the interaction level. - // Eg when drawing, it may make sense to have it here. However for a non drawing tool, - // you don't need to draw anything when mousemoving and you request useless localStorage. - $.publish(Events.LOCALSTORAGE_REQUEST); - } else { - // debug mode to see the selected pixel - // this.drawingController.clearOverlay(); - // this.drawingController.overlay.setPixel( spriteCoordinate.col,spriteCoordinate.row, "#ff0000"); - // this.drawingController.renderOverlay(); - } - previousMousemoveTime = currentTime; - } - }, - - onMouseup : function (event) { - if(isClicked || isRightClicked) { - // A mouse button was clicked on the drawing canvas before this mouseup event, - // the user was probably drawing on the canvas. - // Note: The mousemove movement (and the mouseup) may end up outside - // of the drawing canvas. - if(isRightClicked) { - $.publish(Events.CANVAS_RIGHT_CLICK_RELEASED); - } - - - isClicked = false; - isRightClicked = false; - var spriteCoordinate = this.getSpriteCoordinate(event); - currentToolBehavior.releaseToolAt( - spriteCoordinate.col, - spriteCoordinate.row, - this.getCurrentColor(), - this.drawingController - ); - - - $.publish(Events.TOOL_RELEASED); - // TODO: Remove that when we have the centralized redraw loop - this.previewsController.createPreviews(); - } - }, - - onCanvasContextMenu : function (event) { - event.preventDefault(); - event.stopPropagation(); - event.cancelBubble = true; - return false; - }, - - getRelativeCoordinates : function (x, y) { - var canvasRect = $(".drawing-canvas")[0].getBoundingClientRect(); - return { - x : x - canvasRect.left, - y : y - canvasRect.top - } - }, - - getSpriteCoordinate : function(event) { - var coord = this.getRelativeCoordinates(event.x, event.y); - var coords = this.getRelativeCoordinates(event.clientX, event.clientY); - return { - "col" : (coords.x - coords.x%drawingCanvasDpi) / drawingCanvasDpi, - "row" : (coords.y - coords.y%drawingCanvasDpi) / drawingCanvasDpi - } - }, - // TODO(julz): Create package ? storeSheet : function (event) { // TODO Refactor using jquery ? diff --git a/js/rendering/FrameRenderer.js b/js/rendering/FrameRenderer.js index 63b96533..6dbe9bc0 100644 --- a/js/rendering/FrameRenderer.js +++ b/js/rendering/FrameRenderer.js @@ -80,7 +80,7 @@ canvas.setAttribute("class", canvasClassname); this.canvas = canvas; - this.container.appendChild(this.canvas); + this.container.append(this.canvas); this.canvasConfigDirty = false; } From 6e8142bb3a9d3f5ee14625f888f7176b91cd6a52 Mon Sep 17 00:00:00 2001 From: Vince Date: Sat, 8 Sep 2012 18:45:18 +0200 Subject: [PATCH 2/9] Removing commented outdated code --- js/controller/PreviewFilmController.js | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/js/controller/PreviewFilmController.js b/js/controller/PreviewFilmController.js index 7d7a2fe6..12710341 100644 --- a/js/controller/PreviewFilmController.js +++ b/js/controller/PreviewFilmController.js @@ -148,9 +148,7 @@ */ ns.PreviewFilmController.prototype.createPreviewTile_ = function(tileNumber, framesheet) { var currentFrame = this.framesheet.getFrameByIndex(tileNumber); - //var width = frame.getWidth() * this.dpi, - // height = frame.getHeight() * this.dpi; - + var previewTileRoot = document.createElement("li"); var classname = "preview-tile"; previewTileRoot.setAttribute("data-tile-number", tileNumber); @@ -162,18 +160,10 @@ var canvasContainer = document.createElement("div"); canvasContainer.className = "canvas-container"; - //canvasContainer.setAttribute('style', 'width:' + width + 'px; height:' + height + 'px;'); - + var canvasBackground = document.createElement("div"); canvasBackground.className = "canvas-background"; canvasContainer.appendChild(canvasBackground); - /* - var canvasPreview = document.createElement("canvas"); - canvasPreview.className = "canvas tile-view" - - canvasPreview.setAttribute('width', width); - canvasPreview.setAttribute('height', height); - */ previewTileRoot.addEventListener('click', function(evt) { // has not class tile-action: From 2cda69b000e0819890f7845aa1212e89989592ca Mon Sep 17 00:00:00 2001 From: Vince Date: Sat, 8 Sep 2012 19:00:03 +0200 Subject: [PATCH 3/9] Fixing remove and duplicate actions from previewfilm --- js/controller/PreviewFilmController.js | 5 ++++- js/piskel.js | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/js/controller/PreviewFilmController.js b/js/controller/PreviewFilmController.js index 12710341..7db43364 100644 --- a/js/controller/PreviewFilmController.js +++ b/js/controller/PreviewFilmController.js @@ -178,6 +178,7 @@ canvasPreviewDuplicateAction.addEventListener('click', function(evt) { framesheet.duplicateFrameByIndex(tileNumber); + $.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model $.publish('SET_ACTIVE_FRAME', [tileNumber + 1]); }); @@ -197,7 +198,9 @@ canvasPreviewDeleteAction.className = "tile-action" canvasPreviewDeleteAction.innerHTML = "del" canvasPreviewDeleteAction.addEventListener('click', function(evt) { - piskel.removeFrame(tileNumber); + framesheet.removeFrameByIndex(tileNumber); + $.publish(Events.FRAMESHEET_RESET); + $.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model }); previewTileRoot.appendChild(canvasPreviewDeleteAction); } diff --git a/js/piskel.js b/js/piskel.js index fde522b4..157a4673 100644 --- a/js/piskel.js +++ b/js/piskel.js @@ -80,6 +80,10 @@ $.namespace("pskl"); $.subscribe('SET_ACTIVE_FRAME', function(evt, frameId) { piskel.setActiveFrameAndRedraw(frameId); }); + + $.subscribe('FRAMESHEET_RESET', function(evt, frameId) { + piskel.redraw(); + }); }, /** From 82da78abf1f0e18bd655deed53199a4fcdda8d8d Mon Sep 17 00:00:00 2001 From: Vince Date: Sat, 8 Sep 2012 22:26:17 +0200 Subject: [PATCH 4/9] Adding grid --- js/controller/DrawingController.js | 1 + js/piskel.js | 2 +- js/rendering/FrameRenderer.js | 99 ++++++++++++++++++++++++------ 3 files changed, 82 insertions(+), 20 deletions(-) diff --git a/js/controller/DrawingController.js b/js/controller/DrawingController.js index 66559fc1..25dc9f35 100644 --- a/js/controller/DrawingController.js +++ b/js/controller/DrawingController.js @@ -54,6 +54,7 @@ // Deactivate right click: this.container.contextmenu(this.onCanvasContextMenu_); + //this.container.contextmenu(this.onCanvasContextMenu_); }; /** diff --git a/js/piskel.js b/js/piskel.js index 157a4673..e1f9ac75 100644 --- a/js/piskel.js +++ b/js/piskel.js @@ -105,7 +105,7 @@ $.namespace("pskl"); * @private */ calculateDPIsForDrawingCanvas_ : function() { - var availableViewportHeight = $('.main-panel').height(); + var availableViewportHeight = $('.main-panel').height() - 50; return Math.floor(availableViewportHeight / framePixelHeight); }, diff --git a/js/rendering/FrameRenderer.js b/js/rendering/FrameRenderer.js index 6dbe9bc0..0490dfac 100644 --- a/js/rendering/FrameRenderer.js +++ b/js/rendering/FrameRenderer.js @@ -1,22 +1,30 @@ (function () { var ns = $.namespace("pskl.rendering"); - this.dpi = null; - this.canvas = null; - + ns.FrameRenderer = function (container, renderingOptions, className) { + + this.defaultRenderingOptions = { + "gridStrokeWidth" : 0, + "gridStrokeColor" : "lightgray" + }; + renderingOptions = $.extend(true, {}, this.defaultRenderingOptions, renderingOptions); + if(container == undefined) { throw "Bad FrameRenderer initialization. undefined."; } - this.container = container; - - if(renderingOptions == undefined || renderingOptions.dpi == undefined || isNaN(dpi)) { + + if(isNaN(renderingOptions.dpi)) { throw "Bad FrameRenderer initialization. not well defined."; } - this.displayGrid = !!renderingOptions.displayGrid; + this.container = container; this.dpi = renderingOptions.dpi; this.className = className; + this.canvas = null; + console.log(renderingOptions) + this.gridStrokeWidth = renderingOptions.gridStrokeWidth; + this.gridStrokeColor = renderingOptions.gridStrokeColor; // Flag to know if the config was altered this.canvasConfigDirty = true; @@ -34,16 +42,16 @@ ns.FrameRenderer.prototype.render = function (frame) { for(var col = 0, width = frame.getWidth(); col < width; col++) { for(var row = 0, height = frame.getHeight(); row < height; row++) { - this.drawPixel(col, row, frame, this.getCanvas_(frame), this.dpi); + this.drawPixel(col, row, frame, this.getCanvas_(frame, col, row), this.dpi); } } }; ns.FrameRenderer.prototype.drawPixel = function (col, row, frame) { - var context = this.getCanvas_(frame).getContext('2d'); + var context = this.getCanvas_(frame, col, row).getContext('2d'); var color = frame.getPixel(col, row); if(color == Constants.TRANSPARENT_COLOR) { - context.clearRect(col * this.dpi, row * this.dpi, this.dpi, this.dpi); + context.clearRect(this.getFrameY_(col), this.getFrameY_(row), this.dpi, this.dpi); } else { if(color != Constants.SELECTION_TRANSPARENT_COLOR) { @@ -51,37 +59,90 @@ $.publish(Events.COLOR_USED, [color]); } context.fillStyle = color; - context.fillRect(col * this.dpi, row * this.dpi, this.dpi, this.dpi); + context.fillRect(this.getFrameY_(col), this.getFrameY_(row), this.dpi, this.dpi); } }; ns.FrameRenderer.prototype.clear = function (col, row, frame) { - var canvas = this.getCanvas_(frame) + var canvas = this.getCanvas_(frame, col, row) canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height); }; + /** + * Transform a screen pixel-based coordinate (relative to the top-left corner of the rendered + * frame) into a sprite coordinate in column and row. + * @public + */ + ns.FrameRenderer.prototype.convertPixelCoordinatesIntoSpriteCoordinate = function(coords) { + var cellSize = this.dpi + this.gridStrokeWidth; + return { + "col" : (coords.x - coords.x % cellSize) / cellSize, + "row" : (coords.y - coords.y % cellSize) / cellSize + }; + }; + + /** + * @private + */ + ns.FrameRenderer.prototype.getFrameX_ = function(col) { + return col * this.dpi + ((col - 1) * this.gridStrokeWidth); + }; + + /** + * @private + */ + ns.FrameRenderer.prototype.getFrameY_ = function(row) { + return row * this.dpi + ((row - 1) * this.gridStrokeWidth); + }; + + /** + * @private + */ + ns.FrameRenderer.prototype.drawGrid_ = function(canvas, width, height, col, row) { + var ctx = canvas.getContext("2d"); + ctx.lineWidth = this.gridStrokeWidth; + ctx.strokeStyle = this.gridStrokeColor; + for(var c=1; c < col; c++) { + ctx.moveTo(this.getFrameX_(c), 0); + ctx.lineTo(this.getFrameX_(c), height); + ctx.stroke(); + } + + for(var r=1; r < row; r++) { + ctx.moveTo(0, this.getFrameY_(r)); + ctx.lineTo(width, this.getFrameY_(r)); + ctx.stroke(); + } + }; + /** * @private */ ns.FrameRenderer.prototype.getCanvas_ = function (frame) { if(this.canvasConfigDirty) { $(this.canvas).remove(); - var width = frame.getWidth(), - height = frame.getHeight(); + var col = frame.getWidth(), + row = frame.getHeight(); var canvas = document.createElement("canvas"); - canvas.setAttribute("width", width * this.dpi); - canvas.setAttribute("height", height * this.dpi); + var pixelWidth = col * this.dpi + this.gridStrokeWidth * (col - 1); + var pixelHeight = row * this.dpi + this.gridStrokeWidth * (row - 1); + canvas.setAttribute("width", pixelWidth); + canvas.setAttribute("height", pixelHeight); var canvasClassname = "canvas"; if(this.className) { canvasClassname += " " + this.className; } canvas.setAttribute("class", canvasClassname); - - this.canvas = canvas; - this.container.append(this.canvas); + this.container.append(canvas); + if(this.gridStrokeWidth > 0) { + this.drawGrid_(canvas, pixelWidth, pixelHeight, col, row); + } + + + this.canvas = canvas; this.canvasConfigDirty = false; } return this.canvas; From 6b9904935fa3209e3cc821a7ef457c287d22dee2 Mon Sep 17 00:00:00 2001 From: Vince Date: Sat, 8 Sep 2012 22:26:27 +0200 Subject: [PATCH 5/9] Adding grid --- js/controller/DrawingController.js | 44 +++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/js/controller/DrawingController.js b/js/controller/DrawingController.js index 25dc9f35..b1a639f8 100644 --- a/js/controller/DrawingController.js +++ b/js/controller/DrawingController.js @@ -3,19 +3,41 @@ ns.DrawingController = function (frame, container, dpi) { this.dpi = dpi; + // TODO(vincz): Store user prefs in a localstorage string ? var renderingOptions = { "dpi": dpi, - "displayGrid": true // Retrieve from localsotrage config - } + "gridStrokeWidth" : 1, + "gridStrokeColor" : "lightgray" + }; - // Public + // jQuery deep copy of the rendering config: + overlayRenderingOptions = $.extend(true, {}, renderingOptions); + overlayRenderingOptions.gridStrokeColor = "transparent"; + + /** + * @public + */ this.frame = frame; - this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(frame); // Type is frame + + /** + * @public + */ + this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(frame); - // Private + /** + * @private + */ this.container = container; - this.renderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions, "drawing-canvas"); - this.overlayRenderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions, "canvas-overlay"); + + this.renderer = new pskl.rendering.FrameRenderer( + this.container, + renderingOptions, + "drawing-canvas"); + + this.overlayRenderer = new pskl.rendering.FrameRenderer( + this.container, + overlayRenderingOptions, + "canvas-overlay"); this.renderer.init(this.frame); this.overlayRenderer.init(this.frame); @@ -53,7 +75,6 @@ body.mouseup($.proxy(this.onMouseup_, this)); // Deactivate right click: - this.container.contextmenu(this.onCanvasContextMenu_); //this.container.contextmenu(this.onCanvasContextMenu_); }; @@ -154,7 +175,7 @@ return { x : clientX - canvasPageOffset.left, y : clientY - canvasPageOffset.top - } + }; }; /** @@ -162,10 +183,7 @@ */ ns.DrawingController.prototype.getSpriteCoordinate = function(event) { var coords = this.getRelativeCoordinates(event.clientX, event.clientY); - return { - "col" : (coords.x - coords.x % this.dpi) / this.dpi, - "row" : (coords.y - coords.y % this.dpi) / this.dpi - } + return this.renderer.convertPixelCoordinatesIntoSpriteCoordinate(coords); }; /** From df945e10dd03cb7cad6ff1d6c49f74e94dc97e55 Mon Sep 17 00:00:00 2001 From: Vince Date: Sat, 8 Sep 2012 23:43:16 +0200 Subject: [PATCH 6/9] Add grid checkbox --- index.html | 7 ++++++ js/Constants.js | 5 ++++- js/Events.js | 2 ++ js/ToolSelector.js | 18 +++++++++++++++ js/controller/DrawingController.js | 6 ++--- js/rendering/FrameRenderer.js | 36 ++++++++++++++++++++++++------ 6 files changed, 63 insertions(+), 11 deletions(-) diff --git a/index.html b/index.html index 91efbe58..b0cb5181 100644 --- a/index.html +++ b/index.html @@ -52,6 +52,13 @@ 12 fps + +
    +
  • + + +
  • +
diff --git a/js/Constants.js b/js/Constants.js index ffa5d03f..8ef4e4da 100644 --- a/js/Constants.js +++ b/js/Constants.js @@ -12,5 +12,8 @@ var Constants = { /* * Default entry point for piskel web service: */ - PISKEL_SERVICE_URL: 'http://2.piskel-app.appspot.com' + PISKEL_SERVICE_URL: 'http://2.piskel-app.appspot.com', + + GRID_STROKE_WIDTH: 1, + GRID_STROKE_COLOR: "lightgray" }; \ No newline at end of file diff --git a/js/Events.js b/js/Events.js index df4dfb89..ce13ed7a 100644 --- a/js/Events.js +++ b/js/Events.js @@ -29,6 +29,8 @@ Events = { */ REDRAW_PREVIEWFILM: "REDRAW_PREVIEWFILM", + GRID_DISPLAY_STATE_CHANGED: "GRID_DISPLAY_STATE_CHANGED", + /** * The framesheet was reseted and is now probably drastically different. * Number of frames, content of frames, color used for the palette may have changed. diff --git a/js/ToolSelector.js b/js/ToolSelector.js index 0f69feaf..ed0c51e0 100644 --- a/js/ToolSelector.js +++ b/js/ToolSelector.js @@ -67,6 +67,17 @@ pskl.ToolSelector = (function() { } }; + /** + * Get state for the checkbox that control the display of the grid + * on the drawing canvas. + * @private + */ + var isShowGridChecked_ = function() { + var showGridCheckbox = $('#show-grid'); + var isChecked = showGridCheckbox.is(':checked'); + return isChecked; + }; + return { init: function() { @@ -75,6 +86,13 @@ pskl.ToolSelector = (function() { selectTool_(toolInstances.simplePen); // Activate listener on tool panel: $("#tools-container").click(onToolIconClicked_); + + // Show/hide the grid on drawing canvas: + $.publish(Events.GRID_DISPLAY_STATE_CHANGED, [isShowGridChecked_()]) + $('#show-grid').change(function(evt) { + var checked = isShowGridChecked_(); + $.publish(Events.GRID_DISPLAY_STATE_CHANGED, [checked]) + }); } }; })(); diff --git a/js/controller/DrawingController.js b/js/controller/DrawingController.js index b1a639f8..c6fa5dc9 100644 --- a/js/controller/DrawingController.js +++ b/js/controller/DrawingController.js @@ -6,14 +6,14 @@ // TODO(vincz): Store user prefs in a localstorage string ? var renderingOptions = { "dpi": dpi, - "gridStrokeWidth" : 1, - "gridStrokeColor" : "lightgray" + "hasGrid" : true }; // jQuery deep copy of the rendering config: overlayRenderingOptions = $.extend(true, {}, renderingOptions); - overlayRenderingOptions.gridStrokeColor = "transparent"; + overlayRenderingOptions.hasGrid = false; + /** * @public */ diff --git a/js/rendering/FrameRenderer.js b/js/rendering/FrameRenderer.js index 0490dfac..14f6ae42 100644 --- a/js/rendering/FrameRenderer.js +++ b/js/rendering/FrameRenderer.js @@ -5,8 +5,7 @@ ns.FrameRenderer = function (container, renderingOptions, className) { this.defaultRenderingOptions = { - "gridStrokeWidth" : 0, - "gridStrokeColor" : "lightgray" + "hasGrid" : false }; renderingOptions = $.extend(true, {}, this.defaultRenderingOptions, renderingOptions); @@ -22,16 +21,22 @@ this.dpi = renderingOptions.dpi; this.className = className; this.canvas = null; - console.log(renderingOptions) - this.gridStrokeWidth = renderingOptions.gridStrokeWidth; - this.gridStrokeColor = renderingOptions.gridStrokeColor; + this.hasGrid = renderingOptions.hasGrid; + this.gridStrokeWidth = 0; + + this.lastRenderedFrame = null; // Flag to know if the config was altered this.canvasConfigDirty = true; + + if(this.hasGrid) { + $.subscribe(Events.GRID_DISPLAY_STATE_CHANGED, $.proxy(this.showGrid, this)); + } }; ns.FrameRenderer.prototype.init = function (frame) { this.render(frame); + this.lastRenderedFrame = frame; }; ns.FrameRenderer.prototype.updateDPI = function (newDPI) { @@ -39,12 +44,27 @@ this.canvasConfigDirty = true; }; + ns.FrameRenderer.prototype.showGrid = function (evt, show) { + + this.gridStrokeWidth = 0; + if(show) { + this.gridStrokeWidth = Constants.GRID_STROKE_WIDTH; + } + + this.canvasConfigDirty = true; + + if(this.lastRenderedFrame) { + this.render(this.lastRenderedFrame); + } + }; + ns.FrameRenderer.prototype.render = function (frame) { for(var col = 0, width = frame.getWidth(); col < width; col++) { for(var row = 0, height = frame.getHeight(); row < height; row++) { this.drawPixel(col, row, frame, this.getCanvas_(frame, col, row), this.dpi); } } + this.lastRenderedFrame = frame; }; ns.FrameRenderer.prototype.drawPixel = function (col, row, frame) { @@ -61,6 +81,7 @@ context.fillStyle = color; context.fillRect(this.getFrameY_(col), this.getFrameY_(row), this.dpi, this.dpi); } + this.lastRenderedFrame = frame; }; ns.FrameRenderer.prototype.clear = function (col, row, frame) { @@ -100,8 +121,8 @@ */ ns.FrameRenderer.prototype.drawGrid_ = function(canvas, width, height, col, row) { var ctx = canvas.getContext("2d"); - ctx.lineWidth = this.gridStrokeWidth; - ctx.strokeStyle = this.gridStrokeColor; + ctx.lineWidth = Constants.GRID_STROKE_WIDTH; + ctx.strokeStyle = Constants.GRID_STROKE_COLOR; for(var c=1; c < col; c++) { ctx.moveTo(this.getFrameX_(c), 0); ctx.lineTo(this.getFrameX_(c), height); @@ -121,6 +142,7 @@ ns.FrameRenderer.prototype.getCanvas_ = function (frame) { if(this.canvasConfigDirty) { $(this.canvas).remove(); + var col = frame.getWidth(), row = frame.getHeight(); From f169a90644b7fb229674b40f78d430f13053d7bd Mon Sep 17 00:00:00 2001 From: Vince Date: Sat, 8 Sep 2012 23:53:59 +0200 Subject: [PATCH 7/9] Checkbox crappy styling and fixing overlayproxy grid --- css/tools.css | 7 +++++++ js/controller/DrawingController.js | 11 +++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/css/tools.css b/css/tools.css index 7aeb3f49..6b1f308b 100644 --- a/css/tools.css +++ b/css/tools.css @@ -77,6 +77,13 @@ cursor: url(../img/tools/cursors/hand.png) 14 12, pointer; } +.tool-grid, +.tool-grid label, +.tool-grid input { + line-height: 2.5; + cursor: pointer; +} + .tool-icon.selected { cursor: auto; background-color: #eee; diff --git a/js/controller/DrawingController.js b/js/controller/DrawingController.js index c6fa5dc9..da330fab 100644 --- a/js/controller/DrawingController.js +++ b/js/controller/DrawingController.js @@ -9,11 +9,6 @@ "hasGrid" : true }; - // jQuery deep copy of the rendering config: - overlayRenderingOptions = $.extend(true, {}, renderingOptions); - overlayRenderingOptions.hasGrid = false; - - /** * @public */ @@ -36,7 +31,7 @@ this.overlayRenderer = new pskl.rendering.FrameRenderer( this.container, - overlayRenderingOptions, + renderingOptions, "canvas-overlay"); this.renderer.init(this.frame); @@ -75,7 +70,7 @@ body.mouseup($.proxy(this.onMouseup_, this)); // Deactivate right click: - //this.container.contextmenu(this.onCanvasContextMenu_); + this.container.contextmenu(this.onCanvasContextMenu_); }; /** @@ -152,7 +147,7 @@ this.isClicked = false; this.isRightClicked = false; var spriteCoordinate = this.getSpriteCoordinate(event); - console.log("mousemove: col: " + spriteCoordinate.col + " - row: " + spriteCoordinate.row); + //console.log("mousemove: col: " + spriteCoordinate.col + " - row: " + spriteCoordinate.row); this.currentToolBehavior.releaseToolAt( spriteCoordinate.col, spriteCoordinate.row, From 0fe9ade8709b22aabfb487224c9879c8ae8c0988 Mon Sep 17 00:00:00 2001 From: Patrick Brosset Date: Sun, 9 Sep 2012 00:09:18 +0200 Subject: [PATCH 8/9] added subl project artefacts to gitignore --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 5509140f..742e0b2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,6 @@ +# mac artefacts *.DS_Store + +# sublime text stuff (the -project should actually be shared, but then we'd have to share the same disk location) +*.sublime-project +*.sublime-workspace \ No newline at end of file From d799221c24fb8fddf66e952f0deb04855b557f3b Mon Sep 17 00:00:00 2001 From: juliandescottes Date: Sun, 9 Sep 2012 00:28:58 +0200 Subject: [PATCH 9/9] Ignoring stackdump files from git --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 742e0b2c..69858933 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,7 @@ # sublime text stuff (the -project should actually be shared, but then we'd have to share the same disk location) *.sublime-project -*.sublime-workspace \ No newline at end of file +*.sublime-workspace + +# git stackdumps +*.stackdump \ No newline at end of file