brush library and history (WIP)

This commit is contained in:
Hugh Bord 2021-08-06 14:00:21 +10:00
parent cb5e558922
commit 2581cd45f1
7 changed files with 126 additions and 190 deletions

View File

@ -86,6 +86,8 @@
<ColourPicker
v-if="toolbarState.isChoosingFg || toolbarState.isChoosingBg"
/>
<BrushLibrary />
</template>
<template v-else>
<div style="left: 35%; top: 15%; position: absolute; z-index: -2">
@ -102,6 +104,7 @@
import LZString from "lz-string";
import Toolbar from "./components/Toolbar.vue";
import DebugPanel from "./components/DebugPanel.vue";
import BrushLibrary from "./components/BrushLibrary.vue";
import Editor from "./views/Editor.vue";
import CharPicker from "./components/parts/CharPicker.vue";
@ -135,6 +138,7 @@ export default {
NewAscii,
EditAscii,
PasteAscii,
BrushLibrary
},
name: "Dashboard",
data: () => ({

View File

@ -1,28 +1,71 @@
<template>
<div>
<vue-draggable-resizable
:grid="[currentAscii.blockWidth, currentAscii.blockHeight]"
:min-width="blockWidth * 50"
:max-width="blockWidth * 50"
:min-height="blockHeight * 50"
:max-height="blockHeight * 50"
:w="blockWidth * 50"
:h="blockWidth * 50"
:x="blockWidth * 150"
:y="blockHeight * 3"
>
<t-card class="h-full">
<div class="flex mx-auto">
<div class="w-1/2">
<t-button type="button" class="block w-full" @click="tab = 1">Library</t-button>
</div>
<div class="w-1/2">
<t-button type="button" class="block w-full" @click="tab = 0">History</t-button>
</div>
</div>
<div v-if="tab === 0">
<div v-for="(value, key) in brushHistory" :key="key">
<BrushCanvas :blocks="decompressBlock(value)" />
<t-button type="button" @click="reuseBlocks(decompressBlock(value))">Reuse</t-button>
<t-button type="button" @click="saveToLibrary(decompressBlock(value))">Save to Library</t-button>
</div>
</div>
<div v-if="tab === 1">
<div v-for="(value, key) in brushLibrary" :key="key">
<BrushCanvas :blocks="decompressBlock(value)" />
<t-button type="button" @click="reuseBlocks(decompressBlock(value))">Reuse</t-button>
</div>
</div>
</t-card>
</vue-draggable-resizable>
</div>
</template>
<script>
import { emptyBlock, mircColours99 } from "../../ascii";
import { mircColours99, blockWidth, blockHeight } from "../ascii";
import BrushCanvas from "./parts/BrushCanvas.vue"
import LZString from 'lz-string';
export default {
name: "BrushLibrary",
mounted() {
this.ctx = this.$refs.brushcanvas.getContext("2d");
this.delayRedrawCanvas();
},
data: () => ({
ctx: null,
redraw: true,
blocks: [],
tab: 1
}),
components: {
BrushCanvas,
},
computed: {
blockWidth() {
return blockWidth;
},
blockHeight() {
return blockHeight;
},
currentAscii() {
return this.$store.getters.currentAscii;
},
@ -56,198 +99,42 @@ export default {
brushSizeType() {
return this.$store.getters.brushSizeType;
},
brushHistory() {
return this.$store.getters.brushHistory.slice(0,10);
},
brushLibrary() {
return this.$store.getters.brushLibrary;
},
mircColours() {
return mircColours99;
},
options() {
return this.$store.getters.options;
},
brushBlocks() {
return this.$store.getters.brushBlocks;
},
},
watch: {
brushSizeWidth() {
this.delayRedrawCanvas();
this.brushSizeWidthInput = this.brushSizeWidth;
},
brushSizeHeight() {
this.delayRedrawCanvas();
this.brushSizeHeightInput = this.brushSizeHeight;
},
brushSizeType() {
this.delayRedrawCanvas();
this.brushSizeTypeInput = this.brushSizeType;
},
isTargettingBg() {
this.delayRedrawCanvas();
},
isTargettingFg() {
this.delayRedrawCanvas();
},
isTargettingChar() {
this.delayRedrawCanvas();
},
currentFg() {
this.delayRedrawCanvas();
},
currentBg() {
this.delayRedrawCanvas();
},
currentChar() {
this.delayRedrawCanvas();
},
},
methods: {
updateBrushSize() {
this.$store.commit("updateBrushSize", {
brushSizeHeight: this.brushSizeHeightInput,
brushSizeWidth: this.brushSizeWidthInput,
brushSizeType: this.brushSizeTypeInput,
});
this.ctx.clearRect(0, 0, 10000, 10000);
this.delayRedrawCanvas();
changeTab(tab) {
this.tab = tab
},
drawPreview() {
this.ctx.clearRect(0, 0, 10000, 10000);
const brushHeight = this.brushSizeHeight;
const brushWidth = this.brushSizeWidth;
this.blocks = [];
this.ctx.fillStyle = this.mircColours[1];
const BLOCK_WIDTH = this.currentAscii.blockWidth;
const BLOCK_HEIGHT = this.currentAscii.blockHeight;
// hack font for ascii shout outs 2 beenz
this.ctx.font = "13px Hack";
let y = 0;
let x = 0;
let targetX = 0;
const block = {
fg: this.currentFg,
bg: this.currentBg,
char: this.currentChar,
};
const middleY = Math.floor(brushHeight / 2);
const middleX = Math.floor(brushWidth / 2);
let yModifier = 0;
// Recreate 2d array for preview
for (y = 0; y < brushHeight; y++) {
this.blocks[y] = [];
for (x = 0; x < brushWidth; x++) {
switch (this.brushSizeType) {
case "cross":
// If we are 1x1 force fill 1 block, to avoid an empty 1x1
if (x === 0 && y === 0) {
this.blocks[y][x] = { ...block };
continue;
}
if (x === brushWidth) {
this.blocks[y][x] = { ...emptyBlock };
} else {
this.blocks[y][x] = { ...block };
}
targetX = x;
if (y % 2 === 0) {
targetX -= 1;
}
if (this.blocks[y] && this.blocks[y][targetX]) {
if (x % 2 === 0) {
this.blocks[y][targetX] = { ...emptyBlock };
} else {
this.blocks[y][targetX] = { ...block };
}
}
break;
// default:
case "square":
this.blocks[y][x] = { ...block };
break;
case "circle":
if (middleY >= y) {
// Top half
yModifier = y;
if (x <= middleX + yModifier && x >= middleX - yModifier) {
this.blocks[y][x] = { ...block };
} else {
this.blocks[y][x] = { ...emptyBlock };
}
} else {
// Bottom half
yModifier = middleY - (y - middleY);
if (x <= middleX + yModifier && x >= middleX - yModifier) {
this.blocks[y][x] = { ...block };
} else {
this.blocks[y][x] = { ...emptyBlock };
}
}
break;
}
}
}
// Get middle block
for (y = 0; y < this.blocks.length; y++) {
for (x = 0; x < this.blocks[0].length; x++) {
if (this.blocks[y] && this.blocks[y][x]) {
const curBlock = this.blocks[y][x];
if (curBlock.bg && this.isTargettingBg) {
this.ctx.fillStyle = this.mircColours[curBlock.bg];
this.ctx.fillRect(
x * BLOCK_WIDTH,
y * BLOCK_HEIGHT,
BLOCK_WIDTH,
BLOCK_HEIGHT
);
}
if (curBlock.fg && this.isTargettingFg) {
this.ctx.fillStyle = this.mircColours[curBlock.fg];
}
if (curBlock.char && this.isTargettingChar) {
this.ctx.fillStyle = this.mircColours[curBlock.fg];
this.ctx.fillText(
curBlock.char,
x * BLOCK_WIDTH - 1,
y * BLOCK_HEIGHT + BLOCK_HEIGHT - 3
);
}
}
}
this.ctx.stroke();
this.$store.commit("brushBlocks", this.blocks);
}
decompressBlock(item) {
console.log(JSON.parse(LZString.decompressFromUTF16(item)))
return JSON.parse(LZString.decompressFromUTF16(item))
},
delayRedrawCanvas() {
if (this.redraw) {
this.redraw = false;
setTimeout(() => {
this.redraw = true;
this.drawPreview();
}, this.options.canvasRedrawSpeed);
}
reuseBlocks(value) {
// this.$store.commit('pushBrushHistory', this.brushBlocks)
this.$store.commit('changeColourFg', value[0][0].fg )
this.$store.commit('changeColourBg', value[0][0].bg )
this.$store.commit('changeChar', value[0][0].char )
this.$store.commit('brushBlocks', value)
},
saveToLibrary(value) {
this.$store.commit('pushBrushLibrary', value)
}
},
};
</script>

View File

@ -13,7 +13,7 @@
:x="debugPanelState.x"
:y="debugPanelState.y"
>
<t-card style="height: 100%;">
<t-card class="h-full">
<span
class="ml-5"
v-html="`Tool: ${getToolName}`"

View File

@ -1,17 +1,19 @@
<template>
<div>
<t-card>
<canvas
:ref="canvasName"
:id="canvasName"
:class="canvasName"
:width="brushSizeWidth * currentAscii.blockWidth"
:height="brushSizeHeight * currentAscii.blockHeight"
:width="blocksWidthHeight.w"
:height="blocksWidthHeight.h"
/>
</t-card>
</div>
</template>
<script>
import { mircColours99 } from "../../ascii";
import { mircColours99, blockWidth, blockHeight } from "../../ascii";
export default {
name: "BrushCanvas",
@ -81,6 +83,12 @@ export default {
isMainCanvas() {
return this.blocks === false;
},
blocksWidthHeight() {
return {
w: 20 * blockWidth,
h: this.getBlocks.length * blockHeight
}
},
mircColours() {
return mircColours99;
},
@ -89,6 +97,9 @@ export default {
getBlocks() {
this.delayRedrawCanvas();
},
blocks() {
this.delayRedrawCanvas();
},
currentAscii() {
this.delayRedrawCanvas();
},

View File

@ -99,6 +99,9 @@ export default {
},
currentAsciiBlocks() {
return this.$store.getters.currentAsciiBlocks
},
brushBlocks() {
return this.$store.getters.brushBlocks
}
},
watch: {
@ -126,6 +129,25 @@ export default {
this.createBlocks()
}
},
currentChar(val, old) {
if (val !== old) {
this.createBlocks()
}
},
currentBg(val, old) {
if (val !== old) {
this.createBlocks()
}
},
currentFg(val, old) {
if (val !== old) {
this.createBlocks()
}
},
brushBlocks() {
this.$store.commit("pushBrushHistory", this.brushBlocks)
}
},
methods: {
updateBrushSize() {
@ -156,6 +178,8 @@ export default {
const middleX = Math.floor(brushWidth / 2);
let yModifier = 0;
//
// Recreate 2d array for preview
for (y = 0; y < brushHeight; y++) {
this.blocks[y] = [];

View File

@ -66,8 +66,9 @@ export default new Vuex.Store({
},
blockSizeMultiplier: 1,
brushBlocks: [],
brushHistory: [],
selectBlocks: [],
libraryBlocks: [],
brushLibrary: [],
},
mutations: {
changeState(state, payload) {
@ -178,6 +179,12 @@ export default new Vuex.Store({
selectBlocks(state, payload) {
state.selectBlocks = LZString.compressToUTF16(JSON.stringify(payload));
},
pushBrushHistory(state, payload) {
state.brushHistory.unshift(LZString.compressToUTF16(JSON.stringify(payload)));
},
pushBrushLibrary(state, payload) {
state.brushLibrary.unshift(LZString.compressToUTF16(JSON.stringify(payload)));
},
openModal(state, type) {
switch (type) {
case 'new-ascii':
@ -232,6 +239,8 @@ export default new Vuex.Store({
brushSizeWidth: (state) => state.toolbarState.brushSizeWidth,
brushSizeType: (state) => state.toolbarState.brushSizeType,
blockSizeMultiplier: (state) => state.blockSizeMultiplier,
brushHistory: (state) => state.brushHistory,
brushLibrary: (state) => state.brushLibrary,
brushBlocks: (state) => JSON.parse(LZString.decompressFromUTF16(state.brushBlocks)) || [],
selectBlocks: (state) => JSON.parse(LZString.decompressFromUTF16(state.selectBlocks)) || [],
isModalOpen: (state) => {

View File

@ -118,6 +118,7 @@ export default {
// Ctrl V - paste blocks
if (e.key === 'v' && ctrlKey) {
if (this.haveSelectBlocks) {
this.$store.commit("pushBrushHistory", this.brushBlocks)
this.$store.commit('brushBlocks', this.selectBlocks);
this.$store.commit('changeTool', 4);
}