linter, better canvas resize with undo, readme update, store text data when leaving text mode

This commit is contained in:
Hugh Bord 2021-08-15 11:20:58 +10:00
parent 640cdcf982
commit f0a10e06d8
15 changed files with 198 additions and 112 deletions

View File

@ -24,9 +24,11 @@ A most latest production build to use is available at https://asciibird.jewbird.
# Current Features
* Tabbed ASCII editing
* Layers support with visibility and ordering
* Copy and paste between tabs
* Remembers state on refresh and when the browser loads, can also export the state to a file and load elsewhere.
* So you never lose your ascii art!
* Saves layers, brushes data also to same file
* Can import from clipboard, load from irc.watch/ascii, load from file
* Can export to mirc ascii to clipboard or file
* 99 Colour support, flip colours
@ -60,18 +62,17 @@ A most latest production build to use is available at https://asciibird.jewbird.
ASCIIBIRD is mostly usable. There are some bugs however to note at the moment.
* If you resize an ascii, and then undo and try fill in blocks it will error cuz the blocks don't exist
* Redo (ctrl y) is a buggy
* Circle brush (works okay for odd width and height numbers)
* Importer could be re-written with regex
* Exporter will default transparent bg to black by default, which wont for some asciis
* Duplicate keyboard listeners, if you close all the ascii tabs and open/load a new ASCII it will double up on keyboard events, you can fix this by refreshing the page at the moment.
## Focusing on Now
* Modals to add
* Asciibird options / Options modal from skgs PR
* Context Menus (right click menu) - add to other areas of asciibird
* LAYERS, drag and drop to arrange layers
* Image overlay for trace mode
* Experimental code to only render blocks visible on screen
* Review encodings check on file import - UTF8 vs Latin something

View File

@ -1,11 +1,13 @@
<template>
<div id="app">
<NewAscii />
<EditAscii />
<PasteAscii />
<context-menu :display="showContextMenu" ref="menu">
<context-menu
:display="showContextMenu"
ref="menu"
>
<ul>
<li
@click="$store.commit('openModal', 'new-ascii')"
@ -14,8 +16,18 @@
>
New ASCII
</li>
<li @click="clearCache()" class="ml-1">Clear and Refresh</li>
<li @click="startImport('mirc')" class="ml-1">Import mIRC</li>
<li
@click="clearCache()"
class="ml-1"
>
Clear and Refresh
</li>
<li
@click="startImport('mirc')"
class="ml-1"
>
Import mIRC
</li>
<li
@click="startExport('file')"
class="ml-1"
@ -23,7 +35,10 @@
>
Export mIRC to File
</li>
<li class="ml-1" @click="$store.commit('openModal', 'paste-ascii')">
<li
class="ml-1"
@click="$store.commit('openModal', 'paste-ascii')"
>
Import mIRC from Clipboard
</li>
<li
@ -40,7 +55,12 @@
>
Save Asciibird State
</li>
<li @click="startImport('asb')" class="ml-1">Load Asciibird State</li>
<li
@click="startImport('asb')"
class="ml-1"
>
Load Asciibird State
</li>
<li
@click="$store.commit('openModal', 'edit-ascii')"
class="ml-1"
@ -62,11 +82,18 @@
style="display: none"
ref="asciiInput"
@change="onImport()"
/>
>
<template v-if="asciibirdMeta.length">
<span v-for="(value, key) in asciibirdMeta" :key="key" class="mr-2">
<t-button class="p-1" @click="changeTab(key, value)">
<span
v-for="(value, key) in asciibirdMeta"
:key="key"
class="mr-2"
>
<t-button
class="p-1"
@click="changeTab(key, value)"
>
{{ value.title }}
<t-button
@ -78,7 +105,10 @@
</t-button>
</span>
<Toolbar :canvas-x="canvasX" :canvas-y="canvasY" />
<Toolbar
:canvas-x="canvasX"
:canvas-y="canvasY"
/>
<DebugPanel
:canvas-x="canvasX"
:canvas-y="canvasY"
@ -93,7 +123,6 @@
<BrushLibrary v-if="brushLibraryState.visible" />
<BrushPreview />
</template>
<template v-else>
<div
@ -108,7 +137,9 @@
@mouseup.right="openContextMenu"
@contextmenu.prevent
>
<h1 class="text-4xl">ASCIIBIRD</h1>
<h1 class="text-4xl">
ASCIIBIRD
</h1>
<h3>Right click to start</h3>
<BrushCanvas :blocks="splashAscii" />

