feat: experimental support for compounds

This commit is contained in:
2024-07-11 13:38:19 +02:00
parent d91273d27b
commit 500221f39a
6 changed files with 79 additions and 17 deletions

View File

@@ -104,6 +104,26 @@ actions:
<<: *tertiary_keymap
id: "KM_3_R"
variant: right
558:
id: HOLD_COMPOUND
title: Activate Chord Library
icon: layers
description: |
When used in a chord includes that chord as a base
compound chord for all subsequent chords.
This is effectively a library switch.
Since library activations can be nested, you
usually add a "Reset Chord Library" before this action.
559:
id: RELEASE_COMPOUND
title: Reset Chord Library
icon: layers_clear
description: |
Releases the active compound state, returning
to the default library.
While "Activate Chord Library" can only be used
as an output of a chord, this action can be assigned
to switches directly.
576:
id: ACTION_DELAY_1000
icon: clock_loader_90

View File

@@ -55,3 +55,19 @@ export function deserializeActions(native: bigint): number[] {
return actions;
}
/**
* Hashes a chord input the same way as CCOS
*/
export function hashChord(actions: number[]) {
const chord = new Uint8Array(16);
const view = new DataView(chord.buffer);
const serialized = serializeActions(actions);
view.setBigUint64(0, serialized & 0xffff_ffff_ffff_ffffn, true);
view.setBigUint64(8, serialized >> 64n, true);
let hash = 2166136261;
for (let i = 0; i < 16; i++) {
hash = Math.imul(hash ^ view.getUint8(i), 16777619);
}
return hash & 0x3fff_ffff;
}

View File

@@ -1,6 +1,6 @@
import { persistentWritable } from "$lib/storage";
import { derived } from "svelte/store";
import type { Chord } from "$lib/serial/chord";
import { hashChord, type Chord } from "$lib/serial/chord";
import {
deviceChords,
deviceLayout,
@@ -158,3 +158,9 @@ export const chords = derived([overlay, deviceChords], ([overlay, chords]) => {
a.localeCompare(b),
);
});
export const chordHashes = derived(
chords,
(chords) =>
new Map(chords.map((chord) => [hashChord(chord.actions), chord] as const)),
);

View File

@@ -144,7 +144,6 @@
progress = i;
if ("phrase" in chord) {
console.log(encodeChord(chord, osLayout));
await index.addAsync(i, encodeChord(chord, osLayout));
}
}

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import type { ChordInfo } from "$lib/undo-redo";
import { changes, ChangeType } from "$lib/undo-redo";
import { changes, chordHashes, ChangeType } from "$lib/undo-redo";
import { createEventDispatcher } from "svelte";
import LL from "$i18n/i18n-svelte";
import ActionString from "$lib/components/ActionString.svelte";
@@ -8,6 +8,7 @@
import { serialPort } from "$lib/serial/connection";
import { get } from "svelte/store";
import { inputToAction } from "./input-converter";
import { hashChord } from "$lib/serial/chord";
export let chord: ChordInfo | undefined = undefined;
@@ -21,14 +22,15 @@
}
function makeChordInput(...actions: number[]) {
const compound = compoundIndices ?? [];
const compound = compoundInputs[0]
? hashChord(compoundInputs[0].actions)
: 0;
return [
...compound,
...Array.from(
{
length: 12 - (compound.length + actions.length + 1),
length: 12 - actions.length,
},
() => 0,
(_, i) => (compound >> (i * 10)) & 0x3ff,
),
...actions.toSorted(compare),
];
@@ -73,7 +75,6 @@
function addSpecial(event: MouseEvent) {
selectAction(event, (action) => {
changes.update((changes) => {
console.log(compoundIndices, chordActions, action);
changes.push({
type: ChangeType.Chord,
id: chord!.id,
@@ -85,10 +86,30 @@
});
}
function* resolveCompound(chord?: ChordInfo) {
if (!chord) return;
let current = chord;
for (let i = 0; i < 10; i++) {
if (current.actions[3] !== 0) return;
const compound = current.actions
.slice(0, 3)
.reduce((a, b, i) => a | (b << (i * 10)));
if (compound === 0) return;
const next = $chordHashes.get(compound);
if (!next) {
return null;
}
current = next;
yield next;
}
return;
}
$: chordActions = chord?.actions
.slice(chord.actions.lastIndexOf(0) + 1)
.toSorted(compare);
$: compoundIndices = chord?.actions.slice(0, chord.actions.indexOf(0));
$: compoundInputs = [...resolveCompound(chord)];
</script>
<button
@@ -110,12 +131,15 @@
<span>{$LL.configure.chords.NEW_CHORD()}</span>
{/if}
{#if !editing}
{#each compoundIndices ?? [] as index}
<sub>{index}</sub>
{/each}
{#if compoundIndices?.length}
{#each compoundInputs as compound}
<sub
><ActionString
display="keys"
actions={compound.actions.slice(compound.actions.lastIndexOf(0) + 1)}
></ActionString>
</sub>
<span>&rarr;</span>
{/if}
{/each}
{/if}
<ActionString
display="keys"

View File

@@ -137,9 +137,6 @@
if (parent) {
}
}
console.log(nodeBefore);
console.log(context);
return null;
},
});