@adatechnology/game-floorplan-three 0.10.0 → 0.10.2

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.
@@ -3,6 +3,7 @@ var GameFloorplanThree = (() => {
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
7
  var __export = (target, all) => {
7
8
  for (var name in all)
8
9
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -16,6 +17,7 @@ var GameFloorplanThree = (() => {
16
17
  return to;
17
18
  };
18
19
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
19
21
 
20
22
  // src/index.ts
21
23
  var index_exports = {};
@@ -70,7 +72,7 @@ var GameFloorplanThree = (() => {
70
72
  shade: () => shade
71
73
  });
72
74
 
73
- // ../game-shapes/dist/chunk-M5N2SHNL.js
75
+ // ../game-shapes/dist/chunk-FZQTELDQ.js
74
76
  function canonicalJson(value) {
75
77
  if (value === null) return "null";
76
78
  if (typeof value === "number") return Object.is(value, -0) ? "-0" : Number.isFinite(value) ? String(value) : JSON.stringify(String(value));
@@ -982,17 +984,19 @@ var GameFloorplanThree = (() => {
982
984
  if (p.prevZ) p.prevZ.nextZ = p.nextZ;
983
985
  if (p.nextZ) p.nextZ.prevZ = p.prevZ;
984
986
  }
985
- function Node(i, x, y) {
986
- this.i = i;
987
- this.x = x;
988
- this.y = y;
989
- this.prev = null;
990
- this.next = null;
991
- this.z = 0;
992
- this.prevZ = null;
993
- this.nextZ = null;
994
- this.steiner = false;
995
- }
987
+ var Node = class {
988
+ constructor(i, x, y) {
989
+ this.i = i;
990
+ this.x = x;
991
+ this.y = y;
992
+ this.prev = null;
993
+ this.next = null;
994
+ this.z = 0;
995
+ this.prevZ = null;
996
+ this.nextZ = null;
997
+ this.steiner = false;
998
+ }
999
+ };
996
1000
  function signedArea(data, start, end, dim) {
997
1001
  let sum = 0;
998
1002
  for (let i = start, j = end - dim; i < end; i += dim) {
@@ -1817,6 +1821,9 @@ var GameFloorplanThree = (() => {
1817
1821
  return mesh2;
1818
1822
  });
1819
1823
  }
1824
+ function isMesh(o) {
1825
+ return !!o && o.isMesh === true;
1826
+ }
1820
1827
 
1821
1828
  // ../game-props3d/dist/index.js
1822
1829
  function rng(seed) {
@@ -3691,6 +3698,20 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
3691
3698
  const WITH_MAP = { roughcast: 1, block: 1 };
3692
3699
  class Accumulator {
3693
3700
  constructor() {
3701
+ __publicField(this, "cv");
3702
+ __publicField(this, "ci");
3703
+ __publicField(this, "p");
3704
+ __publicField(this, "n");
3705
+ __publicField(this, "c");
3706
+ __publicField(this, "u");
3707
+ __publicField(this, "i");
3708
+ __publicField(this, "nv");
3709
+ __publicField(this, "ni");
3710
+ __publicField(this, "lim");
3711
+ __publicField(this, "cur");
3712
+ __publicField(this, "piece0");
3713
+ __publicField(this, "mat", "");
3714
+ __publicField(this, "group", "");
3694
3715
  this.cv = 2048;
3695
3716
  this.ci = 3072;
3696
3717
  this.p = new Float32Array(this.cv * 3);
@@ -3753,7 +3774,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
3753
3774
  g.position.copy(u.pose0.p);
3754
3775
  g.quaternion.copy(u.pose0.q);
3755
3776
  g.scale.copy(u.pose0.s);
3756
- const e = new THREE.Vector3(...a.axis || [0, 1, 0]);
3777
+ const [ax, ay, az] = a.axis || [0, 1, 0];
3778
+ const e = new THREE.Vector3(ax, ay, az);
3757
3779
  if (a.type === "swing" || a.type === "toggle") g.rotateOnAxis(e, (a.angle || 0) * t);
3758
3780
  else if (a.type === "slide") g.translateOnAxis(e, (a.dist || 0) * t);
3759
3781
  else if (a.type === "scale") {
@@ -3848,7 +3870,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
3848
3870
  }
3849
3871
  if (uvr) {
3850
3872
  let gu = G.u[k * 2], gv = G.u[k * 2 + 1];
3851
- for (let r = uvr.rot | 0; r > 0; r--) {
3873
+ for (let r = (uvr.rot ?? 0) | 0; r > 0; r--) {
3852
3874
  const t = gu;
3853
3875
  gu = gv;
3854
3876
  gv = 1 - t;
@@ -3946,14 +3968,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
3946
3968
  A.nv += n;
3947
3969
  }
3948
3970
  let bxImpl = bxBase;
3949
- function bx(...a) {
3950
- return bxImpl(...a);
3951
- }
3952
- K.getBx = () => bxImpl;
3953
- K.setBx = (f) => {
3971
+ const bx = (...a) => bxImpl(...a);
3972
+ const getBx = () => bxImpl;
3973
+ const setBx = (f) => {
3954
3974
  bxImpl = f;
3955
3975
  };
3956
- Object.assign(K, { GEO, UV_SCALE, WITH_MAP, Accumulator, cursor, PARTS, MIRRORS, part, applyPart, _Y, _qa, _qb, pieceRecord, structurePiece, accFor, _q, _e, _col, rgbOf, put, boxC, bx, cylBase, polyFace });
3976
+ const defined = { GEO, UV_SCALE, WITH_MAP, Accumulator, cursor, PARTS, MIRRORS, part, applyPart, _Y, _qa, _qb, pieceRecord, structurePiece, accFor, _q, _e, _col, rgbOf, put, boxC, bx, getBx, setBx, cylBase, polyFace };
3977
+ Object.assign(K, defined);
3957
3978
  }
3958
3979
 
3959
3980
  // src/kernel/noise.ts
@@ -3971,17 +3992,20 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
3971
3992
  const n = 0.5 * vnoise(x / 5.5, z / 5.5) + 0.32 * vnoise(x / 1.9 + 31, z / 1.9) + 0.18 * vnoise(x / 0.8 + 7, z / 0.8), m = vnoise(x / 9 + 100, z / 9 + 50) - 0.5, f = 0.76 + 0.5 * n;
3972
3993
  return type === "dirt" ? [f * (1 + 0.14 * m), f * (1 + 0.03 * m), f * (1 - 0.18 * m)] : [f * (1 + 0.1 * m), f * (1 + 0.05 * m), f * (1 - 0.1 * m)];
3973
3994
  }
3974
- Object.assign(K, { _h2, vnoise, macroGround });
3995
+ const defined = { _h2, vnoise, macroGround };
3996
+ Object.assign(K, defined);
3975
3997
  }
3976
3998
 
3977
3999
  // src/materials/textures.ts
3978
4000
  function installMaterialsTextures(K, _shared) {
3979
4001
  const { DOC, THREE, cfg } = K;
3980
4002
  function texture(n, f, rep = true, rx = 1, ry = 1) {
4003
+ if (!DOC) throw new Error("game-floorplan-three: the procedural textures need a document (options.document)");
3981
4004
  const c = DOC.createElement("canvas");
3982
4005
  c.width = n;
3983
4006
  c.height = n;
3984
4007
  const g = c.getContext("2d");
4008
+ if (!g) throw new Error("game-floorplan-three: no 2d canvas context");
3985
4009
  f(g, n);
3986
4010
  const t = new THREE.CanvasTexture(c);
3987
4011
  t.colorSpace = THREE.SRGBColorSpace;
@@ -4100,10 +4124,16 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4100
4124
  const TEX = {};
4101
4125
  for (const k of Object.keys(TEXGEN)) TEX[k] = cfg.textures && cfg.textures[k] || TEXGEN[k]();
4102
4126
  const ATLAS = {};
4103
- Object.assign(K, { texture, rngTexture, TEXGEN, TEX, ATLAS });
4127
+ const defined = { texture, rngTexture, TEXGEN, TEX, ATLAS };
4128
+ Object.assign(K, defined);
4104
4129
  }
4105
4130
 
4106
4131
  // src/materials/materials.ts
4132
+ function context2d(c) {
4133
+ const g = c.getContext("2d");
4134
+ if (!g) throw new Error("game-floorplan-three: no 2d canvas context");
4135
+ return g;
4136
+ }
4107
4137
  function installMaterialsMaterials(K, _shared) {
4108
4138
  const { THREE, cfg, ATLAS, TEX, rngTexture } = K;
4109
4139
  function createMaterials(props) {
@@ -4115,7 +4145,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4115
4145
  return t;
4116
4146
  };
4117
4147
  if (!(cfg.atlas && cfg.atlas.floorKind)) {
4118
- const pc = props.atlas("floor").canvas, g = pc.getContext("2d");
4148
+ const pc = props.atlas("floor").canvas, g = context2d(pc);
4119
4149
  for (const c of [0, 1]) {
4120
4150
  g.save();
4121
4151
  g.globalCompositeOperation = "screen";
@@ -4130,7 +4160,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4130
4160
  g.restore();
4131
4161
  }
4132
4162
  if (!(cfg.atlas && cfg.atlas.floorKind)) {
4133
- const pc = props.atlas("floor").canvas, g = pc.getContext("2d");
4163
+ const pc = props.atlas("floor").canvas, g = context2d(pc);
4134
4164
  g.save();
4135
4165
  g.fillStyle = "rgba(128,92,62,0.52)";
4136
4166
  g.fillRect(256, 256, 256, 256);
@@ -4227,7 +4257,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4227
4257
  }
4228
4258
  const ORDER = { glass: 3, water: 2, screen: 3, building: 4 };
4229
4259
  const NO_SHADOW = /* @__PURE__ */ new Set(["dirt", "glass", "water", "screen", "building", "picture", "floor", "emissive"]);
4230
- Object.assign(K, { createMaterials, antiTile, dirtMaterial, CLOTHES_UNIFORMS, clothesMaterial, ORDER, NO_SHADOW });
4260
+ const defined = { createMaterials, antiTile, dirtMaterial, CLOTHES_UNIFORMS, clothesMaterial, ORDER, NO_SHADOW };
4261
+ Object.assign(K, defined);
4231
4262
  }
4232
4263
 
4233
4264
  // src/kernel/close-scene.ts
@@ -4238,15 +4269,18 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4238
4269
  const assembleVegetation = (...a) => K.assembleVegetation(...a);
4239
4270
  function markMesh(m, A) {
4240
4271
  const L = A.lim, fx = [];
4272
+ const pieces = shared.ctx.pieces;
4241
4273
  for (let k = 0; k < L.length; k++) {
4242
- if (!L[k].pc) continue;
4243
- const v1 = k + 1 < L.length ? L[k + 1].v : A.nv, i1 = k + 1 < L.length ? L[k + 1].i : A.ni;
4244
- if (v1 > L[k].v) fx.push({ id: L[k].pc.id, v0: L[k].v, v1, i0: L[k].i, i1 });
4274
+ const lim = L[k], pc = lim.pc;
4275
+ if (!pc) continue;
4276
+ const next = L[k + 1];
4277
+ const v1 = next ? next.v : A.nv, i1 = next ? next.i : A.ni;
4278
+ if (v1 > lim.v) fx.push({ id: pc.id, v0: lim.v, v1, i0: lim.i, i1 });
4245
4279
  }
4246
4280
  if (!fx.length) return;
4247
4281
  const u = m.userData, ids = [...new Set(fx.map((f) => f.id))], weight = {};
4248
4282
  for (const f of fx) {
4249
- const mt = shared.ctx.pieces.get(f.id).mat;
4283
+ const mt = pieces.get(f.id).mat;
4250
4284
  weight[mt] = (weight[mt] || 0) + f.v1 - f.v0;
4251
4285
  }
4252
4286
  u.ranges = fx;
@@ -4254,7 +4288,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4254
4288
  u.destructionMaterial = Object.keys(weight).sort((a, b) => weight[b] - weight[a])[0];
4255
4289
  if (ids.length === 1) {
4256
4290
  u.destructionPart = ids[0];
4257
- const pc = shared.ctx.pieces.get(ids[0]);
4291
+ const pc = pieces.get(ids[0]);
4258
4292
  if (pc.role) u.structuralRole = pc.role;
4259
4293
  }
4260
4294
  }
@@ -4305,7 +4339,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4305
4339
  assembleVegetation(groups);
4306
4340
  return groups;
4307
4341
  }
4308
- Object.assign(K, { markMesh, closeScene });
4342
+ const defined = { markMesh, closeScene };
4343
+ Object.assign(K, defined);
4309
4344
  }
4310
4345
 
4311
4346
  // src/house/helpers.ts
@@ -4343,8 +4378,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4343
4378
  for (const h of holes) L = L.flatMap((r) => subRect(r, h));
4344
4379
  return L;
4345
4380
  }
4346
- const wallColor = (c) => c && c.color && colorOf(c.color.wall) != null ? colorOf(c.color.wall) : 14999768;
4347
- const floorColor = (c) => c && c.color && colorOf(c.color.floor) != null ? colorOf(c.color.floor) : 11577496;
4381
+ const wallColor = (c) => {
4382
+ const k = c && c.color ? colorOf(c.color.wall) : null;
4383
+ return k != null ? k : 14999768;
4384
+ };
4385
+ const floorColor = (c) => {
4386
+ const k = c && c.color ? colorOf(c.color.floor) : null;
4387
+ return k != null ? k : 11577496;
4388
+ };
4348
4389
  function stairFootprint(m) {
4349
4390
  const c = Math.cos(m.ry), s = Math.sin(m.ry), pts = [[-m.w / 2, -m.d / 2], [m.w / 2, -m.d / 2], [m.w / 2, m.d / 2], [-m.w / 2, m.d / 2]].map(([a, b]) => [m.x + a * c + b * s, m.z - a * s + b * c]);
4350
4391
  return [Math.min(...pts.map((p) => p[0])), Math.min(...pts.map((p) => p[1])), Math.max(...pts.map((p) => p[0])), Math.max(...pts.map((p) => p[1]))];
@@ -4355,13 +4396,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4355
4396
  const pitch = A[f + 1].y0 - A[f].y0;
4356
4397
  return h > pitch && h - pitch <= 0.45 ? pitch : h;
4357
4398
  }
4358
- Object.assign(K, { OPEN_ROOM_TYPES: OPEN_ROOM_TYPES3, NO_CEILING, OPEN_AREA, EPS: EPS3, Y0, colorOf, rectsOf: rectsOf2, roomAt, subRect, subRects, wallColor, floorColor, stairFootprint, effectiveHeight });
4399
+ const defined = { OPEN_ROOM_TYPES: OPEN_ROOM_TYPES3, NO_CEILING, OPEN_AREA, EPS: EPS3, Y0, colorOf, rectsOf: rectsOf2, roomAt, subRect, subRects, wallColor, floorColor, stairFootprint, effectiveHeight };
4400
+ Object.assign(K, defined);
4359
4401
  }
4360
4402
 
4361
4403
  // src/house/walls.ts
4362
4404
  function installHouseWalls(K, shared) {
4363
4405
  const { EPS: EPS3, Y0, boxC, bx, cursor, effectiveHeight, pieceRecord, structurePiece, wallColor } = K;
4364
- const sh = (color2, factor) => K.sh(color2, factor);
4406
+ const sh = (...a) => K.sh(...a);
4365
4407
  function wallBox2(alongU, L, a, b, ya, yb, th, cL, cH, mL, mH) {
4366
4408
  if (yb - ya < 1e-4 || b - a < 1e-4) return;
4367
4409
  if (alongU) {
@@ -4407,7 +4449,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4407
4449
  const corners = /* @__PURE__ */ new Map();
4408
4450
  const looks = /* @__PURE__ */ new Map();
4409
4451
  for (const w of R.walls) {
4410
- const f = w.floor;
4452
+ const f = w.floor, colliders = shared.ctx.colliders;
4411
4453
  cursor.group = "f" + f;
4412
4454
  cursor.pc = pieceOf(w);
4413
4455
  const y0 = Y0(f), pitch = f + 1 < nA ? Y0(f + 1) - y0 : Infinity, th = w.thickness || 0.15, alongU = w.axis === "u";
@@ -4419,7 +4461,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4419
4461
  const face = sideL.exterior ? sideL : sideH;
4420
4462
  looks.set(w.id, { mat: face.mat, color: face.color, top: y0 + hh });
4421
4463
  }
4422
- shared.ctx.colliders.push({ type: "wall", piece: w.id, f, x0: alongU ? s0 : L - th / 2, z0: alongU ? L - th / 2 : s0, x1: alongU ? s1 : L + th / 2, z1: alongU ? L + th / 2 : s1 });
4464
+ colliders.push({ type: "wall", piece: w.id, f, x0: alongU ? s0 : L - th / 2, z0: alongU ? L - th / 2 : s0, x1: alongU ? s1 : L + th / 2, z1: alongU ? L + th / 2 : s1 });
4423
4465
  if (w.type === "railing") {
4424
4466
  const c0 = shared.ctx.colors.metal != null ? shared.ctx.colors.metal : 9080466;
4425
4467
  const sx = alongU ? 1 : 0, sz = alongU ? 0 : 1, len = s1 - s0, n = Math.max(1, Math.round(len / 1.4));
@@ -4485,7 +4527,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4485
4527
  }
4486
4528
  cursor.pc = null;
4487
4529
  }
4488
- Object.assign(K, { wallBox: wallBox2, sideOf, pieceOf, nearestWall, walls, wallPillars });
4530
+ const defined = { wallBox: wallBox2, sideOf, pieceOf, nearestWall, walls, wallPillars };
4531
+ Object.assign(K, defined);
4489
4532
  }
4490
4533
 
4491
4534
  // src/house/doors.ts
@@ -4504,7 +4547,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4504
4547
  }
4505
4548
  shared.doorState = /* @__PURE__ */ new Map();
4506
4549
  function doors() {
4507
- shared.ctx.leaves = [];
4550
+ const leaves = shared.ctx.leaves = [], doorState = shared.doorState, colliders = shared.ctx.colliders;
4508
4551
  const R = shared.ctx.r, cut = shared.ctx.cut, C = shared.ctx.colors, wood = C.wood != null ? C.wood : 8016948, frame2 = sh(wood, 0.55);
4509
4552
  for (const p of R.doors) {
4510
4553
  const f = p.floor;
@@ -4535,21 +4578,21 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4535
4578
  }
4536
4579
  const leaf = (u0, u1, y_0, y_1, tt, color2, mat = "wood") => alongU ? bx(mat, u0, y0 + y_0, L - tt / 2, u1, y0 + y_1, L + tt / 2, color2) : bx(mat, L - tt / 2, y0 + y_0, u0, L + tt / 2, y0 + y_1, u1, color2);
4537
4580
  const extC = wood;
4538
- const open0 = p.blocked ? false : shared.doorState.has(p.id) ? shared.doorState.get(p.id) : !!p.open;
4539
- shared.doorState.set(p.id, open0);
4581
+ const open0 = p.blocked ? false : doorState.has(p.id) ? doorState.get(p.id) === true : !!p.open;
4582
+ doorState.set(p.id, open0);
4540
4583
  const dc = alongU ? [p.at, L] : [L, p.at];
4541
- const fo = { id: p.id, floor: f, type: p.model === "steel" ? "steel" : "swing", open: open0, t: open0 ? 1 : 0, blockedFlag: !!p.blocked, locked: R.state === "fortified" && !!p.exterior, handleNames: [], hT: 0, cx: dc[0], cz: dc[1], visH, groups: [], col: null };
4584
+ const fo = { id: p.id, floor: f, type: p.model === "steel" ? "steel" : "swing", open: open0, t: open0 ? 1 : 0, blockedFlag: !!p.blocked, locked: R.state === "fortified" && !!p.exterior, handleNames: [], hT: 0, cx: dc[0], cz: dc[1], visH, groups: [], gs: [], col: null };
4542
4585
  const colR = { type: "door", f, x0: alongU ? a : L - th / 2, z0: alongU ? L - th / 2 : a, x1: alongU ? b : L + th / 2, z1: alongU ? L + th / 2 : b, off: open0 };
4543
- shared.ctx.colliders.push(colR);
4586
+ colliders.push(colR);
4544
4587
  fo.col = colR;
4545
4588
  const leafBox = (hu, d0, d1, y_0, y_1, tt, color2, mat) => alongU ? bx(mat, d0, y_0, -tt / 2, d1, y_1, tt / 2, color2) : bx(mat, -tt / 2, y_0, d0, tt / 2, y_1, d1, color2);
4546
- const newGroup = (k, hu, topY) => {
4589
+ const newGroup2 = (k, hu, topY) => {
4547
4590
  cursor.group = "dyn:" + p.id + ":" + k;
4548
4591
  fo.groups.push({ name: cursor.group, pos: alongU ? [hu, topY != null ? y0 + topY : y0, L] : [L, topY != null ? y0 + topY : y0, hu] });
4549
4592
  };
4550
4593
  if (p.model === "steel") {
4551
- const light = [14276044, 13223615, 14999766], pal = ((R.seed | 0) + p.id.length * 7) % 4, color2 = pal === 3 ? wood : light[pal], mid = (a + b) / 2;
4552
- newGroup(0, mid, visH);
4594
+ const light = [14276044, 13223615, 14999766], pal = ((Number(R.seed) | 0) + p.id.length * 7) % 4, color2 = pal === 3 ? wood : light[pal], mid = (a + b) / 2;
4595
+ newGroup2(0, mid, visH);
4553
4596
  const la = a + jw - mid, lb = b - jw - mid, nSec = Math.max(4, Math.round(visH / 0.5)), hs = visH / nSec, grv = sh(color2, 0.55);
4554
4597
  leafBox(0, la, lb, -visH, 0, 0.05, color2, "metal");
4555
4598
  for (let k = 1; k < nSec; k++) leafBox(0, la, lb, -k * hs - 0.012, -k * hs + 0.012, 0.07, grv, "metal");
@@ -4564,7 +4607,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4564
4607
  for (let k = 0; k < nf; k++) {
4565
4608
  const u0 = nf === 2 ? k ? (aa + bb) / 2 : aa : aa, u1 = nf === 2 ? k ? bb : (aa + bb) / 2 : bb, color2 = p.exterior ? extC : wood;
4566
4609
  const hingeAt = nf === 2 ? k ? u1 : u0 : p.hinge === "end" ? u1 : u0, dir = hingeAt === u0 ? 1 : -1, len = u1 - u0;
4567
- newGroup(k, hingeAt);
4610
+ newGroup2(k, hingeAt);
4568
4611
  const d0 = dir > 0 ? 5e-3 : -len + 5e-3, d1 = dir > 0 ? len - 5e-3 : -5e-3;
4569
4612
  leafBox(hingeAt, d0, d1, 0, visH, 0.04, color2, PMAT);
4570
4613
  {
@@ -4600,7 +4643,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4600
4643
  fo.rot = Math.atan2(n[0] * A[1] - n[1] * A[0], A[0] * n[0] + A[1] * n[1]);
4601
4644
  }
4602
4645
  }
4603
- shared.ctx.leaves.push(fo);
4646
+ leaves.push(fo);
4604
4647
  cursor.group = "f" + f;
4605
4648
  if (p.blocked) {
4606
4649
  part("window_boards", [0, 0, 0], () => {
@@ -4628,11 +4671,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4628
4671
  }
4629
4672
  }
4630
4673
  }, { id: "boards:" + p.id }, "f" + f);
4631
- shared.ctx.colliders.push({ type: "board", f, x0: alongU ? a : L - th / 2, z0: alongU ? L - th / 2 : a, x1: alongU ? b : L + th / 2, z1: alongU ? L + th / 2 : b });
4674
+ colliders.push({ type: "board", f, x0: alongU ? a : L - th / 2, z0: alongU ? L - th / 2 : a, x1: alongU ? b : L + th / 2, z1: alongU ? L + th / 2 : b });
4632
4675
  }
4633
4676
  }
4634
4677
  }
4635
- Object.assign(K, { doorLineSides, doors });
4678
+ const defined = { doorLineSides, doors };
4679
+ Object.assign(K, defined);
4636
4680
  }
4637
4681
 
4638
4682
  // src/house/windows.ts
@@ -4692,7 +4736,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4692
4736
  }
4693
4737
  }
4694
4738
  }
4695
- Object.assign(K, { FRAME_COLORS, SILL_COLORS, windows });
4739
+ const defined = { FRAME_COLORS, SILL_COLORS, windows };
4740
+ Object.assign(K, defined);
4696
4741
  }
4697
4742
 
4698
4743
  // src/house/floors.ts
@@ -4702,7 +4747,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4702
4747
  if (shared.ctx._flights && shared.ctx._flights.r === shared.ctx.r) return shared.ctx._flights.l;
4703
4748
  const R = shared.ctx.r, mp = /* @__PURE__ */ new Map();
4704
4749
  for (const m of R.items) {
4705
- if (m.type !== "stairs" || !m.link) continue;
4750
+ if (m.type !== "stairs" || !m.link || typeof m.link !== "object") continue;
4706
4751
  const k = [m.link.from, m.link.to, m.x.toFixed(2), m.z.toFixed(2), (m.ry || 0).toFixed(2)].join("|");
4707
4752
  if (!mp.has(k)) mp.set(k, { m, from: m.link.from, to: m.link.to, rect: stairFootprint(m) });
4708
4753
  }
@@ -4721,7 +4766,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4721
4766
  }
4722
4767
  const panelRects = (p) => p.footprint && p.footprint.length ? p.footprint : [p.aabb];
4723
4768
  function tilesOf(parent, rc) {
4724
- const ps = parent && shared.ctx.panelsOf && shared.ctx.panelsOf.get(parent);
4769
+ const ps = parent ? shared.ctx.panelsOf && shared.ctx.panelsOf.get(parent) : void 0;
4725
4770
  if (!ps) return [[parent ? structurePiece(parent) : null, rc]];
4726
4771
  const out = [], taken = [];
4727
4772
  for (const p of ps) for (const q of panelRects(p)) {
@@ -4785,13 +4830,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4785
4830
  const { rectsOf: rectsOf2, Y0, boxC, bx, cursor, flights, stairFootprint, structurePiece } = K;
4786
4831
  const sh = (...a) => K.sh(...a);
4787
4832
  function buildStairs() {
4788
- const R = shared.ctx.r;
4789
- shared.ctx.stairs = [];
4833
+ const R = shared.ctx.r, stairs = shared.ctx.stairs = [];
4790
4834
  for (const vo of flights()) {
4791
4835
  const m = vo.m, f = vo.from, Dr = m.d - (vo.LP || 0);
4792
4836
  cursor.group = "f" + f;
4793
4837
  cursor.pc = structurePiece("stairs_" + vo.from + "_" + vo.to);
4794
- const y0 = Y0(f), H = Y0(m.link.to) - y0, n = Math.max(8, Math.round(H / 0.18)), c = Math.cos(m.ry), s = Math.sin(m.ry);
4838
+ const y0 = Y0(f), H = Y0(vo.to) - y0, n = Math.max(8, Math.round(H / 0.18)), c = Math.cos(m.ry), s = Math.sin(m.ry);
4795
4839
  const wood = shared.ctx.colors.wood != null ? shared.ctx.colors.wood : 9071176, under = sh(wood, 0.7);
4796
4840
  const P = (lx, lz) => [m.x + lx * c + lz * s, m.z - lx * s + lz * c];
4797
4841
  const boxL = (mat, lx, y, lz, w, h, d, color2, rx = 0) => {
@@ -4814,7 +4858,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4814
4858
  }
4815
4859
  }
4816
4860
  cursor.pc = null;
4817
- shared.ctx.stairs.push({ m, f, to: vo.to, y0, H, rect: stairFootprint(m), landingPoint: (vo.LP || 0) / m.d });
4861
+ stairs.push({ m, f, to: vo.to, y0, H, rect: stairFootprint(m), landingPoint: (vo.LP || 0) / m.d });
4818
4862
  }
4819
4863
  }
4820
4864
  function elevator() {
@@ -4831,7 +4875,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4831
4875
  }
4832
4876
  }
4833
4877
  }
