@thi.ng/imgui 2.2.12 → 2.2.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- package/README.md +1 -1
- package/api.js +94 -84
- package/behaviors/button.js +26 -22
- package/behaviors/dial.js +12 -4
- package/behaviors/slider.js +46 -43
- package/behaviors/text.js +75 -70
- package/components/button.js +64 -41
- package/components/dial.js +102 -52
- package/components/dropdown.js +62 -64
- package/components/icon-button.js +40 -31
- package/components/radial-menu.js +43 -37
- package/components/radio.js +19 -14
- package/components/ring.js +123 -79
- package/components/sliderh.js +96 -46
- package/components/sliderv.js +100 -53
- package/components/textfield.js +83 -44
- package/components/textlabel.js +28 -14
- package/components/toggle.js +45 -38
- package/components/tooltip.js +16 -6
- package/components/xypad.js +89 -73
- package/events.js +36 -47
- package/gui.js +400 -415
- package/hash.js +17 -45
- package/layout.js +4 -1
- package/package.json +16 -14
package/gui.js
CHANGED
|
@@ -1,418 +1,403 @@
|
|
|
1
1
|
import { set2 } from "@thi.ng/vectors/set";
|
|
2
|
-
import {
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
add(...els) {
|
|
399
|
-
this.layers[0].push(...els);
|
|
400
|
-
}
|
|
401
|
-
addOverlay(...els) {
|
|
402
|
-
this.layers[1].push(...els);
|
|
403
|
-
}
|
|
404
|
-
/**
|
|
405
|
-
* Returns hiccup representation of all shapes/text primitives
|
|
406
|
-
* created by components in the current frame.
|
|
407
|
-
*/
|
|
408
|
-
toHiccup() {
|
|
409
|
-
return [
|
|
410
|
-
"g",
|
|
411
|
-
{ font: this.theme.font },
|
|
412
|
-
...this.layers[0],
|
|
413
|
-
...this.layers[1],
|
|
414
|
-
];
|
|
415
|
-
}
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_THEME,
|
|
4
|
+
Key,
|
|
5
|
+
KeyModifier,
|
|
6
|
+
MouseButton,
|
|
7
|
+
NONE
|
|
8
|
+
} from "./api.js";
|
|
9
|
+
const defGUI = (opts) => new IMGUI(opts);
|
|
10
|
+
class IMGUI {
|
|
11
|
+
attribs;
|
|
12
|
+
layers;
|
|
13
|
+
mouse;
|
|
14
|
+
buttons;
|
|
15
|
+
key;
|
|
16
|
+
modifiers;
|
|
17
|
+
prevMouse;
|
|
18
|
+
prevButtons;
|
|
19
|
+
prevKey;
|
|
20
|
+
prevModifiers;
|
|
21
|
+
hotID;
|
|
22
|
+
activeID;
|
|
23
|
+
focusID;
|
|
24
|
+
lastID;
|
|
25
|
+
cursor;
|
|
26
|
+
t0;
|
|
27
|
+
time;
|
|
28
|
+
draw;
|
|
29
|
+
currIDs;
|
|
30
|
+
prevIDs;
|
|
31
|
+
themeStack;
|
|
32
|
+
disabledStack;
|
|
33
|
+
resources;
|
|
34
|
+
states;
|
|
35
|
+
sizes;
|
|
36
|
+
constructor(opts) {
|
|
37
|
+
this.mouse = [-1e3, -1e3];
|
|
38
|
+
this.prevMouse = [-1e3, -1e3];
|
|
39
|
+
this.key = this.prevKey = "";
|
|
40
|
+
this.buttons = this.prevButtons = this.modifiers = this.prevModifiers = 0;
|
|
41
|
+
this.hotID = this.activeID = this.focusID = this.lastID = "";
|
|
42
|
+
this.currIDs = /* @__PURE__ */ new Set();
|
|
43
|
+
this.prevIDs = /* @__PURE__ */ new Set();
|
|
44
|
+
this.resources = /* @__PURE__ */ new Map();
|
|
45
|
+
this.sizes = /* @__PURE__ */ new Map();
|
|
46
|
+
this.states = /* @__PURE__ */ new Map();
|
|
47
|
+
this.layers = [[], []];
|
|
48
|
+
this.attribs = {};
|
|
49
|
+
this.cursor = "default";
|
|
50
|
+
this.disabledStack = [false];
|
|
51
|
+
this.setTheme(opts.theme || {});
|
|
52
|
+
this.draw = true;
|
|
53
|
+
this.t0 = Date.now();
|
|
54
|
+
}
|
|
55
|
+
get theme() {
|
|
56
|
+
const stack = this.themeStack;
|
|
57
|
+
return stack[stack.length - 1];
|
|
58
|
+
}
|
|
59
|
+
get disabled() {
|
|
60
|
+
const stack = this.disabledStack;
|
|
61
|
+
return stack[stack.length - 1];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Clears all shape layers and resets theme / disabled stacks.
|
|
65
|
+
*/
|
|
66
|
+
clear() {
|
|
67
|
+
this.layers[0].length = 0;
|
|
68
|
+
this.layers[1].length = 0;
|
|
69
|
+
this.themeStack.length = 1;
|
|
70
|
+
this.disabledStack.length = 1;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Sets mouse position and current mouse button flags (i.e.
|
|
74
|
+
* `MouseEvent.buttons`).
|
|
75
|
+
*
|
|
76
|
+
* @param p -
|
|
77
|
+
* @param buttons -
|
|
78
|
+
*/
|
|
79
|
+
setMouse(p, buttons) {
|
|
80
|
+
set2(this.prevMouse, this.mouse);
|
|
81
|
+
set2(this.mouse, p);
|
|
82
|
+
this.prevButtons = this.buttons;
|
|
83
|
+
this.buttons = buttons;
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Sets internal key state from given key event details.
|
|
88
|
+
*
|
|
89
|
+
* @param e -
|
|
90
|
+
*/
|
|
91
|
+
setKey(e) {
|
|
92
|
+
if (e.type === "keydown") {
|
|
93
|
+
this.prevKey = this.key;
|
|
94
|
+
this.key = e.key;
|
|
95
|
+
}
|
|
96
|
+
this.prevModifiers = this.modifiers;
|
|
97
|
+
this.modifiers = ~~e.shiftKey * KeyModifier.SHIFT | ~~e.ctrlKey * KeyModifier.CONTROL | ~~e.metaKey * KeyModifier.META | ~~e.altKey * KeyModifier.ALT;
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Merges given theme settings with {@link DEFAULT_THEME} and resets theme
|
|
102
|
+
* stack.
|
|
103
|
+
*
|
|
104
|
+
* @param theme -
|
|
105
|
+
*/
|
|
106
|
+
setTheme(theme) {
|
|
107
|
+
this.themeStack = [{ ...DEFAULT_THEME, ...theme }];
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Merges given theme settings with current theme and pushes result
|
|
111
|
+
* on theme stack.
|
|
112
|
+
*
|
|
113
|
+
* IMPORTANT: Currently IMGUI only supports one font and ignores any
|
|
114
|
+
* font changes pushed on the theme stack.
|
|
115
|
+
*
|
|
116
|
+
* @param theme -
|
|
117
|
+
*/
|
|
118
|
+
beginTheme(theme) {
|
|
119
|
+
const stack = this.themeStack;
|
|
120
|
+
stack.push({ ...stack[stack.length - 1], ...theme });
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Removes current theme from stack (unless only one theme left).
|
|
124
|
+
*/
|
|
125
|
+
endTheme() {
|
|
126
|
+
__popIfNotLast(this.themeStack);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Applies component function with given theme, then restores
|
|
130
|
+
* previous theme and returns component result.
|
|
131
|
+
*
|
|
132
|
+
* @param theme -
|
|
133
|
+
* @param component -
|
|
134
|
+
*/
|
|
135
|
+
withTheme(theme, component) {
|
|
136
|
+
this.beginTheme(theme);
|
|
137
|
+
const res = component();
|
|
138
|
+
this.themeStack.pop();
|
|
139
|
+
return res;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Pushes given disabled component state flag on stack (default:
|
|
143
|
+
* true, i.e. disabled). Pass `false` to temporarily enable
|
|
144
|
+
* components.
|
|
145
|
+
*
|
|
146
|
+
* @param disabled -
|
|
147
|
+
*/
|
|
148
|
+
beginDisabled(disabled = true) {
|
|
149
|
+
this.disabledStack.push(disabled);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Removes current disabled flag from stack (unless only one theme left).
|
|
153
|
+
*/
|
|
154
|
+
endDisabled() {
|
|
155
|
+
__popIfNotLast(this.disabledStack);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Applies component function with given disabled flag, then
|
|
159
|
+
* restores previous disabled state and returns component result.
|
|
160
|
+
*
|
|
161
|
+
* @param disabled -
|
|
162
|
+
* @param component -
|
|
163
|
+
*/
|
|
164
|
+
withDisabled(disabled, component) {
|
|
165
|
+
this.disabledStack.push(disabled);
|
|
166
|
+
const res = component();
|
|
167
|
+
this.disabledStack.pop();
|
|
168
|
+
return res;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Sets `focusID` to given `id` if the component can receive focus.
|
|
172
|
+
* Returns true if component is focused.
|
|
173
|
+
*
|
|
174
|
+
* @param id -
|
|
175
|
+
*/
|
|
176
|
+
requestFocus(id) {
|
|
177
|
+
if (this.disabled)
|
|
178
|
+
return false;
|
|
179
|
+
if (this.focusID === "" || this.activeID === id) {
|
|
180
|
+
this.focusID = id;
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
return this.focusID === id;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Attempts to switch focus to next, or if Shift is pressed, to
|
|
187
|
+
* previous component. This is meant be called ONLY from component
|
|
188
|
+
* key handlers.
|
|
189
|
+
*/
|
|
190
|
+
switchFocus() {
|
|
191
|
+
this.focusID = this.isShiftDown() ? this.lastID : "";
|
|
192
|
+
this.key = "";
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Returns true if left mouse button is pressed.
|
|
196
|
+
*/
|
|
197
|
+
isMouseDown() {
|
|
198
|
+
return (this.buttons & MouseButton.LEFT) > 0;
|
|
199
|
+
}
|
|
200
|
+
isShiftDown() {
|
|
201
|
+
return (this.modifiers & KeyModifier.SHIFT) > 0;
|
|
202
|
+
}
|
|
203
|
+
isControlDown() {
|
|
204
|
+
return (this.modifiers & KeyModifier.CONTROL) > 0;
|
|
205
|
+
}
|
|
206
|
+
isMetaDown() {
|
|
207
|
+
return (this.modifiers & KeyModifier.META) > 0;
|
|
208
|
+
}
|
|
209
|
+
isAltDown() {
|
|
210
|
+
return (this.modifiers & KeyModifier.ALT) > 0;
|
|
211
|
+
}
|
|
212
|
+
isPrevMouseDown() {
|
|
213
|
+
return (this.prevButtons & MouseButton.LEFT) > 0;
|
|
214
|
+
}
|
|
215
|
+
isPrevShiftDown() {
|
|
216
|
+
return (this.prevModifiers & KeyModifier.SHIFT) > 0;
|
|
217
|
+
}
|
|
218
|
+
isPrevControlDown() {
|
|
219
|
+
return (this.prevModifiers & KeyModifier.CONTROL) > 0;
|
|
220
|
+
}
|
|
221
|
+
isPrevMetaDown() {
|
|
222
|
+
return (this.prevModifiers & KeyModifier.META) > 0;
|
|
223
|
+
}
|
|
224
|
+
isPrevAltDown() {
|
|
225
|
+
return (this.prevModifiers & KeyModifier.ALT) > 0;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Prepares IMGUI for next frame:
|
|
229
|
+
*
|
|
230
|
+
* - Resets `hotID`, `cursor`
|
|
231
|
+
* - Resets theme & disabled stacks
|
|
232
|
+
* - Clears all draw layers
|
|
233
|
+
* - Updates elapsed time.
|
|
234
|
+
*
|
|
235
|
+
* By default all components will emit draw shapes, however this can
|
|
236
|
+
* be disabled by passing `false` as argument. This is useful for
|
|
237
|
+
* use cases where the GUI is not updated at high frame rates and so
|
|
238
|
+
* would require two invocations per update cycle for immediate
|
|
239
|
+
* visual feedback:
|
|
240
|
+
*
|
|
241
|
+
* ```
|
|
242
|
+
* gui.begin(false); // update state only, no draw
|
|
243
|
+
* updateMyGUI();
|
|
244
|
+
* gui.end();
|
|
245
|
+
* gui.begin(true); // run once more, with draw enabled (default)
|
|
246
|
+
* updateMyGUI();
|
|
247
|
+
* gui.end();
|
|
248
|
+
* ```
|
|
249
|
+
*
|
|
250
|
+
* @param draw -
|
|
251
|
+
*/
|
|
252
|
+
begin(draw = true) {
|
|
253
|
+
this.hotID = "";
|
|
254
|
+
this.cursor = "default";
|
|
255
|
+
this.draw = draw;
|
|
256
|
+
this.clear();
|
|
257
|
+
this.time = (Date.now() - this.t0) * 1e-3;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Performs end-of-frame handling & component cache cleanup. Also
|
|
261
|
+
* removes cached state and resources of all unused components.
|
|
262
|
+
*/
|
|
263
|
+
end() {
|
|
264
|
+
if (!this.buttons) {
|
|
265
|
+
this.activeID = "";
|
|
266
|
+
} else {
|
|
267
|
+
if (this.activeID === "") {
|
|
268
|
+
this.activeID = NONE;
|
|
269
|
+
this.focusID = NONE;
|
|
270
|
+
this.lastID = "";
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
this.key === Key.TAB && (this.focusID = "");
|
|
274
|
+
this.key = "";
|
|
275
|
+
this.gc();
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Garbage collect unused component state / resources.
|
|
279
|
+
*/
|
|
280
|
+
gc() {
|
|
281
|
+
const { currIDs, prevIDs } = this;
|
|
282
|
+
for (let id of prevIDs) {
|
|
283
|
+
if (!currIDs.has(id)) {
|
|
284
|
+
this.resources.delete(id);
|
|
285
|
+
this.sizes.delete(id);
|
|
286
|
+
this.states.delete(id);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
this.prevIDs = currIDs;
|
|
290
|
+
this.currIDs = prevIDs;
|
|
291
|
+
prevIDs.clear();
|
|
292
|
+
}
|
|
293
|
+
bgColor(hover) {
|
|
294
|
+
return this.disabled ? this.theme.bgDisabled : hover ? this.theme.bgHover : this.theme.bg;
|
|
295
|
+
}
|
|
296
|
+
fgColor(hover) {
|
|
297
|
+
return this.disabled ? this.theme.fgDisabled : hover ? this.theme.fgHover : this.theme.fg;
|
|
298
|
+
}
|
|
299
|
+
textColor(hover) {
|
|
300
|
+
return this.disabled ? this.theme.textDisabled : hover ? this.theme.textHover : this.theme.text;
|
|
301
|
+
}
|
|
302
|
+
focusColor(id) {
|
|
303
|
+
return this.focusID === id ? this.theme.focus : void 0;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Returns pixel width of given string based on current theme's font
|
|
307
|
+
* settings.
|
|
308
|
+
*
|
|
309
|
+
* IMPORTANT: Currently only monospace fonts are supported.
|
|
310
|
+
*
|
|
311
|
+
* @param txt -
|
|
312
|
+
*/
|
|
313
|
+
textWidth(txt) {
|
|
314
|
+
return this.theme.charWidth * txt.length;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Marks given component ID as used and checks `hash` to determine
|
|
318
|
+
* if the component's resource cache should be cleared. This hash
|
|
319
|
+
* value should be based on any values (e.g. layout info) which
|
|
320
|
+
* might invalidate cached resources.
|
|
321
|
+
*
|
|
322
|
+
* @param id -
|
|
323
|
+
* @param hash -
|
|
324
|
+
*/
|
|
325
|
+
registerID(id, hash) {
|
|
326
|
+
this.currIDs.add(id);
|
|
327
|
+
if (this.sizes.get(id) !== hash) {
|
|
328
|
+
this.sizes.set(id, hash);
|
|
329
|
+
this.resources.delete(id);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Attempts to retrieve cached resource for given component `id` and
|
|
334
|
+
* resource `hash`. If unsuccessful, calls resource `ctor` function
|
|
335
|
+
* to create it, caches result and returns it.
|
|
336
|
+
*
|
|
337
|
+
* {@link IMGUI.registerID}
|
|
338
|
+
*
|
|
339
|
+
* @param id -
|
|
340
|
+
* @param hash -
|
|
341
|
+
* @param ctor -
|
|
342
|
+
*/
|
|
343
|
+
resource(id, hash, ctor) {
|
|
344
|
+
let res;
|
|
345
|
+
let c = this.resources.get(id);
|
|
346
|
+
!c && this.resources.set(id, c = /* @__PURE__ */ new Map());
|
|
347
|
+
return c.get(hash) || (c.set(hash, res = ctor()), res);
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Attempts to retrieve cached component state for given `id`. If
|
|
351
|
+
* unsuccessful, calls state `ctor` function, caches result and
|
|
352
|
+
* returns it.
|
|
353
|
+
*
|
|
354
|
+
* @param id -
|
|
355
|
+
* @param ctor -
|
|
356
|
+
*/
|
|
357
|
+
state(id, ctor) {
|
|
358
|
+
let res = this.states.get(id);
|
|
359
|
+
return res !== void 0 ? res : (this.states.set(id, res = ctor()), res);
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Stores / overrides given local state value for component `id` in
|
|
363
|
+
* cache.
|
|
364
|
+
*
|
|
365
|
+
* @param id -
|
|
366
|
+
* @param state -
|
|
367
|
+
*/
|
|
368
|
+
setState(id, state) {
|
|
369
|
+
this.states.set(id, state);
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Sets cursor property to given `id`. This setting is cleared at
|
|
373
|
+
* the beginning of each frame (default value: "default").
|
|
374
|
+
*
|
|
375
|
+
* @param id -
|
|
376
|
+
*/
|
|
377
|
+
setCursor(id) {
|
|
378
|
+
this.cursor = id;
|
|
379
|
+
}
|
|
380
|
+
add(...els) {
|
|
381
|
+
this.layers[0].push(...els);
|
|
382
|
+
}
|
|
383
|
+
addOverlay(...els) {
|
|
384
|
+
this.layers[1].push(...els);
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Returns hiccup representation of all shapes/text primitives
|
|
388
|
+
* created by components in the current frame.
|
|
389
|
+
*/
|
|
390
|
+
toHiccup() {
|
|
391
|
+
return [
|
|
392
|
+
"g",
|
|
393
|
+
{ font: this.theme.font },
|
|
394
|
+
...this.layers[0],
|
|
395
|
+
...this.layers[1]
|
|
396
|
+
];
|
|
397
|
+
}
|
|
416
398
|
}
|
|
417
|
-
/** @internal */
|
|
418
399
|
const __popIfNotLast = (stack) => stack.length > 1 && stack.pop();
|
|
400
|
+
export {
|
|
401
|
+
IMGUI,
|
|
402
|
+
defGUI
|
|
403
|
+
};
|