update
This commit is contained in:
@@ -3,13 +3,12 @@ import { Bound } from "./utils";
|
|||||||
|
|
||||||
export type UITool =
|
export type UITool =
|
||||||
| "track-unit-type"
|
| "track-unit-type"
|
||||||
| "eraser"
|
|
||||||
| "sticking";
|
| "sticking";
|
||||||
|
|
||||||
export class AppStateStore extends Bound {
|
class AppStateStore extends Bound {
|
||||||
selectedTool = ref<UITool>("track-unit-type");
|
selectedTool = ref<UITool>("track-unit-type");
|
||||||
activeTrackUnitType = ref(0);
|
activeTrackUnitType = ref<number | null>(0);
|
||||||
activeStickingType = ref(1);
|
activeStickingType = ref<number | null>(1);
|
||||||
unitMouseStart = ref<string | null>(null);
|
unitMouseStart = ref<string | null>(null);
|
||||||
selectingUnits = ref(false);
|
selectingUnits = ref(false);
|
||||||
deselectingUnits = ref(false);
|
deselectingUnits = ref(false);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const TrackSerialSchema = z.object({
|
|||||||
units: z.object({
|
units: z.object({
|
||||||
isOn: z.array(z.boolean()),
|
isOn: z.array(z.boolean()),
|
||||||
type: z.array(z.number()),
|
type: z.array(z.number()),
|
||||||
stickingType: z.array(z.number()),
|
stickingType: z.array(z.number().nullable()),
|
||||||
}),
|
}),
|
||||||
barCount: z.number(),
|
barCount: z.number(),
|
||||||
loopLength: z.number(),
|
loopLength: z.number(),
|
||||||
@@ -72,7 +72,7 @@ export function deserialise(serial: unknown, manager: BeatManager) {
|
|||||||
export type TrackUnit = {
|
export type TrackUnit = {
|
||||||
on: boolean,
|
on: boolean,
|
||||||
type: number,
|
type: number,
|
||||||
stickingType: number,
|
stickingType: number | null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Track extends EffectScoped {
|
export class Track extends EffectScoped {
|
||||||
@@ -191,7 +191,7 @@ export class Track extends EffectScoped {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
setStickingType(index: number, stickingType: number): void {
|
setStickingType(index: number, stickingType: number | null): void {
|
||||||
const unit = this.getUnitByIndex(index);
|
const unit = this.getUnitByIndex(index);
|
||||||
if (!unit) {
|
if (!unit) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
1
src/assets/svgs/delete.svg
Normal file
1
src/assets/svgs/delete.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-delete"><path d="M21 4H8l-7 8 7 8h13a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2z"></path><line x1="18" y1="9" x2="12" y2="15"></line><line x1="12" y1="9" x2="18" y2="15"></line></svg>
|
||||||
|
After Width: | Height: | Size: 374 B |
@@ -5,18 +5,21 @@
|
|||||||
<div class="toolbox-button paint-button-cont"
|
<div class="toolbox-button paint-button-cont"
|
||||||
:class="{ active: selectedTool === 'track-unit-type' }"
|
:class="{ active: selectedTool === 'track-unit-type' }"
|
||||||
@click="selectedTool = 'track-unit-type'">
|
@click="selectedTool = 'track-unit-type'">
|
||||||
<div
|
<track-unit-box
|
||||||
|
v-if="activeTrackUnitType !== null"
|
||||||
class="paint-button"
|
class="paint-button"
|
||||||
:class="getClasses({ on: true, type: TrackUnitTypeList[activeTrackUnitType]!, stickingType: null })" />
|
:sticking-type="null" :on="true" :type="activeTrackUnitType" />
|
||||||
|
<icon v-else class="paint-button" icon-name="eraser" />
|
||||||
</div>
|
</div>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="details">
|
<div class="details">
|
||||||
<div v-for="(type, i) in TrackUnitTypeList"
|
<div v-for="(type, i) in [...TrackUnitTypeList, null]"
|
||||||
:key="type"
|
:key="type ?? 'eraser'"
|
||||||
class="toolbox-button"
|
class="toolbox-button track-unit-type"
|
||||||
:class="{ active: i === activeTrackUnitType }"
|
:class="{ active: i === activeTrackUnitType || type === null && activeTrackUnitType === null }"
|
||||||
@click="activeTrackUnitType = i; selectedTool = 'track-unit-type'">
|
@click="activeTrackUnitType = type === null ? null : i; selectedTool = 'track-unit-type'">
|
||||||
<div :class="getClasses({ on: true, type, stickingType: null })" />
|
<track-unit-box v-if="type !== null" :sticking-type="null" :on="true" :type="i" />
|
||||||
|
<icon v-else icon-name="eraser" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -24,7 +27,7 @@
|
|||||||
<dropdown>
|
<dropdown>
|
||||||
<icon
|
<icon
|
||||||
class="toolbox-button"
|
class="toolbox-button"
|
||||||
:icon-name="PaintableTrackUnitStickingTypeList[activeStickingType]!"
|
:icon-name="activeStickingType ? (PaintableTrackUnitStickingTypeList[activeStickingType] ?? 'eraser') : 'eraser'"
|
||||||
:class="{ active: selectedTool === 'sticking' }"
|
:class="{ active: selectedTool === 'sticking' }"
|
||||||
@click="selectedTool = 'sticking'" />
|
@click="selectedTool = 'sticking'" />
|
||||||
<template #content>
|
<template #content>
|
||||||
@@ -36,16 +39,15 @@
|
|||||||
@click="activeStickingType = i; selectedTool = 'sticking'">
|
@click="activeStickingType = i; selectedTool = 'sticking'">
|
||||||
<icon :icon-name="StickingTypeIconMap[stickingType]" />
|
<icon :icon-name="StickingTypeIconMap[stickingType]" />
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
class="toolbox-button"
|
||||||
|
:class="{ active: activeStickingType === null }"
|
||||||
|
@click="activeStickingType = null; selectedTool = 'sticking'">
|
||||||
|
<icon icon-name="eraser" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</dropdown>
|
</dropdown>
|
||||||
<dropdown>
|
|
||||||
<icon
|
|
||||||
class="toolbox-button"
|
|
||||||
icon-name="eraser"
|
|
||||||
:class="{ active: selectedTool === 'eraser' }"
|
|
||||||
@click="selectedTool = 'eraser'" />
|
|
||||||
</dropdown>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -56,7 +58,7 @@
|
|||||||
import { StickingTypeIconMap } from "@/ui/TrackUnit/trackUnit";
|
import { StickingTypeIconMap } from "@/ui/TrackUnit/trackUnit";
|
||||||
import Icon from "@/ui/Widgets/Icon/Icon.vue";
|
import Icon from "@/ui/Widgets/Icon/Icon.vue";
|
||||||
import Dropdown from '@/ui/Widgets/Dropdown/Dropdown.vue';
|
import Dropdown from '@/ui/Widgets/Dropdown/Dropdown.vue';
|
||||||
import { getClasses } from "@/ui/TrackUnit/trackUnit";
|
import TrackUnitBox from "@/ui/TrackUnitBox/TrackUnitBox.vue";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
selectedTool,
|
selectedTool,
|
||||||
@@ -86,12 +88,19 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.track-unit-type {
|
||||||
|
margin: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
.toolbox-button {
|
.toolbox-button {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: black;
|
color: black;
|
||||||
|
|
||||||
|
&.eraser {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
&.paint-button-cont {
|
&.paint-button-cont {
|
||||||
padding: 0.25em;
|
|
||||||
background-color: var(--color-ui-bg-dark);
|
background-color: var(--color-ui-bg-dark);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@@ -111,10 +120,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.paint-button {
|
.paint-button {
|
||||||
height: 1.5em;
|
|
||||||
width: 1.5em;
|
|
||||||
background-color: black;
|
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
background-color: var(--color-ui-neutral-dark);
|
background-color: var(--color-ui-neutral-dark);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,9 @@
|
|||||||
|
|
||||||
function toggle(index: number) {
|
function toggle(index: number) {
|
||||||
if (!track.value) return;
|
if (!track.value) return;
|
||||||
track.value.toggleUnit(index);
|
if (selectedTool.value === 'track-unit-type') {
|
||||||
|
track.value.toggleUnit(index);
|
||||||
|
}
|
||||||
if (track.value.getUnitByIndex(index)?.on) {
|
if (track.value.getUnitByIndex(index)?.on) {
|
||||||
applyCurrentToolToTrackUnit(index);
|
applyCurrentToolToTrackUnit(index);
|
||||||
}
|
}
|
||||||
@@ -75,10 +77,7 @@
|
|||||||
track.value?.setStickingType(index, activeStickingType.value);
|
track.value?.setStickingType(index, activeStickingType.value);
|
||||||
break;
|
break;
|
||||||
case "track-unit-type":
|
case "track-unit-type":
|
||||||
track.value?.updateUnit(index, { on: true, type: activeTrackUnitType.value });
|
track.value?.updateUnit(index, { on: activeTrackUnitType.value === null ? false : true, type: activeTrackUnitType.value === null ? undefined : activeTrackUnitType.value });
|
||||||
break;
|
|
||||||
case "eraser":
|
|
||||||
track.value?.setUnitOn(index, false);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :class="classes"
|
<track-unit-box
|
||||||
|
class="track-unit"
|
||||||
|
:sticking-type="stickingType"
|
||||||
|
:type="type"
|
||||||
|
:on="on"
|
||||||
@mousedown="handleMouseDown"
|
@mousedown="handleMouseDown"
|
||||||
@mouseup="handleMouseUp"
|
@mouseup="handleMouseUp"
|
||||||
@mouseover="handleMouseOver"
|
@mouseover="handleMouseOver"
|
||||||
@@ -7,21 +11,16 @@
|
|||||||
@mouseout="handleMouseOut"
|
@mouseout="handleMouseOut"
|
||||||
@touchstart="handleTouchStart"
|
@touchstart="handleTouchStart"
|
||||||
@touchend="handleTouchEnd"
|
@touchend="handleTouchEnd"
|
||||||
@contextmenu.prevent.stop="() => false">
|
@contextmenu.prevent.stop="() => false"/>
|
||||||
<icon v-if="iconName" :icon-name="iconName" />
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { TrackUnitStickingTypeList, TrackUnitTypeList } from "@/Track";
|
|
||||||
import Icon from "@/ui/Widgets/Icon/Icon.vue";
|
|
||||||
import { StickingTypeIconMap, getClasses } from "./trackUnit";
|
|
||||||
import { computed } from "vue";
|
|
||||||
import { useAppStateStore } from "@/AppState";
|
import { useAppStateStore } from "@/AppState";
|
||||||
|
import TrackUnitBox from "@/ui/TrackUnitBox/TrackUnitBox.vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
id: string,
|
id: string,
|
||||||
stickingType: number,
|
stickingType: number | null,
|
||||||
type: number,
|
type: number,
|
||||||
on: boolean,
|
on: boolean,
|
||||||
}>();
|
}>();
|
||||||
@@ -44,22 +43,6 @@
|
|||||||
let mouseHeld = false;
|
let mouseHeld = false;
|
||||||
let movement = 0;
|
let movement = 0;
|
||||||
|
|
||||||
const classes = computed(() => getClasses({
|
|
||||||
on: props.on,
|
|
||||||
stickingType: TrackUnitStickingTypeList[props.stickingType] ?? null,
|
|
||||||
type: TrackUnitTypeList[props.type] ?? 'Normal',
|
|
||||||
highlightable: true,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const iconName = computed(() => {
|
|
||||||
const type = TrackUnitStickingTypeList[props.stickingType];
|
|
||||||
if (type) {
|
|
||||||
StickingTypeIconMap[type];
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function handleMouseDown(ev: MouseEvent): void {
|
function handleMouseDown(ev: MouseEvent): void {
|
||||||
blockNextMouseUp = false;
|
blockNextMouseUp = false;
|
||||||
if (ev.button === 0) {
|
if (ev.button === 0) {
|
||||||
@@ -125,53 +108,8 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.track-unit {
|
|
||||||
width: 2em;
|
|
||||||
height: 2em;
|
|
||||||
margin-right: 4px;
|
|
||||||
background-color: #464646;
|
|
||||||
border-color: #464646;
|
|
||||||
border-width: 0.1em 0.1em 0.1em 0.1em;
|
|
||||||
border-style: solid;
|
|
||||||
display: inline-block;
|
|
||||||
transition: background-color 100ms, border-color 100ms;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-unit.highlightable:hover {
|
|
||||||
border-color: #5f5f5f;
|
|
||||||
background-color: #5f5f5f;
|
|
||||||
transition: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vertical-mode .track-unit {
|
.vertical-mode .track-unit {
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-unit.on {
|
|
||||||
border-color: var(--color-ui-accent);
|
|
||||||
background-color: var(--color-ui-accent);
|
|
||||||
transition: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-unit.on.Accent, .track-unit.on.Accent.highlightable:hover {
|
|
||||||
border-color: var(--color-ui-neutral-light);
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-unit.on.highlightable:hover {
|
|
||||||
border-color: var(--color-ui-accent-hover);
|
|
||||||
background-color: var(--color-ui-accent-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-unit.on.Ghost {
|
|
||||||
opacity: 60%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-unit .icon-view {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.track-unit.on.icon-visible .icon-view {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
87
src/ui/TrackUnitBox/TrackUnitBox.vue
Normal file
87
src/ui/TrackUnitBox/TrackUnitBox.vue
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<template>
|
||||||
|
<div class="track-unit-box" :class="classes">
|
||||||
|
<icon v-if="iconName" :icon-name="iconName" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { TrackUnitStickingTypeList, TrackUnitTypeList } from "@/Track";
|
||||||
|
import Icon from "@/ui/Widgets/Icon/Icon.vue";
|
||||||
|
import { StickingTypeIconMap, getClasses } from "@/ui/TrackUnit/trackUnit";
|
||||||
|
import { computed } from "vue";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
stickingType: number | null,
|
||||||
|
type: number,
|
||||||
|
on: boolean,
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const classes = computed(() => getClasses({
|
||||||
|
on: props.on,
|
||||||
|
stickingType: props.stickingType ? (TrackUnitStickingTypeList[props.stickingType] ?? null) : null,
|
||||||
|
type: TrackUnitTypeList[props.type] ?? 'Normal',
|
||||||
|
highlightable: true,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const iconName = computed(() => {
|
||||||
|
if (props.stickingType) {
|
||||||
|
const type = TrackUnitStickingTypeList[props.stickingType] ?? null;
|
||||||
|
if (type) {
|
||||||
|
return StickingTypeIconMap[type];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.track-unit-box {
|
||||||
|
width: 2em;
|
||||||
|
height: 2em;
|
||||||
|
margin-right: 4px;
|
||||||
|
background-color: #464646;
|
||||||
|
border-color: #464646;
|
||||||
|
border-width: 0.1em 0.1em 0.1em 0.1em;
|
||||||
|
border-style: solid;
|
||||||
|
display: inline-block;
|
||||||
|
transition: background-color 100ms, border-color 100ms;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.highlightable {
|
||||||
|
&:hover {
|
||||||
|
border-color: #5f5f5f;
|
||||||
|
background-color: #5f5f5f;
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.on {
|
||||||
|
border-color: var(--color-ui-accent-hover);
|
||||||
|
background-color: var(--color-ui-accent-hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-view {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.on {
|
||||||
|
border-color: var(--color-ui-accent);
|
||||||
|
background-color: var(--color-ui-accent);
|
||||||
|
transition: none;
|
||||||
|
|
||||||
|
&.Accent, &.Accent.highlightable:hover {
|
||||||
|
border-color: var(--color-ui-neutral-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.Ghost {
|
||||||
|
opacity: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.icon-visible .icon-view {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -10,6 +10,7 @@ import RightFoot from "@/assets/svgs/RF.png";
|
|||||||
import Eraser from "@/assets/svgs/eraser-fill.svg";
|
import Eraser from "@/assets/svgs/eraser-fill.svg";
|
||||||
import Upload from "@/assets/svgs/upload.svg";
|
import Upload from "@/assets/svgs/upload.svg";
|
||||||
import Floppy from "@/assets/svgs/floppy2-fill.svg";
|
import Floppy from "@/assets/svgs/floppy2-fill.svg";
|
||||||
|
import Delete from "@/assets/svgs/delete.svg";
|
||||||
|
|
||||||
export const IconUrlMap = {
|
export const IconUrlMap = {
|
||||||
arrowClockwise: ArrowClockwise,
|
arrowClockwise: ArrowClockwise,
|
||||||
@@ -24,6 +25,7 @@ export const IconUrlMap = {
|
|||||||
eraser: Eraser,
|
eraser: Eraser,
|
||||||
upload: Upload,
|
upload: Upload,
|
||||||
save: Floppy,
|
save: Floppy,
|
||||||
|
delete: Delete,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type IconName = keyof typeof IconUrlMap;
|
export type IconName = keyof typeof IconUrlMap;
|
||||||
|
|||||||
Reference in New Issue
Block a user