4834
- Object.assign(K, { buildStairs, elevator });
4878
+ const defined = { buildStairs, elevator };
4879
+ Object.assign(K, defined);
4835
4880
  }
4836
4881
 
4837
4882
  // src/lights/fixtures.ts
@@ -4871,14 +4916,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
4871
4916
  c: (mat, x, y, z, r, h, color2, seg) => api.cylinder(M, mat, x, y0 + y, z, r, h, color2, 0, 0, seg),
4872
4917
  e: (mat, x, y, z, r, h, color2) => api.cylinder(M, mat, x, y0 + y - h / 2, z, r, h, color2, 0, 0, "sphere"),
4873
4918
  t(mat, p, q, r, color2, seg) {
4919
+ const tc = color2 ?? NaN;
4874
4920
  const dx = q[0] - p[0], dy = q[1] - p[1], dz = q[2] - p[2], L = Math.hypot(dx, dy, dz);
4875
4921
  if (L < 1e-5) return;
4876
4922
  const nx = dx / L, ny = dy / L, nz = dz / L;
4877
4923
  if (Math.abs(nx) < 1e-4 && Math.abs(nz) < 1e-4) {
4878
- api.cylinder(M, mat, p[0], y0 + Math.min(p[1], q[1]), p[2], r, L, color2, 0, 0, seg);
4924
+ api.cylinder(M, mat, p[0], y0 + Math.min(p[1], q[1]), p[2], r, L, tc, 0, 0, seg);
4879
4925
  return;
4880
4926
  }
4881
- api.cylinder(M, mat, (p[0] + q[0]) / 2, y0 + (p[1] + q[1]) / 2, (p[2] + q[2]) / 2, r, L, color2, Math.atan2(nz, ny), -Math.asin(nx), seg);
4927
+ api.cylinder(M, mat, (p[0] + q[0]) / 2, y0 + (p[1] + q[1]) / 2, (p[2] + q[2]) / 2, r, L, tc, Math.atan2(nz, ny), -Math.asin(nx), seg);
4882
4928
  },
4883
4929
  polyFace: (mat, pts, color2, hint) => polyFace(mat, pts.map((p) => W(p[0], p[1], p[2])), color2, hint && [hint[0] * c + hint[2] * s, hint[1], -hint[0] * s + hint[2] * c]),
4884
4930
  part(type, lx, ly, lz, fn, meta) {
@@ -5057,7 +5103,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5057
5103
  K2.part("light_switch", x, 0, 0.011, () => K2.b("plain", x, -0.018, 0.0125, two ? 0.03 : 0.036, 0.034, 8e-3, 16513782, 0, -0.12), { id: "sw_" + M.seed + "_" + i, room: M.room, target: M.target || M.room, opens: { type: "toggle", axis: [1, 0, 0], angle: 0.24 }, on: !!M.on, t0: M.on ? 1 : 0 });
5058
5104
  }
5059
5105
  }
5060
- Object.assign(K, { hashString, rngString, SEED, STYLE, kit2, arcPoints, TEMP_WARM, TEMP_NEUTRAL, TEMP_COOL, colorTemperature, lightStyle, ceilingLamp, tableLamp, floorLamp, sconce, outdoorLamp, lightSwitch });
5106
+ const defined = { hashString, rngString, SEED, STYLE, kit2, arcPoints, TEMP_WARM, TEMP_NEUTRAL, TEMP_COOL, colorTemperature, lightStyle, ceilingLamp, tableLamp, floorLamp, sconce, outdoorLamp, lightSwitch };
5107
+ Object.assign(K, defined);
5061
5108
  }
5062
5109
 
5063
5110
  // src/lights/decor.ts
@@ -5124,7 +5171,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5124
5171
  void sd;
5125
5172
  }
5126
5173
  }
5127
- Object.assign(K, { decorLights });
5174
+ const defined = { decorLights };
5175
+ Object.assign(K, defined);
5128
5176
  }
5129
5177
 
5130
5178
  // src/lot/terrain.ts
@@ -5177,7 +5225,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5177
5225
  if (x < b) out.push([x, b]);
5178
5226
  return out.filter((q) => q[1] - q[0] > 0.3);
5179
5227
  }
5180
- Object.assign(K, { terrain, freeSpans });
5228
+ const defined = { terrain, freeSpans };
5229
+ Object.assign(K, defined);
5181
5230
  }
5182
5231
 
5183
5232
  // src/lot/perimeter.ts
@@ -5197,7 +5246,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5197
5246
  for (const s of lt.perimeter) {
5198
5247
  const alongU = Math.abs(s.v1 - s.v0) < EPS3, L = alongU ? s.v0 : s.u0, a = Math.min(alongU ? s.u0 : s.v0, alongU ? s.u1 : s.v1), b = Math.max(alongU ? s.u0 : s.v0, alongU ? s.u1 : s.v1);
5199
5248
  cursor.pc = pieceRecord("lot_wall:" + s.id, s.type === "wall" ? "brick" : s.type === "fence" ? "wood_soft" : "steel", null, { tags: ["wall"] });
5200
- const th = s.thickness || 0.15, h = s.height, color2 = colorOf(s.color) != null ? colorOf(s.color) : C.wall || 12104874, len = b - a;
5249
+ const th = s.thickness || 0.15, h = s.height, color2 = colorOf(s.color) ?? (C.wall || 12104874), len = b - a;
5201
5250
  const B = (mat, u0, y0, u1, y1, t, c, off = 0) => alongU ? bx(mat, u0, y0, L + off - t / 2, u1, y1, L + off + t / 2, c) : bx(mat, L + off - t / 2, y0, u0, L + off + t / 2, y1, u1, c);
5202
5251
  const col = { type: "lot_wall", f: -1, x0: alongU ? a : L - th / 2, z0: alongU ? L - th / 2 : a, x1: alongU ? b : L + th / 2, z1: alongU ? L + th / 2 : b };
5203
5252
  shared.ctx.colliders.push(col);
@@ -5271,7 +5320,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5271
5320
  }
5272
5321
  }
5273
5322
  }
5274
- Object.assign(K, { perimeter, paths });
5323
+ const defined = { perimeter, paths };
5324
+ Object.assign(K, defined);
5275
5325
  }
5276
5326
 
5277
5327
  // src/lot/gates.ts
@@ -5287,7 +5337,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5287
5337
  cursor.group = "lot";
5288
5338
  const structure = R.style, auto = structure !== "budget", wall = colorOf("wall") || 12104874, cu = (lt.rect[0] + lt.rect[2]) / 2, cz = (lt.rect[1] + lt.rect[3]) / 2;
5289
5339
  for (const g of lt.gates) {
5290
- const gc = colorOf(g.color) != null ? colorOf(g.color) : C.gate != null ? C.gate : 2763310, a = g.u - g.width / 2, b = g.u + g.width / 2, v = g.v, h = g.height, t = 0.05, ped = g.model === "pedestrian", tilt = g.model === "tilting";
5340
+ const gc = colorOf(g.color) ?? (C.gate != null ? C.gate : 2763310), a = g.u - g.width / 2, b = g.u + g.width / 2, v = g.v, h = g.height, t = 0.05, ped = g.model === "pedestrian", tilt = g.model === "tilting";
5291
5341
  const sd = cz - v >= 0 ? 1 : -1;
5292
5342
  const pil = (x0, x1, high) => {
5293
5343
  bx("plaster", x0, 0, v - 0.13, x1, high, v + 0.13, wall);
@@ -5359,7 +5409,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5359
5409
  if (!g.open || ped) shared.ctx.colliders.push({ type: "gate", f: -1, x0: a, z0: v - 0.1, x1: b, z1: v + 0.1 });
5360
5410
  }
5361
5411
  }
5362
- Object.assign(K, { slideDirection, gates });
5412
+ const defined = { slideDirection, gates };
5413
+ Object.assign(K, defined);
5363
5414
  }
5364
5415
 
5365
5416
  // src/roof/roofs.ts
@@ -5373,13 +5424,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5373
5424
  function roofs() {
5374
5425
  const R = shared.ctx.r, F = R.facade, C = shared.ctx.colors, nA = R.floors.length, type = F.roof;
5375
5426
  cursor.group = "roof";
5376
- shared.ctx.roofRects = [];
5377
- shared.ctx.gutter = gutterConfig();
5378
- shared.ctx.gutter.ncond = 0;
5379
- shared.ctx.gutter.nbuz = 0;
5380
- shared.ctx.gutter.bz = /* @__PURE__ */ new Set();
5427
+ const roofRects = shared.ctx.roofRects = [];
5428
+ const G = shared.ctx.gutter = gutterConfig();
5429
+ G.ncond = 0;
5430
+ G.nbuz = 0;
5431
+ G.bz = /* @__PURE__ */ new Set();
5381
5432
  shared.ctx.gutterInfo = { gutters: [], downpipes: [], drains: [] };
5382
- const roofColor = C.roof != null ? C.roof : 11031610, gable = (R.seed | 0) % 2 === 0;
5433
+ const roofColor = C.roof != null ? C.roof : 11031610, gable = (Number(R.seed) | 0) % 2 === 0;
5383
5434
  for (let f = 0; f < nA; f++) {
5384
5435
  const rs = R.rooms.filter((c) => c.floor === f && c.type !== "void" && !c.outbuilding && !OPEN_AREA(c)).flatMap(rectsOf2), up = R.rooms.filter((c) => c.floor === f + 1 && c.type !== "void").flatMap(rectsOf2);
5385
5436
  if (!rs.length) continue;
@@ -5401,7 +5452,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5401
5452
  return Y0(f) + Math.max(...cs.map((c) => c.ceiling)) + 0.2;
5402
5453
  };
5403
5454
  if (type === "slab") {
5404
- for (let j = 0; j < nz; j++) for (let i = 0; i < nx; i++) if (O(j, i)) shared.ctx.roofRects.push({ f, r: [xs[i], zs[j], xs[i + 1], zs[j + 1]], slab: true, yb: pe(xs[i], zs[j], xs[i + 1], zs[j + 1]) + 0.03 });
5455
+ for (let j = 0; j < nz; j++) for (let i = 0; i < nx; i++) if (O(j, i)) roofRects.push({ f, r: [xs[i], zs[j], xs[i + 1], zs[j + 1]], slab: true, yb: pe(xs[i], zs[j], xs[i + 1], zs[j + 1]) + 0.03 });
5405
5456
  slabs(f, xs, zs, O, U, nx, nz, full, pe, C);
5406
5457
  cursor.pc = null;
5407
5458
  continue;
@@ -5424,16 +5475,16 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5424
5475
  if (U(q.j0 - 1, i)) touchesU[1] = 1;
5425
5476
  if (U(q.j1 + 1, i)) touchesU[3] = 1;
5426
5477
  }
5427
- shared.ctx.roofRects.push({ f, r: [x0, z0, x1, z1], touchesU });
5478
+ roofRects.push({ f, r: [x0, z0, x1, z1], touchesU });
5428
5479
  const ybq = pe(x0, z0, x1, z1);
5429
5480
  roofRect(type, x0, z0, x1, z1, ybq, roofColor, gable && single, F, touchesU);
5430
5481
  cursor.pc = null;
5431
- if (shared.ctx.gutter.on) gutter(type, f, x0, z0, x1, z1, ybq, touchesU);
5482
+ if (G.on) gutter(type, f, x0, z0, x1, z1, ybq, touchesU);
5432
5483
  }
5433
5484
  }