View File

@ -645,12 +645,6 @@ export const fillNullBlocks = function (height, width, layerData = null) {
var layers = [...layerData]
}
// if (height === false || width === false) {
// height = store.getters.currentAscii.height;
// width = getBlocksWidth(store.getters.currentAsciiLayers[store.getters.currentAscii
// .selectedLayer].data)
// }
for (let i = 0; i <= layers.length - 1; i++) {
let blocks = layers[i].data;

View File

@ -22,8 +22,9 @@
: 'border-gray-200 bg-gray-500'
}`"
@click="changeTab(1)"
>Library</t-button
>
Library
</t-button>
<t-button
type="button"
@ -33,8 +34,9 @@
: 'border-gray-200 bg-gray-500'
}`"
@click="changeTab(0)"
>History</t-button
>
History
</t-button>
<t-button
type="button"
@ -44,12 +46,16 @@
: 'border-gray-200 bg-gray-500'
}`"
@click="changeTab(2)"
>Layers</t-button
>
Layers
</t-button>
<div class="flex">
<div v-if="panel.tab === 0">
<div v-for="(brush, key) in brushHistory" :key="key">
<div
v-for="(brush, key) in brushHistory"
:key="key"
>
<t-card
class="hover:border-blue-900 border-gray-300 bg-gray-200 mt-2"
>
@ -58,34 +64,43 @@
<t-button
type="button"
@click="saveToLibrary(decompressBlock(brush.blocks))"
><font-awesome-icon
>
<font-awesome-icon
:icon="['fas', 'save']"
size="lg"
class="p-1 mx-1"
/></t-button>
/>
</t-button>
<t-button
type="button"
@click="reuseBlocks(decompressBlock(brush.blocks))"
><font-awesome-icon
>
<font-awesome-icon
:icon="['fas', 'paint-brush']"
size="lg"
class="p-1 mx-1"
/></t-button>
/>
</t-button>
<t-button
type="button"
@click="removeFromHistory(decompressBlock(brush.blocks))"
><font-awesome-icon
>
<font-awesome-icon
:icon="['fas', 'trash']"
size="lg"
class="p-1 mx-1 right-auto"
/></t-button>
/>
</t-button>
</t-card>
</div>
</div>
<div v-if="panel.tab === 1">
<div v-for="(brush, key) in brushLibrary" :key="key">
<div
v-for="(brush, key) in brushLibrary"
:key="key"
>
<t-card
:class="`hover:border-blue-900 border-gray-300 bg-gray-200 mt-2`"
>
@ -94,19 +109,23 @@
<t-button
type="button"
@click="removeFromLibrary(decompressBlock(brush.blocks))"
><font-awesome-icon
>
<font-awesome-icon
:icon="['fas', 'trash']"
size="lg"
class="p-1 mx-1"
/></t-button>
/>
</t-button>
<t-button
type="button"
@click="reuseBlocks(decompressBlock(brush.blocks))"
><font-awesome-icon
>
<font-awesome-icon
:icon="['fas', 'paint-brush']"
size="lg"
class="p-1 mx-1"
/></t-button>
/>
</t-button>
</t-card>
</div>
</div>
@ -115,7 +134,6 @@
v-if="panel.tab === 2"
class="w-full bg-white rounded-lg shadow-lg"
>
<Layers />
</div>
</div>
@ -137,11 +155,9 @@
<script>
import { mircColours99, blockWidth, blockHeight } from "../ascii";
import BrushCanvas from "./parts/BrushCanvas.vue";
import BrushPreview from "./parts/BrushPreview.vue";
import Layers from "./parts/Layers.vue";
import LZString from "lz-string";
export default {
name: "BrushLibrary",
created() {
@ -164,8 +180,7 @@ export default {
}),
components: {
BrushCanvas,
BrushPreview,
Layers
Layers,
},
computed: {
blockWidth() {

View File

@ -85,7 +85,7 @@
</label>
</div>
<hr class="m-3" />
<hr class="m-3">
<t-button
type="button"
@ -98,9 +98,11 @@
}`"
@click="$store.commit('changeTool', keyToolbar)"
>
<font-awesome-icon :icon="[value.fa, value.icon]" size="lg" />
<font-awesome-icon
:icon="[value.fa, value.icon]"
size="lg"
/>
</t-button>
</t-card>
</vue-draggable-resizable>
</div>
@ -146,7 +148,7 @@ export default {
return blockHeight * this.blockSizeMultiplier;
},
blockSizeMultiplier() {
return this.$store.getters.blockSizeMultiplier
return this.$store.getters.blockSizeMultiplier;
},
toolbarState() {
return this.$store.getters.toolbarState;

View File

@ -30,15 +30,22 @@
max="128"
/>
<hr class="mt-5 mb-5" />
<hr class="mt-5 mb-5">
<template v-slot:footer>
<div
class="flex justify-between"
@click="$store.commit('closeModal', 'edit-ascii')"
>
<t-button type="button"> Cancel </t-button>
<t-button type="button" @click="updateAscii()"> Update </t-button>
<t-button type="button">
Cancel
</t-button>
<t-button
type="button"
@click="updateAscii()"
>
Update
</t-button>
</div>
</template>
</t-modal>

View File

@ -35,8 +35,15 @@
class="flex justify-between"
@click="$store.commit('closeModal', 'new-ascii')"
>
<t-button type="button"> Cancel </t-button>
<t-button type="button" @click="initiateNewAscii()"> Ok </t-button>
<t-button type="button">
Cancel
</t-button>
<t-button
type="button"
@click="initiateNewAscii()"
>
Ok
</t-button>
</div>
</template>
</t-modal>

View File

@ -7,9 +7,18 @@
@closed="$store.commit('closeModal', 'paste-ascii')"
>
Title
<t-input type="text" name="title" v-model="title" max="128" />
<t-input
type="text"
name="title"
v-model="title"
max="128"
/>
<t-textarea v-model="pasteContent" name="paste-ascii" rows="10" />
<t-textarea
v-model="pasteContent"
name="paste-ascii"
rows="10"
/>
<template v-slot:footer>
<div class="flex justify-between">

View File

@ -9,7 +9,7 @@
:width="blocksWidthHeight.w"
:height="blocksWidthHeight.h"
/>
</div>
</div>
</t-card>
</div>
</template>

View File

@ -67,7 +67,10 @@
</label>
</div>
<div @mouseenter="canDrag = false" @mouseleave="canDrag = true">
<div
@mouseenter="canDrag = false"
@mouseleave="canDrag = true"
>
<MainBrushCanvas />
</div>
</t-card>

View File

@ -1,5 +1,5 @@
<template>
<div></div>
<div />
</template>
<script>

View File

@ -5,10 +5,11 @@
type="button"
class="block w-full border-gray-200 bg-gray-500 p-2 m-2"
@click="addLayer()"
>Add Layer</t-button
>
Add Layer
</t-button>
<hr />
<hr>
<div class="w-full bg-white rounded-lg shadow">
<ul class="divide-y-2 divide-gray-100 reverseorder">
@ -24,23 +25,31 @@
class="rounded-xl"
@click="toggleLayer(key)"
:disabled="!canToggleLayer && lastVisible"
><font-awesome-icon
>
<font-awesome-icon
:icon="[
'fas',
layer.visible ? 'eye' : 'eye-slash',
]" /></t-button
><br />
]"
/>
</t-button><br>
<t-button
type="button"
class="rounded-xl"
@click="removeLayer(key)"
:disabled="!canToggleLayer"
><font-awesome-icon :icon="['fas', 'trash']"
/></t-button>
>
<font-awesome-icon
:icon="['fas', 'trash']"
/>
</t-button>
</div>
<div class="w-full" @click="changeLayer(key)">
<div
class="w-full"
@click="changeLayer(key)"
>
<div class="flex text-right">
<div class="w-full">
<t-card class="w-full">
@ -54,18 +63,22 @@
class="rounded-xl"
@click="downLayer(key)"
:disabled="!canToggleLayer"
><font-awesome-icon
:icon="['fas', 'chevron-circle-up']" /></t-button
><br />
>
<font-awesome-icon
:icon="['fas', 'chevron-circle-up']"
/>
</t-button><br>
<t-button
type="button"
class="rounded-xl"
@click="upLayer(key)"
:disabled="!canToggleLayer"
><font-awesome-icon
>
<font-awesome-icon
:icon="['fas', 'chevron-circle-down']"
/></t-button>
/>
</t-button>
</div>
</div>
</div>

