BRUSH FAILURE, backspace text sorta

This commit is contained in:
Hugh Bord 2021-04-17 10:12:02 +10:00
parent b516bcdfd3
commit a1cbf1ecc1
6 changed files with 346 additions and 123 deletions

View File

@ -8,6 +8,8 @@ ASCIIBIRD DEVELOPMENT - TAKING FLIGHT
* Context Menus (right click menu)
* Keyboard shortcuts
* Undo feature
* BLOCK BUG WITH WHITE CHARS
* COMPRESSION inside the localStorage
# KILLER ASCIIBIRD FEATURES DONE

View File

@ -451,13 +451,13 @@ export default {
// try {
// // convert the incoming base64 -> binary
// const strData = fileContents;
// // const strData = fileContents;
// // split it into an array rather than a "string"
// const charData = strData.split('').map(function(x){return x.charCodeAt(0); });
// // const charData = strData.split('').map(function(x){return x.charCodeAt(0); });
// // var strData = String.fromCharCode.apply(null, pako.inflate(String.fromCharCode.apply(null, input).split("").map(function(x){return x.charCodeAt(0);})));
// input = pako.inflate(charData, { to: 'string' });
// input = pako.inflate(fileContents);
// console.log(input);
// } catch (err) {
@ -476,7 +476,7 @@ export default {
try {
// Make a gzipped JSON of the asciibird app state
// While making a gzip bellow works, had some trouble gunzipping in importAsciibirdState(fileContents, fileName)
// output = pako.gzip(JSON.stringify(this.$store.getters.getState), {level:"9"});
// output = pako.gzip(JSON.stringify(this.$store.getters.getState), {level:"6"});
output = JSON.stringify(this.$store.getters.getState);
// Default timestamp for filename

View File

@ -6,15 +6,15 @@
$store.getters.currentAscii.blockHeight,
$store.getters.currentAscii.blockWidth,
]"
style="z-index: 5; min-height: 500px"
style="z-index: 5;"
:min-width="200"
:max-width="500"
:min-height="500"
:max-height="700"
:min-height="300"
:max-height="500"
:x="$store.getters.getToolbarState.x"
:y="$store.getters.getToolbarState.y"
>
<t-card header="Tools and Stuff" style="height: 100%">
<t-card style="height: 100%">
<label class="flex ml-1">
<t-checkbox
name="targetingFg"
@ -51,8 +51,6 @@
<Colours />
<h5>Brushes and Shit</h5>
<t-button
type="button"
v-for="(value, keyToolbar) in $store.getters.getToolbarIcons"
@ -64,6 +62,11 @@
</t-button>
<hr />
<BrushPreview />
</t-card>
@ -73,11 +76,12 @@
<script>
import Colours from "./Colours.vue";
import BrushPreview from "./parts/BrushPreview.vue";
export default {
created() {},
name: "Toolbar",
components: { Colours },
components: { Colours, BrushPreview },
data: () => ({
floating: {

View File

@ -0,0 +1,184 @@
<template>
<div>
<t-input
type="number"
name="width"
v-model="brushSizeWidth"
@change="updateBrushSizeWidth"
min="1"
max="10"
/>
<t-input
type="number"
name="height"
v-model="brushSizeHeight"
@change="updateBrushSizeHeight"
min="1"
max="10"
/>
<canvas
ref="brushcanvas"
id="brushcanvas"
class="brushcanvas"
:width="100"
:height="100"
></canvas>
</div>
</template>
<script>
export default {
name: "BrushPreview",
mounted() {
this.ctx = this.$refs.brushcanvas.getContext("2d");
this.delayRedrawCanvas();
},
data: () => ({
ctx: null,
redraw: true,
brushSizeHeight: 1,
brushSizeWidth: 1,
}),
computed: {
currentAscii() {
return this.$store.getters.currentAscii;
},
toolbarState() {
return this.$store.getters.getToolbarState;
},
watchBrushSizeWidth() {
return this.brushSizeWidth;
},
watchBrushSizeHeight() {
return this.brushSizeHeight;
},
},
watch: {
toolbarState(val, old) {
console.log(val);
this.delayRedrawCanvas();
},
watchBrushSizeWidth(val, old) {
// console.log(val, old);
// this.brushSizeWidth = val;
this.delayRedrawCanvas();
},
watchBrushSizeHeight(val, old) {
// console.log(val, old);
// this.brushSizeHeight = val;
this.delayRedrawCanvas();
},
},
methods: {
updateBrushSizeHeight() {
this.$store.commit("updateBrushSize", {
brushSizeHeight: this.brushSizeHeight,
brushSizeWidth: this.brushSizeWidth,
});
},
updateBrushSizeWidth() {
this.$store.commit("updateBrushSize", {
brushSizeHeight: this.brushSizeHeight,
brushSizeWidth: this.brushSizeWidth,
});
},
drawPreview() {
let brushHeight = this.toolbarState.brushSizeHeight;
let brushWidth = this.toolbarState.brushSizeWidth;
this.ctx.clearRect(0, 0, 1000, 1000);
this.ctx.fillStyle = this.$store.getters.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 = "12.5px Hack";
let y = 0;
let x = 0;
let emptyBlock = {
fg: null,
bg: null,
char: null,
};
let blocks = [];
let minY = 5 - brushHeight;
let maxY = 5 + brushHeight;
let minX = 5 - brushWidth;
let maxX = 5 + brushWidth;
for (y = 0; y < 10; y++) {
blocks[y] = [];
if (y < maxY && y > minY) {
for (x = 0; x < 10; x++) {
if (x < maxX && x > minX) {
let block = {
fg: this.$store.getters.getFgColour,
bg: this.$store.getters.getBgColour,
char: this.$store.getters.getSelectedChar,
};
blocks[y][x] = Object.assign({}, block);
} else {
blocks[y][x] = Object.assign({}, emptyBlock);
}
}
}
}
console.log("blocks", blocks);
// Get middle block
for (y = 0; y < blocks.length; y++) {
for (x = 0; x < blocks[0].length; x++) {
let curBlock = blocks[y][x];
if (curBlock.bg) {
this.ctx.fillStyle = this.$store.getters.mircColours[curBlock.bg];
this.ctx.fillRect(
x * BLOCK_WIDTH,
y * BLOCK_HEIGHT,
BLOCK_WIDTH,
BLOCK_HEIGHT
);
}
if (curBlock.fg) {
this.ctx.fillStyle = this.$store.getters.mircColours[curBlock.fg];
}
if (curBlock.char) {
this.ctx.fillStyle = this.$store.getters.mircColours[curBlock.fg];
this.ctx.fillText(
curBlock.char,
x * BLOCK_WIDTH - 1,
y * BLOCK_HEIGHT + BLOCK_HEIGHT - 3
);
}
}
this.ctx.stroke();
}
},
delayRedrawCanvas() {
if (this.redraw) {
this.redraw = false;
setTimeout(() => {
this.redraw = true;
this.drawPreview();
}, this.$store.state.options.canvasRedrawSpeed);
}
},
},
};
</script>

View File

@ -14,7 +14,6 @@ export default new Vuex.Store({
// end up in its own modal I guess
options: {
canvasRedrawSpeed: 2,
draggableUpdateSpeed: 200, // How long between updating the vuex store when dragging any of the panels
defaultBg: 1,
defaultFg: 0,
},
@ -110,6 +109,8 @@ export default new Vuex.Store({
isChoosingFg: false,
isChoosingBg: false,
isChoosingChar: false,
brushSizeWidth: 1,
brushSizeHeight: 1,
selectedFg: 0,
selectedBg: 1,
selectedChar: 'A',
@ -194,6 +195,10 @@ export default new Vuex.Store({
updateAsciiBlocks(state, payload) {
Object.assign(state.asciibirdMeta[state.tab].blocks, payload);
},
updateBrushSize(state, payload) {
state.toolbarState.brushSizeHeight = payload.brushSizeHeight;
state.toolbarState.brushSizeWidth = payload.brushSizeWidth;
},
},
getters: {
getState: (state) => state,
@ -215,6 +220,8 @@ export default new Vuex.Store({
currentAsciiBlocks: (state) => state.asciibirdMeta[state.tab].blocks ?? false,
asciibirdMeta: (state) => state.asciibirdMeta,
nextTabValue: (state) => state.asciibirdMeta.length,
brushSizeHeight: (state) => state.toolbarState.brushSizeHeight,
brushSizeWidth: (state) => state.toolbarState.brushSizeWidth,
blockSizeMultiplier: (state) => state.blockSizeMultiplier,
},
actions: {},

View File

@ -3,10 +3,7 @@
<div id="canvas-area">
<vue-draggable-resizable
style="z-index: 5"
:grid="[
currentAscii.blockHeight,
currentAscii.blockWidth,
]"
:grid="[currentAscii.blockHeight, currentAscii.blockWidth]"
:w="canvas.width + currentAscii.blockWidth"
:h="canvas.height + currentAscii.blockHeight"
:draggable="$store.getters.getCurrentTool === 0"
@ -14,7 +11,6 @@
@dragstop="onCavasDragStop"
:x="currentAscii.x"
:y="currentAscii.y"
>
<canvas
ref="canvastools"
@ -61,23 +57,25 @@ body {
</style>
<script>
import Block from '../components/Block.vue';
import Block from "../components/Block.vue";
export default {
name: 'Editor',
name: "Editor",
components: { Block },
mounted() {
if (this.$store.getters.currentAscii.blocks) {
this.ctx = this.$refs.canvas.getContext('2d');
this.toolsCtx = this.$refs.canvastools.getContext('2d');
this.ctx = this.$refs.canvas.getContext("2d");
this.toolsCtx = this.$refs.canvastools.getContext("2d");
this.canvas.width = this.$store.getters.currentAscii.width
* this.$store.getters.currentAscii.blockWidth;
this.canvas.height = this.$store.getters.currentAscii.height
* this.$store.getters.currentAscii.blockHeight;
this.canvas.width =
this.$store.getters.currentAscii.width *
this.$store.getters.currentAscii.blockWidth;
this.canvas.height =
this.$store.getters.currentAscii.height *
this.$store.getters.currentAscii.blockHeight;
this.delayRedrawCanvas();
this.$store.commit('changeTool', 0);
this.$store.commit("changeTool", 0);
const _this = this;
this._keyListener = function (e) {
@ -88,7 +86,7 @@ export default {
// }
};
document.addEventListener('keydown', this._keyListener.bind(this));
document.addEventListener("keydown", this._keyListener.bind(this));
}
},
created() {},
@ -121,35 +119,48 @@ export default {
return `width:${this.canvas.width};height:${this.canvas.height};`;
},
generateTitle() {
return this.$store.getters.currentAscii.title ?? '';
return this.$store.getters.currentAscii.title ?? "";
},
currentAscii() {
return this.$store.getters.currentAscii;
},
currentTool() {
return this.$store.getters.getToolbarIcons[this.$store.getters.getCurrentTool];
return this.$store.getters.getToolbarIcons[
this.$store.getters.getCurrentTool
];
},
isTextEditing() {
return this.$store.getters.getToolbarIcons[this.$store.getters.getCurrentTool].name === 'text';
return (
this.$store.getters.getToolbarIcons[this.$store.getters.getCurrentTool]
.name === "text"
);
},
isSelecting() {
return this.$store.getters.getToolbarIcons[this.$store.getters.getCurrentTool].name === 'select';
return (
this.$store.getters.getToolbarIcons[this.$store.getters.getCurrentTool]
.name === "select"
);
},
},
watch: {
currentAscii(val, old) {
this.canvas.width = this.$store.getters.currentAscii.width
* this.$store.getters.currentAscii.blockWidth;
this.canvas.height = this.$store.getters.currentAscii.height
* this.$store.getters.currentAscii.blockHeight;
this.canvas.width =
this.$store.getters.currentAscii.width *
this.$store.getters.currentAscii.blockWidth;
this.canvas.height =
this.$store.getters.currentAscii.height *
this.$store.getters.currentAscii.blockHeight;
this.delayRedrawCanvas();
document.title = `asciibird - ${this.currentAscii.title}`;
},
currentTool() {
switch (this.$store.getters.getToolbarIcons[this.$store.getters.getCurrentTool].name) {
case 'default':
switch (
this.$store.getters.getToolbarIcons[this.$store.getters.getCurrentTool]
.name
) {
case "default":
Object.assign(this.textEditing, {
startX: null,
startY: null,
@ -170,11 +181,16 @@ export default {
redrawToolCanvas() {
if (this.currentAscii.blocks.length) {
this.clearToolCanvas();
this.toolsCtx.fillStyle = 'rgba(255, 255, 255, 0.4)';
this.toolsCtx.fillStyle = "rgba(255, 255, 255, 0.4)";
const BLOCK_WIDTH = this.currentAscii.blockWidth;
const BLOCK_HEIGHT = this.currentAscii.blockHeight;
this.toolsCtx.fillRect(this.selecting.startX, this.selecting.startY, this.selecting.endX * BLOCK_WIDTH, this.selecting.endY * BLOCK_HEIGHT);
this.toolsCtx.fillRect(
this.selecting.startX,
this.selecting.startY,
this.selecting.endX * BLOCK_WIDTH,
this.selecting.endY * BLOCK_HEIGHT
);
this.toolsCtx.stroke();
}
},
@ -197,19 +213,16 @@ export default {
let curBlock = {};
// hack font for ascii shout outs 2 beenz
this.ctx.font = '12.5px Hack';
this.ctx.font = "12.5px Hack";
for (y = 0; y < this.currentAscii.height + 1; y++) {
canvasY = BLOCK_HEIGHT * y;
for (x = 0; x < this.currentAscii.width + 1; x++) {
if (
this.currentAscii.blocks[y]
&& this.currentAscii.blocks[y][x]
) {
if (this.currentAscii.blocks[y] && this.currentAscii.blocks[y][x]) {
curBlock = Object.assign(
curBlock,
this.currentAscii.blocks[y][x],
this.currentAscii.blocks[y][x]
);
canvasX = BLOCK_WIDTH * x;
@ -221,7 +234,7 @@ export default {
];
this.ctx.fillRect(canvasX, canvasY, BLOCK_WIDTH, BLOCK_HEIGHT);
} else {
this.ctx.fillStyle = 'rgba(0, 0, 200, 0)';
this.ctx.fillStyle = "rgba(0, 0, 200, 0)";
}
if (curBlock.char) {
@ -230,13 +243,13 @@ export default {
curBlock.fg
];
} else {
this.ctx.fillStyle = '#000000';
this.ctx.fillStyle = "#000000";
}
this.ctx.fillText(
curBlock.char,
canvasX - 1,
canvasY + BLOCK_HEIGHT - 3,
canvasY + BLOCK_HEIGHT - 3
);
}
}
@ -255,10 +268,12 @@ export default {
const blocks = this.$store.getters.currentAsciiBlocks;
const oldWidth = blocks[0].length;// * this.currentAscii.blockWidth;
const oldHeight = blocks.length;// * this.currentAscii.blockHeight;
const oldWidth = blocks[0].length; // * this.currentAscii.blockWidth;
const oldHeight = blocks.length; // * this.currentAscii.blockHeight;
const canvasBlockHeight = Math.floor(height / this.currentAscii.blockHeight);
const canvasBlockHeight = Math.floor(
height / this.currentAscii.blockHeight
);
const canvasBlockWidth = Math.floor(width / this.currentAscii.blockWidth);
if (canvasBlockHeight > oldHeight) {
@ -269,14 +284,14 @@ export default {
if (!blocks[y]) {
blocks[y] = [];
for (let x = 0; x < canvasBlockWidth; x++) {
blocks[y][x] = Object.assign({},emptyBlock);
blocks[y][x] = Object.assign({}, emptyBlock);
}
} else {
// blocks[y]
// no new rows but new cols
for (let x = 0; x < canvasBlockWidth; x++) {
if (blocks[y] && !blocks[y][x]) {
blocks[y][x] = Object.assign({},emptyBlock)
blocks[y][x] = Object.assign({}, emptyBlock);
}
}
}
@ -290,73 +305,96 @@ export default {
this.canvas.width = width;
this.canvas.height = height;
this.$store.commit('changeAsciiWidthHeight', {
this.$store.commit("changeAsciiWidthHeight", {
width: canvasBlockWidth,
height: canvasBlockHeight,
});
this.$store.commit('updateAsciiBlocks', blocks);
this.$store.commit("updateAsciiBlocks", blocks);
// Restructure blocks code here
this.delayRedrawCanvas();
},
onCavasDragStop(x, y) {
// Update left and top in panel
this.$store.commit('changeAsciiCanvasState', { x, y });
this.$store.commit("changeAsciiCanvasState", { x, y });
},
canvasKeyDown(char) {
if (this.isTextEditing && char.length === 1) {
if (this.currentAscii.blocks[this.textEditing.startY] && this.currentAscii.blocks[this.textEditing.startY][this.textEditing.startX]) {
const targetBlock = this.currentAscii.blocks[this.textEditing.startY][this.textEditing.startX];
if (this.isTextEditing) {
if (
this.currentAscii.blocks[this.textEditing.startY] &&
this.currentAscii.blocks[this.textEditing.startY][
this.textEditing.startX
]
) {
const targetBlock = this.currentAscii.blocks[this.textEditing.startY][
this.textEditing.startX
];
console.log({
x: this.textEditing.startX, y: this.textEditing.startY, char, targetBlock,
});
switch (char) {
case "Backspace":
if (this.currentAscii.blocks[this.textEditing.startY][this.textEditing.startX-1]) {
if (this.$store.getters.getTargetingFg) {
targetBlock.fg = this.$store.getters.getFgColour;
}
this.textEditing.startX--;
targetBlock.char = null;
targetBlock.char = char;
}
break;
if (this.currentAscii.blocks[this.textEditing.startY][this.textEditing.startX + 1]) {
this.textEditing.startX++;
} else {
this.textEditing.startX = 0;
default:
if (char.length === 1) {
if (this.$store.getters.getTargetingFg) {
targetBlock.fg = this.$store.getters.getFgColour;
}
if (this.textEditing.startY < this.currentAscii.height) {
this.textEditing.startY++;
}
targetBlock.char = char;
if (
this.currentAscii.blocks[this.textEditing.startY][
this.textEditing.startX + 1
]
) {
this.textEditing.startX++;
} else {
this.textEditing.startX = 0;
if (this.textEditing.startY < this.currentAscii.height) {
this.textEditing.startY++;
}
}
}
break;
}
}
this.delayRedrawCanvas();
}
},
// Mouse Up, Down and Move
canvasMouseUp() {
switch (
this.currentTool.name
) {
case 'brush':
switch (this.currentTool.name) {
case "brush":
this.canTool = false;
break;
case 'eraser':
case "eraser":
this.canTool = false;
break;
case 'fill':
case "fill":
this.canTool = false;
break;
case 'select':
case "select":
this.selecting.canSelect = false;
this.clearToolCanvas();
break;
case 'text':
if (this.textEditing.startX === null || this.textEditing.startY === null) {
case "text":
if (
this.textEditing.startX === null ||
this.textEditing.startY === null
) {
this.textEditing.startX = this.x;
this.textEditing.startY = this.y;
}
@ -369,23 +407,21 @@ export default {
this.toolsCtx.clearRect(0, 0, 10000, 10000);
if (
this.currentAscii.blocks[this.y]
&& this.currentAscii.blocks[this.y][this.x]
&& this.currentTool
this.currentAscii.blocks[this.y] &&
this.currentAscii.blocks[this.y][this.x] &&
this.currentTool
) {
const targetBlock = this.currentAscii.blocks[this.y][
this.x
];
const targetBlock = this.currentAscii.blocks[this.y][this.x];
switch (
this.currentTool.name
) {
case 'default':
switch (this.currentTool.name) {
case "default":
break;
case 'select':
if (this.selecting.startX === null || this.selecting.startY === null) {
case "select":
if (
this.selecting.startX === null ||
this.selecting.startY === null
) {
this.selecting.startX = this.x;
this.selecting.startY = this.y;
this.selecting.canSelect = true;
@ -393,32 +429,32 @@ export default {
break;
case 'fill':
case "fill":
this.fill();
break;
case 'brush':
case "brush":
this.canTool = true;
break;
case 'eraser':
case "eraser":
this.canTool = true;
break;
case 'dropper':
case "dropper":
if (this.$store.getters.getTargetingFg) {
this.$store.commit('changeColourFg', targetBlock.fg);
this.$store.commit("changeColourFg", targetBlock.fg);
}
if (this.$store.getters.getTargetingBg) {
this.$store.commit('changeColourBg', targetBlock.bg);
this.$store.commit("changeColourBg", targetBlock.bg);
}
if (this.$store.getters.getTargetingChar) {
this.$store.commit('changeChar', targetBlock.char);
this.$store.commit("changeChar", targetBlock.char);
}
this.$store.commit('changeTool', 0);
this.$store.commit("changeTool", 0);
break;
}
}
@ -433,26 +469,22 @@ export default {
}
this.x = Math.floor(this.x / this.currentAscii.blockWidth);
this.y = Math.floor(
this.y / this.currentAscii.blockHeight,
);
this.y = Math.floor(this.y / this.currentAscii.blockHeight);
this.$emit('coordsupdate', { x: this.x, y: this.y });
this.$emit("coordsupdate", { x: this.x, y: this.y });
if (
this.currentAscii.blocks[this.y]
&& this.currentAscii.blocks[this.y][this.x]
this.currentAscii.blocks[this.y] &&
this.currentAscii.blocks[this.y][this.x]
) {
const targetBlock = this.currentAscii.blocks[this.y][
this.x
];
const targetBlock = this.currentAscii.blocks[this.y][this.x];
switch (
this.$store.getters.getToolbarIcons[
this.$store.getters.getCurrentTool
].name
) {
case 'brush':
case "brush":
if (this.canTool) {
if (this.$store.getters.getTargetingFg) {
targetBlock.fg = this.$store.getters.getFgColour;
@ -468,7 +500,7 @@ export default {
}
break;
case 'eraser':
case "eraser":
if (this.canTool) {
if (this.$store.getters.getTargetingFg) {
targetBlock.fg = null;
@ -484,8 +516,7 @@ export default {
}
break;
case 'select':
case "select":
if (this.selecting.canSelect) {
this.selecting.endX = this.x;
this.selecting.endY = this.y;
@ -517,14 +548,9 @@ export default {
//
// TOOLS
//
// Text tool
textTool() {
},
// Fill tool
fill() {
const fillBlocks = {
...this.currentAscii.blocks,
};
@ -545,7 +571,7 @@ export default {
// Other wise call the fill function which will fill in the existing image.
this.fillTool(fillBlocks, y, x, newColor, current);
this.$store.commit('updateAsciiBlocks', fillBlocks);
this.$store.commit("updateAsciiBlocks", fillBlocks);
},
fillTool(fillBlocks, y, x, newColor, current) {
// If row is less than 0