5434
5485
  for (const e of shared.ctx.outbuildingList || []) {
5435
5486
  const [x0, z0, x1, z1] = e.aabb, yb = Y0(0) + (e.ceiling || 2.6) + 0.2;
5436
- shared.ctx.roofRects.push({ f: 0, r: [x0, z0, x1, z1], outbuilding: e.id });
5487
+ roofRects.push({ f: 0, r: [x0, z0, x1, z1], outbuilding: e.id });
5437
5488
  if (type === "slab") {
5438
5489
  const c = C.facade != null ? C.facade : 14209216;
5439
5490
  bx("plaster", x0 - 0.08, yb, z0 - 0.08, x1 + 0.08, yb + 0.03, z1 + 0.08, sh(C.ceiling != null ? C.ceiling : 12104876, 0.85));
@@ -5444,13 +5495,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5444
5495
  roofRect(type, x0, z0, x1, z1, yb, roofColor, true, F, [0, 0, 0, 0]);
5445
5496
  cursor.pc = null;
5446
5497
  shared.ctx.noPiece = false;
5447
- if (shared.ctx.gutter.on) gutter(type, 0, x0, z0, x1, z1, yb, [0, 0, 0, 0]);
5498
+ if (G.on) gutter(type, 0, x0, z0, x1, z1, yb, [0, 0, 0, 0]);
5448
5499
  }
5449
5500
  }
5450
- Object.assign(K, { roofs });
5501
+ const defined = { roofs };
5502
+ Object.assign(K, defined);
5451
5503
  }
5452
5504
 
5453
5505
  // src/roof/gutters.ts
5506
+ var paletteMeta = (colors) => colors.meta;
5454
5507
  function installRoofGutters(K, shared) {
5455
5508
  const { boxC, bx, cursor, roomAt } = K;
5456
5509
  const sh = (...a) => K.sh(...a);
@@ -5467,7 +5520,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5467
5520
  const draw2 = rnd() < p, light = rnd() < 0.6;
5468
5521
  void draw2;
5469
5522
  const on = true;
5470
- return { on, rnd, color: high ? 3816770 : light ? 15527921 : 10857392, bad: (shared.ctx.colors.meta && shared.ctx.colors.meta.state) === "abandoned" || R.state === "abandoned", fallback: false };
5523
+ return { on, rnd, color: high ? 3816770 : light ? 15527921 : 10857392, bad: paletteMeta(shared.ctx.colors)?.state === "abandoned" || R.state === "abandoned", fallback: false };
5471
5524
  }
5472
5525
  function gutter(type, f, X0, Z0, X1, Z1, yb, touchesU) {
5473
5526
  const G = shared.ctx.gutter, o = type === "fiber_cement" ? 0.3 : 0.45, x0 = X0 - (touchesU[0] ? 0 : o), x1 = X1 + (touchesU[2] ? 0 : o), z0 = Z0 - (touchesU[1] ? 0 : o), z1 = Z1 + (touchesU[3] ? 0 : o), c = G.color, y = yb - 0.05;
@@ -5509,7 +5562,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5509
5562
  const px = cx + sx * 0.06, pz = cz + sz * 0.06;
5510
5563
  if (!freeAt(px, pz, sx, sz)) return false;
5511
5564
  const floats = G.bad && G.ncond === 1, yt = yb - 0.1, ybx = floats ? 0.7 : 0.04;
5512
- G.ncond++;
5565
+ G.ncond = (G.ncond ?? 0) + 1;
5513
5566
  if (run2 >= 2) boxC("plain", (sides[run2][4] + px) / 2, yt, pz, Math.abs(sides[run2][4] - px), 0.07, 0.07, c);
5514
5567
  else boxC("plain", px, yt, (sides[run2][4] + pz) / 2, 0.07, 0.07, Math.abs(sides[run2][4] - pz), c);
5515
5568
  boxC("plain", px, (ybx + yt) / 2, pz, 0.08, yt - ybx, 0.08, c);
@@ -5543,7 +5596,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5543
5596
  function drain(x, z, px, pz, c) {
5544
5597
  const g0 = cursor.group;
5545
5598
  cursor.group = "f0";
5546
- if (px != null) boxC("plain", (px + x) / 2, 0.075, (pz + z) / 2, Math.abs(x - px) + 0.05, 0.05, Math.abs(z - pz) + 0.05, sh(c, 0.85));
5599
+ if (px != null && pz != null && c != null) boxC("plain", (px + x) / 2, 0.075, (pz + z) / 2, Math.abs(x - px) + 0.05, 0.05, Math.abs(z - pz) + 0.05, sh(c, 0.85));
5547
5600
  const t = 0.045;
5548
5601
  bx("plain", x - 0.12, 0, z - 0.12, x + 0.12, t - 6e-3, z + 0.12, 12170668);
5549
5602
  bx("metal", x - 0.11, t, z - 0.11, x + 0.11, t + 0.012, z + 0.11, 5922145);
@@ -5554,7 +5607,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5554
5607
  bx("metal", x - 0.085, t + 0.012, z - 6e-3, x + 0.085, t + 0.02, z + 6e-3, 9080466);
5555
5608
  cursor.group = g0;
5556
5609
  }
5557
- Object.assign(K, { gutterConfig, gutter, drain });
5610
+ const defined = { gutterConfig, gutter, drain };
5611
+ Object.assign(K, defined);
5558
5612
  }
5559
5613
 
5560
5614
  // src/roof/slabs.ts
@@ -5588,15 +5642,16 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5588
5642
  side(free(j, i + 1), x1 + o - t, z0 - ez0, x1 + o, z1 + ez1);
5589
5643
  side(free(j - 1, i), x0 - ex0, z0 - o, x1 + ex1, z0 - o + t);
5590
5644
  side(free(j + 1, i), x0 - ex0, z1 + o - t, x1 + ex1, z1 + o);
5591
- if (shared.ctx.gutter && shared.ctx.gutter.on) for (const [ok, dx, dz] of [[free(j - 1, i), 0, -1], [free(j + 1, i), 0, 1], [free(j, i - 1), -1, 0], [free(j, i + 1), 1, 0]]) {
5645
+ const G = shared.ctx.gutter;
5646
+ if (G && G.on && G.bz) for (const [ok, dx, dz] of [[free(j - 1, i), 0, -1], [free(j + 1, i), 0, 1], [free(j, i - 1), -1, 0], [free(j, i + 1), 1, 0]]) {
5592
5647
  const kd = f + ":" + dx + ":" + dz;
5593
- if (!ok || shared.ctx.gutter.bz.has(kd)) continue;
5594
- shared.ctx.gutter.bz.add(kd);
5595
- shared.ctx.gutter.nbuz++;
5596
- const mx = (x0 + x1) / 2, mz = (z0 + z1) / 2, ex = dx ? dx < 0 ? x0 - o : x1 + o : mx, ez = dz ? dz < 0 ? z0 - o : z1 + o : mz, cc = shared.ctx.gutter.color;
5648
+ if (!ok || G.bz.has(kd)) continue;
5649
+ G.bz.add(kd);
5650
+ G.nbuz = (G.nbuz ?? 0) + 1;
5651
+ const mx = (x0 + x1) / 2, mz = (z0 + z1) / 2, ex = dx ? dx < 0 ? x0 - o : x1 + o : mx, ez = dz ? dz < 0 ? z0 - o : z1 + o : mz, cc = G.color;
5597
5652
  boxC("plain", ex + dx * 0.15, yb + 0.1, ez + dz * 0.15, dx ? 0.42 : 0.14, 0.1, dz ? 0.42 : 0.14, cc);
5598
5653
  boxC("plain", ex + dx * 0.36, yb + 0.1, ez + dz * 0.36, dx ? 0.04 : 0.18, 0.14, dz ? 0.04 : 0.18, sh(cc, 0.8));
5599
- if (shared.ctx.gutter.bad) boxC("plain", ex + dx * 0.05, yb + 0.5 * 0, ez + dz * 0.05, dx ? 0.06 : 0.3, 0.02, dz ? 0.06 : 0.3, 4868674);
5654
+ if (G.bad) boxC("plain", ex + dx * 0.05, yb + 0.5 * 0, ez + dz * 0.05, dx ? 0.06 : 0.3, 0.02, dz ? 0.06 : 0.3, 4868674);
5600
5655
  {
5601
5656
  const tx = ex + dx * 0.38, tz = ez + dz * 0.38;
5602
5657
  let lv = true;
@@ -5616,7 +5671,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5616
5671
  }
5617
5672
  }
5618
5673
  }
5619
- Object.assign(K, { slabs });
5674
+ const defined = { slabs };
5675
+ Object.assign(K, defined);
5620
5676
  }
5621
5677
 
5622
5678
  // src/roof/tiles.ts
@@ -5749,7 +5805,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5749
5805
  }
5750
5806
  return m ? structurePiece(m.id) : null;
5751
5807
  }
5752
- Object.assign(K, { R_STYLE, tileRelief, ridge, pieceOfPane });
5808
+ const defined = { R_STYLE, tileRelief, ridge, pieceOfPane };
5809
+ Object.assign(K, defined);
5753
5810
  }
5754
5811
 
5755
5812
  // src/roof/rect.ts
@@ -5795,7 +5852,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5795
5852
  }
5796
5853
  const rm = alongX ? dz / 2 : dx / 2;
5797
5854
  {
5798
- const rr = shared.ctx.roofRects[shared.ctx.roofRects.length - 1];
5855
+ const roofRects = shared.ctx.roofRects, rr = roofRects[roofRects.length - 1];
5799
5856
  if (rr && !rr.yb) Object.assign(rr, { yb, tp, gable: !!gable, alongX, exterior: [x0, z0, x1, z1], rm });
5800
5857
  }
5801
5858
  if (gable) {
@@ -5832,7 +5889,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5832
5889
  }
5833
5890
  }
5834
5891
  }
5835
- Object.assign(K, { roofRect });
5892
+ const defined = { roofRect };
5893
+ Object.assign(K, defined);
5836
5894
  }
5837
5895
 
5838
5896
  // src/mirrors.ts
@@ -5843,9 +5901,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5843
5901
  function mirrorEnv() {
5844
5902
  if (shared.mirrorEnv) return shared.mirrorEnv;
5845
5903
  const mk = (f) => {
5904
+ if (!DOC) throw new Error("game-floorplan-three: the mirrors need a document (options.document)");
5846
5905
  const c = DOC.createElement("canvas");
5847
5906
  c.width = c.height = 64;
5848
5907
  const g = c.getContext("2d");
5908
+ if (!g) throw new Error("game-floorplan-three: no 2d canvas context");
5849
5909
  f(g);
5850
5910
  return c;
5851
5911
  };
@@ -5904,7 +5964,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5904
5964
  B.N.push(v.x, v.y, v.z);
5905
5965
  B.U.push(ua.getX(i), ua.getY(i));
5906
5966
  }
5907
- for (const k of geo.index.array) B.I.push(B.nv + k);
5967
+ for (const k of geo.index?.array ?? []) B.I.push(B.nv + k);
5908
5968
  B.nv += pa.count;
5909
5969
  geo.dispose();
5910
5970
  }
@@ -5982,7 +6042,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5982
6042
  m.fake.visible = !on;
5983
6043
  }
5984
6044
  }
5985
- Object.assign(K, { mirrorEnv, newMirrorState, assembleMirrors, floorAtY, chooseMirror });
6045
+ const defined = { mirrorEnv, newMirrorState, assembleMirrors, floorAtY, chooseMirror };
6046
+ Object.assign(K, defined);
5986
6047
  }
5987
6048
 
5988
6049
  // src/cars.ts
@@ -5995,13 +6056,16 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
5995
6056
  high: ["electric_hatch", "hybrid_suv", "midsize_suv", "v8_coupe", "large_suv", "midsize_pickup", "crossover_pickup", "fastback_sedan"]
5996
6057
  }, K.cfg.carKinds);
5997
6058
  const CAR_CACHE = /* @__PURE__ */ new Map();
5998
- function materialSignature(m) {
6059
+ function materialSignature(material) {
6060
+ const m = material;
5999
6061
  const f = (v) => v == null ? "" : typeof v === "number" ? v.toFixed(3) : v.isColor ? v.getHexString() : v.uuid || String(v);
6000
6062
  return [m.type, f(m.color), f(m.roughness), f(m.metalness), f(m.opacity), m.transparent ? 1 : 0, m.side, f(m.map), f(m.emissive), f(m.emissiveIntensity), m.vertexColors ? 1 : 0, m.flatShading ? 1 : 0, f(m.envMapIntensity), f(m.alphaTest)].join("|");
6001
6063
  }
6002
6064
  const BUCKETS = /* @__PURE__ */ new Map();
6003
- function bucketMaterial(m) {
6004
- if (m.type !== "MeshStandardMaterial" || m.map || m.alphaTest || m.vertexColors || !m.color) return null;
6065
+ function bucketMaterial(material) {
6066
+ if (material.type !== "MeshStandardMaterial") return null;
6067
+ const m = material;
6068
+ if (m.map || m.alphaTest || m.vertexColors || !m.color) return null;
6005
6069
  const mt = m.metalness > 0.5 ? 2 : m.metalness > 0.2 ? 1 : 0, rg = m.roughness < 0.3 ? 0 : m.roughness < 0.6 ? 1 : 2, tr = m.transparent || m.opacity < 1, op = tr ? Math.max(0.2, Math.min(0.9, Math.round(m.opacity * 5) / 5)) : 1, sig = "bucket" + mt + rg + "s" + m.side + (tr ? "t" + op : "");
6006
6070
  let b = BUCKETS.get(sig);
6007
6071
  if (!b) {
@@ -6013,7 +6077,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6013
6077
  }
6014
6078
  function carModel(k, seed) {
6015
6079
  const kc = k + "|" + shared.quality + "|" + (seed || 0);
6016
- if (CAR_CACHE.has(kc)) return CAR_CACHE.get(kc);
6080
+ if (CAR_CACHE.has(kc)) return CAR_CACHE.get(kc) ?? null;
6017
6081
  if (!FLEET) return null;
6018
6082
  let res = null;
6019
6083
  try {
@@ -6021,8 +6085,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6021
6085
  c.root.updateMatrixWorld(true);
6022
6086
  const inv = new THREE.Matrix4();
6023
6087
  const byMaterial = /* @__PURE__ */ new Map(), tmp = new THREE.Matrix4(), v = new THREE.Vector3(), nm = new THREE.Matrix3(), bb = new THREE.Box3();
6024
- c.g.traverse((o) => {
6025
- if (!o.isMesh || o.isInstancedMesh || o.isSkinnedMesh || !o.geometry || !o.geometry.attributes.position) return;
6088
+ c.g.traverse((node) => {
6089
+ if (!isMesh(node)) return;
6090
+ const o = node;
6091
+ if (o.isInstancedMesh || o.isSkinnedMesh || !o.geometry || !o.geometry.attributes.position) return;
6026
6092
  for (let p = o; p; p = p.parent) if (p.visible === false) return;
6027
6093
  const mats = Array.isArray(o.material) ? o.material : [o.material];
6028
6094
  let geo = o.geometry;
@@ -6036,7 +6102,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6036
6102
  const pa = geo.attributes.position, na = geo.attributes.normal, ua = geo.attributes.uv, total = pa.count;
6037
6103
  const grs = Array.isArray(o.material) && o.geometry.groups.length ? o.geometry.groups : [{ start: 0, count: total, materialIndex: 0 }];
6038
6104
  for (const gr of grs) {
6039
- const m = mats[gr.materialIndex] || mats[0];
6105
+ const m = (gr.materialIndex != null ? mats[gr.materialIndex] : void 0) || mats[0];
6040
6106
  if (!m) continue;
6041
6107
  const a0 = Math.min(gr.start, total), n0 = Math.min(gr.count, total - a0) - Math.min(gr.count, total - a0) % 3;
6042
6108
  if (n0 < 3) continue;
@@ -6137,7 +6203,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6137
6203
  return g;
6138
6204
  }
6139
6205
  function assembleCars(groups) {
6140
- if (shared.quality === "game") return assembleMergedCars(groups);
6206
+ if (shared.quality === "game") {
6207
+ assembleMergedCars(groups);
6208
+ return;
6209
+ }
6141
6210
  for (const C of CARS) {
6142
6211
  const g = carGroup(C.k, C.w, C.d, C.seed);
6143
6212
  if (!g) continue;
@@ -6188,7 +6257,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6188
6257
  (groups[B.parent] || (groups[B.parent] = new THREE.Group())).add(m);
6189
6258
  }
6190
6259
  }
6191
- Object.assign(K, { CARS, CAR_BY_STYLE, CAR_CACHE, materialSignature, BUCKETS, bucketMaterial, carModel, carGroup, assembleCars, assembleMergedCars });
6260
+ const defined = { CARS, CAR_BY_STYLE, CAR_CACHE, materialSignature, BUCKETS, bucketMaterial, carModel, carGroup, assembleCars, assembleMergedCars };
6261
+ Object.assign(K, defined);
6192
6262
  }
6193
6263
 
6194
6264
  // src/house/building.ts
@@ -6244,14 +6314,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6244
6314
  bx("plaster", Math.min(hall[0] - 3, color2[0]), ytop, Math.min(un[1] ? unitBox(un[1])[1] : 0, el[1]), Math.max(color2[2], un0[2]), ytop + 0.2, Math.max(un0[3], un[1] ? unitBox(un[1])[3] : 0), 11841704);
6245
6315
  shared.ctx.limits = { x0: Math.min(hall[0] - 3, color2[0]), z0: Math.min(el[1], un[1] ? unitBox(un[1])[1] : 0), x1: Math.max(color2[2], un0[2]), z1: Math.max(un0[3], un[1] ? unitBox(un[1])[3] : 0) };
6246
6316
  }
6247
- Object.assign(K, { building });
6317
+ const defined = { building };
6318
+ Object.assign(K, defined);
6248
6319
  }
6249
6320
 
6250
6321
  // src/utilities/water.ts
6251
6322
  function installUtilitiesWater(K, shared) {
6252
6323
  const { THREE, _Y, _q, cursor, cylBase, part, pieceRecord, put } = K;
6253
6324
  function createWater(r, state) {
6254
- const H = r.utilities.plumbing, cap = H ? +H.capacityL || 0 : 0, ls = { dry: [], full: [] }, points = {}, itemPoint = {};
6325
+ const H = r.utilities?.plumbing, cap = H ? +H.capacityL || 0 : 0, ls = { dry: [], full: [] }, points = {}, itemPoint = {};
6255
6326
  if (H) for (const p of H.points) {
6256
6327
  points[p.id] = p;
6257
6328
  itemPoint[p.item] = p.id;
@@ -6340,14 +6411,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6340
6411
  }
6341
6412
  const _v3 = new THREE.Vector3();
6342
6413
  function waterPipes() {
6343
- const H = shared.ctx.r.utilities.plumbing;
6414
+ const H = shared.ctx.r.utilities?.plumbing;
6344
6415
  if (!H || !H.visibleRuns) return;
6345
6416
  const nA = shared.ctx.r.floors.length;
6346
6417
  const groupOf = (c) => c && c.floor >= 0 ? "f" + Math.min(c.floor, nA - 1) : "lot", xyz = (p) => [p[0], p[2], p[1]];
6347
6418
  for (const tr of H.visibleRuns) {
6348
6419
  const pts = tr.points.map(xyz), d = tr.diameter || 0.025;
6349
6420
  if (tr.exposed === "wall") {
6350
- const pt = H.points.find((p) => p.run === tr.id), com = shared.ctx.roomById[tr.to], g2 = groupOf(com || pt && { floor: pt.floor });
6421
+ const pt = H.points.find((p) => p.run === tr.id), com = tr.to != null ? shared.ctx.roomById[tr.to] : void 0, g2 = groupOf(com || pt && { floor: pt.floor });
6351
6422
  part("wall_pipe", [0, 0, 0], () => {
6352
6423
  for (let i = 0; i + 1 < pts.length; i++) pipe(pts[i], pts[i + 1], d, PIPE_COLOR);
6353
6424
  for (const p of pts) cylBase("plain", p[0], p[1] - d, p[2], d * 0.7, d * 2, PIPE_COLOR);
@@ -6369,7 +6440,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6369
6440
  cursor.pc = null;
6370
6441
  }
6371
6442
  }
6372
- Object.assign(K, { createWater, PIPE_COLOR, pipe, _v3, waterPipes });
6443
+ const defined = { createWater, PIPE_COLOR, pipe, _v3, waterPipes };
6444
+ Object.assign(K, defined);
6373
6445
  }
6374
6446
 
6375
6447
  // src/utilities/electrical.ts
@@ -6377,10 +6449,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6377
6449
  const { _Y, _q, _v3, bx, cursor, cylBase, pieceRecord, put } = K;
6378
6450
  const sh = (...a) => K.sh(...a);
6379
6451
  function electricalStructure() {
6380
- const E = shared.ctx.r.utilities.electrical;
6452
+ const R = shared.ctx.r, E = R.utilities?.electrical;
6381
6453
  shared.ctx.electricalInfo = null;
6382
6454
  if (!E) return;
6383
- const R = shared.ctx.r, nA = R.floors.length, lotGroup = R.lot ? "lot" : "f0", concreteColor = 11973547, iron = 4869200, wireRun = 1842206, info = { pole: null, meter: null, panel: null, conduits: [], outlets: [], switches: [], circuits: E.circuits || [], exposed: !!E.exposed };
6455
+ const nA = R.floors.length, lotGroup = R.lot ? "lot" : "f0", concreteColor = 11973547, iron = 4869200, wireRun = 1842206, info = { pole: null, meter: null, panel: null, conduits: [], outlets: [], switches: [], circuits: E.circuits || [], exposed: !!E.exposed };
6384
6456
  const en3 = E.serviceEntrance, KV = shared.ctx.iv ? shared.ctx.iv.plane : null;
6385
6457
  const wireL = (a, b, r_ = 8e-3) => {
6386
6458
  const L = Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
@@ -6485,7 +6557,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6485
6557
  _q.setFromUnitVectors(_Y, _v3.set(dx / L, dy / L, dz / L));
6486
6558
  put("plain", "cyl", (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2, _q, diameter, L, diameter, color2);
6487
6559
  }
6488
- Object.assign(K, { electricalStructure, pipe2 });
6560
+ const defined = { electricalStructure, pipe2 };
6561
+ Object.assign(K, defined);
6489
6562
  }
6490
6563
 
6491
6564
  // src/house/baseboard.ts
@@ -6523,7 +6596,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6523
6596
  strip(W, y0, y0 + 0.045, 0, W, "sidewalk", cal);
6524
6597
  }
6525
6598
  }
6526
- Object.assign(K, { baseboardAndSidewalk });
6599
+ const defined = { baseboardAndSidewalk };
6600
+ Object.assign(K, defined);
6527
6601
  }
6528
6602
 
6529
6603
  // src/utilities/solar.ts
@@ -6538,6 +6612,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6538
6612
  if (u >= a - 0.05 && u <= c + 0.05 && v >= b - 0.05 && v <= d + 0.05) y = Math.max(y == null ? -1e9 : y, rr.yb);
6539
6613
  continue;
6540
6614
  }
6615
+ if (!rr.exterior || rr.tp == null || rr.rm == null) continue;
6541
6616
  const [x0, z0, x1, z1] = rr.exterior;
6542
6617
  if (u < x0 || u > x1 || v < z0 || v > z1) continue;
6543
6618
  const dz = Math.min(v - z0, z1 - v), dx = Math.min(u - x0, x1 - u), dd = rr.gable ? rr.alongX ? dz : dx : Math.min(dx, dz), h = rr.yb + rr.tp * Math.min(dd, rr.rm);
@@ -6546,7 +6621,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6546
6621
  return y;
6547
6622
  }
6548
6623
  function solar() {
6549
- const R = shared.ctx.r, S = R.utilities.solar;
6624
+ const R = shared.ctx.r, S = R.utilities?.solar;
6550
6625
  shared.ctx.solarInfo = null;
6551
6626
  if (!S || !S.panels || !S.panels.length) return;
6552
6627
  cursor.group = "roof";
@@ -6589,13 +6664,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6589
6664
  bx("plain", iv.u - W * 0.6, y0 + 0.05, iv.v + fa0, iv.u + W * 0.6, y0 + 0.17, iv.v + fa1, 2106924);
6590
6665
  bx("emissive", iv.u - 0.03, y0 - 0.12, iv.v + fa0, iv.u + 0.03, y0 - 0.09, iv.v + fa1, 6479994);
6591
6666
  }
6592
- const top = Math.max(...(shared.ctx.roofRects || []).filter((t2) => t2.yb != null).map((t2) => t2.yb), Y0(fa) + 2.8);
6667
+ const top = Math.max(...(shared.ctx.roofRects || []).flatMap((t2) => t2.yb != null ? [t2.yb] : []), Y0(fa) + 2.8);
6593
6668
  cylBase("plain", iv.u, y0 + h / 2, iv.v, 0.016, Math.max(0.2, top - 0.2 - (y0 + h / 2)), 15262936);
6594
6669
  info.inverter = { id: iv.id, pos: [iv.u, y0, iv.v], side: iv.side, link: iv.link };
6595
6670
  }
6596
6671
  shared.ctx.solarInfo = info;
6597
6672
  }
6598
- Object.assign(K, { roofHeightAt, solar });
6673
+ const defined = { roofHeightAt, solar };
6674
+ Object.assign(K, defined);
6599
6675
  }
6600
6676
 
6601
6677
  // src/house/outbuildings.ts
@@ -6610,7 +6686,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6610
6686
  counts.set(w.floor, i + 1);
6611
6687
  return w.id ? w : Object.assign({}, w, { id: `wall_${w.floor}_${i}` });
6612
6688
  }) });
