diff --git a/css/style.css b/css/style.css index 41b51856..9889c932 100644 --- a/css/style.css +++ b/css/style.css @@ -154,6 +154,10 @@ ul, li { cursor: url(../img/tools/cursors/pen.png) 5 21, pointer; } +.tool-rectangle .drawing-canvas-container:hover { + cursor: url(../img/tools/cursors/rectangle.png) 4 21, pointer; +} + /** * Tool section: @@ -211,6 +215,7 @@ ul, li { width: 30px; height: 30px; border: 5px solid #fff; + background-color: #fff } .tool-icon:hover { @@ -243,6 +248,10 @@ ul, li { background: #fff url(../img/tools/icons/stroke.png) 3px 3px no-repeat; } +.tool-icon.tool-rectangle { + background: #fff url(../img/tools/icons/rectangle.png) 3px 3px no-repeat; +} + #preview-fps { width : 200px; } diff --git a/img/tools/cursors/rectangle.png b/img/tools/cursors/rectangle.png new file mode 100644 index 00000000..712daccf Binary files /dev/null and b/img/tools/cursors/rectangle.png differ diff --git a/img/tools/icons/rectangle.png b/img/tools/icons/rectangle.png new file mode 100644 index 00000000..8a148f6d Binary files /dev/null and b/img/tools/icons/rectangle.png differ diff --git a/index.html b/index.html index 5eade9ee..648a11ba 100644 --- a/index.html +++ b/index.html @@ -38,6 +38,7 @@
+
@@ -80,6 +81,7 @@ + diff --git a/js/ToolSelector.js b/js/ToolSelector.js index 05329808..11d47765 100644 --- a/js/ToolSelector.js +++ b/js/ToolSelector.js @@ -12,7 +12,8 @@ pskl.ToolSelector = (function() { "simplePen" : new pskl.drawingtools.SimplePen(), "eraser" : new pskl.drawingtools.Eraser(), "paintBucket" : new pskl.drawingtools.PaintBucket(), - "stroke" : new pskl.drawingtools.Stroke() + "stroke" : new pskl.drawingtools.Stroke(), + "rectangle" : new pskl.drawingtools.Rectangle() }; var currentSelectedTool = toolInstances.simplePen; var previousSelectedTool = toolInstances.simplePen; diff --git a/js/drawingtools/Rectangle.js b/js/drawingtools/Rectangle.js new file mode 100644 index 00000000..d139ee04 --- /dev/null +++ b/js/drawingtools/Rectangle.js @@ -0,0 +1,125 @@ +/* + * @provide pskl.drawingtools.Rectangle + * + * @require pskl.utils + */ +(function() { + var ns = $.namespace("pskl.drawingtools"); + + ns.Rectangle = function() { + this.toolId = "tool-rectangle" + + // Rectangle's first point coordinates (set in applyToolAt) + this.startCol = null; + this.startRow = null; + // Rectangle's second point coordinates (changing dynamically in moveToolAt) + this.endCol = null; + this.endRow = null; + + this.canvasOverlay = null; + }; + + pskl.utils.inherit(ns.Rectangle, ns.BaseTool); + + /** + * @override + */ + ns.Rectangle.prototype.applyToolAt = function(col, row, frame, color, canvas, dpi) { + this.startCol = col; + this.startRow = row; + + // The fake canvas where we will draw the preview of the rectangle: + this.canvasOverlay = this.createCanvasOverlay(canvas); + // Drawing the first point of the rectangle in the fake overlay canvas: + this.drawPixelInCanvas(col, row, this.canvasOverlay, color, dpi); + }; + + ns.Rectangle.prototype.moveToolAt = function(col, row, frame, color, canvas, dpi) { + this.endCol = col; + this.endRow = row; + // When the user moussemove (before releasing), we dynamically compute the + // pixel to draw the line and draw this line in the overlay canvas: + var strokePoints = this.getRectanglePixels_(this.startCol, this.endCol, this.startRow, this.endRow); + + // Clean overlay canvas: + this.canvasOverlay.getContext("2d").clearRect( + 0, 0, this.canvasOverlay.width, this.canvasOverlay.height); + + // Drawing current stroke: + for(var i = 0; i< strokePoints.length; i++) { + + if(color == Constants.TRANSPARENT_COLOR) { + color = "rgba(255, 255, 255, 0.6)"; + } + this.drawPixelInCanvas(strokePoints[i].col, strokePoints[i].row, this.canvasOverlay, color, dpi); + } + }; + + /** + * @override + */ + ns.Rectangle.prototype.releaseToolAt = function(col, row, frame, color, canvas, dpi) { + this.endCol = col; + this.endRow = row; + + // If the stroke tool is released outside of the canvas, we cancel the stroke: + // TODO: Mutualize this check in common method + if(col < 0 || row < 0 || col > frame.length || row > frame[0].length) { + this.removeCanvasOverlays(); + return; + } + + // The user released the tool to draw a line. We will compute the pixel coordinate, impact + // the model and draw them in the drawing canvas (not the fake overlay anymore) + var strokePoints = this.getRectanglePixels_(this.startCol, this.endCol, this.startRow, this.endRow); + + for(var i = 0; i< strokePoints.length; i++) { + // Change model: + frame[strokePoints[i].col][strokePoints[i].row] = color; + + // Draw in canvas: + // TODO: Remove that when we have the centralized redraw loop + this.drawPixelInCanvas(strokePoints[i].col, strokePoints[i].row, canvas, color, dpi); + } + + // For now, we are done with the stroke tool and don't need an overlay anymore: + this.removeCanvasOverlays(); + }; + + /** + * Get an array of pixels representing the rectangle. + * + * @private + */ + ns.Rectangle.prototype.getRectanglePixels_ = function(x0, x1, y0, y1) { + + var pixels = []; + var swap; + + if(x0 > x1) { + swap = x0; + x0 = x1; + x1 = swap; + } + if(y0 > y1) { + swap = y0; + y0 = y1; + y1 = swap; + } + + // Creating horizontal sides of the rectangle: + for(var x = x0; x <= x1; x++) { + pixels.push({"col": x, "row": y0}); + pixels.push({"col": x, "row": y1}); + } + + // Creating vertical sides of the rectangle: + for(var y = y0; y <= y1; y++) { + pixels.push({"col": x0, "row": y}); + pixels.push({"col": x1, "row": y}); + } + + return pixels; + }; + +})(); diff --git a/js/drawingtools/Stroke.js b/js/drawingtools/Stroke.js index ca4cdc4b..aa58592f 100644 --- a/js/drawingtools/Stroke.js +++ b/js/drawingtools/Stroke.js @@ -1,5 +1,5 @@ /* - * @provide pskl.drawingtools.SimplePen + * @provide pskl.drawingtools.Stroke * * @require pskl.utils */ @@ -75,7 +75,8 @@ this.endCol = col; this.endRow = row; - // If the stroke tool is released outside of the canvas, we cancel the stroke: + // If the stroke tool is released outside of the canvas, we cancel the stroke: + // TODO: Mutualize this check in common method if(col < 0 || row < 0 || col > frame.length || row > frame[0].length) { this.removeCanvasOverlays(); return;