1import PaintCommand from "px/commands/paint" 2import { Tool } from "px/tools/tool" 3import { Overlay } from "px/tools/overlay" 4import { drawLegoTile } from "px/utils/lego_tile" 5import { EventEmitter } from "px/utils/events"; 6import { receive } from "px/utils/deferred_promise"; 7 8export default class extends Tool { 9 constructor(editor, renderer) { 10 super(editor); 11 Object.assign(this, EventEmitter); 12 13 this.renderer = renderer; 14 this.input = renderer.input; 15 this.painting = false; 16 this.paintCoords = []; 17 this.overlay = null; 18 } 19 20 async activate() { 21 this.input.on('mouseDown', this.onMouseDown); 22 this.input.on('mouseMove', this.onMouseMove); 23 this.input.on('mouseUp', this.onMouseUp); 24 } 25 26 async deactivate() { 27 this.input.off('mouseDown', this.onMouseDown); 28 this.input.off('mouseMove', this.onMouseMove); 29 this.input.off('mouseUp', this.onMouseUp); 30 } 31 32 onMouseDown = (coords) => { 33 this.painting = true; 34 this._emit("paintingStarted"); 35 this.paintCoords = []; 36 37 const absolutePoint = this.mapLogicalToAbsolute(coords.x, coords.y); 38 this.paintCoords.push(absolutePoint); 39 40 this.overlay = new Overlay(this.renderer); 41 this._updateOverlay(this.paintCoords); 42 } 43 44 onMouseMove = (coords) => { 45 if (this.painting) { 46 const absolutePoint = this.mapLogicalToAbsolute(coords.x, coords.y); 47 this.paintCoords.push(absolutePoint); 48 this._updateOverlay(this.paintCoords); 49 } 50 } 51 52 onMouseUp = async () => { 53 if (this.painting) { 54 const currentColor = (await receive("uiSettings")).get("currentColor"); 55 const paintCommand = new PaintCommand({ coords: this.paintCoords, color: currentColor }); 56 this.painting = false; 57 this._emit("paintingFinished"); 58 this.paintCoords = []; 59 const overlay = this.overlay; 60 this.overlay = null; 61 62 const imageVersion = await this.editor.execute(paintCommand); 63 overlay.hideOnCommandReady(imageVersion); 64 } 65 } 66 67 async _updateOverlay(coords) { 68 const currentColor = (await receive("uiSettings")).get("currentColor"); 69 const paintCommand = new PaintCommand({ coords: coords, color: currentColor }); 70 const context = this.editor.currentContext; 71 const pixelCoords = paintCommand.getPixelCoords(context.transform); 72 const overlayCtx = this.overlay.ctx; 73 74 const viewport = this.renderer.viewport; 75 const scale = viewport.scale; 76 77 this.overlay.clear(); 78 79 // Only paint pixels that are within the image boundaries 80 for (const pixelCoord of pixelCoords) { 81 if (pixelCoord.x >= 0 && pixelCoord.x < viewport.imageWidth && 82 pixelCoord.y >= 0 && pixelCoord.y < viewport.imageHeight) { 83 const centerX = (pixelCoord.x + 0.5) * scale + viewport.offsetX; 84 const centerY = (pixelCoord.y + 0.5) * scale + viewport.offsetY; 85 drawLegoTile(overlayCtx, centerX, centerY, scale, `#${currentColor}`); 86 } 87 } 88 } 89}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.