clean files, splash ascii readme, added new bugs to readme

This commit is contained in:
Hugh Bord 2021-12-28 12:09:11 +10:00
parent 458acbfb7b
commit 797914c754
25 changed files with 400 additions and 565 deletions

View File

@ -46,7 +46,7 @@ A most latest production build to use is available at https://asciibird.jewbird.
* Undo and redo with Ctrl + z and Ctrl + y, undos are set to a limit of 200 at the moment.
* Fg, Bg and Char boxes to filter when using certain tools
* For example filling with Char unchecked will ignore characters when filling
* If you want to remove the background but keep the text, unchek FG and Char and eraser the bg only.
* If you want to remove the background but keep the text, uncheck FG and Char and eraser the bg only.
* Image overlay to trace images
* Accepts URLs only at the moment
* Can adjust the size and properties
@ -81,6 +81,10 @@ A most latest production build to use is available at https://asciibird.jewbird.
## Bugs to fix
* Can't move toolbar, maybe related to after dialog or modal is open
* Brush edit if scroll out wont register mouse down and keep applying brush on scroll over without clicking
* Colors / chars panels wont open where toolbar is, if you scroll down a lot then try open them they will be at the top
* Fill tool has too much recursion sometimes
* One of the mirror brushes might be bugged sometimes and leave undoable blocks
* Strange sort of bug with remove layer and selecting layer after, scroll up and down to redraw the canvas if it goes blank
* Redo will cause errors on layers sometimes

View File