6613
- const E = (r.outbuildings || []).filter((e) => e && e.walls && e.walls.length && e.interior && e.interior.length);
6689
+ const E = (r.outbuildings || []).filter((e) => !!(e && e.walls && e.walls.length && e.interior && e.interior.length));
6614
6690
  if (!E.length) return r;
6615
6691
  const rooms = r.rooms.slice(), walls = r.walls.slice(), doors = r.doors.slice(), windows = r.windows.slice(), items = r.items.filter((m) => m.type !== "outbuilding");
6616
6692
  for (const e of E) {
@@ -6624,7 +6700,22 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6624
6700
  const alongU = p.axis === "u", below = p.pos < (alongU ? cz : cx);
6625
6701
  doors.push({ id: p.id, floor: 0, u: p.u, v: p.v, axis: p.axis, pos: p.pos, at: p.at, width: p.width, a: below ? "outside" : e.id, b: below ? e.id : "outside", opensTo: e.id, exterior: true, side: p.side, leaves: 1, model: "single", hinge: "start", zones: [], blocked: false, outbuilding: e.id });
6626
6702
  }
6627
- for (const j of e.windows || []) windows.push({ id: j.id, floor: 0, u: j.u, v: j.v, axis: j.axis, pos: j.pos, at: j.at, width: j.width, y0: j.y0, y1: j.y1, room: e.id, side: j.side, outbuilding: e.id });
6703
+ for (const j of e.windows || []) windows.push({
6704
+ id: j.id,
6705
+ floor: 0,
6706
+ u: j.u,
6707
+ v: j.v,
6708
+ axis: j.axis,
6709
+ pos: j.pos,
6710
+ at: j.at,
6711
+ width: j.width,
6712
+ y0: j.y0 ?? 1,
6713
+ y1: j.y1 ?? 2,
6714
+ /* the structure always gives a window its sill and head (1.0, 2.0) */
6715
+ room: e.id,
6716
+ side: j.side,
6717
+ outbuilding: e.id
6718
+ });
6628
6719
  (e.items || []).forEach((m, i) => items.push({ id: e.id + "." + m.type + i, type: m.type, category: m.category, x: m.u, z: m.v, ry: m.ry || 0, w: m.w, d: m.d, h: m.h, y: 0.04, frontU: m.frontU, frontV: m.frontV, room: e.id, floor: 0, outdoor: false, aabb: m.aabb, color: "wood" }));
6629
6720
  items.push({ id: e.id + ".ceiling_light", type: "ceiling_light", category: "ceiling_light", x: cx, z: cz, ry: 0, w: 0.35, d: 0.35, h: 0.1, y: pe - 0.1, room: e.id, floor: 0, outdoor: false, assembly: "ceiling", color: "metal", decor: true });
6630
6721
  }
@@ -6645,7 +6736,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6645
6736
  }
6646
6737
  }
6647
6738
  }
6648
- Object.assign(K, { OUTBUILDING_USE, applyOutbuildings, outbuildings });
6739
+ const defined = { OUTBUILDING_USE, applyOutbuildings, outbuildings };
6740
+ Object.assign(K, defined);
6649
6741
  }
6650
6742
 
6651
6743
  // src/furniture/api.ts
@@ -6710,7 +6802,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6710
6802
  return { b: (mat, x, y, z, w, h, d, color2, ry, rx, rz) => A.box(M, mat, x, y0 + y, z, w, h, d, color2, ry || 0, rx || 0, rz || 0), c: (mat, x, y, z, r, h, color2, rx, rz, seg) => A.cylinder(M, mat, x, y0 + y, z, r, h, color2, rx || 0, rz || 0, seg), rnd: rngOf(M), wood: paletteColor(M, "wood", 8016948), met: paletteColor(M, "metal", 10133154) };
6711
6803
  }
6712
6804
  const PE = Math.PI / 2;
6713
- Object.assign(K, { MATERIAL_MAP: MATERIAL_MAP2, mm, LIGHTS, makeApi, sh, paletteColor, rngOf, kk, PE });
6805
+ const defined = { MATERIAL_MAP: MATERIAL_MAP2, mm, LIGHTS, makeApi, sh, paletteColor, rngOf, kk, PE };
6806
+ Object.assign(K, defined);
6714
6807
  }
6715
6808
 
6716
6809
  // src/furniture/builders.ts
@@ -6838,7 +6931,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
6838
6931
  for (let s = 0; s < np; s++) lb("fabric", np === 1 ? 0 : (s ? 1 : -1) * w * 0.23, 0.5, -d / 2 + 0.3, w * (np === 1 ? 0.6 : 0.4), 0.12, 0.34, 15789798, (s ? 1 : -1) * 0.08);
6839
6932
  },
6840
6933
  wardrobe(M, A) {
6841
- const { b: lb } = kk(M, A), w = M.w, d = M.d, h = M.h, wood = M.color != null && false ? M.color : paletteColor(M, "wood", 5980208), np = Math.max(2, Math.round(w / 0.7));
6934
+ const { b: lb } = kk(M, A), w = M.w, d = M.d, h = M.h, wood = paletteColor(M, "wood", 5980208), np = Math.max(2, Math.round(w / 0.7));
6842
6935
  lb("wood", 0, 0.06, 0, w, h - 0.06, d, wood);
6843
6936
  lb("wood", 0, h, 0, w + 0.04, 0.04, d + 0.04, sh(wood, 0.8));
6844
6937
  lb("wood", 0, 0, 0, w - 0.04, 0.06, d - 0.04, sh(wood, 0.4));
@@ -7230,7 +7323,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
7230
7323
  lb("metal", 0, h - 0.04, d / 2, w, 0.03, 0.03, 3815994);
7231
7324
  }
7232
7325
  };
7233
- Object.assign(K, { FURNITURE });
7326
+ const defined = { FURNITURE };
7327
+ Object.assign(K, defined);
7234
7328
  }
7235
7329
 
7236
7330
  // src/furniture/type-table.ts
@@ -7240,7 +7334,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
7240
7334
  function typeTable(props) {
7241
7335
  const B = props.builders, T2 = {};
7242
7336
  const mv = (type, id) => {
7243
- if (B[id || type]) T2[type] = { f: B[id || type], source: "props3d" };
7337
+ const f = B[id || type];
7338
+ if (f) T2[type] = { f, source: "props3d" };
7244
7339
  };
7245
7340
  const mine = (type, f, source = "game") => {
7246
7341
  T2[type] = { f, source };
@@ -7379,7 +7474,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
7379
7474
  extraTypes(T2, props);
7380
7475
  return T2;
7381
7476
  }
7382
- Object.assign(K, { typeTable });
7477
+ const defined = { typeTable };
7478
+ Object.assign(K, defined);
7383
7479
  }
7384
7480
 
7385
7481
  // src/furniture/taps.ts
@@ -7443,7 +7539,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
7443
7539
  }, { id: id + "_a", target: id, hidden: true, fluid: "water" });
7444
7540
  return id;
7445
7541
  }
7446
- Object.assign(K, { counterTap, wallTap });
7542
+ const defined = { counterTap, wallTap };
7543
+ Object.assign(K, defined);
7447
7544
  }
7448
7545
 
7449
7546
  // src/furniture/fixtures.ts
@@ -7556,7 +7653,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
7556
7653
  const a = rnd() * 6.283, u = Math.sqrt(rnd()), ph = (rnd() - 0.2) * 1.2, dx = Math.cos(a) * u * R * 0.75, dz = Math.sin(a) * u * R * 0.75, dy = (o.flatten ? 0.35 : 0.55) * R * (Math.sin(ph) * 0.5 + 0.5) * 1.5 - R * 0.15;
7557
7654
  const r = R * (0.34 + rnd() * 0.22) * (1 - u * 0.25), alt = r * 2 * (o.flatten ? 0.75 : 0.95), f = 0.72 + Math.min(1, (dy + R * 0.2) / (R * 1.2)) * 0.32 + rnd() * 0.12;
7558
7655
  K2.e("plant", cx + dx, cy + dy + r * 0.5, cz + dz, r, alt, sh(green2, f));
7559
- if (o.flower && rnd() < o.flower) {
7656
+ if (o.flower && o.flowers && rnd() < o.flower) {
7560
7657
  const fa = rnd() * 6.283;
7561
7658
  K2.e("plain", cx + dx + Math.cos(fa) * r * 0.78, cy + dy + r * 0.5 + rnd() * r * 0.5, cz + dz + Math.sin(fa) * r * 0.78, 0.028 + rnd() * 0.012, 0.05, o.flowers[rnd() * o.flowers.length | 0]);
7562
7659
  }
@@ -7669,7 +7766,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
7669
7766
  else blobs(K2, x, bh - 0.05, z, 0.24 + rnd() * 0.08, 6, green2, rnd, { flatten: true, flower: tp === "flower" ? 0.9 : 0.25, flowers: FLOWERS.slice(i % 3, i % 3 + 3) });
7670
7767
  }
7671
7768
  }
7672
- Object.assign(K, { GREENS: GREENS2, FLOWERS, blobs, potModel, arcLeaf, tuft, palm_tree, treeModel, shrubModel, potPlant, tablePot, planterModel });
7769
+ const defined = { GREENS: GREENS2, FLOWERS, blobs, potModel, arcLeaf, tuft, palm_tree, treeModel, shrubModel, potPlant, tablePot, planterModel };
7770
+ Object.assign(K, defined);
7673
7771
  }
7674
7772
 
7675
7773
  // src/furniture/yard.ts
@@ -7825,7 +7923,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
7825
7923
  };
7826
7924
  FURNITURE.mailbox = function(M, A) {
7827
7925
  const K2 = kit2(M, A, 0), w = M.w || 0.3, d = M.d || 0.22, h = M.h || 0.3, y = M.y != null && M.y > 0 ? M.y : 1, structure = STYLE(), pc = structure === "high" ? 2763824 : structure === "mid" ? 13676640 : 13126202, rnd = rngString(SEED() + "|" + seedKey(M.seed) + "|correio");
7828
- if (M.pole !== false && !(M.y > 0)) {
7926
+ if (M.pole !== false && !(M.y != null && M.y > 0)) {
7829
7927
  K2.b("plain", 0, 0, -d / 2 - 0.1, 0.12, y, 0.12, 12104874);
7830
7928
  }
7831
7929
  K2.b("metal", 0, y, 0, w, h * 0.78, d, pc);
@@ -7845,7 +7943,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
7845
7943
  );
7846
7944
  K2.b("plain", 0, y + h * 0.62, d / 2 + 4e-3, 0.08, 0.05, 4e-3, 15921386);
7847
7945
  };
7848
- Object.assign(K, { CLOTHES_COLORS, strip, garment });
7946
+ const defined = { CLOTHES_COLORS, strip, garment };
7947
+ Object.assign(K, defined);
7849
7948
  }
7850
7949
 
7851
7950
  // src/furniture/extra-types.ts
@@ -7905,7 +8004,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
7905
8004
  tuft(K2, 0, 0, 0, Math.max(0.2, (M.w || 0.4) / 2), 16, 5212738, rnd);
7906
8005
  });
7907
8006
  }
7908
- Object.assign(K, { extraTypes });
8007
+ const defined = { extraTypes };
8008
+ Object.assign(K, defined);
7909
8009
  }
7910
8010
 
7911
8011
  // src/furniture/place-items.ts
@@ -7927,8 +8027,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
7927
8027
  if (m.type === "stairs") continue;
7928
8028
  const exterior = m.outdoor || m.floor < 0, f = exterior ? -1 : Math.min(m.floor, R.floors.length - 1);
7929
8029
  cursor.group = exterior ? "lot" : "f" + f;
7930
- const com = shared.ctx.roomById[m.room], base = exterior ? 0 : Y0(f);
7931
- const M = { x: m.x, z: m.z, ry: m.ry || 0, w: m.w, d: m.d, h: m.h, y: m.y || 0, base, floor: exterior ? -1 : f, palette: shared.ctx.colors, color: m.category === "ground_cover" ? void 0 : colorOf(m.color) != null ? colorOf(m.color) : void 0, seed: m.id, room: m.room, typeWith: com ? com.type : null, ceiling: com ? com.ceiling : 2.9, on: shared.ctx.night, light: shared.ctx.night, lit: shared.ctx.night, open: !!m.doorOpen, overhead: m.overhead, assembly: m.assembly, hose: m.hose };
8030
+ const com = m.room != null ? shared.ctx.roomById[m.room] : void 0, base = exterior ? 0 : Y0(f);
8031
+ const M = { x: m.x, z: m.z, ry: m.ry || 0, w: m.w, d: m.d, h: m.h, y: m.y || 0, base, floor: exterior ? -1 : f, palette: shared.ctx.colors, color: m.category === "ground_cover" ? void 0 : colorOf(m.color) ?? void 0, seed: m.id, room: m.room, typeWith: com ? com.type : null, ceiling: com ? com.ceiling : 2.9, on: shared.ctx.night, light: shared.ctx.night, lit: shared.ctx.night, open: !!m.doorOpen, overhead: m.overhead, assembly: m.assembly, hose: m.hose };
7932
8032
  if (m.category === "ground_cover" && m.polygon) {
7933
8033
  const xs = m.polygon.map((p) => p[0]), zs = m.polygon.map((p) => p[1]);
7934
8034
  M.x = (Math.min(...xs) + Math.max(...xs)) / 2;
@@ -8005,7 +8105,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8005
8105
  boxC("plain", m.x, M.base + (m.y || 0) + h / 2, m.z, m.w, h, m.d, color2, 0, m.ry || 0, 0);
8006
8106
  shared.ctx.labels.push({ pos: new THREE.Vector3(m.x, M.base + (m.y || 0) + h + 0.15, m.z), text: m.type, group, type: "no_model" });
8007
8107
  }
8008
- Object.assign(K, { houseItems, waterTankOfHouse, hashColor, labeledBox });
8108
+ const defined = { houseItems, waterTankOfHouse, hashColor, labeledBox };
8109
+ Object.assign(K, defined);
8009
8110
  }
8010
8111
 
8011
8112
  // src/vegetation/bridge.ts
@@ -8040,7 +8141,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8040
8141
  const ids = VEG_MAP[m.type], can = VEG_PLANTER[m.type];
8041
8142
  if (!ids && !can) return false;
