Implement brush movement interpolation

main
kts of kettek 2024-02-16 12:08:35 -08:00
parent 455a9887ac
commit e6a28635f8
1 changed files with 38 additions and 19 deletions

View File

@ -40,12 +40,18 @@ export interface PickerToolContext {
} }
export class BrushTool implements Tool { export class BrushTool implements Tool {
private lastX: number
private lastY: number
private active: boolean private active: boolean
isActive(): boolean { isActive(): boolean {
return this.active return this.active
} }
pointerDown(ctx: ToolContext & BrushToolContext, ptr: Pointer) { pointerDown(ctx: ToolContext & BrushToolContext, ptr: Pointer) {
// Store last for interp.
this.lastX = ptr.x
this.lastY = ptr.y
this.active = true this.active = true
ctx.file.capture() ctx.file.capture()
if (ctx.brushSize == 1) { if (ctx.brushSize == 1) {
@ -73,28 +79,41 @@ export class BrushTool implements Tool {
} }
} }
pointerMove(ctx: ToolContext & BrushToolContext, ptr: Pointer) { pointerMove(ctx: ToolContext & BrushToolContext, ptr: Pointer) {
if (ctx.brushSize == 1) { let dx = this.lastX - ptr.x
let p = ctx.file.canvas.getPixel(ptr.x, ptr.y) let dy = this.lastY - ptr.y
if (p !== -1) { this.lastX = ptr.x
ctx.file.push(new PixelPlaceUndoable(ptr.x, ptr.y, p, ctx.colorIndex)) this.lastY = ptr.y
}
} else if (ctx.brushSize == 2) { let angle = Math.atan2(dy, dx)
for (let x1 = 0; x1 < 2; x1++) { let dist = Math.sqrt(dx*dx + dy*dy)
for (let y1 = 0; y1 < 2; y1++) { let steps = Math.ceil(dist)
let p = ctx.file.canvas.getPixel(ptr.x+x1, ptr.y+y1) for (let i = 0; i < steps; i++) {
if (p !== -1) { let x = Math.floor(this.lastX + Math.cos(angle) * i)
ctx.file.push(new PixelPlaceUndoable(ptr.x+x1, ptr.y+y1, p, ctx.colorIndex)) let y = Math.floor(this.lastY + Math.sin(angle) * i)
if (ctx.brushSize == 1) {
let p = ctx.file.canvas.getPixel(x, y)
if (p !== -1) {
ctx.file.push(new PixelPlaceUndoable(x, y, p, ctx.colorIndex))
}
} else if (ctx.brushSize == 2) {
for (let x1 = 0; x1 < 2; x1++) {
for (let y1 = 0; y1 < 2; y1++) {
let p = ctx.file.canvas.getPixel(x+x1, y+y1)
if (p !== -1) {
ctx.file.push(new PixelPlaceUndoable(x+x1, y+y1, p, ctx.colorIndex))
}
} }
} }
} else {
let shape: PixelPosition[]
if (ctx.brushType == "circle") {
shape = FilledCircle(x, y, ctx.brushSize-2, ctx.colorIndex)
} else if (ctx.brushType == "square") {
shape = FilledSquare(x, y, ctx.brushSize, ctx.colorIndex)
}
ctx.file.push(new PixelsPlaceUndoable(shape))
} }
} else {
let shape: PixelPosition[]
if (ctx.brushType == "circle") {
shape = FilledCircle(ptr.x, ptr.y, ctx.brushSize-2, ctx.colorIndex)
} else if (ctx.brushType == "square") {
shape = FilledSquare(ptr.x, ptr.y, ctx.brushSize, ctx.colorIndex)
}
ctx.file.push(new PixelsPlaceUndoable(shape))
} }
} }
pointerUp(ctx: ToolContext, ptr: Pointer) { pointerUp(ctx: ToolContext, ptr: Pointer) {