updates, better options modal

This commit is contained in:
Hugh Bord 2021-11-06 10:59:17 +10:00
parent e9307b48bd
commit 4fc0c99977
10 changed files with 213 additions and 62 deletions

View File

@ -64,8 +64,8 @@ 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. Refreshing the page seems to fix most strange things.
* Redo ctrl Y is COOKED (not working)
* Keyboard shortcuts can be pressed at the same time which makes bugs for undo and redo if you aren't careful!
* Some BS on the layers rename stops shit working sometimes ?!!?!?!?!
* Circle brush (works okay for odd width and height numbers)
* Importer could be re-written with regex
* Drag ascii canvas then right click and it gets stuck
@ -73,38 +73,17 @@ ASCIIBIRD is mostly usable. There are some bugs however to note at the moment. R
* Having more than a few layers depending on ascii size will slow things down, until the `fillNullBlocks` is refactored.
* CHUNKED DIFF ENGINE
## Focusing on Now / Roadmap
* Modals to add
* Asciibird options / Options modal from skgs PR
* Arrow keys and space to use brush, eraser,
* More Context Menus (right click menu)
* Brushes Canvas right click
* ASCII right click
* Improve the char window to have a close button and border/bg
* Review encodings check on file import - UTF8 vs Latin something
* Revise the blocks system to only store what's changed
## User Feedback Requests
* Move brush with keys and space to paint
* Improve the character panel, group chars
# Fixed / Finished
* Image overlay for trace mode
* Cannot manually input brush sizes because keyboard shortcuts is stealing focus
* If you open a modal and refresh the page it's stuck as opened inside the state, and you cannot open it again
* Toolbars and panels follow when scrolling down
* Experimental code to only render blocks visible on screen
* Rename Layers
* Some work around layers and transparent blocks, skip drawing transparent bg block on top layers. Or get bg from lowest layer if bg is null on higher layers.
* The code that hides blocks off screen wont work if you scroll down, however it will work if you drag the canvas upward
* Exporter will default transparent bg to black by default, which wont for some asciis
* Review escape and enter keys on dialogs and modals
* Select cannot select entire ASCII, is off by one at the end
* Fill tool use fg or char as bounds
* z indexing for toolbars and stuff is ANNOYING
* Make grid faster (gonna do that later, maybe never)
# Keyboard Shortcuts
## ASCII Editing

View File

@ -23,6 +23,7 @@
"vue": "^2.6.11",
"vue-clipboard2": "^0.3.1",
"vue-draggable-resizable": "^2.3.0",
"vue-slider-component": "^2.8.16",
"vue-tailwind": "^2.0.0",
"vue-toasted": "^1.1.28",
"vuex": "^3.4.0",

View File

