UPD: Knob mapping management
This commit is contained in:
@@ -144,7 +144,7 @@ app.whenReady().then(() => {
|
|||||||
mainWindow.webContents.send('nanoSerialApi:event', 'disconnected', deviceid, data)
|
mainWindow.webContents.send('nanoSerialApi:event', 'disconnected', deviceid, data)
|
||||||
})
|
})
|
||||||
nanoSerialApi.on('nanoSerialApi:update', (deviceid, data) => {
|
nanoSerialApi.on('nanoSerialApi:update', (deviceid, data) => {
|
||||||
if (!data.startsWith('{"idle"') && !data.startsWith('{"p"'))
|
if (!data.startsWith('{"idle"') && !data.startsWith('{"p"') && !data.startsWith('{"ks"'))
|
||||||
console.log('Update event', deviceid, data)
|
console.log('Update event', deviceid, data)
|
||||||
mainWindow.webContents.send('nanoSerialApi:event', 'update', deviceid, data)
|
mainWindow.webContents.send('nanoSerialApi:event', 'update', deviceid, data)
|
||||||
})
|
})
|
||||||
|
|||||||
16
src/renderer/src/components/config/values/MidiValue.vue
Normal file
16
src/renderer/src/components/config/values/MidiValue.vue
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<template>
|
||||||
|
<div>midi value settings</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import ConfigSection from '@renderer/components/common/ConfigSection.vue'
|
||||||
|
import ActionGroup from '@renderer/components/config/actions/ActionGroup.vue'
|
||||||
|
import { RotateCw, RotateCcw, CircleDashed } from 'lucide-vue-next'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -30,4 +30,11 @@ const actionsEvery = ref([
|
|||||||
])
|
])
|
||||||
const actionsCw = ref([])
|
const actionsCw = ref([])
|
||||||
const actionsCcw = ref([])
|
const actionsCcw = ref([])
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
>
|
>
|
||||||
<ScrambleText
|
<ScrambleText
|
||||||
class="overflow-hidden text-ellipsis text-nowrap"
|
class="overflow-hidden text-ellipsis text-nowrap"
|
||||||
:text="inputValue ? valueTypeOptions[inputValue].label : 'Select a value type...'"
|
:text="valueType?.label || 'Select a value type...'"
|
||||||
/>
|
/>
|
||||||
<ChevronsUpDown class="ml-2 size-4 shrink-0 opacity-50" />
|
<ChevronsUpDown class="ml-2 size-4 shrink-0 opacity-50" />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -64,6 +64,7 @@
|
|||||||
<template v-else>
|
<template v-else>
|
||||||
<Button
|
<Button
|
||||||
class="aspect-square bg-orange-950 p-1 text-zinc-200 hover:bg-orange-900 hover:text-zinc-100"
|
class="aspect-square bg-orange-950 p-1 text-zinc-200 hover:bg-orange-900 hover:text-zinc-100"
|
||||||
|
@click="$emit('delete')"
|
||||||
><Check class="size-4"
|
><Check class="size-4"
|
||||||
/></Button>
|
/></Button>
|
||||||
<Button
|
<Button
|
||||||
@@ -95,7 +96,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<Separator />
|
<Separator />
|
||||||
<component
|
<component
|
||||||
:is="valueTypeOptions[inputValue]?.component ? valueTypeOptions[inputValue]?.component : WIP"
|
:is="
|
||||||
|
inputValue && valueTypeOptions[inputValue]?.component
|
||||||
|
? valueTypeOptions[inputValue]?.component
|
||||||
|
: WIP
|
||||||
|
"
|
||||||
|
:value="value"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -113,7 +119,7 @@ import {
|
|||||||
CommandItem,
|
CommandItem,
|
||||||
CommandList
|
CommandList
|
||||||
} from '@renderer/components/ui/command'
|
} from '@renderer/components/ui/command'
|
||||||
import { ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { cn } from '@renderer/lib/utils'
|
import { cn } from '@renderer/lib/utils'
|
||||||
import ScrambleText from '@renderer/components/common/ScrambleText.vue'
|
import ScrambleText from '@renderer/components/common/ScrambleText.vue'
|
||||||
import {
|
import {
|
||||||
@@ -128,8 +134,15 @@ import {
|
|||||||
} from 'lucide-vue-next'
|
} from 'lucide-vue-next'
|
||||||
import { useElementSize } from '@vueuse/core'
|
import { useElementSize } from '@vueuse/core'
|
||||||
import TriggerActionsValue from '@renderer/components/config/values/TriggerActionsValue.vue'
|
import TriggerActionsValue from '@renderer/components/config/values/TriggerActionsValue.vue'
|
||||||
|
import MidiValue from './MidiValue.vue'
|
||||||
|
|
||||||
defineProps({
|
defineEmits(['delete'])
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
valueIndex: {
|
valueIndex: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: false
|
required: false
|
||||||
@@ -137,13 +150,17 @@ defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const valueTypeOptions = ref({
|
const valueTypeOptions = ref({
|
||||||
controlMouse: { label: 'Move or Scroll the Mouse', component: 'ControlMouseValue' },
|
mouse: { label: 'Move or Scroll the Mouse', component: 'ControlMouseValue' },
|
||||||
controlGamepad: { label: 'Control a Gamepad Axis', component: 'ControlGamepadValue' },
|
gamepad: { label: 'Control a Gamepad Axis', component: 'ControlGamepadValue' },
|
||||||
controlMidi: { label: 'Control a MIDI Value', component: 'ControlMidiValue' },
|
midi: { label: 'Control a MIDI CC Value', component: MidiValue },
|
||||||
controlOsc: { label: 'Control an OSC Value', component: 'ControlOscValue' },
|
action: { label: 'Trigger Actions on Rotation', component: TriggerActionsValue }
|
||||||
controlSerial: { label: 'Control a Value over Serial', component: 'ControlSerialValue' },
|
})
|
||||||
controlProfile: { label: 'Switch Device Profiles', component: 'ControlProfileValue' },
|
|
||||||
triggerActions: { label: 'Trigger Actions on Rotation', component: TriggerActionsValue }
|
const valueType = computed(() => {
|
||||||
|
if (inputValue.value in valueTypeOptions.value) {
|
||||||
|
return valueTypeOptions.value[inputValue.value]
|
||||||
|
}
|
||||||
|
return null
|
||||||
})
|
})
|
||||||
|
|
||||||
const conditions = ref({
|
const conditions = ref({
|
||||||
@@ -163,6 +180,6 @@ const comboboxButton = ref(null)
|
|||||||
const { width } = useElementSize(comboboxButton)
|
const { width } = useElementSize(comboboxButton)
|
||||||
|
|
||||||
const open = ref(false)
|
const open = ref(false)
|
||||||
const inputValue = ref('')
|
const inputValue = ref(props.value.value.type || null)
|
||||||
const confirmDelete = ref(false)
|
const confirmDelete = ref(false)
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -11,7 +11,11 @@
|
|||||||
>
|
>
|
||||||
<template #item="dragValue">
|
<template #item="dragValue">
|
||||||
<div :key="dragValue.element.id">
|
<div :key="dragValue.element.id">
|
||||||
<ValueCard :value-index="dragValue.index + 1" />
|
<ValueCard
|
||||||
|
:value="dragValue.element"
|
||||||
|
:value-index="dragValue.index + 1"
|
||||||
|
@delete="deviceStore.removeKnobValue(dragValue.index)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</draggable>
|
</draggable>
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ interface UpdateData {
|
|||||||
profiles: string[] | undefined
|
profiles: string[] | undefined
|
||||||
current: string | undefined
|
current: string | undefined
|
||||||
profile: Profile | undefined
|
profile: Profile | undefined
|
||||||
|
ks: number | undefined
|
||||||
kd: number | undefined
|
kd: number | undefined
|
||||||
ku: number | undefined
|
ku: number | undefined
|
||||||
settings: DeviceSettings | undefined
|
settings: DeviceSettings | undefined
|
||||||
@@ -463,6 +464,13 @@ export const useDeviceStore = defineStore('device', {
|
|||||||
addKnobValue(value: Value | null = null, updateDevice: boolean = true) {
|
addKnobValue(value: Value | null = null, updateDevice: boolean = true) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
value = JSON.parse(JSON.stringify(this.defaultKnobValue)) as Value
|
value = JSON.parse(JSON.stringify(this.defaultKnobValue)) as Value
|
||||||
|
let lowestKeyState = 0
|
||||||
|
this.currentProfile!.knob.forEach((v) => {
|
||||||
|
if (v.keyState > lowestKeyState) {
|
||||||
|
lowestKeyState = v.keyState
|
||||||
|
}
|
||||||
|
})
|
||||||
|
value.keyState = (lowestKeyState + 1) % 16
|
||||||
}
|
}
|
||||||
this.currentProfile!.knob.push(value)
|
this.currentProfile!.knob.push(value)
|
||||||
if (updateDevice) {
|
if (updateDevice) {
|
||||||
@@ -475,6 +483,19 @@ export const useDeviceStore = defineStore('device', {
|
|||||||
)
|
)
|
||||||
this.setDirtyState(true)
|
this.setDirtyState(true)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
removeKnobValue(index: number, updateDevice: boolean = true) {
|
||||||
|
this.currentProfile!.knob.splice(index, 1)
|
||||||
|
if (updateDevice) {
|
||||||
|
sendDebounced(
|
||||||
|
this.currentDeviceId!,
|
||||||
|
JSON.stringify({
|
||||||
|
profile: this.currentProfileName,
|
||||||
|
updates: { knob: this.currentProfile!.knob }
|
||||||
|
})
|
||||||
|
)
|
||||||
|
this.setDirtyState(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -527,7 +548,7 @@ export const initializeDevices = () => {
|
|||||||
console.error('Failed to parse update data:', e, dataString)
|
console.error('Failed to parse update data:', e, dataString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!update.idle && !update.p) {
|
if (!update.idle && !update.p && !update.ks) {
|
||||||
console.log('Received update:', update)
|
console.log('Received update:', update)
|
||||||
}
|
}
|
||||||
if (update.p !== undefined) {
|
if (update.p !== undefined) {
|
||||||
|
|||||||
Reference in New Issue
Block a user