mirror of
				https://github.com/piskelapp/piskel.git
				synced 2023-08-10 21:12:52 +03:00 
			
		
		
		
	Feature : Hold shift to preserve shape ratio
- mutualized shape tools common code in a ShapeTool class - when holding shift and drawing a frame, the ratio is preserved - selection and shape tools now support the mouse to leave the drawing area - shape tools can go 'outside' the drawing canvas - Frame set/getPixel now check the pixel is in range instead of crashing
This commit is contained in:
		| @@ -40,7 +40,7 @@ | |||||||
|   -moz-box-sizing : border-box; |   -moz-box-sizing : border-box; | ||||||
|  |  | ||||||
|   border-radius: 3px; |   border-radius: 3px; | ||||||
|   background: rgba(0,0,0,0.9); |   background: rgba(0,0,0,1); | ||||||
|   overflow: auto; |   overflow: auto; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -120,7 +120,7 @@ | |||||||
|    * @private |    * @private | ||||||
|    */ |    */ | ||||||
|   ns.DrawingController.prototype.onMouseenter_ = function (event) { |   ns.DrawingController.prototype.onMouseenter_ = function (event) { | ||||||
|     this.container.bind('mousemove', $.proxy(this.onMousemove_, this)); |     $('body').bind('mousemove', $.proxy(this.onMousemove_, this)); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|   | |||||||
| @@ -7,49 +7,15 @@ | |||||||
|   var ns = $.namespace("pskl.drawingtools"); |   var ns = $.namespace("pskl.drawingtools"); | ||||||
|  |  | ||||||
|   ns.Circle = function() { |   ns.Circle = function() { | ||||||
|  |     ns.ShapeTool.call(this); | ||||||
|  |  | ||||||
|     this.toolId = "tool-circle"; |     this.toolId = "tool-circle"; | ||||||
|     this.helpText = "Circle tool"; |     this.helpText = "Circle tool"; | ||||||
|  |  | ||||||
|     // Circle's first point coordinates (set in applyToolAt) |  | ||||||
|     this.startCol = null; |  | ||||||
|     this.startRow = null; |  | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   pskl.utils.inherit(ns.Circle, ns.BaseTool); |   pskl.utils.inherit(ns.Circle, ns.ShapeTool); | ||||||
|  |  | ||||||
|   /** |   ns.Circle.prototype.draw_ = function (col, row, color, targetFrame) { | ||||||
|    * @override |  | ||||||
|    */ |  | ||||||
|   ns.Circle.prototype.applyToolAt = function(col, row, color, frame, overlay, event) { |  | ||||||
|     this.startCol = col; |  | ||||||
|     this.startRow = row; |  | ||||||
|  |  | ||||||
|     // Drawing the first point of the rectangle in the fake overlay canvas: |  | ||||||
|     overlay.setPixel(col, row, color); |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   ns.Circle.prototype.moveToolAt = function(col, row, color, frame, overlay, event) { |  | ||||||
|     overlay.clear(); |  | ||||||
|     if(color == Constants.TRANSPARENT_COLOR) { |  | ||||||
|       color = Constants.SELECTION_TRANSPARENT_COLOR; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // draw in overlay |  | ||||||
|     this.drawCircle_(col, row, color, overlay); |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * @override |  | ||||||
|    */ |  | ||||||
|   ns.Circle.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) { |  | ||||||
|     overlay.clear(); |  | ||||||
|     if(frame.containsPixel(col, row)) { // cancel if outside of canvas |  | ||||||
|       // draw in frame to finalize |  | ||||||
|       this.drawCircle_(col, row, color, frame); |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   ns.Circle.prototype.drawCircle_ = function (col, row, color, targetFrame) { |  | ||||||
|     var circlePoints = this.getCirclePixels_(this.startCol, this.startRow, col, row); |     var circlePoints = this.getCirclePixels_(this.startCol, this.startRow, col, row); | ||||||
|     for(var i = 0; i< circlePoints.length; i++) { |     for(var i = 0; i< circlePoints.length; i++) { | ||||||
|       // Change model: |       // Change model: | ||||||
|   | |||||||
| @@ -7,49 +7,15 @@ | |||||||
|   var ns = $.namespace("pskl.drawingtools"); |   var ns = $.namespace("pskl.drawingtools"); | ||||||
|  |  | ||||||
|   ns.Rectangle = function() { |   ns.Rectangle = function() { | ||||||
|  |     ns.ShapeTool.call(this); | ||||||
|  |  | ||||||
|     this.toolId = "tool-rectangle"; |     this.toolId = "tool-rectangle"; | ||||||
|     this.helpText = "Rectangle tool"; |     this.helpText = "Rectangle tool"; | ||||||
|  |  | ||||||
|     // Rectangle's first point coordinates (set in applyToolAt) |  | ||||||
|     this.startCol = null; |  | ||||||
|     this.startRow = null; |  | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   pskl.utils.inherit(ns.Rectangle, ns.BaseTool); |   pskl.utils.inherit(ns.Rectangle, ns.ShapeTool); | ||||||
|  |  | ||||||
|   /** |   ns.Rectangle.prototype.draw_ = function (col, row, color, targetFrame) { | ||||||
|    * @override |  | ||||||
|    */ |  | ||||||
|   ns.Rectangle.prototype.applyToolAt = function(col, row, color, frame, overlay, event) { |  | ||||||
|     this.startCol = col; |  | ||||||
|     this.startRow = row; |  | ||||||
|  |  | ||||||
|     // Drawing the first point of the rectangle in the fake overlay canvas: |  | ||||||
|     overlay.setPixel(col, row, color); |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   ns.Rectangle.prototype.moveToolAt = function(col, row, color, frame, overlay, event) { |  | ||||||
|     overlay.clear(); |  | ||||||
|     if(color == Constants.TRANSPARENT_COLOR) { |  | ||||||
|       color = Constants.SELECTION_TRANSPARENT_COLOR; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // draw in overlay |  | ||||||
|     this.drawRectangle_(col, row, color, overlay); |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * @override |  | ||||||
|    */ |  | ||||||
|   ns.Rectangle.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) { |  | ||||||
|     overlay.clear(); |  | ||||||
|     if(frame.containsPixel(col, row)) { // cancel if outside of canvas |  | ||||||
|       // draw in frame to finalize |  | ||||||
|       this.drawRectangle_(col, row, color, frame); |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   ns.Rectangle.prototype.drawRectangle_ = function (col, row, color, targetFrame) { |  | ||||||
|     var strokePoints = pskl.PixelUtils.getBoundRectanglePixels(this.startCol, this.startRow, col, row); |     var strokePoints = pskl.PixelUtils.getBoundRectanglePixels(this.startCol, this.startRow, col, row); | ||||||
|     for(var i = 0; i< strokePoints.length; i++) { |     for(var i = 0; i< strokePoints.length; i++) { | ||||||
|       // Change model: |       // Change model: | ||||||
|   | |||||||
							
								
								
									
										89
									
								
								src/js/drawingtools/ShapeTool.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/js/drawingtools/ShapeTool.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | |||||||
|  | (function () { | ||||||
|  |   var ns = $.namespace('pskl.drawingtools'); | ||||||
|  |   /** | ||||||
|  |    * Abstract shape tool class, parent to all shape tools (rectangle, circle). | ||||||
|  |    * Shape tools should override only the draw_ method | ||||||
|  |    */ | ||||||
|  |   ns.ShapeTool = function() { | ||||||
|  |     // Shapes's first point coordinates (set in applyToolAt) | ||||||
|  |     this.startCol = null; | ||||||
|  |     this.startRow = null; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   pskl.utils.inherit(ns.ShapeTool, ns.BaseTool); | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * @override | ||||||
|  |    */ | ||||||
|  |   ns.ShapeTool.prototype.applyToolAt = function(col, row, color, frame, overlay, event) { | ||||||
|  |     this.startCol = col; | ||||||
|  |     this.startRow = row; | ||||||
|  |  | ||||||
|  |     // Drawing the first point of the rectangle in the fake overlay canvas: | ||||||
|  |     overlay.setPixel(col, row, color); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   ns.ShapeTool.prototype.moveToolAt = function(col, row, color, frame, overlay, event) { | ||||||
|  |     overlay.clear(); | ||||||
|  |     if(color == Constants.TRANSPARENT_COLOR) { | ||||||
|  |       color = Constants.SELECTION_TRANSPARENT_COLOR; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     var coords = this.getCoordinates_(col, row, event); | ||||||
|  |     // draw in overlay | ||||||
|  |     this.draw_(coords.col, coords.row, color, overlay); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * @override | ||||||
|  |    */ | ||||||
|  |   ns.ShapeTool.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) { | ||||||
|  |     overlay.clear(); | ||||||
|  |     if (event.shiftKey) { | ||||||
|  |       var scaled = this.getScaledCoordinates_(col, row); | ||||||
|  |       col = scaled.col; | ||||||
|  |       row = scaled.row; | ||||||
|  |     } | ||||||
|  |     var coords = this.getCoordinates_(col, row, event); | ||||||
|  |     this.draw_(coords.col, coords.row, color, frame); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Transform the current coordinates based on the original event | ||||||
|  |    * @param {Number} col current col/x coordinate in the frame | ||||||
|  |    * @param {Number} row current row/y coordinate in the frame | ||||||
|  |    * @param {Event} event current event (can be mousemove, mouseup ...) | ||||||
|  |    * @return {Object} {row : Number, col : Number} | ||||||
|  |    */ | ||||||
|  |   ns.ShapeTool.prototype.getCoordinates_ = function(col, row, event) { | ||||||
|  |     if (event.shiftKey) { | ||||||
|  |       return this.getScaledCoordinates_(col, row); | ||||||
|  |     } else { | ||||||
|  |       return {col : col, row : row}; | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Transform the coordinates to preserve a square 1:1 ratio from the origin of the shape | ||||||
|  |    * @param {Number} col current col/x coordinate in the frame | ||||||
|  |    * @param {Number} row current row/y coordinate in the frame | ||||||
|  |    * @return {Object} {row : Number, col : Number} | ||||||
|  |    */ | ||||||
|  |   ns.ShapeTool.prototype.getScaledCoordinates_ = function(col, row) { | ||||||
|  |     var sign; | ||||||
|  |     if (Math.abs(this.startCol - col) > Math.abs(this.startRow - row)) { | ||||||
|  |       sign = row > this.startRow ? 1 : -1; | ||||||
|  |       row = this.startRow + (sign * Math.abs(this.startCol - col)); | ||||||
|  |     } else { | ||||||
|  |       sign = col > this.startCol ? 1 : -1; | ||||||
|  |       col = this.startCol + (sign * Math.abs(this.startRow - row)); | ||||||
|  |     } | ||||||
|  |     return { | ||||||
|  |       col : col, | ||||||
|  |       row : row | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   ns.ShapeTool.prototype.draw_ = Constants.ABSTRACT_FUNCTION; | ||||||
|  |  | ||||||
|  | })(); | ||||||
| @@ -80,15 +80,16 @@ | |||||||
|    * @override |    * @override | ||||||
|    */ |    */ | ||||||
|   ns.BaseSelect.prototype.moveUnactiveToolAt = function(col, row, color, frame, overlay, event) { |   ns.BaseSelect.prototype.moveUnactiveToolAt = function(col, row, color, frame, overlay, event) { | ||||||
|  |     if (overlay.containsPixel(col, row)) { | ||||||
|     if(overlay.getPixel(col, row) != Constants.SELECTION_TRANSPARENT_COLOR) { |       if(overlay.getPixel(col, row) != Constants.SELECTION_TRANSPARENT_COLOR) { | ||||||
|       // We're hovering the selection, show the move tool: |         // We're hovering the selection, show the move tool: | ||||||
|       this.BodyRoot.addClass(this.toolId); |         this.BodyRoot.addClass(this.toolId); | ||||||
|       this.BodyRoot.removeClass(this.secondaryToolId); |         this.BodyRoot.removeClass(this.secondaryToolId); | ||||||
|     } else { |       } else { | ||||||
|       // We're not hovering the selection, show create selection tool: |         // We're not hovering the selection, show create selection tool: | ||||||
|       this.BodyRoot.addClass(this.secondaryToolId); |         this.BodyRoot.addClass(this.secondaryToolId); | ||||||
|       this.BodyRoot.removeClass(this.toolId); |         this.BodyRoot.removeClass(this.toolId); | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -83,11 +83,17 @@ | |||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   ns.Frame.prototype.setPixel = function (col, row, color) { |   ns.Frame.prototype.setPixel = function (col, row, color) { | ||||||
|     this.pixels[col][row] = color; |     if (this.containsPixel(col, row)) { | ||||||
|  |       this.pixels[col][row] = color; | ||||||
|  |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   ns.Frame.prototype.getPixel = function (col, row) { |   ns.Frame.prototype.getPixel = function (col, row) { | ||||||
|     return this.pixels[col][row]; |     if (this.containsPixel(col, row)) { | ||||||
|  |       return this.pixels[col][row]; | ||||||
|  |     } else { | ||||||
|  |       return null; | ||||||
|  |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   ns.Frame.prototype.forEachPixel = function (callback) { |   ns.Frame.prototype.forEachPixel = function (callback) { | ||||||
| @@ -107,7 +113,7 @@ | |||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   ns.Frame.prototype.containsPixel = function (col, row) { |   ns.Frame.prototype.containsPixel = function (col, row) { | ||||||
|     return col >= 0 && row >= 0 && col < this.pixels.length && row < this.pixels[0].length; |     return col >= 0 && row >= 0 && col < this.width && row < this.height; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   ns.Frame.prototype.saveState = function () { |   ns.Frame.prototype.saveState = function () { | ||||||
|   | |||||||
| @@ -100,6 +100,7 @@ exports.scripts = [ | |||||||
|  |  | ||||||
|   // Tools |   // Tools | ||||||
|   "js/drawingtools/BaseTool.js", |   "js/drawingtools/BaseTool.js", | ||||||
|  |   "js/drawingtools/ShapeTool.js", | ||||||
|   "js/drawingtools/SimplePen.js", |   "js/drawingtools/SimplePen.js", | ||||||
|   "js/drawingtools/VerticalMirrorPen.js", |   "js/drawingtools/VerticalMirrorPen.js", | ||||||
|   "js/drawingtools/Eraser.js", |   "js/drawingtools/Eraser.js", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 jdescottes
					jdescottes