@adatechnology/game-floorplan-three 0.9.0 → 0.9.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/index.global.js +243 -165
- package/dist/index.global.js.map +1 -1
- package/package.json +15 -15
package/dist/index.global.js
CHANGED
|
@@ -70,7 +70,7 @@ var GameFloorplanThree = (() => {
|
|
|
70
70
|
shade: () => shade
|
|
71
71
|
});
|
|
72
72
|
|
|
73
|
-
// ../game-shapes/dist/chunk-
|
|
73
|
+
// ../game-shapes/dist/chunk-M5N2SHNL.js
|
|
74
74
|
function canonicalJson(value) {
|
|
75
75
|
if (value === null) return "null";
|
|
76
76
|
if (typeof value === "number") return Object.is(value, -0) ? "-0" : Number.isFinite(value) ? String(value) : JSON.stringify(String(value));
|
|
@@ -1227,13 +1227,13 @@ var GameFloorplanThree = (() => {
|
|
|
1227
1227
|
uvArray.push(x);
|
|
1228
1228
|
uvArray.push(y);
|
|
1229
1229
|
};
|
|
1230
|
-
const
|
|
1230
|
+
const at2 = (index, axis) => verticesArray[index * 3 + axis];
|
|
1231
1231
|
const f3 = (a, b, c) => {
|
|
1232
1232
|
addVertex(a);
|
|
1233
1233
|
addVertex(b);
|
|
1234
1234
|
addVertex(c);
|
|
1235
1235
|
const nextIndex = verticesArray.length / 3;
|
|
1236
|
-
for (const index of [nextIndex - 3, nextIndex - 2, nextIndex - 1]) addUV(
|
|
1236
|
+
for (const index of [nextIndex - 3, nextIndex - 2, nextIndex - 1]) addUV(at2(index, 0), at2(index, 1));
|
|
1237
1237
|
};
|
|
1238
1238
|
const f4 = (a, b, c, d) => {
|
|
1239
1239
|
addVertex(a);
|
|
@@ -1247,8 +1247,8 @@ var GameFloorplanThree = (() => {
|
|
|
1247
1247
|
const iB = nextIndex - 3;
|
|
1248
1248
|
const iC = nextIndex - 2;
|
|
1249
1249
|
const iD = nextIndex - 1;
|
|
1250
|
-
const byX = Math.abs(
|
|
1251
|
-
const uv = (index) => [byX ?
|
|
1250
|
+
const byX = Math.abs(at2(iA, 1) - at2(iB, 1)) < Math.abs(at2(iA, 0) - at2(iB, 0));
|
|
1251
|
+
const uv = (index) => [byX ? at2(index, 0) : at2(index, 1), 1 - at2(index, 2)];
|
|
1252
1252
|
const uvs = [uv(iA), uv(iB), uv(iC), uv(iD)];
|
|
1253
1253
|
for (const k of [0, 1, 3, 1, 2, 3]) addUV(...uvs[k]);
|
|
1254
1254
|
};
|
|
@@ -1353,8 +1353,8 @@ var GameFloorplanThree = (() => {
|
|
|
1353
1353
|
groups: []
|
|
1354
1354
|
};
|
|
1355
1355
|
}
|
|
1356
|
-
function make(
|
|
1357
|
-
switch (kind) {
|
|
1356
|
+
function make(p) {
|
|
1357
|
+
switch (p.kind) {
|
|
1358
1358
|
case "box": {
|
|
1359
1359
|
const size = p.size ?? [1, 1, 1];
|
|
1360
1360
|
const segments = p.segments ?? [1, 1, 1];
|
|
@@ -1383,7 +1383,7 @@ var GameFloorplanThree = (() => {
|
|
|
1383
1383
|
case "mesh":
|
|
1384
1384
|
return mesh(p);
|
|
1385
1385
|
default:
|
|
1386
|
-
throw new Error(`game-shapes: unknown primitive kind "${String(kind)}"`);
|
|
1386
|
+
throw new Error(`game-shapes: unknown primitive kind "${String(p.kind)}"`);
|
|
1387
1387
|
}
|
|
1388
1388
|
}
|
|
1389
1389
|
var templates = /* @__PURE__ */ new Map();
|
|
@@ -1391,7 +1391,7 @@ var GameFloorplanThree = (() => {
|
|
|
1391
1391
|
var stats = { hits: 0, misses: 0 };
|
|
1392
1392
|
function buildPrimitive(node, options = {}) {
|
|
1393
1393
|
const parameters = primitiveParameters(node, options);
|
|
1394
|
-
if (node.kind === "mesh" || templateLimit === 0) return make(node
|
|
1394
|
+
if (node.kind === "mesh" || templateLimit === 0) return make({ ...node, ...parameters });
|
|
1395
1395
|
const key = `${node.kind}:${canonicalJson(parameters)}`;
|
|
1396
1396
|
const cached = templates.get(key);
|
|
1397
1397
|
if (cached) {
|
|
@@ -1401,7 +1401,7 @@ var GameFloorplanThree = (() => {
|
|
|
1401
1401
|
return cached;
|
|
1402
1402
|
}
|
|
1403
1403
|
stats.misses++;
|
|
1404
|
-
const built = make(node
|
|
1404
|
+
const built = make({ ...node, ...parameters });
|
|
1405
1405
|
templates.set(key, built);
|
|
1406
1406
|
if (templates.size > templateLimit) templates.delete(templates.keys().next().value);
|
|
1407
1407
|
return built;
|
|
@@ -1499,7 +1499,7 @@ var GameFloorplanThree = (() => {
|
|
|
1499
1499
|
const positions2 = new Float32Array(total * 3);
|
|
1500
1500
|
const normals = new Float32Array(total * 3);
|
|
1501
1501
|
const uvs = new Float32Array(total * 2);
|
|
1502
|
-
let
|
|
1502
|
+
let at2 = 0;
|
|
1503
1503
|
for (const piece2 of pieces) {
|
|
1504
1504
|
const e = piece2.matrix;
|
|
1505
1505
|
const nm = normalMatrix(e);
|
|
@@ -1513,15 +1513,15 @@ var GameFloorplanThree = (() => {
|
|
|
1513
1513
|
if (piece2.normals) n[k * 3 + c] = piece2.normals[i * 3 + c];
|
|
1514
1514
|
}
|
|
1515
1515
|
if (piece2.uvs) {
|
|
1516
|
-
uvs[(
|
|
1517
|
-
uvs[(
|
|
1516
|
+
uvs[(at2 + k) * 2] = piece2.uvs[i * 2];
|
|
1517
|
+
uvs[(at2 + k) * 2 + 1] = piece2.uvs[i * 2 + 1];
|
|
1518
1518
|
}
|
|
1519
1519
|
}
|
|
1520
1520
|
for (let k = 0; k < count; k++) {
|
|
1521
1521
|
const q = transformPoint(e, p[k * 3], p[k * 3 + 1], p[k * 3 + 2]);
|
|
1522
|
-
positions2[(
|
|
1523
|
-
positions2[(
|
|
1524
|
-
positions2[(
|
|
1522
|
+
positions2[(at2 + k) * 3] = q[0];
|
|
1523
|
+
positions2[(at2 + k) * 3 + 1] = q[1];
|
|
1524
|
+
positions2[(at2 + k) * 3 + 2] = q[2];
|
|
1525
1525
|
const x = n[k * 3];
|
|
1526
1526
|
const y = n[k * 3 + 1];
|
|
1527
1527
|
const z = n[k * 3 + 2];
|
|
@@ -1529,11 +1529,11 @@ var GameFloorplanThree = (() => {
|
|
|
1529
1529
|
const vy = nm[1] * x + nm[4] * y + nm[7] * z;
|
|
1530
1530
|
const vz = nm[2] * x + nm[5] * y + nm[8] * z;
|
|
1531
1531
|
const s = 1 / (Math.sqrt(vx * vx + vy * vy + vz * vz) || 1);
|
|
1532
|
-
normals[(
|
|
1533
|
-
normals[(
|
|
1534
|
-
normals[(
|
|
1532
|
+
normals[(at2 + k) * 3] = vx * s;
|
|
1533
|
+
normals[(at2 + k) * 3 + 1] = vy * s;
|
|
1534
|
+
normals[(at2 + k) * 3 + 2] = vz * s;
|
|
1535
1535
|
}
|
|
1536
|
-
|
|
1536
|
+
at2 += count;
|
|
1537
1537
|
}
|
|
1538
1538
|
return { positions: positions2, normals, uvs };
|
|
1539
1539
|
}
|
|
@@ -3408,17 +3408,17 @@ var GameFloorplanThree = (() => {
|
|
|
3408
3408
|
const index = geometry2.index ? geometry2.index.array : null;
|
|
3409
3409
|
const count = index ? index.length : position.count;
|
|
3410
3410
|
for (let item = 0; item < count; item++) {
|
|
3411
|
-
const
|
|
3412
|
-
vertex.fromBufferAttribute(position,
|
|
3411
|
+
const at2 = index ? index[item] : item;
|
|
3412
|
+
vertex.fromBufferAttribute(position, at2).applyMatrix4(matrix);
|
|
3413
3413
|
positions2.push(vertex.x, vertex.y, vertex.z);
|
|
3414
|
-
if (normalAttribute) normal.fromBufferAttribute(normalAttribute,
|
|
3414
|
+
if (normalAttribute) normal.fromBufferAttribute(normalAttribute, at2).applyMatrix3(normalMatrix2).normalize();
|
|
3415
3415
|
else normal.set(0, 1, 0);
|
|
3416
3416
|
normals.push(normal.x, normal.y, normal.z);
|
|
3417
3417
|
color2.copy(material2.color || color2.set(1, 1, 1)).convertLinearToSRGB();
|
|
3418
3418
|
if (sample && uv && material2.map) {
|
|
3419
3419
|
const repeat = material2.map.repeat;
|
|
3420
|
-
const u = (uv.getX(
|
|
3421
|
-
const v = (uv.getY(
|
|
3420
|
+
const u = (uv.getX(at2) * repeat.x % 1 + 1) % 1;
|
|
3421
|
+
const v = (uv.getY(at2) * repeat.y % 1 + 1) % 1;
|
|
3422
3422
|
const pixelX = Math.min(sample.width - 1, u * sample.width | 0);
|
|
3423
3423
|
const pixelY = Math.min(sample.height - 1, (1 - v) * sample.height | 0);
|
|
3424
3424
|
const offset = (pixelY * sample.width + pixelX) * 4;
|
|
@@ -9871,8 +9871,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9871
9871
|
// was `maquina`
|
|
9872
9872
|
});
|
|
9873
9873
|
var OWN_TYPES = Object.freeze({ lamp: true, gas_piped: true });
|
|
9874
|
+
var sourceOf = (result) => result;
|
|
9874
9875
|
var ADAPTER_VERSION = "0.3.0";
|
|
9875
9876
|
var r3 = (n) => Math.round(n * 1e3) / 1e3;
|
|
9877
|
+
var at = (it) => ({ x: it.x ?? 0, z: it.z ?? 0, ry: it.ry ?? 0 });
|
|
9876
9878
|
function mergeRegistry(base, extra) {
|
|
9877
9879
|
const out = { ...base };
|
|
9878
9880
|
if (extra) {
|
|
@@ -9891,14 +9893,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9891
9893
|
});
|
|
9892
9894
|
function create2(options = {}) {
|
|
9893
9895
|
const opts = options || {};
|
|
9894
|
-
const GI = opts.GameInteractables;
|
|
9895
|
-
const HH = opts.GameInteractablesHousehold;
|
|
9896
9896
|
const locale = opts.locale || "pt-BR";
|
|
9897
9897
|
const msg = createTranslator2(locale, opts.messages);
|
|
9898
|
-
if (!
|
|
9898
|
+
if (!opts.GameInteractables || !opts.GameInteractablesHousehold) throw new Error(msg("error.missingKit"));
|
|
9899
|
+
const GI = opts.GameInteractables;
|
|
9900
|
+
const HH = opts.GameInteractablesHousehold;
|
|
9899
9901
|
const region = opts.region || "br";
|
|
9900
9902
|
const hh = HH.createHousehold({ locale, region });
|
|
9901
9903
|
const householdTypes = new Set(hh.types.map((t) => t.id));
|
|
9904
|
+
const recorderApi = () => HH.createRecorder().api;
|
|
9902
9905
|
const worlds = /* @__PURE__ */ new WeakMap();
|
|
9903
9906
|
const typeMap = mergeRegistry(TYPE_MAP, opts.typeMap);
|
|
9904
9907
|
const contentMap = mergeRegistry(CONTENT_MAP, opts.contentMap);
|
|
@@ -9934,7 +9937,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9934
9937
|
function colorOf(res, color2) {
|
|
9935
9938
|
if (color2 == null) return void 0;
|
|
9936
9939
|
if (typeof color2 === "number") return color2;
|
|
9937
|
-
const v = res.colors && res.colors[color2];
|
|
9940
|
+
const v = res.colors && res.colors[String(color2)];
|
|
9938
9941
|
return typeof v === "number" ? v : void 0;
|
|
9939
9942
|
}
|
|
9940
9943
|
function paletteOf(res) {
|
|
@@ -9963,17 +9966,18 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9963
9966
|
drawerItem: (s) => drawerItems.has(s.itemId)
|
|
9964
9967
|
};
|
|
9965
9968
|
const itemOfContent = (c) => {
|
|
9966
|
-
const
|
|
9969
|
+
const group = stackGroup(c);
|
|
9970
|
+
const id = contentMap[c.itemId] || (hh.items[c.itemId] ? c.itemId : null) || (group != null ? contentByGroup[group] : void 0) || contentFallback;
|
|
9967
9971
|
return hh.items[id] ? id : contentFallback;
|
|
9968
9972
|
};
|
|
9969
9973
|
const volume = (d) => d.size[0] * d.size[1] * d.size[2];
|
|
9970
9974
|
const candidates = (id, objectType) => {
|
|
9971
9975
|
const def = hh.items[id];
|
|
9972
|
-
const siblings = Object.values(hh.items).filter((i) => i.category === def
|
|
9976
|
+
const siblings = Object.values(hh.items).filter((i) => i.category === def?.category && i.id !== id).sort((a, b) => volume(a) - volume(b) || (a.id < b.id ? -1 : 1));
|
|
9973
9977
|
return [id].concat(siblings.map((i) => i.id), substitutes[objectType] || []);
|
|
9974
9978
|
};
|
|
9975
9979
|
function distribute(type, probeItem, stacks) {
|
|
9976
|
-
const spec = hh.build(type, probeItem,
|
|
9980
|
+
const spec = hh.build(type, probeItem, recorderApi());
|
|
9977
9981
|
const conts = spec.containers || [];
|
|
9978
9982
|
const contents = {};
|
|
9979
9983
|
for (const c of conts) contents[c.id] = c.slots.map(() => null);
|
|
@@ -10004,8 +10008,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10004
10008
|
}
|
|
10005
10009
|
return { contents, rejected };
|
|
10006
10010
|
}
|
|
10007
|
-
function plan(
|
|
10008
|
-
|
|
10011
|
+
function plan(source, options2 = {}) {
|
|
10012
|
+
const res = sourceOf(source);
|
|
10013
|
+
const popts = options2 || {};
|
|
10009
10014
|
const o = { ox: popts.originX || 0, oz: popts.originZ || 0, inw: popts.inw || 1, base: popts.base || 0 };
|
|
10010
10015
|
const K = conv(o);
|
|
10011
10016
|
const floorSel = popts.floor;
|
|
@@ -10069,7 +10074,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10069
10074
|
const item = {
|
|
10070
10075
|
x: K.x(m.x),
|
|
10071
10076
|
z: K.z(m.z),
|
|
10072
|
-
ry: m.frontU != null ? K.ry(m.frontU, m.frontV) : r3(m.ry || 0),
|
|
10077
|
+
ry: m.frontU != null ? K.ry(m.frontU, m.frontV ?? 0) : r3(m.ry || 0),
|
|
10073
10078
|
w: m.w,
|
|
10074
10079
|
d: m.d,
|
|
10075
10080
|
h: m.h,
|
|
@@ -10082,7 +10087,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10082
10087
|
return item;
|
|
10083
10088
|
}
|
|
10084
10089
|
function entry2(id, type, item, origin, floor, extra) {
|
|
10085
|
-
|
|
10090
|
+
const e = { id, type, item, origin, floor, floorY: floorYOf(res, o, floor), connections: {} };
|
|
10091
|
+
return Object.assign(e, extra || {});
|
|
10086
10092
|
}
|
|
10087
10093
|
function store(targets, stacks) {
|
|
10088
10094
|
let rest2 = stacks || [];
|
|
@@ -10095,10 +10101,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10095
10101
|
}
|
|
10096
10102
|
const hidden = [];
|
|
10097
10103
|
function distRect(c, x, z) {
|
|
10098
|
-
const
|
|
10099
|
-
const
|
|
10100
|
-
const
|
|
10101
|
-
const
|
|
10104
|
+
const ci = at(c.item);
|
|
10105
|
+
const dx = x - ci.x;
|
|
10106
|
+
const dz = z - ci.z;
|
|
10107
|
+
const s = Math.sin(ci.ry);
|
|
10108
|
+
const co = Math.cos(ci.ry);
|
|
10102
10109
|
const lx = dx * co - dz * s;
|
|
10103
10110
|
const lz = dx * s + dz * co;
|
|
10104
10111
|
return Math.hypot(Math.max(Math.abs(lx) - (c.item.w || 0) / 2, 0), Math.max(Math.abs(lz) - (c.item.d || 0) / 2, 0));
|
|
@@ -10106,9 +10113,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10106
10113
|
function hideCylinders() {
|
|
10107
10114
|
for (const b of hidden) {
|
|
10108
10115
|
let target = null;
|
|
10116
|
+
const bi = at(b.item);
|
|
10109
10117
|
for (const c2 of result.items) {
|
|
10110
10118
|
if (c2.type !== "kitchen_cabinet_base" || c2.floor !== b.floor) continue;
|
|
10111
|
-
const dist = distRect(c2,
|
|
10119
|
+
const dist = distRect(c2, bi.x, bi.z);
|
|
10112
10120
|
if (!target || dist < target.dist) target = { c: c2, dist };
|
|
10113
10121
|
}
|
|
10114
10122
|
if (!target) {
|
|
@@ -10116,16 +10124,18 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10116
10124
|
continue;
|
|
10117
10125
|
}
|
|
10118
10126
|
const c = target.c;
|
|
10119
|
-
const spec = hh.build(c.type, c.item,
|
|
10120
|
-
const
|
|
10121
|
-
const
|
|
10127
|
+
const spec = hh.build(c.type, c.item, recorderApi());
|
|
10128
|
+
const ci = at(c.item);
|
|
10129
|
+
const sn = Math.sin(ci.ry);
|
|
10130
|
+
const cs = Math.cos(ci.ry);
|
|
10122
10131
|
let door = null;
|
|
10123
10132
|
for (const it of spec.interactions || []) {
|
|
10124
|
-
const
|
|
10125
|
-
|
|
10126
|
-
|
|
10127
|
-
const
|
|
10128
|
-
const
|
|
10133
|
+
const action = it.action;
|
|
10134
|
+
const pt = action.do === "toggle_part" ? (spec.parts || []).find((q) => q.id === action.part) : null;
|
|
10135
|
+
if (!pt || !pt.motion || pt.motion.kind !== "hinge") continue;
|
|
10136
|
+
const wx = ci.x + it.pos[0] * cs + it.pos[2] * sn;
|
|
10137
|
+
const wz = ci.z - it.pos[0] * sn + it.pos[2] * cs;
|
|
10138
|
+
const dist = Math.hypot(wx - bi.x, wz - bi.z);
|
|
10129
10139
|
if (!door || dist < door.dist) door = { id: pt.id, dist };
|
|
10130
10140
|
}
|
|
10131
10141
|
if (!door) {
|
|
@@ -10155,9 +10165,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10155
10165
|
const campCylinder = firstOfType("gas_canister");
|
|
10156
10166
|
function planFireplace(m, e, item) {
|
|
10157
10167
|
const def = hh.types.find((t) => t.id === "fireplace");
|
|
10158
|
-
const lack = (def.d - m.d) / 2;
|
|
10159
|
-
|
|
10160
|
-
item.
|
|
10168
|
+
const lack = ((def ? def.d : m.d) - m.d) / 2;
|
|
10169
|
+
const p = at(item);
|
|
10170
|
+
item.x = r3(p.x + Math.sin(p.ry) * lack);
|
|
10171
|
+
item.z = r3(p.z + Math.cos(p.ry) * lack);
|
|
10161
10172
|
const room = (res.rooms || []).find((c) => c.id === m.room && c.floor === m.floor);
|
|
10162
10173
|
const f = (res.floors || []).find((x) => x.index === m.floor);
|
|
10163
10174
|
item.h = r3(room && room.ceiling || f && f.ceiling || 2.6);
|
|
@@ -10185,7 +10196,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10185
10196
|
e.connections.gas = m.gas || "cylinder";
|
|
10186
10197
|
e.connections.cylinder = m.cylinder || null;
|
|
10187
10198
|
}
|
|
10188
|
-
if (map.type === "gas_bottle") result.cylinders.push({ id: e.id, stove: m.link
|
|
10199
|
+
if (map.type === "gas_bottle") result.cylinders.push({ id: e.id, stove: typeof m.link === "string" ? m.link : null, place: m.placement || null });
|
|
10189
10200
|
if (map.type === "gas_canister") {
|
|
10190
10201
|
result.canisters.push(e.id);
|
|
10191
10202
|
if (campCylinder && campCylinder.id === m.id && campStove) result.cylinders.push({ id: e.id, stove: campStove.id, place: null });
|
|
@@ -10209,7 +10220,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10209
10220
|
push(e);
|
|
10210
10221
|
}
|
|
10211
10222
|
function planCompound(m, kind) {
|
|
10212
|
-
const ry = m.frontU != null ? K.ry(m.frontU, m.frontV) : r3(m.ry || 0);
|
|
10223
|
+
const ry = m.frontU != null ? K.ry(m.frontU, m.frontV ?? 0) : r3(m.ry || 0);
|
|
10213
10224
|
const cx = K.x(m.x);
|
|
10214
10225
|
const cz = K.z(m.z);
|
|
10215
10226
|
const part = (id, type, w, d, h, y, lx, lz) => {
|
|
@@ -10261,11 +10272,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10261
10272
|
} else {
|
|
10262
10273
|
const basin = part(m.id, "sink_bathroom", m.w, m.d, m.h + 0.2, 0, 0, 0);
|
|
10263
10274
|
list2.push(basin);
|
|
10264
|
-
|
|
10265
|
-
|
|
10275
|
+
const own = contents[m.id];
|
|
10276
|
+
if (own) {
|
|
10277
|
+
if (own.length) {
|
|
10266
10278
|
const cabinet = part(m.id + "#cabinet", "bathroom_cabinet", Math.max(0.45, Math.min(0.6, m.w)), 0.15, 0.75, 1.3, 0, -(m.d / 2) + 0.075);
|
|
10267
10279
|
list2.push(cabinet);
|
|
10268
|
-
store([["bathroom_cabinet", cabinet.item], ["sink_bathroom", basin.item]],
|
|
10280
|
+
store([["bathroom_cabinet", cabinet.item], ["sink_bathroom", basin.item]], own);
|
|
10269
10281
|
} else {
|
|
10270
10282
|
store([["sink_bathroom", basin.item]], []);
|
|
10271
10283
|
}
|
|
@@ -10305,7 +10317,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10305
10317
|
result.chairs = [];
|
|
10306
10318
|
if (opts.chairs !== false && popts.chairs !== false) {
|
|
10307
10319
|
const blocked = blockedOf(res, { originX: o.ox, originZ: o.oz, inw: o.inw });
|
|
10308
|
-
const floorKind = (q) => !q.decor && !q.flat && (q.y || 0) < 0.9 && q.aabb;
|
|
10320
|
+
const floorKind = (q) => !q.decor && !q.flat && (q.y || 0) < 0.9 && !!q.aabb;
|
|
10309
10321
|
const placed = [];
|
|
10310
10322
|
const free = (m, cu, cv, half) => {
|
|
10311
10323
|
const a = [cu - half + 0.03, cv - half + 0.03, cu + half - 0.03, cv + half - 0.03];
|
|
@@ -10321,8 +10333,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10321
10333
|
for (const m of res.items || []) {
|
|
10322
10334
|
const mode = chairTables[m.type];
|
|
10323
10335
|
if (!mode || !onFloor(m.floor, m.outdoor) || m.frontU == null) continue;
|
|
10324
|
-
const
|
|
10325
|
-
const
|
|
10336
|
+
const fv = m.frontV ?? 0;
|
|
10337
|
+
const f = [m.frontU, fv];
|
|
10338
|
+
const pp = [-fv, m.frontU];
|
|
10326
10339
|
const seats = [];
|
|
10327
10340
|
if (mode === "dining") {
|
|
10328
10341
|
const n = Math.max(1, Math.min(3, Math.floor((m.w - 0.1) / 0.55)));
|
|
@@ -10391,8 +10404,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10391
10404
|
const item = { x: K.x(s.u), z: K.z(s.v), ry: K.ry(s.frontU, s.frontV), y: s.y, seed: seedOf2(s.id) };
|
|
10392
10405
|
item.controls = (s.controls || []).map((id) => id + ":lamp");
|
|
10393
10406
|
const e = entry2(s.id, "wall_switch", item, s.id, s.floor);
|
|
10394
|
-
|
|
10395
|
-
e.
|
|
10407
|
+
const controls = (s.controls || []).slice();
|
|
10408
|
+
e.connections.controls = controls;
|
|
10409
|
+
e.lit = controls.some((id) => result.items.find((x) => x.id === id)?.lit === true);
|
|
10396
10410
|
if (floorSel == null) {
|
|
10397
10411
|
for (const id of s.controls || []) if (!lights.has(id)) result.warnings.push(msg("warn.switchUnknownLamp", { id: s.id, lamp: id }));
|
|
10398
10412
|
}
|
|
@@ -10432,7 +10446,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10432
10446
|
seed: seedOf2("panel"),
|
|
10433
10447
|
circuits: circuits.map((c) => ({ id: c.id, label: c.room }))
|
|
10434
10448
|
};
|
|
10435
|
-
if (!item.circuits
|
|
10449
|
+
if (!item.circuits?.length) delete item.circuits;
|
|
10436
10450
|
const e = entry2("panel", "electrical_panel", item, "panel", q.floor);
|
|
10437
10451
|
push(e);
|
|
10438
10452
|
result.panel = e.id;
|
|
@@ -10454,10 +10468,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10454
10468
|
}
|
|
10455
10469
|
}
|
|
10456
10470
|
const piped = result.items.filter((e) => e.type === "stove" && e.connections.gas === "piped");
|
|
10457
|
-
|
|
10471
|
+
const firstPiped = piped[0];
|
|
10472
|
+
if (firstPiped) {
|
|
10458
10473
|
const med = utilities.gas && utilities.gas.meter;
|
|
10459
|
-
const ref = med ? { x: K.x(med.u), z: K.z(med.v), y: med.y || 1 } : { x:
|
|
10460
|
-
const e = entry2("piped_gas", "gas_piped", { x: ref.x, z: ref.z, ry: 0, y: ref.y, seed: seedOf2("piped_gas") }, "piped_gas",
|
|
10474
|
+
const ref = med ? { x: K.x(med.u), z: K.z(med.v), y: med.y || 1 } : { x: firstPiped.item.x, z: firstPiped.item.z, y: 0.3 };
|
|
10475
|
+
const e = entry2("piped_gas", "gas_piped", { x: ref.x, z: ref.z, ry: 0, y: ref.y, seed: seedOf2("piped_gas") }, "piped_gas", firstPiped.floor);
|
|
10461
10476
|
e.floorY = o.base;
|
|
10462
10477
|
push(e);
|
|
10463
10478
|
for (const f of piped) f.connections.fuel = "piped_gas:gas";
|
|
@@ -10504,9 +10519,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10504
10519
|
for (const dv of spec.devices || []) if (L.outlet && dv.socket === "auto") dv.socket = L.outlet + ":socket";
|
|
10505
10520
|
} else {
|
|
10506
10521
|
const sh = L.shower || {};
|
|
10507
|
-
const
|
|
10522
|
+
const devices = spec.devices || [];
|
|
10523
|
+
const heater = devices.find((d) => d.id === "heater");
|
|
10508
10524
|
if (heater && sh.electric === false) {
|
|
10509
|
-
spec.devices =
|
|
10525
|
+
spec.devices = devices.filter((d) => d !== heater);
|
|
10510
10526
|
for (const f of spec.fixtures || []) if (f.heater === "heater") delete f.heater;
|
|
10511
10527
|
} else if (heater) {
|
|
10512
10528
|
if (sh.powerW) heater.watts = sh.powerW;
|
|
@@ -10517,7 +10533,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10517
10533
|
for (const b of spec.burners || []) if (b.fuel === "auto") b.fuel = L.fuel;
|
|
10518
10534
|
}
|
|
10519
10535
|
if (entry2.type === "fireplace" && L.chimneyTop) {
|
|
10520
|
-
const it = entry2.item;
|
|
10536
|
+
const it = at(entry2.item);
|
|
10521
10537
|
const dx = L.chimneyTop[0] - it.x;
|
|
10522
10538
|
const dz = L.chimneyTop[2] - it.z;
|
|
10523
10539
|
const lx = Math.cos(it.ry) * dx - Math.sin(it.ry) * dz;
|
|
@@ -10536,8 +10552,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10536
10552
|
}
|
|
10537
10553
|
return spec;
|
|
10538
10554
|
}
|
|
10539
|
-
function createWorld(
|
|
10540
|
-
|
|
10555
|
+
function createWorld(source, options2 = {}) {
|
|
10556
|
+
const res = sourceOf(source);
|
|
10557
|
+
const copts = options2 || {};
|
|
10541
10558
|
const info = { points: /* @__PURE__ */ new Map(), water: copts.water || null, lightsOn: copts.lightsOn };
|
|
10542
10559
|
const electrical = res.utilities && res.utilities.electrical;
|
|
10543
10560
|
const world = GI.createWorld({
|
|
@@ -10565,8 +10582,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10565
10582
|
const info = worlds.get(world);
|
|
10566
10583
|
return info ? info.points.get(fixtureId) : void 0;
|
|
10567
10584
|
}
|
|
10568
|
-
function blockedOf(
|
|
10569
|
-
|
|
10585
|
+
function blockedOf(source, options2 = {}) {
|
|
10586
|
+
const res = sourceOf(source);
|
|
10587
|
+
const bopts = options2 || {};
|
|
10570
10588
|
const ox = bopts.originX || 0;
|
|
10571
10589
|
const oz = bopts.originZ || 0;
|
|
10572
10590
|
const inw = bopts.inw || 1;
|
|
@@ -10601,33 +10619,33 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10601
10619
|
return false;
|
|
10602
10620
|
};
|
|
10603
10621
|
}
|
|
10604
|
-
function add(world, planned,
|
|
10605
|
-
aopts =
|
|
10622
|
+
function add(world, planned, options2 = {}) {
|
|
10623
|
+
const aopts = options2 || {};
|
|
10606
10624
|
const info = worlds.get(world);
|
|
10607
|
-
const build = aopts.build || ((type, item) => hh.build(type, item,
|
|
10625
|
+
const build = aopts.build || ((type, item) => hh.build(type, item, recorderApi()));
|
|
10608
10626
|
const isBlocked = aopts.isBlocked || null;
|
|
10609
10627
|
const out = { added: 0, parts: [], hinges: {}, moved: {}, warnings: [] };
|
|
10610
10628
|
const override = aopts.lightsOn !== void 0 ? aopts.lightsOn : info && info.lightsOn;
|
|
10611
10629
|
if (override !== void 0) {
|
|
10612
10630
|
for (const e of planned.items) if (e.type === "lamp") e.lit = typeof override === "function" ? !!override(e.id, e) : !!override;
|
|
10613
10631
|
for (const e of planned.items) if (e.type === "lantern_lamp") e.lit = typeof override === "function" ? !!override(e.id, e) : !!override;
|
|
10614
|
-
for (const e of planned.items) if (e.type === "wall_switch") e.lit = (e.connections.controls || []).some((id) =>
|
|
10632
|
+
for (const e of planned.items) if (e.type === "wall_switch") e.lit = (e.connections.controls || []).some((id) => planned.items.find((x) => x.id === id)?.lit === true);
|
|
10615
10633
|
}
|
|
10616
10634
|
for (const e of planned.items) if (e.type === "lantern_lamp") e.item.on = !!e.lit;
|
|
10617
10635
|
let scratch = null;
|
|
10618
|
-
function probe(e, hinge, setback) {
|
|
10636
|
+
function probe(e, hinge, setback, blockedAt) {
|
|
10619
10637
|
if (!scratch) scratch = GI.createWorld({ locale, strings: hh.strings, items: hh.items, loot: hh.loot, grid: false });
|
|
10620
|
-
const it = e.item;
|
|
10638
|
+
const it = at(e.item);
|
|
10621
10639
|
const x = it.x + Math.sin(it.ry) * setback;
|
|
10622
10640
|
const z = it.z + Math.cos(it.ry) * setback;
|
|
10623
|
-
const spec = hh.build(e.type, Object.assign({},
|
|
10641
|
+
const spec = hh.build(e.type, Object.assign({}, e.item, { hinge }), recorderApi());
|
|
10624
10642
|
scratch.add("__probe", spec, { x, y: e.floorY, z, ry: it.ry });
|
|
10625
|
-
const blocks = (px, pz) =>
|
|
10643
|
+
const blocks = (px, pz) => blockedAt(px, pz, e.floor);
|
|
10626
10644
|
let sum = 0;
|
|
10627
10645
|
let min = 1;
|
|
10628
10646
|
let n = 0;
|
|
10629
10647
|
for (const p of spec.parts || []) {
|
|
10630
|
-
if (p.motion.kind !== "hinge" || !(p.bounds || p.sweep)) continue;
|
|
10648
|
+
if (!p.motion || p.motion.kind !== "hinge" || !(p.bounds || p.sweep)) continue;
|
|
10631
10649
|
const t = scratch.fitSweep("__probe", p.id, blocks);
|
|
10632
10650
|
sum += t;
|
|
10633
10651
|
min = Math.min(min, t);
|
|
@@ -10639,12 +10657,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10639
10657
|
const better = (a, b) => a.sum > b.sum + 1e-9 || Math.abs(a.sum - b.sum) <= 1e-9 && a.min > b.min + 1e-9;
|
|
10640
10658
|
function fitDoors(e) {
|
|
10641
10659
|
if (!isBlocked || !householdTypes.has(e.type)) return;
|
|
10642
|
-
const standard = probe(e, void 0, 0);
|
|
10660
|
+
const standard = probe(e, void 0, 0, isBlocked);
|
|
10643
10661
|
if (!standard.n || standard.min >= 1) return;
|
|
10644
10662
|
let bestSide;
|
|
10645
10663
|
let m = standard;
|
|
10646
10664
|
for (const side of ["left", "right"]) {
|
|
10647
|
-
const r = probe(e, side, 0);
|
|
10665
|
+
const r = probe(e, side, 0, isBlocked);
|
|
10648
10666
|
if (better(r, m)) {
|
|
10649
10667
|
m = r;
|
|
10650
10668
|
bestSide = side;
|
|
@@ -10657,13 +10675,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10657
10675
|
if (m.min >= 1) return;
|
|
10658
10676
|
let target = { setback: 0, r: m };
|
|
10659
10677
|
for (const setback of [0.01, 0.02, 0.03, 0.04]) {
|
|
10660
|
-
const r = probe(e, bestSide, setback);
|
|
10678
|
+
const r = probe(e, bestSide, setback, isBlocked);
|
|
10661
10679
|
if (better(r, target.r)) target = { setback, r };
|
|
10662
10680
|
if (r.min >= 1) break;
|
|
10663
10681
|
}
|
|
10664
10682
|
if (target.setback > 0 && target.r.sum > m.sum + 0.2) {
|
|
10665
|
-
|
|
10666
|
-
e.item.
|
|
10683
|
+
const p = at(e.item);
|
|
10684
|
+
e.item.x = r3(p.x + Math.sin(p.ry) * target.setback);
|
|
10685
|
+
e.item.z = r3(p.z + Math.cos(p.ry) * target.setback);
|
|
10667
10686
|
e.moved = target.setback;
|
|
10668
10687
|
out.moved[e.id] = target.setback;
|
|
10669
10688
|
}
|
|
@@ -10686,7 +10705,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10686
10705
|
}
|
|
10687
10706
|
}
|
|
10688
10707
|
connect(e, spec);
|
|
10689
|
-
|
|
10708
|
+
const pose = at(e.item);
|
|
10709
|
+
world.add(e.id, spec, { x: pose.x, y: e.floorY, z: pose.z, ry: pose.ry });
|
|
10690
10710
|
out.added++;
|
|
10691
10711
|
if (!isBlocked) continue;
|
|
10692
10712
|
for (const p of spec.parts || []) {
|
|
@@ -10926,22 +10946,22 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10926
10946
|
A.stats.external = Ne;
|
|
10927
10947
|
let shadows = 0;
|
|
10928
10948
|
for (let i = 0; i < N; i++) {
|
|
10929
|
-
const g = asg[i],
|
|
10949
|
+
const g = asg[i], at2 = slotOf(i), b0 = LZU.uRB0.value, b1 = LZU.uRB1.value, b2 = LZU.uRB2.value, by = LZU.uRBY.value, ex = LZU.uREx.value;
|
|
10930
10950
|
A.crates[i] = g ? { k: g.k, rects: g.rects, y: g.y, exterior: !!g.exterior, exclusion: g.exclusion || null, d: g.d } : null;
|
|
10931
10951
|
if (!g) {
|
|
10932
10952
|
put(i, { intensity: 0 });
|
|
10933
|
-
for (const a of [b0, b1, b2, ex]) a.set(EMPTY,
|
|
10934
|
-
by.set([0, 0],
|
|
10953
|
+
for (const a of [b0, b1, b2, ex]) a.set(EMPTY, at2 * 4);
|
|
10954
|
+
by.set([0, 0], at2 * 2);
|
|
10935
10955
|
continue;
|
|
10936
10956
|
}
|
|
10937
10957
|
const lamp = g.exterior ? { intensity: g.lumens, distance: g.dist, decay: g.decay } : { intensity: (7 + g.range * 0.8) * lim(1 + 0.4 * (Math.sqrt(g.n) - 1), 1, 2.2), distance: Math.max(3, g.dm * 1.3 + 0.5), decay: 1.6 };
|
|
10938
10958
|
put(i, { position: g.pos, color: g.color, ...lamp });
|
|
10939
10959
|
const rs = g.rects;
|
|
10940
|
-
b0.set(rs[0] || EMPTY,
|
|
10941
|
-
b1.set(rs[1] || EMPTY,
|
|
10942
|
-
b2.set(rs[2] || EMPTY,
|
|
10943
|
-
by.set(g.y,
|
|
10944
|
-
ex.set(g.exclusion || EMPTY,
|
|
10960
|
+
b0.set(rs[0] || EMPTY, at2 * 4);
|
|
10961
|
+
b1.set(rs[1] || EMPTY, at2 * 4);
|
|
10962
|
+
b2.set(rs[2] || EMPTY, at2 * 4);
|
|
10963
|
+
by.set(g.y, at2 * 2);
|
|
10964
|
+
ex.set(g.exclusion || EMPTY, at2 * 4);
|
|
10945
10965
|
if (i < NS) {
|
|
10946
10966
|
shadows++;
|
|
10947
10967
|
const s2 = g.house.group.uuid + "|" + g.k + "|" + g.pos.map((v) => v.toFixed(2)).join(",");
|
|
@@ -11016,10 +11036,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11016
11036
|
for (const p of list2 || []) {
|
|
11017
11037
|
if (isDoor && !(open.has(p.id) ? open.get(p.id) : !!p.open)) continue;
|
|
11018
11038
|
const alongU = p.axis === "u", y = house.y0(p.floor) + (isDoor ? 1 : ((p.y0 != null ? p.y0 : 0.9) + (p.y1 != null ? p.y1 : 2)) / 2);
|
|
11019
|
-
const
|
|
11020
|
-
if (
|
|
11039
|
+
const at2 = (side) => _p.set(alongU ? p.at : p.pos + side, y, alongU ? p.pos + side : p.at).applyMatrix4(M).clone();
|
|
11040
|
+
if (at2(0).distanceTo(P0) > OPENING_REACH) continue;
|
|
11021
11041
|
for (const side of [-OPENING_SIDE, OPENING_SIDE]) {
|
|
11022
|
-
const w =
|
|
11042
|
+
const w = at2(side), hit = boxAt(boxes, w.x, w.y, w.z);
|
|
11023
11043
|
if (hit) into.set(hit.c, hit);
|
|
11024
11044
|
}
|
|
11025
11045
|
}
|
|
@@ -11027,11 +11047,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11027
11047
|
reach(house.r.doors, true);
|
|
11028
11048
|
reach(house.r.windows, false);
|
|
11029
11049
|
};
|
|
11030
|
-
const clear = (
|
|
11031
|
-
for (const key of ["uRB0", "uRB1", "uRB2", "uREx"]) LZU[key].value.set(EMPTY,
|
|
11032
|
-
LZU.uRBY.value.set([0, 0],
|
|
11050
|
+
const clear = (at2) => {
|
|
11051
|
+
for (const key of ["uRB0", "uRB1", "uRB2", "uREx"]) LZU[key].value.set(EMPTY, at2 * 4);
|
|
11052
|
+
LZU.uRBY.value.set([0, 0], at2 * 2);
|
|
11033
11053
|
};
|
|
11034
|
-
const write = (
|
|
11054
|
+
const write = (at2, into) => {
|
|
11035
11055
|
const rs = [];
|
|
11036
11056
|
let lo = 1e9, hi = -1e9;
|
|
11037
11057
|
for (const q of into.values()) {
|
|
@@ -11043,21 +11063,21 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11043
11063
|
const r23 = rs.pop(), r1 = rs[rs.length - 1];
|
|
11044
11064
|
rs[rs.length - 1] = [Math.min(r1[0], r23[0]), Math.min(r1[1], r23[1]), Math.max(r1[2], r23[2]), Math.max(r1[3], r23[3])];
|
|
11045
11065
|
}
|
|
11046
|
-
LZU.uRB0.value.set(rs[0] || EMPTY,
|
|
11047
|
-
LZU.uRB1.value.set(rs[1] || EMPTY,
|
|
11048
|
-
LZU.uRB2.value.set(rs[2] || EMPTY,
|
|
11049
|
-
LZU.uRBY.value.set([lo, hi],
|
|
11050
|
-
LZU.uREx.value.set(EMPTY,
|
|
11066
|
+
LZU.uRB0.value.set(rs[0] || EMPTY, at2 * 4);
|
|
11067
|
+
LZU.uRB1.value.set(rs[1] || EMPTY, at2 * 4);
|
|
11068
|
+
LZU.uRB2.value.set(rs[2] || EMPTY, at2 * 4);
|
|
11069
|
+
LZU.uRBY.value.set([lo, hi], at2 * 2);
|
|
11070
|
+
LZU.uREx.value.set(EMPTY, at2 * 4);
|
|
11051
11071
|
};
|
|
11052
11072
|
const A = {
|
|
11053
11073
|
/** 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. */
|
|
11054
11074
|
update(houses2) {
|
|
11055
11075
|
const indoors = cfg.effectLightsIndoors !== false, list2 = (Array.isArray(houses2) ? houses2 : [houses2]).filter(Boolean), cache2 = /* @__PURE__ */ new Map();
|
|
11056
|
-
for (let
|
|
11057
|
-
if (ours.has(
|
|
11058
|
-
const light = budget.group.children[
|
|
11076
|
+
for (let at2 = 0; at2 < size; at2++) {
|
|
11077
|
+
if (ours.has(at2)) continue;
|
|
11078
|
+
const light = budget.group.children[at2];
|
|
11059
11079
|
if (!indoors || !light || !light.isPointLight || !(light.intensity > 0) || !light.visible) {
|
|
11060
|
-
clear(
|
|
11080
|
+
clear(at2);
|
|
11061
11081
|
continue;
|
|
11062
11082
|
}
|
|
11063
11083
|
const into = /* @__PURE__ */ new Map();
|
|
@@ -11072,8 +11092,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11072
11092
|
if (here) into.set(here.c, here);
|
|
11073
11093
|
openingSides(house, M, boxes, into);
|
|
11074
11094
|
}
|
|
11075
|
-
if (into.size) write(
|
|
11076
|
-
else clear(
|
|
11095
|
+
if (into.size) write(at2, into);
|
|
11096
|
+
else clear(at2);
|
|
11077
11097
|
}
|
|
11078
11098
|
}
|
|
11079
11099
|
};
|
|
@@ -11430,11 +11450,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11430
11450
|
}
|
|
11431
11451
|
return pieces.slice(0, limit).map((p) => ({ center: p.c, size: [p.s[g], p.s[a], p.s[b]], q: frame(g, a, b), shape: "splinter", weight: p.s[0] * p.s[1] * p.s[2] }));
|
|
11432
11452
|
};
|
|
11433
|
-
var severAt = (inp, root,
|
|
11453
|
+
var severAt = (inp, root, at2, gap) => {
|
|
11434
11454
|
const dims = root.s;
|
|
11435
11455
|
const L = [0, 1, 2].sort((x, y) => dims[y] - dims[x])[0];
|
|
11436
11456
|
const half = dims[L] / 2;
|
|
11437
|
-
const lo = clamp(
|
|
11457
|
+
const lo = clamp(at2 - gap / 2, -half, half), hi = clamp(at2 + gap / 2, -half, half);
|
|
11438
11458
|
const out = [];
|
|
11439
11459
|
const stub = (from, to) => {
|
|
11440
11460
|
if (to - from < 0.02) return;
|
|
@@ -13816,7 +13836,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
13816
13836
|
const typed = listeners.get(e.type);
|
|
13817
13837
|
if (typed) for (const fn of [...typed]) fn(e);
|
|
13818
13838
|
};
|
|
13819
|
-
|
|
13839
|
+
let blow;
|
|
13840
|
+
const base = (o, source) => ({
|
|
13841
|
+
object: o.id,
|
|
13842
|
+
time,
|
|
13843
|
+
...source === void 0 ? {} : { source },
|
|
13844
|
+
...blow === void 0 ? {} : { blow }
|
|
13845
|
+
});
|
|
13820
13846
|
const pendingCollapse = /* @__PURE__ */ new Map();
|
|
13821
13847
|
let runDepth = 0;
|
|
13822
13848
|
const drainBlasts = () => {
|
|
@@ -14086,9 +14112,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
14086
14112
|
const [lo, hi] = contactBox(p, above);
|
|
14087
14113
|
return toWorld(p.pos, p.q, [(lo[0] + hi[0]) / 2, (lo[1] + hi[1]) / 2, (lo[2] + hi[2]) / 2]);
|
|
14088
14114
|
};
|
|
14089
|
-
const overSupportAt = (o, p,
|
|
14115
|
+
const overSupportAt = (o, p, at2, lower) => {
|
|
14090
14116
|
const g = p.bend;
|
|
14091
|
-
const local = toLocal(p.pos, p.q,
|
|
14117
|
+
const local = toLocal(p.pos, p.q, at2);
|
|
14092
14118
|
const depth = g.gravity >= 0 ? g.dims[g.gravity] : Math.min(...g.depthAxes.map((a) => g.dims[a]));
|
|
14093
14119
|
let best = -1;
|
|
14094
14120
|
let bestGap = depth;
|
|
@@ -14242,10 +14268,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
14242
14268
|
const incoming = new Array(n).fill(0);
|
|
14243
14269
|
const bending = new Array(n).fill(0);
|
|
14244
14270
|
const through = parts.map(() => []);
|
|
14245
|
-
const pass = (k,
|
|
14246
|
-
const over = overSupportAt(o, parts[k],
|
|
14271
|
+
const pass = (k, at2, mass) => {
|
|
14272
|
+
const over = overSupportAt(o, parts[k], at2, lowerOf.get(k) ?? []);
|
|
14247
14273
|
if (over < 0) bending[k] += mass;
|
|
14248
|
-
else through[k].push({ at, mass, over });
|
|
14274
|
+
else through[k].push({ at: at2, mass, over });
|
|
14249
14275
|
};
|
|
14250
14276
|
for (let h = queue.length - 1; h >= 0; h--) {
|
|
14251
14277
|
const i = queue[h];
|
|
@@ -14312,7 +14338,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
14312
14338
|
const terrain = cfg.terrains.get(cfg.terrain);
|
|
14313
14339
|
if (!terrain) throw new Error(`unknown wind terrain "${cfg.terrain}"`);
|
|
14314
14340
|
const inputs = [];
|
|
14315
|
-
const
|
|
14341
|
+
const at2 = /* @__PURE__ */ new Map();
|
|
14316
14342
|
const keep = [];
|
|
14317
14343
|
let ground = Infinity, foundationTop = -Infinity;
|
|
14318
14344
|
o.parts.forEach((p, i) => {
|
|
@@ -14321,7 +14347,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
14321
14347
|
const role = p.spec.structure?.role;
|
|
14322
14348
|
const e = p.mat.strength?.elasticGPa;
|
|
14323
14349
|
const kind = role === "wall" ? "wall" : role === "column" ? "column" : role === "beam" ? "beam" : role === "foundation" ? "foundation" : "other";
|
|
14324
|
-
|
|
14350
|
+
at2.set(i, inputs.length);
|
|
14325
14351
|
keep.push(i);
|
|
14326
14352
|
ground = Math.min(ground, box3.min[1]);
|
|
14327
14353
|
if (kind === "foundation") foundationTop = Math.max(foundationTop, box3.max[1]);
|
|
@@ -14332,7 +14358,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
14332
14358
|
const beams = [];
|
|
14333
14359
|
for (const j of o.byPart.get(o.parts[i].spec.id)) {
|
|
14334
14360
|
if (j.st.open) continue;
|
|
14335
|
-
const b =
|
|
14361
|
+
const b = at2.get(j.ia === i ? j.ib : j.ia);
|
|
14336
14362
|
if (b !== void 0 && inputs[b].kind === "beam") beams.push(b);
|
|
14337
14363
|
}
|
|
14338
14364
|
inputs[k].beams = beams;
|
|
@@ -15148,7 +15174,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
15148
15174
|
}
|
|
15149
15175
|
};
|
|
15150
15176
|
const tornToEdge = (o) => {
|
|
15151
|
-
const { p, cell, a, b, at, crater: crater2, reach, gone } = o;
|
|
15177
|
+
const { p, cell, a, b, at: at2, crater: crater2, reach, gone } = o;
|
|
15152
15178
|
const half = p.dims[a] / 2;
|
|
15153
15179
|
const lo = cell.center[a] - cell.size[a] / 2, hi = cell.center[a] + cell.size[a] / 2;
|
|
15154
15180
|
const free = (side, sign2) => {
|
|
@@ -15156,8 +15182,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
15156
15182
|
const probe = side + sign2 * 1e-3;
|
|
15157
15183
|
return gridOf(p).some((c, k) => gone(k) && Math.abs(probe - c.center[a]) <= c.size[a] / 2 && Math.abs(cell.center[b] - c.center[b]) <= c.size[b] / 2);
|
|
15158
15184
|
};
|
|
15159
|
-
if (
|
|
15160
|
-
if (hi -
|
|
15185
|
+
if (at2 - lo <= reach && free(lo, -1)) return [lo, Math.max(crater2[1], lo)];
|
|
15186
|
+
if (hi - at2 <= reach && free(hi, 1)) return [Math.min(crater2[0], hi), hi];
|
|
15161
15187
|
return crater2;
|
|
15162
15188
|
};
|
|
15163
15189
|
const craterAcross = (energy) => clamp2(0.03 + 12e-4 * Math.sqrt(Math.max(0, energy)), 0.03, 0.14);
|
|
@@ -15961,7 +15987,17 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
15961
15987
|
res.events = cur.slice(start);
|
|
15962
15988
|
return res;
|
|
15963
15989
|
};
|
|
15964
|
-
const
|
|
15990
|
+
const withBlow = (type, fn) => () => {
|
|
15991
|
+
const outer = blow;
|
|
15992
|
+
blow = type;
|
|
15993
|
+
try {
|
|
15994
|
+
return fn();
|
|
15995
|
+
} finally {
|
|
15996
|
+
blow = outer;
|
|
15997
|
+
}
|
|
15998
|
+
};
|
|
15999
|
+
const doHit = (o, hit, only) => withBlow(hit.type, () => resolveHit(o, hit, only))();
|
|
16000
|
+
const resolveHit = (o, hit, only) => {
|
|
15965
16001
|
let point = hit.point;
|
|
15966
16002
|
let dir = hit.direction;
|
|
15967
16003
|
if (hit.space === "local") {
|
|
@@ -16400,6 +16436,44 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16400
16436
|
blastProbe() {
|
|
16401
16437
|
return { ...blastProbe };
|
|
16402
16438
|
},
|
|
16439
|
+
blastReach(point, target, options2 = {}) {
|
|
16440
|
+
const L = vec.distance(point, target);
|
|
16441
|
+
if (L < 1e-4) return 1;
|
|
16442
|
+
const shelter = { ...SHELTER_DEFAULTS, ...options2.shelter };
|
|
16443
|
+
const ignore = new Set(options2.ignore ?? []);
|
|
16444
|
+
const d = vec.scale(vec.sub(target, point), 1 / L);
|
|
16445
|
+
let t = 1;
|
|
16446
|
+
for (const o of objects.values()) {
|
|
16447
|
+
if (ignore.has(o.id) || raySphereMiss(point, d, toWorld(o.st.position, o.st.rotation, o.bc), o.br, L)) continue;
|
|
16448
|
+
for (const p of o.parts) {
|
|
16449
|
+
if (isLost(p) || p.st.stripped) continue;
|
|
16450
|
+
const r = rayPart(o, p, point, d);
|
|
16451
|
+
if (!r) continue;
|
|
16452
|
+
const t0 = Math.max(r.t0, 0);
|
|
16453
|
+
const path = Math.min(r.t1, L) - t0;
|
|
16454
|
+
if (path < shelter.minPath) continue;
|
|
16455
|
+
if (p.st.opening && insideOpening(o, p, toLocal(o.st.position, o.st.rotation, vec.madd(point, d, t0 + path / 2)))) continue;
|
|
16456
|
+
t *= Math.exp(-(p.mat.hpPerKg * p.mat.density * path * (p.mat.damageScale?.shelter ?? 1)) / shelter.k);
|
|
16457
|
+
if (t < 1e-4) return 0;
|
|
16458
|
+
}
|
|
16459
|
+
}
|
|
16460
|
+
for (const im of impls.values()) {
|
|
16461
|
+
if (ignore.has(im.impl.id)) continue;
|
|
16462
|
+
for (const ps of im.impl.describe().parts) {
|
|
16463
|
+
const mat = materials.get(ps.material);
|
|
16464
|
+
if (!mat) continue;
|
|
16465
|
+
const ov = im.poses.get(ps.id);
|
|
16466
|
+
const r = rayPartRaw(im.position, im.rotation, ps, ov?.q ?? quatFromEuler(...ps.rotation ?? [0, 0, 0]), point, d, ov?.pos);
|
|
16467
|
+
if (!r || r.t1 < 0 || r.t0 > L) continue;
|
|
16468
|
+
let path = Math.min(r.t1, L) - Math.max(r.t0, 0);
|
|
16469
|
+
if (ps.thickness !== void 0 && ps.thickness > 0) path = Math.min(path, 2 * ps.thickness);
|
|
16470
|
+
else if (path < shelter.minPath) continue;
|
|
16471
|
+
t *= Math.exp(-(mat.hpPerKg * mat.density * path * (mat.damageScale?.shelter ?? 1)) / shelter.k);
|
|
16472
|
+
if (t < 1e-4) return 0;
|
|
16473
|
+
}
|
|
16474
|
+
}
|
|
16475
|
+
return t;
|
|
16476
|
+
},
|
|
16403
16477
|
explode(point, energy, radius, source, blast) {
|
|
16404
16478
|
blastProbe.partsTested = 0;
|
|
16405
16479
|
blastProbe.partsNear = 0;
|
|
@@ -16424,7 +16498,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16424
16498
|
},
|
|
16425
16499
|
shoot(origin, direction, energy, caliber, source, round3) {
|
|
16426
16500
|
const extras = typeof round3 === "number" ? { piercing: round3 } : round3 ?? {};
|
|
16427
|
-
return withCollapses(run(() => {
|
|
16501
|
+
return withCollapses(run(withBlow("ballistic", () => {
|
|
16428
16502
|
const results = [];
|
|
16429
16503
|
const d = vec.normalize(direction);
|
|
16430
16504
|
const ignore = /* @__PURE__ */ new Set();
|
|
@@ -16435,10 +16509,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16435
16509
|
if (!rh) break;
|
|
16436
16510
|
const im = impls.get(rh.object);
|
|
16437
16511
|
if (im) {
|
|
16438
|
-
const
|
|
16512
|
+
const scaled = extras.penetration && E < energy ? { ...extras, penetration: Object.fromEntries(Object.entries(extras.penetration).map(([k, mm]) => [k, mm * (E / energy)])) } : extras;
|
|
16513
|
+
const r = implHit(im, { type: "ballistic", point: rh.point, part: rh.part, normal: rh.normal, direction: d, energy: E, caliber, ...scaled, ...source !== void 0 ? { source } : {} });
|
|
16439
16514
|
r.part = rh.part;
|
|
16440
16515
|
r.point = rh.point;
|
|
16441
|
-
|
|
16516
|
+
const left = r.events.find((e) => e.type === "hole" && e.energyLeft !== void 0);
|
|
16517
|
+
r.exitEnergy = r.penetrated ? left?.energyLeft ?? E * 0.5 : 0;
|
|
16442
16518
|
results.push(r);
|
|
16443
16519
|
ignore.add(`${im.impl.id}\0${rh.part}`);
|
|
16444
16520
|
if (!r.penetrated) break;
|
|
@@ -16457,7 +16533,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16457
16533
|
E = out.exitEnergy;
|
|
16458
16534
|
}
|
|
16459
16535
|
return results;
|
|
16460
|
-
}));
|
|
16536
|
+
})));
|
|
16461
16537
|
},
|
|
16462
16538
|
disassemble(objectId, jointId, tool, dt) {
|
|
16463
16539
|
const im = impls.get(objectId);
|
|
@@ -16765,8 +16841,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16765
16841
|
list: () => defs,
|
|
16766
16842
|
get,
|
|
16767
16843
|
register(def) {
|
|
16768
|
-
const
|
|
16769
|
-
if (
|
|
16844
|
+
const at2 = defs.findIndex((a) => a.id === def.id);
|
|
16845
|
+
if (at2 >= 0) defs[at2] = def;
|
|
16770
16846
|
else defs.push(def);
|
|
16771
16847
|
},
|
|
16772
16848
|
part: (assemblyId, options) => buildAssemblyPart(get(assemblyId), assemblyId, options)
|
|
@@ -17837,9 +17913,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
17837
17913
|
}
|
|
17838
17914
|
if (context.isTimber && construction.roof.shape !== "slab") addCeilingJoists(context);
|
|
17839
17915
|
}
|
|
17916
|
+
var isStair = (item) => item.category === "stairs" && typeof item.link === "object" && item.link !== null;
|
|
17840
17917
|
function flightsOf(items) {
|
|
17841
17918
|
const flights = /* @__PURE__ */ new Map();
|
|
17842
|
-
for (const item of items.filter(
|
|
17919
|
+
for (const item of items.filter(isStair)) {
|
|
17843
17920
|
const key = `${item.link.from}_${item.link.to}`;
|
|
17844
17921
|
if (!flights.has(key) || item.floor === item.link.from) flights.set(key, item);
|
|
17845
17922
|
}
|
|
@@ -20219,17 +20296,17 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
20219
20296
|
for (const { c, part, units: units2, thick, mid } of shown) {
|
|
20220
20297
|
if (!near(c)) continue;
|
|
20221
20298
|
const centre = mask.start + (c.a + c.b) / 2, y = (c.y0 + c.y1) / 2, len = c.b - c.a, h = c.y1 - c.y0;
|
|
20222
|
-
const
|
|
20299
|
+
const at2 = (s, dy, d, colour) => {
|
|
20223
20300
|
const unit = clipToBox({ x: mask.alongU ? centre : mid, y, z: mask.alongU ? mid : centre, sx: mask.alongU ? s : d, sy: dy, sz: mask.alongU ? d : s, colour }, view.bounds);
|
|
20224
20301
|
if (unit) list2.push(unit);
|
|
20225
20302
|
};
|
|
20226
20303
|
const base = fragmentMaterial(part.material).color.getHex();
|
|
20227
20304
|
const n = noise2(centre * 3.1, y * 2.7, 0.07);
|
|
20228
20305
|
if (units2.mortar === "concrete") {
|
|
20229
|
-
|
|
20306
|
+
at2(len, h, thick - 2 * COVER2, tone(base, 0.9 + 0.04 * n));
|
|
20230
20307
|
} else {
|
|
20231
|
-
|
|
20232
|
-
|
|
20308
|
+
at2(len, h, thick - 2 * COVER2 - 0.012, 10327948);
|
|
20309
|
+
at2(len - 0.012, h - 0.012, thick - 2 * COVER2, tone(base, 0.8 + 0.35 * n));
|
|
20233
20310
|
}
|
|
20234
20311
|
}
|
|
20235
20312
|
if (view.units) {
|
|
@@ -20545,11 +20622,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
20545
20622
|
};
|
|
20546
20623
|
const extract = (it) => {
|
|
20547
20624
|
const g0 = it.mesh.geometry, src = it.mesh.userData._p0 || g0.attributes.position.array, g = new THREE.BufferGeometry();
|
|
20548
|
-
const
|
|
20549
|
-
|
|
20550
|
-
|
|
20551
|
-
|
|
20552
|
-
|
|
20625
|
+
const at2 = (name, k, arr) => g.setAttribute(name, new THREE.BufferAttribute((arr || g0.attributes[name].array).slice(it.v0 * k, it.v1 * k), k));
|
|
20626
|
+
at2("position", 3, src);
|
|
20627
|
+
at2("normal", 3);
|
|
20628
|
+
at2("color", 3);
|
|
20629
|
+
at2("uv", 2);
|
|
20553
20630
|
const ix = g0.index.array.slice(it.i0, it.i1);
|
|
20554
20631
|
for (let k = 0; k < ix.length; k++) ix[k] -= it.v0;
|
|
20555
20632
|
g.setIndex(new THREE.BufferAttribute(ix, 1));
|
|
@@ -21264,9 +21341,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21264
21341
|
shared.vegMaterials.setActors(focus ? [{ x: focus.x, y: focus.y, z: focus.z, radius: 0.9 }] : []);
|
|
21265
21342
|
}
|
|
21266
21343
|
if (focus && cfg.lod !== false) {
|
|
21267
|
-
const L = Object.assign({ interior: 45, hide: 220 }, cfg.lod), d = distance2(focus),
|
|
21344
|
+
const L = Object.assign({ interior: 45, hide: 220 }, cfg.lod), d = distance2(focus), at2 = h.lodCurrent;
|
|
21268
21345
|
let n = d > L.hide ? 2 : d > L.interior ? 1 : 0;
|
|
21269
|
-
if (n <
|
|
21346
|
+
if (n < at2) n = d < (at2 === 2 ? L.hide : L.interior) * 0.92 ? n : at2;
|
|
21270
21347
|
applyLod(Math.max(n, h.lodMin));
|
|
21271
21348
|
}
|
|
21272
21349
|
},
|
|
@@ -22017,14 +22094,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22017
22094
|
|
|
22018
22095
|
// src/test-area/scenarios.ts
|
|
22019
22096
|
var SPECIMEN_AT = [-5, 0, -11];
|
|
22020
|
-
function createHouseScenarios(text,
|
|
22097
|
+
function createHouseScenarios(text, at2 = SPECIMEN_AT) {
|
|
22021
22098
|
const T2 = text.steps;
|
|
22022
22099
|
const spawn = (room, item) => {
|
|
22023
|
-
const so = room.spawn(item, [
|
|
22100
|
+
const so = room.spawn(item, [at2[0], at2[1], at2[2]], 0);
|
|
22024
22101
|
const parts = so.root.userData.floorplanSpec.parts;
|
|
22025
22102
|
const centre = (id) => {
|
|
22026
22103
|
const p = parts.find((x) => x.id === id);
|
|
22027
|
-
return [p.position[0] +
|
|
22104
|
+
return [p.position[0] + at2[0], p.position[1] + at2[1], p.position[2] + at2[2]];
|
|
22028
22105
|
};
|
|
22029
22106
|
return { oid: so.objectId, parts, centre };
|
|
22030
22107
|
};
|
|
@@ -22399,9 +22476,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22399
22476
|
};
|
|
22400
22477
|
const eyeOf = (p) => {
|
|
22401
22478
|
const camera = host?.camera;
|
|
22402
|
-
const
|
|
22479
|
+
const at2 = toLocal2(p, camera.position.x, camera.position.y, camera.position.z);
|
|
22403
22480
|
const forward = new THREE.Vector3(0, 0, -1).applyQuaternion(camera.quaternion).transformDirection(new THREE.Matrix4().copy(p.house.group.matrixWorld).invert());
|
|
22404
|
-
return { x:
|
|
22481
|
+
return { x: at2.x, y: at2.y, z: at2.z, floor: floorOf(p, camera.position.y), yaw: Math.atan2(forward.x, forward.z), pitch: Math.asin(Math.max(-1, Math.min(1, forward.y))) };
|
|
22405
22482
|
};
|
|
22406
22483
|
const blocked = (x, z, radius) => {
|
|
22407
22484
|
for (const p of placed) {
|
|
@@ -22469,7 +22546,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22469
22546
|
const doorReach = (p, fo) => {
|
|
22470
22547
|
const g = fo.gs[0];
|
|
22471
22548
|
const pivot = fo.handles[0].pivot;
|
|
22472
|
-
const
|
|
22549
|
+
const at2 = (angle) => {
|
|
22473
22550
|
const c = Math.cos(angle);
|
|
22474
22551
|
const s = Math.sin(angle);
|
|
22475
22552
|
const v = new THREE.Vector3(pivot[0] * c + pivot[2] * s, pivot[1], -pivot[0] * s + pivot[2] * c).add(g.position);
|
|
@@ -22478,8 +22555,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22478
22555
|
const camera = host?.camera;
|
|
22479
22556
|
const eye = new THREE.Vector3(camera.position.x, 0, camera.position.z);
|
|
22480
22557
|
const flat = (v) => Math.hypot(v.x - eye.x, v.z - eye.z);
|
|
22481
|
-
const closed =
|
|
22482
|
-
const open =
|
|
22558
|
+
const closed = at2(0);
|
|
22559
|
+
const open = at2(fo.rot);
|
|
22483
22560
|
const opening = !fo.open;
|
|
22484
22561
|
return {
|
|
22485
22562
|
handle: () => {
|
|
@@ -23187,8 +23264,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23187
23264
|
facadeExtra: (f, rng2, w, d, op) => {
|
|
23188
23265
|
f.roof = "slab";
|
|
23189
23266
|
f.finish = rng2() < 0.55 ? "exposed_block" : "partial_plaster";
|
|
23190
|
-
|
|
23191
|
-
|
|
23267
|
+
const slab = { exposedRebar: true, waterTank: { u: r22(0.5 + rng2() * (w - 1.5)), v: r22(1 + rng2() * (d - 2)) }, annex: rng2() < 0.55 ? { rect: [0, 0, r22(w * (0.5 + rng2() * 0.3)), r22(d * 0.4)], state: "exposed_brick" } : null };
|
|
23268
|
+
f.slab = slab;
|
|
23269
|
+
if (floorsOf(op) > 1) slab.exposedRebar = rng2() < 0.6;
|
|
23192
23270
|
}
|
|
23193
23271
|
};
|
|
23194
23272
|
}
|
|
@@ -23900,13 +23978,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23900
23978
|
function apartment(strip, floor, k, from, to, plate, ceiling, win) {
|
|
23901
23979
|
const wide = to - from, depth = strip.depth, facade = r22(depth * 0.56);
|
|
23902
23980
|
const id = (name) => `apt_${floor}_${strip.id}_${k}_${name}`;
|
|
23903
|
-
const
|
|
23981
|
+
const at2 = (f0, f1, b0, b1) => boxOf2(strip, r22(from + wide * f0), r22(from + wide * f1), b0, b1);
|
|
23904
23982
|
const rooms = [
|
|
23905
|
-
{ id: id("living"), type: "living", label: "living", library: "living_tower", rect:
|
|
23906
|
-
{ id: id("bedroom"), type: "bedroom", label: "bedroom", rect:
|
|
23907
|
-
{ id: id("kitchen"), type: "kitchen", label: "kitchen", library: "kitchen_integrated", rect:
|
|
23908
|
-
{ id: id("hall"), type: "hall", label: "hall", rect:
|
|
23909
|
-
{ id: id("bath"), type: "bathroom", label: "bathroom", library: "bathroom_wc", rect:
|
|
23983
|
+
{ id: id("living"), type: "living", label: "living", library: "living_tower", rect: at2(0, 0.58, 0, facade) },
|
|
23984
|
+
{ id: id("bedroom"), type: "bedroom", label: "bedroom", rect: at2(0.58, 1, 0, facade) },
|
|
23985
|
+
{ id: id("kitchen"), type: "kitchen", label: "kitchen", library: "kitchen_integrated", rect: at2(0, 0.4, facade, depth) },
|
|
23986
|
+
{ id: id("hall"), type: "hall", label: "hall", rect: at2(0.4, 0.78, facade, depth) },
|
|
23987
|
+
{ id: id("bath"), type: "bathroom", label: "bathroom", library: "bathroom_wc", rect: at2(0.78, 1, facade, depth) }
|
|
23910
23988
|
];
|
|
23911
23989
|
const doors = [
|
|
23912
23990
|
stripDoor(id("hall"), strip, floor, 0.95),
|
|
@@ -23939,8 +24017,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23939
24017
|
if (strip.id !== "south") return apartments(plan)(strip, context);
|
|
23940
24018
|
const { floor, plate, ceiling } = context;
|
|
23941
24019
|
const lobby = `lobby_${floor}_entrance`, concierge = `concierge_${floor}`, bikes = `bike_room_${floor}`;
|
|
23942
|
-
const
|
|
23943
|
-
const [left, middle, right] = [
|
|
24020
|
+
const at2 = (f0, f1) => boxOf2(strip, r22(strip.length * f0), r22(strip.length * f1), 0, strip.depth);
|
|
24021
|
+
const [left, middle, right] = [at2(0, 0.3), at2(0.3, 0.7), at2(0.7, 1)];
|
|
23944
24022
|
const rooms = [
|
|
23945
24023
|
{ id: concierge, type: "office", label: "concierge", rect: left },
|
|
23946
24024
|
{ id: lobby, type: "hall", label: "lobby_entrance", rect: middle },
|