8042
8143
  const rnd = rngString(SEED() + "|" + seedKey(m.id) + "|veg"), pick2 = (l) => l[Math.min(l.length - 1, rnd() * l.length | 0)], ok = (id) => {
8043
- if (V.ok.has(id)) return V.ok.get(id);
8144
+ if (V.ok.has(id)) return V.ok.get(id) === true;
8044
8145
  let r = true;
8045
8146
  try {
8046
8147
  V.S.toSpec(id);
@@ -8086,7 +8187,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8086
8187
  obj.position.y = G.y;
8087
8188
  obj.name = "vegetation";
8088
8189
  obj.traverse((o) => {
8089
- if (o.isMesh) {
8190
+ if (isMesh(o)) {
8090
8191
  o.castShadow = true;
8091
8192
  o.receiveShadow = true;
8092
8193
  o.name = "veg/" + o.name;
@@ -8101,7 +8202,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8101
8202
  }
8102
8203
  shared.ctx.vegInfo = { plants: pl, triangles: tri, colliders: col, lodCounts: lod, materials: mats };
8103
8204
  }
8104
- Object.assign(K, { VEG_POT, VEG_CACTUS, VEG_MAP, VEG_PLANTER, vegItem, assembleVegetation });
8205
+ const defined = { VEG_POT, VEG_CACTUS, VEG_MAP, VEG_PLANTER, vegItem, assembleVegetation };
8206
+ Object.assign(K, defined);
8105
8207
  }
8106
8208
 
8107
8209
  // src/interaction/state.ts
@@ -8169,12 +8271,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8169
8271
  shared.inter.msg = { text, until: performance.now() + MESSAGE_MS };
8170
8272
  if (cfg.onMessage) cfg.onMessage(text);
8171
8273
  };
8172
- function definePiece(name, def) {
8274
+ const I = () => shared.inter;
8275
+ function definePiece(name, definition) {
8276
+ const def = definition;
8173
8277
  def.name = name;
8174
8278
  def.meshes = [];
8175
8279
  def.t = def.target = shared.partState.has(name) ? shared.partState.get(name) : def.t0 || 0;
8176
- shared.inter.defs.set(name, def);
8177
- shared.inter.pieces.push(def);
8280
+ I().defs.set(name, def);
8281
+ I().pieces.push(def);
8178
8282
  return def;
8179
8283
  }
8180
8284
  const localOf = (M, lx, lz) => {
@@ -8186,17 +8290,18 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8186
8290
  return true;
8187
8291
  }
8188
8292
  function assembleInteractive(gs) {
8189
- for (const [name, def] of shared.inter.defs) {
8293
+ const inter = I();
8294
+ for (const [name, def] of inter.defs) {
8190
8295
  const g = gs[name];
8191
8296
  if (!g) continue;
8192
8297
  delete gs[name];
8193
8298
  const outer = new THREE.Group();
8194
- outer.position.set(...def.pivot);
8299
+ outer.position.fromArray(def.pivot);
8195
8300
  outer.rotation.y = def.ry || 0;
8196
8301
  outer.updateMatrix();
8197
- const inv = new THREE.Matrix4().compose(new THREE.Vector3(...def.pivot), new THREE.Quaternion().setFromAxisAngle(_EY, def.ry || 0), _UM3).invert();
8302
+ const inv = new THREE.Matrix4().compose(new THREE.Vector3().fromArray(def.pivot), new THREE.Quaternion().setFromAxisAngle(_EY, def.ry || 0), _UM3).invert();
8198
8303
  g.traverse((o) => {
8199
- if (o.isMesh) {
8304
+ if (isMesh(o)) {
8200
8305
  o.geometry.applyMatrix4(inv);
8201
8306
  o.userData.piece = def;
8202
8307
  def.meshes.push(o);
@@ -8208,13 +8313,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8208
8313
  const parent = def.leaf ? def.leaf.gs[def.k] : gs[def.parent] || (gs[def.parent] = new THREE.Group());
8209
8314
  if (parent) parent.add(outer);
8210
8315
  if (def.roomId) {
8211
- if (!shared.inter.lights.has(def.roomId)) shared.inter.lights.set(def.roomId, []);
8212
- shared.inter.lights.get(def.roomId).push(def);
8316
+ let lamps = inter.lights.get(def.roomId);
8317
+ if (!lamps) inter.lights.set(def.roomId, lamps = []);
8318
+ lamps.push(def);
8213
8319
  }
8214
8320
  applyPiece(def);
8215
8321
  }
8216
- for (const roomId of shared.inter.litRooms) applyLight(roomId);
8217
- shared.inter.defs.forEach((d) => {
8322
+ for (const roomId of inter.litRooms) applyLight(roomId);
8323
+ inter.defs.forEach((d) => {
8218
8324
  if (d.col) d.col.off = d.t > 0.5;
8219
8325
  });
8220
8326
  }
@@ -8222,6 +8328,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8222
8328
  const n = p.inner;
8223
8329
  if (!n) return;
8224
8330
  switch (p.kind) {
8331
+ /* each kind always sets its dimensions (sgn, angle, travel, k, axis) */
8225
8332
  case "swing":
8226
8333
  n.rotation.y = p.sgn * p.t * p.angle;
8227
8334
  break;
@@ -8254,8 +8361,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8254
8361
  }
8255
8362
  const DURATION = { swing: 0.55, drawer: 0.4, curtain: 0.9, gate_swing: 0.9, gate_tilt: 1.4, gate_slide: 1.6, lightSwitch: 0.12, part: 0.4 };
8256
8363
  function animateInteractive(dt) {
8257
- if (!shared.inter.anim.size) return;
8258
- for (const p of shared.inter.anim) {
8364
+ const inter = I();
8365
+ if (!inter.anim.size) return;
8366
+ for (const p of inter.anim) {
8259
8367
  const step = dt / (DURATION[p.kind] || 0.5), d = p.target - p.t;
8260
8368
  p.t = Math.abs(d) <= step ? p.target : p.t + Math.sign(d) * step;
8261
8369
  applyPiece(p);
@@ -8263,7 +8371,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8263
8371
  p.col.off = p.target > 0.5;
8264
8372
  colliderChanged(p.col);
8265
8373
  }
8266
- if (p.t === p.target) shared.inter.anim.delete(p);
8374
+ if (p.t === p.target) inter.anim.delete(p);
8267
8375
  }
8268
8376
  invalidateShadow();
8269
8377
  }
@@ -8274,7 +8382,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8274
8382
  p.col.off = p.target > 0.5;
8275
8383
  colliderChanged(p.col);
8276
8384
  }
8277
- shared.inter.anim.add(p);
8385
+ I().anim.add(p);
8278
8386
  }
8279
8387
  const lightBase = (roomId) => roomId == null ? true : shared.partState.has("light:" + roomId) ? !!shared.partState.get("light:" + roomId) : !!shared.ctx.night;
8280
8388
  const lightOn = (roomId) => {
@@ -8282,20 +8390,21 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8282
8390
  return S ? S.ef : lightBase(roomId);
8283
8391
  };
8284
8392
  function applyLight(roomId) {
8285
- const on = lightOn(roomId);
8286
- for (const d of shared.inter.lights.get(roomId) || []) for (const m of d.meshes) if (m.name.endsWith("/emissive")) m.material = on ? shared.mats.emissive : shared.mats.off;
8287
- const sw = shared.inter.defs.get("ix:int:" + roomId);
8393
+ const on = lightOn(roomId), inter = I(), mats = shared.mats;
8394
+ for (const d of inter.lights.get(roomId) || []) for (const m of d.meshes) if (m.name.endsWith("/emissive")) m.material = on ? mats.emissive : mats.off;
8395
+ const sw = inter.defs.get("ix:int:" + roomId);
8288
8396
  if (sw) {
8289
8397
  sw.target = on ? 1 : 0;
8290
- if (sw.t !== sw.target) shared.inter.anim.add(sw);
8398
+ if (sw.t !== sw.target) inter.anim.add(sw);
8291
8399
  }
8292
8400
  invalidate();
8293
8401
  }
8294
8402
  function toggleLight(roomId) {
8295
8403
  const S = shared.ctx.iv && shared.ctx.iv.roomStates.get(roomId);
8296
8404
  if (S) {
8297
- ivRoomLight(shared.ctx.iv, roomId, !S.ef);
8298
- const ef = ivRoomEffective(shared.ctx.iv, S);
8405
+ const IV = shared.ctx.iv;
8406
+ ivRoomLight(IV, roomId, !S.ef);
8407
+ const ef = ivRoomEffective(IV, S);
8299
8408
  if (ef !== S.ef) {
8300
8409
  S.ef = ef;
8301
8410
  applyLight(roomId);
@@ -8307,11 +8416,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8307
8416
  applyLight(roomId);
8308
8417
  if (cfg.onLight) cfg.onLight(roomId, lightOn(roomId));
8309
8418
  }
8310
- Object.assign(K, { newInteractiveState, MESSAGE_MS, createInteractiveMaterials, _EY, _UM3, hudMessage, definePiece, localOf, visibleChain, assembleInteractive, applyPiece, DURATION, animateInteractive, togglePiece, lightBase, lightOn, applyLight, toggleLight });
8419
+ const defined = { newInteractiveState, MESSAGE_MS, createInteractiveMaterials, _EY, _UM3, hudMessage, definePiece, localOf, visibleChain, assembleInteractive, applyPiece, DURATION, animateInteractive, togglePiece, lightBase, lightOn, applyLight, toggleLight };
8420
+ Object.assign(K, defined);
8311
8421
  }
8312
8422
 
8313
8423
  // src/interaction/collision.ts
8314
8424
  function installInteractionCollision(K, shared) {
8425
+ const inter = () => shared.inter;
8315
8426
  const NO_COLLIDE = /(^|_)(rug|floor|concrete|dirt|lawn|deck|ceiling_light|pendant|chandelier|spot|picture|curtain|blinds|wall_shelving|plank_shelf|wall_ac|ac_condenser|pool|soaking_tub|pergola|stairs|mirror)/;
8316
8427
  function registerCollision(m, M) {
8317
8428
  const h = m.h || 0, y = M.y || 0;
@@ -8321,7 +8432,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8321
8432
  w = Math.min(w, 0.5);
8322
8433
  d = Math.min(d, 0.5);
8323
8434
  }
8324
- shared.inter.objs.push({ f: M.floor, cx: m.x, cz: m.z, c: Math.cos(M.ry), s: Math.sin(M.ry), hw: w / 2, hd: d / 2, type: m.type });
8435
+ inter().objs.push({ f: M.floor, cx: m.x, cz: m.z, c: Math.cos(M.ry), s: Math.sin(M.ry), hw: w / 2, hd: d / 2, type: m.type });
8325
8436
  }
8326
8437
  function objectDistance(o, x, z) {
8327
8438
  const dx = x - o.cx, dz = z - o.cz, lx = dx * o.c - dz * o.s, lz = dx * o.s + dz * o.c, ex = Math.abs(lx) - o.hw, ez = Math.abs(lz) - o.hd;
@@ -8329,7 +8440,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8329
8440
  }
8330
8441
  function collideObject(x, z, fx, fz, floor) {
8331
8442
  const R = 0.2;
8332
- for (const o of shared.inter.objs) {
8443
+ for (const o of inter().objs) {
8333
8444
  if (o.f !== -1 ? o.f !== floor : floor !== 0) continue;
8334
8445
  const d1 = objectDistance(o, x, z);
8335
8446
  if (d1 < R && d1 < objectDistance(o, fx, fz) - 1e-6) return true;
@@ -8349,7 +8460,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8349
8460
  const de = opt.from || [x + 1e4, z + 1e4];
8350
8461
  return collideObject(x, z, de[0], de[1], floor);
8351
8462
  }
8352
- Object.assign(K, { NO_COLLIDE, registerCollision, objectDistance, collideObject, collideAt });
8463
+ const defined = { NO_COLLIDE, registerCollision, objectDistance, collideObject, collideAt };
8464
+ Object.assign(K, defined);
8353
8465
  }
8354
8466
 
8355
8467
  // src/interaction/items.ts
@@ -8358,6 +8470,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8358
8470
  const DOOR_ITEM = /^(tv_unit|tv_unit_small|tv_unit_large|sideboard|china_cabinet|filing_cabinet|pantry|laundry_cabinet|wardrobe|wardrobe_small|wardrobe_large|closet_wardrobe|kitchen_cabinet|kitchen_cabinet_large|kitchen_cabinet_small|fridge|fridge_large|display_fridge_medium|display_fridge)$/;
8359
8471
  const DRAWER_ITEM = /^(console_table|dresser|nightstand|vanity_table)$/;
8360
8472
  const LIGHT_TYPES = /* @__PURE__ */ new Set(["ceiling_light", "pendant", "chandelier", "track_spot", "hanging_plant"]);
8473
+ const I = () => shared.inter;
8361
8474
  function objectName(type, drawer) {
8362
8475
  return drawer ? "drawer" : /^wardrobe/.test(type) ? "wardrobe" : /fridge|refrig|freezer/.test(type) ? "fridge" : /pantry/.test(type) ? "pantry" : "cabinet";
8363
8476
  }
@@ -8386,8 +8499,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8386
8499
  cursor.group = parent;
8387
8500
  }
8388
8501
  for (let i = n0; i < LIGHTS.length; i++) LIGHTS[i].roomId = m.room;
8389
- if (!shared.inter.defs.has(name)) definePiece(name, { kind: "light", pivot: [0, 0, 0], ry: 0, parent, roomId: m.room });
8390
- shared.inter.litRooms.add(m.room);
8502
+ if (!I().defs.has(name)) definePiece(name, { kind: "light", pivot: [0, 0, 0], ry: 0, parent, roomId: m.room });
8503
+ I().litRooms.add(m.room);
8391
8504
  }
8392
8505
  function curtainItem(m, M, ent, api, parent) {
8393
8506
  M.open = false;
@@ -8415,12 +8528,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8415
8528
  for (const c of body) api[c[0]](M, ...c[1]);
8416
8529
  if (!parts.length) return;
8417
8530
  const [ax, az] = localOf(M, 0, 0.2);
8418
- shared.inter.items.push({ type: "curtain", id: m.id, floor: M.floor, anchor: [ax, M.base + (M.y || 0) + (m.h || 2) * 0.5, az], range: 2.4, angle: 1, pieces: parts, text: () => t(parts[0].target > 0.5 ? "prompt.close" : "prompt.open", { what: t("what.curtain") }), action: () => {
8419
- const al = parts[0].target > 0.5 ? 0 : 1;
8531
+ const first = parts[0];
8532
+ I().items.push({ type: "curtain", id: m.id, floor: M.floor, anchor: [ax, M.base + (M.y || 0) + (m.h || 2) * 0.5, az], range: 2.4, angle: 1, pieces: parts, text: () => t(first.target > 0.5 ? "prompt.close" : "prompt.open", { what: t("what.curtain") }), action: () => {
8533
+ const al = first.target > 0.5 ? 0 : 1;
8420
8534
  for (const p of parts) {
8421
8535
  p.target = al;
8422
8536
  shared.partState.set(p.name, al);
8423
- shared.inter.anim.add(p);
8537
+ I().anim.add(p);
8424
8538
  }
8425
8539
  } });
8426
8540
  }
@@ -8441,7 +8555,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8441
8555
  calls.forEach((c, i) => {
8442
8556
  if (owner.has(i)) return;
8443
8557
  const a = c[1];
8444
- let x0, x1, y0, y1, ok = false, grip = 0, wide = false;
8558
+ let x0 = 0, x1 = 0, y0 = 0, y1 = 0, ok = false, grip = 0, wide = false;
8445
8559
  if (c[0] === "box") {
8446
8560
  const [mat, x, y, z, w, h, d, , ry, rx, rz] = a;
8447
8561
  if (ry || rx || rz || d > 0.05 || z + d / 2 < front - 5e-3 || w > M.w * 1.01) return;
@@ -8473,8 +8587,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8473
8587
  return;
8474
8588
  }
8475
8589
  candidate.sort((p, q) => overlap(x0, x1, q.x0, q.x1) - overlap(x0, x1, p.x0, p.x1));
8476
- owner.set(i, candidate[0]);
8477
- if (grip) candidate[0].grip = grip;
8590
+ const best = candidate[0];
8591
+ owner.set(i, best);
8592
+ if (grip) best.grip = grip;
8478
8593
  });
8479
8594
  const name = objectName(m.type, drawer), parts = [];
8480
8595
  panels.forEach((p, k) => {
@@ -8490,8 +8605,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8490
8605
  p.def = def;
8491
8606
  parts.push(def);
8492
8607
  const [ax, az] = localOf(M, cx, front + 0.08);
8493
- shared.inter.items.push({ type: drawer ? "drawer" : "cabinet", id: m.id, floor: M.floor, anchor: [ax, M.base + (M.y || 0) + (p.y0 + p.y1) / 2, az], range: 1.6, angle: 0.4, pieces: [def], text: () => t(def.target > 0.5 ? "prompt.close" : "prompt.open", { what: t("what." + name) }), action: () => togglePiece(def) });
8494
- def.item = shared.inter.items[shared.inter.items.length - 1];
8608
+ I().items.push({ type: drawer ? "drawer" : "cabinet", id: m.id, floor: M.floor, anchor: [ax, M.base + (M.y || 0) + (p.y0 + p.y1) / 2, az], range: 1.6, angle: 0.4, pieces: [def], text: () => t(def.target > 0.5 ? "prompt.close" : "prompt.open", { what: t("what." + name) }), action: () => togglePiece(def) });
8609
+ def.item = I().items[I().items.length - 1];
8495
8610
  });
8496
8611
  calls.forEach((c, i) => {
8497
8612
  const p = owner.get(i);
@@ -8505,14 +8620,17 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8505
8620
  }
8506
8621
  cursor.group = parent;
8507
8622
  }
8508
- Object.assign(K, { DOOR_ITEM, DRAWER_ITEM, LIGHT_TYPES, objectName, recordApi, buildItem, lightItem, curtainItem, furnitureItem });
8623
+ const defined = { DOOR_ITEM, DRAWER_ITEM, LIGHT_TYPES, objectName, recordApi, buildItem, lightItem, curtainItem, furnitureItem };
8624
+ Object.assign(K, defined);
8509
8625
  }
8510
8626
 
8511
8627
  // src/interaction/fittings.ts
8512
8628
  function installInteractionFittings(K, shared) {
8513
8629
  const { t, EPS: EPS3, OPEN_AREA, Y0, applyPiece, bx, cursor, definePiece, gates, lightOn, roomAt, slideDirection, toggleLight, togglePiece } = K;
8630
+ const I = () => shared.inter;
8631
+ const house = () => shared.ctx.r;
8514
8632
  function gatesInteractive() {
8515
- const lt = shared.ctx.r.lot;
8633
+ const lt = house().lot;
8516
8634
  if (!lt) return;
8517
8635
  const cz0 = (lt.rect[1] + lt.rect[3]) / 2;
8518
8636
  const orig = K.getBx(), gs = lt.gates, opening = gs.map((g) => g.open), reg = gs.map((g) => {
@@ -8532,9 +8650,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8532
8650
  return;
8533
8651
  }
8534
8652
  }
8535
- return orig(mat, x0, y0, z0, x1, y1, z1, color2);
8653
+ orig(mat, x0, y0, z0, x1, y1, z1, color2);
8536
8654
  });
8537
- const n0 = shared.ctx.colliders.length;
8655
+ const colliders = shared.ctx.colliders, n0 = colliders.length;
8538
8656
  try {
8539
8657
  gs.forEach((g) => {
8540
8658
  g.open = false;
@@ -8546,7 +8664,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8546
8664
  g.open = opening[i];
8547
8665
  });
8548
8666
  }
8549
- const cols = shared.ctx.colliders.slice(n0), cz = (lt.rect[1] + lt.rect[3]) / 2, cu = (lt.rect[0] + lt.rect[2]) / 2;
8667
+ const cols = colliders.slice(n0), cz = (lt.rect[1] + lt.rect[3]) / 2, cu = (lt.rect[0] + lt.rect[2]) / 2;
8550
8668
  reg.forEach((r, i) => {
8551
8669
  const g = r.g;
8552
8670
  if (!isFinite(r.x0)) return;
@@ -8555,25 +8673,25 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8555
8673
  const p = ped ? definePiece(name, Object.assign(base, { kind: "gate_swing", pivot: [r.x0, 0, g.v], angle: -sd * 1.65 })) : tilt ? definePiece(name, Object.assign(base, { kind: "gate_tilting", pivot: [(r.x0 + r.x1) / 2, r.y1, g.v], angle: -sd * 1.45 })) : definePiece(name, Object.assign(base, { kind: "gate_sliding", pivot: [r.x0, 0, r.zm], travel: r.dx * g.width }));
8556
8674
  if (p.col) p.col.off = p.target > 0.5;
8557
8675
  const text = () => t(p.target > 0.5 ? "prompt.close" : "prompt.open", { what: t(ped ? "what.pedestrianGate" : "what.garageGate") });
8558
- shared.inter.items.push({ type: "gate", id: g.id, floor: -1, anchor: [g.u, 1, g.v + sd * 0.4], range: 2.8, angle: 0.9, pieces: [p], text, action: () => togglePiece(p), noWall: true });
8676
+ I().items.push({ type: "gate", id: g.id, floor: -1, anchor: [g.u, 1, g.v + sd * 0.4], range: 2.8, angle: 0.9, pieces: [p], text, action: () => togglePiece(p), noWall: true });
8559
8677
  });
8560
8678
  }
8561
8679
  function mailboxInteractive() {
8562
- for (const m of shared.ctx.r.items) {
8680
+ for (const m of house().items) {
8563
8681
  if (m.type !== "mailbox") continue;
8564
8682
  const g = shared.ctx.parts && shared.ctx.parts["mailbox_" + m.id];
8565
8683
  if (!g) continue;
8566
8684
  const name = "ix:correio:" + m.id, def = definePiece(name, { kind: "part", pivot: [0, 0, 0], ry: 0, parent: "lot" });
8567
8685
  def.inner = g;
8568
8686
  const fx = Math.sin(m.ry || 0), fz = Math.cos(m.ry || 0), ay = (m.y || 1) + (m.h || 0.3) * 0.4;
8569
- shared.inter.items.push({ type: "mailbox", id: m.id, floor: -1, anchor: [m.x + fx * 0.2, ay, m.z + fz * 0.2], range: 2.2, angle: 0.7, pieces: [def], text: () => t(def.target > 0.5 ? "prompt.close" : "prompt.open", { what: t("what.mailbox") }), action: () => togglePiece(def), noWall: true });
8687
+ I().items.push({ type: "mailbox", id: m.id, floor: -1, anchor: [m.x + fx * 0.2, ay, m.z + fz * 0.2], range: 2.2, angle: 0.7, pieces: [def], text: () => t(def.target > 0.5 ? "prompt.close" : "prompt.open", { what: t("what.mailbox") }), action: () => togglePiece(def), noWall: true });
8570
8688
  applyPiece(def);
8571
8689
  }
8572
8690
  }
8573
8691
  function placeSwitches() {
8574
- const R = shared.ctx.r, used = /* @__PURE__ */ new Set();
8692
+ const R = house(), used = /* @__PURE__ */ new Set();
8575
8693
  for (const c of R.rooms) {
8576
- if (c.type === "void" || OPEN_AREA(c) || !shared.inter.litRooms.has(c.id) || used.has(c.id) || shared.ctx.iv && shared.ctx.iv.switchRooms.has(c.id)) continue;
8694
+ if (c.type === "void" || OPEN_AREA(c) || !I().litRooms.has(c.id) || used.has(c.id) || shared.ctx.iv && shared.ctx.iv.switchRooms.has(c.id)) continue;
8577
8695
  const doors = R.doors.filter((p) => p.floor === c.floor && (p.a === c.id || p.b === c.id));
8578
8696
  doors.sort((p, q) => ((q.exterior ? 1 : 0) - (p.exterior ? 1 : 0)) * (c.type === "living" ? 1 : -1));
8579
8697
  for (const p of doors) if (putSwitch(c, p)) {
@@ -8583,11 +8701,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8583
8701
  }
8584
8702
  }
8585
8703
  function putSwitch(c, p) {
8586
- const R = shared.ctx.r, f = p.floor, alongU = p.axis === "u", L = p.pos, a = p.at - p.width / 2, b = p.at + p.width / 2;
8704
+ const R = house(), f = p.floor, alongU = p.axis === "u", L = p.pos, a = p.at - p.width / 2, b = p.at + p.width / 2;
8587
8705
  const wref = R.walls.find((w) => w.floor === f && w.axis === p.axis && Math.abs((alongU ? w.v0 : w.u0) - L) < EPS3), th = wref ? wref.thickness || 0.15 : 0.15;
8588
8706
  const inside2 = (sd2) => {
8589
8707
  const cc = roomAt(f, alongU ? p.at : L + sd2 * 0.4, alongU ? L + sd2 * 0.4 : p.at);
8590
- return cc && cc.id === c.id;
8708
+ return !!cc && cc.id === c.id;
8591
8709
  };
8592
8710
  const sd = inside2(1) ? 1 : inside2(-1) ? -1 : 0;
8593
8711
  if (!sd) return false;
@@ -8610,19 +8728,22 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8610
8728
  const piece2 = definePiece("ix:int:" + roomId, { kind: "light_switch", pivot: pv, ry: 0, parent: "f" + f, axis: alongU ? "x" : "z", sgn: alongU ? sd : -sd, t0: lightOn(roomId) ? 1 : 0 });
8611
8729
  piece2.t = piece2.target = lightOn(roomId) ? 1 : 0;
8612
8730
  const an = alongU ? [u, yc, face + sd * 0.12] : [face + sd * 0.12, yc, u];
8613
- shared.inter.items.push({ type: "light_switch", id: roomId, floor: f, anchor: an, range: 1.5, angle: 0.45, pieces: [piece2], text: () => t(lightOn(roomId) ? "prompt.lightOff" : "prompt.lightOn"), action: () => toggleLight(roomId) });
8731
+ I().items.push({ type: "light_switch", id: roomId, floor: f, anchor: an, range: 1.5, angle: 0.45, pieces: [piece2], text: () => t(lightOn(roomId) ? "prompt.lightOff" : "prompt.lightOn"), action: () => toggleLight(roomId) });
8614
8732
  return true;
8615
8733
  }
8616
8734
  return false;
8617
8735
  }
8618
- Object.assign(K, { gatesInteractive, mailboxInteractive, placeSwitches, putSwitch });
8736
+ const defined = { gatesInteractive, mailboxInteractive, placeSwitches, putSwitch };
8737
+ Object.assign(K, defined);
8619
8738
  }
8620
8739
 
8621
8740
  // src/interaction/doors.ts
8622
8741
  function installInteractionDoors(K, shared) {
8623
8742
  const { t, colliderChanged, invalidateShadow, applyPiece, hudMessage } = K;
8743
+ const leaves = () => shared.ctx.leaves;
8624
8744
  function linkDoorLeaves() {
8625
- for (const fo of shared.ctx.leaves) fo.handles = (fo.handleNames || []).map((n) => shared.inter.defs.get(n)).filter(Boolean);
8745
+ const I = shared.inter;
8746
+ for (const fo of leaves()) fo.handles = (fo.handleNames || []).map((n) => I.defs.get(n)).filter((d) => !!d);
8626
8747
  }
8627
8748
  function handleApply(fo) {
8628
8749
  for (const mc of fo.handles || []) {
@@ -8632,11 +8753,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8632
8753
  }
8633
8754
  function toggleDoor(fo) {
8634
8755
  if (fo.phase === "rattle") return;
8756
+ const col = fo.col;
8635
8757
  if (fo.phase === "handle" || fo.phase === "swing") {
8636
8758
  fo.open = !fo.open;
8637
8759
  shared.doorState.set(fo.id, fo.open);
8638
- fo.col.off = fo.open;
8639
- colliderChanged(fo.col);
8760
+ col.off = fo.open;
8761
+ colliderChanged(col);
8640
8762
  fo.anim = true;
8641
8763
  fo.phase = "swing";
8642
8764
  return;
@@ -8650,8 +8772,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8650
8772
  }
8651
8773
  fo.open = !fo.open;
8652
8774
  shared.doorState.set(fo.id, fo.open);
8653
- fo.col.off = fo.open;
8654
- colliderChanged(fo.col);
8775
+ col.off = fo.open;
8776
+ colliderChanged(col);
8655
8777
  fo.anim = true;
8656
8778
  shared.ctx.animateDoorsOn = true;
8657
8779
  if (fo.handles && fo.handles.length) {
@@ -8662,7 +8784,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8662
8784
  function animateDoors(dt) {
8663
8785
  if (!shared.ctx.animateDoorsOn) return;
8664
8786
  let active = false;
8665
- for (const fo of shared.ctx.leaves) {
8787
+ for (const fo of leaves()) {
8666
8788
  if (!fo.phase) continue;
8667
8789
  active = true;
8668
8790
  if (fo.phase === "handle") {
@@ -8682,7 +8804,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8682
8804
  handleApply(fo);
8683
8805
  if (fo.hT <= 0) fo.phase = null;
8684
8806
  } else if (fo.phase === "rattle") {
8685
- fo.jig -= dt;
8807
+ fo.jig = (fo.jig ?? 0) - dt;
8686
8808
  fo.hT = fo.jig > 0 ? 0.55 * Math.abs(Math.sin(fo.jig * 26)) : 0;
8687
8809
  handleApply(fo);
8688
8810
  if (fo.jig <= 0) {
@@ -8696,9 +8818,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8696
8818
  invalidateShadow();
8697
8819
  }
8698
8820
  function wallBlocks(ex, ez, ax, az, floor) {
8699
- const n = shared.ctx.wallColliders != null ? shared.ctx.wallColliders : 0;
8821
+ const n = shared.ctx.wallColliders != null ? shared.ctx.wallColliders : 0, colliders = shared.ctx.colliders;
8700
8822
  for (let i = 0; i < n; i++) {
8701
- const c = shared.ctx.colliders[i];
8823
+ const c = colliders[i];
8702
8824
  if (c.f !== floor && !(c.f === -1 && floor === 0)) continue;
8703
8825
  let t0 = 0, t1 = 1;
8704
8826
  const dx = ax - ex, dz = az - ez;
@@ -8728,7 +8850,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8728
8850
  g.updateMatrix();
8729
8851
  }
8730
8852
  }
8731
- Object.assign(K, { linkDoorLeaves, handleApply, toggleDoor, animateDoors, wallBlocks, doorText, applyLeaf });
8853
+ const defined = { linkDoorLeaves, handleApply, toggleDoor, animateDoors, wallBlocks, doorText, applyLeaf };
8854
+ Object.assign(K, defined);
8732
8855
  }
8733
8856
 
8734
8857
  // src/interaction/target.ts
@@ -8738,6 +8861,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8738
8861
  function targetOf(o, opt) {
8739
8862
  if (!o) return null;
8740
8863
  opt = opt || {};
8864
+ const I = shared.inter;
8741
8865
  const ex = o.x, ey = o.y, ez = o.z, floor = o.floor, cp = Math.cos(o.pitch || 0), vx = Math.sin(o.yaw) * cp, vy = Math.sin(o.pitch || 0), vz = Math.cos(o.yaw) * cp;
8742
8866
  let best = null;
8743
8867
  const tries = (score, text, action, target) => {
@@ -8751,16 +8875,16 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8751
8875
  if (angle > 1.35 && d > 0.9) continue;
8752
8876
  tries(angle * 1.6 + d * 0.5 + (angle < 0.25 ? 0 : 0.6), doorText(fo), () => toggleDoor(fo), fo);
8753
8877
  }
8754
- const vis = shared.inter.pieces.flatMap((p) => p.meshes).filter(visibleChain), hit = vis.length && opt.strike ? opt.strike(vis) : null;
8878
+ const vis = I.pieces.flatMap((p) => p.meshes).filter(visibleChain), hit = vis.length && opt.strike ? opt.strike(vis) : null;
8755
8879
  const kitA = shared.ctx.iv ? ivTarget(shared.ctx.iv, o, opt && opt.interactives) : null;
8756
8880
  const nearKit = kitA && hit && Math.hypot(kitA.target.pos[0] - ex, kitA.target.pos[1] - ey, kitA.target.pos[2] - ez) < hit.distance + 0.1;
8757
8881
  const pieceHit = hit && !nearKit && hit.object.userData.piece;
8758
- for (const it of shared.inter.items) {
8882
+ for (const it of I.items) {
8759
8883
  if (it.floor !== floor && !(it.floor === -1 && floor === 0)) continue;
8760
8884
  const [ax, ay, az] = it.anchor, dx = ax - ex, dy = ay - ey, dz = az - ez, d = Math.hypot(dx, dy, dz), dh = Math.hypot(dx, dz);
8761
8885
  if (dh > it.range + 0.4) continue;
8762
8886
  const angle = Math.acos(Math.max(-1, Math.min(1, (dx * vx + dy * vy + dz * vz) / (d || 1))));
8763
- const byRay = pieceHit && it.pieces.includes(pieceHit) && hit.distance <= it.range + 0.5;
8887
+ const byRay = !!hit && pieceHit && it.pieces.includes(pieceHit) && hit.distance <= it.range + 0.5;
8764
8888
  if (!byRay && !(dh <= it.range && angle <= it.angle)) continue;
8765
8889
  if (!it.noWall && wallBlocks(ex, ez, ax, az, it.floor < 0 ? 0 : it.floor)) continue;
8766
8890
  tries((byRay ? 0 : angle * 2) + d * 0.3 - (byRay ? 1.5 : 0), it.text(), it.action, it);
@@ -8768,7 +8892,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8768
8892
  if (kitA) tries(kitA.score - (nearKit ? 0.5 : 0), kitA.text, kitA.action, kitA.target);
8769
8893
  return best;
8770
8894
  }
8771
- Object.assign(K, { targetOf });
8895
+ const defined = { targetOf };
8896
+ Object.assign(K, defined);
8772
8897
  }
8773
8898
 
8774
8899
  // src/interactables/bridge.ts
@@ -8825,7 +8950,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8825
8950
  function ivBuild(h, water) {
8826
8951
  const ik = K.IVK, r = shared.ctx.r, A = ik.A, world0 = null;
8827
8952
  void world0;
8828
- const plane2 = A.plan(r, { seed: r.seed });
8953
+ const source = r;
8954
+ const plane2 = A.plan(source, { seed: r.seed });
8829
8955
  const IV = { k: ik, plane: plane2, world: null, water, entries: /* @__PURE__ */ new Map(), roots: [], replace: /* @__PURE__ */ new Set(), roomStates: /* @__PURE__ */ new Map(), lampRoom: /* @__PURE__ */ new Map(), anim: /* @__PURE__ */ new Map(), screens: /* @__PURE__ */ new Map(), efx: null, items: null, itemsDirty: true, itemsT: 0, dirty: true, list: null, listT: 0, t: 0, circuits: [], switchRooms: /* @__PURE__ */ new Set(), warnings: [], tBuild: 0 };
8830
8956
  h.IV = IV;
8831
8957
  const t0 = performance.now();
@@ -8844,9 +8970,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8844
8970
  const wants = (roomId) => lightBase(roomId);
8845
8971
  const entById = new Map(plane2.items.map((e) => [e.id, e]));
8846
8972
  const entByItem = new Map(plane2.items.map((e) => [e.item, e]));
8847
- IV.mats = { plain: shared.mats.plain, metal: shared.mats.metal, wood: shared.mats.wood, glass: shared.mats.glass, fabric: shared.mats.fabric, plant: shared.mats.plant, water: shared.mats.water, emissive: shared.mats.emissive, atlas_picture: shared.mats.picture, atlas_floor: shared.mats.floor };
8973
+ const mats = shared.mats;
8974
+ IV.mats = { plain: mats.plain, metal: shared.mats.metal, wood: shared.mats.wood, glass: shared.mats.glass, fabric: shared.mats.fabric, plant: shared.mats.plant, water: shared.mats.water, emissive: shared.mats.emissive, atlas_picture: shared.mats.picture, atlas_floor: shared.mats.floor };
8848
8975
  const ev = (e) => ivEvent(h, e);
8849
- const world = IV.world = A.createWorld(r, { water, seed: r.seed, onEvent: ev });
8976
+ const world = IV.world = A.createWorld(source, { water, seed: r.seed, onEvent: ev });
8850
8977
  const add0 = world.add;
8851
8978
  world.add = (id, spec, tr) => {
8852
8979
  const e = entById.get(id);
@@ -8863,7 +8990,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8863
8990
  }
8864
8991
  return add0(id, spec, tr);
8865
8992
  };
8866
- const added = A.add(world, plane2, { isBlocked: A.blockedOf(r), build: (type, item) => ivDraw(IV, entByItem.get(item), type, item) });
8993
+ const added = A.add(world, plane2, { isBlocked: A.blockedOf(source), build: (type, item) => ivDraw(IV, entByItem.get(item), type, item) });
8867
8994
  world.add = add0;
8868
8995
  IV.warnings = added.warnings;
8869
8996
  IV.added = added;
@@ -8910,14 +9037,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8910
9037
  }
8911
9038
  function ivDraw(IV, ent, type, item) {
8912
9039
  const ik = IV.k, loc = Object.assign({}, item, { x: 0, z: 0, ry: 0 });
9040
+ const ix = item.x, iz = item.z, iry = item.ry;
8913
9041
  const mesh2 = ik.gfx.createMeshApi({ quality: "game", materials: IV.mats, shadows: true, mergeParts: true, swayAmplitude: 0.03 });
8914
9042
  const spec = ik.A.household.build(type, loc, mesh2.api);
8915
9043
  const out = mesh2.finish(spec);
8916
9044
  for (const l of out.lights) l.removeFromParent();
8917
9045
  const group = ivGroup(ent), g0 = cursor.group, root = new THREE.Group();
8918
9046
  root.name = "iv:" + ent.id;
8919
- root.position.set(item.x, ent.floorY, item.z);
8920
- root.rotation.y = item.ry;
9047
+ root.position.set(ix, ent.floorY, iz);
9048
+ root.rotation.y = iry;
8921
9049
  root.userData.iv = ent.id;
8922
9050
  const screen = spec.devices && spec.devices.some((d) => d.kind === "screen");
8923
9051
  let body = null;
@@ -8926,7 +9054,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8926
9054
  if (type === "gas_bottle") {
8927
9055
  cursor.pc = pieceRecord("gas_cylinder:" + ent.id, "steel", null, { floor: ent.floor, mass: 11, form: "cyl", thickness: 3e-3, fill: 0.03, contains: { fluid: "gas", liters: 13, pressurized: true }, explodes: { energy: 12e4, radius: 5, atC: 300 }, tags: ["gas_bottle"] });
8928
9056
  for (const m of out.group.children) if (!m.name.startsWith("static:")) m.traverse((o) => {
8929
- if (o.isMesh) {
9057
+ if (isMesh(o)) {
8930
9058
  o.userData.destructionPart = cursor.pc.id;
8931
9059
  o.userData.destructionMaterial = "steel";
8932
9060
  }
@@ -8934,13 +9062,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8934
9062
  }
8935
9063
  try {
8936
9064
  for (const m of out.group.children.slice()) {
8937
- if (m.isMesh && m.name.startsWith("static:")) {
9065
+ if (isMesh(m) && m.name.startsWith("static:")) {
8938
9066
  if (screen && m.userData.material === "emissive") {
8939
9067
  body = m;
8940
9068
  root.add(m);
8941
9069
  continue;
8942
9070
  }
8943
- ivAccumulate(IV_MATERIAL[m.userData.material] || "plain", m.geometry, item.x, ent.floorY, item.z, item.ry, null);
9071
+ ivAccumulate(IV_MATERIAL[m.userData.material] || "plain", m.geometry, ix, ent.floorY, iz, iry, null);
8944
9072
  m.geometry.dispose();
8945
9073
  } else root.add(m);
8946
9074
  }
@@ -8950,7 +9078,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8950
9078
  }
8951
9079
  const base = new Set(Object.values(IV.mats));
8952
9080
  root.traverse((o) => {
8953
- if (!o.isMesh) return;
9081
+ if (!isMesh(o)) return;
8954
9082
  o.userData.iv = ent.id;
8955
9083
  if (o.castShadow) {
8956
9084
  if (!o.geometry.boundingSphere) o.geometry.computeBoundingSphere();
@@ -8961,7 +9089,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8961
9089
  roomLightMask(m);
8962
9090
  }
8963
9091
  });
8964
- const E = { id: ent.id, type, entry: ent, floor: ent.floor, group, root, parts: out.parts, spec, screen: body, pos: [item.x, ent.floorY, item.z], ry: item.ry, origin: ent.origin };
9092
+ const E = { id: ent.id, type, entry: ent, floor: ent.floor, group, root, parts: out.parts, spec, screen: body, pos: [ix, ent.floorY, iz], ry: iry, origin: ent.origin };
8965
9093
  IV.entries.set(ent.id, E);
8966
9094
  if (root.children.length) IV.roots.push(E);
8967
9095
  return spec;
@@ -8989,7 +9117,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
8989
9117
  const wire = (spec.wires || []).find((x) => x.id === d.id + "_cord"), pts = (wire ? wire.points : [d.plug]).map((p) => wl(o, p));
8990
9118
  const sid = w.power.pluggedInto(E.id, d.id);
8991
9119
  if (sid) {
8992
- const cut = sid.indexOf(":"), so = w.get(sid.slice(0, cut)), sk = so && so.spec.sockets.find((s) => s.id === sid.slice(cut + 1));
9120
+ const cut = sid.indexOf(":"), so = w.get(sid.slice(0, cut)), sk = so && (so.spec.sockets || []).find((s) => s.id === sid.slice(cut + 1));
8993
9121
  if (so && sk) {
8994
9122
  const sp = wl(so, sk.pos), dir = [Math.sin(so.transform.ry), Math.cos(so.transform.ry)], last = pts[pts.length - 1];
8995
9123
  if (last[1] < 0.3 + E.pos[1]) {
@@ -9024,9 +9152,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
9024
9152
  roomLightMask(sc.material);
9025
9153
  IV.screens.set(E.id, sc);
9026
9154
  }
9027
- E.screen.material = sc.material;
9028
- E.screen.castShadow = false;
9029
- E.screen.receiveShadow = false;
9155
+ const mesh2 = E.screen;
9156
+ mesh2.material = sc.material;
9157
+ mesh2.castShadow = false;
9158
+ mesh2.receiveShadow = false;
9030
9159
  }
9031
9160
  function ivEvent(h, e) {
9032
9161
  const IV = h.IV;
@@ -9062,16 +9191,17 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
9062
9191
  IV.itemsDirty = true;
9063
9192
  break;
9064
9193
  }
9065
- if (K.IVK.onEvent) {
9194
+ const ik = K.IVK;
9195
+ if (ik.onEvent) {
9066
9196
  try {
9067
- K.IVK.onEvent(e, h.IV.pub);
9197
+ ik.onEvent(e, IV.pub);
9068
9198
  } catch (err) {
9069
9199
  console.warn("interactables.onEvent", err);
9070
9200
  }
9071
9201
  }
9072
- if (e.type === "seat" && K.IVK.onSeat && e.actor === "player") {
9202
+ if (e.type === "seat" && ik.onSeat && e.actor === "player") {
9073
9203
  try {
9074
- K.IVK.onSeat(e.seated ? ivSeat(IV) : null, e);
9204
+ ik.onSeat(e.seated ? ivSeat(IV) : null, e);
9075
9205
  } catch (err) {
9076
9206
  console.warn("interactables.onSeat", err);
9077
9207
  }
@@ -9080,7 +9210,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
9080
9210
  function ivSeat(IV) {
9081
9211
  const w = IV.world, s = w.seatOf("player");
9082
9212
  if (!s) return null;
9083
- const o = w.get(s.object), seat = o.spec.seats.find((q) => q.id === s.seat), L = IV.k.GI.localToWorld, tr = o.transform, E = IV.entries.get(s.object);
9213
+ const o = w.get(s.object), seat = (o.spec.seats || []).find((q) => q.id === s.seat), L = IV.k.GI.localToWorld, tr = o.transform, E = IV.entries.get(s.object);
9084
9214
  const eye = L(tr, [seat.pos[0], seat.pos[1] + (seat.eye === void 0 ? seat.pose === "lie" ? 0.18 : 0.62 : seat.eye), seat.pos[2]]);
9085
9215
  return { object: s.object, seatInfo: s.seat, pose: seat.pose, eye, yaw: tr.ry + seat.ry, pitch: seat.pose === "lie" ? 0.55 : -0.08, exitPoint: L(tr, seat.exit), floor: E ? E.floor : 0, type: E ? E.type : null };
9086
9216
  }
@@ -9122,18 +9252,19 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
9122
9252
  }
9123
9253
  }
9124
9254
  const em = w.emitters();
9125
- if (em.length && !IV.efx && K.IVK.effects) {
9255
+ const ivk = K.IVK;
9256
+ if (em.length && !IV.efx && ivk.effects) {
9126
9257
  const g = h.houseGroup;
9127
- IV.efx = ik.gfx.createEffects(g, { maxParticles: 1400, seed: 11, document: DOC, ...K.IVK.effectSink ? { effects: K.IVK.effectSink } : {} });
9258
+ IV.efx = ik.gfx.createEffects(g, { maxParticles: 1400, seed: 11, document: DOC, ...ivk.effectSink ? { effects: ivk.effectSink } : {} });
9128
9259
  }
9129
9260
  if (IV.efx) {
9130
9261
  const alive = IV.efx.stats().alive;
9131
9262
  if (em.length || alive) {
9132
- IV.efx.update(dt, em, K.IVK.camera ? typeof K.IVK.camera === "function" ? K.IVK.camera() : K.IVK.camera : void 0);
9263
+ IV.efx.update(dt, em, ivk.camera ? typeof ivk.camera === "function" ? ivk.camera() : ivk.camera : void 0);
9133
9264
  invalidate();
9134
9265
  }
9135
9266
  }
9136
- if (K.IVK.items && IV.itemsDirty && IV.t - IV.itemsT > 0.1 && !IV.anim.size) ivItems(IV, h);
9267
+ if (ivk.items && IV.itemsDirty && IV.t - IV.itemsT > 0.1 && !IV.anim.size) ivItems(IV, h);
9137
9268
  }
9138
9269
  const IV_SHAPE = {
9139
9270
  can: [["cyl", 1, 1, 1, 0, 1]],
@@ -9168,7 +9299,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
9168
9299
  if (c.access && w.partT(E.id, c.access) < 0.02) continue;
9169
9300
  const st = w.contents(E.id, c.id);
9170
9301
  for (let i = 0; i < st.length; i++) {
9171
- if (st[i] && items[st[i].type]) list2.push([E, c.id, i, items[st[i].type]]);
9302
+ const stack = st[i];
9303
+ if (stack && items[stack.type]) list2.push([E, c.id, i, items[stack.type]]);
9172
9304
  }
9173
9305
  }
9174
9306
  }
@@ -9197,12 +9329,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
9197
9329
  gm.setIndex(new THREE.BufferAttribute(A.i.slice(0, A.ni), 1));
9198
9330
  gm.computeBoundingSphere();
9199
9331
  if (!IV.items) {
9200
- IV.items = new THREE.Mesh(gm, shared.mats.plain);
9201
- IV.items.name = "iv-items";
9202
- IV.items.castShadow = false;
9203
- IV.items.receiveShadow = true;
9204
- IV.items.frustumCulled = false;
9205
- h.houseGroup.add(IV.items);
9332
+ const mesh2 = new THREE.Mesh(gm, shared.mats.plain);
9333
+ IV.items = mesh2;
9334
+ mesh2.name = "iv-items";
9335
+ mesh2.castShadow = false;
9336
+ mesh2.receiveShadow = true;
9337
+ mesh2.frustumCulled = false;
9338
+ h.houseGroup.add(mesh2);
9206
9339
  } else {
9207
9340
  IV.items.geometry.dispose();
9208
9341
  IV.items.geometry = gm;
@@ -9336,7 +9469,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
9336
9469
  };
9337
9470
  return IV.pub;
9338
9471
  }
9339
- Object.assign(K, { IV_MATERIAL, IV_WIRE, IV_DOOR, ivGroup, ivAccumulate, ivBuild, ivRoomEffective, ivDraw, ivCords, ivAssemble, ivScreen, ivEvent, ivSeat, ivUpdate, IV_SHAPE, ivItems, ivTarget, ivRoomLight, ivParts, ivDispose, ivPublish });
9472
+ const defined = { IV_MATERIAL, IV_WIRE, IV_DOOR, ivGroup, ivAccumulate, ivBuild, ivRoomEffective, ivDraw, ivCords, ivAssemble, ivScreen, ivEvent, ivSeat, ivUpdate, IV_SHAPE, ivItems, ivTarget, ivRoomLight, ivParts, ivDispose, ivPublish };
9473
+ Object.assign(K, defined);
9340
9474
  }
9341
9475
 
9342
9476
  // src/animation/clotheslines.ts
@@ -9361,7 +9495,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
9361
9495
  }
9362
9496
  invalidate();
9363
9497
  }
9364
- Object.assign(K, { WIND, animateClotheslines });
9498
+ const defined = { WIND, animateClotheslines };
9499
+ Object.assign(K, defined);
9365
9500
  }
9366
9501
 
9367
9502
  // src/build/instance.ts
@@ -9386,7 +9521,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
9386
9521
  shared.quality = h.quality;
9387
9522
  }
9388
9523
  const tagDamage = (type) => ({ type, hp: HP[type], hpMax: HP[type] });
9389
- Object.assign(K, { props, TYPES, newState, enter, tagDamage });
9524
+ const defined = { props, TYPES, newState, enter, tagDamage };
9525
+ Object.assign(K, defined);
9390
9526
  }
9391
9527
 
9392
9528
  // ../game-floorplan-interactables/dist/index.js
@@ -10773,17 +10909,20 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
10773
10909
  for (const k of ["wood", "foliage", "flowers", "fruit", "spines"]) roomLightMask(m[k]);
10774
10910
  return m;
10775
10911
  })());
10776
- Object.assign(K, { IVK, VEG, vegMaterials });
10912
+ const defined = { IVK, VEG, vegMaterials };
10913
+ Object.assign(K, defined);
10777
10914
  }
10778
10915
 
10779
10916
  // src/lights/room-light.ts
10917
+ var newGroup = (k, house, exterior) => ({ k, house, ls: [], exterior, pos: [0, 0, 0], color: 0, n: 0, range: 0, rects: [], y: [0, 0], exclusion: null, lumens: 0, dist: 0, decay: 0, floor: 0, roomId: null, dm: 0, d: 0 });
10780
10918
  function installLightsRoomLight(K, shared) {
10781
10919
  const { THREE, rectsOf: rectsOf2, cfg } = K;
10782
10920
  const MAX_LIGHTS = 12, EMPTY = [1e9, 1e9, -1e9, -1e9];
10783
10921
  const LZU = { uRB0: { value: new Float32Array(MAX_LIGHTS * 4) }, uRB1: { value: new Float32Array(MAX_LIGHTS * 4) }, uRB2: { value: new Float32Array(MAX_LIGHTS * 4) }, uRBY: { value: new Float32Array(MAX_LIGHTS * 2) }, uREx: { value: new Float32Array(MAX_LIGHTS * 4) }, uIndK: { value: 0.06 } };
10784
10922
  for (let i = 0; i < MAX_LIGHTS; i++) for (const k of ["uRB0", "uRB1", "uRB2", "uREx"]) LZU[k].value.set(EMPTY, i * 4);
10785
- function roomLightMask(m) {
10786
- if (!m || m.userData && m.userData.roomLightMask || !(m.isMeshLambertMaterial || m.isMeshPhongMaterial || m.isMeshStandardMaterial || m.isMeshPhysicalMaterial)) return m;
10923
+ function roomLightMask(material) {
10924
+ const m = material;
10925
+ if (!m || m.userData && m.userData.roomLightMask || !(m.isMeshLambertMaterial || m.isMeshPhongMaterial || m.isMeshStandardMaterial || m.isMeshPhysicalMaterial)) return material;
10787
10926
  m.userData = m.userData || {};
10788
10927
  m.userData.roomLightMask = true;
10789
10928
  const prev = m.onBeforeCompile, pk = m.customProgramCacheKey;
@@ -10811,12 +10950,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
10811
10950
  return (pk ? pk.call(this) : "") + "|rm1";
10812
10951
  };
10813
10952
  m.needsUpdate = true;
10814
- return m;
10953
+ return material;
10815
10954
  }
10816
- function lighting(o) {
10817
- o = o || {};
10955
+ function lighting(options) {
10956
+ const o = options || {};
10818
10957
  const scene = o.scene, N = Math.max(1, Math.min(MAX_LIGHTS, o.n || 6)), NS = Math.max(0, Math.min(N, o.shadows != null ? o.shadows : 2)), size = o.shadowSize || 512, MAX_EXTERNAL = o.external != null ? o.external : 2;
10819
- for (const k of Object.keys(shared.mats)) roomLightMask(shared.mats[k]);
10958
+ const mats = shared.mats;
10959
+ for (const k of Object.keys(mats)) roomLightMask(mats[k]);
10820
10960
  const budget = o.budget, lease = budget ? budget.lease({ owner: "floorplan.rooms", point: N, shadows: NS }) : null;
10821
10961
  if (budget && !lease) throw new Error("lighting: the LightBudget has no " + N + " free point slots (" + NS + " with shadow) for the rooms");
10822
10962
  if (budget) for (const [key, width] of [["uRB0", 4], ["uRB1", 4], ["uRB2", 4], ["uRBY", 2], ["uREx", 4]]) {
@@ -10867,9 +11007,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
10867
11007
  }
10868
11008
  for (let i = 0; i < NS; i++) PL[i].shadow.needsUpdate = true;
10869
11009
  };
10870
- A.update = function(houses2, focus, op) {
10871
- op = op || {};
10872
- houses2 = (Array.isArray(houses2) ? houses2 : [houses2]).filter(Boolean);
11010
+ A.update = function(houseOrList, focus, options2) {
11011
+ const op = options2 || {}, houses2 = (Array.isArray(houseOrList) ? houseOrList : [houseOrList]).filter((h) => !!h);
10873
11012
  _f.set(focus.x, focus.y, focus.z);
10874
11013
  const rooms = [], exterior = [];
10875
11014
  for (const house of houses2) {
@@ -10881,7 +11020,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
10881
11020
  if (!house.lightOn(l.roomId)) continue;
10882
11021
  const k = l.type === "outdoor" ? "ext:" + (l.id || exterior.length) : l.roomId != null ? l.roomId : l.room;
10883
11022
  let g = by.get(k);
10884
- if (!g) by.set(k, g = { k, house, ls: [], exterior: l.type === "outdoor" });
11023
+ if (!g) by.set(k, g = newGroup(k, house, l.type === "outdoor"));
10885
11024
  g.ls.push(l);
10886
11025
  }
10887
11026
  for (const g of by.values()) {
@@ -10916,9 +11055,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
10916
11055
  }
10917
11056
  }
10918
11057
  g.exclusion = [x0 + 0.03, z0 + 0.03, x1 - 0.03, z1 - 0.03];
10919
- g.lumens = ls[0].lumens != null ? ls[0].lumens : 3.2;
10920
- g.dist = ls[0].dist != null ? ls[0].dist : 5.5;
10921
- g.decay = ls[0].decay != null ? ls[0].decay : 2;
11058
+ const l0 = ls[0];
11059
+ g.lumens = l0.lumens != null ? l0.lumens : 3.2;
11060
+ g.dist = l0.dist != null ? l0.dist : 5.5;
11061
+ g.decay = l0.decay != null ? l0.decay : 2;
10922
11062
  } else {
10923
11063
  const c = house.r.rooms.find((q) => q.id === g.k);
10924
11064
  if (!c) continue;
@@ -11019,8 +11159,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
11019
11159
  }
11020
11160
  const effectsByBudget = /* @__PURE__ */ new WeakMap();
11021
11161
  const OPENING_REACH = 2.5, OPENING_SIDE = 0.6;
11022
- function effectLights(o) {
11023
- o = o || {};
11162
+ function effectLights(options) {
11163
+ const o = options || {};
11024
11164
  const budget = o.budget;
11025
11165
  if (!budget) throw new Error("effectLights: a LightBudget is required");
11026
11166
  const known = effectsByBudget.get(budget);
@@ -11098,7 +11238,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
11098
11238
  const A = {
11099
11239
  /** Once per frame, after the budget's `present`: points the mask of every lit slot that is not the house's at the rooms its light reaches. */
11100
11240
  update(houses2) {
11101
- const indoors = cfg.effectLightsIndoors !== false, list2 = (Array.isArray(houses2) ? houses2 : [houses2]).filter(Boolean), cache2 = /* @__PURE__ */ new Map();
11241
+ const indoors = cfg.effectLightsIndoors !== false, list2 = (Array.isArray(houses2) ? houses2 : [houses2]).filter((h) => !!h), cache2 = /* @__PURE__ */ new Map();
11102
11242
  for (let at2 = 0; at2 < size; at2++) {
11103
11243
  if (ours.has(at2)) continue;
11104
11244
  const light = budget.group.children[at2];
@@ -11126,7 +11266,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
11126
11266
  if (!o.ours) effectsByBudget.set(budget, A);
11127
11267
  return A;
11128
11268
  }
11129
- Object.assign(K, { MAX_LIGHTS, EMPTY, LZU, roomLightMask, lighting, effectLights });
11269
+ const defined = { MAX_LIGHTS, EMPTY, LZU, roomLightMask, lighting, effectLights };
11270
+ Object.assign(K, defined);
11130
11271
  }
11131
11272
 
11132
11273
  // ../game-destruction/dist/index.js
@@ -13075,6 +13216,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
13075
13216
  floor: 60
13076
13217
  }
13077
13218
  },
13219
+ ricochetDeg: 12,
13078
13220
  hitDebris: "chips",
13079
13221
  breakDebris: "dust",
13080
13222
  visual: { innerColor: 10197652 },
@@ -13106,6 +13248,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
13106
13248
  0.04,
13107
13249
  0.12
13108
13250
  ],
13251
+ ricochetDeg: 10,
13109
13252
  hitDebris: "chips",
13110
13253
  breakDebris: "dust",
13111
13254
  visual: { innerColor: 12085567 },
@@ -13163,6 +13306,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
13163
13306
  0.06,
13164
13307
  0.3
13165
13308
  ],
13309
+ ricochetDeg: 15,
13166
13310
  hitDebris: "chips",
13167
13311
  breakDebris: "dust",
13168
13312
  visual: { innerColor: 9407364 },
@@ -13591,6 +13735,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
13591
13735
  0.03,
13592
13736
  0.15
13593
13737
  ],
13738
+ ricochetDeg: 8,
13594
13739
  hitDebris: "chips",
13595
13740
  breakDebris: "dust",
13596
13741
  thermal: {
@@ -13690,6 +13835,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
13690
13835
  0.02,
13691
13836
  0.08
13692
13837
  ],
13838
+ ricochetDeg: 8,
13693
13839
  hitDebris: "chips",
13694
13840
  breakDebris: "dust",
13695
13841
  thermal: {
@@ -13784,6 +13930,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
13784
13930
  0.05,
13785
13931
  0.15
13786
13932
  ],
13933
+ ricochetDeg: 15,
13787
13934
  hitDebris: "chips",
13788
13935
  breakDebris: "chips",
13789
13936
  thermal: {
@@ -13809,6 +13956,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
13809
13956
  0.04,
13810
13957
  0.12
13811
13958
  ],
13959
+ ricochetDeg: 12,
13812
13960
  hitDebris: "chips",
13813
13961
  breakDebris: "chips",
13814
13962
  thermal: {
@@ -17551,8 +17699,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
17551
17699
 
17552
17700
  // ../game-floorplan-structure/dist/index.js
17553
17701
  var __defProp2 = Object.defineProperty;
17554
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
17555
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
17702
+ var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
17703
+ var __publicField2 = (obj, key, value) => __defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value);
17556
17704
  var uniform = (joint) => ({ wall: joint, slab: joint, beam: joint, column: joint, truss: joint });
17557
17705
  var CONSTRUCTION_SYSTEMS = /* @__PURE__ */ new Map([
17558
17706
  ["masonry", { walls: "brick_wall_plastered", joints: { wall: "mortar", slab: "rebar", beam: "mortar", column: "rebar", truss: "bolt" }, slabThickness: 0.12, plateThickness: 0.2, timber: false, wallRole: "rules", wallFill: 1 }],
@@ -17686,9 +17834,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
17686
17834
  var densityOf = (material) => DENSITY[material] ?? DEFAULT_DENSITY;
17687
17835
  var StructureBuilder = class {
17688
17836
  constructor() {
17689
- __publicField(this, "parts", []);
17690
- __publicField(this, "supports", []);
17691
- __publicField(this, "ids", /* @__PURE__ */ new Set());
17837
+ __publicField2(this, "parts", []);
17838
+ __publicField2(this, "supports", []);
17839
+ __publicField2(this, "ids", /* @__PURE__ */ new Set());
17692
17840
  }
17693
17841
  add(draft, options = {}) {
17694
17842
  const { id, role, material, aabb, y0, y1 } = draft;
@@ -21603,8 +21751,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
21603
21751
  // src/build/build.ts
21604
21752
  function installBuildBuild(K, shared) {
21605
21753
  const { THREE, cfg, rectsOf: rectsOf2, invalidateShadow, colliderChanged, VERSION: VERSION2, CARS, EPS: EPS3, LIGHTS, MIRRORS, Y0, animateClotheslines, animateDoors, animateInteractive, applyLeaf, applyOutbuildings, applyPart, applyPiece, assembleInteractive, baseboardAndSidewalk, buildStairs, building, carModel, chooseMirror, closeScene, collideAt, createWater, cursor, doorText, doors, electricalStructure, elevator, floorsAndSlabs, gatesInteractive, houseItems, ivAssemble, ivBuild, ivDispose, ivParts, ivPublish, ivUpdate, lightOn, linkDoorLeaves, mailboxInteractive, newInteractiveState, newMirrorState, outbuildings, paths, perimeter, placeSwitches, roofs, roomAt, solar, targetOf, terrain, toggleDoor, toggleLight, walls, waterPipes, windows, props, TYPES, IVK, VEG, vegMaterials, markGroups, assembleStructure, createHouseDestruction, newState, enter, tagDamage } = K;
21606
- function build(r0, opts) {
21607
- opts = opts || {};
21754
+ function build(r0, options) {
21755
+ const opts = options || {};
21608
21756
  const r = applyOutbuildings(r0);
21609
21757
  const t0 = performance.now();
21610
21758
  const h = { ctx: { mv: props, types: TYPES }, inter: newInteractiveState(), state: opts.state || newState(), mirrors: newMirrorState(), quality: opts.quality === "game" || opts.quality === "high" ? opts.quality : cfg.quality === "game" ? "game" : "high", lodCurrent: 0, lodMin: 0 };
@@ -21625,7 +21773,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
21625
21773
  shared.ctx.pieces = /* @__PURE__ */ new Map();
21626
21774
  shared.ctx.pieceObjects = /* @__PURE__ */ new Map();
21627
21775
  shared.ctx.structureIndex = {};
21628
- for (const e of r0.structure && r0.structure.parts || []) shared.ctx.structureIndex[e.id] = e;
21776
+ for (const e of r0.structure?.parts || []) shared.ctx.structureIndex[e.id] = e;
21629
21777
  {
21630
21778
  const view = shared.ctx.panelView = panelViewOf(r0.structure, !!cfg.destruction);
21631
21779
  shared.ctx.panelsOf = /* @__PURE__ */ new Map();
@@ -21637,7 +21785,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
21637
21785
  else shared.ctx.panelsOf.set(e.slab, [e]);
21638
21786
  }
21639
21787
  }
21640
- shared.ctx.panes = r0.roof && r0.roof.panes || [];
21788
+ shared.ctx.panes = r0.roof?.panes || [];
21641
21789
  shared.ctx.noPiece = false;
21642
21790
  cursor.separate = opts.pieces === "meshes";
21643
21791
  cursor.pc = null;
@@ -21648,7 +21796,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
21648
21796
  shared.ctx.pu = Math.max(0, pr.unit != null ? pr.unit : 0);
21649
21797
  shared.ctx.showBuilding = shared.ctx.apartment && (pr.showIt == null ? true : !!pr.showIt);
21650
21798
  shared.ctx.limits = { x0: -2, z0: -2, x1: r.w + 2, z1: r.d + 2 };
21651
- shared.ctx.veg = VEG ? { G: VEG.G, S: VEG.S, mats: vegMaterials, groups: /* @__PURE__ */ new Map(), ok: /* @__PURE__ */ new Map(), opts: shared.quality === "game" ? { quality: "game" } : { lod: 0, triangleBudget: 6e4 } } : null;
21799
+ shared.ctx.veg = VEG ? { G: VEG.G, S: VEG.S, mats: vegMaterials, groups: /* @__PURE__ */ new Map(), ok: /* @__PURE__ */ new Map(), opts: shared.quality === "game" ? { quality: "game" } : { quality: "high", lod: 0, triangleBudget: 6e4 } } : null;
21652
21800
  shared.ctx.vegInfo = null;
21653
21801
  terrain();
21654
21802
  if (r.lot) {
@@ -21698,7 +21846,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
21698
21846
  const g = gs[gd.name];
21699
21847
  if (!g) continue;
21700
21848
  delete gs[gd.name];
21701
- g.position.set(...gd.pos);
21849
+ g.position.fromArray(gd.pos);
21702
21850
  parent.add(g);
21703
21851
  fo.gs.push(g);
21704
21852
  }
@@ -21713,7 +21861,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
21713
21861
  root.add(house);
21714
21862
  shared.mirrors.house = house;
21715
21863
  if (shared.ctx.apartment) {
21716
- const u = r.building.units[Math.min(shared.ctx.pu, r.building.units.length - 1)];
21864
+ const units = r.building.units, u = units[Math.min(shared.ctx.pu, units.length - 1)];
21717
21865
  house.position.set(u.u, shared.ctx.showBuilding ? 0 : -r.floors[0].y0, u.v);
21718
21866
  house.rotation.y = u.ry;
21719
21867
  shared.ctx.unitRy = u.ry;
@@ -21829,7 +21977,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
21829
21977
  const wallAt = (f, axis, L) => r.walls.find((w) => w.floor === f && w.axis === axis && Math.abs((axis === "u" ? w.v0 : w.u0) - L) < EPS3);
21830
21978
  for (const j of r.windows) {
21831
21979
  const alongU = j.axis === "u", y0 = Y0(j.floor), a = j.at - j.width / 2, b = j.at + j.width / 2, w = wallAt(j.floor, j.axis, j.pos), th = w ? w.thickness || 0.15 : 0.15, L = j.pos, id = "window:" + j.id;
21832
- parts[id] = { id, type: "window", group: null, virtual: true, floor: j.floor, aabb: alongU ? [a, y0 + j.y0, L - th / 2, b, y0 + j.y1, L + th / 2] : [L - th / 2, y0 + j.y0, a, L + th / 2, y0 + j.y1, b], damageable: tagDamage("glass"), opens: () => {
21980
+ const jy0 = j.y0, jy1 = j.y1;
21981
+ parts[id] = { id, type: "window", group: null, virtual: true, floor: j.floor, aabb: alongU ? [a, y0 + jy0, L - th / 2, b, y0 + jy1, L + th / 2] : [L - th / 2, y0 + jy0, a, L + th / 2, y0 + jy1, b], damageable: tagDamage("glass"), opens: () => {
21833
21982
  }, t: 0 };
21834
21983
  }
21835
21984
  for (const E of mirrorsCopy) {
@@ -21872,7 +22021,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
21872
22021
  const countDraw = () => {
21873
22022
  let n = 0, t = 0;
21874
22023
  root.traverseVisible((o) => {
21875
- if (o.isMesh) {
22024
+ if (isMesh(o)) {
21876
22025
  n++;
21877
22026
  t += (o.geometry.index ? o.geometry.index.count : o.geometry.attributes.position.count) / 3;
21878
22027
  }
@@ -21886,8 +22035,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
21886
22035
  const budget = opts.drawCallBudget != null ? opts.drawCallBudget : cfg.drawCallBudget;
21887
22036
  const stats2 = { quality: h.quality, drawCalls: s0.n, drawCallsLOD1: s1.n, triangles: s0.t, trianglesLod1: s1.t, budget: budget || null, overBudget: !!budget && s0.n > budget, tBuild: performance.now() - t0 };
21888
22037
  shared.ctx.tBuild = stats2.tBuild;
21889
- const applyLod = (n) => {
21890
- n = Math.max(0, Math.min(2, n | 0));
22038
+ const applyLod = (level) => {
22039
+ const n = Math.max(0, Math.min(2, level | 0));
21891
22040
  if (n === h.lodCurrent) return;
21892
22041
  h.lodCurrent = n;
21893
22042
  for (const o of lodObjects) o.visible = n < 1;
@@ -21964,7 +22113,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
21964
22113
  lights: (() => {
21965
22114
  const by = {};
21966
22115
  for (const l of shared.ctx.lights) {
21967
- const k = l.roomId != null ? l.roomId : l.room;
22116
+ const k = String(l.roomId != null ? l.roomId : l.room);
21968
22117
  (by[k] || (by[k] = [])).push(l);
21969
22118
  }
21970
22119
  return { list: shared.ctx.lights, byRoom: by };
@@ -22004,9 +22153,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
22004
22153
  applyLod(Math.max(n, h.lodMin));
22005
22154
  }
22006
22155
  },
22007
- show(o) {
22156
+ show(options2) {
22008
22157
  enter(h);
22009
- o = o || {};
22158
+ const o = options2 || {};
22010
22159
  const rr = shared.ctx.r, nA = rr.floors.length, a = o.floor == null ? -1 : o.floor, sel = a >= nA ? -1 : a, cut = !!o.cut;
22011
22160
  for (const [k, g] of Object.entries(gs)) {
22012
22161
  let v = true;
@@ -22026,7 +22175,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
22026
22175
  enter(h);
22027
22176
  const a = targetOf(o, opt);
22028
22177
  if (!a) return false;
22029
- return actOn(a.target && a.target.pub ? a.target.pub : { id: a.target && a.target.id || a.text, type: a.target && a.target.kit ? a.target.type : "door", label: a.text, ref: a.target, _action: a.action }, a);
22178
+ return actOn(a.target && a.target.pub ? a.target.pub : { id: a.target && a.target.id || a.text, type: a.target && a.target.kit ? a.target.type : "door", label: a.text, ref: a.target, _action: a.action, floor: 0, pos: [], radius: 0 }, a);
22030
22179
  },
22031
22180
  message() {
22032
22181
  return shared.inter.msg && performance.now() < shared.inter.msg.until ? shared.inter.msg.text : null;
@@ -22083,13 +22232,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
22083
22232
  }
22084
22233
  return null;
22085
22234
  },
22086
- partAt(p, tol) {
22087
- tol = tol || 0.05;
22235
+ partAt(p, tolerance) {
22236
+ const tol = tolerance || 0.05;
22088
22237
  let m = null;
22089
22238
  for (const k in parts) {
22090
- const a = parts[k].aabb;
22239
+ const part = parts[k], a = part.aabb;
22091
22240
  if (a && p.x >= a[0] - tol && p.x <= a[3] + tol && p.y >= a[1] - tol && p.y <= a[4] + tol && p.z >= a[2] - tol && p.z <= a[5] + tol) {
22092
- m = parts[k];
22241
+ m = part;
22093
22242
  break;
22094
22243
  }
22095
22244
  }
@@ -22100,8 +22249,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
22100
22249
  destruction.deactivate();
22101
22250
  if (h.IV) ivDispose(h);
22102
22251
  root.traverse((o) => {
22103
- if (o.isMesh && o.geometry && !o.geometry.userData.shared) o.geometry.dispose();
22104
- if (o.type === "Reflector" && o.dispose) o.dispose();
22252
+ if (isMesh(o) && o.geometry && !o.geometry.userData.shared) o.geometry.dispose();
22253
+ if (o.type === "Reflector" && "dispose" in o && typeof o.dispose === "function") o.dispose();
22105
22254
  });
22106
22255
  root.removeFromParent();
22107
22256
  },
@@ -22109,7 +22258,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
22109
22258
  };
22110
22259
  return res;
22111
22260
  }
22112
- Object.assign(K, { build });
22261
+ const defined = { build };
22262
+ Object.assign(K, defined);
22113
22263
  }
22114
22264
 
22115
22265
  // src/build/api.ts
@@ -22131,11 +22281,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
22131
22281
  lighting,
22132
22282
  effectLights,
22133
22283
  setNight(n) {
22134
- shared.mats.glass.emissive.set(n ? 9067040 : 0);
22135
- shared.mats.glass.opacity = n ? 0.4 : 0.24;
22284
+ const glass = shared.mats.glass;
22285
+ glass.emissive.set(n ? 9067040 : 0);
22286
+ glass.opacity = n ? 0.4 : 0.24;
22136
22287
  },
22137
22288
  /** The chipped-plaster painting of every house of this renderer as a `DeferredQueue` for a frame budget (id `floorplan.breach-paint`); asking for it changes nothing. */
22138
22289
  deferredQueue: () => K.breachPaintQueue,
22290
+ /* the destruction side is typed with the breach */
22139
22291
  cars: { model: carModel, group: carGroup, info: (k, seed) => {
22140
22292
  const m = carModel(k, seed);
22141
22293
  return m && { parts: m.parts.length, tris: m.tris, L: m.L, W: m.W, H: m.H };
@@ -22772,7 +22924,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
22772
22924
  const stopListening = () => {
22773
22925
  for (const off of listening.splice(0)) off?.();
22774
22926
  };
22775
- const collapsed = (list2) => list2.filter((e) => e.type === "collapse").flatMap((e) => e.parts.map((p) => p.id || p));
22927
+ const collapsed = (list2) => list2.flatMap((e) => e.type === "collapse" ? e.parts.map((p) => p.id || p) : []);
22776
22928
  const whole = (room, oid, pid) => {
22777
22929
  const p = room.world.part(oid, pid);
22778
22930
  return !!p && p.status !== "broken" && !p.stripped;
@@ -23132,9 +23284,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
23132
23284
  return best;
23133
23285
  };
23134
23286
  const eyeOf = (p) => {
23287
+ const T2 = THREE;
23135
23288
  const camera = host?.camera;
23136
23289
  const at2 = toLocal2(p, camera.position.x, camera.position.y, camera.position.z);
23137
- const forward = new THREE.Vector3(0, 0, -1).applyQuaternion(camera.quaternion).transformDirection(new THREE.Matrix4().copy(p.house.group.matrixWorld).invert());
23290
+ const forward = new T2.Vector3(0, 0, -1).applyQuaternion(camera.quaternion).transformDirection(new T2.Matrix4().copy(p.house.group.matrixWorld).invert());
23138
23291
  return { x: at2.x, y: at2.y, z: at2.z, floor: floorOf(p, camera.position.y), yaw: Math.atan2(forward.x, forward.z), pitch: Math.asin(Math.max(-1, Math.min(1, forward.y))) };
23139
23292
  };
23140
23293
  const blocked = (x, z, radius) => {
@@ -23150,8 +23303,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
23150
23303
  const standAt = (p, u, v, floor, lookU, lookV) => {
23151
23304
  if (!host?.bench) return;
23152
23305
  const y = p.house.y0(floor) + EYE;
23153
- const eye = p.house.group.localToWorld(new THREE.Vector3(u, y, v));
23154
- const target = p.house.group.localToWorld(new THREE.Vector3(lookU, y - 0.1, lookV));
23306
+ const T2 = THREE;
23307
+ const eye = p.house.group.localToWorld(new T2.Vector3(u, y, v));
23308
+ const target = p.house.group.localToWorld(new T2.Vector3(lookU, y - 0.1, lookV));
23155
23309
  host.bench.look([eye.x, eye.y, eye.z], [target.x, target.y, target.z]);
23156
23310
  floorNow = floor;
23157
23311
  };
@@ -23201,16 +23355,17 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
23201
23355
  host?.log(fill(text.steps.door, { text: String(target.text) }));
23202
23356
  };
23203
23357
  const doorReach = (p, fo) => {
23358
+ const T2 = THREE;
23204
23359
  const g = fo.gs[0];
23205
23360
  const pivot = fo.handles[0].pivot;
23206
23361
  const at2 = (angle) => {
23207
23362
  const c = Math.cos(angle);
23208
23363
  const s = Math.sin(angle);
23209
- const v = new THREE.Vector3(pivot[0] * c + pivot[2] * s, pivot[1], -pivot[0] * s + pivot[2] * c).add(g.position);
23364
+ const v = new T2.Vector3(pivot[0] * c + pivot[2] * s, pivot[1], -pivot[0] * s + pivot[2] * c).add(g.position);
23210
23365
  return g.parent ? g.parent.localToWorld(v) : v;
23211
23366
  };
23212
23367
  const camera = host?.camera;
23213
- const eye = new THREE.Vector3(camera.position.x, 0, camera.position.z);
23368
+ const eye = new T2.Vector3(camera.position.x, 0, camera.position.z);
23214
23369
  const flat = (v) => Math.hypot(v.x - eye.x, v.z - eye.z);
23215
23370
  const closed = at2(0);
23216
23371
  const open = at2(fo.rot);
@@ -23218,9 +23373,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
23218
23373
  return {
23219
23374
  handle: () => {
23220
23375
  g.updateMatrixWorld(true);
23221
- return g.localToWorld(new THREE.Vector3(pivot[0], pivot[1], pivot[2])).toArray();
23376
+ return g.localToWorld(new T2.Vector3(pivot[0], pivot[1], pivot[2])).toArray();
23222
23377
  },
23223
- hinge: () => g.getWorldPosition(new THREE.Vector3()).toArray(),
23378
+ hinge: () => g.getWorldPosition(new T2.Vector3()).toArray(),
23224
23379
  seconds: fo.locked || fo.blockedFlag ? 0.6 : 0.55,
23225
23380
  pull: opening ? flat(open) <= flat(closed) : flat(closed) <= flat(open),
23226
23381
  locked: !!(fo.locked || fo.blockedFlag)
@@ -25018,9 +25173,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
25018
25173
  waterTank: null,
25019
25174
  outbuildings: []
25020
25175
  };
25021
- plan.construction = masonryConstruction({ ...plan, facade: { ...facade, roof: "colonial" } });
25022
- plan.structure = buildStructure(plan, { wallDetail: "coarse", construction: plan.construction, roof: false });
25023
- return plan;
25176
+ const construction = masonryConstruction({ ...plan, facade: { ...facade, roof: "colonial" } });
25177
+ const structure = buildStructure({ ...plan, construction }, { wallDetail: "coarse", construction, roof: false });
25178
+ return Object.assign(plan, { construction, structure });
25024
25179
  }
25025
25180
  function draw(THREE, plan, options) {
25026
25181
  return create3(THREE, { ...options, fleet: null }).build(plan, { quality: "game", terrain: false, noPerimeter: true, pieces: "meshes" });
@@ -25030,7 +25185,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
25030
25185
  houses.set(house.group, house);
25031
25186
  for (const [id, items] of Object.entries(house.destruction.ranges())) {
25032
25187
  for (const item of items) {
25033
- const object2 = item.isObject3D ? item : item.mesh;
25188
+ const object2 = "isObject3D" in item ? item : item.mesh;
25034
25189
  object2.userData.destructionPart = id;
25035
25190
  }
25036
25191
  }