Add WIP palette support
parent
2afd2ff119
commit
d2b90298cd
|
@ -9,7 +9,7 @@
|
||||||
import { LoadedFile, PixelsPlaceUndoable, SelectionClearUndoable, SelectionSetUndoable } from './types/file'
|
import { LoadedFile, PixelsPlaceUndoable, SelectionClearUndoable, SelectionSetUndoable } from './types/file'
|
||||||
|
|
||||||
import "carbon-components-svelte/css/all.css"
|
import "carbon-components-svelte/css/all.css"
|
||||||
import { Tabs, Tab, TabContent, Theme, Button, Modal, Truncate, ButtonSet, NumberInput } from "carbon-components-svelte"
|
import { Tabs, Tab, TabContent, Theme, Button, Modal, Truncate, ButtonSet, NumberInput, Dropdown } from "carbon-components-svelte"
|
||||||
import { ComposedModal } from "carbon-components-svelte"
|
import { ComposedModal } from "carbon-components-svelte"
|
||||||
|
|
||||||
import { OverflowMenu, OverflowMenuItem } from "carbon-components-svelte"
|
import { OverflowMenu, OverflowMenuItem } from "carbon-components-svelte"
|
||||||
|
@ -44,6 +44,23 @@
|
||||||
let alpha: number = 0
|
let alpha: number = 0
|
||||||
|
|
||||||
let refreshPalette = {}
|
let refreshPalette = {}
|
||||||
|
let fakePalette: Uint32Array | undefined = undefined
|
||||||
|
let selectedPaletteID: number = 0
|
||||||
|
$: {
|
||||||
|
if (selectedPaletteID === 0) {
|
||||||
|
fakePalette = undefined
|
||||||
|
} else if (selectedPaletteID === 1) {
|
||||||
|
fakePalette = new Uint32Array([
|
||||||
|
0xFFE0F8D0, 0xFF88C070, 0xFF346856, 0xFF081820,
|
||||||
|
0xFFF8F8F8, 0xFFC0C0C0, 0xFF606060, 0xFF202020,
|
||||||
|
0xFFF8D8F8, 0xFFA800A8, 0xFF503050, 0xFF200020,
|
||||||
|
0xFFF8B8F8, 0xFFA800A8, 0xFF503050, 0xFF200020,
|
||||||
|
])
|
||||||
|
}
|
||||||
|
focusedFile?.canvas.setFakePalette(fakePalette)
|
||||||
|
focusedFile?.canvas.refreshImageData()
|
||||||
|
focusedFile?.canvas.refreshCanvas()
|
||||||
|
}
|
||||||
|
|
||||||
// Oh no, what are you doing, step palette~
|
// Oh no, what are you doing, step palette~
|
||||||
function stepPalette(step: number, primary: boolean) {
|
function stepPalette(step: number, primary: boolean) {
|
||||||
|
@ -189,7 +206,15 @@
|
||||||
</menu>
|
</menu>
|
||||||
<section class='content'>
|
<section class='content'>
|
||||||
<section class='left'>
|
<section class='left'>
|
||||||
<PaletteSection refresh={refreshPalette} bind:primaryColorIndex bind:secondaryColorIndex file={focusedFile} on:select={handlePaletteSelect} />
|
<Dropdown
|
||||||
|
size="sm"
|
||||||
|
bind:selectedId={selectedPaletteID}
|
||||||
|
items={[
|
||||||
|
{ id: 0, text: "<image>"},
|
||||||
|
{ id: 1, text: "test palette"},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<PaletteSection refresh={refreshPalette} bind:primaryColorIndex bind:secondaryColorIndex file={focusedFile} fakePalette={fakePalette} on:select={handlePaletteSelect} />
|
||||||
<article>
|
<article>
|
||||||
<ColorSelector bind:red bind:green bind:blue bind:alpha />
|
<ColorSelector bind:red bind:green bind:blue bind:alpha />
|
||||||
<ColorIndex bind:red bind:green bind:blue bind:alpha index={primaryColorIndex} file={focusedFile} on:refresh={()=>refreshPalette={}} />
|
<ColorIndex bind:red bind:green bind:blue bind:alpha index={primaryColorIndex} file={focusedFile} on:refresh={()=>refreshPalette={}} />
|
||||||
|
@ -302,7 +327,7 @@
|
||||||
}
|
}
|
||||||
.left {
|
.left {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: minmax(0, 1fr) auto;
|
grid-template-rows: auto minmax(0, 1fr) auto;
|
||||||
}
|
}
|
||||||
.toolbar {
|
.toolbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -36,6 +36,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export let fakePalette: Uint32Array | undefined
|
||||||
|
let palette: Uint32Array | undefined[]
|
||||||
|
$: {
|
||||||
|
if (fakePalette) {
|
||||||
|
palette = fakePalette
|
||||||
|
} else {
|
||||||
|
palette = file ? file.canvas.palette : []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function paletteClick(event: MouseEvent) {
|
function paletteClick(event: MouseEvent) {
|
||||||
const target = event.target as HTMLSpanElement
|
const target = event.target as HTMLSpanElement
|
||||||
const index = parseInt(target.getAttribute('x-index') || '0')
|
const index = parseInt(target.getAttribute('x-index') || '0')
|
||||||
|
@ -48,16 +58,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function handleWheel(event: WheelEvent) {
|
function handleWheel(event: WheelEvent) {
|
||||||
if (!file) return
|
|
||||||
if (event.deltaX < 0) {
|
if (event.deltaX < 0) {
|
||||||
secondaryColorIndex = (secondaryColorIndex - 1 + file.canvas.palette.length) % file.canvas.palette.length
|
secondaryColorIndex = (secondaryColorIndex - 1 + palette.length) % palette.length
|
||||||
} else if (event.deltaX > 0) {
|
} else if (event.deltaX > 0) {
|
||||||
secondaryColorIndex = (secondaryColorIndex + 1) % file.canvas.palette.length
|
secondaryColorIndex = (secondaryColorIndex + 1) % palette.length
|
||||||
}
|
}
|
||||||
if (event.deltaY < 0) {
|
if (event.deltaY < 0) {
|
||||||
primaryColorIndex = (primaryColorIndex - 1 + file.canvas.palette.length) % file.canvas.palette.length
|
primaryColorIndex = (primaryColorIndex - 1 + palette.length) % palette.length
|
||||||
} else if (event.deltaY > 0) {
|
} else if (event.deltaY > 0) {
|
||||||
primaryColorIndex = (primaryColorIndex + 1) % file.canvas.palette.length
|
primaryColorIndex = (primaryColorIndex + 1) % palette.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,24 +127,22 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<main on:wheel={handleWheel}>
|
<main on:wheel={handleWheel}>
|
||||||
{#if file}
|
{#each palette as swatch, swatchIndex}
|
||||||
{#each file.canvas.palette as palette, paletteIndex}
|
{#if draggingIndex !== -1 && (swatchIndex === hoveringIndex || (swatchIndex === hoveringIndex-1 && swatchIndex === palette.length-1))}
|
||||||
{#if draggingIndex !== -1 && (paletteIndex === hoveringIndex || (paletteIndex === hoveringIndex-1 && paletteIndex === file.canvas.palette.length-2))}
|
<span class="entry primary">
|
||||||
<span class="entry primary">
|
<span class="checkerboard"></span>
|
||||||
<span class="checkerboard"></span>
|
<span style="background-color: rgba({palette[draggingIndex]&0xFF},{(palette[draggingIndex]>>8)&0xFF},{(palette[draggingIndex]>>16)&0xFF},{((palette[draggingIndex]>>24)&0xFF)/255})" class="color"></span>
|
||||||
<span style="background-color: rgba({file.canvas.palette[draggingIndex]&0xFF},{(file.canvas.palette[draggingIndex]>>8)&0xFF},{(file.canvas.palette[draggingIndex]>>16)&0xFF},{((file.canvas.palette[draggingIndex]>>24)&0xFF)/255})" class="color"></span>
|
<span class='label'>{draggingIndex}</span>
|
||||||
<span class='label'>{draggingIndex}</span>
|
</span>
|
||||||
</span>
|
{/if}
|
||||||
{/if}
|
{#if swatchIndex !== draggingIndex}
|
||||||
{#if paletteIndex !== draggingIndex}
|
<span on:click={paletteClick} x-index={swatchIndex} class='entry{swatchIndex===primaryColorIndex?' primary':''}{swatchIndex===secondaryColorIndex?' secondary':''}{swatchIndex===draggingIndex?' hide':''}' use:swatchDrag>
|
||||||
<span on:click={paletteClick} x-index={paletteIndex} class='entry{paletteIndex===primaryColorIndex?' primary':''}{paletteIndex===secondaryColorIndex?' secondary':''}{paletteIndex===draggingIndex?' hide':''}' use:swatchDrag>
|
<span class="checkerboard"></span>
|
||||||
<span class="checkerboard"></span>
|
<span style="background-color: rgba({swatch&0xFF},{(swatch>>8)&0xFF},{(swatch>>16)&0xFF},{((swatch>>24)&0xFF)/255})" class="color"></span>
|
||||||
<span style="background-color: rgba({palette&0xFF},{(palette>>8)&0xFF},{(palette>>16)&0xFF},{((palette>>24)&0xFF)/255})" class="color"></span>
|
<span class='label'>{swatchIndex}</span>
|
||||||
<span class='label'>{paletteIndex}</span>
|
</span>
|
||||||
</span>
|
{/if}
|
||||||
{/if}
|
{/each}
|
||||||
{/each}
|
|
||||||
{/if}
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -4,6 +4,7 @@ export class Canvas {
|
||||||
width: number
|
width: number
|
||||||
height: number
|
height: number
|
||||||
palette: Uint32Array // 32-bit RGBA palette
|
palette: Uint32Array // 32-bit RGBA palette
|
||||||
|
fakePalette: Uint32Array // 32-bit RGBA palette
|
||||||
pixels: Uint8Array // 8-bit indices into the palette
|
pixels: Uint8Array // 8-bit indices into the palette
|
||||||
public isIndexed: boolean = false
|
public isIndexed: boolean = false
|
||||||
canvas: HTMLCanvasElement
|
canvas: HTMLCanvasElement
|
||||||
|
@ -199,9 +200,19 @@ export class Canvas {
|
||||||
}
|
}
|
||||||
this.palette[to] = temp
|
this.palette[to] = temp
|
||||||
}
|
}
|
||||||
|
setFakePalette(palette: Uint32Array | undefined) {
|
||||||
|
this.fakePalette = palette
|
||||||
|
}
|
||||||
refreshImageData() {
|
refreshImageData() {
|
||||||
|
let palette = this.palette
|
||||||
|
if (this.fakePalette) {
|
||||||
|
palette = this.fakePalette
|
||||||
|
}
|
||||||
for (let i = 0; i < this.pixels.length; i++) {
|
for (let i = 0; i < this.pixels.length; i++) {
|
||||||
let color = this.palette[this.pixels[i]]
|
let color: number = 0
|
||||||
|
if (this.pixels[i] < palette.length) {
|
||||||
|
color = palette[this.pixels[i]]
|
||||||
|
}
|
||||||
this.imageData.data[i * 4 + 0] = color & 0xFF
|
this.imageData.data[i * 4 + 0] = color & 0xFF
|
||||||
this.imageData.data[i * 4 + 1] = (color >> 8) & 0xFF
|
this.imageData.data[i * 4 + 1] = (color >> 8) & 0xFF
|
||||||
this.imageData.data[i * 4 + 2] = (color >> 16) & 0xFF
|
this.imageData.data[i * 4 + 2] = (color >> 16) & 0xFF
|
||||||
|
|
Loading…
Reference in New Issue