mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2026-01-18 16:02:57 +00:00
120 lines
2.8 KiB
TypeScript
120 lines
2.8 KiB
TypeScript
import type { Plugin, Rollup } from "vite";
|
|
import type { CompiledLayout } from "./src/lib/assets/layouts/layout.d.ts";
|
|
import yaml from "js-yaml";
|
|
|
|
export interface VisualLayout {
|
|
name: string;
|
|
col: VisualLayoutRow[];
|
|
}
|
|
|
|
interface Positionable {
|
|
offset: [number, number];
|
|
rotate: number;
|
|
}
|
|
|
|
export interface VisualLayoutRow extends Positionable {
|
|
row: Array<VisualLayoutKey | VisualLayoutSwitch>;
|
|
}
|
|
|
|
export interface VisualLayoutKey extends Positionable {
|
|
key: number;
|
|
size?: [number, number];
|
|
}
|
|
|
|
export interface VisualLayoutSwitch extends Positionable {
|
|
switch: {
|
|
n: number;
|
|
e: number;
|
|
w: number;
|
|
s: number;
|
|
d: number;
|
|
};
|
|
}
|
|
|
|
const fileRegex = /\.(layout\.yml)$/;
|
|
|
|
export function layoutPlugin() {
|
|
return {
|
|
name: "charachorder-layout",
|
|
transform(code, id) {
|
|
if (fileRegex.test(id)) {
|
|
return {
|
|
code: `const data = ${JSON.stringify(compileLayout(yaml.load(code) as VisualLayout))};\nexport default data;`,
|
|
map: null,
|
|
} satisfies Rollup.TransformResult;
|
|
}
|
|
return null;
|
|
},
|
|
} satisfies Plugin;
|
|
}
|
|
|
|
export function compileLayout(layout: VisualLayout): CompiledLayout {
|
|
const compiled: CompiledLayout = {
|
|
name: layout.name,
|
|
size: [0, 0],
|
|
keys: [],
|
|
};
|
|
|
|
let y = 0;
|
|
for (const { row, offset } of layout.col) {
|
|
let x = offset?.[0] ?? 0;
|
|
y += offset?.[1] ?? 0;
|
|
let maxHeight = 0;
|
|
for (const info of row) {
|
|
const [ox, oy] = info.offset || [0, 0];
|
|
const rotate = info.rotate || 0;
|
|
if ("key" in info) {
|
|
const [width, height] = info.size ?? [1, 1];
|
|
|
|
compiled.keys.push({
|
|
id: info.key,
|
|
shape: "square",
|
|
size: [width, height],
|
|
pos: [x + ox, y + oy],
|
|
cornerRadius: 0.1,
|
|
rotate,
|
|
});
|
|
|
|
x += width + ox;
|
|
maxHeight = Math.max(maxHeight, height + oy);
|
|
} else if ("switch" in info) {
|
|
const cx = x + ox + 1;
|
|
const cy = y + oy + 1;
|
|
for (const [i, id] of [
|
|
info.switch.s,
|
|
info.switch.w,
|
|
info.switch.n,
|
|
info.switch.e,
|
|
].entries()) {
|
|
compiled.keys.push({
|
|
id,
|
|
shape: "quarter-circle",
|
|
cornerRadius: 0,
|
|
size: [2, 0.6],
|
|
pos: [cx, cy],
|
|
rotate: 90 * i + 45,
|
|
});
|
|
}
|
|
if (info.switch.d !== undefined) {
|
|
compiled.keys.push({
|
|
id: info.switch.d,
|
|
shape: "square",
|
|
cornerRadius: 0.5,
|
|
size: [0.8, 0.8],
|
|
pos: [x + 0.6 + ox, y + 0.6 + oy],
|
|
rotate: 0,
|
|
});
|
|
}
|
|
|
|
x += 2 + ox;
|
|
maxHeight = Math.max(maxHeight, 2 + oy);
|
|
}
|
|
}
|
|
y += maxHeight;
|
|
compiled.size[0] = Math.max(compiled.size[0], x);
|
|
}
|
|
compiled.size[1] = y;
|
|
|
|
return compiled;
|
|
}
|