mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2026-01-08 11:02:50 +00:00
layout viewer
This commit is contained in:
@@ -1,3 +1,94 @@
|
|||||||
{
|
{
|
||||||
"SPA": "␣"
|
"SPA": "␣",
|
||||||
|
"DEL": "␡",
|
||||||
|
"RH_Thumb_3_Left": "",
|
||||||
|
"RH_Thumb_3_Down": "",
|
||||||
|
"RH_Thumb_3_Right": "",
|
||||||
|
"RH_Thumb_3_Up": "",
|
||||||
|
"RH_Thumb_3_Center": "",
|
||||||
|
"RH_Thumb_2_Left": "",
|
||||||
|
"RH_Thumb_2_Down": "",
|
||||||
|
"RH_Thumb_2_Right": "",
|
||||||
|
"RH_Thumb_2_Up": "",
|
||||||
|
"RH_Thumb_2_Center": "",
|
||||||
|
"RH_Thumb_1_Left": "",
|
||||||
|
"RH_Thumb_1_Down": "",
|
||||||
|
"RH_Thumb_1_Right": "",
|
||||||
|
"RH_Thumb_1_Up": "",
|
||||||
|
"RH_Thumb_1_Center": "",
|
||||||
|
"RH_Pinky_Left": "",
|
||||||
|
"RH_Pinky_Down": "",
|
||||||
|
"RH_Pinky_Right": "",
|
||||||
|
"RH_Pinky_Up": "",
|
||||||
|
"RH_Pinky_Center": "",
|
||||||
|
"RH_Ring_Secondary_Left": "",
|
||||||
|
"RH_Ring_Secondary_Down": "",
|
||||||
|
"RH_Ring_Secondary_Right": "",
|
||||||
|
"RH_Ring_Secondary_Up": "",
|
||||||
|
"RH_Ring_Secondary_Center": "",
|
||||||
|
"RH_Ring_Primary_Left": "",
|
||||||
|
"RH_Ring_Primary_Down": "",
|
||||||
|
"RH_Ring_Primary_Right": "",
|
||||||
|
"RH_Ring_Primary_Up": "",
|
||||||
|
"RH_Ring_Primary_Center": "",
|
||||||
|
"RH_Middle_Secondary_Left": "",
|
||||||
|
"RH_Middle_Secondary_Down": "",
|
||||||
|
"RH_Middle_Secondary_Right": "",
|
||||||
|
"RH_Middle_Secondary_Up": "",
|
||||||
|
"RH_Middle_Secondary_Center": "",
|
||||||
|
"RH_Middle_Primary_Left": "",
|
||||||
|
"RH_Middle_Primary_Down": "",
|
||||||
|
"RH_Middle_Primary_Right": "",
|
||||||
|
"RH_Middle_Primary_Up": "",
|
||||||
|
"RH_Middle_Primary_Center": "",
|
||||||
|
"RH_Index_Left": "",
|
||||||
|
"RH_Index_Down": "",
|
||||||
|
"RH_Index_Right": "",
|
||||||
|
"RH_Index_Up": "",
|
||||||
|
"RH_Index_Center": "",
|
||||||
|
"LH_Thumb_3_Left": "",
|
||||||
|
"LH_Thumb_3_Down": "",
|
||||||
|
"LH_Thumb_3_Right": "",
|
||||||
|
"LH_Thumb_3_Up": "",
|
||||||
|
"LH_Thumb_3_Center": "",
|
||||||
|
"LH_Thumb_2_Left": "",
|
||||||
|
"LH_Thumb_2_Down": "",
|
||||||
|
"LH_Thumb_2_Right": "",
|
||||||
|
"LH_Thumb_2_Up": "",
|
||||||
|
"LH_Thumb_2_Center": "",
|
||||||
|
"LH_Thumb_1_Left": "",
|
||||||
|
"LH_Thumb_1_Down": "",
|
||||||
|
"LH_Thumb_1_Right": "",
|
||||||
|
"LH_Thumb_1_Up": "",
|
||||||
|
"LH_Thumb_1_Center": "",
|
||||||
|
"LH_Pinky_Left": "",
|
||||||
|
"LH_Pinky_Down": "",
|
||||||
|
"LH_Pinky_Right": "",
|
||||||
|
"LH_Pinky_Up": "",
|
||||||
|
"LH_Pinky_Center": "",
|
||||||
|
"LH_Ring_Secondary_Left": "",
|
||||||
|
"LH_Ring_Secondary_Down": "",
|
||||||
|
"LH_Ring_Secondary_Right": "",
|
||||||
|
"LH_Ring_Secondary_Up": "",
|
||||||
|
"LH_Ring_Secondary_Center": "",
|
||||||
|
"LH_Ring_Primary_Left": "",
|
||||||
|
"LH_Ring_Primary_Down": "",
|
||||||
|
"LH_Ring_Primary_Right": "",
|
||||||
|
"LH_Ring_Primary_Up": "",
|
||||||
|
"LH_Ring_Primary_Center": "",
|
||||||
|
"LH_Middle_Secondary_Left": "",
|
||||||
|
"LH_Middle_Secondary_Down": "",
|
||||||
|
"LH_Middle_Secondary_Right": "",
|
||||||
|
"LH_Middle_Secondary_Up": "",
|
||||||
|
"LH_Middle_Secondary_Center": "",
|
||||||
|
"LH_Middle_Primary_Left": "",
|
||||||
|
"LH_Middle_Primary_Down": "",
|
||||||
|
"LH_Middle_Primary_Right": "",
|
||||||
|
"LH_Middle_Primary_Up": "",
|
||||||
|
"LH_Middle_Primary_Center": "",
|
||||||
|
"LH_Index_Left": "",
|
||||||
|
"LH_Index_Down": "",
|
||||||
|
"LH_Index_Right": "",
|
||||||
|
"LH_Index_Up": "",
|
||||||
|
"LH_Index_Center": ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,42 +15,42 @@
|
|||||||
<div class="col layout" style="gap: 0">
|
<div class="col layout" style="gap: 0">
|
||||||
<div class="row" style="gap: 156px">
|
<div class="row" style="gap: 156px">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 30, e: 31, n: 32, w: 33, s: 34}} type="tertiary" />
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 25, e: 26, n: 27, w: 28, s: 29}} />
|
||||||
<RingInput {activeLayer} type="secondary" />
|
<RingInput {activeLayer} keys={{d: 40, e: 41, n: 42, w: 43, s: 44}} type="secondary" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 20, e: 21, n: 22, w: 23, s: 24}} />
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 35, e: 36, n: 37, w: 38, s: 39}} type="secondary" />
|
||||||
</div>
|
</div>
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 15, e: 16, n: 17, w: 18, s: 19}} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 60, w: 61, n: 62, e: 63, s: 64}} />
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 65, w: 66, n: 67, e: 68, s: 69}} />
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 80, w: 81, n: 82, e: 83, s: 84}} />
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 70, w: 71, n: 72, e: 73, s: 74}} />
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 85, w: 86, n: 87, e: 88, s: 89}} />
|
||||||
</div>
|
</div>
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 75, w: 76, n: 77, e: 78, s: 79}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row" style="gap: 48px; margin-top: -32px">
|
<div class="row" style="gap: 48px; margin-top: -32px">
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 10, e: 11, n: 12, w: 13, s: 14}} />
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 55, w: 56, n: 57, e: 58, s: 59}} />
|
||||||
</div>
|
</div>
|
||||||
<div class="row" style="gap: 160px">
|
<div class="row" style="gap: 160px">
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 5, e: 6, n: 7, w: 8, s: 9}} />
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 50, w: 51, n: 52, e: 53, s: 54}} />
|
||||||
</div>
|
</div>
|
||||||
<div class="row" style="gap: 320px; margin-top: -12px">
|
<div class="row" style="gap: 320px; margin-top: -12px">
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 0, e: 1, n: 2, w: 3, s: 4}} type="secondary" />
|
||||||
<RingInput {activeLayer} />
|
<RingInput {activeLayer} keys={{d: 45, w: 46, n: 47, e: 48, s: 49}} type="secondary" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import {layout} from "$lib/serial/connection.js"
|
||||||
|
import {ACTION_MAP} from "$lib/serial/webserial/constants/action-map.js"
|
||||||
|
import keySymbols from "$lib/assets/key-symbols.json"
|
||||||
|
|
||||||
export let activeLayer = 0
|
export let activeLayer = 0
|
||||||
|
|
||||||
export let layout = [
|
/** @type {{d: number, n: number, w: number, e: number, s: number}} */
|
||||||
["a", "b", "c"],
|
export let keys
|
||||||
["d", "e", "f"],
|
|
||||||
["g", "h", "i"],
|
|
||||||
["j", "k", "l"],
|
|
||||||
]
|
|
||||||
|
|
||||||
/** @type {'primary' | 'secondary' | 'tertiary'} */
|
/** @type {'primary' | 'secondary' | 'tertiary'} */
|
||||||
export let type = "primary"
|
export let type = "primary"
|
||||||
@@ -23,18 +23,35 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getKeyDescriptions(keys) {
|
function getKeyDescriptions(keys) {
|
||||||
return keys.map((it, i) => (it ? `${it} (${layerNames[i]})` : "")).join("\n")
|
return keys.map(([, it], i) => (it ? `${it} (${layerNames[i]})` : "")).join("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id {number}
|
||||||
|
* @param layout {[number[], number[], number[]]}
|
||||||
|
* @returns [string, string][]
|
||||||
|
*/
|
||||||
|
function getActions(id, layout) {
|
||||||
|
return Array.from({length: 3}).map((_, i) => {
|
||||||
|
const actionId = layout?.[i][id]
|
||||||
|
return actionId !== undefined
|
||||||
|
? [keySymbols[ACTION_MAP[actionId]], ACTION_MAP[actionId]]
|
||||||
|
: ["❓", undefined]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="radial {type}">
|
<div class="radial {type}">
|
||||||
{#each layout as keys, quadrant}
|
{#each [keys.n, keys.e, keys.s, keys.w] as id, quadrant}
|
||||||
<button title={getKeyDescriptions(keys)}>
|
{@const actions = getActions(id, $layout)}
|
||||||
{#each keys as value, layer}
|
<button title={getKeyDescriptions(actions)}>
|
||||||
<span
|
{#each actions as [value, raw], layer}
|
||||||
class:active={virtualLayerMap[activeLayer] === virtualLayerMap[layer]}
|
{#if value || raw}
|
||||||
style="offset-distance: {offsetDistance(quadrant, layer, activeLayer)}%">{value}</span
|
<span
|
||||||
>
|
class:active={virtualLayerMap[activeLayer] === virtualLayerMap[layer]}
|
||||||
|
style="offset-distance: {offsetDistance(quadrant, layer, activeLayer)}%">{value || raw}</span
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</button>
|
</button>
|
||||||
{/each}
|
{/each}
|
||||||
@@ -64,6 +81,7 @@
|
|||||||
$cr: math.div($size, 2) - 2 * $offset;
|
$cr: math.div($size, 2) - 2 * $offset;
|
||||||
|
|
||||||
will-change: scale, offset-distance;
|
will-change: scale, offset-distance;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
scale: 0.9;
|
scale: 0.9;
|
||||||
offset-path: path(
|
offset-path: path(
|
||||||
@@ -82,7 +100,7 @@
|
|||||||
|
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
|
||||||
opacity: 0.3;
|
opacity: 0.2;
|
||||||
|
|
||||||
transition: scale 250ms ease, opacity 250ms ease, offset-distance 250ms ease;
|
transition: scale 250ms ease, opacity 250ms ease, offset-distance 250ms ease;
|
||||||
|
|
||||||
@@ -137,4 +155,12 @@
|
|||||||
clip-path: polygon(50% 50%, 0 0, 0 100%);
|
clip-path: polygon(50% 50%, 0 0, 0 100%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.secondary > button {
|
||||||
|
filter: brightness(80%) contrast(120%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tertiary > button {
|
||||||
|
filter: brightness(80%) contrast(110%);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ export const serialLog = writable([])
|
|||||||
/** @type {import('svelte/store').Writable<Array<{actions: number[]; phrase: string}>>} */
|
/** @type {import('svelte/store').Writable<Array<{actions: number[]; phrase: string}>>} */
|
||||||
export const chords = writable([])
|
export const chords = writable([])
|
||||||
|
|
||||||
|
/** @type {import('svelte/store').Writable<[number[], number[], number[]]>} */
|
||||||
|
export const layout = writable([[], [], []])
|
||||||
|
|
||||||
/** @type {import('svelte/store').Writable<boolean>} */
|
/** @type {import('svelte/store').Writable<boolean>} */
|
||||||
export const syncing = writable(false)
|
export const syncing = writable(false)
|
||||||
|
|
||||||
@@ -21,6 +24,14 @@ export async function initSerial() {
|
|||||||
device ??= new CharaDevice()
|
device ??= new CharaDevice()
|
||||||
serialPort.set(device)
|
serialPort.set(device)
|
||||||
|
|
||||||
|
const parsedLayout = [[], [], []]
|
||||||
|
for (let layer = 1; layer <= 3; layer++) {
|
||||||
|
for (let i = 0; i < 90; i++) {
|
||||||
|
parsedLayout[layer - 1][i] = await device.getLayoutKey(layer, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
layout.set(parsedLayout)
|
||||||
|
|
||||||
const chordCount = await device.getChordCount()
|
const chordCount = await device.getChordCount()
|
||||||
const chordInfo = []
|
const chordInfo = []
|
||||||
for (let i = 0; i < chordCount; i++) {
|
for (let i = 0; i < chordCount; i++) {
|
||||||
|
|||||||
@@ -179,4 +179,15 @@ export class CharaDevice {
|
|||||||
unk: Number(b),
|
unk: Number(b),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param layer {number}
|
||||||
|
* @param id {number}
|
||||||
|
* @returns {Promise<number>}
|
||||||
|
*/
|
||||||
|
async getLayoutKey(layer, id) {
|
||||||
|
const layout = await this.send(`VAR B3 A${layer} ${id}`)
|
||||||
|
const [position] = layout.split(" ").map(Number)
|
||||||
|
return position
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user