View File

@ -1,24 +1,23 @@
<template>
<div>
<t-card class="overflow-x-scroll h-full" >
<div :style="`height: ${blocksWidthHeight.h}px;width: ${blocksWidthHeight.w}px;`">
<canvas
ref="brushcanvas"
id="brushcanvas"
class="brushcanvas"
@mousemove="canvasMouseMove"
@mouseup="disable"
@mousedown.left="addBlock"
@mousedown.right="eraseBlock"
@contextmenu.prevent
:width="blocksWidthHeight.w"
:height="blocksWidthHeight.h"
@mouseenter="disableToolbarMoving"
@mouseleave="enableToolbarMoving"
/>
</div>
<t-card class="overflow-x-scroll h-full">
<div :style="`height: ${blocksWidthHeight.h}px;width: ${blocksWidthHeight.w}px;`">
<canvas
ref="brushcanvas"
id="brushcanvas"
class="brushcanvas"
@mousemove="canvasMouseMove"
@mouseup="disable"
@mousedown.left="addBlock"
@mousedown.right="eraseBlock"
@contextmenu.prevent
:width="blocksWidthHeight.w"
:height="blocksWidthHeight.h"
@mouseenter="disableToolbarMoving"
@mouseleave="enableToolbarMoving"
/>
</div>
</t-card>
</div>
</template>

