-
-
Notifications
You must be signed in to change notification settings - Fork 151
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(imgui): add dial widget, extract key handlers, update layout
- add dial/diaRaw() widgets - extract button & slider value updaters / key handlers - add GridLayout.nextSquare() - update button, toggle, sliders & xyPad widgets
- Loading branch information
1 parent
7e0bfeb
commit d3d2b27
Showing
12 changed files
with
314 additions
and
150 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { Key } from "../api"; | ||
import { IMGUI } from "../gui"; | ||
|
||
export const handleButtonKeys = (gui: IMGUI) => { | ||
switch (gui.key) { | ||
case Key.TAB: | ||
gui.switchFocus(); | ||
break; | ||
case Key.ENTER: | ||
case Key.SPACE: | ||
return true; | ||
default: | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { clamp, roundTo } from "@thi.ng/math"; | ||
import { | ||
add2, | ||
clamp2, | ||
round2, | ||
Vec | ||
} from "@thi.ng/vectors"; | ||
import { Key } from "../api"; | ||
import { IMGUI } from "../gui"; | ||
|
||
export const slider1Val = (x: number, min: number, max: number, prec: number) => | ||
clamp(roundTo(x, prec), min, max); | ||
|
||
export const slider2Val = (v: Vec, min: Vec, max: Vec, prec: number) => | ||
clamp2(v, round2(v, v, prec), min, max); | ||
|
||
export const handleSlider1Keys = ( | ||
gui: IMGUI, | ||
min: number, | ||
max: number, | ||
prec: number, | ||
val: number[], | ||
i = 0 | ||
) => { | ||
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] = slider1Val(val[i] + step, min, max, prec); | ||
gui.isAltDown() && val.fill(val[i]); | ||
return true; | ||
} | ||
default: | ||
} | ||
}; | ||
|
||
export const handleSlider2Keys = ( | ||
gui: IMGUI, | ||
min: Vec, | ||
max: Vec, | ||
prec: number, | ||
val: Vec, | ||
yUp: boolean | ||
) => { | ||
switch (gui.key) { | ||
case Key.TAB: | ||
gui.switchFocus(); | ||
break; | ||
case Key.LEFT: | ||
case Key.RIGHT: { | ||
const step = | ||
(gui.key === Key.RIGHT ? prec : -prec) * | ||
(gui.isShiftDown() ? 5 : 1); | ||
slider2Val(add2(val, val, [step, 0]), min, max, prec); | ||
return true; | ||
} | ||
case Key.UP: | ||
case Key.DOWN: { | ||
const step = | ||
(gui.key === Key.UP ? prec : -prec) * | ||
(yUp ? 1 : -1) * | ||
(gui.isShiftDown() ? 5 : 1); | ||
slider2Val(add2(val, val, [0, step]), min, max, prec); | ||
return true; | ||
} | ||
default: | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
import { Fn } from "@thi.ng/api"; | ||
import { polygon } from "@thi.ng/geom"; | ||
import { pointInCircle } from "@thi.ng/geom-isec"; | ||
import { | ||
fit, | ||
fitClamped, | ||
HALF_PI, | ||
mix, | ||
norm, | ||
PI, | ||
TAU | ||
} from "@thi.ng/math"; | ||
import { map, normRange } from "@thi.ng/transducers"; | ||
import { | ||
cartesian2, | ||
heading, | ||
sub2, | ||
Vec | ||
} from "@thi.ng/vectors"; | ||
import { KeyModifier, LayoutBox, MouseButton } from "../api"; | ||
import { handleSlider1Keys, slider1Val } from "../behaviors/slider"; | ||
import { IMGUI } from "../gui"; | ||
import { GridLayout, isLayout } from "../layout"; | ||
import { textLabelRaw } from "./textlabel"; | ||
import { tooltipRaw } from "./tooltip"; | ||
|
||
const arcVerts = ( | ||
o: Vec, | ||
r: number, | ||
start: number, | ||
end: number, | ||
thetaRes = 12 | ||
): Iterable<Vec> => | ||
r > 1 | ||
? map( | ||
(t) => cartesian2(null, [r, mix(start, end, t)], o), | ||
normRange( | ||
Math.max(1, Math.abs(end - start) / (PI / thetaRes)) | 0 | ||
) | ||
) | ||
: [o]; | ||
|
||
export const dial = ( | ||
gui: IMGUI, | ||
layout: GridLayout | LayoutBox, | ||
id: string, | ||
min: number, | ||
max: number, | ||
prec: number, | ||
val: number[], | ||
i: number, | ||
rscale: number, | ||
label?: string, | ||
fmt?: Fn<number, string>, | ||
info?: string | ||
) => { | ||
const { x, y, w, h, ch } = isLayout(layout) ? layout.nextSquare() : layout; | ||
return dialRaw( | ||
gui, | ||
id, | ||
x, | ||
y, | ||
w, | ||
h, | ||
min, | ||
max, | ||
prec, | ||
val, | ||
i, | ||
rscale, | ||
gui.theme.pad, | ||
h + ch / 2 + gui.theme.baseLine, | ||
label, | ||
fmt, | ||
info | ||
); | ||
}; | ||
|
||
export const dialRaw = ( | ||
gui: IMGUI, | ||
id: string, | ||
x: number, | ||
y: number, | ||
w: number, | ||
h: number, | ||
min: number, | ||
max: number, | ||
prec: number, | ||
val: number[], | ||
i: number, | ||
rscale: number, | ||
lx: number, | ||
ly: number, | ||
label?: string, | ||
fmt?: Fn<number, string>, | ||
info?: string | ||
) => { | ||
const r = Math.min(w, h) / 2; | ||
const pos = [x + w / 2, y + h / 2]; | ||
const hover = pointInCircle(gui.mouse, pos, r); | ||
let active = false; | ||
const thetaGap = PI / 3; | ||
const startTheta = HALF_PI + thetaGap / 2; | ||
const endTheta = HALF_PI + TAU - thetaGap / 2; | ||
if (hover) { | ||
gui.hotID = id; | ||
const aid = gui.activeID; | ||
if ((aid === "" || aid === id) && gui.buttons == MouseButton.LEFT) { | ||
gui.activeID = id; | ||
active = true; | ||
let theta = heading(sub2([], gui.mouse, pos)) - startTheta; | ||
theta < -0.5 && (theta += TAU); | ||
val[i] = slider1Val( | ||
fit(Math.min(theta / (TAU - thetaGap)), 0, 1, min, max), | ||
min, | ||
max, | ||
prec | ||
); | ||
if (gui.modifiers & KeyModifier.ALT) { | ||
val.fill(val[i]); | ||
} | ||
} | ||
info && tooltipRaw(gui, info); | ||
} | ||
const focused = gui.requestFocus(id); | ||
const v = val[i]; | ||
const valTheta = startTheta + (TAU - thetaGap) * norm(v, min, max); | ||
const r2 = r * rscale; | ||
// adaptive arc resolution | ||
const res = fitClamped(r, 15, 60, 12, 30); | ||
const bgShape = polygon( | ||
[ | ||
...arcVerts(pos, r, startTheta, endTheta, res), | ||
...arcVerts(pos, r2, endTheta, startTheta, res) | ||
], | ||
{ fill: gui.bgColor(hover || focused), stroke: gui.focusColor(id) } | ||
); | ||
const valShape = polygon( | ||
[ | ||
...arcVerts(pos, r, startTheta, valTheta, res), | ||
...arcVerts(pos, r2, valTheta, startTheta, res) | ||
], | ||
{ fill: gui.fgColor(hover) } | ||
); | ||
gui.add( | ||
bgShape, | ||
valShape, | ||
textLabelRaw( | ||
[x + lx, y + ly], | ||
gui.textColor(false), | ||
(label ? label + " " : "") + (fmt ? fmt(v) : v) | ||
) | ||
); | ||
if (focused && handleSlider1Keys(gui, min, max, prec, val, i)) { | ||
return true; | ||
} | ||
gui.lastID = id; | ||
return active; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.