Add brush size visualizer

main
kts of kettek 2024-02-14 19:01:51 -08:00
parent 0703417339
commit 02fe8ea1dc
4 changed files with 74 additions and 8 deletions

View File

@ -9,15 +9,16 @@
import { LoadedFile } from './types/file'
import "carbon-components-svelte/css/all.css"
import { Tabs, Tab, TabContent, Theme, Button, Modal, Truncate, ButtonSet } from "carbon-components-svelte"
import { Tabs, Tab, TabContent, Theme, Button, Modal, Truncate, ButtonSet, NumberInput } from "carbon-components-svelte"
import { ComposedModal } from "carbon-components-svelte"
import { OverflowMenu, OverflowMenuItem } from "carbon-components-svelte"
import { Close, Erase, PaintBrushAlt, RainDrop, Redo, Select_01, Undo } from "carbon-icons-svelte"
import { Close, Erase, PaintBrushAlt, RainDrop, Redo, Select_01, Undo, Scale } from "carbon-icons-svelte"
import StackPreview from './sections/StackPreview.svelte'
import type { Canvas } from './types/canvas'
import { BrushTool, EraserTool, FillTool, type Tool } from './types/tools';
import BrushSize from './components/BrushSize.svelte';
let theme: 'white'|'g10'|'g80'|'g90'|'g100' = 'g90'
@ -38,6 +39,7 @@
let toolErase = new EraserTool()
let toolBrush = new BrushTool()
let currentTool: Tool = toolBrush
let brushSize: number = 1
function swapTool(tool: Tool) {
currentTool = tool
@ -104,6 +106,13 @@
<Button isSelected={currentTool === toolErase} kind="ghost" size="small" icon={Erase} iconDescription="erase" tooltipPosition="right" on:click={()=>swapTool(toolErase)}></Button>
</menu>
<section class='middle'>
<menu class='toolsettings'>
{#if currentTool === toolBrush || currentTool === toolErase}
<Scale/>
<BrushSize bind:brushSize/>
<NumberInput size="sm" min={1} max={100} step={1} bind:value={brushSize}/>
{/if}
</menu>
<Tabs>
{#each files as file, index}
<Tab on:click={()=>selectFile(file, index)}>
@ -116,7 +125,7 @@
<svelte:fragment slot="content">
{#each files as file}
<TabContent>
<Editor2D bind:file={file} refresh={refresh} primaryColorIndex={primaryColorIndex} secondaryColorIndex={secondaryColorIndex} bind:currentTool={currentTool} />
<Editor2D bind:file={file} refresh={refresh} primaryColorIndex={primaryColorIndex} secondaryColorIndex={secondaryColorIndex} bind:currentTool={currentTool} brushSize={brushSize} />
</TabContent>
{/each}
</svelte:fragment>
@ -173,10 +182,21 @@
display: flex;
flex-direction: column;
justify-content: flex-start;
padding-top: 2rem;
}
.toolsettings {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
min-height: 2rem;
}
:global(menu.toolsettings > .bx--form-item) {
flex: initial;
}
.middle {
display: grid;
grid-template-rows: auto minmax(0, 1fr);
grid-template-rows: auto auto minmax(0, 1fr);
}
.tab {
display: inline-grid;
@ -193,4 +213,14 @@
overflow: hidden;
text-overflow: ellipsis;
}
:global(.middle .bx--tabs__nav-link) {
height: 1rem;
}
:global(.middle .bx--tabs) {
min-height: 1.4rem;
}
:global(.middle .bx--tabs .bx--btn) {
padding-top: 0;
top: -.25rem;
}
</style>

View File

@ -0,0 +1,34 @@
<script lang='ts'>
import { FilledCircle } from "../types/shapes"
export let brushSize: number
$: ((brushSize: number) => {
if (canvas) {
let {width, height} = getComputedStyle(canvas)
canvas.width = parseInt(width)
canvas.height = parseInt(height)
const ctx = canvas.getContext('2d')
ctx.fillStyle = 'black'
ctx.fillRect(0, 0, canvas.width, canvas.height)
let shape = FilledCircle(canvas.width/2, canvas.height/2, brushSize, 1)
for (let i = 0; i < shape.length; i++) {
ctx.fillStyle = 'white'
ctx.fillRect(shape[i].x, shape[i].y, 1, 1)
}
}
})(brushSize)
let canvas: HTMLCanvasElement
</script>
<canvas bind:this={canvas}>
</canvas>
<style>
canvas {
width: 2rem;
height: 2rem;
}
</style>

View File

@ -27,6 +27,7 @@
export let primaryColorIndex: number
export let secondaryColorIndex: number
export let brushSize: number
let rootCanvas: HTMLCanvasElement
let overlayCanvas: HTMLCanvasElement = document.createElement('canvas')
@ -208,9 +209,9 @@
if (e.button === 0) {
if (currentTool instanceof BrushTool) {
currentTool.pointerDown({file, brushSize: 3, colorIndex: primaryColorIndex}, {x: mousePixelX, y: mousePixelY, id: e.button })
currentTool.pointerDown({file, brushSize, colorIndex: primaryColorIndex}, {x: mousePixelX, y: mousePixelY, id: e.button })
} else if (currentTool instanceof EraserTool) {
currentTool.pointerDown({file, brushSize: 3}, {x: mousePixelX, y: mousePixelY, id: e.button })
currentTool.pointerDown({file, brushSize}, {x: mousePixelX, y: mousePixelY, id: e.button })
} else if (currentTool instanceof FillTool) {
currentTool.pointerDown({file, colorIndex: primaryColorIndex}, {x: mousePixelX, y: mousePixelY, id: e.button })
} else {
@ -268,9 +269,9 @@
if (buttons.has(0)) {
if (currentTool.isActive()) {
if (currentTool instanceof BrushTool) {
currentTool.pointerMove({file, brushSize: 3, colorIndex: primaryColorIndex}, {x: mousePixelX, y: mousePixelY, id: 0 })
currentTool.pointerMove({file, brushSize, colorIndex: primaryColorIndex}, {x: mousePixelX, y: mousePixelY, id: 0 })
} else if (currentTool instanceof EraserTool) {
currentTool.pointerMove({file, brushSize: 3}, {x: mousePixelX, y: mousePixelY, id: 0 })
currentTool.pointerMove({file, brushSize}, {x: mousePixelX, y: mousePixelY, id: 0 })
} else if (currentTool instanceof FillTool) {
currentTool.pointerMove({file, colorIndex: primaryColorIndex}, {x: mousePixelX, y: mousePixelY, id: 0 })
} else {

View File

@ -31,6 +31,7 @@
<style>
main {
background-color: var(--cds-background-selected);
text-align: left;
}
.entry {
position: relative;