View File

@ -219,7 +219,7 @@ export default new Vuex.Store({
tempLayers.push({
label: 'Layer ' + Number.parseInt(tempLayers.length),
visible: true,
data: newBlocksArray,
data: [...newBlocksArray],
width: width,
height: height
})

View File

@ -515,7 +515,7 @@ export default {
return this.$store.getters.currentAsciiLayers;
},
currentSelectedLayer() {
return this.currentAsciiLayers[this.currentAscii.selectedLayer]
return this.currentAsciiLayers[this.currentAscii.selectedLayer];
},
currentAsciiLayerBlocks() {
return this.currentSelectedLayer.data;
@ -615,21 +615,21 @@ export default {
return maxBrushSize;
},
currentAsciiWidth() {
return this.currentSelectedLayer.width
return this.currentSelectedLayer.width;
},
currentAsciiHeight() {
return this.currentSelectedLayer.height
}
return this.currentSelectedLayer.height;
},
},
watch: {
currentAscii(val, old) {
if (val !== old) {
this.onCanvasResize(
100,
100,
this.currentAsciiWidth * blockWidth,
this.currentAsciiHeight * blockHeight
);
// this.onCanvasResize(
// 100,
// 100,
// this.currentAsciiWidth * blockWidth,
// this.currentAsciiHeight * blockHeight
// );
this.canvas.width = this.currentAsciiWidth * blockWidth;
this.canvas.height = this.currentAsciiHeight * blockHeight;
@ -680,6 +680,12 @@ export default {
blockSizeMultiplier() {
this.delayRedrawCanvas();
},
// Save text to store when finished
isTextEditing(val, old) {
if (val !== old && val === false) {
this.$store.commit("updateAsciiBlocks", this.currentAsciiLayerBlocks)
}
}
},
methods: {
checkVisible(top) {
@ -822,10 +828,7 @@ export default {
onCanvasResize(left, top, width, height) {
const canvasBlockHeight = Math.floor(height / blockHeight);
const canvasBlockWidth = Math.floor(width / blockWidth);
let layers = fillNullBlocks(
canvasBlockHeight,
canvasBlockWidth
);
let layers = fillNullBlocks(canvasBlockHeight, canvasBlockWidth);
this.top = top;
this.canvas.width = width;
@ -834,11 +837,11 @@ export default {
this.$store.commit("changeAsciiWidthHeight", {
width: canvasBlockWidth,
height: canvasBlockHeight,
layers: layers
layers: [...layers],
});
this.$refs.canvasdrag.width = width
this.$refs.canvasdrag.width = height
this.$refs.canvasdrag.width = width;
this.$refs.canvasdrag.width = height;
this.delayRedrawCanvas();
},
@ -1338,15 +1341,17 @@ export default {
this.drawRectangleBlock(this.x, this.y);
if (this.isTextEditing) {
this.toolCtx.font = '600 22px "Font Awesome 5 Free"';
this.toolCtx.fillText(
"\uf031",
this.x * blockWidth,
this.y * blockHeight + blockHeight * 2
);
// this.toolCtx.font = "13px Hack";
}
// We can draw icons on the tool canvas with the font awesome CSS
// it needs more work though to not conflict with the brush preview chars
// if (this.isTextEditing) {
// this.toolCtx.font = '600 22px "Font Awesome 5 Free"';
// this.toolCtx.fillText(
// "\uf031",
// this.x * blockWidth,
// this.y * blockHeight + blockHeight * 2
// );
// // this.toolCtx.font = "13px Hack";
// }
if (this.isTextEditing) {
if (this.mirrorX) {