/
slider.ts
120 lines (117 loc) · 2.98 KB
/
slider.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import { Fn } from "@thi.ng/api";
import { pointInside, rect } from "@thi.ng/geom";
import {
clamp,
fit,
norm,
roundTo
} from "@thi.ng/math";
import { Key, KeyModifier, MouseButton } from "../api";
import { IMGUI } from "../gui";
import { textLabel } from "./textlabel";
import { tooltip } from "./tooltip";
const $ = (x: number, prec: number, min: number, max: number) =>
clamp(roundTo(x, prec), min, max);
export const slider = (
gui: IMGUI,
id: string,
x: number,
y: number,
w: number,
h: number,
min: number,
max: number,
prec: number,
val: number[],
i: number,
label?: string,
fmt?: Fn<number, string>,
info?: string
) => {
const theme = gui.theme;
const box = rect([x, y], [w, h]);
const hover = pointInside(box, gui.mouse);
let active = false;
if (hover) {
gui.hotID = id;
const aid = gui.activeID;
if ((aid === "" || aid === id) && gui.buttons == MouseButton.LEFT) {
gui.activeID = id;
active = true;
val[i] = $(
fit(gui.mouse[0], x, x + w - 1, min, max),
prec,
min,
max
);
if (gui.modifiers & KeyModifier.ALT) {
val.fill(val[i]);
}
}
info && tooltip(gui, info);
}
const focused = gui.requestFocus(id);
const v = val[i];
const normVal = norm(v, min, max);
const valueBox = rect([x, y], [1 + normVal * (w - 1), h], {
fill: gui.fgColor(hover)
});
box.attribs = {
fill: gui.bgColor(hover || focused),
stroke: gui.focusColor(id)
};
gui.add(
box,
valueBox,
textLabel(
[x + theme.pad, y + h / 2 + theme.baseLine],
gui.textColor(normVal > 0.25),
(label ? label + " " : "") + (fmt ? fmt(v) : v)
)
);
if (focused) {
switch (gui.key) {
case Key.TAB:
gui.switchFocus();
break;
case Key.UP:
case Key.DOWN: {
const step =
(gui.key === Key.UP ? prec : -prec) *
(gui.isShiftDown() ? 5 : 1);
val[i] = $(v + step, prec, min, max);
gui.isAltDown() && val.fill(val[i]);
return true;
}
default:
}
}
gui.lastID = id;
return active;
};
export const sliderGroup = (
gui: IMGUI,
id: string,
x: number,
y: number,
w: number,
h: number,
offX: number,
offY: number,
min: number,
max: number,
prec: number,
vals: number[],
label: string[],
fmt?: Fn<number, string>,
info: string[] = []
) => {
let res = false;
// prettier-ignore
for (let n = vals.length, i = 0; i < n; i++) {
res = slider(gui, `${id}-${i}`, x, y, w, h, min, max, prec, vals, i, label[i], fmt, info[i]) || res;
x += offX;
y += offY;
}
return res;
};