wadi-mcp 0.1.10 → 0.1.13
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/server.mjs +454 -124
- package/package.json +5 -4
package/dist/server.mjs
CHANGED
|
@@ -14242,7 +14242,7 @@ function setDimensionUnits(u) {
|
|
|
14242
14242
|
function metersToUnits2(meters) {
|
|
14243
14243
|
const { system, perUnit } = activeUnits;
|
|
14244
14244
|
const unitsPerFoot2 = perUnit / (FEET_PER_DISPLAY_UNIT2[system] ?? 1);
|
|
14245
|
-
return meters * unitsPerFoot2 *
|
|
14245
|
+
return meters * unitsPerFoot2 * FEET_PER_METER3;
|
|
14246
14246
|
}
|
|
14247
14247
|
function formatDimension(length) {
|
|
14248
14248
|
const { system, perUnit, precision } = activeUnits;
|
|
@@ -14268,7 +14268,7 @@ function fFloat(n2) {
|
|
|
14268
14268
|
if (Number.isInteger(n2)) return `${n2}.0`;
|
|
14269
14269
|
return String(n2);
|
|
14270
14270
|
}
|
|
14271
|
-
var DEFAULT_UNITS, activeUnits, FEET_PER_DISPLAY_UNIT2,
|
|
14271
|
+
var DEFAULT_UNITS, activeUnits, FEET_PER_DISPLAY_UNIT2, FEET_PER_METER3, SUFFIX;
|
|
14272
14272
|
var init_format = __esm({
|
|
14273
14273
|
"../editor/src/svg2d/format.ts"() {
|
|
14274
14274
|
init_config();
|
|
@@ -14285,7 +14285,7 @@ var init_format = __esm({
|
|
|
14285
14285
|
centimeters: 0.032808399,
|
|
14286
14286
|
millimeters: 3280839e-9
|
|
14287
14287
|
};
|
|
14288
|
-
|
|
14288
|
+
FEET_PER_METER3 = 3.280839895;
|
|
14289
14289
|
SUFFIX = {
|
|
14290
14290
|
feet: "'",
|
|
14291
14291
|
meters: " m",
|
|
@@ -387462,6 +387462,8 @@ var Roof = {
|
|
|
387462
387462
|
segments: "segments",
|
|
387463
387463
|
slab_thickness: "slab_thickness",
|
|
387464
387464
|
slope: "slope",
|
|
387465
|
+
slope_left: "slope_left",
|
|
387466
|
+
slope_right: "slope_right",
|
|
387465
387467
|
trusses: "trusses",
|
|
387466
387468
|
z_offset: "z_offset"
|
|
387467
387469
|
};
|
|
@@ -387559,6 +387561,16 @@ var Slope = {
|
|
|
387559
387561
|
by: "by",
|
|
387560
387562
|
value: "value"
|
|
387561
387563
|
};
|
|
387564
|
+
var SlopeLeft = {
|
|
387565
|
+
$type: "SlopeLeft",
|
|
387566
|
+
by: "by",
|
|
387567
|
+
value: "value"
|
|
387568
|
+
};
|
|
387569
|
+
var SlopeRight = {
|
|
387570
|
+
$type: "SlopeRight",
|
|
387571
|
+
by: "by",
|
|
387572
|
+
value: "value"
|
|
387573
|
+
};
|
|
387562
387574
|
var Staircase = {
|
|
387563
387575
|
$type: "Staircase",
|
|
387564
387576
|
direction: "direction",
|
|
@@ -388580,6 +388592,14 @@ var WadiAstReflection = class extends AbstractAstReflection {
|
|
|
388580
388592
|
name: Roof.slope,
|
|
388581
388593
|
optional: true
|
|
388582
388594
|
},
|
|
388595
|
+
slope_left: {
|
|
388596
|
+
name: Roof.slope_left,
|
|
388597
|
+
optional: true
|
|
388598
|
+
},
|
|
388599
|
+
slope_right: {
|
|
388600
|
+
name: Roof.slope_right,
|
|
388601
|
+
optional: true
|
|
388602
|
+
},
|
|
388583
388603
|
trusses: {
|
|
388584
388604
|
name: Roof.trusses,
|
|
388585
388605
|
defaultValue: [],
|
|
@@ -388894,6 +388914,30 @@ var WadiAstReflection = class extends AbstractAstReflection {
|
|
|
388894
388914
|
},
|
|
388895
388915
|
superTypes: []
|
|
388896
388916
|
},
|
|
388917
|
+
SlopeLeft: {
|
|
388918
|
+
name: SlopeLeft.$type,
|
|
388919
|
+
properties: {
|
|
388920
|
+
by: {
|
|
388921
|
+
name: SlopeLeft.by
|
|
388922
|
+
},
|
|
388923
|
+
value: {
|
|
388924
|
+
name: SlopeLeft.value
|
|
388925
|
+
}
|
|
388926
|
+
},
|
|
388927
|
+
superTypes: []
|
|
388928
|
+
},
|
|
388929
|
+
SlopeRight: {
|
|
388930
|
+
name: SlopeRight.$type,
|
|
388931
|
+
properties: {
|
|
388932
|
+
by: {
|
|
388933
|
+
name: SlopeRight.by
|
|
388934
|
+
},
|
|
388935
|
+
value: {
|
|
388936
|
+
name: SlopeRight.value
|
|
388937
|
+
}
|
|
388938
|
+
},
|
|
388939
|
+
superTypes: []
|
|
388940
|
+
},
|
|
388897
388941
|
Staircase: {
|
|
388898
388942
|
name: Staircase.$type,
|
|
388899
388943
|
properties: {
|
|
@@ -389203,7 +389247,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
389203
389247
|
"terminal": {
|
|
389204
389248
|
"$type": "RuleCall",
|
|
389205
389249
|
"rule": {
|
|
389206
|
-
"$ref": "#/rules@
|
|
389250
|
+
"$ref": "#/rules@61"
|
|
389207
389251
|
},
|
|
389208
389252
|
"arguments": []
|
|
389209
389253
|
}
|
|
@@ -389422,7 +389466,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
389422
389466
|
"terminal": {
|
|
389423
389467
|
"$type": "RuleCall",
|
|
389424
389468
|
"rule": {
|
|
389425
|
-
"$ref": "#/rules@
|
|
389469
|
+
"$ref": "#/rules@63"
|
|
389426
389470
|
},
|
|
389427
389471
|
"arguments": []
|
|
389428
389472
|
}
|
|
@@ -389441,7 +389485,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
389441
389485
|
"terminal": {
|
|
389442
389486
|
"$type": "RuleCall",
|
|
389443
389487
|
"rule": {
|
|
389444
|
-
"$ref": "#/rules@
|
|
389488
|
+
"$ref": "#/rules@61"
|
|
389445
389489
|
},
|
|
389446
389490
|
"arguments": []
|
|
389447
389491
|
}
|
|
@@ -389472,7 +389516,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
389472
389516
|
"terminal": {
|
|
389473
389517
|
"$type": "RuleCall",
|
|
389474
389518
|
"rule": {
|
|
389475
|
-
"$ref": "#/rules@
|
|
389519
|
+
"$ref": "#/rules@63"
|
|
389476
389520
|
},
|
|
389477
389521
|
"arguments": []
|
|
389478
389522
|
}
|
|
@@ -389488,7 +389532,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
389488
389532
|
"terminal": {
|
|
389489
389533
|
"$type": "RuleCall",
|
|
389490
389534
|
"rule": {
|
|
389491
|
-
"$ref": "#/rules@
|
|
389535
|
+
"$ref": "#/rules@63"
|
|
389492
389536
|
},
|
|
389493
389537
|
"arguments": []
|
|
389494
389538
|
}
|
|
@@ -389508,7 +389552,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
389508
389552
|
"terminal": {
|
|
389509
389553
|
"$type": "RuleCall",
|
|
389510
389554
|
"rule": {
|
|
389511
|
-
"$ref": "#/rules@
|
|
389555
|
+
"$ref": "#/rules@62"
|
|
389512
389556
|
},
|
|
389513
389557
|
"arguments": []
|
|
389514
389558
|
}
|
|
@@ -389524,7 +389568,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
389524
389568
|
"terminal": {
|
|
389525
389569
|
"$type": "RuleCall",
|
|
389526
389570
|
"rule": {
|
|
389527
|
-
"$ref": "#/rules@
|
|
389571
|
+
"$ref": "#/rules@62"
|
|
389528
389572
|
},
|
|
389529
389573
|
"arguments": []
|
|
389530
389574
|
}
|
|
@@ -389540,7 +389584,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
389540
389584
|
"terminal": {
|
|
389541
389585
|
"$type": "RuleCall",
|
|
389542
389586
|
"rule": {
|
|
389543
|
-
"$ref": "#/rules@
|
|
389587
|
+
"$ref": "#/rules@62"
|
|
389544
389588
|
},
|
|
389545
389589
|
"arguments": []
|
|
389546
389590
|
}
|
|
@@ -389563,7 +389607,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
389563
389607
|
"terminal": {
|
|
389564
389608
|
"$type": "RuleCall",
|
|
389565
389609
|
"rule": {
|
|
389566
|
-
"$ref": "#/rules@
|
|
389610
|
+
"$ref": "#/rules@63"
|
|
389567
389611
|
},
|
|
389568
389612
|
"arguments": []
|
|
389569
389613
|
}
|
|
@@ -389585,7 +389629,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
389585
389629
|
"terminal": {
|
|
389586
389630
|
"$type": "RuleCall",
|
|
389587
389631
|
"rule": {
|
|
389588
|
-
"$ref": "#/rules@
|
|
389632
|
+
"$ref": "#/rules@63"
|
|
389589
389633
|
},
|
|
389590
389634
|
"arguments": []
|
|
389591
389635
|
}
|
|
@@ -389616,7 +389660,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
389616
389660
|
"terminal": {
|
|
389617
389661
|
"$type": "RuleCall",
|
|
389618
389662
|
"rule": {
|
|
389619
|
-
"$ref": "#/rules@
|
|
389663
|
+
"$ref": "#/rules@61"
|
|
389620
389664
|
},
|
|
389621
389665
|
"arguments": []
|
|
389622
389666
|
}
|
|
@@ -389660,7 +389704,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
389660
389704
|
"terminal": {
|
|
389661
389705
|
"$type": "RuleCall",
|
|
389662
389706
|
"rule": {
|
|
389663
|
-
"$ref": "#/rules@
|
|
389707
|
+
"$ref": "#/rules@61"
|
|
389664
389708
|
},
|
|
389665
389709
|
"arguments": []
|
|
389666
389710
|
}
|
|
@@ -389741,7 +389785,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
389741
389785
|
"terminal": {
|
|
389742
389786
|
"$type": "RuleCall",
|
|
389743
389787
|
"rule": {
|
|
389744
|
-
"$ref": "#/rules@
|
|
389788
|
+
"$ref": "#/rules@61"
|
|
389745
389789
|
},
|
|
389746
389790
|
"arguments": []
|
|
389747
389791
|
}
|
|
@@ -389860,14 +389904,14 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
389860
389904
|
{
|
|
389861
389905
|
"$type": "RuleCall",
|
|
389862
389906
|
"rule": {
|
|
389863
|
-
"$ref": "#/rules@
|
|
389907
|
+
"$ref": "#/rules@61"
|
|
389864
389908
|
},
|
|
389865
389909
|
"arguments": []
|
|
389866
389910
|
},
|
|
389867
389911
|
{
|
|
389868
389912
|
"$type": "RuleCall",
|
|
389869
389913
|
"rule": {
|
|
389870
|
-
"$ref": "#/rules@
|
|
389914
|
+
"$ref": "#/rules@62"
|
|
389871
389915
|
},
|
|
389872
389916
|
"arguments": []
|
|
389873
389917
|
}
|
|
@@ -390040,7 +390084,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390040
390084
|
"terminal": {
|
|
390041
390085
|
"$type": "RuleCall",
|
|
390042
390086
|
"rule": {
|
|
390043
|
-
"$ref": "#/rules@
|
|
390087
|
+
"$ref": "#/rules@61"
|
|
390044
390088
|
},
|
|
390045
390089
|
"arguments": []
|
|
390046
390090
|
}
|
|
@@ -390052,7 +390096,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390052
390096
|
"terminal": {
|
|
390053
390097
|
"$type": "RuleCall",
|
|
390054
390098
|
"rule": {
|
|
390055
|
-
"$ref": "#/rules@
|
|
390099
|
+
"$ref": "#/rules@63"
|
|
390056
390100
|
},
|
|
390057
390101
|
"arguments": []
|
|
390058
390102
|
}
|
|
@@ -390064,7 +390108,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390064
390108
|
"terminal": {
|
|
390065
390109
|
"$type": "RuleCall",
|
|
390066
390110
|
"rule": {
|
|
390067
|
-
"$ref": "#/rules@
|
|
390111
|
+
"$ref": "#/rules@61"
|
|
390068
390112
|
},
|
|
390069
390113
|
"arguments": []
|
|
390070
390114
|
},
|
|
@@ -390081,7 +390125,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390081
390125
|
"terminal": {
|
|
390082
390126
|
"$type": "RuleCall",
|
|
390083
390127
|
"rule": {
|
|
390084
|
-
"$ref": "#/rules@
|
|
390128
|
+
"$ref": "#/rules@62"
|
|
390085
390129
|
},
|
|
390086
390130
|
"arguments": []
|
|
390087
390131
|
}
|
|
@@ -390097,7 +390141,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390097
390141
|
"terminal": {
|
|
390098
390142
|
"$type": "RuleCall",
|
|
390099
390143
|
"rule": {
|
|
390100
|
-
"$ref": "#/rules@
|
|
390144
|
+
"$ref": "#/rules@62"
|
|
390101
390145
|
},
|
|
390102
390146
|
"arguments": []
|
|
390103
390147
|
}
|
|
@@ -390116,7 +390160,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390116
390160
|
"terminal": {
|
|
390117
390161
|
"$type": "RuleCall",
|
|
390118
390162
|
"rule": {
|
|
390119
|
-
"$ref": "#/rules@
|
|
390163
|
+
"$ref": "#/rules@62"
|
|
390120
390164
|
},
|
|
390121
390165
|
"arguments": []
|
|
390122
390166
|
}
|
|
@@ -390151,7 +390195,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390151
390195
|
"terminal": {
|
|
390152
390196
|
"$type": "RuleCall",
|
|
390153
390197
|
"rule": {
|
|
390154
|
-
"$ref": "#/rules@
|
|
390198
|
+
"$ref": "#/rules@61"
|
|
390155
390199
|
},
|
|
390156
390200
|
"arguments": []
|
|
390157
390201
|
}
|
|
@@ -390163,7 +390207,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390163
390207
|
"terminal": {
|
|
390164
390208
|
"$type": "RuleCall",
|
|
390165
390209
|
"rule": {
|
|
390166
|
-
"$ref": "#/rules@
|
|
390210
|
+
"$ref": "#/rules@63"
|
|
390167
390211
|
},
|
|
390168
390212
|
"arguments": []
|
|
390169
390213
|
}
|
|
@@ -390175,7 +390219,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390175
390219
|
"terminal": {
|
|
390176
390220
|
"$type": "RuleCall",
|
|
390177
390221
|
"rule": {
|
|
390178
|
-
"$ref": "#/rules@
|
|
390222
|
+
"$ref": "#/rules@61"
|
|
390179
390223
|
},
|
|
390180
390224
|
"arguments": []
|
|
390181
390225
|
},
|
|
@@ -390204,7 +390248,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390204
390248
|
"terminal": {
|
|
390205
390249
|
"$type": "RuleCall",
|
|
390206
390250
|
"rule": {
|
|
390207
|
-
"$ref": "#/rules@
|
|
390251
|
+
"$ref": "#/rules@61"
|
|
390208
390252
|
},
|
|
390209
390253
|
"arguments": []
|
|
390210
390254
|
}
|
|
@@ -390216,7 +390260,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390216
390260
|
"terminal": {
|
|
390217
390261
|
"$type": "RuleCall",
|
|
390218
390262
|
"rule": {
|
|
390219
|
-
"$ref": "#/rules@
|
|
390263
|
+
"$ref": "#/rules@63"
|
|
390220
390264
|
},
|
|
390221
390265
|
"arguments": []
|
|
390222
390266
|
}
|
|
@@ -390244,7 +390288,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390244
390288
|
"terminal": {
|
|
390245
390289
|
"$type": "RuleCall",
|
|
390246
390290
|
"rule": {
|
|
390247
|
-
"$ref": "#/rules@
|
|
390291
|
+
"$ref": "#/rules@61"
|
|
390248
390292
|
},
|
|
390249
390293
|
"arguments": []
|
|
390250
390294
|
}
|
|
@@ -390256,7 +390300,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390256
390300
|
"terminal": {
|
|
390257
390301
|
"$type": "RuleCall",
|
|
390258
390302
|
"rule": {
|
|
390259
|
-
"$ref": "#/rules@
|
|
390303
|
+
"$ref": "#/rules@63"
|
|
390260
390304
|
},
|
|
390261
390305
|
"arguments": []
|
|
390262
390306
|
}
|
|
@@ -390322,7 +390366,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390322
390366
|
"terminal": {
|
|
390323
390367
|
"$type": "RuleCall",
|
|
390324
390368
|
"rule": {
|
|
390325
|
-
"$ref": "#/rules@
|
|
390369
|
+
"$ref": "#/rules@61"
|
|
390326
390370
|
},
|
|
390327
390371
|
"arguments": []
|
|
390328
390372
|
}
|
|
@@ -390338,7 +390382,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390338
390382
|
"terminal": {
|
|
390339
390383
|
"$type": "RuleCall",
|
|
390340
390384
|
"rule": {
|
|
390341
|
-
"$ref": "#/rules@
|
|
390385
|
+
"$ref": "#/rules@62"
|
|
390342
390386
|
},
|
|
390343
390387
|
"arguments": []
|
|
390344
390388
|
}
|
|
@@ -390578,7 +390622,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390578
390622
|
"terminal": {
|
|
390579
390623
|
"$type": "RuleCall",
|
|
390580
390624
|
"rule": {
|
|
390581
|
-
"$ref": "#/rules@
|
|
390625
|
+
"$ref": "#/rules@62"
|
|
390582
390626
|
},
|
|
390583
390627
|
"arguments": []
|
|
390584
390628
|
}
|
|
@@ -390622,7 +390666,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390622
390666
|
"terminal": {
|
|
390623
390667
|
"$type": "RuleCall",
|
|
390624
390668
|
"rule": {
|
|
390625
|
-
"$ref": "#/rules@
|
|
390669
|
+
"$ref": "#/rules@61"
|
|
390626
390670
|
},
|
|
390627
390671
|
"arguments": []
|
|
390628
390672
|
}
|
|
@@ -390641,7 +390685,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390641
390685
|
"terminal": {
|
|
390642
390686
|
"$type": "RuleCall",
|
|
390643
390687
|
"rule": {
|
|
390644
|
-
"$ref": "#/rules@
|
|
390688
|
+
"$ref": "#/rules@61"
|
|
390645
390689
|
},
|
|
390646
390690
|
"arguments": []
|
|
390647
390691
|
}
|
|
@@ -390735,7 +390779,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390735
390779
|
"terminal": {
|
|
390736
390780
|
"$type": "RuleCall",
|
|
390737
390781
|
"rule": {
|
|
390738
|
-
"$ref": "#/rules@
|
|
390782
|
+
"$ref": "#/rules@63"
|
|
390739
390783
|
},
|
|
390740
390784
|
"arguments": []
|
|
390741
390785
|
}
|
|
@@ -390838,14 +390882,14 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390838
390882
|
{
|
|
390839
390883
|
"$type": "RuleCall",
|
|
390840
390884
|
"rule": {
|
|
390841
|
-
"$ref": "#/rules@
|
|
390885
|
+
"$ref": "#/rules@63"
|
|
390842
390886
|
},
|
|
390843
390887
|
"arguments": []
|
|
390844
390888
|
},
|
|
390845
390889
|
{
|
|
390846
390890
|
"$type": "RuleCall",
|
|
390847
390891
|
"rule": {
|
|
390848
|
-
"$ref": "#/rules@
|
|
390892
|
+
"$ref": "#/rules@61"
|
|
390849
390893
|
},
|
|
390850
390894
|
"arguments": []
|
|
390851
390895
|
}
|
|
@@ -390978,7 +391022,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
390978
391022
|
"terminal": {
|
|
390979
391023
|
"$type": "RuleCall",
|
|
390980
391024
|
"rule": {
|
|
390981
|
-
"$ref": "#/rules@
|
|
391025
|
+
"$ref": "#/rules@62"
|
|
390982
391026
|
},
|
|
390983
391027
|
"arguments": []
|
|
390984
391028
|
}
|
|
@@ -391002,7 +391046,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391002
391046
|
"terminal": {
|
|
391003
391047
|
"$type": "RuleCall",
|
|
391004
391048
|
"rule": {
|
|
391005
|
-
"$ref": "#/rules@
|
|
391049
|
+
"$ref": "#/rules@63"
|
|
391006
391050
|
},
|
|
391007
391051
|
"arguments": []
|
|
391008
391052
|
}
|
|
@@ -391115,7 +391159,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391115
391159
|
"terminal": {
|
|
391116
391160
|
"$type": "RuleCall",
|
|
391117
391161
|
"rule": {
|
|
391118
|
-
"$ref": "#/rules@
|
|
391162
|
+
"$ref": "#/rules@62"
|
|
391119
391163
|
},
|
|
391120
391164
|
"arguments": []
|
|
391121
391165
|
}
|
|
@@ -391201,7 +391245,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391201
391245
|
"terminal": {
|
|
391202
391246
|
"$type": "RuleCall",
|
|
391203
391247
|
"rule": {
|
|
391204
|
-
"$ref": "#/rules@
|
|
391248
|
+
"$ref": "#/rules@62"
|
|
391205
391249
|
},
|
|
391206
391250
|
"arguments": []
|
|
391207
391251
|
}
|
|
@@ -391217,7 +391261,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391217
391261
|
"terminal": {
|
|
391218
391262
|
"$type": "RuleCall",
|
|
391219
391263
|
"rule": {
|
|
391220
|
-
"$ref": "#/rules@
|
|
391264
|
+
"$ref": "#/rules@62"
|
|
391221
391265
|
},
|
|
391222
391266
|
"arguments": []
|
|
391223
391267
|
}
|
|
@@ -391267,7 +391311,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391267
391311
|
"terminal": {
|
|
391268
391312
|
"$type": "RuleCall",
|
|
391269
391313
|
"rule": {
|
|
391270
|
-
"$ref": "#/rules@
|
|
391314
|
+
"$ref": "#/rules@62"
|
|
391271
391315
|
},
|
|
391272
391316
|
"arguments": []
|
|
391273
391317
|
}
|
|
@@ -391289,7 +391333,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391289
391333
|
"terminal": {
|
|
391290
391334
|
"$type": "RuleCall",
|
|
391291
391335
|
"rule": {
|
|
391292
|
-
"$ref": "#/rules@
|
|
391336
|
+
"$ref": "#/rules@62"
|
|
391293
391337
|
},
|
|
391294
391338
|
"arguments": []
|
|
391295
391339
|
}
|
|
@@ -391311,7 +391355,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391311
391355
|
"terminal": {
|
|
391312
391356
|
"$type": "RuleCall",
|
|
391313
391357
|
"rule": {
|
|
391314
|
-
"$ref": "#/rules@
|
|
391358
|
+
"$ref": "#/rules@62"
|
|
391315
391359
|
},
|
|
391316
391360
|
"arguments": []
|
|
391317
391361
|
}
|
|
@@ -391333,7 +391377,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391333
391377
|
"terminal": {
|
|
391334
391378
|
"$type": "RuleCall",
|
|
391335
391379
|
"rule": {
|
|
391336
|
-
"$ref": "#/rules@
|
|
391380
|
+
"$ref": "#/rules@62"
|
|
391337
391381
|
},
|
|
391338
391382
|
"arguments": []
|
|
391339
391383
|
}
|
|
@@ -391368,7 +391412,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391368
391412
|
"terminal": {
|
|
391369
391413
|
"$type": "RuleCall",
|
|
391370
391414
|
"rule": {
|
|
391371
|
-
"$ref": "#/rules@
|
|
391415
|
+
"$ref": "#/rules@63"
|
|
391372
391416
|
},
|
|
391373
391417
|
"arguments": []
|
|
391374
391418
|
}
|
|
@@ -391380,7 +391424,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391380
391424
|
"terminal": {
|
|
391381
391425
|
"$type": "RuleCall",
|
|
391382
391426
|
"rule": {
|
|
391383
|
-
"$ref": "#/rules@
|
|
391427
|
+
"$ref": "#/rules@63"
|
|
391384
391428
|
},
|
|
391385
391429
|
"arguments": []
|
|
391386
391430
|
}
|
|
@@ -391399,7 +391443,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391399
391443
|
"terminal": {
|
|
391400
391444
|
"$type": "RuleCall",
|
|
391401
391445
|
"rule": {
|
|
391402
|
-
"$ref": "#/rules@
|
|
391446
|
+
"$ref": "#/rules@63"
|
|
391403
391447
|
},
|
|
391404
391448
|
"arguments": []
|
|
391405
391449
|
}
|
|
@@ -391421,7 +391465,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391421
391465
|
"terminal": {
|
|
391422
391466
|
"$type": "RuleCall",
|
|
391423
391467
|
"rule": {
|
|
391424
|
-
"$ref": "#/rules@
|
|
391468
|
+
"$ref": "#/rules@63"
|
|
391425
391469
|
},
|
|
391426
391470
|
"arguments": []
|
|
391427
391471
|
}
|
|
@@ -391452,7 +391496,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391452
391496
|
"terminal": {
|
|
391453
391497
|
"$type": "RuleCall",
|
|
391454
391498
|
"rule": {
|
|
391455
|
-
"$ref": "#/rules@
|
|
391499
|
+
"$ref": "#/rules@61"
|
|
391456
391500
|
},
|
|
391457
391501
|
"arguments": []
|
|
391458
391502
|
}
|
|
@@ -391471,7 +391515,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391471
391515
|
"terminal": {
|
|
391472
391516
|
"$type": "RuleCall",
|
|
391473
391517
|
"rule": {
|
|
391474
|
-
"$ref": "#/rules@
|
|
391518
|
+
"$ref": "#/rules@63"
|
|
391475
391519
|
},
|
|
391476
391520
|
"arguments": []
|
|
391477
391521
|
}
|
|
@@ -391566,7 +391610,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391566
391610
|
"terminal": {
|
|
391567
391611
|
"$type": "RuleCall",
|
|
391568
391612
|
"rule": {
|
|
391569
|
-
"$ref": "#/rules@
|
|
391613
|
+
"$ref": "#/rules@61"
|
|
391570
391614
|
},
|
|
391571
391615
|
"arguments": []
|
|
391572
391616
|
}
|
|
@@ -391585,7 +391629,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391585
391629
|
"terminal": {
|
|
391586
391630
|
"$type": "RuleCall",
|
|
391587
391631
|
"rule": {
|
|
391588
|
-
"$ref": "#/rules@
|
|
391632
|
+
"$ref": "#/rules@62"
|
|
391589
391633
|
},
|
|
391590
391634
|
"arguments": []
|
|
391591
391635
|
}
|
|
@@ -391607,7 +391651,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391607
391651
|
"terminal": {
|
|
391608
391652
|
"$type": "RuleCall",
|
|
391609
391653
|
"rule": {
|
|
391610
|
-
"$ref": "#/rules@
|
|
391654
|
+
"$ref": "#/rules@63"
|
|
391611
391655
|
},
|
|
391612
391656
|
"arguments": []
|
|
391613
391657
|
}
|
|
@@ -391638,7 +391682,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391638
391682
|
"terminal": {
|
|
391639
391683
|
"$type": "RuleCall",
|
|
391640
391684
|
"rule": {
|
|
391641
|
-
"$ref": "#/rules@
|
|
391685
|
+
"$ref": "#/rules@62"
|
|
391642
391686
|
},
|
|
391643
391687
|
"arguments": []
|
|
391644
391688
|
}
|
|
@@ -391650,7 +391694,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391650
391694
|
"terminal": {
|
|
391651
391695
|
"$type": "RuleCall",
|
|
391652
391696
|
"rule": {
|
|
391653
|
-
"$ref": "#/rules@
|
|
391697
|
+
"$ref": "#/rules@63"
|
|
391654
391698
|
},
|
|
391655
391699
|
"arguments": []
|
|
391656
391700
|
}
|
|
@@ -391669,7 +391713,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391669
391713
|
"terminal": {
|
|
391670
391714
|
"$type": "RuleCall",
|
|
391671
391715
|
"rule": {
|
|
391672
|
-
"$ref": "#/rules@
|
|
391716
|
+
"$ref": "#/rules@62"
|
|
391673
391717
|
},
|
|
391674
391718
|
"arguments": []
|
|
391675
391719
|
}
|
|
@@ -391691,7 +391735,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391691
391735
|
"terminal": {
|
|
391692
391736
|
"$type": "RuleCall",
|
|
391693
391737
|
"rule": {
|
|
391694
|
-
"$ref": "#/rules@
|
|
391738
|
+
"$ref": "#/rules@62"
|
|
391695
391739
|
},
|
|
391696
391740
|
"arguments": []
|
|
391697
391741
|
}
|
|
@@ -391713,7 +391757,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391713
391757
|
"terminal": {
|
|
391714
391758
|
"$type": "RuleCall",
|
|
391715
391759
|
"rule": {
|
|
391716
|
-
"$ref": "#/rules@
|
|
391760
|
+
"$ref": "#/rules@62"
|
|
391717
391761
|
},
|
|
391718
391762
|
"arguments": []
|
|
391719
391763
|
}
|
|
@@ -391916,7 +391960,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391916
391960
|
"terminal": {
|
|
391917
391961
|
"$type": "RuleCall",
|
|
391918
391962
|
"rule": {
|
|
391919
|
-
"$ref": "#/rules@
|
|
391963
|
+
"$ref": "#/rules@63"
|
|
391920
391964
|
},
|
|
391921
391965
|
"arguments": []
|
|
391922
391966
|
}
|
|
@@ -391946,7 +391990,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
391946
391990
|
"terminal": {
|
|
391947
391991
|
"$type": "RuleCall",
|
|
391948
391992
|
"rule": {
|
|
391949
|
-
"$ref": "#/rules@
|
|
391993
|
+
"$ref": "#/rules@61"
|
|
391950
391994
|
},
|
|
391951
391995
|
"arguments": []
|
|
391952
391996
|
}
|
|
@@ -392074,7 +392118,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
392074
392118
|
"terminal": {
|
|
392075
392119
|
"$type": "RuleCall",
|
|
392076
392120
|
"rule": {
|
|
392077
|
-
"$ref": "#/rules@
|
|
392121
|
+
"$ref": "#/rules@63"
|
|
392078
392122
|
},
|
|
392079
392123
|
"arguments": []
|
|
392080
392124
|
}
|
|
@@ -392275,7 +392319,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
392275
392319
|
"terminal": {
|
|
392276
392320
|
"$type": "RuleCall",
|
|
392277
392321
|
"rule": {
|
|
392278
|
-
"$ref": "#/rules@
|
|
392322
|
+
"$ref": "#/rules@61"
|
|
392279
392323
|
},
|
|
392280
392324
|
"arguments": []
|
|
392281
392325
|
}
|
|
@@ -392420,7 +392464,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
392420
392464
|
"terminal": {
|
|
392421
392465
|
"$type": "RuleCall",
|
|
392422
392466
|
"rule": {
|
|
392423
|
-
"$ref": "#/rules@
|
|
392467
|
+
"$ref": "#/rules@61"
|
|
392424
392468
|
},
|
|
392425
392469
|
"arguments": []
|
|
392426
392470
|
}
|
|
@@ -392592,7 +392636,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
392592
392636
|
"terminal": {
|
|
392593
392637
|
"$type": "RuleCall",
|
|
392594
392638
|
"rule": {
|
|
392595
|
-
"$ref": "#/rules@
|
|
392639
|
+
"$ref": "#/rules@63"
|
|
392596
392640
|
},
|
|
392597
392641
|
"arguments": []
|
|
392598
392642
|
}
|
|
@@ -392650,7 +392694,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
392650
392694
|
"terminal": {
|
|
392651
392695
|
"$type": "RuleCall",
|
|
392652
392696
|
"rule": {
|
|
392653
|
-
"$ref": "#/rules@
|
|
392697
|
+
"$ref": "#/rules@61"
|
|
392654
392698
|
},
|
|
392655
392699
|
"arguments": []
|
|
392656
392700
|
}
|
|
@@ -392794,7 +392838,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
392794
392838
|
"terminal": {
|
|
392795
392839
|
"$type": "RuleCall",
|
|
392796
392840
|
"rule": {
|
|
392797
|
-
"$ref": "#/rules@
|
|
392841
|
+
"$ref": "#/rules@63"
|
|
392798
392842
|
},
|
|
392799
392843
|
"arguments": []
|
|
392800
392844
|
}
|
|
@@ -392941,7 +392985,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
392941
392985
|
"terminal": {
|
|
392942
392986
|
"$type": "RuleCall",
|
|
392943
392987
|
"rule": {
|
|
392944
|
-
"$ref": "#/rules@
|
|
392988
|
+
"$ref": "#/rules@63"
|
|
392945
392989
|
},
|
|
392946
392990
|
"arguments": []
|
|
392947
392991
|
}
|
|
@@ -393088,7 +393132,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
393088
393132
|
"terminal": {
|
|
393089
393133
|
"$type": "RuleCall",
|
|
393090
393134
|
"rule": {
|
|
393091
|
-
"$ref": "#/rules@
|
|
393135
|
+
"$ref": "#/rules@63"
|
|
393092
393136
|
},
|
|
393093
393137
|
"arguments": []
|
|
393094
393138
|
}
|
|
@@ -393213,7 +393257,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
393213
393257
|
"terminal": {
|
|
393214
393258
|
"$type": "RuleCall",
|
|
393215
393259
|
"rule": {
|
|
393216
|
-
"$ref": "#/rules@
|
|
393260
|
+
"$ref": "#/rules@63"
|
|
393217
393261
|
},
|
|
393218
393262
|
"arguments": []
|
|
393219
393263
|
}
|
|
@@ -393251,7 +393295,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
393251
393295
|
"terminal": {
|
|
393252
393296
|
"$type": "RuleCall",
|
|
393253
393297
|
"rule": {
|
|
393254
|
-
"$ref": "#/rules@
|
|
393298
|
+
"$ref": "#/rules@63"
|
|
393255
393299
|
},
|
|
393256
393300
|
"arguments": []
|
|
393257
393301
|
}
|
|
@@ -393382,7 +393426,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
393382
393426
|
"terminal": {
|
|
393383
393427
|
"$type": "RuleCall",
|
|
393384
393428
|
"rule": {
|
|
393385
|
-
"$ref": "#/rules@
|
|
393429
|
+
"$ref": "#/rules@63"
|
|
393386
393430
|
},
|
|
393387
393431
|
"arguments": []
|
|
393388
393432
|
}
|
|
@@ -393420,7 +393464,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
393420
393464
|
"terminal": {
|
|
393421
393465
|
"$type": "RuleCall",
|
|
393422
393466
|
"rule": {
|
|
393423
|
-
"$ref": "#/rules@
|
|
393467
|
+
"$ref": "#/rules@63"
|
|
393424
393468
|
},
|
|
393425
393469
|
"arguments": []
|
|
393426
393470
|
}
|
|
@@ -393699,7 +393743,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
393699
393743
|
"terminal": {
|
|
393700
393744
|
"$type": "RuleCall",
|
|
393701
393745
|
"rule": {
|
|
393702
|
-
"$ref": "#/rules@
|
|
393746
|
+
"$ref": "#/rules@63"
|
|
393703
393747
|
},
|
|
393704
393748
|
"arguments": []
|
|
393705
393749
|
}
|
|
@@ -393737,7 +393781,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
393737
393781
|
"terminal": {
|
|
393738
393782
|
"$type": "RuleCall",
|
|
393739
393783
|
"rule": {
|
|
393740
|
-
"$ref": "#/rules@
|
|
393784
|
+
"$ref": "#/rules@63"
|
|
393741
393785
|
},
|
|
393742
393786
|
"arguments": []
|
|
393743
393787
|
}
|
|
@@ -393888,7 +393932,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
393888
393932
|
"terminal": {
|
|
393889
393933
|
"$type": "RuleCall",
|
|
393890
393934
|
"rule": {
|
|
393891
|
-
"$ref": "#/rules@
|
|
393935
|
+
"$ref": "#/rules@63"
|
|
393892
393936
|
},
|
|
393893
393937
|
"arguments": []
|
|
393894
393938
|
}
|
|
@@ -393919,7 +393963,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
393919
393963
|
"terminal": {
|
|
393920
393964
|
"$type": "RuleCall",
|
|
393921
393965
|
"rule": {
|
|
393922
|
-
"$ref": "#/rules@
|
|
393966
|
+
"$ref": "#/rules@62"
|
|
393923
393967
|
},
|
|
393924
393968
|
"arguments": []
|
|
393925
393969
|
}
|
|
@@ -393935,7 +393979,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
393935
393979
|
"terminal": {
|
|
393936
393980
|
"$type": "RuleCall",
|
|
393937
393981
|
"rule": {
|
|
393938
|
-
"$ref": "#/rules@
|
|
393982
|
+
"$ref": "#/rules@62"
|
|
393939
393983
|
},
|
|
393940
393984
|
"arguments": []
|
|
393941
393985
|
}
|
|
@@ -393974,7 +394018,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
393974
394018
|
"terminal": {
|
|
393975
394019
|
"$type": "RuleCall",
|
|
393976
394020
|
"rule": {
|
|
393977
|
-
"$ref": "#/rules@
|
|
394021
|
+
"$ref": "#/rules@63"
|
|
393978
394022
|
},
|
|
393979
394023
|
"arguments": []
|
|
393980
394024
|
}
|
|
@@ -394118,7 +394162,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394118
394162
|
"terminal": {
|
|
394119
394163
|
"$type": "RuleCall",
|
|
394120
394164
|
"rule": {
|
|
394121
|
-
"$ref": "#/rules@
|
|
394165
|
+
"$ref": "#/rules@63"
|
|
394122
394166
|
},
|
|
394123
394167
|
"arguments": []
|
|
394124
394168
|
}
|
|
@@ -394231,7 +394275,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394231
394275
|
"terminal": {
|
|
394232
394276
|
"$type": "RuleCall",
|
|
394233
394277
|
"rule": {
|
|
394234
|
-
"$ref": "#/rules@
|
|
394278
|
+
"$ref": "#/rules@63"
|
|
394235
394279
|
},
|
|
394236
394280
|
"arguments": []
|
|
394237
394281
|
}
|
|
@@ -394418,7 +394462,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394418
394462
|
"terminal": {
|
|
394419
394463
|
"$type": "RuleCall",
|
|
394420
394464
|
"rule": {
|
|
394421
|
-
"$ref": "#/rules@
|
|
394465
|
+
"$ref": "#/rules@61"
|
|
394422
394466
|
},
|
|
394423
394467
|
"arguments": []
|
|
394424
394468
|
}
|
|
@@ -394437,7 +394481,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394437
394481
|
"terminal": {
|
|
394438
394482
|
"$type": "RuleCall",
|
|
394439
394483
|
"rule": {
|
|
394440
|
-
"$ref": "#/rules@
|
|
394484
|
+
"$ref": "#/rules@63"
|
|
394441
394485
|
},
|
|
394442
394486
|
"arguments": []
|
|
394443
394487
|
}
|
|
@@ -394469,7 +394513,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394469
394513
|
"terminal": {
|
|
394470
394514
|
"$type": "RuleCall",
|
|
394471
394515
|
"rule": {
|
|
394472
|
-
"$ref": "#/rules@
|
|
394516
|
+
"$ref": "#/rules@63"
|
|
394473
394517
|
},
|
|
394474
394518
|
"arguments": []
|
|
394475
394519
|
}
|
|
@@ -394485,7 +394529,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394485
394529
|
"terminal": {
|
|
394486
394530
|
"$type": "RuleCall",
|
|
394487
394531
|
"rule": {
|
|
394488
|
-
"$ref": "#/rules@
|
|
394532
|
+
"$ref": "#/rules@63"
|
|
394489
394533
|
},
|
|
394490
394534
|
"arguments": []
|
|
394491
394535
|
}
|
|
@@ -394505,7 +394549,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394505
394549
|
"terminal": {
|
|
394506
394550
|
"$type": "RuleCall",
|
|
394507
394551
|
"rule": {
|
|
394508
|
-
"$ref": "#/rules@
|
|
394552
|
+
"$ref": "#/rules@62"
|
|
394509
394553
|
},
|
|
394510
394554
|
"arguments": []
|
|
394511
394555
|
}
|
|
@@ -394521,7 +394565,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394521
394565
|
"terminal": {
|
|
394522
394566
|
"$type": "RuleCall",
|
|
394523
394567
|
"rule": {
|
|
394524
|
-
"$ref": "#/rules@
|
|
394568
|
+
"$ref": "#/rules@62"
|
|
394525
394569
|
},
|
|
394526
394570
|
"arguments": []
|
|
394527
394571
|
}
|
|
@@ -394537,7 +394581,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394537
394581
|
"terminal": {
|
|
394538
394582
|
"$type": "RuleCall",
|
|
394539
394583
|
"rule": {
|
|
394540
|
-
"$ref": "#/rules@
|
|
394584
|
+
"$ref": "#/rules@62"
|
|
394541
394585
|
},
|
|
394542
394586
|
"arguments": []
|
|
394543
394587
|
}
|
|
@@ -394560,7 +394604,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394560
394604
|
"terminal": {
|
|
394561
394605
|
"$type": "RuleCall",
|
|
394562
394606
|
"rule": {
|
|
394563
|
-
"$ref": "#/rules@
|
|
394607
|
+
"$ref": "#/rules@63"
|
|
394564
394608
|
},
|
|
394565
394609
|
"arguments": []
|
|
394566
394610
|
}
|
|
@@ -394582,7 +394626,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394582
394626
|
"terminal": {
|
|
394583
394627
|
"$type": "RuleCall",
|
|
394584
394628
|
"rule": {
|
|
394585
|
-
"$ref": "#/rules@
|
|
394629
|
+
"$ref": "#/rules@63"
|
|
394586
394630
|
},
|
|
394587
394631
|
"arguments": []
|
|
394588
394632
|
}
|
|
@@ -394669,7 +394713,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394669
394713
|
"terminal": {
|
|
394670
394714
|
"$type": "RuleCall",
|
|
394671
394715
|
"rule": {
|
|
394672
|
-
"$ref": "#/rules@
|
|
394716
|
+
"$ref": "#/rules@61"
|
|
394673
394717
|
},
|
|
394674
394718
|
"arguments": []
|
|
394675
394719
|
}
|
|
@@ -394688,7 +394732,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394688
394732
|
"terminal": {
|
|
394689
394733
|
"$type": "RuleCall",
|
|
394690
394734
|
"rule": {
|
|
394691
|
-
"$ref": "#/rules@
|
|
394735
|
+
"$ref": "#/rules@61"
|
|
394692
394736
|
},
|
|
394693
394737
|
"arguments": []
|
|
394694
394738
|
}
|
|
@@ -394707,7 +394751,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394707
394751
|
"terminal": {
|
|
394708
394752
|
"$type": "RuleCall",
|
|
394709
394753
|
"rule": {
|
|
394710
|
-
"$ref": "#/rules@
|
|
394754
|
+
"$ref": "#/rules@63"
|
|
394711
394755
|
},
|
|
394712
394756
|
"arguments": []
|
|
394713
394757
|
}
|
|
@@ -394833,7 +394877,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394833
394877
|
"terminal": {
|
|
394834
394878
|
"$type": "RuleCall",
|
|
394835
394879
|
"rule": {
|
|
394836
|
-
"$ref": "#/rules@
|
|
394880
|
+
"$ref": "#/rules@61"
|
|
394837
394881
|
},
|
|
394838
394882
|
"arguments": []
|
|
394839
394883
|
}
|
|
@@ -394884,7 +394928,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394884
394928
|
"terminal": {
|
|
394885
394929
|
"$type": "RuleCall",
|
|
394886
394930
|
"rule": {
|
|
394887
|
-
"$ref": "#/rules@
|
|
394931
|
+
"$ref": "#/rules@63"
|
|
394888
394932
|
},
|
|
394889
394933
|
"arguments": []
|
|
394890
394934
|
}
|
|
@@ -394955,6 +394999,32 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
394955
394999
|
},
|
|
394956
395000
|
"cardinality": "?"
|
|
394957
395001
|
},
|
|
395002
|
+
{
|
|
395003
|
+
"$type": "Assignment",
|
|
395004
|
+
"feature": "slope_left",
|
|
395005
|
+
"operator": "=",
|
|
395006
|
+
"terminal": {
|
|
395007
|
+
"$type": "RuleCall",
|
|
395008
|
+
"rule": {
|
|
395009
|
+
"$ref": "#/rules@54"
|
|
395010
|
+
},
|
|
395011
|
+
"arguments": []
|
|
395012
|
+
},
|
|
395013
|
+
"cardinality": "?"
|
|
395014
|
+
},
|
|
395015
|
+
{
|
|
395016
|
+
"$type": "Assignment",
|
|
395017
|
+
"feature": "slope_right",
|
|
395018
|
+
"operator": "=",
|
|
395019
|
+
"terminal": {
|
|
395020
|
+
"$type": "RuleCall",
|
|
395021
|
+
"rule": {
|
|
395022
|
+
"$ref": "#/rules@55"
|
|
395023
|
+
},
|
|
395024
|
+
"arguments": []
|
|
395025
|
+
},
|
|
395026
|
+
"cardinality": "?"
|
|
395027
|
+
},
|
|
394958
395028
|
{
|
|
394959
395029
|
"$type": "Group",
|
|
394960
395030
|
"elements": [
|
|
@@ -395080,7 +395150,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
395080
395150
|
"terminal": {
|
|
395081
395151
|
"$type": "RuleCall",
|
|
395082
395152
|
"rule": {
|
|
395083
|
-
"$ref": "#/rules@
|
|
395153
|
+
"$ref": "#/rules@63"
|
|
395084
395154
|
},
|
|
395085
395155
|
"arguments": []
|
|
395086
395156
|
}
|
|
@@ -395102,7 +395172,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
395102
395172
|
"terminal": {
|
|
395103
395173
|
"$type": "RuleCall",
|
|
395104
395174
|
"rule": {
|
|
395105
|
-
"$ref": "#/rules@
|
|
395175
|
+
"$ref": "#/rules@56"
|
|
395106
395176
|
},
|
|
395107
395177
|
"arguments": []
|
|
395108
395178
|
}
|
|
@@ -395114,7 +395184,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
395114
395184
|
"terminal": {
|
|
395115
395185
|
"$type": "RuleCall",
|
|
395116
395186
|
"rule": {
|
|
395117
|
-
"$ref": "#/rules@
|
|
395187
|
+
"$ref": "#/rules@57"
|
|
395118
395188
|
},
|
|
395119
395189
|
"arguments": []
|
|
395120
395190
|
}
|
|
@@ -395178,6 +395248,98 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
395178
395248
|
"fragment": false,
|
|
395179
395249
|
"parameters": []
|
|
395180
395250
|
},
|
|
395251
|
+
{
|
|
395252
|
+
"$type": "ParserRule",
|
|
395253
|
+
"name": "SlopeLeft",
|
|
395254
|
+
"definition": {
|
|
395255
|
+
"$type": "Group",
|
|
395256
|
+
"elements": [
|
|
395257
|
+
{
|
|
395258
|
+
"$type": "Keyword",
|
|
395259
|
+
"value": "slope_left"
|
|
395260
|
+
},
|
|
395261
|
+
{
|
|
395262
|
+
"$type": "Assignment",
|
|
395263
|
+
"feature": "by",
|
|
395264
|
+
"operator": "=",
|
|
395265
|
+
"terminal": {
|
|
395266
|
+
"$type": "Alternatives",
|
|
395267
|
+
"elements": [
|
|
395268
|
+
{
|
|
395269
|
+
"$type": "Keyword",
|
|
395270
|
+
"value": "angle"
|
|
395271
|
+
},
|
|
395272
|
+
{
|
|
395273
|
+
"$type": "Keyword",
|
|
395274
|
+
"value": "height"
|
|
395275
|
+
}
|
|
395276
|
+
]
|
|
395277
|
+
}
|
|
395278
|
+
},
|
|
395279
|
+
{
|
|
395280
|
+
"$type": "Assignment",
|
|
395281
|
+
"feature": "value",
|
|
395282
|
+
"operator": "=",
|
|
395283
|
+
"terminal": {
|
|
395284
|
+
"$type": "RuleCall",
|
|
395285
|
+
"rule": {
|
|
395286
|
+
"$ref": "#/rules@14"
|
|
395287
|
+
},
|
|
395288
|
+
"arguments": []
|
|
395289
|
+
}
|
|
395290
|
+
}
|
|
395291
|
+
]
|
|
395292
|
+
},
|
|
395293
|
+
"entry": false,
|
|
395294
|
+
"fragment": false,
|
|
395295
|
+
"parameters": []
|
|
395296
|
+
},
|
|
395297
|
+
{
|
|
395298
|
+
"$type": "ParserRule",
|
|
395299
|
+
"name": "SlopeRight",
|
|
395300
|
+
"definition": {
|
|
395301
|
+
"$type": "Group",
|
|
395302
|
+
"elements": [
|
|
395303
|
+
{
|
|
395304
|
+
"$type": "Keyword",
|
|
395305
|
+
"value": "slope_right"
|
|
395306
|
+
},
|
|
395307
|
+
{
|
|
395308
|
+
"$type": "Assignment",
|
|
395309
|
+
"feature": "by",
|
|
395310
|
+
"operator": "=",
|
|
395311
|
+
"terminal": {
|
|
395312
|
+
"$type": "Alternatives",
|
|
395313
|
+
"elements": [
|
|
395314
|
+
{
|
|
395315
|
+
"$type": "Keyword",
|
|
395316
|
+
"value": "angle"
|
|
395317
|
+
},
|
|
395318
|
+
{
|
|
395319
|
+
"$type": "Keyword",
|
|
395320
|
+
"value": "height"
|
|
395321
|
+
}
|
|
395322
|
+
]
|
|
395323
|
+
}
|
|
395324
|
+
},
|
|
395325
|
+
{
|
|
395326
|
+
"$type": "Assignment",
|
|
395327
|
+
"feature": "value",
|
|
395328
|
+
"operator": "=",
|
|
395329
|
+
"terminal": {
|
|
395330
|
+
"$type": "RuleCall",
|
|
395331
|
+
"rule": {
|
|
395332
|
+
"$ref": "#/rules@14"
|
|
395333
|
+
},
|
|
395334
|
+
"arguments": []
|
|
395335
|
+
}
|
|
395336
|
+
}
|
|
395337
|
+
]
|
|
395338
|
+
},
|
|
395339
|
+
"entry": false,
|
|
395340
|
+
"fragment": false,
|
|
395341
|
+
"parameters": []
|
|
395342
|
+
},
|
|
395181
395343
|
{
|
|
395182
395344
|
"$type": "ParserRule",
|
|
395183
395345
|
"name": "Segment",
|
|
@@ -395195,7 +395357,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
395195
395357
|
"terminal": {
|
|
395196
395358
|
"$type": "RuleCall",
|
|
395197
395359
|
"rule": {
|
|
395198
|
-
"$ref": "#/rules@
|
|
395360
|
+
"$ref": "#/rules@63"
|
|
395199
395361
|
},
|
|
395200
395362
|
"arguments": []
|
|
395201
395363
|
}
|
|
@@ -395686,7 +395848,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
395686
395848
|
"terminal": {
|
|
395687
395849
|
"$type": "RuleCall",
|
|
395688
395850
|
"rule": {
|
|
395689
|
-
"$ref": "#/rules@
|
|
395851
|
+
"$ref": "#/rules@62"
|
|
395690
395852
|
},
|
|
395691
395853
|
"arguments": []
|
|
395692
395854
|
}
|
|
@@ -395717,7 +395879,7 @@ var WadiGrammar = () => loadedWadiGrammar ?? (loadedWadiGrammar = loadGrammarFro
|
|
|
395717
395879
|
"terminal": {
|
|
395718
395880
|
"$type": "RuleCall",
|
|
395719
395881
|
"rule": {
|
|
395720
|
-
"$ref": "#/rules@
|
|
395882
|
+
"$ref": "#/rules@63"
|
|
395721
395883
|
},
|
|
395722
395884
|
"arguments": []
|
|
395723
395885
|
}
|
|
@@ -396291,6 +396453,14 @@ function roof(r2) {
|
|
|
396291
396453
|
const v = exprToValue(r2.slope.value);
|
|
396292
396454
|
o.slope = r2.slope.by === "angle" ? { by: "angle", angle_deg: v } : { by: "height", ridge_h: v };
|
|
396293
396455
|
}
|
|
396456
|
+
if (r2.slope_left) {
|
|
396457
|
+
const v = exprToValue(r2.slope_left.value);
|
|
396458
|
+
o.slope_left = r2.slope_left.by === "angle" ? { by: "angle", angle_deg: v } : { by: "height", ridge_h: v };
|
|
396459
|
+
}
|
|
396460
|
+
if (r2.slope_right) {
|
|
396461
|
+
const v = exprToValue(r2.slope_right.value);
|
|
396462
|
+
o.slope_right = r2.slope_right.by === "angle" ? { by: "angle", angle_deg: v } : { by: "height", ridge_h: v };
|
|
396463
|
+
}
|
|
396294
396464
|
const mo = put("min_overhang", r2.min_overhang);
|
|
396295
396465
|
if (mo !== void 0) o.min_overhang = mo;
|
|
396296
396466
|
const st = put("slab_thickness", r2.slab_thickness);
|
|
@@ -411972,6 +412142,14 @@ function anchorItem(rect, spec, wallT, units) {
|
|
|
411972
412142
|
else y = (iy0 + iy1) / 2 + gy;
|
|
411973
412143
|
return { x, y };
|
|
411974
412144
|
}
|
|
412145
|
+
function anchorFacing(anchor) {
|
|
412146
|
+
const { h, v } = parseAnchor(anchor);
|
|
412147
|
+
if (v === "top") return 0;
|
|
412148
|
+
if (v === "bottom") return 180;
|
|
412149
|
+
if (h === "left") return 90;
|
|
412150
|
+
if (h === "right") return 270;
|
|
412151
|
+
return 0;
|
|
412152
|
+
}
|
|
411975
412153
|
|
|
411976
412154
|
// ../editor/src/svg2d/expand.ts
|
|
411977
412155
|
var SIDES = ["north", "south", "east", "west"];
|
|
@@ -412059,13 +412237,14 @@ function expandRoomWalls(houseConfig, wallThickness, opts, _depth = 0) {
|
|
|
412059
412237
|
}
|
|
412060
412238
|
const anchoredItem = (rect, specIn) => {
|
|
412061
412239
|
const spec = resolveItemFormulas(specIn);
|
|
412240
|
+
const rotation = spec.rotation ?? anchorFacing(spec.anchor);
|
|
412062
412241
|
const p = anchorItem(
|
|
412063
412242
|
rect,
|
|
412064
412243
|
{
|
|
412065
412244
|
anchor: spec.anchor,
|
|
412066
412245
|
gapX: spec.gap_x,
|
|
412067
412246
|
gapY: spec.gap_y,
|
|
412068
|
-
rotation
|
|
412247
|
+
rotation,
|
|
412069
412248
|
scale: spec.scale,
|
|
412070
412249
|
dimensions: spec.asset.dimensions
|
|
412071
412250
|
},
|
|
@@ -412078,7 +412257,7 @@ function expandRoomWalls(houseConfig, wallThickness, opts, _depth = 0) {
|
|
|
412078
412257
|
asset: spec.asset,
|
|
412079
412258
|
x: p.x,
|
|
412080
412259
|
y: p.y,
|
|
412081
|
-
rotation
|
|
412260
|
+
rotation,
|
|
412082
412261
|
scale: spec.scale,
|
|
412083
412262
|
z_offset: spec.z_offset,
|
|
412084
412263
|
layer: spec.layer
|
|
@@ -412121,6 +412300,7 @@ function expandRoomWalls(houseConfig, wallThickness, opts, _depth = 0) {
|
|
|
412121
412300
|
const p = anchoredItem(rr, obj);
|
|
412122
412301
|
obj.x = p.x;
|
|
412123
412302
|
obj.y = p.y;
|
|
412303
|
+
obj.rotation = p.rotation;
|
|
412124
412304
|
} else if (opts?.lenient) {
|
|
412125
412305
|
opts.onWarning?.(`item '${obj.name ?? "?"}': anchor_to room '${at}' not found`);
|
|
412126
412306
|
}
|
|
@@ -412591,6 +412771,27 @@ function resolveRise(slope, crossHalf) {
|
|
|
412591
412771
|
if (slope.by === "height") return slope.ridge_h;
|
|
412592
412772
|
return crossHalf * Math.tan(slope.angle_deg * Math.PI / 180);
|
|
412593
412773
|
}
|
|
412774
|
+
function slopeAngleRad(spec, crossHalf) {
|
|
412775
|
+
if (spec.by === "angle") return spec.angle_deg * Math.PI / 180;
|
|
412776
|
+
return Math.atan(spec.ridge_h / crossHalf);
|
|
412777
|
+
}
|
|
412778
|
+
function resolvePitch(seg, cfg, crossHalf) {
|
|
412779
|
+
const left = seg.slope_left_override ?? cfg.slope_left;
|
|
412780
|
+
const right = seg.slope_right_override ?? cfg.slope_right;
|
|
412781
|
+
if (left && right) {
|
|
412782
|
+
const tanL = Math.tan(slopeAngleRad(left, crossHalf));
|
|
412783
|
+
const tanR = Math.tan(slopeAngleRad(right, crossHalf));
|
|
412784
|
+
if (tanL > 0 && tanR > 0) {
|
|
412785
|
+
const width = 2 * crossHalf;
|
|
412786
|
+
const ridgeH2 = width * tanL * tanR / (tanL + tanR);
|
|
412787
|
+
const leftRun = ridgeH2 / tanL;
|
|
412788
|
+
return { ridgeH: ridgeH2, ridgeShift: crossHalf - leftRun, leftPitchTan: tanL, rightPitchTan: tanR };
|
|
412789
|
+
}
|
|
412790
|
+
}
|
|
412791
|
+
const ridgeH = resolveRise(seg.slope_override ?? cfg.slope, crossHalf);
|
|
412792
|
+
const t = ridgeH / crossHalf;
|
|
412793
|
+
return { ridgeH, ridgeShift: 0, leftPitchTan: t, rightPitchTan: t };
|
|
412794
|
+
}
|
|
412594
412795
|
function to3D(pt, z2) {
|
|
412595
412796
|
return [pt[0], pt[1], z2];
|
|
412596
412797
|
}
|
|
@@ -412633,8 +412834,8 @@ function derivePitchedRoof(cfg, opts) {
|
|
|
412633
412834
|
const alongLen = segmentLength(seg);
|
|
412634
412835
|
if (alongLen === 0) continue;
|
|
412635
412836
|
const crossHalf = seg.width / 2;
|
|
412636
|
-
const
|
|
412637
|
-
const
|
|
412837
|
+
const { ridgeH, ridgeShift, leftPitchTan, rightPitchTan } = resolvePitch(seg, cfg, crossHalf);
|
|
412838
|
+
const asym = ridgeShift !== 0;
|
|
412638
412839
|
if (!(ridgeH > 0)) {
|
|
412639
412840
|
throw new Error(`pitched segment ${seg.id}: rise must be > 0`);
|
|
412640
412841
|
}
|
|
@@ -412654,10 +412855,10 @@ function derivePitchedRoof(cfg, opts) {
|
|
|
412654
412855
|
const ridgeZ = opts.wallTopZ + ridgeH;
|
|
412655
412856
|
const ohLeft = seg.overhang_left ?? minOverhang;
|
|
412656
412857
|
const ohRight = seg.overhang_right ?? minOverhang;
|
|
412657
|
-
const eaveZLeft = opts.wallTopZ - ohLeft * ridgeH / dCrit;
|
|
412658
|
-
const eaveZRight = opts.wallTopZ - ohRight * ridgeH / dCrit;
|
|
412659
|
-
const oCrossLeft = ohLeft * crossHalf / dCrit;
|
|
412660
|
-
const oCrossRight = ohRight * crossHalf / dCrit;
|
|
412858
|
+
const eaveZLeft = asym ? opts.wallTopZ - ohLeft * leftPitchTan : opts.wallTopZ - ohLeft * ridgeH / dCrit;
|
|
412859
|
+
const eaveZRight = asym ? opts.wallTopZ - ohRight * rightPitchTan : opts.wallTopZ - ohRight * ridgeH / dCrit;
|
|
412860
|
+
const oCrossLeft = asym ? ohLeft : ohLeft * crossHalf / dCrit;
|
|
412861
|
+
const oCrossRight = asym ? ohRight : ohRight * crossHalf / dCrit;
|
|
412661
412862
|
const oStart = startRes === "closed" ? minOverhang * hipSetbackStart / dCrit : startRes === "open" ? gableOverhangStart : 0;
|
|
412662
412863
|
const oEnd = endRes === "closed" ? minOverhang * hipSetbackEnd / dCrit : endRes === "open" ? gableOverhangEnd : 0;
|
|
412663
412864
|
const unit = segmentUnitVector(seg);
|
|
@@ -412669,8 +412870,16 @@ function derivePitchedRoof(cfg, opts) {
|
|
|
412669
412870
|
const backRight = shift(startBase, rightN, crossHalf + oCrossRight);
|
|
412670
412871
|
const frontLeft = shift(endBase, leftN, crossHalf + oCrossLeft);
|
|
412671
412872
|
const frontRight = shift(endBase, rightN, crossHalf + oCrossRight);
|
|
412672
|
-
const ridgeStart2D =
|
|
412673
|
-
|
|
412873
|
+
const ridgeStart2D = shift(
|
|
412874
|
+
startRes === "closed" ? shift(seg.start, unit, +hipSetbackStart) : startRes === "open" ? shift(seg.start, unit, -gableOverhangStart) : seg.start,
|
|
412875
|
+
leftN,
|
|
412876
|
+
ridgeShift
|
|
412877
|
+
);
|
|
412878
|
+
const ridgeEnd2D = shift(
|
|
412879
|
+
endRes === "closed" ? shift(seg.end, unit, -hipSetbackEnd) : endRes === "open" ? shift(seg.end, unit, +gableOverhangEnd) : seg.end,
|
|
412880
|
+
leftN,
|
|
412881
|
+
ridgeShift
|
|
412882
|
+
);
|
|
412674
412883
|
const ridgeStart3D = to3D(ridgeStart2D, ridgeZ);
|
|
412675
412884
|
const ridgeEnd3D = to3D(ridgeEnd2D, ridgeZ);
|
|
412676
412885
|
planes.push({
|
|
@@ -412805,7 +413014,8 @@ function derivePitchedRoof(cfg, opts) {
|
|
|
412805
413014
|
if (startRes === "open") {
|
|
412806
413015
|
const wallLeft = shift(seg.start, leftN, crossHalf);
|
|
412807
413016
|
const wallRight = shift(seg.start, rightN, crossHalf);
|
|
412808
|
-
const
|
|
413017
|
+
const apexCross = shift(seg.start, leftN, ridgeShift);
|
|
413018
|
+
const apexAtWall = [apexCross[0], apexCross[1], ridgeZ];
|
|
412809
413019
|
planes.push({
|
|
412810
413020
|
id: `${seg.id}.gable_wall.start`,
|
|
412811
413021
|
vertices: [
|
|
@@ -412866,7 +413076,8 @@ function derivePitchedRoof(cfg, opts) {
|
|
|
412866
413076
|
if (endRes === "open") {
|
|
412867
413077
|
const wallLeft = shift(seg.end, leftN, crossHalf);
|
|
412868
413078
|
const wallRight = shift(seg.end, rightN, crossHalf);
|
|
412869
|
-
const
|
|
413079
|
+
const apexCross = shift(seg.end, leftN, ridgeShift);
|
|
413080
|
+
const apexAtWall = [apexCross[0], apexCross[1], ridgeZ];
|
|
412870
413081
|
planes.push({
|
|
412871
413082
|
id: `${seg.id}.gable_wall.end`,
|
|
412872
413083
|
vertices: [
|
|
@@ -412927,9 +413138,10 @@ function derivePitchedRoof(cfg, opts) {
|
|
|
412927
413138
|
if (segTrussEntry) {
|
|
412928
413139
|
for (let ti = 0; ti < segTrussEntry.positions_along.length; ti++) {
|
|
412929
413140
|
const along = segTrussEntry.positions_along[ti];
|
|
412930
|
-
const
|
|
412931
|
-
const leftBase = shift(
|
|
412932
|
-
const rightBase = shift(
|
|
413141
|
+
const centre2D = interpolatePoint(seg, along);
|
|
413142
|
+
const leftBase = shift(centre2D, leftN, crossHalf);
|
|
413143
|
+
const rightBase = shift(centre2D, rightN, crossHalf);
|
|
413144
|
+
const apex2D = shift(centre2D, leftN, ridgeShift);
|
|
412933
413145
|
trusses.push({
|
|
412934
413146
|
id: `${seg.id}.truss.${ti}`,
|
|
412935
413147
|
bottom_left: to3D(leftBase, opts.wallTopZ),
|
|
@@ -414360,6 +414572,72 @@ function sideHasWall(segs, seg) {
|
|
|
414360
414572
|
}
|
|
414361
414573
|
return false;
|
|
414362
414574
|
}
|
|
414575
|
+
function openLabel(op) {
|
|
414576
|
+
const kind = typeof op.kind === "string" ? op.kind : "opening";
|
|
414577
|
+
const nm = typeof op.name === "string" && op.name ? ` "${op.name}"` : "";
|
|
414578
|
+
return `${kind}${nm}`;
|
|
414579
|
+
}
|
|
414580
|
+
function collectOpeningSegs(objs) {
|
|
414581
|
+
const out = [];
|
|
414582
|
+
for (const o of objs) {
|
|
414583
|
+
if (o.type === "room") {
|
|
414584
|
+
const walls = o.walls;
|
|
414585
|
+
if (!walls || typeof walls !== "object" || Array.isArray(walls)) continue;
|
|
414586
|
+
const rx = num2(o.x), ry = num2(o.y), rw = num2(o.width), rl = num2(o.length);
|
|
414587
|
+
for (const side2 of ALL_SIDES) {
|
|
414588
|
+
const ops = walls[side2]?.openings;
|
|
414589
|
+
if (!Array.isArray(ops)) continue;
|
|
414590
|
+
for (const op of ops) {
|
|
414591
|
+
const off = num2(op.offset), w = num2(op.width);
|
|
414592
|
+
const owner = `room ${objLabel(o)} ${side2}`;
|
|
414593
|
+
const label = openLabel(op);
|
|
414594
|
+
if (side2 === "north") out.push({ horiz: true, at: ry, lo: rx + off, hi: rx + off + w, owner, label });
|
|
414595
|
+
else if (side2 === "south") out.push({ horiz: true, at: ry + rl, lo: rx + off, hi: rx + off + w, owner, label });
|
|
414596
|
+
else if (side2 === "west") out.push({ horiz: false, at: rx, lo: ry + off, hi: ry + off + w, owner, label });
|
|
414597
|
+
else out.push({ horiz: false, at: rx + rw, lo: ry + off, hi: ry + off + w, owner, label });
|
|
414598
|
+
}
|
|
414599
|
+
}
|
|
414600
|
+
} else if (o.type === "wall") {
|
|
414601
|
+
const ops = o.openings;
|
|
414602
|
+
if (!Array.isArray(ops)) continue;
|
|
414603
|
+
const sx = num2(o.start_x), sy = num2(o.start_y), ex = num2(o.end_x), ey = num2(o.end_y);
|
|
414604
|
+
const horiz = Math.abs(sy - ey) < 1, vert = Math.abs(sx - ex) < 1;
|
|
414605
|
+
if (!horiz && !vert) continue;
|
|
414606
|
+
const start = horiz ? Math.min(sx, ex) : Math.min(sy, ey);
|
|
414607
|
+
for (const op of ops) {
|
|
414608
|
+
const off = num2(op.offset), w = num2(op.width);
|
|
414609
|
+
out.push({ horiz, at: horiz ? sy : sx, lo: start + off, hi: start + off + w, owner: `wall ${objLabel(o)}`, label: openLabel(op) });
|
|
414610
|
+
}
|
|
414611
|
+
}
|
|
414612
|
+
}
|
|
414613
|
+
return out;
|
|
414614
|
+
}
|
|
414615
|
+
var FEET_PER_METER2 = 3.280839895;
|
|
414616
|
+
var FEET_PER_DISPLAY = {
|
|
414617
|
+
feet_inches: 1,
|
|
414618
|
+
feet: 1,
|
|
414619
|
+
meters: 3.280839895,
|
|
414620
|
+
centimeters: 0.032808399,
|
|
414621
|
+
millimeters: 3280839e-9
|
|
414622
|
+
};
|
|
414623
|
+
function itemMetersToUnits(m, units) {
|
|
414624
|
+
const perUnit = units?.per_unit ?? 10;
|
|
414625
|
+
const fpu = FEET_PER_DISPLAY[units?.system ?? "feet_inches"] ?? 1;
|
|
414626
|
+
return m * (perUnit / fpu) * FEET_PER_METER2;
|
|
414627
|
+
}
|
|
414628
|
+
function itemBox(it, units) {
|
|
414629
|
+
const asset2 = it.asset;
|
|
414630
|
+
if (!asset2?.dimensions) return null;
|
|
414631
|
+
const scale = it.scale != null ? num2(it.scale) : 1;
|
|
414632
|
+
const fw = itemMetersToUnits(asset2.dimensions[0], units) * scale;
|
|
414633
|
+
const fd = itemMetersToUnits(asset2.dimensions[2], units) * scale;
|
|
414634
|
+
const th = num2(it.rotation) * Math.PI / 180;
|
|
414635
|
+
const c = Math.abs(Math.cos(th)), s = Math.abs(Math.sin(th));
|
|
414636
|
+
const hx = fw / 2 * c + fd / 2 * s;
|
|
414637
|
+
const hy = fw / 2 * s + fd / 2 * c;
|
|
414638
|
+
const cx = num2(it.x), cy = num2(it.y);
|
|
414639
|
+
return { x0: cx - hx, y0: cy - hy, x1: cx + hx, y1: cy + hy };
|
|
414640
|
+
}
|
|
414363
414641
|
function lintStructure(config3) {
|
|
414364
414642
|
const cfg = config3;
|
|
414365
414643
|
const floors = cfg.floors ?? [];
|
|
@@ -414371,6 +414649,13 @@ function lintStructure(config3) {
|
|
|
414371
414649
|
const findings = [];
|
|
414372
414650
|
const rects = buildRoomRects(config3);
|
|
414373
414651
|
const wallSegs = collectWallSegments(floors);
|
|
414652
|
+
const units = cfg.units;
|
|
414653
|
+
let expandedFloors = [];
|
|
414654
|
+
try {
|
|
414655
|
+
expandedFloors = expandRoomWalls(config3, void 0, { lenient: true }).floors ?? [];
|
|
414656
|
+
} catch {
|
|
414657
|
+
expandedFloors = [];
|
|
414658
|
+
}
|
|
414374
414659
|
let baseZ = 0;
|
|
414375
414660
|
for (let fi = 0; fi < floors.length; fi++) {
|
|
414376
414661
|
const fl = floors[fi];
|
|
@@ -414474,6 +414759,49 @@ function lintStructure(config3) {
|
|
|
414474
414759
|
}
|
|
414475
414760
|
}
|
|
414476
414761
|
}
|
|
414762
|
+
{
|
|
414763
|
+
const segs = collectOpeningSegs(objs);
|
|
414764
|
+
const OVERLAP = 1;
|
|
414765
|
+
for (let a = 0; a < segs.length; a++) {
|
|
414766
|
+
for (let b = a + 1; b < segs.length; b++) {
|
|
414767
|
+
const A = segs[a], B = segs[b];
|
|
414768
|
+
if (A.horiz !== B.horiz) continue;
|
|
414769
|
+
if (Math.abs(A.at - B.at) > 1.5) continue;
|
|
414770
|
+
const overlap = Math.min(A.hi, B.hi) - Math.max(A.lo, B.lo);
|
|
414771
|
+
if (overlap <= OVERLAP) continue;
|
|
414772
|
+
const by = Math.round(overlap);
|
|
414773
|
+
findings.push({
|
|
414774
|
+
rule: "C6",
|
|
414775
|
+
level: "error",
|
|
414776
|
+
floor: fnum,
|
|
414777
|
+
where: A.owner,
|
|
414778
|
+
message: A.owner === B.owner ? `${cap(floorLabel(fl))}: ${A.label} and ${B.label} overlap by ~${by} units on ${A.owner}. Two openings can't occupy the same span of a wall \u2014 move or narrow one.` : `${cap(floorLabel(fl))}: ${A.label} on ${A.owner} overlaps ${B.label} on ${B.owner} by ~${by} units \u2014 they sit on the same shared wall and collide. Offset or resize one.`
|
|
414779
|
+
});
|
|
414780
|
+
}
|
|
414781
|
+
}
|
|
414782
|
+
}
|
|
414783
|
+
{
|
|
414784
|
+
const expObjs = (expandedFloors[fi]?.objects ?? []).filter(
|
|
414785
|
+
(o) => o.type === "item" && o.enabled !== false
|
|
414786
|
+
);
|
|
414787
|
+
const boxes = expObjs.map((o) => ({ o, box: itemBox(o, units) })).filter((e) => e.box);
|
|
414788
|
+
const MARGIN = 2;
|
|
414789
|
+
for (let a = 0; a < boxes.length; a++) {
|
|
414790
|
+
for (let b = a + 1; b < boxes.length; b++) {
|
|
414791
|
+
const A = boxes[a], B = boxes[b];
|
|
414792
|
+
const ox = Math.min(A.box.x1, B.box.x1) - Math.max(A.box.x0, B.box.x0);
|
|
414793
|
+
const oy = Math.min(A.box.y1, B.box.y1) - Math.max(A.box.y0, B.box.y0);
|
|
414794
|
+
if (ox <= MARGIN || oy <= MARGIN) continue;
|
|
414795
|
+
findings.push({
|
|
414796
|
+
rule: "C7",
|
|
414797
|
+
level: "warn",
|
|
414798
|
+
floor: fnum,
|
|
414799
|
+
where: objLabel(A.o),
|
|
414800
|
+
message: `${cap(floorLabel(fl))}: furniture ${objLabel(A.o)} and ${objLabel(B.o)} overlap (~${Math.round(ox)}\xD7${Math.round(oy)} units). Reposition one if that isn't intentional.`
|
|
414801
|
+
});
|
|
414802
|
+
}
|
|
414803
|
+
}
|
|
414804
|
+
}
|
|
414477
414805
|
}
|
|
414478
414806
|
return findings;
|
|
414479
414807
|
}
|
|
@@ -414655,8 +414983,10 @@ function svgDrawItem(cx, cy, w, l, yawDeg = 0) {
|
|
|
414655
414983
|
const fx = Math.sin(r2), fy = Math.cos(r2);
|
|
414656
414984
|
const px = -fy, py = fx;
|
|
414657
414985
|
const ex = cx + fx * (l / 2), ey = cy + fy * (l / 2);
|
|
414658
|
-
const
|
|
414659
|
-
const
|
|
414986
|
+
const NOTCH_HALF_W = 3.5;
|
|
414987
|
+
const NOTCH_H = 5;
|
|
414988
|
+
const hw = Math.min(NOTCH_HALF_W, w * 0.45);
|
|
414989
|
+
const hh = Math.min(NOTCH_H, Math.min(w, l) * 0.45);
|
|
414660
414990
|
const p1 = `${fFloat(ex + px * hw)},${fFloat(ey + py * hw)}`;
|
|
414661
414991
|
const p2 = `${fFloat(ex - px * hw)},${fFloat(ey - py * hw)}`;
|
|
414662
414992
|
const tip = `${fFloat(ex + fx * hh)},${fFloat(ey + fy * hh)}`;
|
|
@@ -418007,11 +418337,11 @@ var DOCS = {
|
|
|
418007
418337
|
},
|
|
418008
418338
|
"dsl": {
|
|
418009
418339
|
"title": "The Wadi DSL (.wdl) \u2014 syntax reference",
|
|
418010
|
-
"body": '# The Wadi DSL (`.wdl`) \u2014 authoring reference\n\nYou author houses in the **Wadi DSL** \u2014 a small, formal language (`.wdl`) that\ncompiles to a resolved `.wadi` (`house_config.json`). The DSL is **complete**:\nevery object type in the model has first-class syntax, so you rarely need the\n`raw` escape. Authoring the DSL is more direct and less error-prone than writing\nJSON \u2014 the grammar enforces structure, and `check.sh` reports parse errors with\nline:col.\n\n**This file is the SYNTAX reference.** The *semantics* live in the other\nreferences and apply unchanged \u2014 read them:\n\n- `coordinate-system.md` \u2014 X\u2192right, **Y\u2192DOWN**, Z\u2192up; **10 units = 1 ft**;\n the **centreline** convention. The #1 source of mistakes.\n- `conventions.md` \u2014 the **structural coding conventions** (`check.sh` enforces\n them): plinth-floor height must match the plinth block, rooms must wall every\n exterior side, a no-slab floor must set `slab_thickness 0`.\n- `parametric-conventions.md` \u2014 the grid-first recipe for reusable templates.\n- `roof-v2-guide.md` \u2014 roof segments, hip vs gable, trusses, joints.\n- `data-model.md` \u2014 the underlying `.wadi` schema (what the DSL compiles to; also\n the field reference for the `raw` escape).\n\n## The loop\n\n1. Write / edit `house.wdl` \u2014 the **single shared source** (you and the human\n co-edit it; the app\'s DSL previewer renders it live). You never produce a `.wadi`.\n2. `wadi-skill/architect/scripts/check.sh house.wdl` \u2014 runs the DSL compiler +\n validator (schema + wall/roof geometry) against a **throwaway temp** just for\n feedback; fix any reported error and re-run.\n3. `preview.sh house.wdl` \u2192 read the PNGs (plans / elevations / roof) to check your\n work. (It also compiles to a throwaway temp \u2014 no persistent `.wadi`.)\n\n## Skeleton\n\n```wdl\nhouse MyHouse {\n convention center // ALWAYS use center (wall-centreline coords)\n units feet_inches per_unit 10 // 10 project units = 1 ft\n site { plot (WIDTH, LENGTH) ref (0, 0) }\n defaults { floor_height 120 wall_height 108 slab_thickness 8 wall_thickness 8 }\n\n // parametric core (optional): var, point, grid, configurator\n // component / layer declarations (optional)\n floor 0 "Plinth" { \u2026 } // floors stack in source order (0 = plinth)\n floor 1 "Ground Floor" { \u2026 }\n floor 2 "Loft" { roof \u2026 } // roof lives ALONE on its own top floor\n}\n```\n\nNumbers are **project units** (feet \xD7 10 by default). Names after `house`,\n`room`, `pillar`, `var`, `point`, `grid`, and `use`/`component` are bare\nidentifiers (no spaces); names introduced with the `name` keyword are quoted\nstrings.\n\n## Parametric core (domain-neutral)\n\n```wdl\nvar wallT = 8 // a knob; may reference other vars\nvar pilInset = (pillarW - wallT) / 2\n\npoint House { x = 420, y = 470 } // reference as House.x / House.W / House.L\n // (.W = x, .L = y \u2014 a point doubles as a size)\n\ngrid main { // named wall centrelines; publishes main.x1 / main.yA\n x: 1 @ wallT / 2, 2 @ House.W / 2, 3 @ House.W - wallT / 2\n y: A @ wallT / 2, B @ House.L / 2, C @ House.L - wallT / 2\n}\n// each line may add: \u2026 @ <expr> thick <expr> role structural|planning\n\nconfigurator { // the knobs a downstream user turns\n slider pillarW "Column size" ft [8 .. 14 step 1]\n number ceiling "Ceiling height" ft\n toggle has_loft "Add a loft"\n select roof_style "Roof style" { Flat = 0, Shed = 1, Gable = 2, Hip = 3 }\n}\n```\n\n**Formulas are automatic.** Any geometry number can be a formula \u2014 just write the\nexpression instead of a literal (`at (main.x1, main.yA)`, `size (House.W/2, 200)`).\nOperators: `+ - * /`, unary `-`, parentheses, and the functions\n`min max clamp round floor ceil abs`. References: a `var`, a `point`\n(`House.W`), or a grid line (`main.x3 - main.x1`). No comparison operators \u2014 gate\nthings with the `min/abs` idiom (see `enabled` below).\n\n## Common attribute tail (every object)\n\nAfter an object\'s geometry, in THIS order, any of:\n\n```\n\u2026 z_offset <expr> enabled <expr> layer "id" [material "id"]\n```\n\n- `enabled <expr>` \u2014 the on/off switch. A `0`/`false` value hides the object. To\n gate on a configurator variable, use a 0/1 formula:\n `enabled 1 - min(1, abs(roof_style - 3))` renders the object only when\n `roof_style == 3`. (This is how one template carries several roofs and shows\n only the chosen one.)\n- `z_offset <expr>` \u2014 lift above the floor base (split levels).\n- `material "id"` \u2014 only on plinth / ground / room / wall / staircase / kitchen /\n roof.\n\n## Objects \u2014 structure & envelope\n\n```wdl\nslab [name "N"] at (x,y) size (w,l) [thickness <t>] // floor_slab\nbeam [name "N"] at (x,y) size (w,l) [height <h>]\nplinth [name "N"] at (x,y) size (w,l) height <h> // raised base (Plinth floor)\nground [name "N"] at (x,y) size (w,l) [height <h>] // terrain plane\npillar Name at (x,y) size (w,l) [height <h>] // (x,y) = TOP-LEFT corner\n```\n\n`at (x,y)` is the **TOP-LEFT CORNER** \u2014 **not the centre** \u2014 for every one of these\n(same as rooms/slabs/beams); `size (w,l)` is width \xD7 length. All accept the common tail.\n\n**Pillars catch people out here.** A column reads as "placed at a point," but `at` is\nstill its corner. To **centre a column on a point** `(cx, cy)` \u2014 a grid node, a room\ncorner \u2014 place it at **`at (cx - w/2, cy - l/2)`**, never at `(cx, cy)`. On a grid, the\n`pilInset` idiom (see `parametric-conventions.md`) does exactly this so columns sit flush.\n\n## Objects \u2014 rooms, walls & openings\n\nA room shows exactly the walls you declare. A **bare room (no `wall` lines) is\nenclosed on all four sides.** List plain walls compactly; give a wall its own line\nonly when it carries a door/window; omit a side to leave it open (verandah).\n\n```wdl\nroom Name at (x,y) size (w,l) [height <h>] [material "\u2026"] {\n wall east west north // plain walls \u2014 several in one statement\n wall south { door Main at <offset> size (w,h) [open] } // wall WITH openings: one side\n wall west { window W at <offset> size (w,h) [sill <s>] [open] }\n item asset { \u2026 } anchor center [gap (gx,gy)] // furniture anchored inside the room\n}\n```\n\n- `wall <side>\u2026` sides are `north|south|east|west`. A `wall <side>` line may also\n add `height <h>` / `height_end <h>` (sloped).\n- `door`/`window` `at <offset>` is measured along the wall from its start;\n `size (width, height)`; `window \u2026 sill <s>` sets the sill height; `open` = a bare\n hole (no leaf/glazing).\n\nA **free-standing wall** (not a room side):\n\n```wdl\nwall Name from (x1,y1) to (x2,y2) [height <h>] [height_end <h>] [facing north|\u2026] {\n \u2026 door/window openings \u2026\n}\n```\n\n- `from`/`to` are the wall\'s **centreline** endpoints; the wall is drawn as a rectangle\n `wall_thickness` wide, centred on that line.\n- **Overlap walls at corners \u2014 they do NOT auto-mitre.** Two free-standing walls that\n merely *touch* at a shared endpoint leave an unfilled square notch (\xBD\xB7`wall_thickness`)\n at the corner, because each is just a rectangle capped at its endpoint. To fill the\n corner, **extend the endpoints so the wall bodies OVERLAP** \u2014 run at least one wall\'s\n end **half the wall thickness past** the shared point (overlapping by the full thickness\n is fine and simplest). For an L of thickness 8 meeting at `(160,40)`:\n\n ```wdl\n wall H from (40, 40) to (164, 40) height 108 // ends 4 (\xBD\xB78) PAST the corner\n wall V from (160, 40) to (160, 160) height 108 // butts into H\'s overlapped body\n ```\n\n (Room walls handle their own corners; this only applies to `wall \u2026 from \u2026 to \u2026`.)\n\n## Objects \u2014 circulation & fittings\n\n```wdl\nstaircase [name "N"] at (start_x, start_y) step (rise, tread, width)\n direction north|south|east|west\n [total_height <h>] [max_run <r>] [landing_depth <d>]\n [landing_thickness <t>] [turn clockwise|anticlockwise] [flight_gap <g>]\n\nkitchen [name "N"] path ((x,y), (x,y), \u2026) side left|right\n depth <d> height <h> [base_z <z>] // path points are literal numbers\n```\n\n**Staircases are TOP-anchored \u2014 this is the #1 mistake.** You put a staircase on the\n**UPPER** floor and it **DESCENDS** to the floor below:\n\n- `at (x,y)` is the **TOP** of the stair (where it meets the floor it\'s declared on).\n- `direction` is the **descent** direction (the way it travels going *down*).\n- `total_height` is the **drop** to the floor below (omit \u2192 the floor-below\'s height).\n- `max_run` caps a flight\'s run; exceed it and the stair auto-splits into switchback\n flights with turn landings (`landing_depth`/`turn`/`flight_gap` tune the switchback).\n\nSo a stair connecting the ground floor **up** to the first floor lives on the **First\nFloor**, descending to the ground:\n\n```wdl\nfloor 2 "First Floor" height 116 {\n slab at (\u2026) size (\u2026)\n staircase name "Stair" at (212, 64) step (7, 11, 44) // top = this floor, at the landing\n direction south total_height 116 // descends south to the floor below\n}\n```\n\nPut it on the *lower* floor (thinking of it as "climbing up") and it descends the wrong way\n\u2014 **below ground** \u2014 where it draws in 2D plans but is buried/invisible in 3D. `check.sh`\ncatches that (convention **C5**), but author it top-anchored from the start.\n\n// three ways to name the GLB, in order of preference:\nitem [name "N"] f."sofa" // 1. from an imported module (see Imports)\nitem [name "N"] "sofa" // 2. a same-file / bare-imported `asset` id\nitem [name "N"] asset { id "sofa" src "\u2026/sofa.glb" dims (w,h,d) [category "\u2026"] } // 3. inline one-off\n at (x,y) [rotation <deg>] [scale <s>]\n [anchor_to "RoomName" anchor center gap (gx,gy)]\n```\n\nPrefer the module form (`item f."bed_double"`) \u2014 `import "std-furniture" as f`\nonce and every piece is a short id, no URLs. The bare form (`item "sofa"`) needs\na matching top-level `asset "sofa" \u2026` in the file (or a bare `import`). The inline\n`asset { \u2026 }` block is only for a one-off GLB not in any pack. All three produce\nthe identical `{id,src,dims}` downstream. Furniture `dims` are the real-world size\nin **metres** `(width, height, depth)`; `src` is a GLB URL (an unreachable GLB\nshows a placeholder box, never a blank). `anchor` is one of `top-left top-center\ntop-right center-left center center-right bottom-left bottom-center bottom-right`.\n\n**Orientation \u2014 this is how you point furniture the right way.** A piece\'s FRONT\n(the side you sit at / the doors / the open side) faces a known compass direction\nper its `rotation` (degrees):\n\n| `rotation` | front faces |\n|---|---|\n| `0` | **South** (the plot front / entrance side, +Y) |\n| `90` | East |\n| `180` | North |\n| `270` | West |\n\nSo a sofa against the NORTH wall (facing into the room, i.e. south) is `rotation\n0`; against the SOUTH wall (facing north) it\'s `rotation 180`; against the WEST\nwall (facing east) `rotation 90`. The floor plan (`wadi_preview plans`) draws a\nsmall triangle on each piece\'s front edge so you can verify the way it points;\nfor a definitive 3D check use `wadi_capture_3d({ room: "\u2026" })` (first-person from\ninside the room).\n\n## Imports & modules (reusable `.wdl` libraries)\n\nA `.wdl` file can be a **module** \u2014 top-level declarations (no `house` needed) \u2014\nthat another file `import`s. Two bundled ones: `std-furniture` (asset pack \u2192\n`item ns."id"`) and `konkan/base` (goal-tagged component pack \u2192 `use ns.Comp`;\nStairwell, Verandah, Otla, Bathroom, Kitchen, TulsiVrindavan, Parapet). The\n`konkan_cottage` example (`wadi_examples`) assembles a whole house from both.\n\n```wdl\nhouse Home {\n import "std-furniture" as f // aliased: refer to its assets as f."<id>"\n // import "std-furniture" // bare: its ids drop into scope for item "<id>"\n floor 1 "G" slab_thickness 0 {\n room Bed at (20,20) size (160,200) { wall north east south west\n item f."bed_double" anchor center }\n }\n}\n```\n\nA module file itself is just top-level `asset` (later: `component`) decls:\n\n```wdl\n// my-furniture.wdl \u2014 a house-less module (a reusable library)\nasset "daybed" src "https://\u2026/daybed.glb" dims (1.8, 0.4, 0.9) name "Daybed" category "Living"\n```\n\nOver MCP, `wadi_modules` lists importable modules and `wadi_module "<name>"`\nshows a module\'s asset ids + dimensions (filter with a `query`). Import refs\nresolve by name against the bundled `std-*` packs (a local `modules/` search\npath and git refs come later).\n\n## Objects \u2014 roof (one object; flat / shed / gable / hip)\n\nThe roof lives ALONE on its own top floor and you never set its Z (see\n`roof-v2-guide.md`). `endpoint`: `closed` = hip triangle, `open` = gable end-wall.\n\n```wdl\nroof [name "N"] pitched|shed|flat\n [endpoint open|closed]\n [slope angle <deg> | slope height <ridge_h>]\n [overhang <o>] [slab_thickness <t>] [parapet <h> x <t>] [gable_wall_thickness <t>] {\n segment "id" from (x,y) to (x,y) width <w>\n [high_side left|right] // shed only\n [start_endpoint open|closed] [end_endpoint open|closed]\n [hip_setback (a,b)] [gable_overhang (a,b)] [hip_ridge_extension (a,b)]\n [overhang <o>] // uniform eave, all four sides\n [overhang_start <o>] [overhang_end <o>] // per-side along the axis (shed;\n // on a gable end = gable_overhang)\n [overhang_low <o>] [overhang_high <o>] // SHED eaves (down-slope / up-slope)\n [overhang_left <o>] [overhang_right <o>] // PITCHED eaves (left / right of ridge)\n [tie_beams N]\n truss "segId" fink|mono_pitch at (pos, pos, \u2026)\n }\n```\n\nSegment `from`/`to`/`width` and the `hip_setback`/\u2026 values accept formulas, so a\nroof scales with the plot (e.g. `width House.W`, `hip_setback (Verandah.L, Padvi.L)`).\n\n**Per-side overhang (cantilever one edge).** `overhang <o>` sets a uniform eave on\nall four sides. Any sloping roof can override a side independently \u2014 each defaults to\n`overhang`. **Along the axis:** `overhang_start` / `overhang_end` (on a shed, or a\ngable open end \u2014 there they\'re the same as `gable_overhang`; a hip end is geometric,\ntuned via `hip_setback`). **Eaves:** `overhang_low` / `overhang_high` on a **shed**\n(down-slope / up-slope); `overhang_left` / `overhang_right` on a **pitched** roof\n(the two eaves either side of the ridge). A bigger eave overhang also drops that\neave\'s edge along the same pitch, so the slope stays planar. (Per-eave on a *pitched*\nroof is single-segment only \u2014 on a multi-segment roof the eaves share one height so\njoints line up.)\nIdiom: keep the roof FOOTPRINT (its supported edges) on the main room, then cantilever\none eave to cover an entry landing / stair \u2014 end the axis on the room wall and set a big\n`overhang_end`:\n```wdl\n// footprint ends on the main room\'s east wall (x204 centreline \u2192 x208 outer);\n// the east eave reaches 258, covering a landing that sticks out to x256.\nsegment "seg0" from (4,124) to (204,124) width 240 high_side right overhang 25 overhang_end 50\n```\n\n**Roof coordinates are wall centrelines (under `convention center`), same as\nrooms.** `from`/`to` is the segment\'s ridge/axis and `width` its span *centred on\nthat axis*. Author them on the **same centreline grid as the walls** \u2014 a segment\nwhose axis + width match the rooms\' centrelines auto-grows to the **outer wall\nface** on every side (the compiler extends the axis by \xBD\xB7wall_thickness at each end\nand widens by wall_thickness, exactly the grow a room gets). `overhang` then\nextends *beyond* the outer face. So to cover a footprint spanning wall centrelines\n`x1..x2` (E\u2013W) and `yA..yB` (N\u2013S), write `from (x1, (yA+yB)/2) to (x2, (yA+yB)/2)\nwidth (yB - yA)` \u2014 do **not** add \xBD-wall fudge factors; the convention handles it.\n(Before this, a roof drawn on the grid sat half a wall-thickness *inside* the walls.)\n\n## Components & layers\n\n```wdl\ncomponent Bench { // a reusable mini-house in LOCAL coords (origin 0,0)\n param blen = 60 label "Bench length"\n beam name "Top" at (0,0) size (blen, 18) height 6\n}\nuse Bench as "B1" at (x,y) with { blen = 80 } // stamp it onto a floor\n\nlayer "structure" "Structure" [color "#rrggbb"] [group "Frame"] // per-house layer registry\n```\n\nA component may carry a **`goal`** \u2014 a short description of what it accomplishes,\nthe discovery key for module lookup (`wadi_module` / a `wadi_modules` query):\n\n```wdl\ncomponent Stairwell goal "climb to the next floor" {\n param rise = 116\n staircase name "Stair" at (0,0) step (7,11,44) direction south total_height rise\n}\n```\n\nComponents can also come from an **imported module** (see *Imports & modules*),\nstamped with a namespaced `use ns.Comp`:\n\n```wdl\nhouse Home {\n import "konkan/base" as kb // Stairwell, Verandah, Otla (goal-tagged)\n floor 1 "G" slab_thickness 0 {\n room Hall at (20,20) size (200,200) { wall north east south west }\n use kb.Stairwell at (60,60) with { rise = 116 } // param args use `=`, not `:`\n }\n}\n```\n\n`use ns.Comp` expands byte-identical to an inline `component`; keep module\ncomponents flat (they don\'t `use` other components). Un-overridden `param`s fall\nback to their declared defaults.\n\n## The `raw` escape (rarely needed)\n\nAnything the first-class syntax doesn\'t cover can be written as literal JSON per\nthe `.wadi` schema (`data-model.md`):\n\n```wdl\nraw "type" { "field": 1, "formulas": { "field": "= expr" } }\n```\n\n## DSL-specific pitfalls\n\n- **`convention center` and `units \u2026 per_unit 10`** belong at the top of every\n `house` \u2014 same as the JSON path. All the `coordinate-system.md` rules (Y-down,\n units, centreline abutment) apply identically; the DSL just writes them shorter.\n- **Formulas are bare expressions**, not `"= \u2026"` strings \u2014 the compiler emits the\n `= \u2026` form for you. Write `at (main.x1, main.yA)`, not `at ("= main.x1", \u2026)`.\n- **`name "\u2026"` is quoted; `room`/`pillar`/`var`/grid-line names are bare** ids\n (no spaces, and not a reserved word like `width`, `height`, `size`, `at`).\n- **Roof alone on the top floor**; segment widths/positions come from the walls\n they sit on. See `roof-v2-guide.md`.\n- **A pillar\'s `at` is its TOP-LEFT corner, not its centre.** To centre a column on\n `(cx,cy)`, author `at (cx - w/2, cy - l/2)`.\n- **Free-standing walls don\'t auto-mitre at corners** \u2014 extend endpoints so the wall\n bodies overlap (\u2265 \xBD\xB7`wall_thickness` past the shared point), or the corner is left\n as a gap.\n- **Staircases are top-anchored** \u2014 put them on the UPPER floor; they descend to the\n floor below (`check.sh` C5 flags one that lands below ground). See the staircase note.\n- **Structural conventions are enforced** \u2014 `check.sh` fails on floating floors\n (plinth-floor `height` \u2260 plinth block height; a no-slab floor with nonzero\n `slab_thickness`) and warns on exterior room sides left open. See\n `conventions.md`; the DSL editor shows the same findings in its status pill.\n- Compile after **every** edit; a parse error means the `.wadi` wasn\'t updated, so\n the live model just won\'t change \u2014 never silently wrong.\n'
|
|
418340
|
+
"body": '# The Wadi DSL (`.wdl`) \u2014 authoring reference\n\nYou author houses in the **Wadi DSL** \u2014 a small, formal language (`.wdl`) that\ncompiles to a resolved `.wadi` (`house_config.json`). The DSL is **complete**:\nevery object type in the model has first-class syntax, so you rarely need the\n`raw` escape. Authoring the DSL is more direct and less error-prone than writing\nJSON \u2014 the grammar enforces structure, and `check.sh` reports parse errors with\nline:col.\n\n**This file is the SYNTAX reference.** The *semantics* live in the other\nreferences and apply unchanged \u2014 read them:\n\n- `coordinate-system.md` \u2014 X\u2192right, **Y\u2192DOWN**, Z\u2192up; **10 units = 1 ft**;\n the **centreline** convention. The #1 source of mistakes.\n- `conventions.md` \u2014 the **structural coding conventions** (`check.sh` enforces\n them): plinth-floor height must match the plinth block, rooms must wall every\n exterior side, a no-slab floor must set `slab_thickness 0`.\n- `parametric-conventions.md` \u2014 the grid-first recipe for reusable templates.\n- `roof-v2-guide.md` \u2014 roof segments, hip vs gable, trusses, joints.\n- `data-model.md` \u2014 the underlying `.wadi` schema (what the DSL compiles to; also\n the field reference for the `raw` escape).\n\n## The loop\n\n1. Write / edit `house.wdl` \u2014 the **single shared source** (you and the human\n co-edit it; the app\'s DSL previewer renders it live). You never produce a `.wadi`.\n2. `wadi-skill/architect/scripts/check.sh house.wdl` \u2014 runs the DSL compiler +\n validator (schema + wall/roof geometry) against a **throwaway temp** just for\n feedback; fix any reported error and re-run.\n3. `preview.sh house.wdl` \u2192 read the PNGs (plans / elevations / roof) to check your\n work. (It also compiles to a throwaway temp \u2014 no persistent `.wadi`.)\n\n## Skeleton\n\n```wdl\nhouse MyHouse {\n convention center // ALWAYS use center (wall-centreline coords)\n units feet_inches per_unit 10 // 10 project units = 1 ft\n site { plot (WIDTH, LENGTH) ref (0, 0) }\n defaults { floor_height 120 wall_height 108 slab_thickness 8 wall_thickness 8 }\n\n // parametric core (optional): var, point, grid, configurator\n // component / layer declarations (optional)\n floor 0 "Plinth" { \u2026 } // floors stack in source order (0 = plinth)\n floor 1 "Ground Floor" { \u2026 }\n floor 2 "Loft" { roof \u2026 } // roof lives ALONE on its own top floor\n}\n```\n\nNumbers are **project units** (feet \xD7 10 by default). Names after `house`,\n`room`, `pillar`, `var`, `point`, `grid`, and `use`/`component` are bare\nidentifiers (no spaces); names introduced with the `name` keyword are quoted\nstrings.\n\n## Parametric core (domain-neutral)\n\n```wdl\nvar wallT = 8 // a knob; may reference other vars\nvar pilInset = (pillarW - wallT) / 2\n\npoint House { x = 420, y = 470 } // reference as House.x / House.W / House.L\n // (.W = x, .L = y \u2014 a point doubles as a size)\n\ngrid main { // named wall centrelines; publishes main.x1 / main.yA\n x: 1 @ wallT / 2, 2 @ House.W / 2, 3 @ House.W - wallT / 2\n y: A @ wallT / 2, B @ House.L / 2, C @ House.L - wallT / 2\n}\n// each line may add: \u2026 @ <expr> thick <expr> role structural|planning\n\nconfigurator { // the knobs a downstream user turns\n slider pillarW "Column size" ft [8 .. 14 step 1]\n number ceiling "Ceiling height" ft\n toggle has_loft "Add a loft"\n select roof_style "Roof style" { Flat = 0, Shed = 1, Gable = 2, Hip = 3 }\n}\n```\n\n**Formulas are automatic.** Any geometry number can be a formula \u2014 just write the\nexpression instead of a literal (`at (main.x1, main.yA)`, `size (House.W/2, 200)`).\nOperators: `+ - * /`, unary `-`, parentheses, and the functions\n`min max clamp round floor ceil abs`. References: a `var`, a `point`\n(`House.W`), or a grid line (`main.x3 - main.x1`). No comparison operators \u2014 gate\nthings with the `min/abs` idiom (see `enabled` below).\n\n## Common attribute tail (every object)\n\nAfter an object\'s geometry, in THIS order, any of:\n\n```\n\u2026 z_offset <expr> enabled <expr> layer "id" [material "id"]\n```\n\n- `enabled <expr>` \u2014 the on/off switch. A `0`/`false` value hides the object. To\n gate on a configurator variable, use a 0/1 formula:\n `enabled 1 - min(1, abs(roof_style - 3))` renders the object only when\n `roof_style == 3`. (This is how one template carries several roofs and shows\n only the chosen one.)\n- `z_offset <expr>` \u2014 lift above the floor base (split levels).\n- `material "id"` \u2014 only on plinth / ground / room / wall / staircase / kitchen /\n roof.\n\n## Objects \u2014 structure & envelope\n\n```wdl\nslab [name "N"] at (x,y) size (w,l) [thickness <t>] // floor_slab\nbeam [name "N"] at (x,y) size (w,l) [height <h>]\nplinth [name "N"] at (x,y) size (w,l) height <h> // raised base (Plinth floor)\nground [name "N"] at (x,y) size (w,l) [height <h>] // terrain plane\npillar Name at (x,y) size (w,l) [height <h>] // (x,y) = TOP-LEFT corner\n```\n\n`at (x,y)` is the **TOP-LEFT CORNER** \u2014 **not the centre** \u2014 for every one of these\n(same as rooms/slabs/beams); `size (w,l)` is width \xD7 length. All accept the common tail.\n\n**Pillars catch people out here.** A column reads as "placed at a point," but `at` is\nstill its corner. To **centre a column on a point** `(cx, cy)` \u2014 a grid node, a room\ncorner \u2014 place it at **`at (cx - w/2, cy - l/2)`**, never at `(cx, cy)`. On a grid, the\n`pilInset` idiom (see `parametric-conventions.md`) does exactly this so columns sit flush.\n\n## Objects \u2014 rooms, walls & openings\n\nA room shows exactly the walls you declare. A **bare room (no `wall` lines) is\nenclosed on all four sides.** List plain walls compactly; give a wall its own line\nonly when it carries a door/window; omit a side to leave it open (verandah).\n\n```wdl\nroom Name at (x,y) size (w,l) [height <h>] [material "\u2026"] {\n wall east west north // plain walls \u2014 several in one statement\n wall south { door Main at <offset> size (w,h) [open] } // wall WITH openings: one side\n wall west { window W at <offset> size (w,h) [sill <s>] [open] }\n item asset { \u2026 } anchor center [gap (gx,gy)] // furniture anchored inside the room\n}\n```\n\n- `wall <side>\u2026` sides are `north|south|east|west`. A `wall <side>` line may also\n add `height <h>` / `height_end <h>` (sloped).\n- `door`/`window` `at <offset>` is measured along the wall from its start;\n `size (width, height)`; `window \u2026 sill <s>` sets the sill height; `open` = a bare\n hole (no leaf/glazing).\n\nA **free-standing wall** (not a room side):\n\n```wdl\nwall Name from (x1,y1) to (x2,y2) [height <h>] [height_end <h>] [facing north|\u2026] {\n \u2026 door/window openings \u2026\n}\n```\n\n- `from`/`to` are the wall\'s **centreline** endpoints; the wall is drawn as a rectangle\n `wall_thickness` wide, centred on that line.\n- **Overlap walls at corners \u2014 they do NOT auto-mitre.** Two free-standing walls that\n merely *touch* at a shared endpoint leave an unfilled square notch (\xBD\xB7`wall_thickness`)\n at the corner, because each is just a rectangle capped at its endpoint. To fill the\n corner, **extend the endpoints so the wall bodies OVERLAP** \u2014 run at least one wall\'s\n end **half the wall thickness past** the shared point (overlapping by the full thickness\n is fine and simplest). For an L of thickness 8 meeting at `(160,40)`:\n\n ```wdl\n wall H from (40, 40) to (164, 40) height 108 // ends 4 (\xBD\xB78) PAST the corner\n wall V from (160, 40) to (160, 160) height 108 // butts into H\'s overlapped body\n ```\n\n (Room walls handle their own corners; this only applies to `wall \u2026 from \u2026 to \u2026`.)\n\n## Objects \u2014 circulation & fittings\n\n```wdl\nstaircase [name "N"] at (start_x, start_y) step (rise, tread, width)\n direction north|south|east|west\n [total_height <h>] [max_run <r>] [landing_depth <d>]\n [landing_thickness <t>] [turn clockwise|anticlockwise] [flight_gap <g>]\n\nkitchen [name "N"] path ((x,y), (x,y), \u2026) side left|right\n depth <d> height <h> [base_z <z>] // path points are literal numbers\n```\n\n**Staircases are TOP-anchored \u2014 this is the #1 mistake.** You put a staircase on the\n**UPPER** floor and it **DESCENDS** to the floor below:\n\n- `at (x,y)` is the **TOP** of the stair (where it meets the floor it\'s declared on).\n- `direction` is the **descent** direction (the way it travels going *down*).\n- `total_height` is the **drop** to the floor below (omit \u2192 the floor-below\'s height).\n- `max_run` caps a flight\'s run; exceed it and the stair auto-splits into switchback\n flights with turn landings (`landing_depth`/`turn`/`flight_gap` tune the switchback).\n\nSo a stair connecting the ground floor **up** to the first floor lives on the **First\nFloor**, descending to the ground:\n\n```wdl\nfloor 2 "First Floor" height 116 {\n slab at (\u2026) size (\u2026)\n staircase name "Stair" at (212, 64) step (7, 11, 44) // top = this floor, at the landing\n direction south total_height 116 // descends south to the floor below\n}\n```\n\nPut it on the *lower* floor (thinking of it as "climbing up") and it descends the wrong way\n\u2014 **below ground** \u2014 where it draws in 2D plans but is buried/invisible in 3D. `check.sh`\ncatches that (convention **C5**), but author it top-anchored from the start.\n\n// three ways to name the GLB, in order of preference:\nitem [name "N"] f."sofa" // 1. from an imported module (see Imports)\nitem [name "N"] "sofa" // 2. a same-file / bare-imported `asset` id\nitem [name "N"] asset { id "sofa" src "\u2026/sofa.glb" dims (w,h,d) [category "\u2026"] } // 3. inline one-off\n at (x,y) [rotation <deg>] [scale <s>]\n [anchor_to "RoomName" anchor center gap (gx,gy)]\n```\n\nPrefer the module form (`item f."bed_double"`) \u2014 `import "std-furniture" as f`\nonce and every piece is a short id, no URLs. The bare form (`item "sofa"`) needs\na matching top-level `asset "sofa" \u2026` in the file (or a bare `import`). The inline\n`asset { \u2026 }` block is only for a one-off GLB not in any pack. All three produce\nthe identical `{id,src,dims}` downstream. Furniture `dims` are the real-world size\nin **metres** `(width, height, depth)`; `src` is a GLB URL (an unreachable GLB\nshows a placeholder box, never a blank). `anchor` is one of `top-left top-center\ntop-right center-left center center-right bottom-left bottom-center bottom-right`.\n\n**Orientation \u2014 this is how you point furniture the right way.** A piece\'s FRONT\n(the side you sit at / the doors / the open side) faces a known compass direction\nper its `rotation` (degrees):\n\n| `rotation` | front faces |\n|---|---|\n| `0` | **South** (the plot front / entrance side, +Y) |\n| `90` | East |\n| `180` | North |\n| `270` | West |\n\nSo a sofa against the NORTH wall (facing into the room, i.e. south) is `rotation\n0`; against the SOUTH wall (facing north) it\'s `rotation 180`; against the WEST\nwall (facing east) `rotation 90`. The floor plan (`wadi_preview plans`) draws a\nsmall triangle on each piece\'s front edge so you can verify the way it points;\nfor a definitive 3D check use `wadi_capture_3d({ room: "\u2026" })` (first-person from\ninside the room).\n\n**Anchoring auto-orients.** When you `anchor` a piece to a wall and DON\'T give a\n`rotation`, it automatically faces away from that wall, into the room \u2014 `anchor\ntop-center` \u2192 faces south, `bottom-center` \u2192 north, `center-left` \u2192 east,\n`center-right` \u2192 west (a corner uses its north/south edge). So `item f."bed_double"\nanchor top-center` needs no rotation. An explicit `rotation` always overrides,\nand the derived value is written into the resolved model, so the plan notch and\nthe 3D view show it \u2014 anchoring never changes facing silently.\n\n## Imports & modules (reusable `.wdl` libraries)\n\nA `.wdl` file can be a **module** \u2014 top-level declarations (no `house` needed) \u2014\nthat another file `import`s. Two bundled ones: `std-furniture` (asset pack \u2192\n`item ns."id"`) and `konkan/base` (goal-tagged component pack \u2192 `use ns.Comp`;\nStairwell, Verandah, Otla, Bathroom, Kitchen, TulsiVrindavan, Parapet). The\n`konkan_cottage` example (`wadi_examples`) assembles a whole house from both.\n\n```wdl\nhouse Home {\n import "std-furniture" as f // aliased: refer to its assets as f."<id>"\n // import "std-furniture" // bare: its ids drop into scope for item "<id>"\n floor 1 "G" slab_thickness 0 {\n room Bed at (20,20) size (160,200) { wall north east south west\n item f."bed_double" anchor center }\n }\n}\n```\n\nA module file itself is just top-level `asset` (later: `component`) decls:\n\n```wdl\n// my-furniture.wdl \u2014 a house-less module (a reusable library)\nasset "daybed" src "https://\u2026/daybed.glb" dims (1.8, 0.4, 0.9) name "Daybed" category "Living"\n```\n\nOver MCP, `wadi_modules` lists importable modules and `wadi_module "<name>"`\nshows a module\'s asset ids + dimensions (filter with a `query`). Import refs\nresolve by name against the bundled `std-*` packs (a local `modules/` search\npath and git refs come later).\n\n## Objects \u2014 roof (one object; flat / shed / gable / hip)\n\nThe roof lives ALONE on its own top floor and you never set its Z (see\n`roof-v2-guide.md`). `endpoint`: `closed` = hip triangle, `open` = gable end-wall.\n\n```wdl\nroof [name "N"] pitched|shed|flat\n [endpoint open|closed]\n [slope angle <deg> | slope height <ridge_h>] // symmetric pitch\n [slope_left angle <deg>] [slope_right angle <deg>] // asymmetric gable (set BOTH)\n [overhang <o>] [slab_thickness <t>] [parapet <h> x <t>] [gable_wall_thickness <t>] {\n segment "id" from (x,y) to (x,y) width <w>\n [high_side left|right] // shed only\n [start_endpoint open|closed] [end_endpoint open|closed]\n [hip_setback (a,b)] [gable_overhang (a,b)] [hip_ridge_extension (a,b)]\n [overhang <o>] // uniform eave, all four sides\n [overhang_start <o>] [overhang_end <o>] // per-side along the axis (shed;\n // on a gable end = gable_overhang)\n [overhang_low <o>] [overhang_high <o>] // SHED eaves (down-slope / up-slope)\n [overhang_left <o>] [overhang_right <o>] // PITCHED eaves (left / right of ridge)\n [tie_beams N]\n truss "segId" fink|mono_pitch at (pos, pos, \u2026)\n }\n```\n\nSegment `from`/`to`/`width` and the `hip_setback`/\u2026 values accept formulas, so a\nroof scales with the plot (e.g. `width House.W`, `hip_setback (Verandah.L, Padvi.L)`).\n\n**Per-side overhang (cantilever one edge).** `overhang <o>` sets a uniform eave on\nall four sides. Any sloping roof can override a side independently \u2014 each defaults to\n`overhang`. **Along the axis:** `overhang_start` / `overhang_end` (on a shed, or a\ngable open end \u2014 there they\'re the same as `gable_overhang`; a hip end is geometric,\ntuned via `hip_setback`). **Eaves:** `overhang_low` / `overhang_high` on a **shed**\n(down-slope / up-slope); `overhang_left` / `overhang_right` on a **pitched** roof\n(the two eaves either side of the ridge). A bigger eave overhang also drops that\neave\'s edge along the same pitch, so the slope stays planar. (Per-eave on a *pitched*\nroof is single-segment only \u2014 on a multi-segment roof the eaves share one height so\njoints line up.)\n\n**Asymmetric gable (saltbox) \u2014 two independent slope angles.** A pitched roof\'s\n`slope` gives both faces the same pitch (a symmetric gable). To make the two sides\ndifferent, set **both** `slope_left` and `slope_right` (angles) \u2014 they override\n`slope`. The two eaves stay put (footprint unchanged) and the ridge shifts across the\nwidth so each face takes its angle; the gable-end triangle and trusses follow. `left`/\n`right` are by the segment\'s left normal \u2014 the **same sides as** `overhang_left`/\n`overhang_right`. Angles are measured to the wall-top eave line. Setting only one side\nis ignored (falls back to symmetric). Intended for a single-segment gable (`endpoint\nopen`); on a hip end the ridge shift skews the hip, so keep it to gables.\n\n```wdl\nroof pitched endpoint open slope_left angle 45 slope_right angle 25 {\n segment "s0" from (House.W/2, 0) to (House.W/2, House.L) width House.W\n}\n```\nIdiom: keep the roof FOOTPRINT (its supported edges) on the main room, then cantilever\none eave to cover an entry landing / stair \u2014 end the axis on the room wall and set a big\n`overhang_end`:\n```wdl\n// footprint ends on the main room\'s east wall (x204 centreline \u2192 x208 outer);\n// the east eave reaches 258, covering a landing that sticks out to x256.\nsegment "seg0" from (4,124) to (204,124) width 240 high_side right overhang 25 overhang_end 50\n```\n\n**Roof coordinates are wall centrelines (under `convention center`), same as\nrooms.** `from`/`to` is the segment\'s ridge/axis and `width` its span *centred on\nthat axis*. Author them on the **same centreline grid as the walls** \u2014 a segment\nwhose axis + width match the rooms\' centrelines auto-grows to the **outer wall\nface** on every side (the compiler extends the axis by \xBD\xB7wall_thickness at each end\nand widens by wall_thickness, exactly the grow a room gets). `overhang` then\nextends *beyond* the outer face. So to cover a footprint spanning wall centrelines\n`x1..x2` (E\u2013W) and `yA..yB` (N\u2013S), write `from (x1, (yA+yB)/2) to (x2, (yA+yB)/2)\nwidth (yB - yA)` \u2014 do **not** add \xBD-wall fudge factors; the convention handles it.\n(Before this, a roof drawn on the grid sat half a wall-thickness *inside* the walls.)\n\n## Components & layers\n\n```wdl\ncomponent Bench { // a reusable mini-house in LOCAL coords (origin 0,0)\n param blen = 60 label "Bench length"\n beam name "Top" at (0,0) size (blen, 18) height 6\n}\nuse Bench as "B1" at (x,y) with { blen = 80 } // stamp it onto a floor\n\nlayer "structure" "Structure" [color "#rrggbb"] [group "Frame"] // per-house layer registry\n```\n\nA component may carry a **`goal`** \u2014 a short description of what it accomplishes,\nthe discovery key for module lookup (`wadi_module` / a `wadi_modules` query):\n\n```wdl\ncomponent Stairwell goal "climb to the next floor" {\n param rise = 116\n staircase name "Stair" at (0,0) step (7,11,44) direction south total_height rise\n}\n```\n\nComponents can also come from an **imported module** (see *Imports & modules*),\nstamped with a namespaced `use ns.Comp`:\n\n```wdl\nhouse Home {\n import "konkan/base" as kb // Stairwell, Verandah, Otla (goal-tagged)\n floor 1 "G" slab_thickness 0 {\n room Hall at (20,20) size (200,200) { wall north east south west }\n use kb.Stairwell at (60,60) with { rise = 116 } // param args use `=`, not `:`\n }\n}\n```\n\n`use ns.Comp` expands byte-identical to an inline `component`; keep module\ncomponents flat (they don\'t `use` other components). Un-overridden `param`s fall\nback to their declared defaults.\n\n## The `raw` escape (rarely needed)\n\nAnything the first-class syntax doesn\'t cover can be written as literal JSON per\nthe `.wadi` schema (`data-model.md`):\n\n```wdl\nraw "type" { "field": 1, "formulas": { "field": "= expr" } }\n```\n\n## DSL-specific pitfalls\n\n- **`convention center` and `units \u2026 per_unit 10`** belong at the top of every\n `house` \u2014 same as the JSON path. All the `coordinate-system.md` rules (Y-down,\n units, centreline abutment) apply identically; the DSL just writes them shorter.\n- **Formulas are bare expressions**, not `"= \u2026"` strings \u2014 the compiler emits the\n `= \u2026` form for you. Write `at (main.x1, main.yA)`, not `at ("= main.x1", \u2026)`.\n- **`name "\u2026"` is quoted; `room`/`pillar`/`var`/grid-line names are bare** ids\n (no spaces, and not a reserved word like `width`, `height`, `size`, `at`).\n- **Roof alone on the top floor**; segment widths/positions come from the walls\n they sit on. See `roof-v2-guide.md`.\n- **A pillar\'s `at` is its TOP-LEFT corner, not its centre.** To centre a column on\n `(cx,cy)`, author `at (cx - w/2, cy - l/2)`.\n- **Free-standing walls don\'t auto-mitre at corners** \u2014 extend endpoints so the wall\n bodies overlap (\u2265 \xBD\xB7`wall_thickness` past the shared point), or the corner is left\n as a gap.\n- **Staircases are top-anchored** \u2014 put them on the UPPER floor; they descend to the\n floor below (`check.sh` C5 flags one that lands below ground). See the staircase note.\n- **Structural conventions are enforced** \u2014 `check.sh` fails on floating floors\n (plinth-floor `height` \u2260 plinth block height; a no-slab floor with nonzero\n `slab_thickness`) and warns on exterior room sides left open. See\n `conventions.md`; the DSL editor shows the same findings in its status pill.\n- Compile after **every** edit; a parse error means the `.wadi` wasn\'t updated, so\n the live model just won\'t change \u2014 never silently wrong.\n'
|
|
418011
418341
|
},
|
|
418012
418342
|
"conventions": {
|
|
418013
418343
|
"title": "Structural coding conventions (C1/C2/C3\u2026)",
|
|
418014
|
-
"body": '# Wadi structural conventions (coding guidelines)\n\nA house can be **well-formed but structurally unsound**: it passes the schema and\nthe wall/roof geometry check, yet the building would not stand up \u2014 a floor floats\nin mid-air, a room is open to the weather, walls hover above a phantom slab. These\nare the *coding conventions* every Wadi house must follow.\n\nThey are **formally defined here** and **enforced in code** by the structural\nlinter (`editor/src/lint/structural.ts`), which runs automatically:\n\n- in **`check.sh`** (and `validate.mjs`) \u2014 **errors fail** the check, **warnings**\n are printed but advisory;\n- in the **DSL editor** \u2014 the status pill shows the count and lists every finding\n in its hover tooltip, while still rendering the model so you can *see* the\n unsound part.\n\nEach finding carries its convention id (`C1`, `C2`, \u2026) so this document and the\nlinter stay in lockstep. Add a rule by adding a check to `lintStructure` **and** a\nsection here with the next id.\n\n---\n\n## The vertical model (why C1 and C3 exist)\n\nFloors stack in source order (floor 0 = the Plinth floor). The renderer places\nthem like this (`editor/src/three/coords.ts`):\n\n- **A floor\'s base elevation = the running sum of the previous floors\' `height`\n only.** `wall_height` and `slab_thickness` do **not** raise the next floor.\n- The **plinth block** is drawn to its *own* `height`. So the floor above sits at\n `plinth-floor.height`, while the plinth top is at `plinth.height` \u2014 they must be\n equal or the floor above floats/sinks by the difference. \u2192 **C1**\n- **`slab_thickness` lifts a floor\'s walls within its band** (`wallZ = base +\n slab_thickness`) \u2014 it is the deck the walls stand on. With no slab object there\n is no deck, so the walls float by that amount. \u2192 **C3**\n\n`height`, `wall_height`, and `slab_thickness` are otherwise **independent** \u2014 the\nmodel enforces no relationship between them. These conventions add the few\nrelationships that structural soundness *does* require.\n\n---\n\n## C1 \u2014 The plinth floor\'s height must match the plinth block height \xB7 **error**\n\n**Statement.** A floor that carries a `plinth` object (the Plinth floor) must set\nan explicit `height`, and that height must equal the plinth block\'s `height`.\n\n**Rationale.** The floor above is stacked at `plinth-floor.height`; the plinth\nblock rises to `plinth.height`. If they differ, the floor above floats above the\nplinth (`floor.height > plinth.height`) or sinks into it (`<`). If the floor\n`height` is omitted it silently defaults to `100`, almost never the plinth height.\n\n**Fix.**\n\n```wdl\nfloor 0 "Plinth" height 40 { // == the plinth block height below\n ground name "Ground" at (0,0) size (500,500)\n plinth name "Plinth" at (\u2026) size (\u2026) height 40\n}\n```\n\n(If the plinth block omits its own `height`, it follows the floor height and is\nconsistent by construction \u2014 but set the floor `height` explicitly anyway, so the\nstack is not left to the default.)\n\n---\n\n## C2 \u2014 A room must wall every exterior side \xB7 **warning**\n\n**Statement.** A room shown with a **partial** `walls` list must still wall every\nside that faces **outside** (no room beyond it). Interior (shared) sides may be\nomitted \u2014 the neighbour\'s wall stands on the shared centreline.\n\n**Rationale.** A room shows exactly the walls it declares; a **bare room (no\n`wall` lines) is enclosed on all four sides**. But the moment you add a `wall`\nline to hang a door or window, the room switches to a *whitelist* \u2014 every side you\ndon\'t list is now a hole. An exterior hole leaves the room open to the weather.\nThis is the #1 footgun the conventions guard against.\n\nIt is a **warning**, not an error, because an open exterior side is sometimes\nintentional (a verandah / open padvi). If it is deliberate, leave it \u2014 the warning\ndocuments the choice. Otherwise, add the wall.\n\n**Fix.** List the plain exterior walls compactly alongside the opening walls:\n\n```wdl\nroom Living at (x,y) size (w,l) {\n wall east west // plain exterior sides \u2014 enclosed\n wall south { door Main at 120 size (36,84) }\n wall north { window N1 at 100 size (60,50) sill 35 }\n}\n```\n\n*(The check samples several points along each side, so a side sheltered by rooms\nabove is correctly treated as interior, not open. It also skips a side that\nalready has a wall on its line \u2014 one declared by an adjacent or overlapping room,\nor a standalone wall \u2014 so a shared exterior wall the neighbour declares is not\ndouble-flagged.)*\n\n---\n\n## C3 \u2014 A floor with no slab must set slab_thickness to 0 \xB7 **error**\n\n**Statement.** A floor that has wall/room objects but **no `floor_slab` object**\nmust set `slab_thickness 0`.\n\n**Rationale.** `slab_thickness` is the deck the floor\'s walls stand on\n(`wallZ = base + slab_thickness`). Its default is `8`. With no slab object there is\nno deck, so every wall on the floor floats `slab_thickness` units above the floor\nbase. Setting it to `0` puts the walls on the floor base; alternatively, model the\ndeck by adding a `slab`.\n\n**Fix.**\n\n```wdl\nfloor 1 "Ground" slab_thickness 0 { // no slab modelled \u2192 walls sit on the base\n room Studio at (\u2026) size (\u2026) { \u2026 }\n}\n```\n\n*(This does not fire on a floor that carries no walls/rooms \u2014 e.g. a Plinth floor\nof just `ground` + `plinth`, or a roof-only top floor \u2014 where `slab_thickness` is\nharmless.)*\n\n---\n\n## C4 \u2014 A stacked floor\'s height should equal wall_height + slab_thickness \xB7 **warning**\n\n**Statement.** A floor that carries a floor above it (and has walls/rooms) should set\n`height` = `wall_height` + `slab_thickness`.\n\n**Rationale.** The next floor sits at `base + height`; this floor\'s walls stand on the\ndeck and reach `base + slab_thickness + wall_height`. When `height` is larger, the floor\nabove leaves a gap over the walls; when smaller, the walls poke through it. (These three\nfields are otherwise independent \u2014 see the vertical model above.) It is a **warning** \u2014 a\ndeliberate gap is legitimate (a service plenum, a deep transfer beam) \u2014 but usually they\nshould match.\n\n**Fix.** Make them add up, most simply via the house defaults:\n\n```wdl\ndefaults { floor_height 116 wall_height 108 slab_thickness 8 } // 108 + 8 = 116\n```\n\n*(Skipped for the plinth floor \u2014 governed by C1 \u2014 and for the topmost floor, since nothing\nstacks on its walls.)*\n\n## C5 \u2014 A staircase must land on a floor, not below ground \xB7 **warning**\n\n**Statement.** A staircase\'s descent must not carry it below the ground plane (z < 0).\n\n**Rationale.** Staircases are **top-anchored**: you place one on the **upper** floor and it\n**descends** to the floor below (`at` is the top, `direction` is the descent, `total_height`\nis the drop). Put it on the *lower* floor (as if climbing up), or give it too large a\n`total_height`, and the expanded flight lands **below ground** \u2014 it still draws in the 2D\nplans (which ignore Z) but is **buried and invisible in 3D**, with no other error. This is\nthe one that bit a real design: a stair on the ground floor "climbing" to the first floor\nwas expanded to `z_offset: -105` and vanished from the 3D view.\n\n**Fix.** Move the staircase **up one floor** and let it descend. The stair that connects the\nground floor to the first floor lives on the **First Floor**:\n\n```wdl\nfloor 2 "First Floor" height 116 {\n slab at (\u2026) size (\u2026)\n staircase name "Stair" at (212, 64) step (7, 11, 44) // `at` = the TOP (this floor)\n direction south total_height 116 // descends to the floor below\n}\n```\n\n*(See the staircase section of `dsl.md` for the full top-anchored convention.)*\n\n## Running the checks\n\n```bash\nwadi-skill/architect/scripts/check.sh house.wdl\n```\n\n- **`\u2716 [C\u2026]`** \u2014 a structural **error**; the check exits non-zero. Fix before you\n save/share.\n- **`\u26A0 [C\u2026]`** \u2014 a structural **warning**; advisory. Fix, or keep it if the open\n side is intentional.\n\nIn the DSL editor the same findings appear in the status pill (hover for the full\nlist); the model still renders so you can see the problem.\n\n---\n\n## Planned conventions (not yet enforced)\n\nDocumented so authors know they matter; not linted yet:\n\n- **Interior partition gaps** \u2014 where two rooms share a centreline and *neither*\n declares that wall, there is no partition between them. (C2 only covers\n *exterior* sides.)\n- **Slab thickness \u2194 slab object** \u2014 when a floor *does* carry a `floor_slab`,\n its `slab_thickness` should match the slab\'s own thickness so walls sit on the\n real deck.\n- **Roof footprint coverage** \u2014 the roof segments should span the top occupied\n floor\'s footprint (no uncovered rooms).\n'
|
|
418344
|
+
"body": "# Wadi structural conventions (coding guidelines)\n\nA house can be **well-formed but structurally unsound**: it passes the schema and\nthe wall/roof geometry check, yet the building would not stand up \u2014 a floor floats\nin mid-air, a room is open to the weather, walls hover above a phantom slab. These\nare the *coding conventions* every Wadi house must follow.\n\nThey are **formally defined here** and **enforced in code** by the structural\nlinter (`editor/src/lint/structural.ts`), which runs automatically:\n\n- in **`check.sh`** (and `validate.mjs`) \u2014 **errors fail** the check, **warnings**\n are printed but advisory;\n- in the **DSL editor** \u2014 the status pill shows the count and lists every finding\n in its hover tooltip, while still rendering the model so you can *see* the\n unsound part.\n\nEach finding carries its convention id (`C1`, `C2`, \u2026) so this document and the\nlinter stay in lockstep. Add a rule by adding a check to `lintStructure` **and** a\nsection here with the next id.\n\n---\n\n## The vertical model (why C1 and C3 exist)\n\nFloors stack in source order (floor 0 = the Plinth floor). The renderer places\nthem like this (`editor/src/three/coords.ts`):\n\n- **A floor's base elevation = the running sum of the previous floors' `height`\n only.** `wall_height` and `slab_thickness` do **not** raise the next floor.\n- The **plinth block** is drawn to its *own* `height`. So the floor above sits at\n `plinth-floor.height`, while the plinth top is at `plinth.height` \u2014 they must be\n equal or the floor above floats/sinks by the difference. \u2192 **C1**\n- **`slab_thickness` lifts a floor's walls within its band** (`wallZ = base +\n slab_thickness`) \u2014 it is the deck the walls stand on. With no slab object there\n is no deck, so the walls float by that amount. \u2192 **C3**\n\n`height`, `wall_height`, and `slab_thickness` are otherwise **independent** \u2014 the\nmodel enforces no relationship between them. These conventions add the few\nrelationships that structural soundness *does* require.\n\n---\n\n## C1 \u2014 The plinth floor's height must match the plinth block height \xB7 **error**\n\n**Statement.** A floor that carries a `plinth` object (the Plinth floor) must set\nan explicit `height`, and that height must equal the plinth block's `height`.\n\n**Rationale.** The floor above is stacked at `plinth-floor.height`; the plinth\nblock rises to `plinth.height`. If they differ, the floor above floats above the\nplinth (`floor.height > plinth.height`) or sinks into it (`<`). If the floor\n`height` is omitted it silently defaults to `100`, almost never the plinth height.\n\n**Fix.**\n\n```wdl\nfloor 0 \"Plinth\" height 40 { // == the plinth block height below\n ground name \"Ground\" at (0,0) size (500,500)\n plinth name \"Plinth\" at (\u2026) size (\u2026) height 40\n}\n```\n\n(If the plinth block omits its own `height`, it follows the floor height and is\nconsistent by construction \u2014 but set the floor `height` explicitly anyway, so the\nstack is not left to the default.)\n\n---\n\n## C2 \u2014 A room must wall every exterior side \xB7 **warning**\n\n**Statement.** A room shown with a **partial** `walls` list must still wall every\nside that faces **outside** (no room beyond it). Interior (shared) sides may be\nomitted \u2014 the neighbour's wall stands on the shared centreline.\n\n**Rationale.** A room shows exactly the walls it declares; a **bare room (no\n`wall` lines) is enclosed on all four sides**. But the moment you add a `wall`\nline to hang a door or window, the room switches to a *whitelist* \u2014 every side you\ndon't list is now a hole. An exterior hole leaves the room open to the weather.\nThis is the #1 footgun the conventions guard against.\n\nIt is a **warning**, not an error, because an open exterior side is sometimes\nintentional (a verandah / open padvi). If it is deliberate, leave it \u2014 the warning\ndocuments the choice. Otherwise, add the wall.\n\n**Fix.** List the plain exterior walls compactly alongside the opening walls:\n\n```wdl\nroom Living at (x,y) size (w,l) {\n wall east west // plain exterior sides \u2014 enclosed\n wall south { door Main at 120 size (36,84) }\n wall north { window N1 at 100 size (60,50) sill 35 }\n}\n```\n\n*(The check samples several points along each side, so a side sheltered by rooms\nabove is correctly treated as interior, not open. It also skips a side that\nalready has a wall on its line \u2014 one declared by an adjacent or overlapping room,\nor a standalone wall \u2014 so a shared exterior wall the neighbour declares is not\ndouble-flagged.)*\n\n---\n\n## C3 \u2014 A floor with no slab must set slab_thickness to 0 \xB7 **error**\n\n**Statement.** A floor that has wall/room objects but **no `floor_slab` object**\nmust set `slab_thickness 0`.\n\n**Rationale.** `slab_thickness` is the deck the floor's walls stand on\n(`wallZ = base + slab_thickness`). Its default is `8`. With no slab object there is\nno deck, so every wall on the floor floats `slab_thickness` units above the floor\nbase. Setting it to `0` puts the walls on the floor base; alternatively, model the\ndeck by adding a `slab`.\n\n**Fix.**\n\n```wdl\nfloor 1 \"Ground\" slab_thickness 0 { // no slab modelled \u2192 walls sit on the base\n room Studio at (\u2026) size (\u2026) { \u2026 }\n}\n```\n\n*(This does not fire on a floor that carries no walls/rooms \u2014 e.g. a Plinth floor\nof just `ground` + `plinth`, or a roof-only top floor \u2014 where `slab_thickness` is\nharmless.)*\n\n---\n\n## C4 \u2014 A stacked floor's height should equal wall_height + slab_thickness \xB7 **warning**\n\n**Statement.** A floor that carries a floor above it (and has walls/rooms) should set\n`height` = `wall_height` + `slab_thickness`.\n\n**Rationale.** The next floor sits at `base + height`; this floor's walls stand on the\ndeck and reach `base + slab_thickness + wall_height`. When `height` is larger, the floor\nabove leaves a gap over the walls; when smaller, the walls poke through it. (These three\nfields are otherwise independent \u2014 see the vertical model above.) It is a **warning** \u2014 a\ndeliberate gap is legitimate (a service plenum, a deep transfer beam) \u2014 but usually they\nshould match.\n\n**Fix.** Make them add up, most simply via the house defaults:\n\n```wdl\ndefaults { floor_height 116 wall_height 108 slab_thickness 8 } // 108 + 8 = 116\n```\n\n*(Skipped for the plinth floor \u2014 governed by C1 \u2014 and for the topmost floor, since nothing\nstacks on its walls.)*\n\n## C5 \u2014 A staircase must land on a floor, not below ground \xB7 **warning**\n\n**Statement.** A staircase's descent must not carry it below the ground plane (z < 0).\n\n**Rationale.** Staircases are **top-anchored**: you place one on the **upper** floor and it\n**descends** to the floor below (`at` is the top, `direction` is the descent, `total_height`\nis the drop). Put it on the *lower* floor (as if climbing up), or give it too large a\n`total_height`, and the expanded flight lands **below ground** \u2014 it still draws in the 2D\nplans (which ignore Z) but is **buried and invisible in 3D**, with no other error. This is\nthe one that bit a real design: a stair on the ground floor \"climbing\" to the first floor\nwas expanded to `z_offset: -105` and vanished from the 3D view.\n\n**Fix.** Move the staircase **up one floor** and let it descend. The stair that connects the\nground floor to the first floor lives on the **First Floor**:\n\n```wdl\nfloor 2 \"First Floor\" height 116 {\n slab at (\u2026) size (\u2026)\n staircase name \"Stair\" at (212, 64) step (7, 11, 44) // `at` = the TOP (this floor)\n direction south total_height 116 // descends to the floor below\n}\n```\n\n*(See the staircase section of `dsl.md` for the full top-anchored convention.)*\n\n## C6 \u2014 Openings on the same wall must not overlap \xB7 **error**\n\n**Statement.** Two openings (doors/windows) cut into the **same physical wall** must not\noverlap along it. This includes openings that belong to **two different rooms sharing a\nboundary wall** \u2014 a door on Living's east side and a door on Bedroom's west side sit on the\nsame wall line and can collide.\n\n**Rationale.** Each opening is a boolean-subtract from the wall. Overlapping spans merge into\none ragged hole (or fight over the same brick), which is never what you meant \u2014 and on a\nshared wall it silently punches a bigger gap than either room's plan shows.\n\n**Fix.** Offset or narrow one opening so the spans are disjoint. Openings are measured from\nthe wall's start corner (`offset` = near edge; the opening occupies `[offset, offset+width]`).\nFor a shared wall, remember both rooms' offsets are measured along the **same** line, so a\ndoor at `offset 50 width 40` (\u2192 `[50,90]`) on one room clears a door at `offset 90` on the\nother, but not one at `offset 60`.\n\n## C7 \u2014 Furniture items should not overlap \xB7 **warning**\n\n**Statement.** Two furniture `item`s whose plan footprints overlap are flagged \u2014 as a\n**warning**, because it is sometimes intentional (a rug under a table, a lamp on a desk,\ndeliberately stacked pieces).\n\n**Rationale.** More often it's a placement slip \u2014 two beds dropped on the same spot, or an\nanchored piece that reflowed into another when a room was resized. The footprint used is the\nitem's rotated bounding box (yaw-aware), so it matches what the plan draws.\n\n**Fix.** Reposition one item, or ignore the warning if the overlap is deliberate.\n\n## Running the checks\n\n```bash\nwadi-skill/architect/scripts/check.sh house.wdl\n```\n\n- **`\u2716 [C\u2026]`** \u2014 a structural **error**; the check exits non-zero. Fix before you\n save/share.\n- **`\u26A0 [C\u2026]`** \u2014 a structural **warning**; advisory. Fix, or keep it if the open\n side is intentional.\n\nIn the DSL editor the same findings appear in the status pill (hover for the full\nlist); the model still renders so you can see the problem.\n\n---\n\n## Planned conventions (not yet enforced)\n\nDocumented so authors know they matter; not linted yet:\n\n- **Interior partition gaps** \u2014 where two rooms share a centreline and *neither*\n declares that wall, there is no partition between them. (C2 only covers\n *exterior* sides.)\n- **Slab thickness \u2194 slab object** \u2014 when a floor *does* carry a `floor_slab`,\n its `slab_thickness` should match the slab's own thickness so walls sit on the\n real deck.\n- **Roof footprint coverage** \u2014 the roof segments should span the top occupied\n floor's footprint (no uncovered rooms).\n"
|
|
418015
418345
|
},
|
|
418016
418346
|
"coordinate-system": {
|
|
418017
418347
|
"title": "Coordinates, units & the centreline convention",
|
|
@@ -418430,7 +418760,7 @@ server.registerTool(
|
|
|
418430
418760
|
}
|
|
418431
418761
|
lines.push(` e.g. \`item ns."${assets[0].id}" at (x, y)\` or in a room \`item ns."${assets[0].id}" anchor center\``);
|
|
418432
418762
|
lines.push(
|
|
418433
|
-
` Orientation: a piece's front faces SOUTH at rotation 0 (90=East, 180=North, 270=West) \u2014
|
|
418763
|
+
` Orientation: a piece's front faces SOUTH at rotation 0 (90=East, 180=North, 270=West). ANCHORING auto-orients \u2014 an anchored piece with no rotation faces into the room (anchor top-center\u2192south, bottom-center\u2192north, center-left\u2192east, center-right\u2192west); an explicit rotation overrides. wadi_preview plans draws a front-notch; wadi_capture_3d({room}) shows it from inside.`
|
|
418434
418764
|
);
|
|
418435
418765
|
}
|
|
418436
418766
|
return { content: [{ type: "text", text: lines.join("\n") }] };
|