@adatechnology/game-floorplan-three 0.9.3 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-QUVGWVEC.js → chunk-Y3Y7NYOL.js} +547 -317
- package/dist/chunk-Y3Y7NYOL.js.map +1 -0
- package/dist/index.d.ts +100 -36
- package/dist/index.global.js +1232 -386
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +42 -6
- package/dist/index.js.map +1 -1
- package/dist/testing-BK7QmoUq.d.ts +1611 -0
- package/dist/testing.d.ts +12 -1
- package/dist/testing.js +1 -1
- package/package.json +24 -10
- package/dist/chunk-QUVGWVEC.js.map +0 -1
- package/dist/testing-ikPy2Nxl.d.ts +0 -379
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
|
|
1
5
|
// src/test-area/module.ts
|
|
2
6
|
import { DEFERRED_PRIORITY, DEFERRED_QUEUE_ID as DEFERRED_QUEUE_ID2 } from "@adatechnology/game-contracts";
|
|
3
7
|
import { isLightBudget } from "@adatechnology/game-render-three";
|
|
@@ -108,6 +112,20 @@ function installKernelGeometry(K, shared) {
|
|
|
108
112
|
const WITH_MAP = { roughcast: 1, block: 1 };
|
|
109
113
|
class Accumulator {
|
|
110
114
|
constructor() {
|
|
115
|
+
__publicField(this, "cv");
|
|
116
|
+
__publicField(this, "ci");
|
|
117
|
+
__publicField(this, "p");
|
|
118
|
+
__publicField(this, "n");
|
|
119
|
+
__publicField(this, "c");
|
|
120
|
+
__publicField(this, "u");
|
|
121
|
+
__publicField(this, "i");
|
|
122
|
+
__publicField(this, "nv");
|
|
123
|
+
__publicField(this, "ni");
|
|
124
|
+
__publicField(this, "lim");
|
|
125
|
+
__publicField(this, "cur");
|
|
126
|
+
__publicField(this, "piece0");
|
|
127
|
+
__publicField(this, "mat", "");
|
|
128
|
+
__publicField(this, "group", "");
|
|
111
129
|
this.cv = 2048;
|
|
112
130
|
this.ci = 3072;
|
|
113
131
|
this.p = new Float32Array(this.cv * 3);
|
|
@@ -170,7 +188,8 @@ function installKernelGeometry(K, shared) {
|
|
|
170
188
|
g.position.copy(u.pose0.p);
|
|
171
189
|
g.quaternion.copy(u.pose0.q);
|
|
172
190
|
g.scale.copy(u.pose0.s);
|
|
173
|
-
const
|
|
191
|
+
const [ax, ay, az] = a.axis || [0, 1, 0];
|
|
192
|
+
const e = new THREE.Vector3(ax, ay, az);
|
|
174
193
|
if (a.type === "swing" || a.type === "toggle") g.rotateOnAxis(e, (a.angle || 0) * t);
|
|
175
194
|
else if (a.type === "slide") g.translateOnAxis(e, (a.dist || 0) * t);
|
|
176
195
|
else if (a.type === "scale") {
|
|
@@ -265,7 +284,7 @@ function installKernelGeometry(K, shared) {
|
|
|
265
284
|
}
|
|
266
285
|
if (uvr) {
|
|
267
286
|
let gu = G.u[k * 2], gv = G.u[k * 2 + 1];
|
|
268
|
-
for (let r = uvr.rot | 0; r > 0; r--) {
|
|
287
|
+
for (let r = (uvr.rot ?? 0) | 0; r > 0; r--) {
|
|
269
288
|
const t = gu;
|
|
270
289
|
gu = gv;
|
|
271
290
|
gv = 1 - t;
|
|
@@ -363,14 +382,13 @@ function installKernelGeometry(K, shared) {
|
|
|
363
382
|
A.nv += n;
|
|
364
383
|
}
|
|
365
384
|
let bxImpl = bxBase;
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
K.getBx = () => bxImpl;
|
|
370
|
-
K.setBx = (f) => {
|
|
385
|
+
const bx = (...a) => bxImpl(...a);
|
|
386
|
+
const getBx = () => bxImpl;
|
|
387
|
+
const setBx = (f) => {
|
|
371
388
|
bxImpl = f;
|
|
372
389
|
};
|
|
373
|
-
|
|
390
|
+
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 };
|
|
391
|
+
Object.assign(K, defined);
|
|
374
392
|
}
|
|
375
393
|
|
|
376
394
|
// src/kernel/noise.ts
|
|
@@ -388,17 +406,20 @@ function installKernelNoise(K, _shared) {
|
|
|
388
406
|
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;
|
|
389
407
|
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)];
|
|
390
408
|
}
|
|
391
|
-
|
|
409
|
+
const defined = { _h2, vnoise, macroGround };
|
|
410
|
+
Object.assign(K, defined);
|
|
392
411
|
}
|
|
393
412
|
|
|
394
413
|
// src/materials/textures.ts
|
|
395
414
|
function installMaterialsTextures(K, _shared) {
|
|
396
415
|
const { DOC, THREE, cfg } = K;
|
|
397
416
|
function texture(n, f, rep = true, rx = 1, ry = 1) {
|
|
417
|
+
if (!DOC) throw new Error("game-floorplan-three: the procedural textures need a document (options.document)");
|
|
398
418
|
const c = DOC.createElement("canvas");
|
|
399
419
|
c.width = n;
|
|
400
420
|
c.height = n;
|
|
401
421
|
const g = c.getContext("2d");
|
|
422
|
+
if (!g) throw new Error("game-floorplan-three: no 2d canvas context");
|
|
402
423
|
f(g, n);
|
|
403
424
|
const t = new THREE.CanvasTexture(c);
|
|
404
425
|
t.colorSpace = THREE.SRGBColorSpace;
|
|
@@ -517,10 +538,16 @@ function installMaterialsTextures(K, _shared) {
|
|
|
517
538
|
const TEX = {};
|
|
518
539
|
for (const k of Object.keys(TEXGEN)) TEX[k] = cfg.textures && cfg.textures[k] || TEXGEN[k]();
|
|
519
540
|
const ATLAS = {};
|
|
520
|
-
|
|
541
|
+
const defined = { texture, rngTexture, TEXGEN, TEX, ATLAS };
|
|
542
|
+
Object.assign(K, defined);
|
|
521
543
|
}
|
|
522
544
|
|
|
523
545
|
// src/materials/materials.ts
|
|
546
|
+
function context2d(c) {
|
|
547
|
+
const g = c.getContext("2d");
|
|
548
|
+
if (!g) throw new Error("game-floorplan-three: no 2d canvas context");
|
|
549
|
+
return g;
|
|
550
|
+
}
|
|
524
551
|
function installMaterialsMaterials(K, _shared) {
|
|
525
552
|
const { THREE, cfg, ATLAS, TEX, rngTexture } = K;
|
|
526
553
|
function createMaterials(props) {
|
|
@@ -532,7 +559,7 @@ function installMaterialsMaterials(K, _shared) {
|
|
|
532
559
|
return t;
|
|
533
560
|
};
|
|
534
561
|
if (!(cfg.atlas && cfg.atlas.floorKind)) {
|
|
535
|
-
const pc = props.atlas("floor").canvas, g = pc
|
|
562
|
+
const pc = props.atlas("floor").canvas, g = context2d(pc);
|
|
536
563
|
for (const c of [0, 1]) {
|
|
537
564
|
g.save();
|
|
538
565
|
g.globalCompositeOperation = "screen";
|
|
@@ -547,7 +574,7 @@ function installMaterialsMaterials(K, _shared) {
|
|
|
547
574
|
g.restore();
|
|
548
575
|
}
|
|
549
576
|
if (!(cfg.atlas && cfg.atlas.floorKind)) {
|
|
550
|
-
const pc = props.atlas("floor").canvas, g = pc
|
|
577
|
+
const pc = props.atlas("floor").canvas, g = context2d(pc);
|
|
551
578
|
g.save();
|
|
552
579
|
g.fillStyle = "rgba(128,92,62,0.52)";
|
|
553
580
|
g.fillRect(256, 256, 256, 256);
|
|
@@ -644,7 +671,8 @@ function installMaterialsMaterials(K, _shared) {
|
|
|
644
671
|
}
|
|
645
672
|
const ORDER = { glass: 3, water: 2, screen: 3, building: 4 };
|
|
646
673
|
const NO_SHADOW = /* @__PURE__ */ new Set(["dirt", "glass", "water", "screen", "building", "picture", "floor", "emissive"]);
|
|
647
|
-
|
|
674
|
+
const defined = { createMaterials, antiTile, dirtMaterial, CLOTHES_UNIFORMS, clothesMaterial, ORDER, NO_SHADOW };
|
|
675
|
+
Object.assign(K, defined);
|
|
648
676
|
}
|
|
649
677
|
|
|
650
678
|
// src/kernel/close-scene.ts
|
|
@@ -655,15 +683,18 @@ function installKernelCloseScene(K, shared) {
|
|
|
655
683
|
const assembleVegetation = (...a) => K.assembleVegetation(...a);
|
|
656
684
|
function markMesh(m, A) {
|
|
657
685
|
const L = A.lim, fx = [];
|
|
686
|
+
const pieces = shared.ctx.pieces;
|
|
658
687
|
for (let k = 0; k < L.length; k++) {
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
688
|
+
const lim = L[k], pc = lim.pc;
|
|
689
|
+
if (!pc) continue;
|
|
690
|
+
const next = L[k + 1];
|
|
691
|
+
const v1 = next ? next.v : A.nv, i1 = next ? next.i : A.ni;
|
|
692
|
+
if (v1 > lim.v) fx.push({ id: pc.id, v0: lim.v, v1, i0: lim.i, i1 });
|
|
662
693
|
}
|
|
663
694
|
if (!fx.length) return;
|
|
664
695
|
const u = m.userData, ids = [...new Set(fx.map((f) => f.id))], weight = {};
|
|
665
696
|
for (const f of fx) {
|
|
666
|
-
const mt =
|
|
697
|
+
const mt = pieces.get(f.id).mat;
|
|
667
698
|
weight[mt] = (weight[mt] || 0) + f.v1 - f.v0;
|
|
668
699
|
}
|
|
669
700
|
u.ranges = fx;
|
|
@@ -671,7 +702,7 @@ function installKernelCloseScene(K, shared) {
|
|
|
671
702
|
u.destructionMaterial = Object.keys(weight).sort((a, b) => weight[b] - weight[a])[0];
|
|
672
703
|
if (ids.length === 1) {
|
|
673
704
|
u.destructionPart = ids[0];
|
|
674
|
-
const pc =
|
|
705
|
+
const pc = pieces.get(ids[0]);
|
|
675
706
|
if (pc.role) u.structuralRole = pc.role;
|
|
676
707
|
}
|
|
677
708
|
}
|
|
@@ -722,7 +753,8 @@ function installKernelCloseScene(K, shared) {
|
|
|
722
753
|
assembleVegetation(groups);
|
|
723
754
|
return groups;
|
|
724
755
|
}
|
|
725
|
-
|
|
756
|
+
const defined = { markMesh, closeScene };
|
|
757
|
+
Object.assign(K, defined);
|
|
726
758
|
}
|
|
727
759
|
|
|
728
760
|
// src/house/helpers.ts
|
|
@@ -760,8 +792,14 @@ function installHouseHelpers(K, shared) {
|
|
|
760
792
|
for (const h of holes) L = L.flatMap((r) => subRect(r, h));
|
|
761
793
|
return L;
|
|
762
794
|
}
|
|
763
|
-
const wallColor = (c) =>
|
|
764
|
-
|
|
795
|
+
const wallColor = (c) => {
|
|
796
|
+
const k = c && c.color ? colorOf(c.color.wall) : null;
|
|
797
|
+
return k != null ? k : 14999768;
|
|
798
|
+
};
|
|
799
|
+
const floorColor = (c) => {
|
|
800
|
+
const k = c && c.color ? colorOf(c.color.floor) : null;
|
|
801
|
+
return k != null ? k : 11577496;
|
|
802
|
+
};
|
|
765
803
|
function stairFootprint(m) {
|
|
766
804
|
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]);
|
|
767
805
|
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]))];
|
|
@@ -772,12 +810,14 @@ function installHouseHelpers(K, shared) {
|
|
|
772
810
|
const pitch = A[f + 1].y0 - A[f].y0;
|
|
773
811
|
return h > pitch && h - pitch <= 0.45 ? pitch : h;
|
|
774
812
|
}
|
|
775
|
-
|
|
813
|
+
const defined = { OPEN_ROOM_TYPES: OPEN_ROOM_TYPES2, NO_CEILING, OPEN_AREA, EPS, Y0, colorOf, rectsOf: rectsOf2, roomAt, subRect, subRects, wallColor, floorColor, stairFootprint, effectiveHeight };
|
|
814
|
+
Object.assign(K, defined);
|
|
776
815
|
}
|
|
777
816
|
|
|
778
817
|
// src/house/walls.ts
|
|
779
818
|
function installHouseWalls(K, shared) {
|
|
780
819
|
const { EPS, Y0, boxC, bx, cursor, effectiveHeight, pieceRecord, structurePiece, wallColor } = K;
|
|
820
|
+
const sh = (...a) => K.sh(...a);
|
|
781
821
|
function wallBox(alongU, L, a, b, ya, yb, th, cL, cH, mL, mH) {
|
|
782
822
|
if (yb - ya < 1e-4 || b - a < 1e-4) return;
|
|
783
823
|
if (alongU) {
|
|
@@ -821,8 +861,9 @@ function installHouseWalls(K, shared) {
|
|
|
821
861
|
function walls() {
|
|
822
862
|
const R = shared.ctx.r, cut = shared.ctx.cut, nA = R.floors.length, vMin = Math.min(...R.walls.map((w) => w.axis === "u" ? w.v0 : Math.min(w.v0, w.v1)));
|
|
823
863
|
const corners = /* @__PURE__ */ new Map();
|
|
864
|
+
const looks = /* @__PURE__ */ new Map();
|
|
824
865
|
for (const w of R.walls) {
|
|
825
|
-
const f = w.floor;
|
|
866
|
+
const f = w.floor, colliders = shared.ctx.colliders;
|
|
826
867
|
cursor.group = "f" + f;
|
|
827
868
|
cursor.pc = pieceOf(w);
|
|
828
869
|
const y0 = Y0(f), pitch = f + 1 < nA ? Y0(f + 1) - y0 : Infinity, th = w.thickness || 0.15, alongU = w.axis === "u";
|
|
@@ -830,7 +871,11 @@ function installHouseWalls(K, shared) {
|
|
|
830
871
|
const hh = cut ? Math.min(h, 1.2) : h, L = alongU ? w.v0 : w.u0, s0 = Math.min(alongU ? w.u0 : w.v0, alongU ? w.u1 : w.v1), s1 = Math.max(alongU ? w.u0 : w.v0, alongU ? w.u1 : w.v1);
|
|
831
872
|
const front = alongU && Math.abs(L - vMin) < 0.05;
|
|
832
873
|
const sideL = sideOf(w.sides[0], front), sideH = sideOf(w.sides[1], front);
|
|
833
|
-
|
|
874
|
+
if (w.id) {
|
|
875
|
+
const face = sideL.exterior ? sideL : sideH;
|
|
876
|
+
looks.set(w.id, { mat: face.mat, color: face.color, top: y0 + hh });
|
|
877
|
+
}
|
|
878
|
+
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 });
|
|
834
879
|
if (w.type === "railing") {
|
|
835
880
|
const c0 = shared.ctx.colors.metal != null ? shared.ctx.colors.metal : 9080466;
|
|
836
881
|
const sx = alongU ? 1 : 0, sz = alongU ? 0 : 1, len = s1 - s0, n = Math.max(1, Math.round(len / 1.4));
|
|
@@ -876,8 +921,28 @@ function installHouseWalls(K, shared) {
|
|
|
876
921
|
cursor.group = "f" + e.f;
|
|
877
922
|
bx(e.color.mat, e.pu - e.th / 2, e.y0, e.pv - e.th / 2, e.pu + e.th / 2, e.y0 + e.hh, e.pv + e.th / 2, e.color.color);
|
|
878
923
|
}
|
|
924
|
+
if (shared.ctx.showPillars) wallPillars(looks);
|
|
925
|
+
}
|
|
926
|
+
const PILLAR_IN_WALL = /^(wall_column_|column_\d|jamb_column_)/;
|
|
927
|
+
const wallOf = (pillar, parts) => {
|
|
928
|
+
const u = (pillar.aabb[0] + pillar.aabb[2]) / 2, v = (pillar.aabb[1] + pillar.aabb[3]) / 2;
|
|
929
|
+
return parts.find((q) => (q.role === "wall" || q.role === "partition") && q.assembly !== void 0 && q.floor === pillar.floor && u >= q.aabb[0] - 1e-3 && u <= q.aabb[2] + 1e-3 && v >= q.aabb[1] - 1e-3 && v <= q.aabb[3] + 1e-3);
|
|
930
|
+
};
|
|
931
|
+
function wallPillars(looks) {
|
|
932
|
+
const parts = Object.values(shared.ctx.structureIndex);
|
|
933
|
+
for (const e of parts) {
|
|
934
|
+
if (e.role !== "column" || !PILLAR_IN_WALL.test(e.id)) continue;
|
|
935
|
+
const host = wallOf(e, parts);
|
|
936
|
+
const look = host && looks.get(host.id);
|
|
937
|
+
if (!host || !look) continue;
|
|
938
|
+
cursor.group = "f" + e.floor;
|
|
939
|
+
cursor.pc = structurePiece(host.id);
|
|
940
|
+
bx(look.mat, e.aabb[0], e.y0, e.aabb[1], e.aabb[2], Math.min(e.y1, look.top), e.aabb[3], sh(look.color != null ? look.color : 15262420, 0.93));
|
|
941
|
+
}
|
|
942
|
+
cursor.pc = null;
|
|
879
943
|
}
|
|
880
|
-
|
|
944
|
+
const defined = { wallBox, sideOf, pieceOf, nearestWall, walls, wallPillars };
|
|
945
|
+
Object.assign(K, defined);
|
|
881
946
|
}
|
|
882
947
|
|
|
883
948
|
// src/house/doors.ts
|
|
@@ -896,7 +961,7 @@ function installHouseDoors(K, shared) {
|
|
|
896
961
|
}
|
|
897
962
|
shared.doorState = /* @__PURE__ */ new Map();
|
|
898
963
|
function doors() {
|
|
899
|
-
shared.ctx.leaves = [];
|
|
964
|
+
const leaves = shared.ctx.leaves = [], doorState = shared.doorState, colliders = shared.ctx.colliders;
|
|
900
965
|
const R = shared.ctx.r, cut = shared.ctx.cut, C = shared.ctx.colors, wood = C.wood != null ? C.wood : 8016948, frame = sh(wood, 0.55);
|
|
901
966
|
for (const p of R.doors) {
|
|
902
967
|
const f = p.floor;
|
|
@@ -927,21 +992,21 @@ function installHouseDoors(K, shared) {
|
|
|
927
992
|
}
|
|
928
993
|
const leaf = (u0, u1, y_0, y_1, tt, color, mat = "wood") => alongU ? bx(mat, u0, y0 + y_0, L - tt / 2, u1, y0 + y_1, L + tt / 2, color) : bx(mat, L - tt / 2, y0 + y_0, u0, L + tt / 2, y0 + y_1, u1, color);
|
|
929
994
|
const extC = wood;
|
|
930
|
-
const open0 = p.blocked ? false :
|
|
931
|
-
|
|
995
|
+
const open0 = p.blocked ? false : doorState.has(p.id) ? doorState.get(p.id) === true : !!p.open;
|
|
996
|
+
doorState.set(p.id, open0);
|
|
932
997
|
const dc = alongU ? [p.at, L] : [L, p.at];
|
|
933
|
-
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 };
|
|
998
|
+
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 };
|
|
934
999
|
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 };
|
|
935
|
-
|
|
1000
|
+
colliders.push(colR);
|
|
936
1001
|
fo.col = colR;
|
|
937
1002
|
const leafBox = (hu, d0, d1, y_0, y_1, tt, color, mat) => alongU ? bx(mat, d0, y_0, -tt / 2, d1, y_1, tt / 2, color) : bx(mat, -tt / 2, y_0, d0, tt / 2, y_1, d1, color);
|
|
938
|
-
const
|
|
1003
|
+
const newGroup2 = (k, hu, topY) => {
|
|
939
1004
|
cursor.group = "dyn:" + p.id + ":" + k;
|
|
940
1005
|
fo.groups.push({ name: cursor.group, pos: alongU ? [hu, topY != null ? y0 + topY : y0, L] : [L, topY != null ? y0 + topY : y0, hu] });
|
|
941
1006
|
};
|
|
942
1007
|
if (p.model === "steel") {
|
|
943
|
-
const light = [14276044, 13223615, 14999766], pal = ((R.seed | 0) + p.id.length * 7) % 4, color = pal === 3 ? wood : light[pal], mid = (a + b) / 2;
|
|
944
|
-
|
|
1008
|
+
const light = [14276044, 13223615, 14999766], pal = ((Number(R.seed) | 0) + p.id.length * 7) % 4, color = pal === 3 ? wood : light[pal], mid = (a + b) / 2;
|
|
1009
|
+
newGroup2(0, mid, visH);
|
|
945
1010
|
const la = a + jw - mid, lb = b - jw - mid, nSec = Math.max(4, Math.round(visH / 0.5)), hs = visH / nSec, grv = sh(color, 0.55);
|
|
946
1011
|
leafBox(0, la, lb, -visH, 0, 0.05, color, "metal");
|
|
947
1012
|
for (let k = 1; k < nSec; k++) leafBox(0, la, lb, -k * hs - 0.012, -k * hs + 0.012, 0.07, grv, "metal");
|
|
@@ -956,7 +1021,7 @@ function installHouseDoors(K, shared) {
|
|
|
956
1021
|
for (let k = 0; k < nf; k++) {
|
|
957
1022
|
const u0 = nf === 2 ? k ? (aa + bb) / 2 : aa : aa, u1 = nf === 2 ? k ? bb : (aa + bb) / 2 : bb, color = p.exterior ? extC : wood;
|
|
958
1023
|
const hingeAt = nf === 2 ? k ? u1 : u0 : p.hinge === "end" ? u1 : u0, dir = hingeAt === u0 ? 1 : -1, len = u1 - u0;
|
|
959
|
-
|
|
1024
|
+
newGroup2(k, hingeAt);
|
|
960
1025
|
const d0 = dir > 0 ? 5e-3 : -len + 5e-3, d1 = dir > 0 ? len - 5e-3 : -5e-3;
|
|
961
1026
|
leafBox(hingeAt, d0, d1, 0, visH, 0.04, color, PMAT);
|
|
962
1027
|
{
|
|
@@ -992,7 +1057,7 @@ function installHouseDoors(K, shared) {
|
|
|
992
1057
|
fo.rot = Math.atan2(n[0] * A[1] - n[1] * A[0], A[0] * n[0] + A[1] * n[1]);
|
|
993
1058
|
}
|
|
994
1059
|
}
|
|
995
|
-
|
|
1060
|
+
leaves.push(fo);
|
|
996
1061
|
cursor.group = "f" + f;
|
|
997
1062
|
if (p.blocked) {
|
|
998
1063
|
part("window_boards", [0, 0, 0], () => {
|
|
@@ -1020,11 +1085,12 @@ function installHouseDoors(K, shared) {
|
|
|
1020
1085
|
}
|
|
1021
1086
|
}
|
|
1022
1087
|
}, { id: "boards:" + p.id }, "f" + f);
|
|
1023
|
-
|
|
1088
|
+
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 });
|
|
1024
1089
|
}
|
|
1025
1090
|
}
|
|
1026
1091
|
}
|
|
1027
|
-
|
|
1092
|
+
const defined = { doorLineSides, doors };
|
|
1093
|
+
Object.assign(K, defined);
|
|
1028
1094
|
}
|
|
1029
1095
|
|
|
1030
1096
|
// src/house/windows.ts
|
|
@@ -1084,7 +1150,8 @@ function installHouseWindows(K, shared) {
|
|
|
1084
1150
|
}
|
|
1085
1151
|
}
|
|
1086
1152
|
}
|
|
1087
|
-
|
|
1153
|
+
const defined = { FRAME_COLORS, SILL_COLORS, windows };
|
|
1154
|
+
Object.assign(K, defined);
|
|
1088
1155
|
}
|
|
1089
1156
|
|
|
1090
1157
|
// src/house/floors.ts
|
|
@@ -1094,7 +1161,7 @@ function installHouseFloors(K, shared) {
|
|
|
1094
1161
|
if (shared.ctx._flights && shared.ctx._flights.r === shared.ctx.r) return shared.ctx._flights.l;
|
|
1095
1162
|
const R = shared.ctx.r, mp = /* @__PURE__ */ new Map();
|
|
1096
1163
|
for (const m of R.items) {
|
|
1097
|
-
if (m.type !== "stairs" || !m.link) continue;
|
|
1164
|
+
if (m.type !== "stairs" || !m.link || typeof m.link !== "object") continue;
|
|
1098
1165
|
const k = [m.link.from, m.link.to, m.x.toFixed(2), m.z.toFixed(2), (m.ry || 0).toFixed(2)].join("|");
|
|
1099
1166
|
if (!mp.has(k)) mp.set(k, { m, from: m.link.from, to: m.link.to, rect: stairFootprint(m) });
|
|
1100
1167
|
}
|
|
@@ -1113,7 +1180,7 @@ function installHouseFloors(K, shared) {
|
|
|
1113
1180
|
}
|
|
1114
1181
|
const panelRects = (p) => p.footprint && p.footprint.length ? p.footprint : [p.aabb];
|
|
1115
1182
|
function tilesOf(parent, rc) {
|
|
1116
|
-
const ps = parent
|
|
1183
|
+
const ps = parent ? shared.ctx.panelsOf && shared.ctx.panelsOf.get(parent) : void 0;
|
|
1117
1184
|
if (!ps) return [[parent ? structurePiece(parent) : null, rc]];
|
|
1118
1185
|
const out = [], taken = [];
|
|
1119
1186
|
for (const p of ps) for (const q of panelRects(p)) {
|
|
@@ -1177,13 +1244,12 @@ function installHouseStairs(K, shared) {
|
|
|
1177
1244
|
const { rectsOf: rectsOf2, Y0, boxC, bx, cursor, flights, stairFootprint, structurePiece } = K;
|
|
1178
1245
|
const sh = (...a) => K.sh(...a);
|
|
1179
1246
|
function buildStairs() {
|
|
1180
|
-
const R = shared.ctx.r;
|
|
1181
|
-
shared.ctx.stairs = [];
|
|
1247
|
+
const R = shared.ctx.r, stairs = shared.ctx.stairs = [];
|
|
1182
1248
|
for (const vo of flights()) {
|
|
1183
1249
|
const m = vo.m, f = vo.from, Dr = m.d - (vo.LP || 0);
|
|
1184
1250
|
cursor.group = "f" + f;
|
|
1185
1251
|
cursor.pc = structurePiece("stairs_" + vo.from + "_" + vo.to);
|
|
1186
|
-
const y0 = Y0(f), H = Y0(
|
|
1252
|
+
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);
|
|
1187
1253
|
const wood = shared.ctx.colors.wood != null ? shared.ctx.colors.wood : 9071176, under = sh(wood, 0.7);
|
|
1188
1254
|
const P = (lx, lz) => [m.x + lx * c + lz * s, m.z - lx * s + lz * c];
|
|
1189
1255
|
const boxL = (mat, lx, y, lz, w, h, d, color, rx = 0) => {
|
|
@@ -1206,7 +1272,7 @@ function installHouseStairs(K, shared) {
|
|
|
1206
1272
|
}
|
|
1207
1273
|
}
|
|
1208
1274
|
cursor.pc = null;
|
|
1209
|
-
|
|
1275
|
+
stairs.push({ m, f, to: vo.to, y0, H, rect: stairFootprint(m), landingPoint: (vo.LP || 0) / m.d });
|
|
1210
1276
|
}
|
|
1211
1277
|
}
|
|
1212
1278
|
function elevator() {
|
|
@@ -1223,7 +1289,8 @@ function installHouseStairs(K, shared) {
|
|
|
1223
1289
|
}
|
|
1224
1290
|
}
|
|
1225
1291
|
}
|
|
1226
|
-
|
|
1292
|
+
const defined = { buildStairs, elevator };
|
|
1293
|
+
Object.assign(K, defined);
|
|
1227
1294
|
}
|
|
1228
1295
|
|
|
1229
1296
|
// src/lights/fixtures.ts
|
|
@@ -1263,14 +1330,15 @@ function installLightsFixtures(K, shared) {
|
|
|
1263
1330
|
c: (mat, x, y, z, r, h, color, seg) => api.cylinder(M, mat, x, y0 + y, z, r, h, color, 0, 0, seg),
|
|
1264
1331
|
e: (mat, x, y, z, r, h, color) => api.cylinder(M, mat, x, y0 + y - h / 2, z, r, h, color, 0, 0, "sphere"),
|
|
1265
1332
|
t(mat, p, q, r, color, seg) {
|
|
1333
|
+
const tc = color ?? NaN;
|
|
1266
1334
|
const dx = q[0] - p[0], dy = q[1] - p[1], dz = q[2] - p[2], L = Math.hypot(dx, dy, dz);
|
|
1267
1335
|
if (L < 1e-5) return;
|
|
1268
1336
|
const nx = dx / L, ny = dy / L, nz = dz / L;
|
|
1269
1337
|
if (Math.abs(nx) < 1e-4 && Math.abs(nz) < 1e-4) {
|
|
1270
|
-
api.cylinder(M, mat, p[0], y0 + Math.min(p[1], q[1]), p[2], r, L,
|
|
1338
|
+
api.cylinder(M, mat, p[0], y0 + Math.min(p[1], q[1]), p[2], r, L, tc, 0, 0, seg);
|
|
1271
1339
|
return;
|
|
1272
1340
|
}
|
|
1273
|
-
api.cylinder(M, mat, (p[0] + q[0]) / 2, y0 + (p[1] + q[1]) / 2, (p[2] + q[2]) / 2, r, L,
|
|
1341
|
+
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);
|
|
1274
1342
|
},
|
|
1275
1343
|
polyFace: (mat, pts, color, hint) => polyFace(mat, pts.map((p) => W(p[0], p[1], p[2])), color, hint && [hint[0] * c + hint[2] * s, hint[1], -hint[0] * s + hint[2] * c]),
|
|
1276
1344
|
part(type, lx, ly, lz, fn, meta) {
|
|
@@ -1449,7 +1517,8 @@ function installLightsFixtures(K, shared) {
|
|
|
1449
1517
|
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 });
|
|
1450
1518
|
}
|
|
1451
1519
|
}
|
|
1452
|
-
|
|
1520
|
+
const defined = { hashString, rngString, SEED, STYLE, kit2, arcPoints, TEMP_WARM, TEMP_NEUTRAL, TEMP_COOL, colorTemperature, lightStyle, ceilingLamp, tableLamp, floorLamp, sconce, outdoorLamp, lightSwitch };
|
|
1521
|
+
Object.assign(K, defined);
|
|
1453
1522
|
}
|
|
1454
1523
|
|
|
1455
1524
|
// src/lights/decor.ts
|
|
@@ -1516,7 +1585,8 @@ function installLightsDecor(K, shared) {
|
|
|
1516
1585
|
void sd;
|
|
1517
1586
|
}
|
|
1518
1587
|
}
|
|
1519
|
-
|
|
1588
|
+
const defined = { decorLights };
|
|
1589
|
+
Object.assign(K, defined);
|
|
1520
1590
|
}
|
|
1521
1591
|
|
|
1522
1592
|
// src/lot/terrain.ts
|
|
@@ -1569,7 +1639,8 @@ function installLotTerrain(K, shared) {
|
|
|
1569
1639
|
if (x < b) out.push([x, b]);
|
|
1570
1640
|
return out.filter((q) => q[1] - q[0] > 0.3);
|
|
1571
1641
|
}
|
|
1572
|
-
|
|
1642
|
+
const defined = { terrain, freeSpans };
|
|
1643
|
+
Object.assign(K, defined);
|
|
1573
1644
|
}
|
|
1574
1645
|
|
|
1575
1646
|
// src/lot/perimeter.ts
|
|
@@ -1589,7 +1660,7 @@ function installLotPerimeter(K, shared) {
|
|
|
1589
1660
|
for (const s of lt.perimeter) {
|
|
1590
1661
|
const alongU = Math.abs(s.v1 - s.v0) < EPS, 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);
|
|
1591
1662
|
cursor.pc = pieceRecord("lot_wall:" + s.id, s.type === "wall" ? "brick" : s.type === "fence" ? "wood_soft" : "steel", null, { tags: ["wall"] });
|
|
1592
|
-
const th = s.thickness || 0.15, h = s.height, color = colorOf(s.color)
|
|
1663
|
+
const th = s.thickness || 0.15, h = s.height, color = colorOf(s.color) ?? (C.wall || 12104874), len = b - a;
|
|
1593
1664
|
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);
|
|
1594
1665
|
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 };
|
|
1595
1666
|
shared.ctx.colliders.push(col);
|
|
@@ -1663,7 +1734,8 @@ function installLotPerimeter(K, shared) {
|
|
|
1663
1734
|
}
|
|
1664
1735
|
}
|
|
1665
1736
|
}
|
|
1666
|
-
|
|
1737
|
+
const defined = { perimeter, paths };
|
|
1738
|
+
Object.assign(K, defined);
|
|
1667
1739
|
}
|
|
1668
1740
|
|
|
1669
1741
|
// src/lot/gates.ts
|
|
@@ -1679,7 +1751,7 @@ function installLotGates(K, shared) {
|
|
|
1679
1751
|
cursor.group = "lot";
|
|
1680
1752
|
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;
|
|
1681
1753
|
for (const g of lt.gates) {
|
|
1682
|
-
const gc = colorOf(g.color)
|
|
1754
|
+
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";
|
|
1683
1755
|
const sd = cz - v >= 0 ? 1 : -1;
|
|
1684
1756
|
const pil = (x0, x1, high) => {
|
|
1685
1757
|
bx("plaster", x0, 0, v - 0.13, x1, high, v + 0.13, wall);
|
|
@@ -1751,7 +1823,8 @@ function installLotGates(K, shared) {
|
|
|
1751
1823
|
if (!g.open || ped) shared.ctx.colliders.push({ type: "gate", f: -1, x0: a, z0: v - 0.1, x1: b, z1: v + 0.1 });
|
|
1752
1824
|
}
|
|
1753
1825
|
}
|
|
1754
|
-
|
|
1826
|
+
const defined = { slideDirection, gates };
|
|
1827
|
+
Object.assign(K, defined);
|
|
1755
1828
|
}
|
|
1756
1829
|
|
|
1757
1830
|
// src/roof/roofs.ts
|
|
@@ -1765,13 +1838,13 @@ function installRoofRoofs(K, shared) {
|
|
|
1765
1838
|
function roofs() {
|
|
1766
1839
|
const R = shared.ctx.r, F = R.facade, C = shared.ctx.colors, nA = R.floors.length, type = F.roof;
|
|
1767
1840
|
cursor.group = "roof";
|
|
1768
|
-
shared.ctx.roofRects = [];
|
|
1769
|
-
shared.ctx.gutter = gutterConfig();
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1841
|
+
const roofRects = shared.ctx.roofRects = [];
|
|
1842
|
+
const G = shared.ctx.gutter = gutterConfig();
|
|
1843
|
+
G.ncond = 0;
|
|
1844
|
+
G.nbuz = 0;
|
|
1845
|
+
G.bz = /* @__PURE__ */ new Set();
|
|
1773
1846
|
shared.ctx.gutterInfo = { gutters: [], downpipes: [], drains: [] };
|
|
1774
|
-
const roofColor = C.roof != null ? C.roof : 11031610, gable = (R.seed | 0) % 2 === 0;
|
|
1847
|
+
const roofColor = C.roof != null ? C.roof : 11031610, gable = (Number(R.seed) | 0) % 2 === 0;
|
|
1775
1848
|
for (let f = 0; f < nA; f++) {
|
|
1776
1849
|
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);
|
|
1777
1850
|
if (!rs.length) continue;
|
|
@@ -1793,7 +1866,7 @@ function installRoofRoofs(K, shared) {
|
|
|
1793
1866
|
return Y0(f) + Math.max(...cs.map((c) => c.ceiling)) + 0.2;
|
|
1794
1867
|
};
|
|
1795
1868
|
if (type === "slab") {
|
|
1796
|
-
for (let j = 0; j < nz; j++) for (let i = 0; i < nx; i++) if (O(j, i))
|
|
1869
|
+
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 });
|
|
1797
1870
|
slabs(f, xs, zs, O, U, nx, nz, full, pe, C);
|
|
1798
1871
|
cursor.pc = null;
|
|
1799
1872
|
continue;
|
|
@@ -1816,16 +1889,16 @@ function installRoofRoofs(K, shared) {
|
|
|
1816
1889
|
if (U(q.j0 - 1, i)) touchesU[1] = 1;
|
|
1817
1890
|
if (U(q.j1 + 1, i)) touchesU[3] = 1;
|
|
1818
1891
|
}
|
|
1819
|
-
|
|
1892
|
+
roofRects.push({ f, r: [x0, z0, x1, z1], touchesU });
|
|
1820
1893
|
const ybq = pe(x0, z0, x1, z1);
|
|
1821
1894
|
roofRect(type, x0, z0, x1, z1, ybq, roofColor, gable && single, F, touchesU);
|
|
1822
1895
|
cursor.pc = null;
|
|
1823
|
-
if (
|
|
1896
|
+
if (G.on) gutter(type, f, x0, z0, x1, z1, ybq, touchesU);
|
|
1824
1897
|
}
|
|
1825
1898
|
}
|
|
1826
1899
|
for (const e of shared.ctx.outbuildingList || []) {
|
|
1827
1900
|
const [x0, z0, x1, z1] = e.aabb, yb = Y0(0) + (e.ceiling || 2.6) + 0.2;
|
|
1828
|
-
|
|
1901
|
+
roofRects.push({ f: 0, r: [x0, z0, x1, z1], outbuilding: e.id });
|
|
1829
1902
|
if (type === "slab") {
|
|
1830
1903
|
const c = C.facade != null ? C.facade : 14209216;
|
|
1831
1904
|
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));
|
|
@@ -1836,13 +1909,15 @@ function installRoofRoofs(K, shared) {
|
|
|
1836
1909
|
roofRect(type, x0, z0, x1, z1, yb, roofColor, true, F, [0, 0, 0, 0]);
|
|
1837
1910
|
cursor.pc = null;
|
|
1838
1911
|
shared.ctx.noPiece = false;
|
|
1839
|
-
if (
|
|
1912
|
+
if (G.on) gutter(type, 0, x0, z0, x1, z1, yb, [0, 0, 0, 0]);
|
|
1840
1913
|
}
|
|
1841
1914
|
}
|
|
1842
|
-
|
|
1915
|
+
const defined = { roofs };
|
|
1916
|
+
Object.assign(K, defined);
|
|
1843
1917
|
}
|
|
1844
1918
|
|
|
1845
1919
|
// src/roof/gutters.ts
|
|
1920
|
+
var paletteMeta = (colors) => colors.meta;
|
|
1846
1921
|
function installRoofGutters(K, shared) {
|
|
1847
1922
|
const { boxC, bx, cursor, roomAt } = K;
|
|
1848
1923
|
const sh = (...a) => K.sh(...a);
|
|
@@ -1859,7 +1934,7 @@ function installRoofGutters(K, shared) {
|
|
|
1859
1934
|
const draw = rnd() < p, light = rnd() < 0.6;
|
|
1860
1935
|
void draw;
|
|
1861
1936
|
const on = true;
|
|
1862
|
-
return { on, rnd, color: high ? 3816770 : light ? 15527921 : 10857392, bad: (shared.ctx.colors
|
|
1937
|
+
return { on, rnd, color: high ? 3816770 : light ? 15527921 : 10857392, bad: paletteMeta(shared.ctx.colors)?.state === "abandoned" || R.state === "abandoned", fallback: false };
|
|
1863
1938
|
}
|
|
1864
1939
|
function gutter(type, f, X0, Z0, X1, Z1, yb, touchesU) {
|
|
1865
1940
|
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;
|
|
@@ -1901,7 +1976,7 @@ function installRoofGutters(K, shared) {
|
|
|
1901
1976
|
const px = cx + sx * 0.06, pz = cz + sz * 0.06;
|
|
1902
1977
|
if (!freeAt(px, pz, sx, sz)) return false;
|
|
1903
1978
|
const floats = G.bad && G.ncond === 1, yt = yb - 0.1, ybx = floats ? 0.7 : 0.04;
|
|
1904
|
-
G.ncond
|
|
1979
|
+
G.ncond = (G.ncond ?? 0) + 1;
|
|
1905
1980
|
if (run2 >= 2) boxC("plain", (sides[run2][4] + px) / 2, yt, pz, Math.abs(sides[run2][4] - px), 0.07, 0.07, c);
|
|
1906
1981
|
else boxC("plain", px, yt, (sides[run2][4] + pz) / 2, 0.07, 0.07, Math.abs(sides[run2][4] - pz), c);
|
|
1907
1982
|
boxC("plain", px, (ybx + yt) / 2, pz, 0.08, yt - ybx, 0.08, c);
|
|
@@ -1935,7 +2010,7 @@ function installRoofGutters(K, shared) {
|
|
|
1935
2010
|
function drain(x, z, px, pz, c) {
|
|
1936
2011
|
const g0 = cursor.group;
|
|
1937
2012
|
cursor.group = "f0";
|
|
1938
|
-
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));
|
|
2013
|
+
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));
|
|
1939
2014
|
const t = 0.045;
|
|
1940
2015
|
bx("plain", x - 0.12, 0, z - 0.12, x + 0.12, t - 6e-3, z + 0.12, 12170668);
|
|
1941
2016
|
bx("metal", x - 0.11, t, z - 0.11, x + 0.11, t + 0.012, z + 0.11, 5922145);
|
|
@@ -1946,7 +2021,8 @@ function installRoofGutters(K, shared) {
|
|
|
1946
2021
|
bx("metal", x - 0.085, t + 0.012, z - 6e-3, x + 0.085, t + 0.02, z + 6e-3, 9080466);
|
|
1947
2022
|
cursor.group = g0;
|
|
1948
2023
|
}
|
|
1949
|
-
|
|
2024
|
+
const defined = { gutterConfig, gutter, drain };
|
|
2025
|
+
Object.assign(K, defined);
|
|
1950
2026
|
}
|
|
1951
2027
|
|
|
1952
2028
|
// src/roof/slabs.ts
|
|
@@ -1980,15 +2056,16 @@ function installRoofSlabs(K, shared) {
|
|
|
1980
2056
|
side(free(j, i + 1), x1 + o - t, z0 - ez0, x1 + o, z1 + ez1);
|
|
1981
2057
|
side(free(j - 1, i), x0 - ex0, z0 - o, x1 + ex1, z0 - o + t);
|
|
1982
2058
|
side(free(j + 1, i), x0 - ex0, z1 + o - t, x1 + ex1, z1 + o);
|
|
1983
|
-
|
|
2059
|
+
const G = shared.ctx.gutter;
|
|
2060
|
+
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]]) {
|
|
1984
2061
|
const kd = f + ":" + dx + ":" + dz;
|
|
1985
|
-
if (!ok ||
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
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 =
|
|
2062
|
+
if (!ok || G.bz.has(kd)) continue;
|
|
2063
|
+
G.bz.add(kd);
|
|
2064
|
+
G.nbuz = (G.nbuz ?? 0) + 1;
|
|
2065
|
+
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;
|
|
1989
2066
|
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);
|
|
1990
2067
|
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));
|
|
1991
|
-
if (
|
|
2068
|
+
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);
|
|
1992
2069
|
{
|
|
1993
2070
|
const tx = ex + dx * 0.38, tz = ez + dz * 0.38;
|
|
1994
2071
|
let lv = true;
|
|
@@ -2008,7 +2085,8 @@ function installRoofSlabs(K, shared) {
|
|
|
2008
2085
|
}
|
|
2009
2086
|
}
|
|
2010
2087
|
}
|
|
2011
|
-
|
|
2088
|
+
const defined = { slabs };
|
|
2089
|
+
Object.assign(K, defined);
|
|
2012
2090
|
}
|
|
2013
2091
|
|
|
2014
2092
|
// src/roof/tiles.ts
|
|
@@ -2141,7 +2219,8 @@ function installRoofTiles(K, shared) {
|
|
|
2141
2219
|
}
|
|
2142
2220
|
return m ? structurePiece(m.id) : null;
|
|
2143
2221
|
}
|
|
2144
|
-
|
|
2222
|
+
const defined = { R_STYLE, tileRelief, ridge, pieceOfPane };
|
|
2223
|
+
Object.assign(K, defined);
|
|
2145
2224
|
}
|
|
2146
2225
|
|
|
2147
2226
|
// src/roof/rect.ts
|
|
@@ -2187,7 +2266,7 @@ function installRoofRect(K, shared) {
|
|
|
2187
2266
|
}
|
|
2188
2267
|
const rm = alongX ? dz / 2 : dx / 2;
|
|
2189
2268
|
{
|
|
2190
|
-
const
|
|
2269
|
+
const roofRects = shared.ctx.roofRects, rr = roofRects[roofRects.length - 1];
|
|
2191
2270
|
if (rr && !rr.yb) Object.assign(rr, { yb, tp, gable: !!gable, alongX, exterior: [x0, z0, x1, z1], rm });
|
|
2192
2271
|
}
|
|
2193
2272
|
if (gable) {
|
|
@@ -2224,7 +2303,8 @@ function installRoofRect(K, shared) {
|
|
|
2224
2303
|
}
|
|
2225
2304
|
}
|
|
2226
2305
|
}
|
|
2227
|
-
|
|
2306
|
+
const defined = { roofRect };
|
|
2307
|
+
Object.assign(K, defined);
|
|
2228
2308
|
}
|
|
2229
2309
|
|
|
2230
2310
|
// src/mirrors.ts
|
|
@@ -2235,9 +2315,11 @@ function installMirrors(K, shared) {
|
|
|
2235
2315
|
function mirrorEnv() {
|
|
2236
2316
|
if (shared.mirrorEnv) return shared.mirrorEnv;
|
|
2237
2317
|
const mk = (f) => {
|
|
2318
|
+
if (!DOC) throw new Error("game-floorplan-three: the mirrors need a document (options.document)");
|
|
2238
2319
|
const c = DOC.createElement("canvas");
|
|
2239
2320
|
c.width = c.height = 64;
|
|
2240
2321
|
const g = c.getContext("2d");
|
|
2322
|
+
if (!g) throw new Error("game-floorplan-three: no 2d canvas context");
|
|
2241
2323
|
f(g);
|
|
2242
2324
|
return c;
|
|
2243
2325
|
};
|
|
@@ -2296,7 +2378,7 @@ function installMirrors(K, shared) {
|
|
|
2296
2378
|
B.N.push(v.x, v.y, v.z);
|
|
2297
2379
|
B.U.push(ua.getX(i), ua.getY(i));
|
|
2298
2380
|
}
|
|
2299
|
-
for (const k of geo.index
|
|
2381
|
+
for (const k of geo.index?.array ?? []) B.I.push(B.nv + k);
|
|
2300
2382
|
B.nv += pa.count;
|
|
2301
2383
|
geo.dispose();
|
|
2302
2384
|
}
|
|
@@ -2374,10 +2456,12 @@ function installMirrors(K, shared) {
|
|
|
2374
2456
|
m.fake.visible = !on;
|
|
2375
2457
|
}
|
|
2376
2458
|
}
|
|
2377
|
-
|
|
2459
|
+
const defined = { mirrorEnv, newMirrorState, assembleMirrors, floorAtY, chooseMirror };
|
|
2460
|
+
Object.assign(K, defined);
|
|
2378
2461
|
}
|
|
2379
2462
|
|
|
2380
2463
|
// src/cars.ts
|
|
2464
|
+
import { isMesh } from "@adatechnology/game-shapes-three";
|
|
2381
2465
|
function installCars(K, shared) {
|
|
2382
2466
|
const { THREE, FLEET, _Y } = K;
|
|
2383
2467
|
const CARS = [];
|
|
@@ -2387,13 +2471,16 @@ function installCars(K, shared) {
|
|
|
2387
2471
|
high: ["electric_hatch", "hybrid_suv", "midsize_suv", "v8_coupe", "large_suv", "midsize_pickup", "crossover_pickup", "fastback_sedan"]
|
|
2388
2472
|
}, K.cfg.carKinds);
|
|
2389
2473
|
const CAR_CACHE = /* @__PURE__ */ new Map();
|
|
2390
|
-
function materialSignature(
|
|
2474
|
+
function materialSignature(material) {
|
|
2475
|
+
const m = material;
|
|
2391
2476
|
const f = (v) => v == null ? "" : typeof v === "number" ? v.toFixed(3) : v.isColor ? v.getHexString() : v.uuid || String(v);
|
|
2392
2477
|
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("|");
|
|
2393
2478
|
}
|
|
2394
2479
|
const BUCKETS = /* @__PURE__ */ new Map();
|
|
2395
|
-
function bucketMaterial(
|
|
2396
|
-
if (
|
|
2480
|
+
function bucketMaterial(material) {
|
|
2481
|
+
if (material.type !== "MeshStandardMaterial") return null;
|
|
2482
|
+
const m = material;
|
|
2483
|
+
if (m.map || m.alphaTest || m.vertexColors || !m.color) return null;
|
|
2397
2484
|
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 : "");
|
|
2398
2485
|
let b = BUCKETS.get(sig);
|
|
2399
2486
|
if (!b) {
|
|
@@ -2405,7 +2492,7 @@ function installCars(K, shared) {
|
|
|
2405
2492
|
}
|
|
2406
2493
|
function carModel(k, seed) {
|
|
2407
2494
|
const kc = k + "|" + shared.quality + "|" + (seed || 0);
|
|
2408
|
-
if (CAR_CACHE.has(kc)) return CAR_CACHE.get(kc);
|
|
2495
|
+
if (CAR_CACHE.has(kc)) return CAR_CACHE.get(kc) ?? null;
|
|
2409
2496
|
if (!FLEET) return null;
|
|
2410
2497
|
let res = null;
|
|
2411
2498
|
try {
|
|
@@ -2413,8 +2500,10 @@ function installCars(K, shared) {
|
|
|
2413
2500
|
c.root.updateMatrixWorld(true);
|
|
2414
2501
|
const inv = new THREE.Matrix4();
|
|
2415
2502
|
const byMaterial = /* @__PURE__ */ new Map(), tmp = new THREE.Matrix4(), v = new THREE.Vector3(), nm = new THREE.Matrix3(), bb = new THREE.Box3();
|
|
2416
|
-
c.g.traverse((
|
|
2417
|
-
if (!
|
|
2503
|
+
c.g.traverse((node) => {
|
|
2504
|
+
if (!isMesh(node)) return;
|
|
2505
|
+
const o = node;
|
|
2506
|
+
if (o.isInstancedMesh || o.isSkinnedMesh || !o.geometry || !o.geometry.attributes.position) return;
|
|
2418
2507
|
for (let p = o; p; p = p.parent) if (p.visible === false) return;
|
|
2419
2508
|
const mats = Array.isArray(o.material) ? o.material : [o.material];
|
|
2420
2509
|
let geo = o.geometry;
|
|
@@ -2428,7 +2517,7 @@ function installCars(K, shared) {
|
|
|
2428
2517
|
const pa = geo.attributes.position, na = geo.attributes.normal, ua = geo.attributes.uv, total = pa.count;
|
|
2429
2518
|
const grs = Array.isArray(o.material) && o.geometry.groups.length ? o.geometry.groups : [{ start: 0, count: total, materialIndex: 0 }];
|
|
2430
2519
|
for (const gr of grs) {
|
|
2431
|
-
const m = mats[gr.materialIndex] || mats[0];
|
|
2520
|
+
const m = (gr.materialIndex != null ? mats[gr.materialIndex] : void 0) || mats[0];
|
|
2432
2521
|
if (!m) continue;
|
|
2433
2522
|
const a0 = Math.min(gr.start, total), n0 = Math.min(gr.count, total - a0) - Math.min(gr.count, total - a0) % 3;
|
|
2434
2523
|
if (n0 < 3) continue;
|
|
@@ -2529,7 +2618,10 @@ function installCars(K, shared) {
|
|
|
2529
2618
|
return g;
|
|
2530
2619
|
}
|
|
2531
2620
|
function assembleCars(groups) {
|
|
2532
|
-
if (shared.quality === "game")
|
|
2621
|
+
if (shared.quality === "game") {
|
|
2622
|
+
assembleMergedCars(groups);
|
|
2623
|
+
return;
|
|
2624
|
+
}
|
|
2533
2625
|
for (const C of CARS) {
|
|
2534
2626
|
const g = carGroup(C.k, C.w, C.d, C.seed);
|
|
2535
2627
|
if (!g) continue;
|
|
@@ -2580,7 +2672,8 @@ function installCars(K, shared) {
|
|
|
2580
2672
|
(groups[B.parent] || (groups[B.parent] = new THREE.Group())).add(m);
|
|
2581
2673
|
}
|
|
2582
2674
|
}
|
|
2583
|
-
|
|
2675
|
+
const defined = { CARS, CAR_BY_STYLE, CAR_CACHE, materialSignature, BUCKETS, bucketMaterial, carModel, carGroup, assembleCars, assembleMergedCars };
|
|
2676
|
+
Object.assign(K, defined);
|
|
2584
2677
|
}
|
|
2585
2678
|
|
|
2586
2679
|
// src/house/building.ts
|
|
@@ -2636,14 +2729,15 @@ function installHouseBuilding(K, shared) {
|
|
|
2636
2729
|
bx("plaster", Math.min(hall[0] - 3, color[0]), ytop, Math.min(un[1] ? unitBox(un[1])[1] : 0, el[1]), Math.max(color[2], un0[2]), ytop + 0.2, Math.max(un0[3], un[1] ? unitBox(un[1])[3] : 0), 11841704);
|
|
2637
2730
|
shared.ctx.limits = { x0: Math.min(hall[0] - 3, color[0]), z0: Math.min(el[1], un[1] ? unitBox(un[1])[1] : 0), x1: Math.max(color[2], un0[2]), z1: Math.max(un0[3], un[1] ? unitBox(un[1])[3] : 0) };
|
|
2638
2731
|
}
|
|
2639
|
-
|
|
2732
|
+
const defined = { building };
|
|
2733
|
+
Object.assign(K, defined);
|
|
2640
2734
|
}
|
|
2641
2735
|
|
|
2642
2736
|
// src/utilities/water.ts
|
|
2643
2737
|
function installUtilitiesWater(K, shared) {
|
|
2644
2738
|
const { THREE, _Y, _q, cursor, cylBase, part, pieceRecord, put } = K;
|
|
2645
2739
|
function createWater(r, state) {
|
|
2646
|
-
const H = r.utilities
|
|
2740
|
+
const H = r.utilities?.plumbing, cap = H ? +H.capacityL || 0 : 0, ls = { dry: [], full: [] }, points = {}, itemPoint = {};
|
|
2647
2741
|
if (H) for (const p of H.points) {
|
|
2648
2742
|
points[p.id] = p;
|
|
2649
2743
|
itemPoint[p.item] = p.id;
|
|
@@ -2732,14 +2826,14 @@ function installUtilitiesWater(K, shared) {
|
|
|
2732
2826
|
}
|
|
2733
2827
|
const _v3 = new THREE.Vector3();
|
|
2734
2828
|
function waterPipes() {
|
|
2735
|
-
const H = shared.ctx.r.utilities
|
|
2829
|
+
const H = shared.ctx.r.utilities?.plumbing;
|
|
2736
2830
|
if (!H || !H.visibleRuns) return;
|
|
2737
2831
|
const nA = shared.ctx.r.floors.length;
|
|
2738
2832
|
const groupOf = (c) => c && c.floor >= 0 ? "f" + Math.min(c.floor, nA - 1) : "lot", xyz = (p) => [p[0], p[2], p[1]];
|
|
2739
2833
|
for (const tr of H.visibleRuns) {
|
|
2740
2834
|
const pts = tr.points.map(xyz), d = tr.diameter || 0.025;
|
|
2741
2835
|
if (tr.exposed === "wall") {
|
|
2742
|
-
const pt = H.points.find((p) => p.run === tr.id), com = shared.ctx.roomById[tr.to], g2 = groupOf(com || pt && { floor: pt.floor });
|
|
2836
|
+
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 });
|
|
2743
2837
|
part("wall_pipe", [0, 0, 0], () => {
|
|
2744
2838
|
for (let i = 0; i + 1 < pts.length; i++) pipe(pts[i], pts[i + 1], d, PIPE_COLOR);
|
|
2745
2839
|
for (const p of pts) cylBase("plain", p[0], p[1] - d, p[2], d * 0.7, d * 2, PIPE_COLOR);
|
|
@@ -2761,7 +2855,8 @@ function installUtilitiesWater(K, shared) {
|
|
|
2761
2855
|
cursor.pc = null;
|
|
2762
2856
|
}
|
|
2763
2857
|
}
|
|
2764
|
-
|
|
2858
|
+
const defined = { createWater, PIPE_COLOR, pipe, _v3, waterPipes };
|
|
2859
|
+
Object.assign(K, defined);
|
|
2765
2860
|
}
|
|
2766
2861
|
|
|
2767
2862
|
// src/utilities/electrical.ts
|
|
@@ -2769,10 +2864,10 @@ function installUtilitiesElectrical(K, shared) {
|
|
|
2769
2864
|
const { _Y, _q, _v3, bx, cursor, cylBase, pieceRecord, put } = K;
|
|
2770
2865
|
const sh = (...a) => K.sh(...a);
|
|
2771
2866
|
function electricalStructure() {
|
|
2772
|
-
const
|
|
2867
|
+
const R = shared.ctx.r, E = R.utilities?.electrical;
|
|
2773
2868
|
shared.ctx.electricalInfo = null;
|
|
2774
2869
|
if (!E) return;
|
|
2775
|
-
const
|
|
2870
|
+
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 };
|
|
2776
2871
|
const en2 = E.serviceEntrance, KV = shared.ctx.iv ? shared.ctx.iv.plane : null;
|
|
2777
2872
|
const wireL = (a, b, r_ = 8e-3) => {
|
|
2778
2873
|
const L = Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
|
|
@@ -2877,7 +2972,8 @@ function installUtilitiesElectrical(K, shared) {
|
|
|
2877
2972
|
_q.setFromUnitVectors(_Y, _v3.set(dx / L, dy / L, dz / L));
|
|
2878
2973
|
put("plain", "cyl", (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2, _q, diameter, L, diameter, color);
|
|
2879
2974
|
}
|
|
2880
|
-
|
|
2975
|
+
const defined = { electricalStructure, pipe2 };
|
|
2976
|
+
Object.assign(K, defined);
|
|
2881
2977
|
}
|
|
2882
2978
|
|
|
2883
2979
|
// src/house/baseboard.ts
|
|
@@ -2915,7 +3011,8 @@ function installHouseBaseboard(K, shared) {
|
|
|
2915
3011
|
strip(W, y0, y0 + 0.045, 0, W, "sidewalk", cal);
|
|
2916
3012
|
}
|
|
2917
3013
|
}
|
|
2918
|
-
|
|
3014
|
+
const defined = { baseboardAndSidewalk };
|
|
3015
|
+
Object.assign(K, defined);
|
|
2919
3016
|
}
|
|
2920
3017
|
|
|
2921
3018
|
// src/utilities/solar.ts
|
|
@@ -2930,6 +3027,7 @@ function installUtilitiesSolar(K, shared) {
|
|
|
2930
3027
|
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);
|
|
2931
3028
|
continue;
|
|
2932
3029
|
}
|
|
3030
|
+
if (!rr.exterior || rr.tp == null || rr.rm == null) continue;
|
|
2933
3031
|
const [x0, z0, x1, z1] = rr.exterior;
|
|
2934
3032
|
if (u < x0 || u > x1 || v < z0 || v > z1) continue;
|
|
2935
3033
|
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);
|
|
@@ -2938,7 +3036,7 @@ function installUtilitiesSolar(K, shared) {
|
|
|
2938
3036
|
return y;
|
|
2939
3037
|
}
|
|
2940
3038
|
function solar() {
|
|
2941
|
-
const R = shared.ctx.r, S = R.utilities
|
|
3039
|
+
const R = shared.ctx.r, S = R.utilities?.solar;
|
|
2942
3040
|
shared.ctx.solarInfo = null;
|
|
2943
3041
|
if (!S || !S.panels || !S.panels.length) return;
|
|
2944
3042
|
cursor.group = "roof";
|
|
@@ -2981,13 +3079,14 @@ function installUtilitiesSolar(K, shared) {
|
|
|
2981
3079
|
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);
|
|
2982
3080
|
bx("emissive", iv.u - 0.03, y0 - 0.12, iv.v + fa0, iv.u + 0.03, y0 - 0.09, iv.v + fa1, 6479994);
|
|
2983
3081
|
}
|
|
2984
|
-
const top = Math.max(...(shared.ctx.roofRects || []).
|
|
3082
|
+
const top = Math.max(...(shared.ctx.roofRects || []).flatMap((t2) => t2.yb != null ? [t2.yb] : []), Y0(fa) + 2.8);
|
|
2985
3083
|
cylBase("plain", iv.u, y0 + h / 2, iv.v, 0.016, Math.max(0.2, top - 0.2 - (y0 + h / 2)), 15262936);
|
|
2986
3084
|
info.inverter = { id: iv.id, pos: [iv.u, y0, iv.v], side: iv.side, link: iv.link };
|
|
2987
3085
|
}
|
|
2988
3086
|
shared.ctx.solarInfo = info;
|
|
2989
3087
|
}
|
|
2990
|
-
|
|
3088
|
+
const defined = { roofHeightAt, solar };
|
|
3089
|
+
Object.assign(K, defined);
|
|
2991
3090
|
}
|
|
2992
3091
|
|
|
2993
3092
|
// src/house/outbuildings.ts
|
|
@@ -3002,7 +3101,7 @@ function installHouseOutbuildings(K, shared) {
|
|
|
3002
3101
|
counts.set(w.floor, i + 1);
|
|
3003
3102
|
return w.id ? w : Object.assign({}, w, { id: `wall_${w.floor}_${i}` });
|
|
3004
3103
|
}) });
|
|
3005
|
-
const E = (r.outbuildings || []).filter((e) => e && e.walls && e.walls.length && e.interior && e.interior.length);
|
|
3104
|
+
const E = (r.outbuildings || []).filter((e) => !!(e && e.walls && e.walls.length && e.interior && e.interior.length));
|
|
3006
3105
|
if (!E.length) return r;
|
|
3007
3106
|
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");
|
|
3008
3107
|
for (const e of E) {
|
|
@@ -3016,7 +3115,22 @@ function installHouseOutbuildings(K, shared) {
|
|
|
3016
3115
|
const alongU = p.axis === "u", below = p.pos < (alongU ? cz : cx);
|
|
3017
3116
|
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 });
|
|
3018
3117
|
}
|
|
3019
|
-
for (const j of e.windows || []) windows.push({
|
|
3118
|
+
for (const j of e.windows || []) windows.push({
|
|
3119
|
+
id: j.id,
|
|
3120
|
+
floor: 0,
|
|
3121
|
+
u: j.u,
|
|
3122
|
+
v: j.v,
|
|
3123
|
+
axis: j.axis,
|
|
3124
|
+
pos: j.pos,
|
|
3125
|
+
at: j.at,
|
|
3126
|
+
width: j.width,
|
|
3127
|
+
y0: j.y0 ?? 1,
|
|
3128
|
+
y1: j.y1 ?? 2,
|
|
3129
|
+
/* the structure always gives a window its sill and head (1.0, 2.0) */
|
|
3130
|
+
room: e.id,
|
|
3131
|
+
side: j.side,
|
|
3132
|
+
outbuilding: e.id
|
|
3133
|
+
});
|
|
3020
3134
|
(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" }));
|
|
3021
3135
|
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 });
|
|
3022
3136
|
}
|
|
@@ -3037,7 +3151,8 @@ function installHouseOutbuildings(K, shared) {
|
|
|
3037
3151
|
}
|
|
3038
3152
|
}
|
|
3039
3153
|
}
|
|
3040
|
-
|
|
3154
|
+
const defined = { OUTBUILDING_USE, applyOutbuildings, outbuildings };
|
|
3155
|
+
Object.assign(K, defined);
|
|
3041
3156
|
}
|
|
3042
3157
|
|
|
3043
3158
|
// src/furniture/api.ts
|
|
@@ -3102,7 +3217,8 @@ function installFurnitureApi(K, _shared) {
|
|
|
3102
3217
|
return { b: (mat, x, y, z, w, h, d, color, ry, rx, rz) => A.box(M, mat, x, y0 + y, z, w, h, d, color, ry || 0, rx || 0, rz || 0), c: (mat, x, y, z, r, h, color, rx, rz, seg) => A.cylinder(M, mat, x, y0 + y, z, r, h, color, rx || 0, rz || 0, seg), rnd: rngOf(M), wood: paletteColor(M, "wood", 8016948), met: paletteColor(M, "metal", 10133154) };
|
|
3103
3218
|
}
|
|
3104
3219
|
const PE = Math.PI / 2;
|
|
3105
|
-
|
|
3220
|
+
const defined = { MATERIAL_MAP, mm, LIGHTS, makeApi, sh, paletteColor, rngOf, kk, PE };
|
|
3221
|
+
Object.assign(K, defined);
|
|
3106
3222
|
}
|
|
3107
3223
|
|
|
3108
3224
|
// src/furniture/builders.ts
|
|
@@ -3230,7 +3346,7 @@ function installFurnitureBuilders(K, _shared) {
|
|
|
3230
3346
|
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);
|
|
3231
3347
|
},
|
|
3232
3348
|
wardrobe(M, A) {
|
|
3233
|
-
const { b: lb } = kk(M, A), w = M.w, d = M.d, h = M.h, wood =
|
|
3349
|
+
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));
|
|
3234
3350
|
lb("wood", 0, 0.06, 0, w, h - 0.06, d, wood);
|
|
3235
3351
|
lb("wood", 0, h, 0, w + 0.04, 0.04, d + 0.04, sh(wood, 0.8));
|
|
3236
3352
|
lb("wood", 0, 0, 0, w - 0.04, 0.06, d - 0.04, sh(wood, 0.4));
|
|
@@ -3622,7 +3738,8 @@ function installFurnitureBuilders(K, _shared) {
|
|
|
3622
3738
|
lb("metal", 0, h - 0.04, d / 2, w, 0.03, 0.03, 3815994);
|
|
3623
3739
|
}
|
|
3624
3740
|
};
|
|
3625
|
-
|
|
3741
|
+
const defined = { FURNITURE };
|
|
3742
|
+
Object.assign(K, defined);
|
|
3626
3743
|
}
|
|
3627
3744
|
|
|
3628
3745
|
// src/furniture/type-table.ts
|
|
@@ -3632,7 +3749,8 @@ function installFurnitureTypeTable(K, _shared) {
|
|
|
3632
3749
|
function typeTable(props) {
|
|
3633
3750
|
const B = props.builders, T = {};
|
|
3634
3751
|
const mv = (type, id) => {
|
|
3635
|
-
|
|
3752
|
+
const f = B[id || type];
|
|
3753
|
+
if (f) T[type] = { f, source: "props3d" };
|
|
3636
3754
|
};
|
|
3637
3755
|
const mine = (type, f, source = "game") => {
|
|
3638
3756
|
T[type] = { f, source };
|
|
@@ -3771,7 +3889,8 @@ function installFurnitureTypeTable(K, _shared) {
|
|
|
3771
3889
|
extraTypes(T, props);
|
|
3772
3890
|
return T;
|
|
3773
3891
|
}
|
|
3774
|
-
|
|
3892
|
+
const defined = { typeTable };
|
|
3893
|
+
Object.assign(K, defined);
|
|
3775
3894
|
}
|
|
3776
3895
|
|
|
3777
3896
|
// src/furniture/taps.ts
|
|
@@ -3835,7 +3954,8 @@ function installFurnitureTaps(K, shared) {
|
|
|
3835
3954
|
}, { id: id + "_a", target: id, hidden: true, fluid: "water" });
|
|
3836
3955
|
return id;
|
|
3837
3956
|
}
|
|
3838
|
-
|
|
3957
|
+
const defined = { counterTap, wallTap };
|
|
3958
|
+
Object.assign(K, defined);
|
|
3839
3959
|
}
|
|
3840
3960
|
|
|
3841
3961
|
// src/furniture/fixtures.ts
|
|
@@ -3948,7 +4068,7 @@ function installFurniturePlants(K, _shared) {
|
|
|
3948
4068
|
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;
|
|
3949
4069
|
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;
|
|
3950
4070
|
K2.e("plant", cx + dx, cy + dy + r * 0.5, cz + dz, r, alt, sh(green, f));
|
|
3951
|
-
if (o.flower && rnd() < o.flower) {
|
|
4071
|
+
if (o.flower && o.flowers && rnd() < o.flower) {
|
|
3952
4072
|
const fa = rnd() * 6.283;
|
|
3953
4073
|
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]);
|
|
3954
4074
|
}
|
|
@@ -4061,7 +4181,8 @@ function installFurniturePlants(K, _shared) {
|
|
|
4061
4181
|
else blobs(K2, x, bh - 0.05, z, 0.24 + rnd() * 0.08, 6, green, rnd, { flatten: true, flower: tp === "flower" ? 0.9 : 0.25, flowers: FLOWERS.slice(i % 3, i % 3 + 3) });
|
|
4062
4182
|
}
|
|
4063
4183
|
}
|
|
4064
|
-
|
|
4184
|
+
const defined = { GREENS, FLOWERS, blobs, potModel, arcLeaf, tuft, palm_tree, treeModel, shrubModel, potPlant, tablePot, planterModel };
|
|
4185
|
+
Object.assign(K, defined);
|
|
4065
4186
|
}
|
|
4066
4187
|
|
|
4067
4188
|
// src/furniture/yard.ts
|
|
@@ -4217,7 +4338,7 @@ function installFurnitureYard(K, shared) {
|
|
|
4217
4338
|
};
|
|
4218
4339
|
FURNITURE.mailbox = function(M, A) {
|
|
4219
4340
|
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");
|
|
4220
|
-
if (M.pole !== false && !(M.y > 0)) {
|
|
4341
|
+
if (M.pole !== false && !(M.y != null && M.y > 0)) {
|
|
4221
4342
|
K2.b("plain", 0, 0, -d / 2 - 0.1, 0.12, y, 0.12, 12104874);
|
|
4222
4343
|
}
|
|
4223
4344
|
K2.b("metal", 0, y, 0, w, h * 0.78, d, pc);
|
|
@@ -4237,7 +4358,8 @@ function installFurnitureYard(K, shared) {
|
|
|
4237
4358
|
);
|
|
4238
4359
|
K2.b("plain", 0, y + h * 0.62, d / 2 + 4e-3, 0.08, 0.05, 4e-3, 15921386);
|
|
4239
4360
|
};
|
|
4240
|
-
|
|
4361
|
+
const defined = { CLOTHES_COLORS, strip, garment };
|
|
4362
|
+
Object.assign(K, defined);
|
|
4241
4363
|
}
|
|
4242
4364
|
|
|
4243
4365
|
// src/furniture/extra-types.ts
|
|
@@ -4297,7 +4419,8 @@ function installFurnitureExtraTypes(K, _shared) {
|
|
|
4297
4419
|
tuft(K2, 0, 0, 0, Math.max(0.2, (M.w || 0.4) / 2), 16, 5212738, rnd);
|
|
4298
4420
|
});
|
|
4299
4421
|
}
|
|
4300
|
-
|
|
4422
|
+
const defined = { extraTypes };
|
|
4423
|
+
Object.assign(K, defined);
|
|
4301
4424
|
}
|
|
4302
4425
|
|
|
4303
4426
|
// src/furniture/place-items.ts
|
|
@@ -4319,8 +4442,8 @@ function installFurniturePlaceItems(K, shared) {
|
|
|
4319
4442
|
if (m.type === "stairs") continue;
|
|
4320
4443
|
const exterior = m.outdoor || m.floor < 0, f = exterior ? -1 : Math.min(m.floor, R.floors.length - 1);
|
|
4321
4444
|
cursor.group = exterior ? "lot" : "f" + f;
|
|
4322
|
-
const com = shared.ctx.roomById[m.room], base = exterior ? 0 : Y0(f);
|
|
4323
|
-
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)
|
|
4445
|
+
const com = m.room != null ? shared.ctx.roomById[m.room] : void 0, base = exterior ? 0 : Y0(f);
|
|
4446
|
+
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 };
|
|
4324
4447
|
if (m.category === "ground_cover" && m.polygon) {
|
|
4325
4448
|
const xs = m.polygon.map((p) => p[0]), zs = m.polygon.map((p) => p[1]);
|
|
4326
4449
|
M.x = (Math.min(...xs) + Math.max(...xs)) / 2;
|
|
@@ -4397,10 +4520,12 @@ function installFurniturePlaceItems(K, shared) {
|
|
|
4397
4520
|
boxC("plain", m.x, M.base + (m.y || 0) + h / 2, m.z, m.w, h, m.d, color, 0, m.ry || 0, 0);
|
|
4398
4521
|
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" });
|
|
4399
4522
|
}
|
|
4400
|
-
|
|
4523
|
+
const defined = { houseItems, waterTankOfHouse, hashColor, labeledBox };
|
|
4524
|
+
Object.assign(K, defined);
|
|
4401
4525
|
}
|
|
4402
4526
|
|
|
4403
4527
|
// src/vegetation/bridge.ts
|
|
4528
|
+
import { isMesh as isMesh2 } from "@adatechnology/game-shapes-three";
|
|
4404
4529
|
function installVegetationBridge(K, shared) {
|
|
4405
4530
|
const seedKey = (id) => K.seedKey(id);
|
|
4406
4531
|
const { THREE, SEED, rngString } = K;
|
|
@@ -4432,7 +4557,7 @@ function installVegetationBridge(K, shared) {
|
|
|
4432
4557
|
const ids = VEG_MAP[m.type], can = VEG_PLANTER[m.type];
|
|
4433
4558
|
if (!ids && !can) return false;
|
|
4434
4559
|
const rnd = rngString(SEED() + "|" + seedKey(m.id) + "|veg"), pick = (l) => l[Math.min(l.length - 1, rnd() * l.length | 0)], ok = (id) => {
|
|
4435
|
-
if (V.ok.has(id)) return V.ok.get(id);
|
|
4560
|
+
if (V.ok.has(id)) return V.ok.get(id) === true;
|
|
4436
4561
|
let r = true;
|
|
4437
4562
|
try {
|
|
4438
4563
|
V.S.toSpec(id);
|
|
@@ -4478,7 +4603,7 @@ function installVegetationBridge(K, shared) {
|
|
|
4478
4603
|
obj.position.y = G.y;
|
|
4479
4604
|
obj.name = "vegetation";
|
|
4480
4605
|
obj.traverse((o) => {
|
|
4481
|
-
if (o
|
|
4606
|
+
if (isMesh2(o)) {
|
|
4482
4607
|
o.castShadow = true;
|
|
4483
4608
|
o.receiveShadow = true;
|
|
4484
4609
|
o.name = "veg/" + o.name;
|
|
@@ -4493,10 +4618,12 @@ function installVegetationBridge(K, shared) {
|
|
|
4493
4618
|
}
|
|
4494
4619
|
shared.ctx.vegInfo = { plants: pl, triangles: tri, colliders: col, lodCounts: lod, materials: mats };
|
|
4495
4620
|
}
|
|
4496
|
-
|
|
4621
|
+
const defined = { VEG_POT, VEG_CACTUS, VEG_MAP, VEG_PLANTER, vegItem, assembleVegetation };
|
|
4622
|
+
Object.assign(K, defined);
|
|
4497
4623
|
}
|
|
4498
4624
|
|
|
4499
4625
|
// src/interaction/state.ts
|
|
4626
|
+
import { isMesh as isMesh3 } from "@adatechnology/game-shapes-three";
|
|
4500
4627
|
function installInteractionState(K, shared) {
|
|
4501
4628
|
const { THREE, cfg, colliderChanged, invalidateShadow, invalidate, UV_SCALE, applyPart, texture } = K;
|
|
4502
4629
|
const ivRoomEffective = (...a) => K.ivRoomEffective(...a);
|
|
@@ -4561,12 +4688,14 @@ function installInteractionState(K, shared) {
|
|
|
4561
4688
|
shared.inter.msg = { text, until: performance.now() + MESSAGE_MS };
|
|
4562
4689
|
if (cfg.onMessage) cfg.onMessage(text);
|
|
4563
4690
|
};
|
|
4564
|
-
|
|
4691
|
+
const I = () => shared.inter;
|
|
4692
|
+
function definePiece(name, definition) {
|
|
4693
|
+
const def = definition;
|
|
4565
4694
|
def.name = name;
|
|
4566
4695
|
def.meshes = [];
|
|
4567
4696
|
def.t = def.target = shared.partState.has(name) ? shared.partState.get(name) : def.t0 || 0;
|
|
4568
|
-
|
|
4569
|
-
|
|
4697
|
+
I().defs.set(name, def);
|
|
4698
|
+
I().pieces.push(def);
|
|
4570
4699
|
return def;
|
|
4571
4700
|
}
|
|
4572
4701
|
const localOf = (M, lx, lz) => {
|
|
@@ -4578,17 +4707,18 @@ function installInteractionState(K, shared) {
|
|
|
4578
4707
|
return true;
|
|
4579
4708
|
}
|
|
4580
4709
|
function assembleInteractive(gs) {
|
|
4581
|
-
|
|
4710
|
+
const inter = I();
|
|
4711
|
+
for (const [name, def] of inter.defs) {
|
|
4582
4712
|
const g = gs[name];
|
|
4583
4713
|
if (!g) continue;
|
|
4584
4714
|
delete gs[name];
|
|
4585
4715
|
const outer = new THREE.Group();
|
|
4586
|
-
outer.position.
|
|
4716
|
+
outer.position.fromArray(def.pivot);
|
|
4587
4717
|
outer.rotation.y = def.ry || 0;
|
|
4588
4718
|
outer.updateMatrix();
|
|
4589
|
-
const inv = new THREE.Matrix4().compose(new THREE.Vector3(
|
|
4719
|
+
const inv = new THREE.Matrix4().compose(new THREE.Vector3().fromArray(def.pivot), new THREE.Quaternion().setFromAxisAngle(_EY, def.ry || 0), _UM3).invert();
|
|
4590
4720
|
g.traverse((o) => {
|
|
4591
|
-
if (o
|
|
4721
|
+
if (isMesh3(o)) {
|
|
4592
4722
|
o.geometry.applyMatrix4(inv);
|
|
4593
4723
|
o.userData.piece = def;
|
|
4594
4724
|
def.meshes.push(o);
|
|
@@ -4600,13 +4730,14 @@ function installInteractionState(K, shared) {
|
|
|
4600
4730
|
const parent = def.leaf ? def.leaf.gs[def.k] : gs[def.parent] || (gs[def.parent] = new THREE.Group());
|
|
4601
4731
|
if (parent) parent.add(outer);
|
|
4602
4732
|
if (def.roomId) {
|
|
4603
|
-
|
|
4604
|
-
|
|
4733
|
+
let lamps = inter.lights.get(def.roomId);
|
|
4734
|
+
if (!lamps) inter.lights.set(def.roomId, lamps = []);
|
|
4735
|
+
lamps.push(def);
|
|
4605
4736
|
}
|
|
4606
4737
|
applyPiece(def);
|
|
4607
4738
|
}
|
|
4608
|
-
for (const roomId of
|
|
4609
|
-
|
|
4739
|
+
for (const roomId of inter.litRooms) applyLight(roomId);
|
|
4740
|
+
inter.defs.forEach((d) => {
|
|
4610
4741
|
if (d.col) d.col.off = d.t > 0.5;
|
|
4611
4742
|
});
|
|
4612
4743
|
}
|
|
@@ -4614,6 +4745,7 @@ function installInteractionState(K, shared) {
|
|
|
4614
4745
|
const n = p.inner;
|
|
4615
4746
|
if (!n) return;
|
|
4616
4747
|
switch (p.kind) {
|
|
4748
|
+
/* each kind always sets its dimensions (sgn, angle, travel, k, axis) */
|
|
4617
4749
|
case "swing":
|
|
4618
4750
|
n.rotation.y = p.sgn * p.t * p.angle;
|
|
4619
4751
|
break;
|
|
@@ -4646,8 +4778,9 @@ function installInteractionState(K, shared) {
|
|
|
4646
4778
|
}
|
|
4647
4779
|
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 };
|
|
4648
4780
|
function animateInteractive(dt) {
|
|
4649
|
-
|
|
4650
|
-
|
|
4781
|
+
const inter = I();
|
|
4782
|
+
if (!inter.anim.size) return;
|
|
4783
|
+
for (const p of inter.anim) {
|
|
4651
4784
|
const step = dt / (DURATION[p.kind] || 0.5), d = p.target - p.t;
|
|
4652
4785
|
p.t = Math.abs(d) <= step ? p.target : p.t + Math.sign(d) * step;
|
|
4653
4786
|
applyPiece(p);
|
|
@@ -4655,7 +4788,7 @@ function installInteractionState(K, shared) {
|
|
|
4655
4788
|
p.col.off = p.target > 0.5;
|
|
4656
4789
|
colliderChanged(p.col);
|
|
4657
4790
|
}
|
|
4658
|
-
if (p.t === p.target)
|
|
4791
|
+
if (p.t === p.target) inter.anim.delete(p);
|
|
4659
4792
|
}
|
|
4660
4793
|
invalidateShadow();
|
|
4661
4794
|
}
|
|
@@ -4666,7 +4799,7 @@ function installInteractionState(K, shared) {
|
|
|
4666
4799
|
p.col.off = p.target > 0.5;
|
|
4667
4800
|
colliderChanged(p.col);
|
|
4668
4801
|
}
|
|
4669
|
-
|
|
4802
|
+
I().anim.add(p);
|
|
4670
4803
|
}
|
|
4671
4804
|
const lightBase = (roomId) => roomId == null ? true : shared.partState.has("light:" + roomId) ? !!shared.partState.get("light:" + roomId) : !!shared.ctx.night;
|
|
4672
4805
|
const lightOn = (roomId) => {
|
|
@@ -4674,20 +4807,21 @@ function installInteractionState(K, shared) {
|
|
|
4674
4807
|
return S ? S.ef : lightBase(roomId);
|
|
4675
4808
|
};
|
|
4676
4809
|
function applyLight(roomId) {
|
|
4677
|
-
const on = lightOn(roomId);
|
|
4678
|
-
for (const d of
|
|
4679
|
-
const sw =
|
|
4810
|
+
const on = lightOn(roomId), inter = I(), mats = shared.mats;
|
|
4811
|
+
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;
|
|
4812
|
+
const sw = inter.defs.get("ix:int:" + roomId);
|
|
4680
4813
|
if (sw) {
|
|
4681
4814
|
sw.target = on ? 1 : 0;
|
|
4682
|
-
if (sw.t !== sw.target)
|
|
4815
|
+
if (sw.t !== sw.target) inter.anim.add(sw);
|
|
4683
4816
|
}
|
|
4684
4817
|
invalidate();
|
|
4685
4818
|
}
|
|
4686
4819
|
function toggleLight(roomId) {
|
|
4687
4820
|
const S = shared.ctx.iv && shared.ctx.iv.roomStates.get(roomId);
|
|
4688
4821
|
if (S) {
|
|
4689
|
-
|
|
4690
|
-
|
|
4822
|
+
const IV = shared.ctx.iv;
|
|
4823
|
+
ivRoomLight(IV, roomId, !S.ef);
|
|
4824
|
+
const ef = ivRoomEffective(IV, S);
|
|
4691
4825
|
if (ef !== S.ef) {
|
|
4692
4826
|
S.ef = ef;
|
|
4693
4827
|
applyLight(roomId);
|
|
@@ -4699,11 +4833,13 @@ function installInteractionState(K, shared) {
|
|
|
4699
4833
|
applyLight(roomId);
|
|
4700
4834
|
if (cfg.onLight) cfg.onLight(roomId, lightOn(roomId));
|
|
4701
4835
|
}
|
|
4702
|
-
|
|
4836
|
+
const defined = { newInteractiveState, MESSAGE_MS, createInteractiveMaterials, _EY, _UM3, hudMessage, definePiece, localOf, visibleChain, assembleInteractive, applyPiece, DURATION, animateInteractive, togglePiece, lightBase, lightOn, applyLight, toggleLight };
|
|
4837
|
+
Object.assign(K, defined);
|
|
4703
4838
|
}
|
|
4704
4839
|
|
|
4705
4840
|
// src/interaction/collision.ts
|
|
4706
4841
|
function installInteractionCollision(K, shared) {
|
|
4842
|
+
const inter = () => shared.inter;
|
|
4707
4843
|
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)/;
|
|
4708
4844
|
function registerCollision(m, M) {
|
|
4709
4845
|
const h = m.h || 0, y = M.y || 0;
|
|
@@ -4713,7 +4849,7 @@ function installInteractionCollision(K, shared) {
|
|
|
4713
4849
|
w = Math.min(w, 0.5);
|
|
4714
4850
|
d = Math.min(d, 0.5);
|
|
4715
4851
|
}
|
|
4716
|
-
|
|
4852
|
+
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 });
|
|
4717
4853
|
}
|
|
4718
4854
|
function objectDistance(o, x, z) {
|
|
4719
4855
|
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;
|
|
@@ -4721,7 +4857,7 @@ function installInteractionCollision(K, shared) {
|
|
|
4721
4857
|
}
|
|
4722
4858
|
function collideObject(x, z, fx, fz, floor) {
|
|
4723
4859
|
const R = 0.2;
|
|
4724
|
-
for (const o of
|
|
4860
|
+
for (const o of inter().objs) {
|
|
4725
4861
|
if (o.f !== -1 ? o.f !== floor : floor !== 0) continue;
|
|
4726
4862
|
const d1 = objectDistance(o, x, z);
|
|
4727
4863
|
if (d1 < R && d1 < objectDistance(o, fx, fz) - 1e-6) return true;
|
|
@@ -4741,7 +4877,8 @@ function installInteractionCollision(K, shared) {
|
|
|
4741
4877
|
const de = opt.from || [x + 1e4, z + 1e4];
|
|
4742
4878
|
return collideObject(x, z, de[0], de[1], floor);
|
|
4743
4879
|
}
|
|
4744
|
-
|
|
4880
|
+
const defined = { NO_COLLIDE, registerCollision, objectDistance, collideObject, collideAt };
|
|
4881
|
+
Object.assign(K, defined);
|
|
4745
4882
|
}
|
|
4746
4883
|
|
|
4747
4884
|
// src/interaction/items.ts
|
|
@@ -4750,6 +4887,7 @@ function installInteractionItems(K, shared) {
|
|
|
4750
4887
|
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)$/;
|
|
4751
4888
|
const DRAWER_ITEM = /^(console_table|dresser|nightstand|vanity_table)$/;
|
|
4752
4889
|
const LIGHT_TYPES = /* @__PURE__ */ new Set(["ceiling_light", "pendant", "chandelier", "track_spot", "hanging_plant"]);
|
|
4890
|
+
const I = () => shared.inter;
|
|
4753
4891
|
function objectName(type, drawer) {
|
|
4754
4892
|
return drawer ? "drawer" : /^wardrobe/.test(type) ? "wardrobe" : /fridge|refrig|freezer/.test(type) ? "fridge" : /pantry/.test(type) ? "pantry" : "cabinet";
|
|
4755
4893
|
}
|
|
@@ -4778,8 +4916,8 @@ function installInteractionItems(K, shared) {
|
|
|
4778
4916
|
cursor.group = parent;
|
|
4779
4917
|
}
|
|
4780
4918
|
for (let i = n0; i < LIGHTS.length; i++) LIGHTS[i].roomId = m.room;
|
|
4781
|
-
if (!
|
|
4782
|
-
|
|
4919
|
+
if (!I().defs.has(name)) definePiece(name, { kind: "light", pivot: [0, 0, 0], ry: 0, parent, roomId: m.room });
|
|
4920
|
+
I().litRooms.add(m.room);
|
|
4783
4921
|
}
|
|
4784
4922
|
function curtainItem(m, M, ent, api, parent) {
|
|
4785
4923
|
M.open = false;
|
|
@@ -4807,12 +4945,13 @@ function installInteractionItems(K, shared) {
|
|
|
4807
4945
|
for (const c of body) api[c[0]](M, ...c[1]);
|
|
4808
4946
|
if (!parts.length) return;
|
|
4809
4947
|
const [ax, az] = localOf(M, 0, 0.2);
|
|
4810
|
-
|
|
4811
|
-
|
|
4948
|
+
const first = parts[0];
|
|
4949
|
+
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: () => {
|
|
4950
|
+
const al = first.target > 0.5 ? 0 : 1;
|
|
4812
4951
|
for (const p of parts) {
|
|
4813
4952
|
p.target = al;
|
|
4814
4953
|
shared.partState.set(p.name, al);
|
|
4815
|
-
|
|
4954
|
+
I().anim.add(p);
|
|
4816
4955
|
}
|
|
4817
4956
|
} });
|
|
4818
4957
|
}
|
|
@@ -4833,7 +4972,7 @@ function installInteractionItems(K, shared) {
|
|
|
4833
4972
|
calls.forEach((c, i) => {
|
|
4834
4973
|
if (owner.has(i)) return;
|
|
4835
4974
|
const a = c[1];
|
|
4836
|
-
let x0, x1, y0, y1, ok = false, grip = 0, wide = false;
|
|
4975
|
+
let x0 = 0, x1 = 0, y0 = 0, y1 = 0, ok = false, grip = 0, wide = false;
|
|
4837
4976
|
if (c[0] === "box") {
|
|
4838
4977
|
const [mat, x, y, z, w, h, d, , ry, rx, rz] = a;
|
|
4839
4978
|
if (ry || rx || rz || d > 0.05 || z + d / 2 < front - 5e-3 || w > M.w * 1.01) return;
|
|
@@ -4865,8 +5004,9 @@ function installInteractionItems(K, shared) {
|
|
|
4865
5004
|
return;
|
|
4866
5005
|
}
|
|
4867
5006
|
candidate.sort((p, q) => overlap(x0, x1, q.x0, q.x1) - overlap(x0, x1, p.x0, p.x1));
|
|
4868
|
-
|
|
4869
|
-
|
|
5007
|
+
const best = candidate[0];
|
|
5008
|
+
owner.set(i, best);
|
|
5009
|
+
if (grip) best.grip = grip;
|
|
4870
5010
|
});
|
|
4871
5011
|
const name = objectName(m.type, drawer), parts = [];
|
|
4872
5012
|
panels.forEach((p, k) => {
|
|
@@ -4882,8 +5022,8 @@ function installInteractionItems(K, shared) {
|
|
|
4882
5022
|
p.def = def;
|
|
4883
5023
|
parts.push(def);
|
|
4884
5024
|
const [ax, az] = localOf(M, cx, front + 0.08);
|
|
4885
|
-
|
|
4886
|
-
def.item =
|
|
5025
|
+
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) });
|
|
5026
|
+
def.item = I().items[I().items.length - 1];
|
|
4887
5027
|
});
|
|
4888
5028
|
calls.forEach((c, i) => {
|
|
4889
5029
|
const p = owner.get(i);
|
|
@@ -4897,14 +5037,17 @@ function installInteractionItems(K, shared) {
|
|
|
4897
5037
|
}
|
|
4898
5038
|
cursor.group = parent;
|
|
4899
5039
|
}
|
|
4900
|
-
|
|
5040
|
+
const defined = { DOOR_ITEM, DRAWER_ITEM, LIGHT_TYPES, objectName, recordApi, buildItem, lightItem, curtainItem, furnitureItem };
|
|
5041
|
+
Object.assign(K, defined);
|
|
4901
5042
|
}
|
|
4902
5043
|
|
|
4903
5044
|
// src/interaction/fittings.ts
|
|
4904
5045
|
function installInteractionFittings(K, shared) {
|
|
4905
5046
|
const { t, EPS, OPEN_AREA, Y0, applyPiece, bx, cursor, definePiece, gates, lightOn, roomAt, slideDirection, toggleLight, togglePiece } = K;
|
|
5047
|
+
const I = () => shared.inter;
|
|
5048
|
+
const house = () => shared.ctx.r;
|
|
4906
5049
|
function gatesInteractive() {
|
|
4907
|
-
const lt =
|
|
5050
|
+
const lt = house().lot;
|
|
4908
5051
|
if (!lt) return;
|
|
4909
5052
|
const cz0 = (lt.rect[1] + lt.rect[3]) / 2;
|
|
4910
5053
|
const orig = K.getBx(), gs = lt.gates, opening = gs.map((g) => g.open), reg = gs.map((g) => {
|
|
@@ -4924,9 +5067,9 @@ function installInteractionFittings(K, shared) {
|
|
|
4924
5067
|
return;
|
|
4925
5068
|
}
|
|
4926
5069
|
}
|
|
4927
|
-
|
|
5070
|
+
orig(mat, x0, y0, z0, x1, y1, z1, color);
|
|
4928
5071
|
});
|
|
4929
|
-
const
|
|
5072
|
+
const colliders = shared.ctx.colliders, n0 = colliders.length;
|
|
4930
5073
|
try {
|
|
4931
5074
|
gs.forEach((g) => {
|
|
4932
5075
|
g.open = false;
|
|
@@ -4938,7 +5081,7 @@ function installInteractionFittings(K, shared) {
|
|
|
4938
5081
|
g.open = opening[i];
|
|
4939
5082
|
});
|
|
4940
5083
|
}
|
|
4941
|
-
const cols =
|
|
5084
|
+
const cols = colliders.slice(n0), cz = (lt.rect[1] + lt.rect[3]) / 2, cu = (lt.rect[0] + lt.rect[2]) / 2;
|
|
4942
5085
|
reg.forEach((r, i) => {
|
|
4943
5086
|
const g = r.g;
|
|
4944
5087
|
if (!isFinite(r.x0)) return;
|
|
@@ -4947,25 +5090,25 @@ function installInteractionFittings(K, shared) {
|
|
|
4947
5090
|
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 }));
|
|
4948
5091
|
if (p.col) p.col.off = p.target > 0.5;
|
|
4949
5092
|
const text = () => t(p.target > 0.5 ? "prompt.close" : "prompt.open", { what: t(ped ? "what.pedestrianGate" : "what.garageGate") });
|
|
4950
|
-
|
|
5093
|
+
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 });
|
|
4951
5094
|
});
|
|
4952
5095
|
}
|
|
4953
5096
|
function mailboxInteractive() {
|
|
4954
|
-
for (const m of
|
|
5097
|
+
for (const m of house().items) {
|
|
4955
5098
|
if (m.type !== "mailbox") continue;
|
|
4956
5099
|
const g = shared.ctx.parts && shared.ctx.parts["mailbox_" + m.id];
|
|
4957
5100
|
if (!g) continue;
|
|
4958
5101
|
const name = "ix:correio:" + m.id, def = definePiece(name, { kind: "part", pivot: [0, 0, 0], ry: 0, parent: "lot" });
|
|
4959
5102
|
def.inner = g;
|
|
4960
5103
|
const fx = Math.sin(m.ry || 0), fz = Math.cos(m.ry || 0), ay = (m.y || 1) + (m.h || 0.3) * 0.4;
|
|
4961
|
-
|
|
5104
|
+
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 });
|
|
4962
5105
|
applyPiece(def);
|
|
4963
5106
|
}
|
|
4964
5107
|
}
|
|
4965
5108
|
function placeSwitches() {
|
|
4966
|
-
const R =
|
|
5109
|
+
const R = house(), used = /* @__PURE__ */ new Set();
|
|
4967
5110
|
for (const c of R.rooms) {
|
|
4968
|
-
if (c.type === "void" || OPEN_AREA(c) || !
|
|
5111
|
+
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;
|
|
4969
5112
|
const doors = R.doors.filter((p) => p.floor === c.floor && (p.a === c.id || p.b === c.id));
|
|
4970
5113
|
doors.sort((p, q) => ((q.exterior ? 1 : 0) - (p.exterior ? 1 : 0)) * (c.type === "living" ? 1 : -1));
|
|
4971
5114
|
for (const p of doors) if (putSwitch(c, p)) {
|
|
@@ -4975,11 +5118,11 @@ function installInteractionFittings(K, shared) {
|
|
|
4975
5118
|
}
|
|
4976
5119
|
}
|
|
4977
5120
|
function putSwitch(c, p) {
|
|
4978
|
-
const R =
|
|
5121
|
+
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;
|
|
4979
5122
|
const wref = R.walls.find((w) => w.floor === f && w.axis === p.axis && Math.abs((alongU ? w.v0 : w.u0) - L) < EPS), th = wref ? wref.thickness || 0.15 : 0.15;
|
|
4980
5123
|
const inside = (sd2) => {
|
|
4981
5124
|
const cc = roomAt(f, alongU ? p.at : L + sd2 * 0.4, alongU ? L + sd2 * 0.4 : p.at);
|
|
4982
|
-
return cc && cc.id === c.id;
|
|
5125
|
+
return !!cc && cc.id === c.id;
|
|
4983
5126
|
};
|
|
4984
5127
|
const sd = inside(1) ? 1 : inside(-1) ? -1 : 0;
|
|
4985
5128
|
if (!sd) return false;
|
|
@@ -5002,19 +5145,22 @@ function installInteractionFittings(K, shared) {
|
|
|
5002
5145
|
const piece = 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 });
|
|
5003
5146
|
piece.t = piece.target = lightOn(roomId) ? 1 : 0;
|
|
5004
5147
|
const an = alongU ? [u, yc, face + sd * 0.12] : [face + sd * 0.12, yc, u];
|
|
5005
|
-
|
|
5148
|
+
I().items.push({ type: "light_switch", id: roomId, floor: f, anchor: an, range: 1.5, angle: 0.45, pieces: [piece], text: () => t(lightOn(roomId) ? "prompt.lightOff" : "prompt.lightOn"), action: () => toggleLight(roomId) });
|
|
5006
5149
|
return true;
|
|
5007
5150
|
}
|
|
5008
5151
|
return false;
|
|
5009
5152
|
}
|
|
5010
|
-
|
|
5153
|
+
const defined = { gatesInteractive, mailboxInteractive, placeSwitches, putSwitch };
|
|
5154
|
+
Object.assign(K, defined);
|
|
5011
5155
|
}
|
|
5012
5156
|
|
|
5013
5157
|
// src/interaction/doors.ts
|
|
5014
5158
|
function installInteractionDoors(K, shared) {
|
|
5015
5159
|
const { t, colliderChanged, invalidateShadow, applyPiece, hudMessage } = K;
|
|
5160
|
+
const leaves = () => shared.ctx.leaves;
|
|
5016
5161
|
function linkDoorLeaves() {
|
|
5017
|
-
|
|
5162
|
+
const I = shared.inter;
|
|
5163
|
+
for (const fo of leaves()) fo.handles = (fo.handleNames || []).map((n) => I.defs.get(n)).filter((d) => !!d);
|
|
5018
5164
|
}
|
|
5019
5165
|
function handleApply(fo) {
|
|
5020
5166
|
for (const mc of fo.handles || []) {
|
|
@@ -5024,11 +5170,12 @@ function installInteractionDoors(K, shared) {
|
|
|
5024
5170
|
}
|
|
5025
5171
|
function toggleDoor(fo) {
|
|
5026
5172
|
if (fo.phase === "rattle") return;
|
|
5173
|
+
const col = fo.col;
|
|
5027
5174
|
if (fo.phase === "handle" || fo.phase === "swing") {
|
|
5028
5175
|
fo.open = !fo.open;
|
|
5029
5176
|
shared.doorState.set(fo.id, fo.open);
|
|
5030
|
-
|
|
5031
|
-
colliderChanged(
|
|
5177
|
+
col.off = fo.open;
|
|
5178
|
+
colliderChanged(col);
|
|
5032
5179
|
fo.anim = true;
|
|
5033
5180
|
fo.phase = "swing";
|
|
5034
5181
|
return;
|
|
@@ -5042,8 +5189,8 @@ function installInteractionDoors(K, shared) {
|
|
|
5042
5189
|
}
|
|
5043
5190
|
fo.open = !fo.open;
|
|
5044
5191
|
shared.doorState.set(fo.id, fo.open);
|
|
5045
|
-
|
|
5046
|
-
colliderChanged(
|
|
5192
|
+
col.off = fo.open;
|
|
5193
|
+
colliderChanged(col);
|
|
5047
5194
|
fo.anim = true;
|
|
5048
5195
|
shared.ctx.animateDoorsOn = true;
|
|
5049
5196
|
if (fo.handles && fo.handles.length) {
|
|
@@ -5054,7 +5201,7 @@ function installInteractionDoors(K, shared) {
|
|
|
5054
5201
|
function animateDoors(dt) {
|
|
5055
5202
|
if (!shared.ctx.animateDoorsOn) return;
|
|
5056
5203
|
let active = false;
|
|
5057
|
-
for (const fo of
|
|
5204
|
+
for (const fo of leaves()) {
|
|
5058
5205
|
if (!fo.phase) continue;
|
|
5059
5206
|
active = true;
|
|
5060
5207
|
if (fo.phase === "handle") {
|
|
@@ -5074,7 +5221,7 @@ function installInteractionDoors(K, shared) {
|
|
|
5074
5221
|
handleApply(fo);
|
|
5075
5222
|
if (fo.hT <= 0) fo.phase = null;
|
|
5076
5223
|
} else if (fo.phase === "rattle") {
|
|
5077
|
-
fo.jig
|
|
5224
|
+
fo.jig = (fo.jig ?? 0) - dt;
|
|
5078
5225
|
fo.hT = fo.jig > 0 ? 0.55 * Math.abs(Math.sin(fo.jig * 26)) : 0;
|
|
5079
5226
|
handleApply(fo);
|
|
5080
5227
|
if (fo.jig <= 0) {
|
|
@@ -5088,9 +5235,9 @@ function installInteractionDoors(K, shared) {
|
|
|
5088
5235
|
invalidateShadow();
|
|
5089
5236
|
}
|
|
5090
5237
|
function wallBlocks(ex, ez, ax, az, floor) {
|
|
5091
|
-
const n = shared.ctx.wallColliders != null ? shared.ctx.wallColliders : 0;
|
|
5238
|
+
const n = shared.ctx.wallColliders != null ? shared.ctx.wallColliders : 0, colliders = shared.ctx.colliders;
|
|
5092
5239
|
for (let i = 0; i < n; i++) {
|
|
5093
|
-
const c =
|
|
5240
|
+
const c = colliders[i];
|
|
5094
5241
|
if (c.f !== floor && !(c.f === -1 && floor === 0)) continue;
|
|
5095
5242
|
let t0 = 0, t1 = 1;
|
|
5096
5243
|
const dx = ax - ex, dz = az - ez;
|
|
@@ -5120,7 +5267,8 @@ function installInteractionDoors(K, shared) {
|
|
|
5120
5267
|
g.updateMatrix();
|
|
5121
5268
|
}
|
|
5122
5269
|
}
|
|
5123
|
-
|
|
5270
|
+
const defined = { linkDoorLeaves, handleApply, toggleDoor, animateDoors, wallBlocks, doorText, applyLeaf };
|
|
5271
|
+
Object.assign(K, defined);
|
|
5124
5272
|
}
|
|
5125
5273
|
|
|
5126
5274
|
// src/interaction/target.ts
|
|
@@ -5130,6 +5278,7 @@ function installInteractionTarget(K, shared) {
|
|
|
5130
5278
|
function targetOf(o, opt) {
|
|
5131
5279
|
if (!o) return null;
|
|
5132
5280
|
opt = opt || {};
|
|
5281
|
+
const I = shared.inter;
|
|
5133
5282
|
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;
|
|
5134
5283
|
let best = null;
|
|
5135
5284
|
const tries = (score, text, action, target) => {
|
|
@@ -5143,16 +5292,16 @@ function installInteractionTarget(K, shared) {
|
|
|
5143
5292
|
if (angle > 1.35 && d > 0.9) continue;
|
|
5144
5293
|
tries(angle * 1.6 + d * 0.5 + (angle < 0.25 ? 0 : 0.6), doorText(fo), () => toggleDoor(fo), fo);
|
|
5145
5294
|
}
|
|
5146
|
-
const vis =
|
|
5295
|
+
const vis = I.pieces.flatMap((p) => p.meshes).filter(visibleChain), hit = vis.length && opt.strike ? opt.strike(vis) : null;
|
|
5147
5296
|
const kitA = shared.ctx.iv ? ivTarget(shared.ctx.iv, o, opt && opt.interactives) : null;
|
|
5148
5297
|
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;
|
|
5149
5298
|
const pieceHit = hit && !nearKit && hit.object.userData.piece;
|
|
5150
|
-
for (const it of
|
|
5299
|
+
for (const it of I.items) {
|
|
5151
5300
|
if (it.floor !== floor && !(it.floor === -1 && floor === 0)) continue;
|
|
5152
5301
|
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);
|
|
5153
5302
|
if (dh > it.range + 0.4) continue;
|
|
5154
5303
|
const angle = Math.acos(Math.max(-1, Math.min(1, (dx * vx + dy * vy + dz * vz) / (d || 1))));
|
|
5155
|
-
const byRay = pieceHit && it.pieces.includes(pieceHit) && hit.distance <= it.range + 0.5;
|
|
5304
|
+
const byRay = !!hit && pieceHit && it.pieces.includes(pieceHit) && hit.distance <= it.range + 0.5;
|
|
5156
5305
|
if (!byRay && !(dh <= it.range && angle <= it.angle)) continue;
|
|
5157
5306
|
if (!it.noWall && wallBlocks(ex, ez, ax, az, it.floor < 0 ? 0 : it.floor)) continue;
|
|
5158
5307
|
tries((byRay ? 0 : angle * 2) + d * 0.3 - (byRay ? 1.5 : 0), it.text(), it.action, it);
|
|
@@ -5160,10 +5309,12 @@ function installInteractionTarget(K, shared) {
|
|
|
5160
5309
|
if (kitA) tries(kitA.score - (nearKit ? 0.5 : 0), kitA.text, kitA.action, kitA.target);
|
|
5161
5310
|
return best;
|
|
5162
5311
|
}
|
|
5163
|
-
|
|
5312
|
+
const defined = { targetOf };
|
|
5313
|
+
Object.assign(K, defined);
|
|
5164
5314
|
}
|
|
5165
5315
|
|
|
5166
5316
|
// src/interactables/bridge.ts
|
|
5317
|
+
import { isMesh as isMesh4 } from "@adatechnology/game-shapes-three";
|
|
5167
5318
|
function installInteractablesBridge(K, shared) {
|
|
5168
5319
|
const { t, THREE, invalidate, invalidateShadow, cfg, DOC, LIGHT_TYPES, _Y, _q, _v3, accFor, applyLight, cursor, hashString, hudMessage, lightBase, pieceRecord, put, rgbOf, sh, wallBlocks } = K;
|
|
5169
5320
|
const enter = (...a) => K.enter(...a);
|
|
@@ -5217,7 +5368,8 @@ function installInteractablesBridge(K, shared) {
|
|
|
5217
5368
|
function ivBuild(h, water) {
|
|
5218
5369
|
const ik = K.IVK, r = shared.ctx.r, A = ik.A, world0 = null;
|
|
5219
5370
|
void world0;
|
|
5220
|
-
const
|
|
5371
|
+
const source = r;
|
|
5372
|
+
const plane = A.plan(source, { seed: r.seed });
|
|
5221
5373
|
const IV = { k: ik, plane, 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 };
|
|
5222
5374
|
h.IV = IV;
|
|
5223
5375
|
const t0 = performance.now();
|
|
@@ -5236,9 +5388,10 @@ function installInteractablesBridge(K, shared) {
|
|
|
5236
5388
|
const wants = (roomId) => lightBase(roomId);
|
|
5237
5389
|
const entById = new Map(plane.items.map((e) => [e.id, e]));
|
|
5238
5390
|
const entByItem = new Map(plane.items.map((e) => [e.item, e]));
|
|
5239
|
-
|
|
5391
|
+
const mats = shared.mats;
|
|
5392
|
+
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 };
|
|
5240
5393
|
const ev = (e) => ivEvent(h, e);
|
|
5241
|
-
const world = IV.world = A.createWorld(
|
|
5394
|
+
const world = IV.world = A.createWorld(source, { water, seed: r.seed, onEvent: ev });
|
|
5242
5395
|
const add0 = world.add;
|
|
5243
5396
|
world.add = (id, spec, tr) => {
|
|
5244
5397
|
const e = entById.get(id);
|
|
@@ -5255,7 +5408,7 @@ function installInteractablesBridge(K, shared) {
|
|
|
5255
5408
|
}
|
|
5256
5409
|
return add0(id, spec, tr);
|
|
5257
5410
|
};
|
|
5258
|
-
const added = A.add(world, plane, { isBlocked: A.blockedOf(
|
|
5411
|
+
const added = A.add(world, plane, { isBlocked: A.blockedOf(source), build: (type, item) => ivDraw(IV, entByItem.get(item), type, item) });
|
|
5259
5412
|
world.add = add0;
|
|
5260
5413
|
IV.warnings = added.warnings;
|
|
5261
5414
|
IV.added = added;
|
|
@@ -5302,14 +5455,15 @@ function installInteractablesBridge(K, shared) {
|
|
|
5302
5455
|
}
|
|
5303
5456
|
function ivDraw(IV, ent, type, item) {
|
|
5304
5457
|
const ik = IV.k, loc = Object.assign({}, item, { x: 0, z: 0, ry: 0 });
|
|
5458
|
+
const ix = item.x, iz = item.z, iry = item.ry;
|
|
5305
5459
|
const mesh = ik.gfx.createMeshApi({ quality: "game", materials: IV.mats, shadows: true, mergeParts: true, swayAmplitude: 0.03 });
|
|
5306
5460
|
const spec = ik.A.household.build(type, loc, mesh.api);
|
|
5307
5461
|
const out = mesh.finish(spec);
|
|
5308
5462
|
for (const l of out.lights) l.removeFromParent();
|
|
5309
5463
|
const group = ivGroup(ent), g0 = cursor.group, root = new THREE.Group();
|
|
5310
5464
|
root.name = "iv:" + ent.id;
|
|
5311
|
-
root.position.set(
|
|
5312
|
-
root.rotation.y =
|
|
5465
|
+
root.position.set(ix, ent.floorY, iz);
|
|
5466
|
+
root.rotation.y = iry;
|
|
5313
5467
|
root.userData.iv = ent.id;
|
|
5314
5468
|
const screen = spec.devices && spec.devices.some((d) => d.kind === "screen");
|
|
5315
5469
|
let body = null;
|
|
@@ -5318,7 +5472,7 @@ function installInteractablesBridge(K, shared) {
|
|
|
5318
5472
|
if (type === "gas_bottle") {
|
|
5319
5473
|
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"] });
|
|
5320
5474
|
for (const m of out.group.children) if (!m.name.startsWith("static:")) m.traverse((o) => {
|
|
5321
|
-
if (o
|
|
5475
|
+
if (isMesh4(o)) {
|
|
5322
5476
|
o.userData.destructionPart = cursor.pc.id;
|
|
5323
5477
|
o.userData.destructionMaterial = "steel";
|
|
5324
5478
|
}
|
|
@@ -5326,13 +5480,13 @@ function installInteractablesBridge(K, shared) {
|
|
|
5326
5480
|
}
|
|
5327
5481
|
try {
|
|
5328
5482
|
for (const m of out.group.children.slice()) {
|
|
5329
|
-
if (m
|
|
5483
|
+
if (isMesh4(m) && m.name.startsWith("static:")) {
|
|
5330
5484
|
if (screen && m.userData.material === "emissive") {
|
|
5331
5485
|
body = m;
|
|
5332
5486
|
root.add(m);
|
|
5333
5487
|
continue;
|
|
5334
5488
|
}
|
|
5335
|
-
ivAccumulate(IV_MATERIAL[m.userData.material] || "plain", m.geometry,
|
|
5489
|
+
ivAccumulate(IV_MATERIAL[m.userData.material] || "plain", m.geometry, ix, ent.floorY, iz, iry, null);
|
|
5336
5490
|
m.geometry.dispose();
|
|
5337
5491
|
} else root.add(m);
|
|
5338
5492
|
}
|
|
@@ -5342,7 +5496,7 @@ function installInteractablesBridge(K, shared) {
|
|
|
5342
5496
|
}
|
|
5343
5497
|
const base = new Set(Object.values(IV.mats));
|
|
5344
5498
|
root.traverse((o) => {
|
|
5345
|
-
if (!o
|
|
5499
|
+
if (!isMesh4(o)) return;
|
|
5346
5500
|
o.userData.iv = ent.id;
|
|
5347
5501
|
if (o.castShadow) {
|
|
5348
5502
|
if (!o.geometry.boundingSphere) o.geometry.computeBoundingSphere();
|
|
@@ -5353,7 +5507,7 @@ function installInteractablesBridge(K, shared) {
|
|
|
5353
5507
|
roomLightMask(m);
|
|
5354
5508
|
}
|
|
5355
5509
|
});
|
|
5356
|
-
const E = { id: ent.id, type, entry: ent, floor: ent.floor, group, root, parts: out.parts, spec, screen: body, pos: [
|
|
5510
|
+
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 };
|
|
5357
5511
|
IV.entries.set(ent.id, E);
|
|
5358
5512
|
if (root.children.length) IV.roots.push(E);
|
|
5359
5513
|
return spec;
|
|
@@ -5381,7 +5535,7 @@ function installInteractablesBridge(K, shared) {
|
|
|
5381
5535
|
const wire = (spec.wires || []).find((x) => x.id === d.id + "_cord"), pts = (wire ? wire.points : [d.plug]).map((p) => wl(o, p));
|
|
5382
5536
|
const sid = w.power.pluggedInto(E.id, d.id);
|
|
5383
5537
|
if (sid) {
|
|
5384
|
-
const cut = sid.indexOf(":"), so = w.get(sid.slice(0, cut)), sk = so && so.spec.sockets.find((s) => s.id === sid.slice(cut + 1));
|
|
5538
|
+
const cut = sid.indexOf(":"), so = w.get(sid.slice(0, cut)), sk = so && (so.spec.sockets || []).find((s) => s.id === sid.slice(cut + 1));
|
|
5385
5539
|
if (so && sk) {
|
|
5386
5540
|
const sp = wl(so, sk.pos), dir = [Math.sin(so.transform.ry), Math.cos(so.transform.ry)], last = pts[pts.length - 1];
|
|
5387
5541
|
if (last[1] < 0.3 + E.pos[1]) {
|
|
@@ -5416,9 +5570,10 @@ function installInteractablesBridge(K, shared) {
|
|
|
5416
5570
|
roomLightMask(sc.material);
|
|
5417
5571
|
IV.screens.set(E.id, sc);
|
|
5418
5572
|
}
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5573
|
+
const mesh = E.screen;
|
|
5574
|
+
mesh.material = sc.material;
|
|
5575
|
+
mesh.castShadow = false;
|
|
5576
|
+
mesh.receiveShadow = false;
|
|
5422
5577
|
}
|
|
5423
5578
|
function ivEvent(h, e) {
|
|
5424
5579
|
const IV = h.IV;
|
|
@@ -5454,16 +5609,17 @@ function installInteractablesBridge(K, shared) {
|
|
|
5454
5609
|
IV.itemsDirty = true;
|
|
5455
5610
|
break;
|
|
5456
5611
|
}
|
|
5457
|
-
|
|
5612
|
+
const ik = K.IVK;
|
|
5613
|
+
if (ik.onEvent) {
|
|
5458
5614
|
try {
|
|
5459
|
-
|
|
5615
|
+
ik.onEvent(e, IV.pub);
|
|
5460
5616
|
} catch (err) {
|
|
5461
5617
|
console.warn("interactables.onEvent", err);
|
|
5462
5618
|
}
|
|
5463
5619
|
}
|
|
5464
|
-
if (e.type === "seat" &&
|
|
5620
|
+
if (e.type === "seat" && ik.onSeat && e.actor === "player") {
|
|
5465
5621
|
try {
|
|
5466
|
-
|
|
5622
|
+
ik.onSeat(e.seated ? ivSeat(IV) : null, e);
|
|
5467
5623
|
} catch (err) {
|
|
5468
5624
|
console.warn("interactables.onSeat", err);
|
|
5469
5625
|
}
|
|
@@ -5472,7 +5628,7 @@ function installInteractablesBridge(K, shared) {
|
|
|
5472
5628
|
function ivSeat(IV) {
|
|
5473
5629
|
const w = IV.world, s = w.seatOf("player");
|
|
5474
5630
|
if (!s) return null;
|
|
5475
|
-
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);
|
|
5631
|
+
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);
|
|
5476
5632
|
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]]);
|
|
5477
5633
|
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 };
|
|
5478
5634
|
}
|
|
@@ -5514,18 +5670,19 @@ function installInteractablesBridge(K, shared) {
|
|
|
5514
5670
|
}
|
|
5515
5671
|
}
|
|
5516
5672
|
const em = w.emitters();
|
|
5517
|
-
|
|
5673
|
+
const ivk = K.IVK;
|
|
5674
|
+
if (em.length && !IV.efx && ivk.effects) {
|
|
5518
5675
|
const g = h.houseGroup;
|
|
5519
|
-
IV.efx = ik.gfx.createEffects(g, { maxParticles: 1400, seed: 11, document: DOC, ...
|
|
5676
|
+
IV.efx = ik.gfx.createEffects(g, { maxParticles: 1400, seed: 11, document: DOC, ...ivk.effectSink ? { effects: ivk.effectSink } : {} });
|
|
5520
5677
|
}
|
|
5521
5678
|
if (IV.efx) {
|
|
5522
5679
|
const alive = IV.efx.stats().alive;
|
|
5523
5680
|
if (em.length || alive) {
|
|
5524
|
-
IV.efx.update(dt, em,
|
|
5681
|
+
IV.efx.update(dt, em, ivk.camera ? typeof ivk.camera === "function" ? ivk.camera() : ivk.camera : void 0);
|
|
5525
5682
|
invalidate();
|
|
5526
5683
|
}
|
|
5527
5684
|
}
|
|
5528
|
-
if (
|
|
5685
|
+
if (ivk.items && IV.itemsDirty && IV.t - IV.itemsT > 0.1 && !IV.anim.size) ivItems(IV, h);
|
|
5529
5686
|
}
|
|
5530
5687
|
const IV_SHAPE = {
|
|
5531
5688
|
can: [["cyl", 1, 1, 1, 0, 1]],
|
|
@@ -5560,7 +5717,8 @@ function installInteractablesBridge(K, shared) {
|
|
|
5560
5717
|
if (c.access && w.partT(E.id, c.access) < 0.02) continue;
|
|
5561
5718
|
const st = w.contents(E.id, c.id);
|
|
5562
5719
|
for (let i = 0; i < st.length; i++) {
|
|
5563
|
-
|
|
5720
|
+
const stack = st[i];
|
|
5721
|
+
if (stack && items[stack.type]) list.push([E, c.id, i, items[stack.type]]);
|
|
5564
5722
|
}
|
|
5565
5723
|
}
|
|
5566
5724
|
}
|
|
@@ -5589,12 +5747,13 @@ function installInteractablesBridge(K, shared) {
|
|
|
5589
5747
|
gm.setIndex(new THREE.BufferAttribute(A.i.slice(0, A.ni), 1));
|
|
5590
5748
|
gm.computeBoundingSphere();
|
|
5591
5749
|
if (!IV.items) {
|
|
5592
|
-
|
|
5593
|
-
IV.items
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5750
|
+
const mesh = new THREE.Mesh(gm, shared.mats.plain);
|
|
5751
|
+
IV.items = mesh;
|
|
5752
|
+
mesh.name = "iv-items";
|
|
5753
|
+
mesh.castShadow = false;
|
|
5754
|
+
mesh.receiveShadow = true;
|
|
5755
|
+
mesh.frustumCulled = false;
|
|
5756
|
+
h.houseGroup.add(mesh);
|
|
5598
5757
|
} else {
|
|
5599
5758
|
IV.items.geometry.dispose();
|
|
5600
5759
|
IV.items.geometry = gm;
|
|
@@ -5728,7 +5887,8 @@ function installInteractablesBridge(K, shared) {
|
|
|
5728
5887
|
};
|
|
5729
5888
|
return IV.pub;
|
|
5730
5889
|
}
|
|
5731
|
-
|
|
5890
|
+
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 };
|
|
5891
|
+
Object.assign(K, defined);
|
|
5732
5892
|
}
|
|
5733
5893
|
|
|
5734
5894
|
// src/animation/clotheslines.ts
|
|
@@ -5753,7 +5913,8 @@ function installAnimationClotheslines(K, shared) {
|
|
|
5753
5913
|
}
|
|
5754
5914
|
invalidate();
|
|
5755
5915
|
}
|
|
5756
|
-
|
|
5916
|
+
const defined = { WIND, animateClotheslines };
|
|
5917
|
+
Object.assign(K, defined);
|
|
5757
5918
|
}
|
|
5758
5919
|
|
|
5759
5920
|
// src/build/instance.ts
|
|
@@ -5778,7 +5939,8 @@ function installBuildInstance(K, shared) {
|
|
|
5778
5939
|
shared.quality = h.quality;
|
|
5779
5940
|
}
|
|
5780
5941
|
const tagDamage = (type) => ({ type, hp: HP[type], hpMax: HP[type] });
|
|
5781
|
-
|
|
5942
|
+
const defined = { props, TYPES, newState, enter, tagDamage };
|
|
5943
|
+
Object.assign(K, defined);
|
|
5782
5944
|
}
|
|
5783
5945
|
|
|
5784
5946
|
// src/interactables/kit.ts
|
|
@@ -5807,17 +5969,20 @@ function installInteractablesKit(K, shared) {
|
|
|
5807
5969
|
for (const k of ["wood", "foliage", "flowers", "fruit", "spines"]) roomLightMask(m[k]);
|
|
5808
5970
|
return m;
|
|
5809
5971
|
})());
|
|
5810
|
-
|
|
5972
|
+
const defined = { IVK, VEG, vegMaterials };
|
|
5973
|
+
Object.assign(K, defined);
|
|
5811
5974
|
}
|
|
5812
5975
|
|
|
5813
5976
|
// src/lights/room-light.ts
|
|
5977
|
+
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 });
|
|
5814
5978
|
function installLightsRoomLight(K, shared) {
|
|
5815
5979
|
const { THREE, rectsOf: rectsOf2, cfg } = K;
|
|
5816
5980
|
const MAX_LIGHTS = 12, EMPTY = [1e9, 1e9, -1e9, -1e9];
|
|
5817
5981
|
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 } };
|
|
5818
5982
|
for (let i = 0; i < MAX_LIGHTS; i++) for (const k of ["uRB0", "uRB1", "uRB2", "uREx"]) LZU[k].value.set(EMPTY, i * 4);
|
|
5819
|
-
function roomLightMask(
|
|
5820
|
-
|
|
5983
|
+
function roomLightMask(material) {
|
|
5984
|
+
const m = material;
|
|
5985
|
+
if (!m || m.userData && m.userData.roomLightMask || !(m.isMeshLambertMaterial || m.isMeshPhongMaterial || m.isMeshStandardMaterial || m.isMeshPhysicalMaterial)) return material;
|
|
5821
5986
|
m.userData = m.userData || {};
|
|
5822
5987
|
m.userData.roomLightMask = true;
|
|
5823
5988
|
const prev = m.onBeforeCompile, pk = m.customProgramCacheKey;
|
|
@@ -5845,12 +6010,13 @@ function installLightsRoomLight(K, shared) {
|
|
|
5845
6010
|
return (pk ? pk.call(this) : "") + "|rm1";
|
|
5846
6011
|
};
|
|
5847
6012
|
m.needsUpdate = true;
|
|
5848
|
-
return
|
|
6013
|
+
return material;
|
|
5849
6014
|
}
|
|
5850
|
-
function lighting(
|
|
5851
|
-
o =
|
|
6015
|
+
function lighting(options) {
|
|
6016
|
+
const o = options || {};
|
|
5852
6017
|
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;
|
|
5853
|
-
|
|
6018
|
+
const mats = shared.mats;
|
|
6019
|
+
for (const k of Object.keys(mats)) roomLightMask(mats[k]);
|
|
5854
6020
|
const budget = o.budget, lease = budget ? budget.lease({ owner: "floorplan.rooms", point: N, shadows: NS }) : null;
|
|
5855
6021
|
if (budget && !lease) throw new Error("lighting: the LightBudget has no " + N + " free point slots (" + NS + " with shadow) for the rooms");
|
|
5856
6022
|
if (budget) for (const [key, width] of [["uRB0", 4], ["uRB1", 4], ["uRB2", 4], ["uRBY", 2], ["uREx", 4]]) {
|
|
@@ -5901,9 +6067,8 @@ function installLightsRoomLight(K, shared) {
|
|
|
5901
6067
|
}
|
|
5902
6068
|
for (let i = 0; i < NS; i++) PL[i].shadow.needsUpdate = true;
|
|
5903
6069
|
};
|
|
5904
|
-
A.update = function(
|
|
5905
|
-
op =
|
|
5906
|
-
houses = (Array.isArray(houses) ? houses : [houses]).filter(Boolean);
|
|
6070
|
+
A.update = function(houseOrList, focus, options2) {
|
|
6071
|
+
const op = options2 || {}, houses = (Array.isArray(houseOrList) ? houseOrList : [houseOrList]).filter((h) => !!h);
|
|
5907
6072
|
_f.set(focus.x, focus.y, focus.z);
|
|
5908
6073
|
const rooms = [], exterior = [];
|
|
5909
6074
|
for (const house of houses) {
|
|
@@ -5915,7 +6080,7 @@ function installLightsRoomLight(K, shared) {
|
|
|
5915
6080
|
if (!house.lightOn(l.roomId)) continue;
|
|
5916
6081
|
const k = l.type === "outdoor" ? "ext:" + (l.id || exterior.length) : l.roomId != null ? l.roomId : l.room;
|
|
5917
6082
|
let g = by.get(k);
|
|
5918
|
-
if (!g) by.set(k, g =
|
|
6083
|
+
if (!g) by.set(k, g = newGroup(k, house, l.type === "outdoor"));
|
|
5919
6084
|
g.ls.push(l);
|
|
5920
6085
|
}
|
|
5921
6086
|
for (const g of by.values()) {
|
|
@@ -5950,9 +6115,10 @@ function installLightsRoomLight(K, shared) {
|
|
|
5950
6115
|
}
|
|
5951
6116
|
}
|
|
5952
6117
|
g.exclusion = [x0 + 0.03, z0 + 0.03, x1 - 0.03, z1 - 0.03];
|
|
5953
|
-
|
|
5954
|
-
g.
|
|
5955
|
-
g.
|
|
6118
|
+
const l0 = ls[0];
|
|
6119
|
+
g.lumens = l0.lumens != null ? l0.lumens : 3.2;
|
|
6120
|
+
g.dist = l0.dist != null ? l0.dist : 5.5;
|
|
6121
|
+
g.decay = l0.decay != null ? l0.decay : 2;
|
|
5956
6122
|
} else {
|
|
5957
6123
|
const c = house.r.rooms.find((q) => q.id === g.k);
|
|
5958
6124
|
if (!c) continue;
|
|
@@ -6053,8 +6219,8 @@ function installLightsRoomLight(K, shared) {
|
|
|
6053
6219
|
}
|
|
6054
6220
|
const effectsByBudget = /* @__PURE__ */ new WeakMap();
|
|
6055
6221
|
const OPENING_REACH = 2.5, OPENING_SIDE = 0.6;
|
|
6056
|
-
function effectLights(
|
|
6057
|
-
o =
|
|
6222
|
+
function effectLights(options) {
|
|
6223
|
+
const o = options || {};
|
|
6058
6224
|
const budget = o.budget;
|
|
6059
6225
|
if (!budget) throw new Error("effectLights: a LightBudget is required");
|
|
6060
6226
|
const known = effectsByBudget.get(budget);
|
|
@@ -6132,7 +6298,7 @@ function installLightsRoomLight(K, shared) {
|
|
|
6132
6298
|
const A = {
|
|
6133
6299
|
/** 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. */
|
|
6134
6300
|
update(houses) {
|
|
6135
|
-
const indoors = cfg.effectLightsIndoors !== false, list = (Array.isArray(houses) ? houses : [houses]).filter(
|
|
6301
|
+
const indoors = cfg.effectLightsIndoors !== false, list = (Array.isArray(houses) ? houses : [houses]).filter((h) => !!h), cache2 = /* @__PURE__ */ new Map();
|
|
6136
6302
|
for (let at = 0; at < size; at++) {
|
|
6137
6303
|
if (ours.has(at)) continue;
|
|
6138
6304
|
const light = budget.group.children[at];
|
|
@@ -6160,12 +6326,13 @@ function installLightsRoomLight(K, shared) {
|
|
|
6160
6326
|
if (!o.ours) effectsByBudget.set(budget, A);
|
|
6161
6327
|
return A;
|
|
6162
6328
|
}
|
|
6163
|
-
|
|
6329
|
+
const defined = { MAX_LIGHTS, EMPTY, LZU, roomLightMask, lighting, effectLights };
|
|
6330
|
+
Object.assign(K, defined);
|
|
6164
6331
|
}
|
|
6165
6332
|
|
|
6166
6333
|
// src/destruction/pieces.ts
|
|
6167
6334
|
import { assemblyPart, getAssembly } from "@adatechnology/game-destruction";
|
|
6168
|
-
import { DENSITY, MEMBER_CAGE, toDestructibleSpec } from "@adatechnology/game-floorplan-structure";
|
|
6335
|
+
import { DENSITY, MEMBER_CAGE, cageResidualCapacity, toDestructibleSpec } from "@adatechnology/game-floorplan-structure";
|
|
6169
6336
|
|
|
6170
6337
|
// src/destruction/panels.ts
|
|
6171
6338
|
import { resolveSlabPanels, slabPanelView } from "@adatechnology/game-floorplan-structure";
|
|
@@ -6345,7 +6512,8 @@ function installDestructionPieces(K, shared) {
|
|
|
6345
6512
|
if (!pc || pc.unit) return sp;
|
|
6346
6513
|
if (pc.role !== "wall" && pc.role !== "partition") {
|
|
6347
6514
|
const def = getAssembly(pc.assembly || (pc.material === "concrete" && ["slab", "beam", "column", "stair"].includes(pc.role) ? "reinforced_concrete" : ""));
|
|
6348
|
-
const
|
|
6515
|
+
const cage = def && def.reinforcement ? pc.role === "column" && sp.shape.kind === "box" ? { ...def.reinforcement, residualCapacity: cageResidualCapacity(sp.shape.size, def.reinforcement, sp.structure?.capacity) } : { ...def.reinforcement } : null;
|
|
6516
|
+
const out = cage && !sp.reinforcement ? { ...sp, reinforcement: cage } : sp;
|
|
6349
6517
|
if (out.reinforcement && !out.units && pc.material === "concrete" && (pc.role === "beam" || pc.role === "column") && sp.shape.kind === "box") {
|
|
6350
6518
|
return { ...out, units: { size: [MEMBER_CAGE.unit, MEMBER_CAGE.unit, Math.min(...sp.shape.size)], bond: "stack", mortar: "concrete" } };
|
|
6351
6519
|
}
|
|
@@ -6374,6 +6542,7 @@ function collapseRange(mesh, v0, v1) {
|
|
|
6374
6542
|
const a = pos.array;
|
|
6375
6543
|
const u = mesh.userData;
|
|
6376
6544
|
if (!u._p0) u._p0 = a.slice();
|
|
6545
|
+
if (!u.plainPositions) Object.defineProperty(u, "plainPositions", { value: u._p0, enumerable: false, configurable: true, writable: true });
|
|
6377
6546
|
const list = u.collapsedRanges ?? (u.collapsedRanges = []);
|
|
6378
6547
|
if (!list.some((r) => r[0] === v0 && r[1] === v1)) list.push([v0, v1]);
|
|
6379
6548
|
const saved = a.slice(v0 * 3, v1 * 3);
|
|
@@ -6457,10 +6626,11 @@ function installDestructionBreach(K, _shared) {
|
|
|
6457
6626
|
const v = house.worldToLocal(tmp.p.set(p[0], p[1], p[2]));
|
|
6458
6627
|
return [v.x, v.y, v.z];
|
|
6459
6628
|
};
|
|
6460
|
-
function cells(part, units) {
|
|
6629
|
+
function cells(part, units, mask) {
|
|
6461
6630
|
const [u0, v0, u1, v1] = part.aabb;
|
|
6462
|
-
const alongU =
|
|
6631
|
+
const alongU = mask.alongU;
|
|
6463
6632
|
const len = alongU ? u1 - u0 : v1 - v0;
|
|
6633
|
+
const offset = (alongU ? u0 : v0) - mask.start;
|
|
6464
6634
|
const [ul, uh] = units.size;
|
|
6465
6635
|
const rows = Math.max(1, Math.round((part.y1 - part.y0) / uh));
|
|
6466
6636
|
const rowH = (part.y1 - part.y0) / rows;
|
|
@@ -6471,7 +6641,7 @@ function installDestructionBreach(K, _shared) {
|
|
|
6471
6641
|
const shift = units.bond === "running" && r & 1 ? w / 2 : 0;
|
|
6472
6642
|
for (let i = 0; i < per + (shift ? 1 : 0); i++) {
|
|
6473
6643
|
const a = Math.max(0, i * w - shift), b = Math.min(len, i * w - shift + w);
|
|
6474
|
-
if (b - a > 1e-3) out.push({ a, b, y0: part.y0 + r * rowH, y1: part.y0 + (r + 1) * rowH, r, i });
|
|
6644
|
+
if (b - a > 1e-3) out.push({ a: offset + a, b: offset + b, y0: part.y0 + r * rowH, y1: part.y0 + (r + 1) * rowH, r, i });
|
|
6475
6645
|
}
|
|
6476
6646
|
}
|
|
6477
6647
|
return out;
|
|
@@ -6485,8 +6655,21 @@ function installDestructionBreach(K, _shared) {
|
|
|
6485
6655
|
for (const q of structure.parts) {
|
|
6486
6656
|
if (q.id !== partId && same(q.aabb, part.aabb) && Math.abs(q.y1 - part.y0) < 0.01 && structure.meshesOf(q.id).some((it) => it.mesh)) return q.id;
|
|
6487
6657
|
}
|
|
6658
|
+
return part.role === "column" ? wallAround(part) : null;
|
|
6659
|
+
}
|
|
6660
|
+
function wallAround(part) {
|
|
6661
|
+
const cu = (part.aabb[0] + part.aabb[2]) / 2, cv = (part.aabb[1] + part.aabb[3]) / 2;
|
|
6662
|
+
for (const q of structure.parts) {
|
|
6663
|
+
if (q.id === part.id || q.role !== "wall" && q.role !== "partition" || !structure.meshesOf(q.id).some((it) => it.mesh)) continue;
|
|
6664
|
+
const inside = cu >= q.aabb[0] - 1e-3 && cu <= q.aabb[2] + 1e-3 && cv >= q.aabb[1] - 1e-3 && cv <= q.aabb[3] + 1e-3;
|
|
6665
|
+
if (inside && Math.min(q.y1, part.y1) - Math.max(q.y0, part.y0) > 0.5) return q.id;
|
|
6666
|
+
}
|
|
6488
6667
|
return null;
|
|
6489
6668
|
}
|
|
6669
|
+
const pillarSpans = (view) => structure.parts.filter((q) => q.role === "column" && wallAround(q) === view.host).map((q) => {
|
|
6670
|
+
const a = (view.mask.alongU ? q.aabb[0] : q.aabb[1]) - view.mask.start, b = (view.mask.alongU ? q.aabb[2] : q.aabb[3]) - view.mask.start;
|
|
6671
|
+
return { a, b, y0: q.y0, y1: q.y1 };
|
|
6672
|
+
});
|
|
6490
6673
|
const riders = (hostId) => structure.parts.filter((q) => q.id !== hostId && specOf(q.id)?.units && hostOf(q.id) === hostId && !structure.meshesOf(q.id).some((it) => it.mesh)).map((q) => q.id);
|
|
6491
6674
|
function shell(it, mask) {
|
|
6492
6675
|
const g0 = it.mesh.geometry, g = new THREE.BufferGeometry();
|
|
@@ -6575,6 +6758,17 @@ function installDestructionBreach(K, _shared) {
|
|
|
6575
6758
|
texture.needsUpdate = true;
|
|
6576
6759
|
return { data, texture, w, h, alongU, start: alongU ? u0 : v0, len, y0, height: y1 - y0, rect: new THREE.Vector4(alongU ? u0 : v0, y0, len, y1 - y0) };
|
|
6577
6760
|
}
|
|
6761
|
+
function besidePillars(c, pillars) {
|
|
6762
|
+
let { a, b } = c;
|
|
6763
|
+
for (const k of pillars) {
|
|
6764
|
+
if (c.y1 <= k.y0 || c.y0 >= k.y1 || b <= k.a || a >= k.b) continue;
|
|
6765
|
+
const centre = (a + b) / 2;
|
|
6766
|
+
if (centre > k.a && centre < k.b) return [];
|
|
6767
|
+
if (centre <= k.a) b = Math.min(b, k.a);
|
|
6768
|
+
else a = Math.max(a, k.b);
|
|
6769
|
+
}
|
|
6770
|
+
return b - a > 1e-3 ? [{ ...c, a, b }] : [];
|
|
6771
|
+
}
|
|
6578
6772
|
const boxDistance = (s, y, a, b, c, d) => Math.hypot(Math.max(a - s, 0, s - b), Math.max(c - y, 0, y - d));
|
|
6579
6773
|
const ellipseDistance = (s, y, cs, cy, rs, ry) => (Math.hypot((s - cs) / Math.max(rs, 1e-4), (y - cy) / Math.max(ry, 1e-4)) - 1) * Math.min(rs, ry);
|
|
6580
6774
|
function covered(c, boxes) {
|
|
@@ -6597,9 +6791,15 @@ function installDestructionBreach(K, _shared) {
|
|
|
6597
6791
|
const discs = [];
|
|
6598
6792
|
const flakes = [];
|
|
6599
6793
|
const shown = [];
|
|
6794
|
+
const pillars = pillarSpans(view);
|
|
6600
6795
|
for (const id of view.parts) {
|
|
6601
6796
|
const part = structure.byId.get(id), units2 = specOf(id).units, chips = view.chips.get(id), opening = view.openings.get(id), spalls = view.spalls.get(id);
|
|
6602
|
-
const
|
|
6797
|
+
const own = cells(part, units2, mask);
|
|
6798
|
+
const all = id === view.host ? own.flatMap((c) => besidePillars(c, pillars)) : own;
|
|
6799
|
+
if (view.fallen.has(id)) {
|
|
6800
|
+
holes.push(...all);
|
|
6801
|
+
continue;
|
|
6802
|
+
}
|
|
6603
6803
|
const thick = mask.alongU ? part.aabb[3] - part.aabb[1] : part.aabb[2] - part.aabb[0];
|
|
6604
6804
|
const mid = mask.alongU ? (part.aabb[1] + part.aabb[3]) / 2 : (part.aabb[0] + part.aabb[2]) / 2;
|
|
6605
6805
|
if (opening) discs.push({ s: along(opening.center), y: opening.center[1], r: opening.radius });
|
|
@@ -6695,52 +6895,55 @@ function installDestructionBreach(K, _shared) {
|
|
|
6695
6895
|
}
|
|
6696
6896
|
return { center: local(chip.center), along: a, up: u };
|
|
6697
6897
|
}
|
|
6898
|
+
function newView(hostId) {
|
|
6899
|
+
const items = structure.meshesOf(hostId).filter((it) => it.mesh);
|
|
6900
|
+
if (!items.length) return null;
|
|
6901
|
+
const parts = [hostId, ...riders(hostId)].filter((id) => structure.byId.get(id) && specOf(id)?.units);
|
|
6902
|
+
const mask = maskOf(hostId, parts), core = maskOf(hostId, parts);
|
|
6903
|
+
return {
|
|
6904
|
+
host: hostId,
|
|
6905
|
+
parts,
|
|
6906
|
+
items,
|
|
6907
|
+
mask,
|
|
6908
|
+
core,
|
|
6909
|
+
unitMaterial: unitsMaterial(core),
|
|
6910
|
+
shells: [],
|
|
6911
|
+
saved: null,
|
|
6912
|
+
units: null,
|
|
6913
|
+
gone: 0,
|
|
6914
|
+
pits: 0,
|
|
6915
|
+
bounds: drawnBounds(items),
|
|
6916
|
+
chips: new Map(parts.map((id) => [id, []])),
|
|
6917
|
+
spalls: new Map(parts.map((id) => [id, []])),
|
|
6918
|
+
openings: /* @__PURE__ */ new Map(),
|
|
6919
|
+
flakes: 0,
|
|
6920
|
+
fallen: /* @__PURE__ */ new Set()
|
|
6921
|
+
};
|
|
6922
|
+
}
|
|
6923
|
+
function cut(view) {
|
|
6924
|
+
if (view.saved) return;
|
|
6925
|
+
view.shells = view.items.map((it) => shell(it, view.mask));
|
|
6926
|
+
for (const m of view.shells) m.userData.behind = () => view.units;
|
|
6927
|
+
view.saved = view.items.map((it) => ({ it, v0: it.v0, data: collapseRange(it.mesh, it.v0, it.v1) }));
|
|
6928
|
+
}
|
|
6698
6929
|
function draw(partId, change) {
|
|
6699
6930
|
if (lod !== 0) return false;
|
|
6700
6931
|
const hostId = hostOf(partId);
|
|
6701
6932
|
if (!hostId || !specOf(partId)?.units) return false;
|
|
6702
|
-
|
|
6703
|
-
if (!view)
|
|
6704
|
-
const items = structure.meshesOf(hostId).filter((it) => it.mesh);
|
|
6705
|
-
if (!items.length) return false;
|
|
6706
|
-
const parts = [hostId, ...riders(hostId)].filter((id) => structure.byId.get(id) && specOf(id)?.units);
|
|
6707
|
-
if (!parts.includes(partId)) return false;
|
|
6708
|
-
const mask = maskOf(hostId, parts), core = maskOf(hostId, parts);
|
|
6709
|
-
view = {
|
|
6710
|
-
host: hostId,
|
|
6711
|
-
parts,
|
|
6712
|
-
items,
|
|
6713
|
-
mask,
|
|
6714
|
-
core,
|
|
6715
|
-
unitMaterial: unitsMaterial(core),
|
|
6716
|
-
shells: [],
|
|
6717
|
-
saved: null,
|
|
6718
|
-
units: null,
|
|
6719
|
-
gone: 0,
|
|
6720
|
-
pits: 0,
|
|
6721
|
-
bounds: drawnBounds(items),
|
|
6722
|
-
chips: new Map(parts.map((id) => [id, []])),
|
|
6723
|
-
spalls: new Map(parts.map((id) => [id, []])),
|
|
6724
|
-
openings: /* @__PURE__ */ new Map(),
|
|
6725
|
-
flakes: 0
|
|
6726
|
-
};
|
|
6727
|
-
}
|
|
6728
|
-
if (!view.chips.has(partId)) return false;
|
|
6933
|
+
const view = views.get(hostId) ?? newView(hostId);
|
|
6934
|
+
if (!view || !view.chips.has(partId)) return false;
|
|
6729
6935
|
if (change.opening) {
|
|
6730
6936
|
if (view.openings.has(partId)) return false;
|
|
6731
6937
|
view.openings.set(partId, { center: local(change.opening.center), radius: change.opening.radius });
|
|
6732
6938
|
}
|
|
6733
6939
|
if (change.chip) view.chips.get(partId).push(chipBox(change.chip, view.mask.alongU));
|
|
6940
|
+
for (const chip of change.chips ?? []) view.chips.get(partId).push(chipBox(chip, view.mask.alongU));
|
|
6734
6941
|
if (change.spall) {
|
|
6735
6942
|
const list = view.spalls.get(partId);
|
|
6736
6943
|
list.push({ center: local(change.spall.center), radius: change.spall.radius });
|
|
6737
6944
|
if (list.length > MAX_FLAKES) list.shift();
|
|
6738
6945
|
}
|
|
6739
|
-
|
|
6740
|
-
view.shells = view.items.map((it) => shell(it, view.mask));
|
|
6741
|
-
for (const m of view.shells) m.userData.behind = () => view.units;
|
|
6742
|
-
view.saved = view.items.map((it) => ({ it, v0: it.v0, data: collapseRange(it.mesh, it.v0, it.v1) }));
|
|
6743
|
-
}
|
|
6946
|
+
cut(view);
|
|
6744
6947
|
views.set(hostId, view);
|
|
6745
6948
|
if (opts.deferPaint && change.spall) dirty.add(view);
|
|
6746
6949
|
else {
|
|
@@ -6851,14 +7054,32 @@ function installDestructionBreach(K, _shared) {
|
|
|
6851
7054
|
*/
|
|
6852
7055
|
chip(event) {
|
|
6853
7056
|
if (event.torn) return false;
|
|
6854
|
-
|
|
7057
|
+
const rotation = event.rotation ?? [0, 0, 0, 1];
|
|
7058
|
+
if (event.units?.length) return draw(event.part, { chips: event.units.map((unit) => ({ center: unit.center, size: unit.size, rotation })) });
|
|
7059
|
+
return draw(event.part, { chip: { center: event.center, size: event.size ?? [0, 0, 0], rotation } });
|
|
6855
7060
|
},
|
|
6856
7061
|
/** The part broke or fell: its damage goes (the plain range stays collapsed, the renderer hides the part). */
|
|
6857
7062
|
drop(partId) {
|
|
6858
|
-
|
|
6859
|
-
if (!
|
|
7063
|
+
let host = views.get(partId) ?? [...views.values()].find((view) => view.parts.includes(partId));
|
|
7064
|
+
if (!host && lod === 0 && riders(partId).length > 0) {
|
|
7065
|
+
host = newView(partId);
|
|
7066
|
+
if (host) {
|
|
7067
|
+
cut(host);
|
|
7068
|
+
views.set(partId, host);
|
|
7069
|
+
}
|
|
7070
|
+
}
|
|
7071
|
+
if (!host) return;
|
|
7072
|
+
host.fallen.add(partId);
|
|
7073
|
+
if (host.parts.some((id) => !host.fallen.has(id))) {
|
|
7074
|
+
dirty.delete(host);
|
|
7075
|
+
paint(host);
|
|
7076
|
+
invalidate();
|
|
7077
|
+
invalidateShadow();
|
|
7078
|
+
return;
|
|
7079
|
+
}
|
|
7080
|
+
const v = host;
|
|
6860
7081
|
dispose(v);
|
|
6861
|
-
views.delete(
|
|
7082
|
+
views.delete(v.host);
|
|
6862
7083
|
if (v.saved) dropped.push(v);
|
|
6863
7084
|
},
|
|
6864
7085
|
/** LOD 0 draws the cut wall; LOD 1 and 2 give the wall its box back. */
|
|
@@ -7298,10 +7519,11 @@ function installDestructionWorld(K, shared) {
|
|
|
7298
7519
|
|
|
7299
7520
|
// src/build/build.ts
|
|
7300
7521
|
import { markKitOrigin } from "@adatechnology/game-contracts";
|
|
7522
|
+
import { isMesh as isMesh5 } from "@adatechnology/game-shapes-three";
|
|
7301
7523
|
function installBuildBuild(K, shared) {
|
|
7302
7524
|
const { THREE, cfg, rectsOf: rectsOf2, invalidateShadow, colliderChanged, VERSION: VERSION2, CARS, EPS, 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;
|
|
7303
|
-
function build(r0,
|
|
7304
|
-
opts =
|
|
7525
|
+
function build(r0, options) {
|
|
7526
|
+
const opts = options || {};
|
|
7305
7527
|
const r = applyOutbuildings(r0);
|
|
7306
7528
|
const t0 = performance.now();
|
|
7307
7529
|
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 };
|
|
@@ -7322,7 +7544,7 @@ function installBuildBuild(K, shared) {
|
|
|
7322
7544
|
shared.ctx.pieces = /* @__PURE__ */ new Map();
|
|
7323
7545
|
shared.ctx.pieceObjects = /* @__PURE__ */ new Map();
|
|
7324
7546
|
shared.ctx.structureIndex = {};
|
|
7325
|
-
for (const e of r0.structure
|
|
7547
|
+
for (const e of r0.structure?.parts || []) shared.ctx.structureIndex[e.id] = e;
|
|
7326
7548
|
{
|
|
7327
7549
|
const view = shared.ctx.panelView = panelViewOf(r0.structure, !!cfg.destruction);
|
|
7328
7550
|
shared.ctx.panelsOf = /* @__PURE__ */ new Map();
|
|
@@ -7334,17 +7556,18 @@ function installBuildBuild(K, shared) {
|
|
|
7334
7556
|
else shared.ctx.panelsOf.set(e.slab, [e]);
|
|
7335
7557
|
}
|
|
7336
7558
|
}
|
|
7337
|
-
shared.ctx.panes = r0.roof
|
|
7559
|
+
shared.ctx.panes = r0.roof?.panes || [];
|
|
7338
7560
|
shared.ctx.noPiece = false;
|
|
7339
7561
|
cursor.separate = opts.pieces === "meshes";
|
|
7340
7562
|
cursor.pc = null;
|
|
7563
|
+
shared.ctx.showPillars = opts.pillars !== "hidden";
|
|
7341
7564
|
shared.ctx.apartment = r.template === "apartment_modern";
|
|
7342
7565
|
shared.ctx.pa = Math.max(3, Math.min(20, pr.floors != null ? pr.floors : 5));
|
|
7343
7566
|
shared.ctx.pf = Math.max(1, Math.min(shared.ctx.pa, pr.floor != null ? pr.floor : 3));
|
|
7344
7567
|
shared.ctx.pu = Math.max(0, pr.unit != null ? pr.unit : 0);
|
|
7345
7568
|
shared.ctx.showBuilding = shared.ctx.apartment && (pr.showIt == null ? true : !!pr.showIt);
|
|
7346
7569
|
shared.ctx.limits = { x0: -2, z0: -2, x1: r.w + 2, z1: r.d + 2 };
|
|
7347
|
-
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;
|
|
7570
|
+
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;
|
|
7348
7571
|
shared.ctx.vegInfo = null;
|
|
7349
7572
|
terrain();
|
|
7350
7573
|
if (r.lot) {
|
|
@@ -7394,7 +7617,7 @@ function installBuildBuild(K, shared) {
|
|
|
7394
7617
|
const g = gs[gd.name];
|
|
7395
7618
|
if (!g) continue;
|
|
7396
7619
|
delete gs[gd.name];
|
|
7397
|
-
g.position.
|
|
7620
|
+
g.position.fromArray(gd.pos);
|
|
7398
7621
|
parent.add(g);
|
|
7399
7622
|
fo.gs.push(g);
|
|
7400
7623
|
}
|
|
@@ -7409,7 +7632,7 @@ function installBuildBuild(K, shared) {
|
|
|
7409
7632
|
root.add(house);
|
|
7410
7633
|
shared.mirrors.house = house;
|
|
7411
7634
|
if (shared.ctx.apartment) {
|
|
7412
|
-
const
|
|
7635
|
+
const units = r.building.units, u = units[Math.min(shared.ctx.pu, units.length - 1)];
|
|
7413
7636
|
house.position.set(u.u, shared.ctx.showBuilding ? 0 : -r.floors[0].y0, u.v);
|
|
7414
7637
|
house.rotation.y = u.ry;
|
|
7415
7638
|
shared.ctx.unitRy = u.ry;
|
|
@@ -7525,7 +7748,8 @@ function installBuildBuild(K, shared) {
|
|
|
7525
7748
|
const wallAt = (f, axis, L) => r.walls.find((w) => w.floor === f && w.axis === axis && Math.abs((axis === "u" ? w.v0 : w.u0) - L) < EPS);
|
|
7526
7749
|
for (const j of r.windows) {
|
|
7527
7750
|
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;
|
|
7528
|
-
|
|
7751
|
+
const jy0 = j.y0, jy1 = j.y1;
|
|
7752
|
+
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: () => {
|
|
7529
7753
|
}, t: 0 };
|
|
7530
7754
|
}
|
|
7531
7755
|
for (const E of mirrorsCopy) {
|
|
@@ -7568,7 +7792,7 @@ function installBuildBuild(K, shared) {
|
|
|
7568
7792
|
const countDraw = () => {
|
|
7569
7793
|
let n = 0, t = 0;
|
|
7570
7794
|
root.traverseVisible((o) => {
|
|
7571
|
-
if (o
|
|
7795
|
+
if (isMesh5(o)) {
|
|
7572
7796
|
n++;
|
|
7573
7797
|
t += (o.geometry.index ? o.geometry.index.count : o.geometry.attributes.position.count) / 3;
|
|
7574
7798
|
}
|
|
@@ -7582,8 +7806,8 @@ function installBuildBuild(K, shared) {
|
|
|
7582
7806
|
const budget = opts.drawCallBudget != null ? opts.drawCallBudget : cfg.drawCallBudget;
|
|
7583
7807
|
const stats = { 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 };
|
|
7584
7808
|
shared.ctx.tBuild = stats.tBuild;
|
|
7585
|
-
const applyLod = (
|
|
7586
|
-
n = Math.max(0, Math.min(2,
|
|
7809
|
+
const applyLod = (level) => {
|
|
7810
|
+
const n = Math.max(0, Math.min(2, level | 0));
|
|
7587
7811
|
if (n === h.lodCurrent) return;
|
|
7588
7812
|
h.lodCurrent = n;
|
|
7589
7813
|
for (const o of lodObjects) o.visible = n < 1;
|
|
@@ -7660,7 +7884,7 @@ function installBuildBuild(K, shared) {
|
|
|
7660
7884
|
lights: (() => {
|
|
7661
7885
|
const by = {};
|
|
7662
7886
|
for (const l of shared.ctx.lights) {
|
|
7663
|
-
const k = l.roomId != null ? l.roomId : l.room;
|
|
7887
|
+
const k = String(l.roomId != null ? l.roomId : l.room);
|
|
7664
7888
|
(by[k] || (by[k] = [])).push(l);
|
|
7665
7889
|
}
|
|
7666
7890
|
return { list: shared.ctx.lights, byRoom: by };
|
|
@@ -7700,9 +7924,9 @@ function installBuildBuild(K, shared) {
|
|
|
7700
7924
|
applyLod(Math.max(n, h.lodMin));
|
|
7701
7925
|
}
|
|
7702
7926
|
},
|
|
7703
|
-
show(
|
|
7927
|
+
show(options2) {
|
|
7704
7928
|
enter(h);
|
|
7705
|
-
o =
|
|
7929
|
+
const o = options2 || {};
|
|
7706
7930
|
const rr = shared.ctx.r, nA = rr.floors.length, a = o.floor == null ? -1 : o.floor, sel = a >= nA ? -1 : a, cut = !!o.cut;
|
|
7707
7931
|
for (const [k, g] of Object.entries(gs)) {
|
|
7708
7932
|
let v = true;
|
|
@@ -7722,7 +7946,7 @@ function installBuildBuild(K, shared) {
|
|
|
7722
7946
|
enter(h);
|
|
7723
7947
|
const a = targetOf(o, opt);
|
|
7724
7948
|
if (!a) return false;
|
|
7725
|
-
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);
|
|
7949
|
+
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);
|
|
7726
7950
|
},
|
|
7727
7951
|
message() {
|
|
7728
7952
|
return shared.inter.msg && performance.now() < shared.inter.msg.until ? shared.inter.msg.text : null;
|
|
@@ -7779,13 +8003,13 @@ function installBuildBuild(K, shared) {
|
|
|
7779
8003
|
}
|
|
7780
8004
|
return null;
|
|
7781
8005
|
},
|
|
7782
|
-
partAt(p,
|
|
7783
|
-
tol =
|
|
8006
|
+
partAt(p, tolerance) {
|
|
8007
|
+
const tol = tolerance || 0.05;
|
|
7784
8008
|
let m = null;
|
|
7785
8009
|
for (const k in parts) {
|
|
7786
|
-
const
|
|
8010
|
+
const part = parts[k], a = part.aabb;
|
|
7787
8011
|
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) {
|
|
7788
|
-
m =
|
|
8012
|
+
m = part;
|
|
7789
8013
|
break;
|
|
7790
8014
|
}
|
|
7791
8015
|
}
|
|
@@ -7796,8 +8020,8 @@ function installBuildBuild(K, shared) {
|
|
|
7796
8020
|
destruction.deactivate();
|
|
7797
8021
|
if (h.IV) ivDispose(h);
|
|
7798
8022
|
root.traverse((o) => {
|
|
7799
|
-
if (o
|
|
7800
|
-
if (o.type === "Reflector" && o.dispose) o.dispose();
|
|
8023
|
+
if (isMesh5(o) && o.geometry && !o.geometry.userData.shared) o.geometry.dispose();
|
|
8024
|
+
if (o.type === "Reflector" && "dispose" in o && typeof o.dispose === "function") o.dispose();
|
|
7801
8025
|
});
|
|
7802
8026
|
root.removeFromParent();
|
|
7803
8027
|
},
|
|
@@ -7805,7 +8029,8 @@ function installBuildBuild(K, shared) {
|
|
|
7805
8029
|
};
|
|
7806
8030
|
return res;
|
|
7807
8031
|
}
|
|
7808
|
-
|
|
8032
|
+
const defined = { build };
|
|
8033
|
+
Object.assign(K, defined);
|
|
7809
8034
|
}
|
|
7810
8035
|
|
|
7811
8036
|
// src/build/api.ts
|
|
@@ -7827,11 +8052,13 @@ function buildApi(K, shared) {
|
|
|
7827
8052
|
lighting,
|
|
7828
8053
|
effectLights,
|
|
7829
8054
|
setNight(n) {
|
|
7830
|
-
shared.mats.glass
|
|
7831
|
-
|
|
8055
|
+
const glass = shared.mats.glass;
|
|
8056
|
+
glass.emissive.set(n ? 9067040 : 0);
|
|
8057
|
+
glass.opacity = n ? 0.4 : 0.24;
|
|
7832
8058
|
},
|
|
7833
8059
|
/** 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. */
|
|
7834
8060
|
deferredQueue: () => K.breachPaintQueue,
|
|
8061
|
+
/* the destruction side is typed with the breach */
|
|
7835
8062
|
cars: { model: carModel, group: carGroup, info: (k, seed) => {
|
|
7836
8063
|
const m = carModel(k, seed);
|
|
7837
8064
|
return m && { parts: m.parts.length, tris: m.tris, L: m.L, W: m.W, H: m.H };
|
|
@@ -8096,7 +8323,7 @@ function createHouseScenarios(text, at = SPECIMEN_AT) {
|
|
|
8096
8323
|
const stopListening = () => {
|
|
8097
8324
|
for (const off of listening.splice(0)) off?.();
|
|
8098
8325
|
};
|
|
8099
|
-
const collapsed = (list) => list.
|
|
8326
|
+
const collapsed = (list) => list.flatMap((e) => e.type === "collapse" ? e.parts.map((p) => p.id || p) : []);
|
|
8100
8327
|
const whole = (room, oid, pid) => {
|
|
8101
8328
|
const p = room.world.part(oid, pid);
|
|
8102
8329
|
return !!p && p.status !== "broken" && !p.stripped;
|
|
@@ -8133,10 +8360,10 @@ function createHouseScenarios(text, at = SPECIMEN_AT) {
|
|
|
8133
8360
|
const list = events(room);
|
|
8134
8361
|
const columns = groundColumns(parts);
|
|
8135
8362
|
const laj = slabs(parts);
|
|
8136
|
-
const first = columns[0];
|
|
8137
|
-
const mate = columns.
|
|
8138
|
-
|
|
8139
|
-
blunt(room, oid,
|
|
8363
|
+
const first = columns.find((p) => !/^wall_column_/.test(p.id)) ?? columns[0];
|
|
8364
|
+
const mate = columns.filter((p) => p !== first && !/^wall_column_/.test(p.id)).filter((p) => Math.abs(p.position[0] - first.position[0]) < 0.5).sort((a, b) => Math.abs(b.position[2] - first.position[2]) - Math.abs(a.position[2] - first.position[2]))[0] ?? columns[1];
|
|
8365
|
+
const along = columns.filter((p) => /^wall_column_/.test(p.id) && Math.abs(p.position[0] - first.position[0]) < 0.5);
|
|
8366
|
+
for (const p of [first, mate, ...along]) blunt(room, oid, p.id, centre(p.id), 3e6);
|
|
8140
8367
|
step(90);
|
|
8141
8368
|
const fell = collapsed(list);
|
|
8142
8369
|
expect(laj.some((id) => fell.includes(id)), fill(T.two_slab_fell, { n: fell.length }));
|
|
@@ -8457,9 +8684,10 @@ function createFloorplanTestModule(options = {}) {
|
|
|
8457
8684
|
return best;
|
|
8458
8685
|
};
|
|
8459
8686
|
const eyeOf = (p) => {
|
|
8687
|
+
const T = THREE;
|
|
8460
8688
|
const camera = host?.camera;
|
|
8461
8689
|
const at = toLocal(p, camera.position.x, camera.position.y, camera.position.z);
|
|
8462
|
-
const forward = new
|
|
8690
|
+
const forward = new T.Vector3(0, 0, -1).applyQuaternion(camera.quaternion).transformDirection(new T.Matrix4().copy(p.house.group.matrixWorld).invert());
|
|
8463
8691
|
return { x: at.x, y: at.y, z: at.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))) };
|
|
8464
8692
|
};
|
|
8465
8693
|
const blocked = (x, z, radius) => {
|
|
@@ -8475,8 +8703,9 @@ function createFloorplanTestModule(options = {}) {
|
|
|
8475
8703
|
const standAt = (p, u, v, floor, lookU, lookV) => {
|
|
8476
8704
|
if (!host?.bench) return;
|
|
8477
8705
|
const y = p.house.y0(floor) + EYE;
|
|
8478
|
-
const
|
|
8479
|
-
const
|
|
8706
|
+
const T = THREE;
|
|
8707
|
+
const eye = p.house.group.localToWorld(new T.Vector3(u, y, v));
|
|
8708
|
+
const target = p.house.group.localToWorld(new T.Vector3(lookU, y - 0.1, lookV));
|
|
8480
8709
|
host.bench.look([eye.x, eye.y, eye.z], [target.x, target.y, target.z]);
|
|
8481
8710
|
floorNow = floor;
|
|
8482
8711
|
};
|
|
@@ -8526,16 +8755,17 @@ function createFloorplanTestModule(options = {}) {
|
|
|
8526
8755
|
host?.log(fill(text.steps.door, { text: String(target.text) }));
|
|
8527
8756
|
};
|
|
8528
8757
|
const doorReach = (p, fo) => {
|
|
8758
|
+
const T = THREE;
|
|
8529
8759
|
const g = fo.gs[0];
|
|
8530
8760
|
const pivot = fo.handles[0].pivot;
|
|
8531
8761
|
const at = (angle) => {
|
|
8532
8762
|
const c = Math.cos(angle);
|
|
8533
8763
|
const s = Math.sin(angle);
|
|
8534
|
-
const v = new
|
|
8764
|
+
const v = new T.Vector3(pivot[0] * c + pivot[2] * s, pivot[1], -pivot[0] * s + pivot[2] * c).add(g.position);
|
|
8535
8765
|
return g.parent ? g.parent.localToWorld(v) : v;
|
|
8536
8766
|
};
|
|
8537
8767
|
const camera = host?.camera;
|
|
8538
|
-
const eye = new
|
|
8768
|
+
const eye = new T.Vector3(camera.position.x, 0, camera.position.z);
|
|
8539
8769
|
const flat = (v) => Math.hypot(v.x - eye.x, v.z - eye.z);
|
|
8540
8770
|
const closed = at(0);
|
|
8541
8771
|
const open = at(fo.rot);
|
|
@@ -8543,9 +8773,9 @@ function createFloorplanTestModule(options = {}) {
|
|
|
8543
8773
|
return {
|
|
8544
8774
|
handle: () => {
|
|
8545
8775
|
g.updateMatrixWorld(true);
|
|
8546
|
-
return g.localToWorld(new
|
|
8776
|
+
return g.localToWorld(new T.Vector3(pivot[0], pivot[1], pivot[2])).toArray();
|
|
8547
8777
|
},
|
|
8548
|
-
hinge: () => g.getWorldPosition(new
|
|
8778
|
+
hinge: () => g.getWorldPosition(new T.Vector3()).toArray(),
|
|
8549
8779
|
seconds: fo.locked || fo.blockedFlag ? 0.6 : 0.55,
|
|
8550
8780
|
pull: opening ? flat(open) <= flat(closed) : flat(closed) <= flat(open),
|
|
8551
8781
|
locked: !!(fo.locked || fo.blockedFlag)
|
|
@@ -8879,4 +9109,4 @@ export {
|
|
|
8879
9109
|
FLOORPLAN_AREA_ID,
|
|
8880
9110
|
createFloorplanTestModule
|
|
8881
9111
|
};
|
|
8882
|
-
//# sourceMappingURL=chunk-
|
|
9112
|
+
//# sourceMappingURL=chunk-Y3Y7NYOL.js.map
|