2018-04-04 17:37:11 -04:00
|
|
|
import paper from '@scratch/paper';
|
|
|
|
import {getRaster} from '../layer';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tool for drawing with the bitmap brush.
|
|
|
|
*/
|
|
|
|
class BrushTool extends paper.Tool {
|
|
|
|
/**
|
|
|
|
* @param {!function} onUpdateSvg A callback to call when the image visibly changes
|
|
|
|
*/
|
|
|
|
constructor (onUpdateSvg) {
|
|
|
|
super();
|
|
|
|
this.onUpdateSvg = onUpdateSvg;
|
|
|
|
|
|
|
|
// We have to set these functions instead of just declaring them because
|
|
|
|
// paper.js tools hook up the listeners in the setter functions.
|
|
|
|
this.onMouseDown = this.handleMouseDown;
|
|
|
|
this.onMouseDrag = this.handleMouseDrag;
|
|
|
|
this.onMouseUp = this.handleMouseUp;
|
|
|
|
|
|
|
|
this.colorState = null;
|
|
|
|
this.active = false;
|
2018-04-04 23:54:41 -04:00
|
|
|
this.lastPoint = null;
|
2018-04-05 01:10:36 -04:00
|
|
|
this.size = 5;
|
2018-04-04 17:37:11 -04:00
|
|
|
}
|
2018-04-04 23:54:41 -04:00
|
|
|
setColor (color) {
|
2018-04-05 01:32:27 -04:00
|
|
|
this.color = color ? color : new paper.Color(0, 0, 0, 0);
|
2018-04-04 23:54:41 -04:00
|
|
|
}
|
2018-04-05 01:10:36 -04:00
|
|
|
bresenhamLine (point1, point2, callback){
|
2018-04-04 23:54:41 -04:00
|
|
|
// Fast Math.floor
|
|
|
|
let x1 = ~~point1.x;
|
|
|
|
let x2 = ~~point2.x;
|
|
|
|
let y1 = ~~point1.y;
|
|
|
|
let y2 = ~~point2.y;
|
|
|
|
|
|
|
|
const dx = Math.abs(x2 - x1);
|
|
|
|
const dy = Math.abs(y2 - y1);
|
|
|
|
const sx = (x1 < x2) ? 1 : -1;
|
|
|
|
const sy = (y1 < y2) ? 1 : -1;
|
|
|
|
let err = dx - dy;
|
|
|
|
|
2018-04-05 01:10:36 -04:00
|
|
|
callback(x1, y1);
|
2018-04-04 23:54:41 -04:00
|
|
|
while (x1 !== x2 || y1 !== y2) {
|
|
|
|
let e2 = err*2;
|
|
|
|
if (e2 >-dy) {
|
|
|
|
err -= dy; x1 += sx;
|
|
|
|
}
|
|
|
|
if (e2 < dx) {
|
|
|
|
err += dx; y1 += sy;
|
|
|
|
}
|
2018-04-05 01:10:36 -04:00
|
|
|
callback(x1, y1);
|
2018-04-04 23:54:41 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Draw a brush mark at the given point
|
2018-04-05 01:10:36 -04:00
|
|
|
draw (centerX, centerY) {
|
|
|
|
for (let x = centerX - this.size; x <= centerX + this.size; x++) {
|
|
|
|
for (let y = centerY - this.size; y <= centerY + this.size; y++) {
|
|
|
|
getRaster().setPixel(new paper.Point(x, y), this.color);
|
|
|
|
}
|
|
|
|
}
|
2018-04-04 17:37:11 -04:00
|
|
|
}
|
|
|
|
handleMouseDown (event) {
|
|
|
|
if (event.event.button > 0) return; // only first mouse button
|
|
|
|
this.active = true;
|
2018-04-05 01:10:36 -04:00
|
|
|
this.draw(event.point, event.point);
|
2018-04-04 23:54:41 -04:00
|
|
|
this.lastPoint = event.point;
|
2018-04-04 17:37:11 -04:00
|
|
|
}
|
|
|
|
handleMouseDrag (event) {
|
|
|
|
if (event.event.button > 0 || !this.active) return; // only first mouse button
|
|
|
|
|
|
|
|
if (this.isBoundingBoxMode) {
|
|
|
|
this.boundingBoxTool.onMouseDrag(event);
|
|
|
|
return;
|
|
|
|
}
|
2018-04-05 01:10:36 -04:00
|
|
|
this.bresenhamLine(this.lastPoint, event.point, this.draw.bind(this));
|
2018-04-04 23:54:41 -04:00
|
|
|
this.lastPoint = event.point;
|
2018-04-04 17:37:11 -04:00
|
|
|
}
|
|
|
|
handleMouseUp (event) {
|
|
|
|
if (event.event.button > 0 || !this.active) return; // only first mouse button
|
2018-04-05 01:10:36 -04:00
|
|
|
this.bresenhamLine(this.lastPoint, event.point, this.draw.bind(this));
|
2018-04-04 23:54:41 -04:00
|
|
|
this.lastPoint = null;
|
2018-04-04 17:37:11 -04:00
|
|
|
this.active = false;
|
|
|
|
}
|
|
|
|
deactivateTool () {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default BrushTool;
|