@ -1,5 +1,5 @@
<template>
<div id="app">
<div id="app" @contextmenu.prevent>
<div v-show="menuBarVisible">
<vue-file-toolbar-menu :content="myMenu" />
</div>
@ -39,7 +39,6 @@
<li
@click="$store.commit('openModal', 'new-ascii')"
class="ab-context-menu-item"
@contextmenu.prevent
>
New ASCII
</li>
@ -110,7 +109,6 @@
<span
@mouseup.right="openContextMenu"
@contextmenu.prevent
style="width: 100%; height: 100%; position: absolute; z-index: -1"
/>
@ -202,16 +200,8 @@
</template>
<template v-else>
<div
class="
absolute
top-1/2
left-1/2
transform
-translate-x-1/2 -translate-y-1/2
text-center
"
class="absolute left-1/2 transform -translate-x-1/2 text-center"
@mouseup.right="openContextMenu"
@contextmenu.prevent
>
<BrushCanvas :blocks="this.splashAscii()" />
</div>
@ -220,6 +210,10 @@
</template>
<script>
// top-1/2
// -translate-y-1/2
// these css classes can put back to center smaller asciis
import LZString from "lz-string";
import Toolbar from "./components/Toolbar.vue";
import DebugPanel from "./components/DebugPanel.vue";
@ -267,7 +261,6 @@ export default {
});
this.mirror.x = this.toolbarState.mirrorX;
this.mirror.y = this.toolbarState.mirrorY;
},
destroyed() {
window.removeEventListener("scroll", function (event) {

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,6 @@
ref="brushlibrarypanel"
>
<t-card class="h-full overflow-y-auto overflow-x-auto">
<t-button
type="button"
:class="`w-1/2 border-gray-200 bg-gray-500 text-sm ${
@ -25,10 +24,10 @@
}`"
@click="changeTab(0)"
>
<span class="material-icons relative top-2 pb-4">history</span> History
<span class="material-icons relative top-2 pb-4">history</span>
History
</t-button>
<t-button
type="button"
:class="`w-1/2 border-gray-200 bg-gray-500 text-sm ${
@ -38,11 +37,10 @@
}`"
@click="changeTab(1)"
>
<span class="material-icons relative top-2 pb-4">library_books</span> Library {{ libraryCount }}
<span class="material-icons relative top-2 pb-4">library_books</span>
Library {{ libraryCount }}
</t-button>
<div class="flex">
<div v-if="panel.tab === 0">
<div v-for="(brush, key) in brushHistory" :key="key">
@ -56,23 +54,22 @@
class="ab-rounded-button ml-1 mt-1"
@click="saveToLibrary(decompressBlock(brush.blocks))"
>
<span class="material-icons">save</span>
<span class="material-icons">save</span>
</t-button>
<t-button
type="button"
class="ab-rounded-button ml-1 mt-1"
@click="reuseBlocks(decompressBlock(brush.blocks))">
<span class="material-icons">brush</span>
</t-button>
@click="reuseBlocks(decompressBlock(brush.blocks))"
>
<span class="material-icons">brush</span>
</t-button>
<t-button
type="button"
class="ab-rounded-button ml-1 mt-1"
@click="removeFromHistory(decompressBlock(brush.blocks))"
>
<span class="material-icons">delete</span>
<span class="material-icons">delete</span>
</t-button>
</t-card>
</div>
@ -80,7 +77,9 @@
<div v-if="panel.tab === 1">
<div v-if="!brushLibrary.length">
<p class="text-sm text-center p-5">Save brushes to your library to use them here.</p>
<p class="text-sm text-center p-5">
Save brushes to your library to use them here.
</p>
</div>
<div v-for="(brush, key) in brushLibrary" :key="key">
@ -94,16 +93,14 @@
class="ab-rounded-button ml-1 mt-1"
@click="removeFromLibrary(decompressBlock(brush.blocks))"
>
<span class="material-icons">delete</span>
<span class="material-icons">delete</span>
</t-button>
<t-button
type="button"
class="ab-rounded-button ml-1 mt-1"
@click="reuseBlocks(decompressBlock(brush.blocks))"
>
<span class="material-icons">brush</span>
<span class="material-icons">brush</span>
</t-button>
</t-card>
</div>
@ -152,7 +149,7 @@ export default {
components: {
BrushCanvas,
},
props: ['yOffset'],
props: ["yOffset"],
computed: {
blockWidth() {
return blockWidth * this.blockSizeMultiplier;
@ -182,13 +179,17 @@ export default {
return this.$store.getters.brushLibraryState;
},
libraryCount() {
return this.brushLibrary.length > 0 ? `(${this.brushLibrary.length})` : '';
}
return this.brushLibrary.length > 0
? `(${this.brushLibrary.length})`
: "";
},
},
watch: {
yOffset(val) {
this.$refs.brushlibrarypanel.top = Number.parseInt(this.brushLibraryState.y+val)
}
this.$refs.brushlibrarypanel.top = Number.parseInt(
this.brushLibraryState.y + val
);
},
},
methods: {
changeTab(tab) {
@ -202,14 +203,14 @@ export default {
this.$store.commit("brushBlocks", value);
this.$store.commit("changeTool", 4);
this.$toasted.show(`Applied brush from Library`, {
type: "success",
});
type: "success",
});
},
saveToLibrary(value) {
this.$store.commit("pushBrushLibrary", value);
this.$toasted.show(`Saved brush to Library`, {
type: "success",
});
type: "success",
});
},
removeFromLibrary(value) {
this.$store.commit("removeBrushLibrary", value);

View File

@ -5,7 +5,7 @@
:style="`background-color: ${mircColours[currentFg]} !important;`"
class="border-gray-200 w-14 h-14 text-2xl"
id="currentColourFg"
@click="$store.commit('changeIsUpdatingFg', ! toolbarState.isChoosingFg )"
@click="$store.commit('changeIsUpdatingFg', !toolbarState.isChoosingFg)"
>
FG
</t-button>
@ -15,7 +15,7 @@
:style="`background-color: ${mircColours[currentBg]} !important;`"
class="border-gray-200 w-14 h-14 text-2xl ml-2"
id="currentColourBg"
@click="$store.commit('changeIsUpdatingBg', ! toolbarState.isChoosingBg )"
@click="$store.commit('changeIsUpdatingBg', !toolbarState.isChoosingBg)"
>
BG
</t-button>
@ -23,7 +23,7 @@
<t-button
type="button"
class="rounded-3xl w-7 h-7"
style="margin-left: -75px; margin-top: 12px;"
style="margin-left: -75px; margin-top: 12px"
id="swapColour"
@click="swapColours()"
>
@ -35,7 +35,9 @@
:style="`background-color: ${mircColours[currentBg]} !important;color: ${mircColours[currentFg]};`"
class="border-gray-200 w-14 h-14 text-2xl ml-14"
id="currentChar"
@click="$store.commit('changeIsUpdatingChar', ! toolbarState.isChoosingChar )"
@click="
$store.commit('changeIsUpdatingChar', !toolbarState.isChoosingChar)
"
>
{{ toolbarState.selectedChar === " " ? "SP" : toolbarState.selectedChar }}
</t-button>

View File

@ -13,57 +13,45 @@
:y="debugPanelState.y"
>
<t-card class="h-full">
<span
class="ml-5"
v-html="`Tool: ${getToolName}`"
/> <br>
<span
class="ml-5"
v-html="`FgColour: ${currentFg}`"
/> <br>
<span
class="ml-5"
v-html="`BgColor: ${currentBg}`"
/> <br>
<span
class="ml-5"
v-html="`Char: ${currentChar}`"
/> <br>
<span class="ml-5" v-html="`Tool: ${getToolName}`" /> <br />
<span class="ml-5" v-html="`FgColour: ${currentFg}`" /> <br />
<span class="ml-5" v-html="`BgColor: ${currentBg}`" /> <br />
<span class="ml-5" v-html="`Char: ${currentChar}`" /> <br />
<span
class="ml-5"
v-html="`canvasX: ${canvasX}`"
/> <br>
<span
class="ml-5"
v-html="`canvasY: ${canvasY}`"
/> <br>
<span class="ml-5" v-html="`canvasX: ${canvasX}`" /> <br />
<span class="ml-5" v-html="`canvasY: ${canvasY}`" /> <br />
<span
class="ml-5"
v-html="`mirrorX: ${mirrorX}`"
/> <br>
<span
class="ml-5"
v-html="`mirrorY: ${mirrorY}`"
/>
<br>
<span class="ml-5" v-html="`mirrorX: ${mirrorX}`" /> <br />
<span class="ml-5" v-html="`mirrorY: ${mirrorY}`" />
<span class="ml-5">State Internal Size: {{ asciiStats.stateSize }} </span> <br>
<br />
<span class="ml-5"
>State Internal Size: {{ asciiStats.stateSize }}
</span>
<br />
<div class="mb-4 border-t-2">
<div class="mt-1 p-2 bg-red-300 rounded-md cursor-pointer" @click="copyUriToClipboard()">Copy URI Encoded String</div>
<div
class="mt-1 p-2 bg-red-300 rounded-md cursor-pointer"
@click="copyUriToClipboard()"
>
Copy URI Encoded String
</div>
</div>
</t-card>
</vue-draggable-resizable>
</div>
</template>
<script>
import { toolbarIcons, mircColours99, blockWidth, blockHeight, exportMirc, mergeLayers } from '../ascii';
import {
toolbarIcons,
mircColours99,
blockWidth,
blockHeight,
exportMirc,
mergeLayers,
} from "../ascii";
import LZString from "lz-string";
export default {
@ -73,8 +61,8 @@ export default {
this.panel.w = this.debugPanelState.w;
this.panel.h = this.debugPanelState.h;
},
name: 'DebugPanel',
props: ['canvasX', 'canvasY'],
name: "DebugPanel",
props: ["canvasX", "canvasY"],
data: () => ({
panel: {
w: 0,
@ -93,10 +81,12 @@ export default {
return blockHeight * this.blockSizeMultiplier;
},
blockSizeMultiplier() {
return this.$store.getters.blockSizeMultiplier
return this.$store.getters.blockSizeMultiplier;
},
getToolName() {
return toolbarIcons[this.$store.getters.currentTool] ? toolbarIcons[this.$store.getters.currentTool].name : 'none';
return toolbarIcons[this.$store.getters.currentTool]
? toolbarIcons[this.$store.getters.currentTool].name
: "none";
},
debugPanelState() {
return this.$store.getters.debugPanel;
@ -107,18 +97,17 @@ export default {
asciiStats() {
// const compressed = ( JSON.stringify(this.currentAscii) / 1024).toFixed(2);
// const uncompressed = (JSON.stringify(this.currentAscii).length / 1024).toFixed(2);
const byteSize = str => new Blob([str]).size;
const byteSize = (str) => new Blob([str]).size;
const stateSize = (byteSize(JSON.stringify(this.state)) / 1024).toFixed(2);
const stateSize = (byteSize(JSON.stringify(this.state)) / 1024).toFixed(
2
);
return {
stateSize: `${stateSize}kb`,
};
},
currentTool() {
return toolbarIcons[
this.$store.getters.currentTool
];
return toolbarIcons[this.$store.getters.currentTool];
},
mircColours() {
return mircColours99;
@ -142,17 +131,17 @@ export default {
return this.$store.getters.currentChar;
},
isTextEditing() {
return this.currentTool.name === 'text';
return this.currentTool.name === "text";
},
isSelecting() {
return this.currentTool.name === 'select';
return this.currentTool.name === "select";
},
isSelected() {
return (
this.selecting.startX
&& this.selecting.startY
&& this.selecting.endX
&& this.selecting.endY
this.selecting.startX &&
this.selecting.startY &&
this.selecting.endX &&
this.selecting.endY
);
},
brushBlocks() {
@ -174,20 +163,22 @@ export default {
watch: {},
methods: {
copyUriToClipboard() {
let ascii = LZString.compressToEncodedURIComponent(JSON.stringify(mergeLayers()));
let ascii = LZString.compressToEncodedURIComponent(
JSON.stringify(mergeLayers())
);
this.$copyText(ascii).then(
(e) => {
this.$toasted.show("Copied URI encoded ASCII for Splash Ascii!", {
type: "success",
});
},
(e) => {
this.$toasted.show("Error when copying URI encoded ASCII!", {
type: "error",
});
}
);
this.$copyText(ascii).then(
(e) => {
this.$toasted.show("Copied URI encoded ASCII for Splash Ascii!", {
type: "success",
});
},
(e) => {
this.$toasted.show("Error when copying URI encoded ASCII!", {
type: "error",
});
}
);
},
onResize(x, y, w, h) {
this.panel.x = x;
@ -195,17 +186,17 @@ export default {
this.panel.w = w;
this.panel.h = h;
this.$store.commit('changeDebugPanelState', this.panel);
this.$store.commit("changeDebugPanelState", this.panel);
},
onDragStop(x, y) {
this.panel.x = x;
this.panel.y = y;
this.$store.commit('changeDebugPanelState', this.panel);
this.$store.commit("changeDebugPanelState", this.panel);
},
exportMirc() {
return exportMirc()
}
return exportMirc();
},
},
};
</script>

View File

@ -14,9 +14,7 @@
:y="layersLibraryState.y"
ref="layerspanel"
>
<t-card
class="h-full overflow-y-auto overflow-x-hidden"
>
<t-card class="h-full overflow-y-auto overflow-x-hidden">
<Layers />
</t-card>
</vue-draggable-resizable>
@ -52,7 +50,7 @@ export default {
components: {
Layers,
},
props: ['yOffset'],
props: ["yOffset"],
computed: {
blockWidth() {
return blockWidth * this.blockSizeMultiplier;
@ -69,8 +67,10 @@ export default {
},
watch: {
yOffset(val) {
this.$refs.layerspanel.top = Number.parseInt(this.layersLibraryState.y+val)
}
this.$refs.layerspanel.top = Number.parseInt(
this.layersLibraryState.y + val
);
},
},
methods: {
onResize(x, y, w, h) {

View File

@ -7,47 +7,23 @@
@closed="$store.commit('closeModal', 'edit-ascii')"
>
Width
<t-input
type="number"
name="width"
v-model="layer.width"
min="1"
/>
<t-input type="number" name="width" v-model="layer.width" min="1" />
Height
<t-input
type="number"
name="height"
v-model="layer.height"
min="1"
/>
<t-input type="number" name="height" v-model="layer.height" min="1" />
Title
<t-input
type="text"
name="title"
v-model="layer.title"
max="128"
/>
<t-input type="text" name="title" v-model="layer.title" 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"
class="p-2"
>
Cancel
</t-button>
<t-button
type="button"
@click="updateAscii()"
class="p-2"
>
<t-button type="button" class="p-2"> Cancel </t-button>
<t-button type="button" @click="updateAscii()" class="p-2">
Update
</t-button>
</div>
@ -56,17 +32,14 @@
</template>
<script>
export default {
name: "EditAsciiModal",
created() {
},
created() {},
mounted() {
if (this.showEditAsciiModal) {
this.open()
this.open();
} else {
this.close()
this.close();
}
},
data: () => ({
@ -80,7 +53,7 @@ export default {
return this.$store.getters.currentAscii;
},
selectedLayerIndex() {
return this.currentAscii.selectedLayer
return this.currentAscii.selectedLayer;
},
currentAsciiEditingTitle() {
return `Editing ASCII ${this.currentAscii.title}`;
@ -115,20 +88,20 @@ export default {
this.$emit("updateAscii", {
width: this.layer.width,
height: this.layer.height,
});
});
this.close();
},
open() {
this.layer = {
width: this.currentSelectedLayer.width,
height: this.currentSelectedLayer.height,
title: this.currentAscii.title
}
title: this.currentAscii.title,
};
this.$modal.show("edit-ascii-modal");
},
close() {
this.$modal.hide("edit-ascii-modal");
this.layer = {}
this.layer = {};
},
},
};

View File

@ -7,18 +7,16 @@
@closed="$store.commit('closeModal', 'overlay')"
>
<template v-slot:default>
<div >
<span class="text-sm">URL <br><small>Note: ASCIIBIRD only supports URL images</small></span>
<t-input
type="text"
name="url"
v-model="imageOverlay.url"
/>
<div>
<span class="text-sm"
>URL <br /><small
>Note: ASCIIBIRD only supports URL images</small
></span
>
<t-input type="text" name="url" v-model="imageOverlay.url" />
</div>
</div>
<div class="flex">
<label class="ml-1 w-1/3">
<t-checkbox
@ -39,22 +37,26 @@
max="100"
class="m-1"
/>
</label>
<div class="flex">
<label class="flex items-center">
<t-radio
name="options"
:value="true"
v-model="imageOverlay.stretched"
/>
<span class="ml-2 text-sm">Fit to ASCII</span>
</label>
<div class="flex">
<label class="flex items-center">
<t-radio name="options" :value="true" v-model="imageOverlay.stretched" />
<span class="ml-2 text-sm">Fit to ASCII</span>
</label>
<label class="flex items-center ml-2">
<t-radio name="options" :value="false" v-model="imageOverlay.stretched" />
<span class="ml-2 text-sm">Original Size</span>
</label>
</div>
<label class="flex items-center ml-2">
<t-radio
name="options"
:value="false"
v-model="imageOverlay.stretched"
/>
<span class="ml-2 text-sm">Original Size</span>
</label>
</div>
</div>
<div class="flex">
@ -75,8 +77,6 @@
/>
<span class="text-sm">Repeat Y</span>
</label>
</div>
</template>
@ -86,9 +86,7 @@
@click="$store.commit('closeModal', 'overlay')"
>
<t-button type="button" class="p-2"> Cancel </t-button>
<t-button type="button" class="p-2">
Ok
</t-button>
<t-button type="button" class="p-2"> Ok </t-button>
</div>
</template>
</t-modal>
@ -105,15 +103,14 @@ export default {
this.close();
}
},
data: () => ({
}),
data: () => ({}),
computed: {
showOverlayModal() {
return this.$store.getters.modalState.overlay;
},
imageOverlay() {
return this.$store.getters.imageOverlay || {};
}
},
},
watch: {
showOverlayModal(val) {
@ -125,12 +122,12 @@ export default {
this.close();
}
},
imageOverlay:{
handler: function(val, old) {
this.$store.commit("updateImageOverlay", this.imageOverlay);
},
deep: true
}
imageOverlay: {
handler: function (val, old) {
this.$store.commit("updateImageOverlay", this.imageOverlay);
},
deep: true,
},
},
methods: {
open() {

View File

@ -35,17 +35,8 @@
class="flex justify-between"
@click="$store.commit('closeModal', 'new-ascii')"
>
<t-button
type="button"
class="p-2"
>
Cancel
</t-button>
<t-button
type="button"
class="p-2"
@click="initiateNewAscii()"
>
<t-button type="button" class="p-2"> Cancel </t-button>
<t-button type="button" class="p-2" @click="initiateNewAscii()">
Ok
</t-button>
</div>
@ -61,11 +52,11 @@ export default {
created() {},
mounted() {
if (this.showNewAsciiModal) {
this.open()
this.open();
} else {
this.close()
this.close();
}
},
},
data: () => ({
forms: {
createAscii: {

View File

@ -6,92 +6,96 @@
:esc-to-close="true"
@closed="$store.commit('closeModal', 'options')"
>
<template v-slot:default>
<div class="mt-6 lg:mt-0 rounded shadow bg-white">
<div class="mb-4">
<label class="ml-1">
<div class="mt-6 lg:mt-0 rounded shadow bg-white">
<div class="mb-4">
<label class="ml-1">
<span class="text-sm">FPS</span>
<vue-slider class="mt-10" v-model="options.fps" @dragend="updateOptions" :min="1" :max="200"></vue-slider>
</label>
</div>
<div class="mb-4">
<label class="ml-1">
<span class="text-lg">Render Offscreen Blocks</span><br />
<t-checkbox
class="form-checkbox m-1"
name="renderOffScreen"
v-model="options.renderOffScreen"
@change="updateOptions"
/>
<small>ASCIIBIRD will avoid rendering blocks off screen to speed things up. </small>
</label>
</div>
<div class="mb-4">
<label class="ml-1">
<span class="text-sm">Brush Histroy Limit</span>
<vue-slider class="mt-10" v-model="options.brushLimit" @dragend="updateOptions" :min="1" :max="maxBrushHistory"></vue-slider>
</label>
</div>
<div class="mb-4">
<label class="ml-1">
<span class="text-sm">Undo/Redo Histroy Limit</span>
<vue-slider class="mt-10" v-model="options.undoLimit" @dragend="updateOptions" :min="1" :max="maxUndoHistory"></vue-slider>
</label>
</div>
<div class="mb-4 border-t-2">
<label class="ml-1">
<span class="text-lg">Reset ASCIIBIRD state</span><br />
<small>This will clear all data and start asciibird from a fresh state.</small><br />
<div class="mt-1 p-2 bg-red-300 rounded-md cursor-pointer" @click="clearCache()">Clear and Reset ASCIIBIRD</div>
</label>
</div>
<vue-slider
class="mt-10"
v-model="options.fps"
@dragend="updateOptions"
:min="1"
:max="200"
></vue-slider>
</label>
</div>
<div class="mb-4">
<label class="ml-1">
<span class="text-lg">Render Offscreen Blocks</span><br />
<t-checkbox
class="form-checkbox m-1"
name="renderOffScreen"
v-model="options.renderOffScreen"
@change="updateOptions"
/>
<small
>ASCIIBIRD will avoid rendering blocks off screen to speed things
up.
</small>
</label>
</div>
<div class="mb-4">
<label class="ml-1">
<span class="text-sm">Brush Histroy Limit</span>
<vue-slider
class="mt-10"
v-model="options.brushLimit"
@dragend="updateOptions"
:min="1"
:max="maxBrushHistory"
></vue-slider>
</label>
</div>
<div class="mb-4">
<label class="ml-1">
<span class="text-sm">Undo/Redo Histroy Limit</span>
<vue-slider
class="mt-10"
v-model="options.undoLimit"
@dragend="updateOptions"
:min="1"
:max="maxUndoHistory"
></vue-slider>
</label>
</div>
<div class="mb-4 border-t-2">
<label class="ml-1">
<span class="text-lg">Reset ASCIIBIRD state</span><br />
<small
>This will clear all data and start asciibird from a fresh
state.</small
><br />
<div
class="mt-1 p-2 bg-red-300 rounded-md cursor-pointer"
@click="clearCache()"
>
Clear and Reset ASCIIBIRD
</div>
</label>
</div>
</div>
</template>
<template v-slot:footer>
<div
class="flex justify-between"
@click="$store.commit('closeModal', 'options')"
>
<t-button
type="button"
class="p-2"
>
Cancel
</t-button>
<t-button
type="button"
class="p-2"
>
Ok
</t-button>
<t-button type="button" class="p-2"> Cancel </t-button>
<t-button type="button" class="p-2"> Ok </t-button>
</div>
</template>
</t-modal>
</template>
<script>
import vueSlider from 'vue-slider-component'
import { maxBrushHistory,
maxUndoHistory,
tabLimit } from './../../ascii.js'
import vueSlider from "vue-slider-component";
import { maxBrushHistory, maxUndoHistory, tabLimit } from "./../../ascii.js";
export default {
name: "Options",
@ -101,29 +105,12 @@ export default {
created() {},
mounted() {
if (this.showOptionsModal) {
this.open()
this.open();
} else {
this.close()
this.close();
}
},
data: () => ({
// options: {
// defaultBg: 1,
// defaultFg: 0,
// renderOffScreen: true,
// undoLimit: 50,
// tabLimit: 12,
// fps: 50,
// },
// forms: {
// fps: this.options.fps,
// renderOffScreen: true,
// undoLimit: this.options.undoLimit,
// tabLimit: this.options.tabLimit
// },
}),
},
data: () => ({}),
computed: {
showOptionsModal() {
return this.$store.getters.modalState.options;
@ -151,12 +138,6 @@ export default {
this.close();
}
},
// options:{
// handler: function(val, old) {
// this.$store.commit(updateOptions, val)
// },
// deep: true
// }
},
methods: {
open() {
@ -167,11 +148,11 @@ export default {
},
clearCache() {
localStorage.clear();
window.location.reload()
window.location.reload();
},
updateOptions() {
this.$store.commit("updateOptions", { ...this.options})
}
this.$store.commit("updateOptions", { ...this.options });
},
},
};
</script>

View File

@ -7,18 +7,9 @@
@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">
@ -49,11 +40,11 @@ export default {
created() {},
mounted() {
if (this.showPasteAscii) {
this.open()
this.open();
} else {
this.close()
this.close();
}
},
},
data: () => ({
pasteContent: "",
title: "clipboard.txt",

View File

@ -1,7 +1,9 @@
<template>
<div>
<t-card class="overflow-x-scroll h-full">
<div :style="`height: ${blocksWidthHeight.h}px;width: ${blocksWidthHeight.w}px;`">
<div
:style="`height: ${blocksWidthHeight.h}px;width: ${blocksWidthHeight.w}px;`"
>
<canvas
:ref="canvasName"
:id="canvasName"
@ -9,25 +11,24 @@
:width="blocksWidthHeight.w"
:height="blocksWidthHeight.h"
@mouseup.right="openContextMenu"
@contextmenu.prevent
/>
</div>
<context-menu :ref="`block-menu-${hash}`" class="z-50" >
<ul>
<li @click="canvasToPng()" class="ab-context-menu-item">
Save as PNG
</li>
<li @click="startExport('clipboard')" class="ab-context-menu-item">
Export Brush to mIRC Clipboard
</li>
<li @click="startExport('file')" class="ab-context-menu-item">
Export Brush to mIRC File
</li>
<li @click="saveToLibrary()" class="ab-context-menu-item">
Save to Library
</li>
</ul>
<context-menu :ref="`block-menu-${hash}`" class="z-50">
<ul>
<li @click="canvasToPng()" class="ab-context-menu-item">
Save as PNG
</li>
<li @click="startExport('clipboard')" class="ab-context-menu-item">
Export Brush to mIRC Clipboard
</li>
<li @click="startExport('file')" class="ab-context-menu-item">
Export Brush to mIRC File
</li>
<li @click="saveToLibrary()" class="ab-context-menu-item">
Save to Library
</li>
</ul>
</context-menu>
</t-card>
</div>
@ -35,18 +36,25 @@
<script>
import { mircColours99, blockWidth, blockHeight, cyrb53, getBlocksWidth, filterNullBlocks,
import {
mircColours99,
blockWidth,
blockHeight,
cyrb53,
getBlocksWidth,
filterNullBlocks,
canvasToPng,
exportMirc,
downloadFile } from "../../ascii";
downloadFile,
} from "../../ascii";
import ContextMenu from "./ContextMenu.vue";
export default {
name: "BrushCanvas",
created() {
window.addEventListener('load', () => {
// Fixes the font on load issue
this.delayRedrawCanvas();
})
window.addEventListener("load", () => {
// Fixes the font on load issue
this.delayRedrawCanvas();
});
},
mounted() {
this.ctx = this.$refs[this.canvasName].getContext("2d");
@ -75,7 +83,7 @@ export default {
return blockHeight * this.blockSizeMultiplier;
},
blockSizeMultiplier() {
return this.$store.getters.blockSizeMultiplier
return this.$store.getters.blockSizeMultiplier;
},
currentAscii() {
return this.$store.getters.currentAscii;
@ -129,9 +137,9 @@ export default {
},
blocksWidthHeight() {
return {
w: getBlocksWidth(this.getBlocks) * this.blockWidth,
h: this.getBlocks.length * this.blockHeight
}
w: getBlocksWidth(this.getBlocks) * this.blockWidth,
h: this.getBlocks.length * this.blockHeight,
};
},
mircColours() {
return mircColours99;
@ -200,7 +208,11 @@ export default {
default:
case "file":
downloadFile(ascii.output.join(""), `brush-${this.hash}.txt`, "text/plain");
downloadFile(
ascii.output.join(""),
`brush-${this.hash}.txt`,
"text/plain"
);
this.$refs[`block-menu-${this.hash}`].close();
break;
}
@ -208,19 +220,19 @@ export default {
saveToLibrary() {
this.$store.commit("pushBrushLibrary", this.getBlocks);
this.$toasted.show(`Saved brush to Library`, {
type: "success",
});
this.$refs[`block-menu-${this.hash}`].close();
type: "success",
});
this.$refs[`block-menu-${this.hash}`].close();
},
canvasToPng() {
canvasToPng(this.canvasRef, `brush-${this.hash}.png`)
canvasToPng(this.canvasRef, `brush-${this.hash}.png`);
this.$refs[`block-menu-${this.hash}`].close();
},
getBlocksWidth(blocks) {
return getBlocksWidth(blocks)
return getBlocksWidth(blocks);
},
filterNullBlocks(blocks) {
return filterNullBlocks(blocks)
return filterNullBlocks(blocks);
},
openContextMenu(e) {
e.preventDefault();
@ -246,7 +258,7 @@ export default {
// Get middle block
if (this.getBlocks) {
let blocksWidth = this.getBlocksWidth(this.getBlocks)
let blocksWidth = this.getBlocksWidth(this.getBlocks);
for (y = 0; y < this.getBlocks.length; y++) {
for (x = 0; x < blocksWidth; x++) {
if (this.getBlocks[y] && this.getBlocks[y][x]) {
@ -286,12 +298,12 @@ export default {
if (this.redraw) {
this.redraw = false;
var _this = this;
setTimeout(function(){
setTimeout(function () {
requestAnimationFrame(() => {
_this.drawPreview();
_this.redraw = true;
});
}, 1000/this.options.fps)
}, 1000 / this.options.fps);
}
},
},

View File

@ -23,7 +23,7 @@
name="width"
v-model="brushSizeWidthInput"
min="1"
:max="maxBrushSize"
:max="maxBrushSize"
@focus="isInputtingBrushSize = true"
@blur="isInputtingBrushSize = false"
/>
@ -35,7 +35,7 @@
name="height"
v-model="brushSizeHeightInput"
min="1"
:max="maxBrushSize"
:max="maxBrushSize"
@focus="isInputtingBrushSize = true"
@blur="isInputtingBrushSize = false"
/>
@ -43,69 +43,10 @@
</div>
<div class="w-full">
<t-select :options="brushOptions" v-model="brushSizeTypeInput" />
<!-- <label class="block">
<t-radio
name="options"
value="square"
checked
v-model="brushSizeTypeInput"
/>
<span class="text-sm">Square</span>
</label>
<label class="block">
<t-radio
name="options"
value="circle"
v-model="brushSizeTypeInput"
/>
<span class="text-sm">Circle</span>
</label>
<label class="block">
<t-radio
name="options"
value="cross"
v-model="brushSizeTypeInput"
/>
<span class="text-sm">Cross</span>
</label>
<label class="block">
<t-radio
name="options"
value="grid"
v-model="brushSizeTypeInput"
/>
<span class="text-sm">Grid</span>
</label>
<label class="block">
<t-radio
name="options"
value="inverted-grid"
v-model="brushSizeTypeInput"
/>
<span class="text-sm">Inverted Grid</span>
</label>
<label class="block">
<t-radio
name="options"
value="lines"
v-model="brushSizeTypeInput"
/>
<span class="text-sm">Lines</span>
</label> -->
<t-select :options="brushOptions" v-model="brushSizeTypeInput" />
</div>
<div
@mouseenter="canDrag = false"
@mouseleave="canDrag = true"
>
<div @mouseenter="canDrag = false" @mouseleave="canDrag = true">
<MainBrushCanvas />
</div>
</t-card>
@ -135,7 +76,7 @@ export default {
this.panel.w = this.brushPreviewState.w;
this.panel.h = this.brushPreviewState.h;
},
props: ['yOffset'],
props: ["yOffset"],
data: () => ({
canDrag: true,
blocks: [],
@ -154,14 +95,14 @@ export default {
computed: {
brushOptions() {
return [
'Square',
'Circle',
'Cross',
'Grid',
'Inverted Grid',
'H lines',
'V lines',
]
"Square",
"Circle",
"Cross",
"Grid",
"Inverted Grid",
"H lines",
"V lines",
];
},
blockWidth() {
return blockWidth * this.blockSizeMultiplier;
@ -216,17 +157,17 @@ export default {
},
updateBrush() {
return this.toolbarState.updateBrush;
},
},
middleY() {
return Math.floor(this.brushSizeHeight / 2);
},
middleX() {
return Math.floor(this.brushSizeWidth / 2);
}
},
},
watch: {
isInputtingBrushSize(val) {
this.$emit("inputtingbrush", val)
this.$emit("inputtingbrush", val);
},
brushSizeWidth() {
this.brushSizeWidthInput = this.brushSizeWidth;
@ -286,8 +227,10 @@ export default {
this.$store.commit("pushBrushHistory", this.brushBlocks);
},
yOffset(val) {
this.$refs.previewpaneldrag.top = Number.parseInt(this.brushPreviewState.y+val)
}
this.$refs.previewpaneldrag.top = Number.parseInt(
this.brushPreviewState.y + val
);
},
},
methods: {
updateBrushSize() {
@ -318,7 +261,7 @@ export default {
for (y = 0; y < brushHeight; y++) {
this.blocks[y] = [];
for (x = 0; x < brushWidth; x++) {
switch (this.brushSizeType.toLowerCase() ) {
switch (this.brushSizeType.toLowerCase()) {
case "cross":
// If we are 1x1 force fill 1 block, to avoid an empty 1x1
if (x === 0 && y === 0) {
@ -329,11 +272,10 @@ export default {
this.blocks[y][x] = { ...emptyBlock };
if (this.blocks[y] && this.blocks[y][x]) {
if (x % 2 === 0 && y % 2 === 0) {
this.blocks[y][x] = { ...block };
}
}
if (x % 2 === 1 && y % 2 === 1) {
this.blocks[y][x] = { ...block };
}
@ -353,7 +295,6 @@ export default {
}
break;
case "grid":
if (x === 0 && y === 0) {
this.blocks[y][x] = { ...block };
@ -370,7 +311,7 @@ export default {
if (y % 2 === 0) {
targetX -= 1;
}
}
if (this.blocks[y] && this.blocks[y][targetX]) {
if (y % 2 === 0 && x % 2 !== 0) {
@ -398,11 +339,13 @@ export default {
if (y % 2 === 0) {
targetX -= 1;
}
}
if (this.blocks[y] && this.blocks[y][targetX]) {
if (y % 2 === 0) {
if (targetX % 2 === 0) { this.blocks[y][targetX] = { ...block }; }
if (targetX % 2 === 0) {
this.blocks[y][targetX] = { ...block };
}
} else {
this.blocks[y][targetX] = { ...emptyBlock };
}
@ -426,11 +369,13 @@ export default {
if (screenY % 2 === 0) {
screenY -= 1;
}
}
if (this.blocks[targetY] && this.blocks[targetY][x]) {
if (x % 2 === 0) {
if (x % 2 === 0) { this.blocks[targetY][x] = { ...block }; }
if (x % 2 === 0) {
this.blocks[targetY][x] = { ...block };
}
} else {
this.blocks[targetY][x] = { ...emptyBlock };
}
@ -444,31 +389,34 @@ export default {
break;
case "circle":
this.blocks[y][x] = { ... emptyBlock };
this.blocks[y][x] = { ...emptyBlock };
break;
}
}
}
switch(this.brushSizeType.toLowerCase()) {
case "circle":
let x1 = 0;
let y1 = 0;
switch (this.brushSizeType.toLowerCase()) {
case "circle":
let x1 = 0;
let y1 = 0;
for (let angle = 0; angle <= 360; angle += 1) {
let radian = angle * (Math.PI*2/360);
x1 = Math.round( (brushWidth - 1) * ( (Math.cos(radian) + 1.0) / 2.0));
y1 = Math.round( (brushHeight - 1) * ((Math.sin(radian) + 1.0) / 2.0));
for (let angle = 0; angle <= 360; angle += 1) {
let radian = angle * ((Math.PI * 2) / 360);
x1 = Math.round(
(brushWidth - 1) * ((Math.cos(radian) + 1.0) / 2.0)
);
y1 = Math.round(
(brushHeight - 1) * ((Math.sin(radian) + 1.0) / 2.0)
);
if (this.blocks[y1] && this.blocks[y1][x1]) {
this.blocks[y1][x1] = { ...block };
}
}
if (this.blocks[y1] && this.blocks[y1][x1]) {
this.blocks[y1][x1] = { ...block };
}
}
this.fill();
break;
}
this.fill();
break;
}
this.$store.commit("brushBlocks", this.blocks);
},
@ -476,10 +424,7 @@ export default {
const current = {};
current.bg = null;
this.fillTool(
this.middleY,
this.middleX,
);
this.fillTool(this.middleY, this.middleX);
},
fillTool(y, x) {
if (y >= this.brushSizeHeight) {

View File

@ -1,8 +1,6 @@
<template>
<vue-draggable-resizable :x="100" :y="100" :w="1100" :h="350">
<t-card
class="w-full h-full"
>
<t-card class="w-full h-full">
<t-button
type="button"
v-for="(char, keyChar) in charCodes"

View File

@ -1,16 +1,8 @@
<template>
<vue-draggable-resizable
:x="100"
:y="100"
:w="400"
:h="278"
>
<vue-draggable-resizable :x="100" :y="100" :w="400" :h="278">
<t-card class="w-full h-full">
<span
v-for="(value, keyColours) in mircColours"
:key="keyColours"
>
<hr v-if="keyColours === 16">
<span v-for="(value, keyColours) in mircColours" :key="keyColours">
<hr v-if="keyColours === 16" />
<t-button
type="button"
@ -24,10 +16,10 @@
</template>
<script>
import { mircColours99 } from '../../ascii';
import { mircColours99 } from "../../ascii";
export default {
name: 'ColourPicker',
name: "ColourPicker",
created() {},
computed: {
mircColours() {
@ -39,16 +31,16 @@ export default {
},
methods: {
close() {
this.$store.commit('changeIsUpdatingFg', false);
this.$store.commit('changeIsUpdatingBg', false);
this.$store.commit("changeIsUpdatingFg", false);
this.$store.commit("changeIsUpdatingBg", false);
},
onColourChange(colour) {
if (this.toolbarState.isChoosingFg) {
this.$store.commit('changeColourFg', colour);
this.$store.commit("changeColourFg", colour);
}
if (this.toolbarState.isChoosingBg) {
this.$store.commit('changeColourBg', colour);
this.$store.commit("changeColourBg", colour);
}
},
},

View File

@ -1,4 +1,4 @@
<template @contextmenu.prevent>
<template>
<div
class="context-menu"
v-show="show"
@ -6,16 +6,15 @@
ref="context"
tabindex="0"
@blur="close"
@contextmenu.prevent
>
<slot />
</div>
</template>
<script>
import Vue from 'vue';
import Vue from "vue";
export default {
name: 'ContextMenu',
name: "ContextMenu",
props: {
display: Boolean, // prop detect if we should show context menu
},

View File

@ -3,10 +3,7 @@
</template>
<script>
import {
toolbarIcons,
maxBrushSize,
} from "../../ascii";
import { toolbarIcons, maxBrushSize } from "../../ascii";
export default {
name: "KeyboardShortcuts",
@ -39,7 +36,6 @@ export default {
event.altKey &&
_this.haveOpenTabs
) {
_this.$store.commit("changeTool", Number.parseInt(event.key - 1));
_this.$emit("updatecanvas");
return;
@ -52,7 +48,6 @@ export default {
(_this.toolbarState.isChoosingFg || _this.toolbarState.isChoosingBg) &&
_this.haveOpenTabs
) {
if (_this.toolbarState.isChoosingFg) {
_this.$store.commit("changeColourFg", Number.parseInt(event.key));
return;

View File

@ -50,7 +50,7 @@
<li></li>
</ul>
<context-menu ref="layers-menu" class="z-50" @contextmenu.prevent>
<context-menu ref="layers-menu" class="z-50">
<ul>
<li @click="addLayer()" class="ab-context-menu-item">
Add New Layer
@ -82,20 +82,14 @@
<ul
class="divide-y-2 divide-gray-100 reverseorder"
@mouseup.right="openContextMenu"
@contextmenu.prevent
>
<li
:class="`p-1 ${selectedLayerClass(key)}`"
v-for="(layer, key) in currentAsciiLayers"
:key="key"
@click.right="changeLayer(key)"
>
<div
class="flex"
@mouseup.right="openContextMenu"
@contextmenu.prevent
>
<div class="flex" @mouseup.right="openContextMenu">
<div class="w-12" @click="changeLayer(key)">
<t-button
type="button"
@ -172,16 +166,19 @@ export default {
},
selectedLayer() {
let selectedLayer = this.$store.getters.selectedLayer;
if (this.currentAsciiLayers[selectedLayer] === undefined) {
while (this.currentAsciiLayers[selectedLayer] === undefined && selectedLayer >= 0) {
while (
this.currentAsciiLayers[selectedLayer] === undefined &&
selectedLayer >= 0
) {
selectedLayer--;
}
this.$store.commit("changeLayer", selectedLayer);
}
return selectedLayer
return selectedLayer;
},
currentLayer() {
return this.currentAsciiLayers[this.selectedLayer];

View File

@ -15,14 +15,13 @@
@mousemove="canvasMouseMove"
@mousedown.left="processClick"
@mouseup.left="canTool = false"
@contextmenu.prevent
:width="blocksWidthHeight.w"
:height="blocksWidthHeight.h"
@mouseenter="disableToolbarMoving"
@mouseleave="enableToolbarMoving"
/>
<context-menu ref="main-brush-menu" class="z-50" @contextmenu.prevent>
<context-menu ref="main-brush-menu" class="z-50">
<ul>
<li @click="canvasToPng()" class="ab-context-menu-item">
Save as PNG
@ -56,7 +55,7 @@ import {
canvasToPng,
cyrb53,
exportMirc,
downloadFile
downloadFile,
} from "../../ascii";
export default {
@ -170,7 +169,7 @@ export default {
},
hash() {
return cyrb53(JSON.stringify(this.brushBlocks));
}
},
},
watch: {
brushBlocks() {
@ -242,7 +241,11 @@ export default {
default:
case "file":
downloadFile(ascii.output.join(""), `brush-${this.hash}.txt`, "text/plain");
downloadFile(
ascii.output.join(""),
`brush-${this.hash}.txt`,
"text/plain"
);
this.$refs[`main-brush-menu`].close();
break;
}
@ -250,12 +253,12 @@ export default {
saveToLibrary() {
this.$store.commit("pushBrushLibrary", this.brushBlocks);
this.$toasted.show(`Saved brush to Library`, {
type: "success",
});
type: "success",
});
this.$refs[`main-brush-menu`].close();
},
canvasToPng() {
canvasToPng(this.canvasRef, `brush-${this.hash}.png`)
canvasToPng(this.canvasRef, `brush-${this.hash}.png`);
this.$refs[`main-brush-menu`].close();
},
processClick(e) {
@ -427,7 +430,7 @@ export default {
enableToolbarMoving() {
// Save the blocks when the mouse leaves the canvas area
// To avoid one block history changes
if ( (this.isErasing || this.isBrushing) && this.hasChanged) {
if ((this.isErasing || this.isBrushing) && this.hasChanged) {
this.$store.commit("brushBlocks", this.brushBlocks);
this.$store.commit("changeToolBarDraggable", true);
this.hasChanged = false;

View File

@ -1,26 +0,0 @@
import {
library,
} from '@fortawesome/fontawesome-svg-core';
import {
faMousePointer,
faFont,
faFillDrip,
faPaintBrush,
faEyeDropper,
faEraser,
faSync,
faSave,
faTrash,
faFill,
faChevronCircleUp,
faChevronCircleDown,
faEye,
faEyeSlash
} from '@fortawesome/free-solid-svg-icons';
import {
faSquare,
} from '@fortawesome/free-regular-svg-icons';
library.add(faMousePointer, faSquare, faFont, faFillDrip, faPaintBrush, faEyeDropper, faEraser,
faSync, faSave, faTrash, faFill, faChevronCircleUp, faChevronCircleDown, faEye, faEyeSlash);

View File

@ -1,13 +1,15 @@
import Vue from 'vue';
import './style.css';
import VueTailwind from 'vue-tailwind';
import VueDraggableResizable from 'vue-draggable-resizable';
import VueClipboard from 'vue-clipboard2';
import { tailwindCss } from './tailwindSettings';
import {
tailwindCss
} from './tailwindSettings';
import 'vue-draggable-resizable/dist/VueDraggableResizable.css';
import store from './store';
import Dashboard from './Dashboard.vue';
import Toasted from 'vue-toasted';
import './style.scss';
Vue.config.productionTip = false;
Vue.use(VueTailwind, tailwindCss);

View File

@ -100,7 +100,6 @@ body {
--bar-sub-menu-border-radius: 6px;
}
/* @layer base { */
.bar {
@apply bg-gray-500;
}
@ -137,4 +136,3 @@ body {
.ab-context-menu-item {
@apply ml-1 hover:bg-gray-800 hover:text-white;
}
/* } */

View File

@ -219,4 +219,4 @@ export const tailwindCss = {
}
}
}
}
}

View File

@ -64,7 +64,6 @@
@mousedown.left="canvasMouseDown"
@mouseup.left="canvasMouseUp"
@mouseup.right="openContextMenu"
@contextmenu.prevent
@touchmove="canvasMouseMove"
@touchend="canvasMouseDown"
@touchstart="canvasMouseUp"
@ -496,7 +495,7 @@ export default {
// Layers undo
currentAsciiLayers(val, old) {
this.delayRedrawCanvas(true);
}
},
},
methods: {
startExport(type) {
@ -1025,7 +1024,6 @@ export default {
}
}
}
}
this.ctx.restore();
@ -1049,7 +1047,7 @@ export default {
this.$refs.canvasdrag.width = width;
this.$refs.canvasdrag.height = height;
this.$toasted.show(`${canvasBlockWidth} x ${canvasBlockHeight}`)
this.$toasted.show(`${canvasBlockWidth} x ${canvasBlockHeight}`);
},
onCavasDragStop(x, y) {
// Update left and top in panel
@ -1768,8 +1766,6 @@ export default {
} else if (this.isErasing) {
this.drawBrushBlocks(brushX, brushY, brushBlock, null, true);
}
}
}
}