Add some magic
parent
7cce4f2fbd
commit
6bbb473784
|
|
@ -14,10 +14,10 @@
|
||||||
|
|
||||||
import { OverflowMenu, OverflowMenuItem } from "carbon-components-svelte"
|
import { OverflowMenu, OverflowMenuItem } from "carbon-components-svelte"
|
||||||
|
|
||||||
import { Close, Erase, PaintBrushAlt, RainDrop, Redo, Select_01, Undo, Scale, Eyedropper, Move } from "carbon-icons-svelte"
|
import { Close, Erase, PaintBrushAlt, RainDrop, Redo, Select_01, Undo, Scale, Eyedropper, Move, MagicWand } from "carbon-icons-svelte"
|
||||||
import StackPreview from './sections/StackPreview.svelte'
|
import StackPreview from './sections/StackPreview.svelte'
|
||||||
import type { Canvas } from './types/canvas'
|
import type { Canvas } from './types/canvas'
|
||||||
import { BrushTool, EraserTool, FillTool, PickerTool, SelectionTool, type BrushType, type Tool, MoveTool } from './types/tools'
|
import { BrushTool, EraserTool, FillTool, PickerTool, SelectionTool, MagicWandTool, type BrushType, type Tool, MoveTool } from './types/tools'
|
||||||
import BrushSize from './components/BrushSize.svelte'
|
import BrushSize from './components/BrushSize.svelte'
|
||||||
import Shortcut from './components/Shortcut.svelte'
|
import Shortcut from './components/Shortcut.svelte'
|
||||||
import Shortcuts from './components/Shortcuts.svelte'
|
import Shortcuts from './components/Shortcuts.svelte'
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
let showPreview: boolean = false
|
let showPreview: boolean = false
|
||||||
|
|
||||||
let toolSelection = new SelectionTool()
|
let toolSelection = new SelectionTool()
|
||||||
|
let toolMagicWand = new MagicWandTool()
|
||||||
let toolFill = new FillTool()
|
let toolFill = new FillTool()
|
||||||
let toolErase = new EraserTool()
|
let toolErase = new EraserTool()
|
||||||
let toolBrush = new BrushTool()
|
let toolBrush = new BrushTool()
|
||||||
|
|
@ -147,6 +148,7 @@
|
||||||
<menu class='toolbar'>
|
<menu class='toolbar'>
|
||||||
<Button isSelected={currentTool === toolMove} kind="ghost" size="small" icon={Move} iconDescription="move" tooltipPosition="right" on:click={()=>swapTool(toolMove)}></Button>
|
<Button isSelected={currentTool === toolMove} kind="ghost" size="small" icon={Move} iconDescription="move" tooltipPosition="right" on:click={()=>swapTool(toolMove)}></Button>
|
||||||
<Button isSelected={currentTool === toolSelection} kind="ghost" size="small" icon={Select_01} iconDescription="selection" tooltipPosition="right" on:click={()=>swapTool(toolSelection)}></Button>
|
<Button isSelected={currentTool === toolSelection} kind="ghost" size="small" icon={Select_01} iconDescription="selection" tooltipPosition="right" on:click={()=>swapTool(toolSelection)}></Button>
|
||||||
|
<Button isSelected={currentTool === toolMagicWand} kind="ghost" size="small" icon={MagicWand} iconDescription="magic selection" tooltipPosition="right" on:click={()=>swapTool(toolMagicWand)}></Button>
|
||||||
<Button isSelected={currentTool === toolFill} kind="ghost" size="small" icon={RainDrop} iconDescription="fill" tooltipPosition="right" on:click={()=>swapTool(toolFill)}></Button>
|
<Button isSelected={currentTool === toolFill} kind="ghost" size="small" icon={RainDrop} iconDescription="fill" tooltipPosition="right" on:click={()=>swapTool(toolFill)}></Button>
|
||||||
<Button isSelected={currentTool === toolBrush} kind="ghost" size="small" icon={PaintBrushAlt} iconDescription="paint" tooltipPosition="right" on:click={()=>swapTool(toolBrush)}></Button>
|
<Button isSelected={currentTool === toolBrush} kind="ghost" size="small" icon={PaintBrushAlt} iconDescription="paint" tooltipPosition="right" on:click={()=>swapTool(toolBrush)}></Button>
|
||||||
<Button isSelected={currentTool === toolPicker} kind="ghost" size="small" icon={Eyedropper} iconDescription="pick" tooltipPosition="right" on:click={()=>swapTool(toolPicker)}></Button>
|
<Button isSelected={currentTool === toolPicker} kind="ghost" size="small" icon={Eyedropper} iconDescription="pick" tooltipPosition="right" on:click={()=>swapTool(toolPicker)}></Button>
|
||||||
|
|
@ -154,6 +156,7 @@
|
||||||
<Shortcuts group='editor2D'>
|
<Shortcuts group='editor2D'>
|
||||||
<Shortcut global cmd='clear selection' keys={['escape']} on:trigger={()=>focusedFile?.push(new SelectionClearUndoable())} />
|
<Shortcut global cmd='clear selection' keys={['escape']} on:trigger={()=>focusedFile?.push(new SelectionClearUndoable())} />
|
||||||
<Shortcut global cmd='selection' keys={['s']} on:trigger={()=>swapTool(toolSelection)} />
|
<Shortcut global cmd='selection' keys={['s']} on:trigger={()=>swapTool(toolSelection)} />
|
||||||
|
<Shortcut global cmd='magic selection' keys={['shift+s']} on:trigger={()=>swapTool(toolMagicWand)} />
|
||||||
<Shortcut global cmd='move' keys={['m']} on:trigger={()=>swapTool(toolMove)} />
|
<Shortcut global cmd='move' keys={['m']} on:trigger={()=>swapTool(toolMove)} />
|
||||||
<Shortcut global cmd='move left' keys={['arrowleft']} on:trigger={()=>toolMove.shift({file: focusedFile}, {x: -1, y: 0, id: 0})} />
|
<Shortcut global cmd='move left' keys={['arrowleft']} on:trigger={()=>toolMove.shift({file: focusedFile}, {x: -1, y: 0, id: 0})} />
|
||||||
<Shortcut global cmd='move right' keys={['arrowright']} on:trigger={()=>toolMove.shift({file: focusedFile}, {x: 1, y: 0, id: 0})} />
|
<Shortcut global cmd='move right' keys={['arrowright']} on:trigger={()=>toolMove.shift({file: focusedFile}, {x: 1, y: 0, id: 0})} />
|
||||||
|
|
|
||||||
|
|
@ -282,6 +282,59 @@ export class SelectionTool implements Tool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class MagicWandTool implements Tool {
|
||||||
|
private active: boolean
|
||||||
|
|
||||||
|
isActive(): boolean {
|
||||||
|
return this.active
|
||||||
|
}
|
||||||
|
|
||||||
|
pointerDown(ctx: ToolContext & FloodToolContext, ptr: Pointer) {
|
||||||
|
this.active = true
|
||||||
|
let pixels: { x: number, y: number, marked: boolean }[] = []
|
||||||
|
|
||||||
|
let traversed = new Set<number>()
|
||||||
|
|
||||||
|
let value = true
|
||||||
|
let clear = false
|
||||||
|
if (!ptr.shift && !ptr.control) {
|
||||||
|
clear = true
|
||||||
|
}
|
||||||
|
if (ptr.control) {
|
||||||
|
value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
let p = ctx.file.canvas.getPixel(ptr.x, ptr.y)
|
||||||
|
if (p !== -1) {
|
||||||
|
let queue = [{x: ptr.x, y: ptr.y}]
|
||||||
|
while (queue.length > 0) {
|
||||||
|
let {x, y} = queue.shift()
|
||||||
|
let index = y * ctx.file.canvas.width + x
|
||||||
|
if (traversed.has(index)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
traversed.add(index)
|
||||||
|
let p2 = ctx.file.canvas.getPixel(x, y)
|
||||||
|
if (p2 === p) {
|
||||||
|
pixels.push({x, y, marked: value})
|
||||||
|
if (x > 0) queue.push({x: x-1, y})
|
||||||
|
if (x < ctx.file.canvas.width-1) queue.push({x: x+1, y})
|
||||||
|
if (y > 0) queue.push({x, y: y-1})
|
||||||
|
if (y < ctx.file.canvas.height-1) queue.push({x, y: y+1})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.file.selection.active = true
|
||||||
|
ctx.file.push(new SelectionSetUndoable(pixels, clear))
|
||||||
|
}
|
||||||
|
pointerMove(ctx: ToolContext & FloodToolContext, ptr: Pointer) {
|
||||||
|
}
|
||||||
|
pointerUp(ctx: ToolContext & FloodToolContext, ptr: Pointer) {
|
||||||
|
this.active = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class MoveTool implements Tool {
|
export class MoveTool implements Tool {
|
||||||
private active: boolean
|
private active: boolean
|
||||||
private startX: number
|
private startX: number
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue