imxc 0.5.4 → 0.6.0
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/dist/compile.d.ts +8 -0
- package/dist/compile.js +285 -25
- package/dist/components.js +597 -45
- package/dist/diagnostics.js +3 -2
- package/dist/emitter.d.ts +6 -3
- package/dist/emitter.js +1454 -322
- package/dist/index.js +34 -7
- package/dist/init.d.ts +7 -1
- package/dist/init.js +43 -455
- package/dist/ir.d.ts +437 -5
- package/dist/lowering.d.ts +4 -3
- package/dist/lowering.js +770 -57
- package/dist/parser.d.ts +1 -0
- package/dist/templates/async.d.ts +1 -0
- package/dist/templates/async.js +228 -0
- package/dist/templates/custom.d.ts +15 -0
- package/dist/templates/custom.js +945 -0
- package/dist/templates/filedialog.d.ts +1 -0
- package/dist/templates/filedialog.js +216 -0
- package/dist/templates/hotreload.d.ts +1 -0
- package/dist/templates/hotreload.js +400 -0
- package/dist/templates/index.d.ts +16 -0
- package/dist/templates/index.js +553 -0
- package/dist/templates/minimal.d.ts +1 -0
- package/dist/templates/minimal.js +165 -0
- package/dist/templates/networking.d.ts +1 -0
- package/dist/templates/networking.js +244 -0
- package/dist/templates/persistence.d.ts +1 -0
- package/dist/templates/persistence.js +238 -0
- package/dist/validator.d.ts +1 -0
- package/dist/validator.js +51 -22
- package/dist/watch.d.ts +2 -1
- package/dist/watch.js +21 -4
- package/package.json +2 -4
package/dist/emitter.js
CHANGED
|
@@ -2,10 +2,15 @@ const INDENT = ' ';
|
|
|
2
2
|
let currentCompName = '';
|
|
3
3
|
let currentBoundProps = new Set();
|
|
4
4
|
let allBoundProps = new Map();
|
|
5
|
+
let sourceMapEnabled = true;
|
|
5
6
|
function emitLocComment(loc, tag, lines, indent) {
|
|
6
|
-
if (loc)
|
|
7
|
-
|
|
7
|
+
if (!loc)
|
|
8
|
+
return;
|
|
9
|
+
if (sourceMapEnabled) {
|
|
10
|
+
const filename = loc.file.replace(/\\/g, '/');
|
|
11
|
+
lines.push(`#line ${loc.line} "${filename}"`);
|
|
8
12
|
}
|
|
13
|
+
lines.push(`${indent}// ${loc.file}:${loc.line} <${tag}>`);
|
|
9
14
|
}
|
|
10
15
|
function cppType(t) {
|
|
11
16
|
switch (t) {
|
|
@@ -14,12 +19,16 @@ function cppType(t) {
|
|
|
14
19
|
case 'bool': return 'bool';
|
|
15
20
|
case 'string': return 'std::string';
|
|
16
21
|
case 'color': return 'std::array<float, 4>';
|
|
22
|
+
case 'int_array': return 'std::array<int, 4>';
|
|
17
23
|
}
|
|
18
24
|
}
|
|
19
25
|
function cppPropType(t) {
|
|
20
26
|
if (t === 'callback')
|
|
21
27
|
return 'std::function<void()>';
|
|
22
|
-
|
|
28
|
+
if (t === 'int' || t === 'float' || t === 'bool' || t === 'string' || t === 'color' || t === 'int_array') {
|
|
29
|
+
return cppType(t);
|
|
30
|
+
}
|
|
31
|
+
return t;
|
|
23
32
|
}
|
|
24
33
|
/**
|
|
25
34
|
* Ensure a string expression is a const char*.
|
|
@@ -38,33 +47,50 @@ function asCharPtr(expr) {
|
|
|
38
47
|
}
|
|
39
48
|
/**
|
|
40
49
|
* For directBind emitters: if the valueExpr references a bound prop (pointer),
|
|
41
|
-
* return
|
|
42
|
-
* blocks the post-processing regex lookbehind from dereferencing again).
|
|
50
|
+
* return the correct address expression for nested bound props.
|
|
43
51
|
* Otherwise, emit &expr.
|
|
44
52
|
*/
|
|
45
53
|
function emitDirectBindPtr(valueExpr) {
|
|
46
|
-
const
|
|
47
|
-
if (
|
|
48
|
-
return
|
|
54
|
+
const boundExpr = emitBoundValueExpr(valueExpr);
|
|
55
|
+
if (boundExpr !== valueExpr) {
|
|
56
|
+
return `&${boundExpr}`;
|
|
49
57
|
}
|
|
50
58
|
return `&${valueExpr}`;
|
|
51
59
|
}
|
|
60
|
+
function boundPropName(valueExpr) {
|
|
61
|
+
return valueExpr.startsWith('props.') ? valueExpr.slice(6).split('.')[0].split('[')[0] : '';
|
|
62
|
+
}
|
|
63
|
+
function emitBoundValueExpr(valueExpr) {
|
|
64
|
+
const propName = boundPropName(valueExpr);
|
|
65
|
+
if (!currentBoundProps.has(propName)) {
|
|
66
|
+
return valueExpr;
|
|
67
|
+
}
|
|
68
|
+
const prefix = `props.${propName}`;
|
|
69
|
+
const suffix = valueExpr.slice(prefix.length);
|
|
70
|
+
if (suffix.length === 0) {
|
|
71
|
+
return `(*props.${propName})`;
|
|
72
|
+
}
|
|
73
|
+
return `((*props.${propName})${suffix})`;
|
|
74
|
+
}
|
|
52
75
|
function emitImVec4(arrayStr) {
|
|
53
76
|
const parts = arrayStr.split(',').map(s => {
|
|
54
77
|
const v = s.trim();
|
|
55
|
-
return v.includes('.') ? `${v}f` : `${v}.0f
|
|
78
|
+
return /^-?\d+(\.\d+)?$/.test(v) ? (v.includes('.') ? `${v}f` : `${v}.0f`) : v;
|
|
56
79
|
});
|
|
57
80
|
return `ImVec4(${parts.join(', ')})`;
|
|
58
81
|
}
|
|
59
82
|
function emitImVec2(arrayStr) {
|
|
60
83
|
const parts = arrayStr.split(',').map(s => {
|
|
61
84
|
const v = s.trim();
|
|
62
|
-
return v.includes('.') ? `${v}f` : `${v}.0f
|
|
85
|
+
return /^-?\d+(\.\d+)?$/.test(v) ? (v.includes('.') ? `${v}f` : `${v}.0f`) : v;
|
|
63
86
|
});
|
|
64
87
|
return `ImVec2(${parts.join(', ')})`;
|
|
65
88
|
}
|
|
66
89
|
function emitFloat(val) {
|
|
67
|
-
|
|
90
|
+
const trimmed = val.trim();
|
|
91
|
+
if (!/^-?\d+(\.\d+)?$/.test(trimmed))
|
|
92
|
+
return trimmed;
|
|
93
|
+
return trimmed.includes('.') ? `${trimmed}F` : `${trimmed}.0F`;
|
|
68
94
|
}
|
|
69
95
|
function findDockLayout(nodes) {
|
|
70
96
|
for (const node of nodes) {
|
|
@@ -111,7 +137,7 @@ function emitDockSetupFunction(layout, compName, lines) {
|
|
|
111
137
|
* Emit a .gen.h header for a component that has props.
|
|
112
138
|
* Contains the props struct and function forward declaration.
|
|
113
139
|
*/
|
|
114
|
-
export function emitComponentHeader(comp, sourceFile, boundProps) {
|
|
140
|
+
export function emitComponentHeader(comp, sourceFile, boundProps, sharedPropsType, resolvedBoundTypes) {
|
|
115
141
|
const lines = [];
|
|
116
142
|
if (sourceFile) {
|
|
117
143
|
lines.push(`// Generated from ${sourceFile} by imxc`);
|
|
@@ -121,26 +147,37 @@ export function emitComponentHeader(comp, sourceFile, boundProps) {
|
|
|
121
147
|
lines.push('#include <imx/renderer.h>');
|
|
122
148
|
lines.push('#include <functional>');
|
|
123
149
|
lines.push('#include <string>');
|
|
150
|
+
if (sharedPropsType) {
|
|
151
|
+
lines.push(`#include "${sharedPropsType}.h"`);
|
|
152
|
+
}
|
|
124
153
|
lines.push('');
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
154
|
+
if (comp.params.length > 0) {
|
|
155
|
+
// Props struct
|
|
156
|
+
lines.push(`struct ${comp.name}Props {`);
|
|
157
|
+
for (const p of comp.params) {
|
|
158
|
+
if (boundProps && boundProps.has(p.name)) {
|
|
159
|
+
// Use resolved C++ type from parent interface if available (e.g. float instead of int)
|
|
160
|
+
const actualType = resolvedBoundTypes?.get(p.name) ?? cppPropType(p.type);
|
|
161
|
+
lines.push(`${INDENT}${actualType}* ${p.name} = nullptr;`);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
lines.push(`${INDENT}${cppPropType(p.type)} ${p.name};`);
|
|
165
|
+
}
|
|
133
166
|
}
|
|
167
|
+
lines.push('};');
|
|
168
|
+
lines.push('');
|
|
169
|
+
lines.push(`void ${comp.name}_render(imx::RenderContext& ctx, ${comp.name}Props& props);`);
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
// Propless component — just the function forward declaration
|
|
173
|
+
lines.push(`void ${comp.name}_render(imx::RenderContext& ctx);`);
|
|
134
174
|
}
|
|
135
|
-
lines.push('};');
|
|
136
|
-
lines.push('');
|
|
137
|
-
// Function forward declaration
|
|
138
|
-
lines.push(`void ${comp.name}_render(imx::RenderContext& ctx, ${comp.name}Props& props);`);
|
|
139
175
|
lines.push('');
|
|
140
176
|
return lines.join('\n');
|
|
141
177
|
}
|
|
142
|
-
export function emitComponent(comp, imports, sourceFile, boundProps, boundPropsMap) {
|
|
178
|
+
export function emitComponent(comp, imports, sourceFile, boundProps, boundPropsMap, options) {
|
|
143
179
|
const lines = [];
|
|
180
|
+
sourceMapEnabled = options?.sourceMap ?? true;
|
|
144
181
|
// Reset counters for each component
|
|
145
182
|
styleCounter = 0;
|
|
146
183
|
customComponentCounter = 0;
|
|
@@ -149,8 +186,10 @@ export function emitComponent(comp, imports, sourceFile, boundProps, boundPropsM
|
|
|
149
186
|
listBoxCounter = 0;
|
|
150
187
|
nativeWidgetCounter = 0;
|
|
151
188
|
plotCounter = 0;
|
|
189
|
+
widgetTempCounter = 0;
|
|
152
190
|
dragDropSourceStack.length = 0;
|
|
153
191
|
dragDropTargetStack.length = 0;
|
|
192
|
+
collapsingHeaderOnCloseStack.length = 0;
|
|
154
193
|
currentCompName = comp.name;
|
|
155
194
|
currentBoundProps = boundProps ?? new Set();
|
|
156
195
|
allBoundProps = boundPropsMap ?? new Map();
|
|
@@ -191,6 +230,12 @@ export function emitComponent(comp, imports, sourceFile, boundProps, boundPropsM
|
|
|
191
230
|
if (hasColorType) {
|
|
192
231
|
lines.push('#include <array>');
|
|
193
232
|
}
|
|
233
|
+
// Include imported component headers
|
|
234
|
+
if (imports && imports.length > 0) {
|
|
235
|
+
for (const imp of imports) {
|
|
236
|
+
lines.push(`#include "${imp.headerFile}"`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
194
239
|
// Embed image includes
|
|
195
240
|
const embedKeysProps = collectEmbedKeys(comp.body);
|
|
196
241
|
for (const key of embedKeysProps) {
|
|
@@ -241,7 +286,9 @@ export function emitComponent(comp, imports, sourceFile, boundProps, boundPropsM
|
|
|
241
286
|
? `std::string(${slot.initialValue})`
|
|
242
287
|
: slot.type === 'color'
|
|
243
288
|
? `std::array<float, 4>${slot.initialValue}`
|
|
244
|
-
: slot.
|
|
289
|
+
: slot.type === 'int_array'
|
|
290
|
+
? `std::array<int, 4>${slot.initialValue}`
|
|
291
|
+
: slot.initialValue;
|
|
245
292
|
lines.push(`${INDENT}auto ${slot.name} = ctx.use_state<${cppType(slot.type)}>(${initVal}, ${slot.index});`);
|
|
246
293
|
}
|
|
247
294
|
if (comp.stateSlots.length > 0) {
|
|
@@ -254,6 +301,8 @@ export function emitComponent(comp, imports, sourceFile, boundProps, boundPropsM
|
|
|
254
301
|
for (let i = 0; i < lines.length; i++) {
|
|
255
302
|
if (lines[i].trimStart().startsWith('//'))
|
|
256
303
|
continue;
|
|
304
|
+
if (lines[i].trimStart().startsWith('#line'))
|
|
305
|
+
continue;
|
|
257
306
|
for (const prop of currentBoundProps) {
|
|
258
307
|
// Replace props.X reads with (*props.X) — but not &props.X or *props.X (already handled)
|
|
259
308
|
const pattern = new RegExp(`(?<![&*])\\bprops\\.${prop}\\b`, 'g');
|
|
@@ -265,12 +314,37 @@ export function emitComponent(comp, imports, sourceFile, boundProps, boundPropsM
|
|
|
265
314
|
lines.push('');
|
|
266
315
|
return lines.join('\n');
|
|
267
316
|
}
|
|
268
|
-
export function emitRoot(rootName, stateCount, bufferCount, sourceFile, propsType, namedPropsType) {
|
|
317
|
+
export function emitRoot(rootName, stateCount, bufferCount, sourceFile, propsType, namedPropsType, fontDeclarations) {
|
|
269
318
|
const lines = [];
|
|
319
|
+
const fonts = fontDeclarations ?? [];
|
|
270
320
|
if (sourceFile) {
|
|
271
321
|
lines.push(`// Generated from ${sourceFile} by imxc`);
|
|
272
322
|
}
|
|
273
323
|
lines.push('#include <imx/runtime.h>');
|
|
324
|
+
// Font embed includes and init function
|
|
325
|
+
if (fonts.length > 0) {
|
|
326
|
+
lines.push('#include <imx/renderer.h>');
|
|
327
|
+
for (const f of fonts) {
|
|
328
|
+
if (f.embed && f.embedKey) {
|
|
329
|
+
lines.push(`#include "${f.embedKey}.embed.h"`);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
lines.push('');
|
|
333
|
+
lines.push('void _imx_load_fonts() {');
|
|
334
|
+
lines.push(`${INDENT}static bool done = false;`);
|
|
335
|
+
lines.push(`${INDENT}if (done) return;`);
|
|
336
|
+
lines.push(`${INDENT}done = true;`);
|
|
337
|
+
for (const f of fonts) {
|
|
338
|
+
if (f.embed && f.embedKey) {
|
|
339
|
+
lines.push(`${INDENT}imx::load_font_embedded("${f.name}", ${f.embedKey}_data, ${f.embedKey}_size, ${f.size});`);
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
lines.push(`${INDENT}imx::load_font("${f.name}", "${f.src}", ${f.size});`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
lines.push('}');
|
|
346
|
+
lines.push('');
|
|
347
|
+
}
|
|
274
348
|
if (propsType) {
|
|
275
349
|
if (namedPropsType) {
|
|
276
350
|
// Named interface type (e.g. AppState defined in user code).
|
|
@@ -295,6 +369,9 @@ export function emitRoot(rootName, stateCount, bufferCount, sourceFile, propsTyp
|
|
|
295
369
|
lines.push(`void render_root(Runtime& runtime, ${propsType}& state) {`);
|
|
296
370
|
}
|
|
297
371
|
lines.push(`${INDENT}auto& ctx = runtime.begin_frame();`);
|
|
372
|
+
if (fonts.length > 0) {
|
|
373
|
+
lines.push(`${INDENT}_imx_load_fonts();`);
|
|
374
|
+
}
|
|
298
375
|
lines.push(`${INDENT}ctx.begin_instance("${rootName}", 0, ${stateCount}, ${bufferCount});`);
|
|
299
376
|
lines.push(`${INDENT}${rootName}_render(ctx, state);`);
|
|
300
377
|
lines.push(`${INDENT}ctx.end_instance();`);
|
|
@@ -309,6 +386,9 @@ export function emitRoot(rootName, stateCount, bufferCount, sourceFile, propsTyp
|
|
|
309
386
|
lines.push('namespace imx {');
|
|
310
387
|
lines.push('void render_root(Runtime& runtime) {');
|
|
311
388
|
lines.push(`${INDENT}auto& ctx = runtime.begin_frame();`);
|
|
389
|
+
if (fonts.length > 0) {
|
|
390
|
+
lines.push(`${INDENT}_imx_load_fonts();`);
|
|
391
|
+
}
|
|
312
392
|
lines.push(`${INDENT}ctx.begin_instance("${rootName}", 0, ${stateCount}, ${bufferCount});`);
|
|
313
393
|
lines.push(`${INDENT}${rootName}_render(ctx);`);
|
|
314
394
|
lines.push(`${INDENT}ctx.end_instance();`);
|
|
@@ -339,6 +419,18 @@ function emitNode(node, lines, depth) {
|
|
|
339
419
|
case 'button':
|
|
340
420
|
emitButton(node, lines, indent, depth);
|
|
341
421
|
break;
|
|
422
|
+
case 'small_button':
|
|
423
|
+
emitSmallButton(node, lines, indent);
|
|
424
|
+
break;
|
|
425
|
+
case 'arrow_button':
|
|
426
|
+
emitArrowButton(node, lines, indent);
|
|
427
|
+
break;
|
|
428
|
+
case 'invisible_button':
|
|
429
|
+
emitInvisibleButton(node, lines, indent);
|
|
430
|
+
break;
|
|
431
|
+
case 'image_button':
|
|
432
|
+
emitImageButton(node, lines, indent);
|
|
433
|
+
break;
|
|
342
434
|
case 'text_input':
|
|
343
435
|
emitTextInput(node, lines, indent);
|
|
344
436
|
break;
|
|
@@ -348,6 +440,21 @@ function emitNode(node, lines, depth) {
|
|
|
348
440
|
case 'separator':
|
|
349
441
|
lines.push(`${indent}imx::renderer::separator();`);
|
|
350
442
|
break;
|
|
443
|
+
case 'spacing':
|
|
444
|
+
emitSpacing(node, lines, indent);
|
|
445
|
+
break;
|
|
446
|
+
case 'dummy':
|
|
447
|
+
emitDummy(node, lines, indent);
|
|
448
|
+
break;
|
|
449
|
+
case 'same_line':
|
|
450
|
+
emitSameLine(node, lines, indent);
|
|
451
|
+
break;
|
|
452
|
+
case 'new_line':
|
|
453
|
+
emitNewLine(node, lines, indent);
|
|
454
|
+
break;
|
|
455
|
+
case 'cursor':
|
|
456
|
+
emitCursor(node, lines, indent);
|
|
457
|
+
break;
|
|
351
458
|
case 'begin_popup':
|
|
352
459
|
emitLocComment(node.loc, 'Popup', lines, indent);
|
|
353
460
|
lines.push(`${indent}if (imx::renderer::begin_popup(${node.id})) {`);
|
|
@@ -369,6 +476,37 @@ function emitNode(node, lines, depth) {
|
|
|
369
476
|
case 'menu_item':
|
|
370
477
|
emitMenuItem(node, lines, indent, depth);
|
|
371
478
|
break;
|
|
479
|
+
case 'begin_table':
|
|
480
|
+
emitBeginTable(node, lines, indent);
|
|
481
|
+
break;
|
|
482
|
+
case 'end_table':
|
|
483
|
+
lines.push(`${indent}imx::renderer::end_table();`);
|
|
484
|
+
lines.push(`${indent}}`);
|
|
485
|
+
break;
|
|
486
|
+
case 'begin_table_row':
|
|
487
|
+
emitBeginTableRow(node, lines, indent);
|
|
488
|
+
break;
|
|
489
|
+
case 'end_table_row':
|
|
490
|
+
lines.push(`${indent}imx::renderer::end_table_row();`);
|
|
491
|
+
break;
|
|
492
|
+
case 'begin_table_cell':
|
|
493
|
+
emitBeginTableCell(node, lines, indent);
|
|
494
|
+
break;
|
|
495
|
+
case 'end_table_cell':
|
|
496
|
+
lines.push(`${indent}imx::renderer::end_table_cell();`);
|
|
497
|
+
break;
|
|
498
|
+
case 'begin_tree_node':
|
|
499
|
+
emitBeginTreeNode(node, lines, indent);
|
|
500
|
+
break;
|
|
501
|
+
case 'end_tree_node':
|
|
502
|
+
emitEndTreeNode(node, lines, indent);
|
|
503
|
+
break;
|
|
504
|
+
case 'begin_collapsing_header':
|
|
505
|
+
emitBeginCollapsingHeader(node, lines, indent);
|
|
506
|
+
break;
|
|
507
|
+
case 'end_collapsing_header':
|
|
508
|
+
emitEndCollapsingHeader(node, lines, indent);
|
|
509
|
+
break;
|
|
372
510
|
case 'custom_component':
|
|
373
511
|
emitCustomComponent(node, lines, indent);
|
|
374
512
|
break;
|
|
@@ -384,6 +522,35 @@ function emitNode(node, lines, depth) {
|
|
|
384
522
|
case 'drag_int':
|
|
385
523
|
emitDragInt(node, lines, indent);
|
|
386
524
|
break;
|
|
525
|
+
case 'begin_combo': {
|
|
526
|
+
const n = node;
|
|
527
|
+
emitLocComment(n.loc, 'Combo (manual)', lines, indent);
|
|
528
|
+
const label = asCharPtr(n.label);
|
|
529
|
+
const preview = asCharPtr(n.preview);
|
|
530
|
+
const flagStr = n.flags.length > 0 ? n.flags.join(' | ') : '0';
|
|
531
|
+
if (n.width) {
|
|
532
|
+
lines.push(`${indent}ImGui::PushItemWidth(${n.width});`);
|
|
533
|
+
}
|
|
534
|
+
lines.push(`${indent}if (imx::renderer::begin_combo(${label}, ${preview}, ${flagStr})) {`);
|
|
535
|
+
break;
|
|
536
|
+
}
|
|
537
|
+
case 'end_combo':
|
|
538
|
+
lines.push(`${indent}imx::renderer::end_combo();`);
|
|
539
|
+
lines.push(`${indent}}`);
|
|
540
|
+
break;
|
|
541
|
+
case 'begin_list_box': {
|
|
542
|
+
const n = node;
|
|
543
|
+
emitLocComment(n.loc, 'ListBox (manual)', lines, indent);
|
|
544
|
+
const label = asCharPtr(n.label);
|
|
545
|
+
const w = n.width ?? '0.0f';
|
|
546
|
+
const h = n.height ?? '0.0f';
|
|
547
|
+
lines.push(`${indent}if (imx::renderer::begin_list_box(${label}, ${w}, ${h})) {`);
|
|
548
|
+
break;
|
|
549
|
+
}
|
|
550
|
+
case 'end_list_box':
|
|
551
|
+
lines.push(`${indent}imx::renderer::end_list_box();`);
|
|
552
|
+
lines.push(`${indent}}`);
|
|
553
|
+
break;
|
|
387
554
|
case 'combo':
|
|
388
555
|
emitCombo(node, lines, indent);
|
|
389
556
|
break;
|
|
@@ -396,6 +563,9 @@ function emitNode(node, lines, depth) {
|
|
|
396
563
|
case 'color_edit':
|
|
397
564
|
emitColorEdit(node, lines, indent);
|
|
398
565
|
break;
|
|
566
|
+
case 'color_edit3':
|
|
567
|
+
emitColorEdit3(node, lines, indent);
|
|
568
|
+
break;
|
|
399
569
|
case 'list_box':
|
|
400
570
|
emitListBox(node, lines, indent);
|
|
401
571
|
break;
|
|
@@ -405,9 +575,16 @@ function emitNode(node, lines, depth) {
|
|
|
405
575
|
case 'tooltip':
|
|
406
576
|
emitTooltip(node, lines, indent);
|
|
407
577
|
break;
|
|
578
|
+
case 'shortcut':
|
|
579
|
+
emitShortcut(node, lines, indent);
|
|
580
|
+
break;
|
|
408
581
|
case 'bullet_text':
|
|
409
582
|
emitBulletText(node, lines, indent);
|
|
410
583
|
break;
|
|
584
|
+
case 'bullet':
|
|
585
|
+
emitLocComment(node.loc, 'Bullet', lines, indent);
|
|
586
|
+
lines.push(`${indent}imx::renderer::bullet();`);
|
|
587
|
+
break;
|
|
411
588
|
case 'label_text':
|
|
412
589
|
emitLabelText(node, lines, indent);
|
|
413
590
|
break;
|
|
@@ -423,6 +600,9 @@ function emitNode(node, lines, depth) {
|
|
|
423
600
|
case 'color_picker':
|
|
424
601
|
emitColorPicker(node, lines, indent);
|
|
425
602
|
break;
|
|
603
|
+
case 'color_picker3':
|
|
604
|
+
emitColorPicker3(node, lines, indent);
|
|
605
|
+
break;
|
|
426
606
|
case 'plot_lines':
|
|
427
607
|
emitPlotLines(node, lines, indent);
|
|
428
608
|
break;
|
|
@@ -444,6 +624,62 @@ function emitNode(node, lines, depth) {
|
|
|
444
624
|
case 'draw_text':
|
|
445
625
|
emitDrawText(node, lines, indent);
|
|
446
626
|
break;
|
|
627
|
+
case 'draw_bezier_cubic':
|
|
628
|
+
emitDrawBezierCubic(node, lines, indent);
|
|
629
|
+
break;
|
|
630
|
+
case 'draw_bezier_quadratic':
|
|
631
|
+
emitDrawBezierQuadratic(node, lines, indent);
|
|
632
|
+
break;
|
|
633
|
+
case 'draw_polyline':
|
|
634
|
+
emitDrawPolyline(node, lines, indent);
|
|
635
|
+
break;
|
|
636
|
+
case 'draw_convex_poly_filled':
|
|
637
|
+
emitDrawConvexPolyFilled(node, lines, indent);
|
|
638
|
+
break;
|
|
639
|
+
case 'draw_ngon':
|
|
640
|
+
emitDrawNgon(node, lines, indent);
|
|
641
|
+
break;
|
|
642
|
+
case 'draw_ngon_filled':
|
|
643
|
+
emitDrawNgonFilled(node, lines, indent);
|
|
644
|
+
break;
|
|
645
|
+
case 'draw_triangle':
|
|
646
|
+
emitDrawTriangle(node, lines, indent);
|
|
647
|
+
break;
|
|
648
|
+
case 'input_float_n':
|
|
649
|
+
emitVectorInput(node, 'input_float_n', 'float', lines, indent);
|
|
650
|
+
break;
|
|
651
|
+
case 'input_int_n':
|
|
652
|
+
emitVectorInput(node, 'input_int_n', 'int', lines, indent);
|
|
653
|
+
break;
|
|
654
|
+
case 'drag_float_n': {
|
|
655
|
+
const speed = ensureFloatLiteral(node.speed);
|
|
656
|
+
emitVectorInput(node, 'drag_float_n', 'float', lines, indent, `, ${speed}`);
|
|
657
|
+
break;
|
|
658
|
+
}
|
|
659
|
+
case 'drag_int_n': {
|
|
660
|
+
const speed = ensureFloatLiteral(node.speed);
|
|
661
|
+
emitVectorInput(node, 'drag_int_n', 'int', lines, indent, `, ${speed}`);
|
|
662
|
+
break;
|
|
663
|
+
}
|
|
664
|
+
case 'slider_float_n': {
|
|
665
|
+
const min = ensureFloatLiteral(node.min);
|
|
666
|
+
const max = ensureFloatLiteral(node.max);
|
|
667
|
+
emitVectorInput(node, 'slider_float_n', 'float', lines, indent, `, ${min}, ${max}`);
|
|
668
|
+
break;
|
|
669
|
+
}
|
|
670
|
+
case 'slider_int_n': {
|
|
671
|
+
emitVectorInput(node, 'slider_int_n', 'int', lines, indent, `, ${node.min}, ${node.max}`);
|
|
672
|
+
break;
|
|
673
|
+
}
|
|
674
|
+
case 'vslider_float':
|
|
675
|
+
emitVSliderFloat(node, lines, indent);
|
|
676
|
+
break;
|
|
677
|
+
case 'vslider_int':
|
|
678
|
+
emitVSliderInt(node, lines, indent);
|
|
679
|
+
break;
|
|
680
|
+
case 'slider_angle':
|
|
681
|
+
emitSliderAngle(node, lines, indent);
|
|
682
|
+
break;
|
|
447
683
|
case 'native_widget':
|
|
448
684
|
emitNativeWidget(node, lines, indent);
|
|
449
685
|
break;
|
|
@@ -472,10 +708,13 @@ let comboCounter = 0;
|
|
|
472
708
|
let listBoxCounter = 0;
|
|
473
709
|
let nativeWidgetCounter = 0;
|
|
474
710
|
let plotCounter = 0;
|
|
711
|
+
let widgetTempCounter = 0;
|
|
475
712
|
const windowOpenStack = []; // tracks if begin_window used open prop
|
|
476
713
|
const modalOnCloseStack = []; // tracks modal onClose expressions
|
|
714
|
+
const collapsingHeaderOnCloseStack = [];
|
|
477
715
|
const dragDropSourceStack = [];
|
|
478
716
|
const dragDropTargetStack = [];
|
|
717
|
+
const multiSelectCallbackStack = [];
|
|
479
718
|
/**
|
|
480
719
|
* Build a Style variable from a raw style expression string for self-closing components.
|
|
481
720
|
* Handles JS-like object literals: { width: 300, height: 100 } -> imx::Style with assignments.
|
|
@@ -507,53 +746,118 @@ function splitStylePairs(inner) {
|
|
|
507
746
|
pairs.push(last);
|
|
508
747
|
return pairs;
|
|
509
748
|
}
|
|
749
|
+
function assignStyleExpr(varName, styleExpr, indent, lines) {
|
|
750
|
+
const trimmed = styleExpr.trim();
|
|
751
|
+
if (!trimmed)
|
|
752
|
+
return;
|
|
753
|
+
if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {
|
|
754
|
+
lines.push(`${indent}${varName} = ${trimmed};`);
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
const inner = trimmed.slice(1, -1).trim();
|
|
758
|
+
if (!inner)
|
|
759
|
+
return;
|
|
760
|
+
const pairs = splitStylePairs(inner);
|
|
761
|
+
for (const pair of pairs) {
|
|
762
|
+
const colonIdx = pair.indexOf(':');
|
|
763
|
+
if (colonIdx === -1)
|
|
764
|
+
continue;
|
|
765
|
+
const key = pair.substring(0, colonIdx).trim();
|
|
766
|
+
const val = pair.substring(colonIdx + 1).trim();
|
|
767
|
+
const cppKey = key === 'paddingHorizontal' ? 'padding_horizontal'
|
|
768
|
+
: key === 'paddingVertical' ? 'padding_vertical'
|
|
769
|
+
: key === 'minWidth' ? 'min_width'
|
|
770
|
+
: key === 'minHeight' ? 'min_height'
|
|
771
|
+
: key === 'backgroundColor' ? 'background_color'
|
|
772
|
+
: key === 'textColor' ? 'text_color'
|
|
773
|
+
: key === 'fontSize' ? 'font_size'
|
|
774
|
+
: key;
|
|
775
|
+
if (cppKey === 'background_color' || cppKey === 'text_color') {
|
|
776
|
+
const arrInner = val.trim().replace(/^\[/, '').replace(/\]$/, '');
|
|
777
|
+
const components = arrInner.split(',').map(c => {
|
|
778
|
+
const s = c.trim();
|
|
779
|
+
return /^-?\d+(\.\d+)?$/.test(s) ? (s.includes('.') ? `${s}f` : `${s}.0f`) : s;
|
|
780
|
+
});
|
|
781
|
+
lines.push(`${indent}${varName}.${cppKey} = ImVec4(${components.join(', ')});`);
|
|
782
|
+
}
|
|
783
|
+
else {
|
|
784
|
+
lines.push(`${indent}${varName}.${cppKey} = ${emitFloat(val)};`);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
}
|
|
510
788
|
function buildStyleVar(styleExpr, indent, lines) {
|
|
511
789
|
if (!styleExpr)
|
|
512
790
|
return null;
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
791
|
+
const varName = `style_${styleCounter++}`;
|
|
792
|
+
lines.push(`${indent}imx::Style ${varName};`);
|
|
793
|
+
assignStyleExpr(varName, styleExpr, indent, lines);
|
|
794
|
+
return varName;
|
|
795
|
+
}
|
|
796
|
+
function buildWidgetStyleVar(styleExpr, widthExpr, indent, lines) {
|
|
797
|
+
if (!styleExpr && !widthExpr)
|
|
798
|
+
return null;
|
|
799
|
+
const varName = `style_${styleCounter++}`;
|
|
800
|
+
lines.push(`${indent}imx::Style ${varName};`);
|
|
801
|
+
if (styleExpr) {
|
|
802
|
+
assignStyleExpr(varName, styleExpr, indent, lines);
|
|
803
|
+
}
|
|
804
|
+
if (widthExpr) {
|
|
805
|
+
lines.push(`${indent}${varName}.width = ${emitFloat(widthExpr)};`);
|
|
806
|
+
}
|
|
807
|
+
return varName;
|
|
808
|
+
}
|
|
809
|
+
function nextWidgetTemp(prefix) {
|
|
810
|
+
return `_${prefix}_${widgetTempCounter++}`;
|
|
811
|
+
}
|
|
812
|
+
function emitActionStatements(statements, lines, indent) {
|
|
813
|
+
if (!statements)
|
|
814
|
+
return;
|
|
815
|
+
for (const stmt of statements) {
|
|
816
|
+
lines.push(`${indent}${stmt}`);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
function emitItemInteractionBefore(item, lines, indent) {
|
|
820
|
+
if (!item?.autoFocus)
|
|
821
|
+
return;
|
|
822
|
+
lines.push(`${indent}if (${item.autoFocus}) imx::renderer::request_keyboard_focus();`);
|
|
823
|
+
}
|
|
824
|
+
function emitItemInteractionAfter(item, lines, indent) {
|
|
825
|
+
if (!item)
|
|
826
|
+
return;
|
|
827
|
+
if (item.tooltip) {
|
|
828
|
+
lines.push(`${indent}imx::renderer::tooltip(${asCharPtr(item.tooltip)});`);
|
|
829
|
+
}
|
|
830
|
+
if (item.scrollToHere) {
|
|
831
|
+
lines.push(`${indent}if (${item.scrollToHere}) imx::renderer::item_scroll_to_here();`);
|
|
832
|
+
}
|
|
833
|
+
if (item.cursor) {
|
|
834
|
+
lines.push(`${indent}imx::renderer::item_cursor(${asCharPtr(item.cursor)});`);
|
|
835
|
+
}
|
|
836
|
+
const callbackChecks = [
|
|
837
|
+
[item.onHover, 'item_hovered'],
|
|
838
|
+
[item.onActive, 'item_active'],
|
|
839
|
+
[item.onFocused, 'item_focused'],
|
|
840
|
+
[item.onClicked, 'item_clicked'],
|
|
841
|
+
[item.onDoubleClicked, 'item_double_clicked'],
|
|
842
|
+
];
|
|
843
|
+
for (const [statements, fn] of callbackChecks) {
|
|
844
|
+
if (!statements || statements.length === 0)
|
|
845
|
+
continue;
|
|
846
|
+
lines.push(`${indent}if (imx::renderer::${fn}()) {`);
|
|
847
|
+
emitActionStatements(statements, lines, indent + INDENT);
|
|
848
|
+
lines.push(`${indent}}`);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
function emitBoolWidgetCall(callExpr, item, lines, indent, resultVar) {
|
|
852
|
+
emitItemInteractionBefore(item, lines, indent);
|
|
853
|
+
if (item || resultVar) {
|
|
854
|
+
const varName = resultVar ?? nextWidgetTemp('item');
|
|
855
|
+
lines.push(`${indent}bool ${varName} = ${callExpr};`);
|
|
856
|
+
emitItemInteractionAfter(item, lines, indent);
|
|
553
857
|
return varName;
|
|
554
858
|
}
|
|
555
|
-
|
|
556
|
-
return
|
|
859
|
+
lines.push(`${indent}${callExpr};`);
|
|
860
|
+
return null;
|
|
557
861
|
}
|
|
558
862
|
function buildStyleBlock(node, indent, lines) {
|
|
559
863
|
// Check for style-related props (gap, padding, width, height, etc.)
|
|
@@ -582,12 +886,158 @@ function buildStyleBlock(node, indent, lines) {
|
|
|
582
886
|
const varName = `style_${styleCounter++}`;
|
|
583
887
|
lines.push(`${indent}imx::Style ${varName};`);
|
|
584
888
|
for (const [key, val] of Object.entries(styleProps)) {
|
|
585
|
-
|
|
586
|
-
const floatVal = val.includes('.') ? `${val}F` : `${val}.0F`;
|
|
587
|
-
lines.push(`${indent}${varName}.${key} = ${floatVal};`);
|
|
889
|
+
lines.push(`${indent}${varName}.${key} = ${emitFloat(val)};`);
|
|
588
890
|
}
|
|
589
891
|
return varName;
|
|
590
892
|
}
|
|
893
|
+
function emitTableOptions(node, varName, indent, lines) {
|
|
894
|
+
lines.push(`${indent}imx::TableOptions ${varName};`);
|
|
895
|
+
if (node.sortable || node.onSortBody)
|
|
896
|
+
lines.push(`${indent}${varName}.sortable = ${node.sortable ?? 'true'};`);
|
|
897
|
+
if (node.hideable)
|
|
898
|
+
lines.push(`${indent}${varName}.hideable = ${node.hideable};`);
|
|
899
|
+
if (node.multiSortable)
|
|
900
|
+
lines.push(`${indent}${varName}.multi_sortable = ${node.multiSortable};`);
|
|
901
|
+
if (node.noClip)
|
|
902
|
+
lines.push(`${indent}${varName}.no_clip = ${node.noClip};`);
|
|
903
|
+
if (node.padOuterX)
|
|
904
|
+
lines.push(`${indent}${varName}.pad_outer_x = ${node.padOuterX};`);
|
|
905
|
+
if (node.scrollX)
|
|
906
|
+
lines.push(`${indent}${varName}.scroll_x = ${node.scrollX};`);
|
|
907
|
+
if (node.scrollY)
|
|
908
|
+
lines.push(`${indent}${varName}.scroll_y = ${node.scrollY};`);
|
|
909
|
+
if (node.noBorders)
|
|
910
|
+
lines.push(`${indent}${varName}.no_borders = ${node.noBorders};`);
|
|
911
|
+
if (node.noRowBg)
|
|
912
|
+
lines.push(`${indent}${varName}.no_row_bg = ${node.noRowBg};`);
|
|
913
|
+
}
|
|
914
|
+
function emitBeginTable(node, lines, indent) {
|
|
915
|
+
emitLocComment(node.loc, 'Table', lines, indent);
|
|
916
|
+
const colsVar = `table_cols_${styleCounter++}`;
|
|
917
|
+
const optsVar = `table_opts_${styleCounter++}`;
|
|
918
|
+
const style = node.style ? buildStyleVar(node.style, indent, lines) : null;
|
|
919
|
+
lines.push(`${indent}imx::TableColumn ${colsVar}[${node.columns.length}];`);
|
|
920
|
+
node.columns.forEach((column, index) => {
|
|
921
|
+
lines.push(`${indent}${colsVar}[${index}].label = ${asCharPtr(column.label)};`);
|
|
922
|
+
if (column.defaultHide)
|
|
923
|
+
lines.push(`${indent}if (${column.defaultHide}) ${colsVar}[${index}].flags |= ImGuiTableColumnFlags_DefaultHide;`);
|
|
924
|
+
if (column.preferSortAscending)
|
|
925
|
+
lines.push(`${indent}if (${column.preferSortAscending}) ${colsVar}[${index}].flags |= ImGuiTableColumnFlags_PreferSortAscending;`);
|
|
926
|
+
if (column.preferSortDescending)
|
|
927
|
+
lines.push(`${indent}if (${column.preferSortDescending}) ${colsVar}[${index}].flags |= ImGuiTableColumnFlags_PreferSortDescending;`);
|
|
928
|
+
if (column.noResize)
|
|
929
|
+
lines.push(`${indent}if (${column.noResize}) ${colsVar}[${index}].flags |= ImGuiTableColumnFlags_NoResize;`);
|
|
930
|
+
if (column.fixedWidth)
|
|
931
|
+
lines.push(`${indent}if (${column.fixedWidth}) ${colsVar}[${index}].flags |= ImGuiTableColumnFlags_WidthFixed;`);
|
|
932
|
+
});
|
|
933
|
+
emitTableOptions(node, optsVar, indent, lines);
|
|
934
|
+
const styleArg = style ?? '{}';
|
|
935
|
+
lines.push(`${indent}if (imx::renderer::begin_table("##table", ${colsVar}, ${node.columns.length}, ${styleArg}, ${optsVar})) {`);
|
|
936
|
+
if (node.onSortBody) {
|
|
937
|
+
const paramName = node.onSortParam ?? 'tableSortSpecs';
|
|
938
|
+
lines.push(`${indent}${INDENT}if (ImGuiTableSortSpecs* _imx_sort_specs = ImGui::TableGetSortSpecs()) {`);
|
|
939
|
+
lines.push(`${indent}${INDENT}${INDENT}if (_imx_sort_specs->SpecsDirty) {`);
|
|
940
|
+
lines.push(`${indent}${INDENT}${INDENT}${INDENT}ImGuiTableSortSpecs& ${paramName} = *_imx_sort_specs;`);
|
|
941
|
+
lines.push(`${indent}${INDENT}${INDENT}${INDENT}${node.onSortBody}`);
|
|
942
|
+
lines.push(`${indent}${INDENT}${INDENT}${INDENT}_imx_sort_specs->SpecsDirty = false;`);
|
|
943
|
+
lines.push(`${indent}${INDENT}${INDENT}}`);
|
|
944
|
+
lines.push(`${indent}${INDENT}}`);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
function emitBeginTableRow(node, lines, indent) {
|
|
948
|
+
emitLocComment(node.loc, 'TableRow', lines, indent);
|
|
949
|
+
if (node.bgColor) {
|
|
950
|
+
lines.push(`${indent}imx::renderer::begin_table_row(${emitImVec4(node.bgColor)});`);
|
|
951
|
+
}
|
|
952
|
+
else {
|
|
953
|
+
lines.push(`${indent}imx::renderer::begin_table_row();`);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
function emitBeginTableCell(node, lines, indent) {
|
|
957
|
+
emitLocComment(node.loc, 'TableCell', lines, indent);
|
|
958
|
+
const columnIndex = node.columnIndex ?? '-1';
|
|
959
|
+
if (node.bgColor) {
|
|
960
|
+
lines.push(`${indent}imx::renderer::begin_table_cell(${columnIndex}, ${emitImVec4(node.bgColor)});`);
|
|
961
|
+
}
|
|
962
|
+
else {
|
|
963
|
+
lines.push(`${indent}imx::renderer::begin_table_cell(${columnIndex});`);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
function emitBeginTreeNode(node, lines, indent) {
|
|
967
|
+
emitLocComment(node.loc, 'TreeNode', lines, indent);
|
|
968
|
+
if (node.forceOpen) {
|
|
969
|
+
lines.push(`${indent}ImGui::SetNextItemOpen(${node.forceOpen}, ImGuiCond_Always);`);
|
|
970
|
+
}
|
|
971
|
+
else if (node.defaultOpen) {
|
|
972
|
+
lines.push(`${indent}ImGui::SetNextItemOpen(${node.defaultOpen}, ImGuiCond_Once);`);
|
|
973
|
+
}
|
|
974
|
+
const flagsVar = `tree_flags_${styleCounter++}`;
|
|
975
|
+
lines.push(`${indent}ImGuiTreeNodeFlags ${flagsVar} = 0;`);
|
|
976
|
+
if (node.defaultOpen)
|
|
977
|
+
lines.push(`${indent}if (${node.defaultOpen}) ${flagsVar} |= ImGuiTreeNodeFlags_DefaultOpen;`);
|
|
978
|
+
if (node.openOnArrow)
|
|
979
|
+
lines.push(`${indent}if (${node.openOnArrow}) ${flagsVar} |= ImGuiTreeNodeFlags_OpenOnArrow;`);
|
|
980
|
+
if (node.openOnDoubleClick)
|
|
981
|
+
lines.push(`${indent}if (${node.openOnDoubleClick}) ${flagsVar} |= ImGuiTreeNodeFlags_OpenOnDoubleClick;`);
|
|
982
|
+
if (node.leaf)
|
|
983
|
+
lines.push(`${indent}if (${node.leaf}) ${flagsVar} |= ImGuiTreeNodeFlags_Leaf;`);
|
|
984
|
+
if (node.bullet)
|
|
985
|
+
lines.push(`${indent}if (${node.bullet}) ${flagsVar} |= ImGuiTreeNodeFlags_Bullet;`);
|
|
986
|
+
if (node.noTreePushOnOpen)
|
|
987
|
+
lines.push(`${indent}if (${node.noTreePushOnOpen}) ${flagsVar} |= ImGuiTreeNodeFlags_NoTreePushOnOpen;`);
|
|
988
|
+
emitItemInteractionBefore(node.item, lines, indent);
|
|
989
|
+
const openVar = nextWidgetTemp('tree_open');
|
|
990
|
+
lines.push(`${indent}bool ${openVar} = imx::renderer::begin_tree_node(${asCharPtr(node.label)}, ${flagsVar});`);
|
|
991
|
+
emitItemInteractionAfter(node.item, lines, indent);
|
|
992
|
+
lines.push(`${indent}if (${openVar}) {`);
|
|
993
|
+
}
|
|
994
|
+
function emitEndTreeNode(node, lines, indent) {
|
|
995
|
+
lines.push(`${indent}imx::renderer::end_tree_node(${node.noTreePushOnOpen ?? 'false'});`);
|
|
996
|
+
lines.push(`${indent}}`);
|
|
997
|
+
}
|
|
998
|
+
function emitBeginCollapsingHeader(node, lines, indent) {
|
|
999
|
+
emitLocComment(node.loc, 'CollapsingHeader', lines, indent);
|
|
1000
|
+
if (node.forceOpen) {
|
|
1001
|
+
lines.push(`${indent}ImGui::SetNextItemOpen(${node.forceOpen}, ImGuiCond_Always);`);
|
|
1002
|
+
}
|
|
1003
|
+
else if (node.defaultOpen) {
|
|
1004
|
+
lines.push(`${indent}ImGui::SetNextItemOpen(${node.defaultOpen}, ImGuiCond_Once);`);
|
|
1005
|
+
}
|
|
1006
|
+
const flagsVar = `header_flags_${styleCounter++}`;
|
|
1007
|
+
lines.push(`${indent}ImGuiTreeNodeFlags ${flagsVar} = 0;`);
|
|
1008
|
+
if (node.defaultOpen)
|
|
1009
|
+
lines.push(`${indent}if (${node.defaultOpen}) ${flagsVar} |= ImGuiTreeNodeFlags_DefaultOpen;`);
|
|
1010
|
+
if (node.closable) {
|
|
1011
|
+
collapsingHeaderOnCloseStack.push(node.onCloseBody ?? null);
|
|
1012
|
+
lines.push(`${indent}{`);
|
|
1013
|
+
lines.push(`${indent}${INDENT}bool header_visible = true;`);
|
|
1014
|
+
lines.push(`${indent}${INDENT}bool* header_visible_ptr = ${node.closable} ? &header_visible : nullptr;`);
|
|
1015
|
+
emitItemInteractionBefore(node.item, lines, indent + INDENT);
|
|
1016
|
+
const openVar = nextWidgetTemp('header_open');
|
|
1017
|
+
lines.push(`${indent}${INDENT}bool ${openVar} = imx::renderer::begin_collapsing_header(${asCharPtr(node.label)}, ${flagsVar}, header_visible_ptr);`);
|
|
1018
|
+
emitItemInteractionAfter(node.item, lines, indent + INDENT);
|
|
1019
|
+
lines.push(`${indent}${INDENT}if (${openVar}) {`);
|
|
1020
|
+
}
|
|
1021
|
+
else {
|
|
1022
|
+
collapsingHeaderOnCloseStack.push(null);
|
|
1023
|
+
emitItemInteractionBefore(node.item, lines, indent);
|
|
1024
|
+
const openVar = nextWidgetTemp('header_open');
|
|
1025
|
+
lines.push(`${indent}bool ${openVar} = imx::renderer::begin_collapsing_header(${asCharPtr(node.label)}, ${flagsVar});`);
|
|
1026
|
+
emitItemInteractionAfter(node.item, lines, indent);
|
|
1027
|
+
lines.push(`${indent}if (${openVar}) {`);
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
function emitEndCollapsingHeader(node, lines, indent) {
|
|
1031
|
+
lines.push(`${indent}imx::renderer::end_collapsing_header();`);
|
|
1032
|
+
lines.push(`${indent}}`);
|
|
1033
|
+
const onCloseBody = collapsingHeaderOnCloseStack.pop() ?? null;
|
|
1034
|
+
if (node.closable) {
|
|
1035
|
+
if (onCloseBody) {
|
|
1036
|
+
lines.push(`${indent}${INDENT}if (${node.closable} && !header_visible) { ${onCloseBody} }`);
|
|
1037
|
+
}
|
|
1038
|
+
lines.push(`${indent}}`);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
591
1041
|
function emitBeginContainer(node, lines, indent) {
|
|
592
1042
|
emitLocComment(node.loc, node.tag, lines, indent);
|
|
593
1043
|
switch (node.tag) {
|
|
@@ -606,21 +1056,89 @@ function emitBeginContainer(node, lines, indent) {
|
|
|
606
1056
|
flagParts.push('ImGuiWindowFlags_NoDocking');
|
|
607
1057
|
if (node.props['noScrollbar'] === 'true')
|
|
608
1058
|
flagParts.push('ImGuiWindowFlags_NoScrollbar');
|
|
1059
|
+
if (node.props['noBackground'] === 'true')
|
|
1060
|
+
flagParts.push('ImGuiWindowFlags_NoBackground');
|
|
1061
|
+
if (node.props['alwaysAutoResize'] === 'true')
|
|
1062
|
+
flagParts.push('ImGuiWindowFlags_AlwaysAutoResize');
|
|
1063
|
+
if (node.props['noNavFocus'] === 'true')
|
|
1064
|
+
flagParts.push('ImGuiWindowFlags_NoNavFocus');
|
|
1065
|
+
if (node.props['noNav'] === 'true')
|
|
1066
|
+
flagParts.push('ImGuiWindowFlags_NoNav');
|
|
1067
|
+
if (node.props['noDecoration'] === 'true')
|
|
1068
|
+
flagParts.push('ImGuiWindowFlags_NoDecoration');
|
|
1069
|
+
if (node.props['noInputs'] === 'true')
|
|
1070
|
+
flagParts.push('ImGuiWindowFlags_NoInputs');
|
|
1071
|
+
if (node.props['noScrollWithMouse'] === 'true')
|
|
1072
|
+
flagParts.push('ImGuiWindowFlags_NoScrollWithMouse');
|
|
1073
|
+
if (node.props['horizontalScrollbar'] === 'true')
|
|
1074
|
+
flagParts.push('ImGuiWindowFlags_HorizontalScrollbar');
|
|
1075
|
+
if (node.props['alwaysVerticalScrollbar'] === 'true')
|
|
1076
|
+
flagParts.push('ImGuiWindowFlags_AlwaysVerticalScrollbar');
|
|
1077
|
+
if (node.props['alwaysHorizontalScrollbar'] === 'true')
|
|
1078
|
+
flagParts.push('ImGuiWindowFlags_AlwaysHorizontalScrollbar');
|
|
1079
|
+
if (node.props['hasMenuBar'] === 'true')
|
|
1080
|
+
flagParts.push('ImGuiWindowFlags_MenuBar');
|
|
609
1081
|
const flags = flagParts.length > 0 ? flagParts.join(' | ') : '0';
|
|
1082
|
+
// Window positioning
|
|
1083
|
+
const xExpr = node.props['x'];
|
|
1084
|
+
const yExpr = node.props['y'];
|
|
1085
|
+
if (xExpr && yExpr) {
|
|
1086
|
+
const posCond = node.props['forcePosition'] === 'true' ? 'ImGuiCond_Always' : 'ImGuiCond_Once';
|
|
1087
|
+
lines.push(`${indent}ImGui::SetNextWindowPos(ImVec2(${xExpr}, ${yExpr}), ${posCond});`);
|
|
1088
|
+
}
|
|
1089
|
+
// Window sizing
|
|
1090
|
+
const wExpr = node.props['width'];
|
|
1091
|
+
const hExpr = node.props['height'];
|
|
1092
|
+
if (wExpr || hExpr) {
|
|
1093
|
+
const sizeCond = node.props['forceSize'] === 'true' ? 'ImGuiCond_Always' : 'ImGuiCond_Once';
|
|
1094
|
+
const sw = wExpr ?? '0.0f';
|
|
1095
|
+
const sh = hExpr ?? '0.0f';
|
|
1096
|
+
lines.push(`${indent}ImGui::SetNextWindowSize(ImVec2(${sw}, ${sh}), ${sizeCond});`);
|
|
1097
|
+
}
|
|
1098
|
+
// Window size constraints
|
|
1099
|
+
const minW = node.props['minWidth'];
|
|
1100
|
+
const minH = node.props['minHeight'];
|
|
1101
|
+
const maxW = node.props['maxWidth'];
|
|
1102
|
+
const maxH = node.props['maxHeight'];
|
|
1103
|
+
if (minW || minH || maxW || maxH) {
|
|
1104
|
+
const cminW = minW ?? '0.0f';
|
|
1105
|
+
const cminH = minH ?? '0.0f';
|
|
1106
|
+
const cmaxW = maxW ?? 'FLT_MAX';
|
|
1107
|
+
const cmaxH = maxH ?? 'FLT_MAX';
|
|
1108
|
+
lines.push(`${indent}ImGui::SetNextWindowSizeConstraints(ImVec2(${cminW}, ${cminH}), ImVec2(${cmaxW}, ${cmaxH}));`);
|
|
1109
|
+
}
|
|
1110
|
+
// Window background alpha
|
|
1111
|
+
const bgAlpha = node.props['bgAlpha'];
|
|
1112
|
+
if (bgAlpha) {
|
|
1113
|
+
lines.push(`${indent}ImGui::SetNextWindowBgAlpha(${bgAlpha});`);
|
|
1114
|
+
}
|
|
1115
|
+
// Viewport control
|
|
1116
|
+
if (node.props['noViewport'] === 'true') {
|
|
1117
|
+
lines.push(`${indent}ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID);`);
|
|
1118
|
+
}
|
|
610
1119
|
const openExpr = node.props['open'];
|
|
611
1120
|
const onCloseExpr = node.props['onClose'];
|
|
612
1121
|
if (openExpr) {
|
|
1122
|
+
const vpOnTop = node.props['viewportAlwaysOnTop'] === 'true';
|
|
613
1123
|
windowOpenStack.push(true);
|
|
614
1124
|
lines.push(`${indent}{`);
|
|
615
1125
|
lines.push(`${indent} bool win_open = ${openExpr};`);
|
|
616
|
-
lines.push(`${indent} imx::renderer::begin_window(${title}, ${flags}, &win_open);`);
|
|
1126
|
+
lines.push(`${indent} imx::renderer::begin_window(${title}, ${flags}, &win_open${vpOnTop ? ', true' : ''});`);
|
|
617
1127
|
if (onCloseExpr) {
|
|
618
|
-
|
|
1128
|
+
const lambdaMatch = onCloseExpr.match(/^\[&\]\(\)\s*\{\s*(.*?)\s*\}$/);
|
|
1129
|
+
const onCloseBody = lambdaMatch ? lambdaMatch[1] : `${onCloseExpr}();`;
|
|
1130
|
+
lines.push(`${indent} if (!win_open) { ${onCloseBody} }`);
|
|
619
1131
|
}
|
|
620
1132
|
}
|
|
621
1133
|
else {
|
|
1134
|
+
const vpOnTopElse = node.props['viewportAlwaysOnTop'] === 'true';
|
|
622
1135
|
windowOpenStack.push(false);
|
|
623
|
-
|
|
1136
|
+
if (vpOnTopElse) {
|
|
1137
|
+
lines.push(`${indent}imx::renderer::begin_window(${title}, ${flags}, nullptr, true);`);
|
|
1138
|
+
}
|
|
1139
|
+
else {
|
|
1140
|
+
lines.push(`${indent}imx::renderer::begin_window(${title}, ${flags});`);
|
|
1141
|
+
}
|
|
624
1142
|
}
|
|
625
1143
|
break;
|
|
626
1144
|
}
|
|
@@ -654,6 +1172,15 @@ function emitBeginContainer(node, lines, indent) {
|
|
|
654
1172
|
}
|
|
655
1173
|
break;
|
|
656
1174
|
}
|
|
1175
|
+
case 'Indent': {
|
|
1176
|
+
const width = node.props['width'] ? emitFloat(node.props['width']) : '0.0F';
|
|
1177
|
+
lines.push(`${indent}imx::renderer::begin_indent(${width});`);
|
|
1178
|
+
break;
|
|
1179
|
+
}
|
|
1180
|
+
case 'TextWrap': {
|
|
1181
|
+
lines.push(`${indent}imx::renderer::begin_text_wrap(${emitFloat(node.props['width'] ?? '0')});`);
|
|
1182
|
+
break;
|
|
1183
|
+
}
|
|
657
1184
|
case 'DockSpace': {
|
|
658
1185
|
const style = buildStyleBlock(node, indent, lines);
|
|
659
1186
|
const hasMenuBar = node.props['hasMenuBar'] === 'true';
|
|
@@ -668,6 +1195,10 @@ function emitBeginContainer(node, lines, indent) {
|
|
|
668
1195
|
}
|
|
669
1196
|
break;
|
|
670
1197
|
}
|
|
1198
|
+
case 'MainMenuBar': {
|
|
1199
|
+
lines.push(`${indent}if (imx::renderer::begin_main_menu_bar()) {`);
|
|
1200
|
+
break;
|
|
1201
|
+
}
|
|
671
1202
|
case 'MenuBar': {
|
|
672
1203
|
lines.push(`${indent}if (imx::renderer::begin_menu_bar()) {`);
|
|
673
1204
|
break;
|
|
@@ -677,32 +1208,6 @@ function emitBeginContainer(node, lines, indent) {
|
|
|
677
1208
|
lines.push(`${indent}if (imx::renderer::begin_menu(${label})) {`);
|
|
678
1209
|
break;
|
|
679
1210
|
}
|
|
680
|
-
case 'Table': {
|
|
681
|
-
const columnsRaw = node.props['columns'] ?? '';
|
|
682
|
-
const columnNames = columnsRaw.split(',').map(s => s.trim()).filter(s => s.length > 0);
|
|
683
|
-
const count = columnNames.length;
|
|
684
|
-
const varName = `table_cols_${styleCounter++}`;
|
|
685
|
-
const style = buildStyleVar(node.style, indent, lines);
|
|
686
|
-
const scrollY = node.props['scrollY'] === 'true';
|
|
687
|
-
const noBorders = node.props['noBorders'] === 'true';
|
|
688
|
-
const noRowBg = node.props['noRowBg'] === 'true';
|
|
689
|
-
lines.push(`${indent}const char* ${varName}[] = {${columnNames.join(', ')}};`);
|
|
690
|
-
const styleArg = style ?? '{}';
|
|
691
|
-
if (scrollY || noBorders || noRowBg) {
|
|
692
|
-
lines.push(`${indent}if (imx::renderer::begin_table("##table", ${count}, ${varName}, ${styleArg}, ${scrollY}, ${noBorders}, ${noRowBg})) {`);
|
|
693
|
-
}
|
|
694
|
-
else if (style) {
|
|
695
|
-
lines.push(`${indent}if (imx::renderer::begin_table("##table", ${count}, ${varName}, ${styleArg})) {`);
|
|
696
|
-
}
|
|
697
|
-
else {
|
|
698
|
-
lines.push(`${indent}if (imx::renderer::begin_table("##table", ${count}, ${varName})) {`);
|
|
699
|
-
}
|
|
700
|
-
break;
|
|
701
|
-
}
|
|
702
|
-
case 'TableRow': {
|
|
703
|
-
lines.push(`${indent}imx::renderer::begin_table_row();`);
|
|
704
|
-
break;
|
|
705
|
-
}
|
|
706
1211
|
case 'TabBar': {
|
|
707
1212
|
lines.push(`${indent}if (imx::renderer::begin_tab_bar()) {`);
|
|
708
1213
|
break;
|
|
@@ -712,16 +1217,6 @@ function emitBeginContainer(node, lines, indent) {
|
|
|
712
1217
|
lines.push(`${indent}if (imx::renderer::begin_tab_item(${label})) {`);
|
|
713
1218
|
break;
|
|
714
1219
|
}
|
|
715
|
-
case 'TreeNode': {
|
|
716
|
-
const label = asCharPtr(node.props['label'] ?? '""');
|
|
717
|
-
lines.push(`${indent}if (imx::renderer::begin_tree_node(${label})) {`);
|
|
718
|
-
break;
|
|
719
|
-
}
|
|
720
|
-
case 'CollapsingHeader': {
|
|
721
|
-
const label = asCharPtr(node.props['label'] ?? '""');
|
|
722
|
-
lines.push(`${indent}if (imx::renderer::begin_collapsing_header(${label})) {`);
|
|
723
|
-
break;
|
|
724
|
-
}
|
|
725
1220
|
case 'Theme': {
|
|
726
1221
|
const preset = asCharPtr(node.props['preset'] ?? '"dark"');
|
|
727
1222
|
const varName = `theme_${styleCounter++}`;
|
|
@@ -755,6 +1250,25 @@ function emitBeginContainer(node, lines, indent) {
|
|
|
755
1250
|
}
|
|
756
1251
|
case 'Modal': {
|
|
757
1252
|
const title = asCharPtr(node.props['title'] ?? '""');
|
|
1253
|
+
// Build modal flags
|
|
1254
|
+
const flagParts = [];
|
|
1255
|
+
if (node.props['noTitleBar'] === 'true')
|
|
1256
|
+
flagParts.push('ImGuiWindowFlags_NoTitleBar');
|
|
1257
|
+
if (node.props['noResize'] === 'true')
|
|
1258
|
+
flagParts.push('ImGuiWindowFlags_NoResize');
|
|
1259
|
+
if (node.props['noMove'] === 'true')
|
|
1260
|
+
flagParts.push('ImGuiWindowFlags_NoMove');
|
|
1261
|
+
if (node.props['noScrollbar'] === 'true')
|
|
1262
|
+
flagParts.push('ImGuiWindowFlags_NoScrollbar');
|
|
1263
|
+
if (node.props['noCollapse'] === 'true')
|
|
1264
|
+
flagParts.push('ImGuiWindowFlags_NoCollapse');
|
|
1265
|
+
if (node.props['alwaysAutoResize'] === 'true')
|
|
1266
|
+
flagParts.push('ImGuiWindowFlags_AlwaysAutoResize');
|
|
1267
|
+
if (node.props['noBackground'] === 'true')
|
|
1268
|
+
flagParts.push('ImGuiWindowFlags_NoBackground');
|
|
1269
|
+
if (node.props['horizontalScrollbar'] === 'true')
|
|
1270
|
+
flagParts.push('ImGuiWindowFlags_HorizontalScrollbar');
|
|
1271
|
+
const modalFlags = flagParts.length > 0 ? flagParts.join(' | ') : '0';
|
|
758
1272
|
const openExpr = node.props['open'];
|
|
759
1273
|
const onCloseExpr = node.props['onClose'];
|
|
760
1274
|
if (openExpr) {
|
|
@@ -768,12 +1282,12 @@ function emitBeginContainer(node, lines, indent) {
|
|
|
768
1282
|
modalOnCloseStack.push(onCloseBody);
|
|
769
1283
|
lines.push(`${indent}{`);
|
|
770
1284
|
lines.push(`${indent} bool modal_closed = false;`);
|
|
771
|
-
lines.push(`${indent} if (imx::renderer::begin_modal(${title}, ${openExpr}, &modal_closed)) {`);
|
|
1285
|
+
lines.push(`${indent} if (imx::renderer::begin_modal(${title}, ${openExpr}, &modal_closed, ${modalFlags})) {`);
|
|
772
1286
|
}
|
|
773
1287
|
else {
|
|
774
1288
|
windowOpenStack.push(false);
|
|
775
1289
|
modalOnCloseStack.push(null);
|
|
776
|
-
lines.push(`${indent}if (imx::renderer::begin_modal(${title}, true, nullptr)) {`);
|
|
1290
|
+
lines.push(`${indent}if (imx::renderer::begin_modal(${title}, true, nullptr, ${modalFlags})) {`);
|
|
777
1291
|
}
|
|
778
1292
|
break;
|
|
779
1293
|
}
|
|
@@ -875,6 +1389,64 @@ function emitBeginContainer(node, lines, indent) {
|
|
|
875
1389
|
}
|
|
876
1390
|
break;
|
|
877
1391
|
}
|
|
1392
|
+
case 'Font': {
|
|
1393
|
+
const name = asCharPtr(node.props['name'] ?? '""');
|
|
1394
|
+
lines.push(`${indent}imx::renderer::begin_font(${name});`);
|
|
1395
|
+
break;
|
|
1396
|
+
}
|
|
1397
|
+
case 'ContextMenu': {
|
|
1398
|
+
const idExpr = node.props['id'];
|
|
1399
|
+
const idArg = idExpr ? asCharPtr(idExpr) : 'nullptr';
|
|
1400
|
+
const mbExpr = node.props['mouseButton'];
|
|
1401
|
+
let mouseButtonArg = '1'; // default: right click
|
|
1402
|
+
if (mbExpr === '"left"')
|
|
1403
|
+
mouseButtonArg = '0';
|
|
1404
|
+
else if (mbExpr === '"middle"')
|
|
1405
|
+
mouseButtonArg = '2';
|
|
1406
|
+
if (node.props['target'] === '"window"') {
|
|
1407
|
+
lines.push(`${indent}if (imx::renderer::begin_context_menu_window(${idArg}, ${mouseButtonArg})) {`);
|
|
1408
|
+
}
|
|
1409
|
+
else {
|
|
1410
|
+
lines.push(`${indent}if (imx::renderer::begin_context_menu_item(${idArg}, ${mouseButtonArg})) {`);
|
|
1411
|
+
}
|
|
1412
|
+
break;
|
|
1413
|
+
}
|
|
1414
|
+
case 'MultiSelect': {
|
|
1415
|
+
const flagParts = [];
|
|
1416
|
+
if (node.props['singleSelect'] === 'true')
|
|
1417
|
+
flagParts.push('ImGuiMultiSelectFlags_SingleSelect');
|
|
1418
|
+
if (node.props['noSelectAll'] === 'true')
|
|
1419
|
+
flagParts.push('ImGuiMultiSelectFlags_NoSelectAll');
|
|
1420
|
+
if (node.props['noRangeSelect'] === 'true')
|
|
1421
|
+
flagParts.push('ImGuiMultiSelectFlags_NoRangeSelect');
|
|
1422
|
+
if (node.props['noAutoSelect'] === 'true')
|
|
1423
|
+
flagParts.push('ImGuiMultiSelectFlags_NoAutoSelect');
|
|
1424
|
+
if (node.props['noAutoClear'] === 'true')
|
|
1425
|
+
flagParts.push('ImGuiMultiSelectFlags_NoAutoClear');
|
|
1426
|
+
if (node.props['boxSelect'] === 'true')
|
|
1427
|
+
flagParts.push('ImGuiMultiSelectFlags_BoxSelect1d');
|
|
1428
|
+
if (node.props['boxSelect2d'] === 'true')
|
|
1429
|
+
flagParts.push('ImGuiMultiSelectFlags_BoxSelect2d');
|
|
1430
|
+
if (node.props['boxSelectNoScroll'] === 'true')
|
|
1431
|
+
flagParts.push('ImGuiMultiSelectFlags_BoxSelectNoScroll');
|
|
1432
|
+
if (node.props['clearOnClickVoid'] === 'true')
|
|
1433
|
+
flagParts.push('ImGuiMultiSelectFlags_ClearOnClickVoid');
|
|
1434
|
+
const flags = flagParts.length > 0 ? flagParts.join(' | ') : '0';
|
|
1435
|
+
const selSize = node.props['selectionSize'] ?? '-1';
|
|
1436
|
+
const itemCount = node.props['itemsCount'] ?? '-1';
|
|
1437
|
+
lines.push(`${indent}{`);
|
|
1438
|
+
lines.push(`${indent} auto* ms_io = imx::renderer::begin_multi_select(${flags}, ${selSize}, ${itemCount});`);
|
|
1439
|
+
const onChangeExpr = node.props['onSelectionChange'];
|
|
1440
|
+
// Also apply requests from BeginMultiSelect (ImGui protocol requires both)
|
|
1441
|
+
if (onChangeExpr) {
|
|
1442
|
+
const lambdaMatch = onChangeExpr.match(/^\[&\]\(\)\s*\{\s*(.*?)\(\s*\d+\s*\)\s*;?\s*\}$/);
|
|
1443
|
+
if (lambdaMatch) {
|
|
1444
|
+
lines.push(`${indent} ${lambdaMatch[1]}(ms_io);`);
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
multiSelectCallbackStack.push(onChangeExpr ?? null);
|
|
1448
|
+
break;
|
|
1449
|
+
}
|
|
878
1450
|
case 'DockLayout':
|
|
879
1451
|
case 'DockSplit':
|
|
880
1452
|
case 'DockPanel':
|
|
@@ -900,9 +1472,19 @@ function emitEndContainer(node, lines, indent) {
|
|
|
900
1472
|
case 'View':
|
|
901
1473
|
lines.push(`${indent}imx::renderer::end_view();`);
|
|
902
1474
|
break;
|
|
1475
|
+
case 'Indent':
|
|
1476
|
+
lines.push(`${indent}imx::renderer::end_indent();`);
|
|
1477
|
+
break;
|
|
1478
|
+
case 'TextWrap':
|
|
1479
|
+
lines.push(`${indent}imx::renderer::end_text_wrap();`);
|
|
1480
|
+
break;
|
|
903
1481
|
case 'DockSpace':
|
|
904
1482
|
lines.push(`${indent}imx::renderer::end_dockspace();`);
|
|
905
1483
|
break;
|
|
1484
|
+
case 'MainMenuBar':
|
|
1485
|
+
lines.push(`${indent}imx::renderer::end_main_menu_bar();`);
|
|
1486
|
+
lines.push(`${indent}}`);
|
|
1487
|
+
break;
|
|
906
1488
|
case 'MenuBar':
|
|
907
1489
|
lines.push(`${indent}imx::renderer::end_menu_bar();`);
|
|
908
1490
|
lines.push(`${indent}}`);
|
|
@@ -911,13 +1493,6 @@ function emitEndContainer(node, lines, indent) {
|
|
|
911
1493
|
lines.push(`${indent}imx::renderer::end_menu();`);
|
|
912
1494
|
lines.push(`${indent}}`);
|
|
913
1495
|
break;
|
|
914
|
-
case 'Table':
|
|
915
|
-
lines.push(`${indent}imx::renderer::end_table();`);
|
|
916
|
-
lines.push(`${indent}}`);
|
|
917
|
-
break;
|
|
918
|
-
case 'TableRow':
|
|
919
|
-
lines.push(`${indent}imx::renderer::end_table_row();`);
|
|
920
|
-
break;
|
|
921
1496
|
case 'TabBar':
|
|
922
1497
|
lines.push(`${indent}imx::renderer::end_tab_bar();`);
|
|
923
1498
|
lines.push(`${indent}}`);
|
|
@@ -926,14 +1501,6 @@ function emitEndContainer(node, lines, indent) {
|
|
|
926
1501
|
lines.push(`${indent}imx::renderer::end_tab_item();`);
|
|
927
1502
|
lines.push(`${indent}}`);
|
|
928
1503
|
break;
|
|
929
|
-
case 'TreeNode':
|
|
930
|
-
lines.push(`${indent}imx::renderer::end_tree_node();`);
|
|
931
|
-
lines.push(`${indent}}`);
|
|
932
|
-
break;
|
|
933
|
-
case 'CollapsingHeader':
|
|
934
|
-
lines.push(`${indent}imx::renderer::end_collapsing_header();`);
|
|
935
|
-
lines.push(`${indent}}`);
|
|
936
|
-
break;
|
|
937
1504
|
case 'Theme':
|
|
938
1505
|
lines.push(`${indent}imx::renderer::end_theme();`);
|
|
939
1506
|
break;
|
|
@@ -989,6 +1556,30 @@ function emitEndContainer(node, lines, indent) {
|
|
|
989
1556
|
case 'Canvas':
|
|
990
1557
|
lines.push(`${indent}imx::renderer::end_canvas();`);
|
|
991
1558
|
break;
|
|
1559
|
+
case 'Font':
|
|
1560
|
+
lines.push(`${indent}imx::renderer::end_font();`);
|
|
1561
|
+
break;
|
|
1562
|
+
case 'ContextMenu':
|
|
1563
|
+
lines.push(`${indent}imx::renderer::end_context_menu();`);
|
|
1564
|
+
lines.push(`${indent}}`);
|
|
1565
|
+
break;
|
|
1566
|
+
case 'MultiSelect': {
|
|
1567
|
+
lines.push(`${indent} auto* ms_io_end = imx::renderer::end_multi_select();`);
|
|
1568
|
+
const onChangeExpr = multiSelectCallbackStack.pop() ?? null;
|
|
1569
|
+
if (onChangeExpr) {
|
|
1570
|
+
// Extract function call from lambda [&]() { fn(placeholder); }
|
|
1571
|
+
// Replace the placeholder argument with ms_io_end
|
|
1572
|
+
const lambdaMatch = onChangeExpr.match(/^\[&\]\(\)\s*\{\s*(.*?)\(\s*\d+\s*\)\s*;?\s*\}$/);
|
|
1573
|
+
if (lambdaMatch) {
|
|
1574
|
+
lines.push(`${indent} if (ms_io_end) { ${lambdaMatch[1]}(ms_io_end); }`);
|
|
1575
|
+
}
|
|
1576
|
+
else {
|
|
1577
|
+
lines.push(`${indent} if (ms_io_end) { ${onChangeExpr}; }`);
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
lines.push(`${indent}}`);
|
|
1581
|
+
break;
|
|
1582
|
+
}
|
|
992
1583
|
case 'DragDropTarget': {
|
|
993
1584
|
const props = dragDropTargetStack.pop() ?? {};
|
|
994
1585
|
const typeStr = asCharPtr(props['type'] ?? '""');
|
|
@@ -1018,26 +1609,96 @@ function emitEndContainer(node, lines, indent) {
|
|
|
1018
1609
|
}
|
|
1019
1610
|
function emitText(node, lines, indent) {
|
|
1020
1611
|
emitLocComment(node.loc, 'Text', lines, indent);
|
|
1021
|
-
|
|
1022
|
-
|
|
1612
|
+
const fmtStr = JSON.stringify(node.format);
|
|
1613
|
+
const argsStr = node.args.length > 0 ? ', ' + node.args.join(', ') : '';
|
|
1614
|
+
if (node.disabled) {
|
|
1615
|
+
// disabled takes priority — ImGui::TextDisabled has its own grayed style
|
|
1616
|
+
lines.push(`${indent}imx::renderer::text_disabled(${fmtStr}${argsStr});`);
|
|
1617
|
+
}
|
|
1618
|
+
else if (node.color && node.wrapped) {
|
|
1619
|
+
// color + wrapped: PushStyleColor + TextWrapped + PopStyleColor
|
|
1620
|
+
lines.push(`${indent}ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(${node.color}));`);
|
|
1621
|
+
lines.push(`${indent}imx::renderer::text_wrapped(${fmtStr}${argsStr});`);
|
|
1622
|
+
lines.push(`${indent}ImGui::PopStyleColor();`);
|
|
1623
|
+
}
|
|
1624
|
+
else if (node.color) {
|
|
1625
|
+
// color only: inline ImGui::TextColored
|
|
1626
|
+
lines.push(`${indent}ImGui::TextColored(ImVec4(${node.color}), ${fmtStr}${argsStr});`);
|
|
1627
|
+
}
|
|
1628
|
+
else if (node.wrapped) {
|
|
1629
|
+
// wrapped only
|
|
1630
|
+
lines.push(`${indent}imx::renderer::text_wrapped(${fmtStr}${argsStr});`);
|
|
1023
1631
|
}
|
|
1024
1632
|
else {
|
|
1025
|
-
|
|
1026
|
-
|
|
1633
|
+
// plain text (current behavior)
|
|
1634
|
+
if (node.args.length === 0) {
|
|
1635
|
+
lines.push(`${indent}imx::renderer::text(${fmtStr});`);
|
|
1636
|
+
}
|
|
1637
|
+
else {
|
|
1638
|
+
lines.push(`${indent}imx::renderer::text(${fmtStr}${argsStr});`);
|
|
1639
|
+
}
|
|
1027
1640
|
}
|
|
1028
1641
|
}
|
|
1029
1642
|
function emitButton(node, lines, indent, depth) {
|
|
1030
1643
|
emitLocComment(node.loc, 'Button', lines, indent);
|
|
1031
1644
|
const title = asCharPtr(node.title);
|
|
1032
1645
|
const disabledArg = node.disabled ? ', {}, true' : '';
|
|
1033
|
-
|
|
1034
|
-
|
|
1646
|
+
const pressedVar = node.action.length > 0 ? nextWidgetTemp('button_pressed') : undefined;
|
|
1647
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::button(${title}${disabledArg})`, node.item, lines, indent, pressedVar);
|
|
1648
|
+
if (node.action.length > 0 && resultVar) {
|
|
1649
|
+
lines.push(`${indent}if (${resultVar}) {`);
|
|
1650
|
+
emitActionStatements(node.action, lines, indent + INDENT);
|
|
1651
|
+
lines.push(`${indent}}`);
|
|
1035
1652
|
}
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1653
|
+
}
|
|
1654
|
+
function emitSmallButton(node, lines, indent) {
|
|
1655
|
+
emitLocComment(node.loc, 'SmallButton', lines, indent);
|
|
1656
|
+
const label = asCharPtr(node.label);
|
|
1657
|
+
const pressedVar = node.action.length > 0 ? nextWidgetTemp('small_button_pressed') : undefined;
|
|
1658
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::small_button(${label})`, node.item, lines, indent, pressedVar);
|
|
1659
|
+
if (node.action.length > 0 && resultVar) {
|
|
1660
|
+
lines.push(`${indent}if (${resultVar}) {`);
|
|
1661
|
+
emitActionStatements(node.action, lines, indent + INDENT);
|
|
1662
|
+
lines.push(`${indent}}`);
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
function emitArrowButton(node, lines, indent) {
|
|
1666
|
+
emitLocComment(node.loc, 'ArrowButton', lines, indent);
|
|
1667
|
+
const id = asCharPtr(node.id);
|
|
1668
|
+
const dirMap = { '"left"': '0', '"right"': '1', '"up"': '2', '"down"': '3' };
|
|
1669
|
+
const dir = dirMap[node.direction] ?? '0';
|
|
1670
|
+
const pressedVar = node.action.length > 0 ? nextWidgetTemp('arrow_button_pressed') : undefined;
|
|
1671
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::arrow_button(${id}, ${dir})`, node.item, lines, indent, pressedVar);
|
|
1672
|
+
if (node.action.length > 0 && resultVar) {
|
|
1673
|
+
lines.push(`${indent}if (${resultVar}) {`);
|
|
1674
|
+
emitActionStatements(node.action, lines, indent + INDENT);
|
|
1675
|
+
lines.push(`${indent}}`);
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
function emitInvisibleButton(node, lines, indent) {
|
|
1679
|
+
emitLocComment(node.loc, 'InvisibleButton', lines, indent);
|
|
1680
|
+
const id = asCharPtr(node.id);
|
|
1681
|
+
const width = emitFloat(node.width);
|
|
1682
|
+
const height = emitFloat(node.height);
|
|
1683
|
+
const pressedVar = node.action.length > 0 ? nextWidgetTemp('invisible_button_pressed') : undefined;
|
|
1684
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::invisible_button(${id}, ${width}, ${height})`, node.item, lines, indent, pressedVar);
|
|
1685
|
+
if (node.action.length > 0 && resultVar) {
|
|
1686
|
+
lines.push(`${indent}if (${resultVar}) {`);
|
|
1687
|
+
emitActionStatements(node.action, lines, indent + INDENT);
|
|
1688
|
+
lines.push(`${indent}}`);
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
function emitImageButton(node, lines, indent) {
|
|
1692
|
+
emitLocComment(node.loc, 'ImageButton', lines, indent);
|
|
1693
|
+
const id = asCharPtr(node.id);
|
|
1694
|
+
const src = asCharPtr(node.src);
|
|
1695
|
+
const width = node.width ? emitFloat(node.width) : '0';
|
|
1696
|
+
const height = node.height ? emitFloat(node.height) : '0';
|
|
1697
|
+
const pressedVar = node.action.length > 0 ? nextWidgetTemp('image_button_pressed') : undefined;
|
|
1698
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::image_button(${id}, ${src}, ${width}, ${height})`, node.item, lines, indent, pressedVar);
|
|
1699
|
+
if (node.action.length > 0 && resultVar) {
|
|
1700
|
+
lines.push(`${indent}if (${resultVar}) {`);
|
|
1701
|
+
emitActionStatements(node.action, lines, indent + INDENT);
|
|
1041
1702
|
lines.push(`${indent}}`);
|
|
1042
1703
|
}
|
|
1043
1704
|
}
|
|
@@ -1045,24 +1706,14 @@ function emitMenuItem(node, lines, indent, depth) {
|
|
|
1045
1706
|
emitLocComment(node.loc, 'MenuItem', lines, indent);
|
|
1046
1707
|
const label = asCharPtr(node.label);
|
|
1047
1708
|
const shortcut = node.shortcut ? asCharPtr(node.shortcut) : undefined;
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
else {
|
|
1057
|
-
if (shortcut) {
|
|
1058
|
-
lines.push(`${indent}if (imx::renderer::menu_item(${label}, ${shortcut})) {`);
|
|
1059
|
-
}
|
|
1060
|
-
else {
|
|
1061
|
-
lines.push(`${indent}if (imx::renderer::menu_item(${label})) {`);
|
|
1062
|
-
}
|
|
1063
|
-
for (const stmt of node.action) {
|
|
1064
|
-
lines.push(`${indent} ${stmt}`);
|
|
1065
|
-
}
|
|
1709
|
+
const callExpr = shortcut
|
|
1710
|
+
? `imx::renderer::menu_item(${label}, ${shortcut})`
|
|
1711
|
+
: `imx::renderer::menu_item(${label})`;
|
|
1712
|
+
const pressedVar = node.action.length > 0 ? nextWidgetTemp('menu_item_pressed') : undefined;
|
|
1713
|
+
const resultVar = emitBoolWidgetCall(callExpr, node.item, lines, indent, pressedVar);
|
|
1714
|
+
if (node.action.length > 0 && resultVar) {
|
|
1715
|
+
lines.push(`${indent}if (${resultVar}) {`);
|
|
1716
|
+
emitActionStatements(node.action, lines, indent + INDENT);
|
|
1066
1717
|
lines.push(`${indent}}`);
|
|
1067
1718
|
}
|
|
1068
1719
|
}
|
|
@@ -1071,40 +1722,58 @@ function emitTextInput(node, lines, indent) {
|
|
|
1071
1722
|
const label = asCharPtr(node.label && node.label !== '""' ? node.label : `"##textinput_${node.bufferIndex}"`);
|
|
1072
1723
|
if (node.stateVar) {
|
|
1073
1724
|
lines.push(`${indent}{`);
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
lines.push(`${
|
|
1078
|
-
lines.push(`${
|
|
1725
|
+
const innerIndent = indent + INDENT;
|
|
1726
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
1727
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
1728
|
+
lines.push(`${innerIndent}auto& buf = ctx.get_buffer(${node.bufferIndex});`);
|
|
1729
|
+
lines.push(`${innerIndent}buf.sync_from(${node.stateVar}.get());`);
|
|
1730
|
+
const changedVar = nextWidgetTemp('text_input_changed');
|
|
1731
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::text_input(${label}, buf${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
1732
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1733
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(buf.value());`);
|
|
1734
|
+
lines.push(`${innerIndent}}`);
|
|
1079
1735
|
lines.push(`${indent}}`);
|
|
1080
1736
|
}
|
|
1081
1737
|
else if (node.directBind && node.valueExpr) {
|
|
1082
|
-
const
|
|
1083
|
-
const
|
|
1084
|
-
const readExpr = isBound ? `(*${node.valueExpr})` : node.valueExpr;
|
|
1085
|
-
const writeExpr = isBound ? `(*${node.valueExpr})` : node.valueExpr;
|
|
1738
|
+
const readExpr = emitBoundValueExpr(node.valueExpr);
|
|
1739
|
+
const writeExpr = emitBoundValueExpr(node.valueExpr);
|
|
1086
1740
|
lines.push(`${indent}{`);
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
lines.push(`${
|
|
1091
|
-
lines.push(`${
|
|
1741
|
+
const innerIndent = indent + INDENT;
|
|
1742
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
1743
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
1744
|
+
lines.push(`${innerIndent}auto& buf = ctx.get_buffer(${node.bufferIndex});`);
|
|
1745
|
+
lines.push(`${innerIndent}buf.sync_from(${readExpr});`);
|
|
1746
|
+
const changedVar = nextWidgetTemp('text_input_changed');
|
|
1747
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::text_input(${label}, buf${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
1748
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1749
|
+
lines.push(`${innerIndent}${INDENT}${writeExpr} = buf.value();`);
|
|
1750
|
+
lines.push(`${innerIndent}}`);
|
|
1092
1751
|
lines.push(`${indent}}`);
|
|
1093
1752
|
}
|
|
1094
1753
|
else if (node.valueExpr !== undefined) {
|
|
1095
1754
|
lines.push(`${indent}{`);
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1755
|
+
const innerIndent = indent + INDENT;
|
|
1756
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
1757
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
1758
|
+
lines.push(`${innerIndent}auto& buf = ctx.get_buffer(${node.bufferIndex});`);
|
|
1759
|
+
lines.push(`${innerIndent}buf.sync_from(${node.valueExpr});`);
|
|
1760
|
+
const changedVar = nextWidgetTemp('text_input_changed');
|
|
1761
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::text_input(${label}, buf${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
1762
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1099
1763
|
if (node.onChangeExpr) {
|
|
1100
|
-
lines.push(`${
|
|
1764
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
1101
1765
|
}
|
|
1102
|
-
lines.push(`${
|
|
1766
|
+
lines.push(`${innerIndent}}`);
|
|
1103
1767
|
lines.push(`${indent}}`);
|
|
1104
1768
|
}
|
|
1105
1769
|
else {
|
|
1106
|
-
lines.push(`${indent}
|
|
1107
|
-
|
|
1770
|
+
lines.push(`${indent}{`);
|
|
1771
|
+
const innerIndent = indent + INDENT;
|
|
1772
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
1773
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
1774
|
+
lines.push(`${innerIndent}auto& buf_${node.bufferIndex} = ctx.get_buffer(${node.bufferIndex});`);
|
|
1775
|
+
emitBoolWidgetCall(`imx::renderer::text_input(${label}, buf_${node.bufferIndex}${styleArg})`, node.item, lines, innerIndent);
|
|
1776
|
+
lines.push(`${indent}}`);
|
|
1108
1777
|
}
|
|
1109
1778
|
}
|
|
1110
1779
|
function emitCheckbox(node, lines, indent) {
|
|
@@ -1114,31 +1783,55 @@ function emitCheckbox(node, lines, indent) {
|
|
|
1114
1783
|
if (node.stateVar) {
|
|
1115
1784
|
// State-bound case
|
|
1116
1785
|
lines.push(`${indent}{`);
|
|
1117
|
-
|
|
1118
|
-
lines.push(`${
|
|
1119
|
-
|
|
1120
|
-
|
|
1786
|
+
const innerIndent = indent + INDENT;
|
|
1787
|
+
lines.push(`${innerIndent}bool val = ${node.stateVar}.get();`);
|
|
1788
|
+
const changedVar = nextWidgetTemp('checkbox_changed');
|
|
1789
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::checkbox(${label}, &val)`, node.item, lines, innerIndent, changedVar);
|
|
1790
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1791
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
1792
|
+
lines.push(`${innerIndent}}`);
|
|
1121
1793
|
lines.push(`${indent}}`);
|
|
1122
1794
|
}
|
|
1123
1795
|
else if (node.directBind && node.valueExpr) {
|
|
1124
|
-
|
|
1125
|
-
lines.push(`${indent}imx::renderer::checkbox(${label}, ${emitDirectBindPtr(node.valueExpr)});`);
|
|
1796
|
+
emitBoolWidgetCall(`imx::renderer::checkbox(${label}, ${emitDirectBindPtr(node.valueExpr)})`, node.item, lines, indent);
|
|
1126
1797
|
}
|
|
1127
1798
|
else if (node.valueExpr !== undefined) {
|
|
1128
|
-
// Props-bound / expression-bound case
|
|
1129
1799
|
lines.push(`${indent}{`);
|
|
1130
|
-
|
|
1131
|
-
lines.push(`${
|
|
1800
|
+
const innerIndent = indent + INDENT;
|
|
1801
|
+
lines.push(`${innerIndent}bool val = ${node.valueExpr};`);
|
|
1802
|
+
const changedVar = nextWidgetTemp('checkbox_changed');
|
|
1803
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::checkbox(${label}, &val)`, node.item, lines, innerIndent, changedVar);
|
|
1804
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1132
1805
|
if (node.onChangeExpr) {
|
|
1133
|
-
lines.push(`${
|
|
1806
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
1134
1807
|
}
|
|
1135
|
-
lines.push(`${
|
|
1808
|
+
lines.push(`${innerIndent}}`);
|
|
1136
1809
|
lines.push(`${indent}}`);
|
|
1137
1810
|
}
|
|
1138
1811
|
else {
|
|
1139
|
-
|
|
1812
|
+
emitBoolWidgetCall(`imx::renderer::checkbox(${label}, nullptr)`, node.item, lines, indent);
|
|
1140
1813
|
}
|
|
1141
1814
|
}
|
|
1815
|
+
function emitSpacing(node, lines, indent) {
|
|
1816
|
+
emitLocComment(node.loc, 'Spacing', lines, indent);
|
|
1817
|
+
lines.push(`${indent}imx::renderer::spacing();`);
|
|
1818
|
+
}
|
|
1819
|
+
function emitDummy(node, lines, indent) {
|
|
1820
|
+
emitLocComment(node.loc, 'Dummy', lines, indent);
|
|
1821
|
+
lines.push(`${indent}imx::renderer::dummy(${emitFloat(node.width)}, ${emitFloat(node.height)});`);
|
|
1822
|
+
}
|
|
1823
|
+
function emitSameLine(node, lines, indent) {
|
|
1824
|
+
emitLocComment(node.loc, 'SameLine', lines, indent);
|
|
1825
|
+
lines.push(`${indent}imx::renderer::same_line(${emitFloat(node.offset)}, ${emitFloat(node.spacing)});`);
|
|
1826
|
+
}
|
|
1827
|
+
function emitNewLine(node, lines, indent) {
|
|
1828
|
+
emitLocComment(node.loc, 'NewLine', lines, indent);
|
|
1829
|
+
lines.push(`${indent}imx::renderer::new_line();`);
|
|
1830
|
+
}
|
|
1831
|
+
function emitCursor(node, lines, indent) {
|
|
1832
|
+
emitLocComment(node.loc, 'Cursor', lines, indent);
|
|
1833
|
+
lines.push(`${indent}imx::renderer::set_cursor_pos(${emitFloat(node.x)}, ${emitFloat(node.y)});`);
|
|
1834
|
+
}
|
|
1142
1835
|
function emitConditional(node, lines, indent, depth) {
|
|
1143
1836
|
if (node.loc) {
|
|
1144
1837
|
lines.push(`${indent}// ${node.loc.file}:${node.loc.line} conditional`);
|
|
@@ -1176,7 +1869,15 @@ function emitCustomComponent(node, lines, indent) {
|
|
|
1176
1869
|
lines.push(`${indent}${INDENT}${node.name}Props p;`);
|
|
1177
1870
|
for (const [k, v] of propsEntries) {
|
|
1178
1871
|
if (childBound.has(k)) {
|
|
1179
|
-
|
|
1872
|
+
// Check if the value is already a pointer (bound prop of current component)
|
|
1873
|
+
const valPropName = v.startsWith('props.') ? v.slice(6).split('.')[0].split('[')[0] : '';
|
|
1874
|
+
if (currentBoundProps.has(valPropName)) {
|
|
1875
|
+
// Already a pointer — pass through directly. Use &* to block post-processing regex.
|
|
1876
|
+
lines.push(`${indent}${INDENT}p.${k} = &*${v};`);
|
|
1877
|
+
}
|
|
1878
|
+
else {
|
|
1879
|
+
lines.push(`${indent}${INDENT}p.${k} = &${v};`);
|
|
1880
|
+
}
|
|
1180
1881
|
}
|
|
1181
1882
|
else {
|
|
1182
1883
|
lines.push(`${indent}${INDENT}p.${k} = ${v};`);
|
|
@@ -1208,11 +1909,10 @@ function emitNativeWidget(node, lines, indent) {
|
|
|
1208
1909
|
lines.push(`${indent}}`);
|
|
1209
1910
|
}
|
|
1210
1911
|
function ensureFloatLiteral(val) {
|
|
1211
|
-
|
|
1212
|
-
if (
|
|
1213
|
-
return
|
|
1214
|
-
|
|
1215
|
-
return `${val}.0f`;
|
|
1912
|
+
const trimmed = val.trim();
|
|
1913
|
+
if (!/^-?\d+(\.\d+)?$/.test(trimmed))
|
|
1914
|
+
return trimmed;
|
|
1915
|
+
return trimmed.includes('.') ? `${trimmed}f` : `${trimmed}.0f`;
|
|
1216
1916
|
}
|
|
1217
1917
|
function emitSliderFloat(node, lines, indent) {
|
|
1218
1918
|
emitLocComment(node.loc, 'SliderFloat', lines, indent);
|
|
@@ -1221,24 +1921,35 @@ function emitSliderFloat(node, lines, indent) {
|
|
|
1221
1921
|
const max = ensureFloatLiteral(node.max);
|
|
1222
1922
|
if (node.stateVar) {
|
|
1223
1923
|
lines.push(`${indent}{`);
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
lines.push(`${
|
|
1924
|
+
const innerIndent = indent + INDENT;
|
|
1925
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
1926
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
1927
|
+
lines.push(`${innerIndent}float val = ${node.stateVar}.get();`);
|
|
1928
|
+
const changedVar = nextWidgetTemp('slider_float_changed');
|
|
1929
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::slider_float(${label}, &val, ${min}, ${max}${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
1930
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1931
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
1932
|
+
lines.push(`${innerIndent}}`);
|
|
1228
1933
|
lines.push(`${indent}}`);
|
|
1229
1934
|
}
|
|
1230
1935
|
else if (node.directBind && node.valueExpr) {
|
|
1231
|
-
|
|
1232
|
-
|
|
1936
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, indent, lines);
|
|
1937
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
1938
|
+
emitBoolWidgetCall(`imx::renderer::slider_float(${label}, ${emitDirectBindPtr(node.valueExpr)}, ${min}, ${max}${styleArg})`, node.item, lines, indent);
|
|
1233
1939
|
}
|
|
1234
1940
|
else if (node.valueExpr !== undefined) {
|
|
1235
1941
|
lines.push(`${indent}{`);
|
|
1236
|
-
|
|
1237
|
-
|
|
1942
|
+
const innerIndent = indent + INDENT;
|
|
1943
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
1944
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
1945
|
+
lines.push(`${innerIndent}float val = ${node.valueExpr};`);
|
|
1946
|
+
const changedVar = nextWidgetTemp('slider_float_changed');
|
|
1947
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::slider_float(${label}, &val, ${min}, ${max}${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
1948
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1238
1949
|
if (node.onChangeExpr) {
|
|
1239
|
-
lines.push(`${
|
|
1950
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
1240
1951
|
}
|
|
1241
|
-
lines.push(`${
|
|
1952
|
+
lines.push(`${innerIndent}}`);
|
|
1242
1953
|
lines.push(`${indent}}`);
|
|
1243
1954
|
}
|
|
1244
1955
|
}
|
|
@@ -1247,23 +1958,142 @@ function emitSliderInt(node, lines, indent) {
|
|
|
1247
1958
|
const label = asCharPtr(node.label);
|
|
1248
1959
|
if (node.stateVar) {
|
|
1249
1960
|
lines.push(`${indent}{`);
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
lines.push(`${
|
|
1961
|
+
const innerIndent = indent + INDENT;
|
|
1962
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
1963
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
1964
|
+
lines.push(`${innerIndent}int val = ${node.stateVar}.get();`);
|
|
1965
|
+
const changedVar = nextWidgetTemp('slider_int_changed');
|
|
1966
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::slider_int(${label}, &val, ${node.min}, ${node.max}${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
1967
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1968
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
1969
|
+
lines.push(`${innerIndent}}`);
|
|
1254
1970
|
lines.push(`${indent}}`);
|
|
1255
1971
|
}
|
|
1256
1972
|
else if (node.directBind && node.valueExpr) {
|
|
1257
|
-
|
|
1973
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, indent, lines);
|
|
1974
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
1975
|
+
emitBoolWidgetCall(`imx::renderer::slider_int(${label}, ${emitDirectBindPtr(node.valueExpr)}, ${node.min}, ${node.max}${styleArg})`, node.item, lines, indent);
|
|
1258
1976
|
}
|
|
1259
1977
|
else if (node.valueExpr !== undefined) {
|
|
1260
1978
|
lines.push(`${indent}{`);
|
|
1261
|
-
|
|
1262
|
-
|
|
1979
|
+
const innerIndent = indent + INDENT;
|
|
1980
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
1981
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
1982
|
+
lines.push(`${innerIndent}int val = ${node.valueExpr};`);
|
|
1983
|
+
const changedVar = nextWidgetTemp('slider_int_changed');
|
|
1984
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::slider_int(${label}, &val, ${node.min}, ${node.max}${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
1985
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1263
1986
|
if (node.onChangeExpr) {
|
|
1264
|
-
lines.push(`${
|
|
1987
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
1265
1988
|
}
|
|
1266
|
-
lines.push(`${
|
|
1989
|
+
lines.push(`${innerIndent}}`);
|
|
1990
|
+
lines.push(`${indent}}`);
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
function emitVSliderFloat(node, lines, indent) {
|
|
1994
|
+
emitLocComment(node.loc, 'VSliderFloat', lines, indent);
|
|
1995
|
+
const label = asCharPtr(node.label);
|
|
1996
|
+
const min = ensureFloatLiteral(node.min);
|
|
1997
|
+
const max = ensureFloatLiteral(node.max);
|
|
1998
|
+
const width = emitFloat(node.width);
|
|
1999
|
+
const height = emitFloat(node.height);
|
|
2000
|
+
if (node.stateVar) {
|
|
2001
|
+
lines.push(`${indent}{`);
|
|
2002
|
+
const innerIndent = indent + INDENT;
|
|
2003
|
+
lines.push(`${innerIndent}float val = ${node.stateVar}.get();`);
|
|
2004
|
+
const changedVar = nextWidgetTemp('vslider_float_changed');
|
|
2005
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::vslider_float(${label}, ${width}, ${height}, &val, ${min}, ${max})`, node.item, lines, innerIndent, changedVar);
|
|
2006
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2007
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
2008
|
+
lines.push(`${innerIndent}}`);
|
|
2009
|
+
lines.push(`${indent}}`);
|
|
2010
|
+
}
|
|
2011
|
+
else if (node.directBind && node.valueExpr) {
|
|
2012
|
+
emitBoolWidgetCall(`imx::renderer::vslider_float(${label}, ${width}, ${height}, ${emitDirectBindPtr(node.valueExpr)}, ${min}, ${max})`, node.item, lines, indent);
|
|
2013
|
+
}
|
|
2014
|
+
else if (node.valueExpr !== undefined) {
|
|
2015
|
+
lines.push(`${indent}{`);
|
|
2016
|
+
const innerIndent = indent + INDENT;
|
|
2017
|
+
lines.push(`${innerIndent}float val = ${node.valueExpr};`);
|
|
2018
|
+
const changedVar = nextWidgetTemp('vslider_float_changed');
|
|
2019
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::vslider_float(${label}, ${width}, ${height}, &val, ${min}, ${max})`, node.item, lines, innerIndent, changedVar);
|
|
2020
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2021
|
+
if (node.onChangeExpr) {
|
|
2022
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
2023
|
+
}
|
|
2024
|
+
lines.push(`${innerIndent}}`);
|
|
2025
|
+
lines.push(`${indent}}`);
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
function emitVSliderInt(node, lines, indent) {
|
|
2029
|
+
emitLocComment(node.loc, 'VSliderInt', lines, indent);
|
|
2030
|
+
const label = asCharPtr(node.label);
|
|
2031
|
+
const width = emitFloat(node.width);
|
|
2032
|
+
const height = emitFloat(node.height);
|
|
2033
|
+
if (node.stateVar) {
|
|
2034
|
+
lines.push(`${indent}{`);
|
|
2035
|
+
const innerIndent = indent + INDENT;
|
|
2036
|
+
lines.push(`${innerIndent}int val = ${node.stateVar}.get();`);
|
|
2037
|
+
const changedVar = nextWidgetTemp('vslider_int_changed');
|
|
2038
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::vslider_int(${label}, ${width}, ${height}, &val, ${node.min}, ${node.max})`, node.item, lines, innerIndent, changedVar);
|
|
2039
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2040
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
2041
|
+
lines.push(`${innerIndent}}`);
|
|
2042
|
+
lines.push(`${indent}}`);
|
|
2043
|
+
}
|
|
2044
|
+
else if (node.directBind && node.valueExpr) {
|
|
2045
|
+
emitBoolWidgetCall(`imx::renderer::vslider_int(${label}, ${width}, ${height}, ${emitDirectBindPtr(node.valueExpr)}, ${node.min}, ${node.max})`, node.item, lines, indent);
|
|
2046
|
+
}
|
|
2047
|
+
else if (node.valueExpr !== undefined) {
|
|
2048
|
+
lines.push(`${indent}{`);
|
|
2049
|
+
const innerIndent = indent + INDENT;
|
|
2050
|
+
lines.push(`${innerIndent}int val = ${node.valueExpr};`);
|
|
2051
|
+
const changedVar = nextWidgetTemp('vslider_int_changed');
|
|
2052
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::vslider_int(${label}, ${width}, ${height}, &val, ${node.min}, ${node.max})`, node.item, lines, innerIndent, changedVar);
|
|
2053
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2054
|
+
if (node.onChangeExpr) {
|
|
2055
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
2056
|
+
}
|
|
2057
|
+
lines.push(`${innerIndent}}`);
|
|
2058
|
+
lines.push(`${indent}}`);
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
function emitSliderAngle(node, lines, indent) {
|
|
2062
|
+
emitLocComment(node.loc, 'SliderAngle', lines, indent);
|
|
2063
|
+
const label = asCharPtr(node.label);
|
|
2064
|
+
const min = ensureFloatLiteral(node.min);
|
|
2065
|
+
const max = ensureFloatLiteral(node.max);
|
|
2066
|
+
if (node.stateVar) {
|
|
2067
|
+
lines.push(`${indent}{`);
|
|
2068
|
+
const innerIndent = indent + INDENT;
|
|
2069
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2070
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2071
|
+
lines.push(`${innerIndent}float val = ${node.stateVar}.get();`);
|
|
2072
|
+
const changedVar = nextWidgetTemp('slider_angle_changed');
|
|
2073
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::slider_angle(${label}, &val, ${min}, ${max}${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2074
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2075
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
2076
|
+
lines.push(`${innerIndent}}`);
|
|
2077
|
+
lines.push(`${indent}}`);
|
|
2078
|
+
}
|
|
2079
|
+
else if (node.directBind && node.valueExpr) {
|
|
2080
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, indent, lines);
|
|
2081
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2082
|
+
emitBoolWidgetCall(`imx::renderer::slider_angle(${label}, ${emitDirectBindPtr(node.valueExpr)}, ${min}, ${max}${styleArg})`, node.item, lines, indent);
|
|
2083
|
+
}
|
|
2084
|
+
else if (node.valueExpr !== undefined) {
|
|
2085
|
+
lines.push(`${indent}{`);
|
|
2086
|
+
const innerIndent = indent + INDENT;
|
|
2087
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2088
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2089
|
+
lines.push(`${innerIndent}float val = ${node.valueExpr};`);
|
|
2090
|
+
const changedVar = nextWidgetTemp('slider_angle_changed');
|
|
2091
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::slider_angle(${label}, &val, ${min}, ${max}${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2092
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2093
|
+
if (node.onChangeExpr) {
|
|
2094
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
2095
|
+
}
|
|
2096
|
+
lines.push(`${innerIndent}}`);
|
|
1267
2097
|
lines.push(`${indent}}`);
|
|
1268
2098
|
}
|
|
1269
2099
|
}
|
|
@@ -1273,23 +2103,35 @@ function emitDragFloat(node, lines, indent) {
|
|
|
1273
2103
|
const speed = ensureFloatLiteral(node.speed);
|
|
1274
2104
|
if (node.stateVar) {
|
|
1275
2105
|
lines.push(`${indent}{`);
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
lines.push(`${
|
|
2106
|
+
const innerIndent = indent + INDENT;
|
|
2107
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2108
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2109
|
+
lines.push(`${innerIndent}float val = ${node.stateVar}.get();`);
|
|
2110
|
+
const changedVar = nextWidgetTemp('drag_float_changed');
|
|
2111
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::drag_float(${label}, &val, ${speed}${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2112
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2113
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
2114
|
+
lines.push(`${innerIndent}}`);
|
|
1280
2115
|
lines.push(`${indent}}`);
|
|
1281
2116
|
}
|
|
1282
2117
|
else if (node.directBind && node.valueExpr) {
|
|
1283
|
-
|
|
2118
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, indent, lines);
|
|
2119
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2120
|
+
emitBoolWidgetCall(`imx::renderer::drag_float(${label}, ${emitDirectBindPtr(node.valueExpr)}, ${speed}${styleArg})`, node.item, lines, indent);
|
|
1284
2121
|
}
|
|
1285
2122
|
else if (node.valueExpr !== undefined) {
|
|
1286
2123
|
lines.push(`${indent}{`);
|
|
1287
|
-
|
|
1288
|
-
|
|
2124
|
+
const innerIndent = indent + INDENT;
|
|
2125
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2126
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2127
|
+
lines.push(`${innerIndent}float val = ${node.valueExpr};`);
|
|
2128
|
+
const changedVar = nextWidgetTemp('drag_float_changed');
|
|
2129
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::drag_float(${label}, &val, ${speed}${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2130
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1289
2131
|
if (node.onChangeExpr) {
|
|
1290
|
-
lines.push(`${
|
|
2132
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
1291
2133
|
}
|
|
1292
|
-
lines.push(`${
|
|
2134
|
+
lines.push(`${innerIndent}}`);
|
|
1293
2135
|
lines.push(`${indent}}`);
|
|
1294
2136
|
}
|
|
1295
2137
|
}
|
|
@@ -1299,23 +2141,35 @@ function emitDragInt(node, lines, indent) {
|
|
|
1299
2141
|
const speed = ensureFloatLiteral(node.speed);
|
|
1300
2142
|
if (node.stateVar) {
|
|
1301
2143
|
lines.push(`${indent}{`);
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
lines.push(`${
|
|
2144
|
+
const innerIndent = indent + INDENT;
|
|
2145
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2146
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2147
|
+
lines.push(`${innerIndent}int val = ${node.stateVar}.get();`);
|
|
2148
|
+
const changedVar = nextWidgetTemp('drag_int_changed');
|
|
2149
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::drag_int(${label}, &val, ${speed}${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2150
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2151
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
2152
|
+
lines.push(`${innerIndent}}`);
|
|
1306
2153
|
lines.push(`${indent}}`);
|
|
1307
2154
|
}
|
|
1308
2155
|
else if (node.directBind && node.valueExpr) {
|
|
1309
|
-
|
|
2156
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, indent, lines);
|
|
2157
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2158
|
+
emitBoolWidgetCall(`imx::renderer::drag_int(${label}, ${emitDirectBindPtr(node.valueExpr)}, ${speed}${styleArg})`, node.item, lines, indent);
|
|
1310
2159
|
}
|
|
1311
2160
|
else if (node.valueExpr !== undefined) {
|
|
1312
2161
|
lines.push(`${indent}{`);
|
|
1313
|
-
|
|
1314
|
-
|
|
2162
|
+
const innerIndent = indent + INDENT;
|
|
2163
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2164
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2165
|
+
lines.push(`${innerIndent}int val = ${node.valueExpr};`);
|
|
2166
|
+
const changedVar = nextWidgetTemp('drag_int_changed');
|
|
2167
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::drag_int(${label}, &val, ${speed}${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2168
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1315
2169
|
if (node.onChangeExpr) {
|
|
1316
|
-
lines.push(`${
|
|
2170
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
1317
2171
|
}
|
|
1318
|
-
lines.push(`${
|
|
2172
|
+
lines.push(`${innerIndent}}`);
|
|
1319
2173
|
lines.push(`${indent}}`);
|
|
1320
2174
|
}
|
|
1321
2175
|
}
|
|
@@ -1327,28 +2181,41 @@ function emitCombo(node, lines, indent) {
|
|
|
1327
2181
|
const varName = `combo_items_${comboCounter++}`;
|
|
1328
2182
|
if (node.stateVar) {
|
|
1329
2183
|
lines.push(`${indent}{`);
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
lines.push(`${
|
|
1334
|
-
lines.push(`${
|
|
2184
|
+
const innerIndent = indent + INDENT;
|
|
2185
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2186
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2187
|
+
lines.push(`${innerIndent}const char* ${varName}[] = {${itemsList.join(', ')}};`);
|
|
2188
|
+
lines.push(`${innerIndent}int val = ${node.stateVar}.get();`);
|
|
2189
|
+
const changedVar = nextWidgetTemp('combo_changed');
|
|
2190
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::combo(${label}, &val, ${varName}, ${count}${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2191
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2192
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
2193
|
+
lines.push(`${innerIndent}}`);
|
|
1335
2194
|
lines.push(`${indent}}`);
|
|
1336
2195
|
}
|
|
1337
2196
|
else if (node.directBind && node.valueExpr) {
|
|
1338
2197
|
lines.push(`${indent}{`);
|
|
1339
|
-
|
|
1340
|
-
|
|
2198
|
+
const innerIndent = indent + INDENT;
|
|
2199
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2200
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2201
|
+
lines.push(`${innerIndent}const char* ${varName}[] = {${itemsList.join(', ')}};`);
|
|
2202
|
+
emitBoolWidgetCall(`imx::renderer::combo(${label}, ${emitDirectBindPtr(node.valueExpr)}, ${varName}, ${count}${styleArg})`, node.item, lines, innerIndent);
|
|
1341
2203
|
lines.push(`${indent}}`);
|
|
1342
2204
|
}
|
|
1343
2205
|
else if (node.valueExpr !== undefined) {
|
|
1344
2206
|
lines.push(`${indent}{`);
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
2207
|
+
const innerIndent = indent + INDENT;
|
|
2208
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2209
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2210
|
+
lines.push(`${innerIndent}const char* ${varName}[] = {${itemsList.join(', ')}};`);
|
|
2211
|
+
lines.push(`${innerIndent}int val = ${node.valueExpr};`);
|
|
2212
|
+
const changedVar = nextWidgetTemp('combo_changed');
|
|
2213
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::combo(${label}, &val, ${varName}, ${count}${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2214
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1348
2215
|
if (node.onChangeExpr) {
|
|
1349
|
-
lines.push(`${
|
|
2216
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
1350
2217
|
}
|
|
1351
|
-
lines.push(`${
|
|
2218
|
+
lines.push(`${innerIndent}}`);
|
|
1352
2219
|
lines.push(`${indent}}`);
|
|
1353
2220
|
}
|
|
1354
2221
|
}
|
|
@@ -1357,23 +2224,35 @@ function emitInputInt(node, lines, indent) {
|
|
|
1357
2224
|
const label = asCharPtr(node.label);
|
|
1358
2225
|
if (node.stateVar) {
|
|
1359
2226
|
lines.push(`${indent}{`);
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
lines.push(`${
|
|
2227
|
+
const innerIndent = indent + INDENT;
|
|
2228
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2229
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2230
|
+
lines.push(`${innerIndent}int val = ${node.stateVar}.get();`);
|
|
2231
|
+
const changedVar = nextWidgetTemp('input_int_changed');
|
|
2232
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::input_int(${label}, &val${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2233
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2234
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
2235
|
+
lines.push(`${innerIndent}}`);
|
|
1364
2236
|
lines.push(`${indent}}`);
|
|
1365
2237
|
}
|
|
1366
2238
|
else if (node.directBind && node.valueExpr) {
|
|
1367
|
-
|
|
2239
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, indent, lines);
|
|
2240
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2241
|
+
emitBoolWidgetCall(`imx::renderer::input_int(${label}, ${emitDirectBindPtr(node.valueExpr)}${styleArg})`, node.item, lines, indent);
|
|
1368
2242
|
}
|
|
1369
2243
|
else if (node.valueExpr !== undefined) {
|
|
1370
2244
|
lines.push(`${indent}{`);
|
|
1371
|
-
|
|
1372
|
-
|
|
2245
|
+
const innerIndent = indent + INDENT;
|
|
2246
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2247
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2248
|
+
lines.push(`${innerIndent}int val = ${node.valueExpr};`);
|
|
2249
|
+
const changedVar = nextWidgetTemp('input_int_changed');
|
|
2250
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::input_int(${label}, &val${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2251
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1373
2252
|
if (node.onChangeExpr) {
|
|
1374
|
-
lines.push(`${
|
|
2253
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
1375
2254
|
}
|
|
1376
|
-
lines.push(`${
|
|
2255
|
+
lines.push(`${innerIndent}}`);
|
|
1377
2256
|
lines.push(`${indent}}`);
|
|
1378
2257
|
}
|
|
1379
2258
|
}
|
|
@@ -1382,23 +2261,35 @@ function emitInputFloat(node, lines, indent) {
|
|
|
1382
2261
|
const label = asCharPtr(node.label);
|
|
1383
2262
|
if (node.stateVar) {
|
|
1384
2263
|
lines.push(`${indent}{`);
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
lines.push(`${
|
|
2264
|
+
const innerIndent = indent + INDENT;
|
|
2265
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2266
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2267
|
+
lines.push(`${innerIndent}float val = ${node.stateVar}.get();`);
|
|
2268
|
+
const changedVar = nextWidgetTemp('input_float_changed');
|
|
2269
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::input_float(${label}, &val${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2270
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2271
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
2272
|
+
lines.push(`${innerIndent}}`);
|
|
1389
2273
|
lines.push(`${indent}}`);
|
|
1390
2274
|
}
|
|
1391
2275
|
else if (node.directBind && node.valueExpr) {
|
|
1392
|
-
|
|
2276
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, indent, lines);
|
|
2277
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2278
|
+
emitBoolWidgetCall(`imx::renderer::input_float(${label}, ${emitDirectBindPtr(node.valueExpr)}${styleArg})`, node.item, lines, indent);
|
|
1393
2279
|
}
|
|
1394
2280
|
else if (node.valueExpr !== undefined) {
|
|
1395
2281
|
lines.push(`${indent}{`);
|
|
1396
|
-
|
|
1397
|
-
|
|
2282
|
+
const innerIndent = indent + INDENT;
|
|
2283
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2284
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2285
|
+
lines.push(`${innerIndent}float val = ${node.valueExpr};`);
|
|
2286
|
+
const changedVar = nextWidgetTemp('input_float_changed');
|
|
2287
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::input_float(${label}, &val${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2288
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1398
2289
|
if (node.onChangeExpr) {
|
|
1399
|
-
lines.push(`${
|
|
2290
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
1400
2291
|
}
|
|
1401
|
-
lines.push(`${
|
|
2292
|
+
lines.push(`${innerIndent}}`);
|
|
1402
2293
|
lines.push(`${indent}}`);
|
|
1403
2294
|
}
|
|
1404
2295
|
}
|
|
@@ -1407,26 +2298,74 @@ function emitColorEdit(node, lines, indent) {
|
|
|
1407
2298
|
const label = asCharPtr(node.label);
|
|
1408
2299
|
if (node.stateVar) {
|
|
1409
2300
|
lines.push(`${indent}{`);
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
lines.push(`${
|
|
2301
|
+
const innerIndent = indent + INDENT;
|
|
2302
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2303
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2304
|
+
lines.push(`${innerIndent}auto val = ${node.stateVar}.get();`);
|
|
2305
|
+
const changedVar = nextWidgetTemp('color_edit_changed');
|
|
2306
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::color_edit(${label}, val.data()${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2307
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2308
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
2309
|
+
lines.push(`${innerIndent}}`);
|
|
1414
2310
|
lines.push(`${indent}}`);
|
|
1415
2311
|
}
|
|
1416
2312
|
else if (node.directBind && node.valueExpr) {
|
|
1417
|
-
const
|
|
1418
|
-
const
|
|
1419
|
-
const
|
|
1420
|
-
|
|
2313
|
+
const dataExpr = `${emitBoundValueExpr(node.valueExpr)}.data()`;
|
|
2314
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, indent, lines);
|
|
2315
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2316
|
+
emitBoolWidgetCall(`imx::renderer::color_edit(${label}, ${dataExpr}${styleArg})`, node.item, lines, indent);
|
|
1421
2317
|
}
|
|
1422
2318
|
else if (node.valueExpr !== undefined) {
|
|
1423
2319
|
lines.push(`${indent}{`);
|
|
1424
|
-
|
|
1425
|
-
|
|
2320
|
+
const innerIndent = indent + INDENT;
|
|
2321
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2322
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2323
|
+
lines.push(`${innerIndent}auto val = ${node.valueExpr};`);
|
|
2324
|
+
const changedVar = nextWidgetTemp('color_edit_changed');
|
|
2325
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::color_edit(${label}, val.data()${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2326
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1426
2327
|
if (node.onChangeExpr) {
|
|
1427
|
-
lines.push(`${
|
|
2328
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
1428
2329
|
}
|
|
1429
|
-
lines.push(`${
|
|
2330
|
+
lines.push(`${innerIndent}}`);
|
|
2331
|
+
lines.push(`${indent}}`);
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
function emitColorEdit3(node, lines, indent) {
|
|
2335
|
+
emitLocComment(node.loc, 'ColorEdit3', lines, indent);
|
|
2336
|
+
const label = asCharPtr(node.label);
|
|
2337
|
+
if (node.stateVar) {
|
|
2338
|
+
lines.push(`${indent}{`);
|
|
2339
|
+
const innerIndent = indent + INDENT;
|
|
2340
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2341
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2342
|
+
lines.push(`${innerIndent}auto val = ${node.stateVar}.get();`);
|
|
2343
|
+
const changedVar = nextWidgetTemp('color_edit3_changed');
|
|
2344
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::color_edit3(${label}, val.data()${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2345
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2346
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
2347
|
+
lines.push(`${innerIndent}}`);
|
|
2348
|
+
lines.push(`${indent}}`);
|
|
2349
|
+
}
|
|
2350
|
+
else if (node.directBind && node.valueExpr) {
|
|
2351
|
+
const dataExpr = `${emitBoundValueExpr(node.valueExpr)}.data()`;
|
|
2352
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, indent, lines);
|
|
2353
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2354
|
+
emitBoolWidgetCall(`imx::renderer::color_edit3(${label}, ${dataExpr}${styleArg})`, node.item, lines, indent);
|
|
2355
|
+
}
|
|
2356
|
+
else if (node.valueExpr !== undefined) {
|
|
2357
|
+
lines.push(`${indent}{`);
|
|
2358
|
+
const innerIndent = indent + INDENT;
|
|
2359
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2360
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2361
|
+
lines.push(`${innerIndent}auto val = ${node.valueExpr};`);
|
|
2362
|
+
const changedVar = nextWidgetTemp('color_edit3_changed');
|
|
2363
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::color_edit3(${label}, val.data()${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2364
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2365
|
+
if (node.onChangeExpr) {
|
|
2366
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
2367
|
+
}
|
|
2368
|
+
lines.push(`${innerIndent}}`);
|
|
1430
2369
|
lines.push(`${indent}}`);
|
|
1431
2370
|
}
|
|
1432
2371
|
}
|
|
@@ -1438,28 +2377,41 @@ function emitListBox(node, lines, indent) {
|
|
|
1438
2377
|
const varName = `listbox_items_${listBoxCounter++}`;
|
|
1439
2378
|
if (node.stateVar) {
|
|
1440
2379
|
lines.push(`${indent}{`);
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
lines.push(`${
|
|
1445
|
-
lines.push(`${
|
|
2380
|
+
const innerIndent = indent + INDENT;
|
|
2381
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2382
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2383
|
+
lines.push(`${innerIndent}const char* ${varName}[] = {${itemsList.join(', ')}};`);
|
|
2384
|
+
lines.push(`${innerIndent}int val = ${node.stateVar}.get();`);
|
|
2385
|
+
const changedVar = nextWidgetTemp('list_box_changed');
|
|
2386
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::list_box(${label}, &val, ${varName}, ${count}${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2387
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2388
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
2389
|
+
lines.push(`${innerIndent}}`);
|
|
1446
2390
|
lines.push(`${indent}}`);
|
|
1447
2391
|
}
|
|
1448
2392
|
else if (node.directBind && node.valueExpr) {
|
|
1449
2393
|
lines.push(`${indent}{`);
|
|
1450
|
-
|
|
1451
|
-
|
|
2394
|
+
const innerIndent = indent + INDENT;
|
|
2395
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2396
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2397
|
+
lines.push(`${innerIndent}const char* ${varName}[] = {${itemsList.join(', ')}};`);
|
|
2398
|
+
emitBoolWidgetCall(`imx::renderer::list_box(${label}, ${emitDirectBindPtr(node.valueExpr)}, ${varName}, ${count}${styleArg})`, node.item, lines, innerIndent);
|
|
1452
2399
|
lines.push(`${indent}}`);
|
|
1453
2400
|
}
|
|
1454
2401
|
else if (node.valueExpr !== undefined) {
|
|
1455
2402
|
lines.push(`${indent}{`);
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
2403
|
+
const innerIndent = indent + INDENT;
|
|
2404
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2405
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2406
|
+
lines.push(`${innerIndent}const char* ${varName}[] = {${itemsList.join(', ')}};`);
|
|
2407
|
+
lines.push(`${innerIndent}int val = ${node.valueExpr};`);
|
|
2408
|
+
const changedVar = nextWidgetTemp('list_box_changed');
|
|
2409
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::list_box(${label}, &val, ${varName}, ${count}${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2410
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1459
2411
|
if (node.onChangeExpr) {
|
|
1460
|
-
lines.push(`${
|
|
2412
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
1461
2413
|
}
|
|
1462
|
-
lines.push(`${
|
|
2414
|
+
lines.push(`${innerIndent}}`);
|
|
1463
2415
|
lines.push(`${indent}}`);
|
|
1464
2416
|
}
|
|
1465
2417
|
}
|
|
@@ -1476,6 +2428,13 @@ function emitTooltip(node, lines, indent) {
|
|
|
1476
2428
|
emitLocComment(node.loc, 'Tooltip', lines, indent);
|
|
1477
2429
|
lines.push(`${indent}imx::renderer::tooltip(${node.text});`);
|
|
1478
2430
|
}
|
|
2431
|
+
function emitShortcut(node, lines, indent) {
|
|
2432
|
+
emitLocComment(node.loc, 'Shortcut', lines, indent);
|
|
2433
|
+
const keys = asCharPtr(node.keys);
|
|
2434
|
+
lines.push(`${indent}if (imx::renderer::shortcut_pressed(${keys})) {`);
|
|
2435
|
+
emitActionStatements(node.action, lines, indent + INDENT);
|
|
2436
|
+
lines.push(`${indent}}`);
|
|
2437
|
+
}
|
|
1479
2438
|
function emitBulletText(node, lines, indent) {
|
|
1480
2439
|
emitLocComment(node.loc, 'BulletText', lines, indent);
|
|
1481
2440
|
if (node.args.length === 0) {
|
|
@@ -1496,40 +2455,47 @@ function emitLabelText(node, lines, indent) {
|
|
|
1496
2455
|
}
|
|
1497
2456
|
function emitSelectable(node, lines, indent) {
|
|
1498
2457
|
emitLocComment(node.loc, 'Selectable', lines, indent);
|
|
2458
|
+
if (node.selectionIndex) {
|
|
2459
|
+
lines.push(`${indent}imx::renderer::set_next_item_selection_data(${node.selectionIndex});`);
|
|
2460
|
+
}
|
|
1499
2461
|
const label = asCharPtr(node.label);
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
}
|
|
2462
|
+
const flagsArg = node.flags ? `, ${node.flags}` : '';
|
|
2463
|
+
const pressedVar = node.action.length > 0 ? nextWidgetTemp('selectable_pressed') : undefined;
|
|
2464
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::selectable(${label}, ${node.selected}${flagsArg})`, node.item, lines, indent, pressedVar);
|
|
2465
|
+
if (node.action.length > 0 && resultVar) {
|
|
2466
|
+
lines.push(`${indent}if (${resultVar}) {`);
|
|
2467
|
+
emitActionStatements(node.action, lines, indent + INDENT);
|
|
1505
2468
|
lines.push(`${indent}}`);
|
|
1506
2469
|
}
|
|
1507
|
-
else {
|
|
1508
|
-
lines.push(`${indent}imx::renderer::selectable(${label}, ${node.selected});`);
|
|
1509
|
-
}
|
|
1510
2470
|
}
|
|
1511
2471
|
function emitRadio(node, lines, indent) {
|
|
1512
2472
|
emitLocComment(node.loc, 'Radio', lines, indent);
|
|
1513
2473
|
const label = asCharPtr(node.label);
|
|
1514
2474
|
if (node.stateVar) {
|
|
1515
2475
|
lines.push(`${indent}{`);
|
|
1516
|
-
|
|
1517
|
-
lines.push(`${
|
|
1518
|
-
|
|
1519
|
-
|
|
2476
|
+
const innerIndent = indent + INDENT;
|
|
2477
|
+
lines.push(`${innerIndent}int val = ${node.stateVar}.get();`);
|
|
2478
|
+
const changedVar = nextWidgetTemp('radio_changed');
|
|
2479
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::radio(${label}, &val, ${node.index})`, node.item, lines, innerIndent, changedVar);
|
|
2480
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2481
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
2482
|
+
lines.push(`${innerIndent}}`);
|
|
1520
2483
|
lines.push(`${indent}}`);
|
|
1521
2484
|
}
|
|
1522
2485
|
else if (node.directBind && node.valueExpr) {
|
|
1523
|
-
|
|
2486
|
+
emitBoolWidgetCall(`imx::renderer::radio(${label}, ${emitDirectBindPtr(node.valueExpr)}, ${node.index})`, node.item, lines, indent);
|
|
1524
2487
|
}
|
|
1525
2488
|
else if (node.valueExpr !== undefined) {
|
|
1526
2489
|
lines.push(`${indent}{`);
|
|
1527
|
-
|
|
1528
|
-
lines.push(`${
|
|
2490
|
+
const innerIndent = indent + INDENT;
|
|
2491
|
+
lines.push(`${innerIndent}int val = ${node.valueExpr};`);
|
|
2492
|
+
const changedVar = nextWidgetTemp('radio_changed');
|
|
2493
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::radio(${label}, &val, ${node.index})`, node.item, lines, innerIndent, changedVar);
|
|
2494
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1529
2495
|
if (node.onChangeExpr) {
|
|
1530
|
-
lines.push(`${
|
|
2496
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
1531
2497
|
}
|
|
1532
|
-
lines.push(`${
|
|
2498
|
+
lines.push(`${innerIndent}}`);
|
|
1533
2499
|
lines.push(`${indent}}`);
|
|
1534
2500
|
}
|
|
1535
2501
|
}
|
|
@@ -1537,17 +2503,40 @@ function emitInputTextMultiline(node, lines, indent) {
|
|
|
1537
2503
|
emitLocComment(node.loc, 'InputTextMultiline', lines, indent);
|
|
1538
2504
|
lines.push(`${indent}{`);
|
|
1539
2505
|
const innerIndent = indent + INDENT;
|
|
1540
|
-
const styleVar =
|
|
2506
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
1541
2507
|
lines.push(`${innerIndent}auto& buf = ctx.get_buffer(${node.bufferIndex});`);
|
|
1542
|
-
if (node.stateVar) {
|
|
1543
|
-
lines.push(`${innerIndent}buf.sync_from(${node.stateVar}.get());`);
|
|
1544
|
-
}
|
|
1545
2508
|
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
1546
|
-
lines.push(`${innerIndent}if (imx::renderer::text_input_multiline(${node.label}, buf${styleArg})) {`);
|
|
1547
2509
|
if (node.stateVar) {
|
|
2510
|
+
lines.push(`${innerIndent}buf.sync_from(${node.stateVar}.get());`);
|
|
2511
|
+
const changedVar = nextWidgetTemp('text_input_multiline_changed');
|
|
2512
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::text_input_multiline(${node.label}, buf${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2513
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1548
2514
|
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(buf.value());`);
|
|
2515
|
+
lines.push(`${innerIndent}}`);
|
|
2516
|
+
}
|
|
2517
|
+
else if (node.directBind && node.valueExpr) {
|
|
2518
|
+
const readExpr = emitBoundValueExpr(node.valueExpr);
|
|
2519
|
+
const writeExpr = emitBoundValueExpr(node.valueExpr);
|
|
2520
|
+
lines.push(`${innerIndent}buf.sync_from(${readExpr});`);
|
|
2521
|
+
const changedVar = nextWidgetTemp('text_input_multiline_changed');
|
|
2522
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::text_input_multiline(${node.label}, buf${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2523
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2524
|
+
lines.push(`${innerIndent}${INDENT}${writeExpr} = buf.value();`);
|
|
2525
|
+
lines.push(`${innerIndent}}`);
|
|
2526
|
+
}
|
|
2527
|
+
else if (node.valueExpr !== undefined) {
|
|
2528
|
+
lines.push(`${innerIndent}buf.sync_from(${node.valueExpr});`);
|
|
2529
|
+
const changedVar = nextWidgetTemp('text_input_multiline_changed');
|
|
2530
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::text_input_multiline(${node.label}, buf${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2531
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2532
|
+
if (node.onChangeExpr) {
|
|
2533
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
2534
|
+
}
|
|
2535
|
+
lines.push(`${innerIndent}}`);
|
|
2536
|
+
}
|
|
2537
|
+
else {
|
|
2538
|
+
emitBoolWidgetCall(`imx::renderer::text_input_multiline(${node.label}, buf${styleArg})`, node.item, lines, innerIndent);
|
|
1549
2539
|
}
|
|
1550
|
-
lines.push(`${innerIndent}}`);
|
|
1551
2540
|
lines.push(`${indent}}`);
|
|
1552
2541
|
}
|
|
1553
2542
|
function emitColorPicker(node, lines, indent) {
|
|
@@ -1555,26 +2544,68 @@ function emitColorPicker(node, lines, indent) {
|
|
|
1555
2544
|
const label = asCharPtr(node.label);
|
|
1556
2545
|
if (node.stateVar) {
|
|
1557
2546
|
lines.push(`${indent}{`);
|
|
1558
|
-
|
|
1559
|
-
lines.push(`${
|
|
1560
|
-
|
|
1561
|
-
|
|
2547
|
+
const innerIndent = indent + INDENT;
|
|
2548
|
+
lines.push(`${innerIndent}auto val = ${node.stateVar}.get();`);
|
|
2549
|
+
const changedVar = nextWidgetTemp('color_picker_changed');
|
|
2550
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::color_picker(${label}, val.data())`, node.item, lines, innerIndent, changedVar);
|
|
2551
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2552
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
2553
|
+
lines.push(`${innerIndent}}`);
|
|
1562
2554
|
lines.push(`${indent}}`);
|
|
1563
2555
|
}
|
|
1564
2556
|
else if (node.directBind && node.valueExpr) {
|
|
1565
|
-
const
|
|
1566
|
-
|
|
1567
|
-
const dataExpr = isBound ? `(${node.valueExpr})->data()` : `${node.valueExpr}.data()`;
|
|
1568
|
-
lines.push(`${indent}imx::renderer::color_picker(${label}, ${dataExpr});`);
|
|
2557
|
+
const dataExpr = `${emitBoundValueExpr(node.valueExpr)}.data()`;
|
|
2558
|
+
emitBoolWidgetCall(`imx::renderer::color_picker(${label}, ${dataExpr})`, node.item, lines, indent);
|
|
1569
2559
|
}
|
|
1570
2560
|
else if (node.valueExpr !== undefined) {
|
|
1571
2561
|
lines.push(`${indent}{`);
|
|
1572
|
-
|
|
1573
|
-
lines.push(`${
|
|
2562
|
+
const innerIndent = indent + INDENT;
|
|
2563
|
+
lines.push(`${innerIndent}auto val = ${node.valueExpr};`);
|
|
2564
|
+
const changedVar = nextWidgetTemp('color_picker_changed');
|
|
2565
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::color_picker(${label}, val.data())`, node.item, lines, innerIndent, changedVar);
|
|
2566
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
1574
2567
|
if (node.onChangeExpr) {
|
|
1575
|
-
lines.push(`${
|
|
2568
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
1576
2569
|
}
|
|
1577
|
-
lines.push(`${
|
|
2570
|
+
lines.push(`${innerIndent}}`);
|
|
2571
|
+
lines.push(`${indent}}`);
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
function emitColorPicker3(node, lines, indent) {
|
|
2575
|
+
emitLocComment(node.loc, 'ColorPicker3', lines, indent);
|
|
2576
|
+
const label = asCharPtr(node.label);
|
|
2577
|
+
if (node.stateVar) {
|
|
2578
|
+
lines.push(`${indent}{`);
|
|
2579
|
+
const innerIndent = indent + INDENT;
|
|
2580
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2581
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2582
|
+
lines.push(`${innerIndent}auto val = ${node.stateVar}.get();`);
|
|
2583
|
+
const changedVar = nextWidgetTemp('color_picker3_changed');
|
|
2584
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::color_picker3(${label}, val.data()${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2585
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2586
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
2587
|
+
lines.push(`${innerIndent}}`);
|
|
2588
|
+
lines.push(`${indent}}`);
|
|
2589
|
+
}
|
|
2590
|
+
else if (node.directBind && node.valueExpr) {
|
|
2591
|
+
const dataExpr = `${emitBoundValueExpr(node.valueExpr)}.data()`;
|
|
2592
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, indent, lines);
|
|
2593
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2594
|
+
emitBoolWidgetCall(`imx::renderer::color_picker3(${label}, ${dataExpr}${styleArg})`, node.item, lines, indent);
|
|
2595
|
+
}
|
|
2596
|
+
else if (node.valueExpr !== undefined) {
|
|
2597
|
+
lines.push(`${indent}{`);
|
|
2598
|
+
const innerIndent = indent + INDENT;
|
|
2599
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2600
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2601
|
+
lines.push(`${innerIndent}auto val = ${node.valueExpr};`);
|
|
2602
|
+
const changedVar = nextWidgetTemp('color_picker3_changed');
|
|
2603
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::color_picker3(${label}, val.data()${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2604
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2605
|
+
if (node.onChangeExpr) {
|
|
2606
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
2607
|
+
}
|
|
2608
|
+
lines.push(`${innerIndent}}`);
|
|
1578
2609
|
lines.push(`${indent}}`);
|
|
1579
2610
|
}
|
|
1580
2611
|
}
|
|
@@ -1672,6 +2703,107 @@ function emitDrawText(node, lines, indent) {
|
|
|
1672
2703
|
const text = asCharPtr(node.text);
|
|
1673
2704
|
lines.push(`${indent}imx::renderer::draw_text(${posParts.join(', ')}, ${color}, ${text});`);
|
|
1674
2705
|
}
|
|
2706
|
+
function emitDrawBezierCubic(node, lines, indent) {
|
|
2707
|
+
const p1 = node.p1.split(',').map((s) => emitFloat(s.trim()));
|
|
2708
|
+
const p2 = node.p2.split(',').map((s) => emitFloat(s.trim()));
|
|
2709
|
+
const p3 = node.p3.split(',').map((s) => emitFloat(s.trim()));
|
|
2710
|
+
const p4 = node.p4.split(',').map((s) => emitFloat(s.trim()));
|
|
2711
|
+
const color = emitImVec4(node.color);
|
|
2712
|
+
const thickness = emitFloat(node.thickness);
|
|
2713
|
+
const segments = node.segments;
|
|
2714
|
+
lines.push(`${indent}imx::renderer::draw_bezier_cubic(${p1.join(', ')}, ${p2.join(', ')}, ${p3.join(', ')}, ${p4.join(', ')}, ${color}, ${thickness}, ${segments});`);
|
|
2715
|
+
}
|
|
2716
|
+
function emitDrawBezierQuadratic(node, lines, indent) {
|
|
2717
|
+
const p1 = node.p1.split(',').map((s) => emitFloat(s.trim()));
|
|
2718
|
+
const p2 = node.p2.split(',').map((s) => emitFloat(s.trim()));
|
|
2719
|
+
const p3 = node.p3.split(',').map((s) => emitFloat(s.trim()));
|
|
2720
|
+
const color = emitImVec4(node.color);
|
|
2721
|
+
const thickness = emitFloat(node.thickness);
|
|
2722
|
+
const segments = node.segments;
|
|
2723
|
+
lines.push(`${indent}imx::renderer::draw_bezier_quadratic(${p1.join(', ')}, ${p2.join(', ')}, ${p3.join(', ')}, ${color}, ${thickness}, ${segments});`);
|
|
2724
|
+
}
|
|
2725
|
+
function emitDrawPolyline(node, lines, indent) {
|
|
2726
|
+
const color = emitImVec4(node.color);
|
|
2727
|
+
const thickness = emitFloat(node.thickness);
|
|
2728
|
+
const closed = node.closed;
|
|
2729
|
+
lines.push(`${indent}{`);
|
|
2730
|
+
lines.push(`${indent}${INDENT}float _poly_pts[] = {${node.points}};`);
|
|
2731
|
+
lines.push(`${indent}${INDENT}imx::renderer::draw_polyline(_poly_pts, sizeof(_poly_pts) / (2 * sizeof(float)), ${color}, ${thickness}, ${closed});`);
|
|
2732
|
+
lines.push(`${indent}}`);
|
|
2733
|
+
}
|
|
2734
|
+
function emitDrawConvexPolyFilled(node, lines, indent) {
|
|
2735
|
+
const color = emitImVec4(node.color);
|
|
2736
|
+
lines.push(`${indent}{`);
|
|
2737
|
+
lines.push(`${indent}${INDENT}float _poly_pts[] = {${node.points}};`);
|
|
2738
|
+
lines.push(`${indent}${INDENT}imx::renderer::draw_convex_poly_filled(_poly_pts, sizeof(_poly_pts) / (2 * sizeof(float)), ${color});`);
|
|
2739
|
+
lines.push(`${indent}}`);
|
|
2740
|
+
}
|
|
2741
|
+
function emitDrawNgon(node, lines, indent) {
|
|
2742
|
+
const center = node.center.split(',').map((s) => emitFloat(s.trim()));
|
|
2743
|
+
const radius = emitFloat(node.radius);
|
|
2744
|
+
const color = emitImVec4(node.color);
|
|
2745
|
+
const numSegments = node.numSegments;
|
|
2746
|
+
const thickness = emitFloat(node.thickness);
|
|
2747
|
+
lines.push(`${indent}imx::renderer::draw_ngon(${center.join(', ')}, ${radius}, ${color}, ${numSegments}, ${thickness});`);
|
|
2748
|
+
}
|
|
2749
|
+
function emitDrawNgonFilled(node, lines, indent) {
|
|
2750
|
+
const center = node.center.split(',').map((s) => emitFloat(s.trim()));
|
|
2751
|
+
const radius = emitFloat(node.radius);
|
|
2752
|
+
const color = emitImVec4(node.color);
|
|
2753
|
+
const numSegments = node.numSegments;
|
|
2754
|
+
lines.push(`${indent}imx::renderer::draw_ngon_filled(${center.join(', ')}, ${radius}, ${color}, ${numSegments});`);
|
|
2755
|
+
}
|
|
2756
|
+
function emitDrawTriangle(node, lines, indent) {
|
|
2757
|
+
const p1 = node.p1.split(',').map((s) => emitFloat(s.trim()));
|
|
2758
|
+
const p2 = node.p2.split(',').map((s) => emitFloat(s.trim()));
|
|
2759
|
+
const p3 = node.p3.split(',').map((s) => emitFloat(s.trim()));
|
|
2760
|
+
const color = emitImVec4(node.color);
|
|
2761
|
+
const filled = node.filled;
|
|
2762
|
+
const thickness = emitFloat(node.thickness);
|
|
2763
|
+
lines.push(`${indent}imx::renderer::draw_triangle(${p1.join(', ')}, ${p2.join(', ')}, ${p3.join(', ')}, ${color}, ${filled}, ${thickness});`);
|
|
2764
|
+
}
|
|
2765
|
+
function emitVectorInput(node, rendererFn, cppType, lines, indent, extraArgs = '') {
|
|
2766
|
+
const label = asCharPtr(node.label);
|
|
2767
|
+
const count = node.count;
|
|
2768
|
+
if (node.stateVar) {
|
|
2769
|
+
lines.push(`${indent}{`);
|
|
2770
|
+
const innerIndent = indent + INDENT;
|
|
2771
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2772
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2773
|
+
lines.push(`${innerIndent}auto val = ${node.stateVar}.get();`);
|
|
2774
|
+
const changedVar = nextWidgetTemp(`${rendererFn}_changed`);
|
|
2775
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::${rendererFn}(${label}, val.data(), ${count}${extraArgs}${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2776
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2777
|
+
lines.push(`${innerIndent}${INDENT}${node.stateVar}.set(val);`);
|
|
2778
|
+
lines.push(`${innerIndent}}`);
|
|
2779
|
+
lines.push(`${indent}}`);
|
|
2780
|
+
}
|
|
2781
|
+
else if (node.directBind && node.valueExpr) {
|
|
2782
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, indent, lines);
|
|
2783
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2784
|
+
emitBoolWidgetCall(`imx::renderer::${rendererFn}(${label}, ${node.valueExpr}, ${count}${extraArgs}${styleArg})`, node.item, lines, indent);
|
|
2785
|
+
}
|
|
2786
|
+
else if (node.valueExpr) {
|
|
2787
|
+
lines.push(`${indent}{`);
|
|
2788
|
+
const innerIndent = indent + INDENT;
|
|
2789
|
+
const styleVar = buildWidgetStyleVar(node.style, node.width, innerIndent, lines);
|
|
2790
|
+
const styleArg = styleVar ? `, ${styleVar}` : '';
|
|
2791
|
+
lines.push(`${innerIndent}${cppType} _vec_val[${count}];`);
|
|
2792
|
+
lines.push(`${innerIndent}auto& _vec_src = ${node.valueExpr};`);
|
|
2793
|
+
lines.push(`${innerIndent}for (int i = 0; i < ${count}; ++i) _vec_val[i] = _vec_src[i];`);
|
|
2794
|
+
const changedVar = nextWidgetTemp(`${rendererFn}_changed`);
|
|
2795
|
+
const resultVar = emitBoolWidgetCall(`imx::renderer::${rendererFn}(${label}, _vec_val, ${count}${extraArgs}${styleArg})`, node.item, lines, innerIndent, changedVar);
|
|
2796
|
+
lines.push(`${innerIndent}if (${resultVar}) {`);
|
|
2797
|
+
if (node.onChangeExpr) {
|
|
2798
|
+
lines.push(`${innerIndent}${INDENT}${node.onChangeExpr};`);
|
|
2799
|
+
}
|
|
2800
|
+
else {
|
|
2801
|
+
lines.push(`${innerIndent}${INDENT}for (int i = 0; i < ${count}; ++i) _vec_src[i] = _vec_val[i];`);
|
|
2802
|
+
}
|
|
2803
|
+
lines.push(`${innerIndent}}`);
|
|
2804
|
+
lines.push(`${indent}}`);
|
|
2805
|
+
}
|
|
2806
|
+
}
|
|
1675
2807
|
function collectEmbedKeys(nodes) {
|
|
1676
2808
|
const keys = [];
|
|
1677
2809
|
for (const node of nodes) {
|