@ -13,6 +13,9 @@
:is-showing-dialog="isShowingDialog"
@updatecanvas="updatecanvas"
:is-inputting-brush-size="this.isInputtingBrushSize"
:canvas-x="canvasX"
:canvas-y="canvasY"
@triggerbrush="triggerbrush"
/>
<t-dialog
@ -142,6 +145,7 @@
:update-canvas="updateCanvas"
@selecting="updateSelecting"
:y-offset="scrollOffset"
:brush="drawBrush"
/>
@ -165,7 +169,6 @@
<LayersLibrary :y-offset="scrollOffset" />
<CharPicker
v-if="toolbarState.isChoosingChar"
class="z-50"
@ -279,6 +282,7 @@ export default {
toolbarString: "top: 0px;",
lastPostURL: "",
isShowingDialog: false,
drawBrush: false,
}),
computed: {
splashAscii() {
@ -340,6 +344,9 @@ export default {
// },
},
methods: {
triggerbrush() {
this.drawBrush = ! this.drawBrush
},
inputtingbrush(val) {
this.isInputtingBrushSize = val;
},

View File

@ -212,8 +212,9 @@ export const blockWidth = 8;
export const blockHeight = 15;
// Limits for undo and brush histories
export const maxBrushHistory = 50;
export const maxUndoHistory = 50;
export const maxBrushHistory = 200;
export const maxUndoHistory = 200;
export const tabLimit = 20;
export const parseMircAscii = async (content, title) => {
const MIRC_MAX_COLOURS = mircColours99.length;

View File

@ -10,17 +10,55 @@
<template v-slot:default>
<div>
<div class="mt-6 lg:mt-0 rounded shadow bg-white">
<ul>
<li> Redraw canvas speed? </li>
<li>Render blocks off screen</li>
<div class="mb-4">
<label class="ml-1">
<span class="text-sm">FPS</span>
<vue-slider v-model="options.fps" @dragend="updateOptions" :min="1" :max="200"></vue-slider>
</label>
</div>
<li>Undo history?</li>
<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="mt-3 p-2 bg-red-300 rounded-md cursor-pointer" @click="clearCache()">Clear and Reset ASCIIBIRD</div>
</ul>
<div class="mb-4">
<label class="ml-1">
<span class="text-sm">Brush Histroy Limit</span>
<vue-slider 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 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>
@ -41,7 +79,6 @@
<t-button
type="button"
class="p-2"
@click="initiateNewAscii()"
>
Ok
</t-button>
@ -51,9 +88,16 @@
</template>
<script>
import vueSlider from 'vue-slider-component'
import { maxBrushHistory,
maxUndoHistory,
tabLimit } from './../../ascii.js'
export default {
name: "Options",
components: {
vueSlider,
},
created() {},
mounted() {
if (this.showOptionsModal) {
@ -63,18 +107,39 @@ export default {
}
},
data: () => ({
forms: {
createAscii: {
width: 80,
height: 30,
title: "ascii",
},
},
// 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
// },
}),
computed: {
showOptionsModal() {
return this.$store.getters.modalState.options;
},
options() {
return this.$store.getters.options;
},
maxBrushHistory() {
return maxBrushHistory;
},
maxUndoHistory() {
return maxUndoHistory;
},
tabLimit() {
return tabLimit;
},
},
watch: {
showOptionsModal(val) {
@ -86,24 +151,27 @@ export default {
this.close();
}
},
// options:{
// handler: function(val, old) {
// this.$store.commit(updateOptions, val)
// },
// deep: true
// }
},
methods: {
open() {
this.$modal.show("options-modal");
this.forms.createAscii.title = `New ASCII ${
this.$store.getters.asciibirdMeta.length + 1
}`;
},
close() {
this.$modal.hide("options-modal");
this.forms.createAscii.width = 80;
this.forms.createAscii.height = 30;
this.forms.createAscii.title = "New ASCII";
},
clearCache() {
localStorage.clear();
window.location.reload()
},
updateOptions() {
this.$store.commit("updateOptions", { ...this.options})
}
},
};
</script>

View File

@ -19,14 +19,20 @@ export default {
window.removeEventListener("keydown", this.keyListener.bind(this));
},
created() {
console.log(this.canvasX);
this.keyListener = function (e) {
// Stop blocking input when modals are open
// Whatever this char "'\0'" is it'd occur even without pressing any keys
// This fixes it
if (e.key === "\0" || this.isInputtingBrushSize || this.isKeyboardDisabled || this.isShowingDialog || this.isModalOpen) {
if (
e.key === "\0" ||
this.isInputtingBrushSize ||
this.isKeyboardDisabled ||
this.isShowingDialog ||
this.isModalOpen
) {
if (e.key === "Enter" && this.isShowingDialog) {
this.$dialog.hide('dialog-posthttp');
this.$dialog.hide("dialog-posthttp");
return;
}
@ -68,7 +74,10 @@ export default {
const altKey = e.altKey;
// Used for text typing
if (this.isTextEditing && this.haveOpenTabs) {
if (
(this.isTextEditing) &&
this.haveOpenTabs
) {
this.canvasKeyDown(e.key);
return;
}
@ -399,8 +408,20 @@ export default {
data: () => ({
isPressed: false,
}),
props: ["selectedBlocks", "textEditing", "selecting", "isInputtingBrushSize", "showingPostUrl", "isShowingDialog"],
props: [
"selectedBlocks",
"textEditing",
"selecting",
"isInputtingBrushSize",
"showingPostUrl",
"isShowingDialog",
"canvasX",
"canvasY",
],
computed: {
canvasXy() {
return {x: this.canvasX, y: this.canvasY};
},
isModalOpen() {
return this.$store.getters.isModalOpen;
},
@ -449,6 +470,9 @@ export default {
isBrushing() {
return this.currentTool.name === "brush";
},
isEraser() {
return this.currentTool.name === "eraser";
},
isSelected() {
return (
this.selecting.startX >= 0 &&
@ -504,7 +528,7 @@ export default {
},
isKeyboardDisabled() {
return this.$store.getters.isKeyboardDisabled;
}
},
},
methods: {
undo() {
@ -514,6 +538,43 @@ export default {
this.$store.commit("redoBlocks");
},
canvasKeyDown(char) {
// if (this.isBrushing || this.isEraser) {
// switch (char) {
// // Move the text indicator around with the arrow keys
// case "ArrowUp":
// if (this.currentAsciiLayerBlocks[this.canvasXy.y - 1][this.canvasXy.x]) {
// this.canvasXy.y -= 1;
// }
// break;
// case "ArrowDown":
// if (this.currentAsciiLayerBlocks[this.canvasXy.y + 1][this.canvasXy.x]) {
// this.canvasXy.y += 1;
// }
// break;
// case "ArrowLeft":
// if (this.currentAsciiLayerBlocks[this.canvasXy.y][this.canvasXy.x - 1]) {
// this.canvasXy.x -= 1;
// }
// break;
// case "ArrowRight":
// if (this.currentAsciiLayerBlocks[this.canvasXy.y][this.canvasXy.x + 1]) {
// this.canvasXy.x += 1;
// }
// break;
// case " ":
// this.$emit("triggerbrush");
// return;
// break;
// }
// this.$emit("arrowkeys", this.canvasXy);
// }
if (this.isTextEditing) {
if (
this.currentAsciiLayerBlocks[this.textEditing.startY] &&

View File

@ -9,7 +9,6 @@ import store from './store';
import Dashboard from './Dashboard.vue';
import Toasted from 'vue-toasted';
Vue.config.productionTip = false;
import {

View File

@ -9,8 +9,6 @@ import {
getBlocksWidth,
create2DArray,
emptyBlock,
maxBrushHistory,
maxUndoHistory,
mergeLayers
} from "../ascii";
@ -37,6 +35,7 @@ export default new Vuex.Store({
defaultFg: 0,
renderOffScreen: true,
undoLimit: 50,
brushLimit: 50,
tabLimit: 12,
fps: 50,
},
@ -111,6 +110,9 @@ export default new Vuex.Store({
changeState(state, payload) {
Object.assign(state, payload);
},
updateOptions(state, payload) {
state.options = { ... payload};
},
changeTab(state, payload) {
state.tab = payload;
document.title = `asciibird - ${state.asciibirdMeta[payload].title}`;
@ -202,7 +204,7 @@ export default new Vuex.Store({
state.toolbarState.mirrorY = payload.y;
},
updateAsciiBlocks(state, payload, skipUndo = false) {
if (state.asciibirdMeta[state.tab].history.length >= maxUndoHistory) {
if (state.asciibirdMeta[state.tab].history.length >= state.options.undoLimit) {
state.asciibirdMeta[state.tab].history.shift()
}
@ -428,8 +430,7 @@ export default new Vuex.Store({
// Brush Library
pushBrushHistory(state, payload) {
// Check and remove duplicate brushes based on hash value
console.log(state.brushHistory.length, maxBrushHistory)
if (state.brushHistory.length >= maxBrushHistory) {
if (state.brushHistory.length >= state.options.brushLimit) {
state.brushHistory.pop();
}

View File

@ -113,8 +113,10 @@ export default {
new: [],
old: [],
},
isUsingKeyboard: false,
}),
props: ["updateCanvas", "yOffset"],
props: ["updateCanvas", "yOffset", "canvasxy", "brush"],
computed: {
canvasRef() {
return this.$refs.canvas;
@ -181,6 +183,9 @@ export default {
isBrushing() {
return this.currentTool.name === "brush";
},
isErasing() {
return this.currentTool.name === "eraser";
},
isSelected() {
return (
this.selecting.startX !== null &&
@ -377,6 +382,22 @@ export default {
// }
// },
// canvasxy(val,old) {
// if ((this.isBrushing || this.isErasing) && isUsingKeyboard) {
// this.x = val.x;
// this.y = val.y;
// let e = {offsetX: (this.x), offsetY: (this.y)}
// this.canvasMouseMove(e)
// }
// },
// brush(val, old) {
// console.log({triggerbrush: val})
// if (val !== old) {
// this.canvasMouseDown()
// this.canvasMouseUp()
// }
// }
},
methods: {
warnInvisibleLayer() {
@ -1350,6 +1371,14 @@ export default {
);
},
fillTool(fillBlocks, y, x, current, eraser) {
if (y >= Math.floor(this.canvas.height / blockHeight)) {
return;
}
if (x >= Math.floor(this.canvas.width / blockWidth)) {
return;
}
if (fillBlocks[y] === undefined || fillBlocks[y][x] === undefined) {
return;
}

View File

@ -9466,6 +9466,11 @@ vue-loader@^15.9.2:
vue-hot-reload-api "^2.3.0"
vue-style-loader "^4.1.0"
vue-slider-component@^2.8.16:
version "2.8.16"
resolved "https://registry.yarnpkg.com/vue-slider-component/-/vue-slider-component-2.8.16.tgz#b2036f816ed64fa4fcd6741219b80c5063b4fd60"
integrity sha512-06gDoheKMU8TdqjoofIJaYfXw3uuWOXF2I14d/F5yW/8iOxnoI4Ks9WSXy8RWY+gs62GBE6tQXHDSX/H6IOaAw==
vue-style-loader@^4.1.0, vue-style-loader@^4.1.2:
version "4.1.3"
resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.3.tgz#6d55863a51fa757ab24e89d9371465072aa7bc35"