@thi.ng/imgui
Version:
Immediate mode GUI with flexible state handling & data only shape output
67 lines (66 loc) • 1.69 kB
JavaScript
import {
TESSELLATE_TRI_FAN,
groupFromTessellation,
tessellate
} from "@thi.ng/geom";
import { centroid } from "@thi.ng/geom/centroid";
import { circle } from "@thi.ng/geom/circle";
import { mod } from "@thi.ng/math/prec";
import { mapIndexed } from "@thi.ng/transducers/map-indexed";
import { add2 } from "@thi.ng/vectors/add";
import { hash } from "@thi.ng/vectors/hash";
import { Key } from "../api.js";
import { buttonRaw } from "./button.js";
import { textLabelRaw } from "./textlabel.js";
const radialMenu = ({
gui,
id,
x,
y,
r,
items,
info
}) => {
const n = items.length;
const key = hash([x, y, r, n, ~~gui.disabled]);
gui.registerID(id, key);
const cells = gui.resource(id, key, () => [
...mapIndexed((i, cell) => {
const p = add2(
null,
[-gui.textWidth(items[i]) >> 1, gui.theme.baseLine],
centroid(cell)
);
return [
cell,
hash(p),
textLabelRaw(p, gui.textColor(false), items[i]),
textLabelRaw(p, gui.textColor(true), items[i])
];
}, groupFromTessellation(tessellate(circle([x, y], r, { __samples: n }), [TESSELLATE_TRI_FAN])))
]);
let res;
let sel = -1;
for (let i = 0; i < n; i++) {
const cell = cells[i];
const _id = id + i;
buttonRaw(gui, _id, cell[0], cell[1], cell[2], cell[3], info?.[i]) && (res = i);
gui.focusID === _id && (sel = i);
}
if (sel !== -1) {
switch (gui.key) {
case Key.UP:
case Key.RIGHT:
gui.focusID = id + mod(sel + 1, n);
break;
case Key.DOWN:
case Key.LEFT:
gui.focusID = id + mod(sel - 1, n);
default:
}
}
return res;
};
export {
radialMenu
};