new maps

This commit is contained in:
2024-11-24 17:34:41 +00:00
parent eb6abbb97d
commit 641938f7e4
38 changed files with 1241 additions and 228 deletions

View File

@@ -7,6 +7,7 @@
>
<div class="a-card__label-wrapper">
<div class="a-card__label">{{ label }}</div>
<div class="a-card__delete" @click="emits('delete')">&times;</div>
</div>
<div class="a-card__volume">
<span style="height: 1.25rem" @click="node.toggleMute()">
@@ -60,6 +61,7 @@ import DeviceVolume from './DeviceVolume.vue';
import Stop from '../Icons/Stop.vue';
const emits = defineEmits<{
'delete': [],
'next': [],
'prev': [],
'togglePlay': [],
@@ -119,6 +121,7 @@ function onDrop(event: DragEvent) {
.a-card {
--box-color: var(--audio-box-color-playlist, #ffb308);
--box-color-900: color-mix(in lab, var(--box-color), #000 80%);
--box-color-800: color-mix(in lab, var(--box-color), #000 60%);
--box-color-100: color-mix(in lab, var(--box-color), #fff 80%);
--box-color-300: color-mix(in lab, var(--box-color), #fff 40%);
width: 160px;
@@ -179,6 +182,7 @@ function onDrop(event: DragEvent) {
}
.a-card__label-wrapper {
position: relative;
width: 100%;
text-align: center;
margin-top: -1rem;
@@ -224,6 +228,24 @@ function onDrop(event: DragEvent) {
}
}
.a-card__delete {
position: absolute;
top: 0;
right: -1rem;
width: 1.5rem;
height: 1.5rem;
color: var(--box-color-100);
background: var(--box-color-900);
border-radius: 0.25rem;
cursor: pointer;
border: 1px solid rgba(from var(--box-color) r g b / 0.2);
opacity: 0%;
}
.a-card:hover .a-card__delete {
opacity: 100%;
}
@keyframes ripples {
to {
box-shadow:

View File

@@ -4,7 +4,8 @@
:supports="[ 'next', 'prev', 'togglePlay' ]"
@next="node.next()"
@prev="node.prev()"
label="Playlist test"
@delete="$emit('delete')"
label="Playlist"
style="--box-color: var(--color-amber)"
>
<template #preview>
@@ -12,20 +13,32 @@
</template>
<template #popover>
<div>
<!--<div>
{{ node.currentTrack?.name ?? 'No track selected' }}
<div>
<input type="range" min="0" max="100" style="width: 100%" />00:00
<input type="range" min="0" max="100" style="width: 100%" />
</div>
</div>-->
<div>
<div
class="a-playlist__song"
:class="{
'a-playlist__song--playing': song.isPlaying
}"
v-for="(song, idx) in node.sounds()"
:key="song.options.vFile.name"
@click="playTrack(idx)"
>
<span class="a-playlist__song-play-indicator">
<Play style="height: 1rem" />
</span>
<span class="a-playlist__song-name">
{{ song.options.vFile.name }}
</span>
<span @click.prevent="removeSong(song)">
&times;
</span>
</div>
</div>
<div
class="a-playlist__song"
v-for="(song, idx) in node.sounds()"
:key="song.options.vFile.name"
@click="playTrack(idx)"
>
<span>{{ song.options.vFile.name }}</span>
<span>00:00</span>
</div>
</template>
@@ -34,17 +47,27 @@
<script setup lang="ts">
import AudioCard from './AudioCard.vue';
import {PlaylistGroupNode} from '../../model/Audio/PlaylistGroupNode';
import Play from '../Icons/Play.vue';
import {SoundNode} from '../../model/Audio/SoundNode';
const props = defineProps<{
node: PlaylistGroupNode
}>();
const emit = defineEmits<{
'delete': [],
}>();
// playlist.connect(audioContext.destination);
function playTrack(idx: number) {
props.node.changeTrack(idx);
}
function removeSong(song: SoundNode) {
props.node.removeSoundNode(song);
}
</script>
<style>
@@ -92,4 +115,36 @@ function playTrack(idx: number) {
border: 2px solid var(--box-color-300);
}
}
.a-playlist__song {
display: flex;
flex-direction: row;
cursor: pointer;
padding: 0.5rem;
border-bottom: 1px solid var(--box-color-800);
transition: background-color 0.2s;
}
.a-playlist__song-name {
flex: 1;
}
.a-playlist__song--playing {
background-color: var(--box-color-800);
}
.a-playlist__song:first-child {
border-top: 1px solid var(--box-color-800);
}
.a-playlist__song-play-indicator {
opacity: 0;
transition: opacity 0.2s;
margin-right: 0.5rem;
}
.a-playlist__song:hover .a-playlist__song-play-indicator,
.a-playlist__song--playing .a-playlist__song-play-indicator {
opacity: 1;
}
</style>

View File

@@ -6,6 +6,7 @@
:supports="['stop']"
label="SFX"
:node="node"
@delete="emit('delete')"
>
<template #preview>
<div
@@ -38,6 +39,11 @@ const props = defineProps<{
node: SfxGroupNode,
}>();
const emit = defineEmits<{
'delete': [],
}>();
const grouppedSounds = computed(() => {
return groupBy(props.node.sounds(), (sound) => {
return sound.name.replace(/(\d+)$/, '').trim();

View File

@@ -8,17 +8,34 @@
<Playlist
v-if="node.type === 'playlist'"
:node="node"
@delete="deleteNode(node)"
/>
<Sfx
v-else-if="node.type === 'sfx'"
:node="node"
@delete="deleteNode(node)"
/>
<TabSource
v-else-if="node.type === 'tabSource'"
:node="node"
@delete="deleteNode(node)"
/>
</template>
</div>
<div class="a-card add-card" style="--box-color: var(--color-zinc)">
<div class="a-card__label-wrapper">
<div class="a-card__label">Add</div>
</div>
<div @click="addNode('playlist')" class="soundboard-add-card__btn">
Playlist
</div>
<div @click="addNode('sfx')" class="soundboard-add-card__btn">
Sfx
</div>
<div @click="addNode('tab')" class="soundboard-add-card__btn">
Tab Source
</div>
</div>
</div>
</template>
<script setup lang="ts">
@@ -34,45 +51,56 @@ import TabSource from './TabSource.vue';
import DeviceVolume from './DeviceVolume.vue';
import {AudioNodeManager} from '../../model/Audio/AudioNodesManager';
import {debounce} from '../../utils/debounce';
import IconPlus from '../Icons/IconPlus.vue';
import {SoundNode} from '../../model/Audio/SoundNode';
const fs = inject(MountedFsSymbol)!;
const audioContext = inject(AudioContextSymbol) as AudioContext;
const deviceManager = inject(RemoteDeviceManagerSymbol)!;
const nodesDefinition = JSON.parse(localStorage.getItem('soundboard') ?? '[]');
const audioNodesManager = new AudioNodeManager();
// const playlist = reactive(new PlaylistGroupNode({
// currentTrack: 0,
// currentTrackTime: 0,
// volume: 100,
// isMuted: false,
// sounds: [],
// }, {
// fs,
// audioContext,
// }))
// const sfx = reactive(new SfxGroupNode({
// isMuted: false,
// volume: 100,
// sounds: [],
// }, {
// fs,
// audioContext,
// }))
// const tabSource = reactive(new TabSourceNode({
// isMuted: false,
// volume: 100,
// sounds: [],
// }, {
// fs,
// audioContext,
// }))
const nodes = reactive(audioNodesManager.restore({fs, audioContext}));
function addNode(name: string) {
if (name === 'playlist') {
nodes.push(reactive(new PlaylistGroupNode({
currentTrack: 0,
currentTrackTime: 0,
volume: 100,
isMuted: false,
sounds: [],
}, {
fs,
audioContext,
})))
} else if (name === 'sfx') {
nodes.push(reactive(new SfxGroupNode({
isMuted: false,
volume: 100,
sounds: [],
}, {
fs,
audioContext,
})))
} else if (name === 'tab') {
nodes.push(reactive(new TabSourceNode({
isMuted: false,
volume: 100,
sounds: [],
}, {
fs,
audioContext,
})))
}
}
const deleteNode = (node: SoundNode) => {
node.stop?.();
node.disconnect();
// @ts-ignore
nodes.splice(nodes.indexOf(node), 1);
}
watch(() => nodes, debounce((newNodes) => {
console.log('NEW_NODES', newNodes);
audioNodesManager.store(newNodes);
@@ -116,5 +144,22 @@ watch(() => deviceManager.audioDevices.length, () => {
gap: 3rem 1rem;
padding: 1rem;
}
.soundboard-add-card {
}
.soundboard-add-card__btn {
text-align: center;
border: 1px solid;
margin: 0.25rem;
background: var(--box-color-900);
border: 1px solid rgba(from var(--box-color) r g b / 0.2);
cursor: pointer;
}
.soundboard-add-card__btn:hover {
background: var(--box-color-800);
}
</style>

View File

@@ -7,6 +7,7 @@
:supports="['play', 'stop']"
label="Tab Audio"
:node="node"
@delete="emit('delete')"
>
</AudioCard>
</template>
@@ -15,6 +16,10 @@
import {TabSourceNode} from '../../model/Audio/TabSourceNode';
import AudioCard from './AudioCard.vue';
const emit = defineEmits<{
'delete': [],
}>();
const props = defineProps<{
node: TabSourceNode,
}>();