@adatechnology/game-floorplan-three 0.1.1 → 0.2.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/MIGRATION.md +1 -1
- package/README.md +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.global.js +1993 -375
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +14 -13
- package/dist/index.js.map +1 -1
- package/package.json +14 -10
package/dist/index.global.js
CHANGED
|
@@ -27,10 +27,10 @@ var GameFloorplanThree = (() => {
|
|
|
27
27
|
VERSION: () => VERSION,
|
|
28
28
|
bindNavigator: () => bindNavigator,
|
|
29
29
|
buildSpecimenMeshes: () => buildSpecimenMeshes,
|
|
30
|
-
create: () =>
|
|
30
|
+
create: () => create3,
|
|
31
31
|
createFloorNavigator: () => createFloorNavigator,
|
|
32
32
|
createFloorplanTestModule: () => createFloorplanTestModule,
|
|
33
|
-
createHouseRenderer: () =>
|
|
33
|
+
createHouseRenderer: () => create3,
|
|
34
34
|
createHouseScenarios: () => createHouseScenarios,
|
|
35
35
|
createTranslator: () => createTranslator,
|
|
36
36
|
en: () => en,
|
|
@@ -54,6 +54,7 @@ var GameFloorplanThree = (() => {
|
|
|
54
54
|
create: () => create,
|
|
55
55
|
createNodeSkin: () => createNodeSkin,
|
|
56
56
|
createRecorder: () => createRecorder,
|
|
57
|
+
createShapeRecorder: () => createShapeRecorder,
|
|
57
58
|
hex: () => hex,
|
|
58
59
|
listTypes: () => listTypes,
|
|
59
60
|
locales: () => locales,
|
|
@@ -64,6 +65,228 @@ var GameFloorplanThree = (() => {
|
|
|
64
65
|
seedOf: () => seedOf,
|
|
65
66
|
shade: () => shade
|
|
66
67
|
});
|
|
68
|
+
|
|
69
|
+
// ../game-shapes/dist/chunk-R4RY23RH.js
|
|
70
|
+
function normalMatrix(me) {
|
|
71
|
+
const n11 = me[0], n21 = me[1], n31 = me[2];
|
|
72
|
+
const n12 = me[4], n22 = me[5], n32 = me[6];
|
|
73
|
+
const n13 = me[8], n23 = me[9], n33 = me[10];
|
|
74
|
+
const t11 = n33 * n22 - n32 * n23;
|
|
75
|
+
const t12 = n32 * n13 - n33 * n12;
|
|
76
|
+
const t13 = n23 * n12 - n22 * n13;
|
|
77
|
+
const det = n11 * t11 + n21 * t12 + n31 * t13;
|
|
78
|
+
if (det === 0) return [0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
79
|
+
const detInv = 1 / det;
|
|
80
|
+
const te = [
|
|
81
|
+
t11 * detInv,
|
|
82
|
+
(n31 * n23 - n33 * n21) * detInv,
|
|
83
|
+
(n32 * n21 - n31 * n22) * detInv,
|
|
84
|
+
t12 * detInv,
|
|
85
|
+
(n33 * n11 - n31 * n13) * detInv,
|
|
86
|
+
(n31 * n12 - n32 * n11) * detInv,
|
|
87
|
+
t13 * detInv,
|
|
88
|
+
(n21 * n13 - n23 * n11) * detInv,
|
|
89
|
+
(n22 * n11 - n21 * n12) * detInv
|
|
90
|
+
];
|
|
91
|
+
let tmp = te[1];
|
|
92
|
+
te[1] = te[3];
|
|
93
|
+
te[3] = tmp;
|
|
94
|
+
tmp = te[2];
|
|
95
|
+
te[2] = te[6];
|
|
96
|
+
te[6] = tmp;
|
|
97
|
+
tmp = te[5];
|
|
98
|
+
te[5] = te[7];
|
|
99
|
+
te[7] = tmp;
|
|
100
|
+
return te;
|
|
101
|
+
}
|
|
102
|
+
function transformPoint(e, x, y, z) {
|
|
103
|
+
const w = 1 / (e[3] * x + e[7] * y + e[11] * z + e[15]);
|
|
104
|
+
return [(e[0] * x + e[4] * y + e[8] * z + e[12]) * w, (e[1] * x + e[5] * y + e[9] * z + e[13]) * w, (e[2] * x + e[6] * y + e[10] * z + e[14]) * w];
|
|
105
|
+
}
|
|
106
|
+
var num = (v) => typeof v === "number" && Number.isFinite(v) ? null : "expected a finite number";
|
|
107
|
+
var bool = (v) => typeof v === "boolean" ? null : "expected a boolean";
|
|
108
|
+
var str = (v) => typeof v === "string" ? null : "expected a string";
|
|
109
|
+
var int = (min) => (v) => typeof v === "number" && Number.isInteger(v) && v >= min ? null : `expected an integer >= ${min}`;
|
|
110
|
+
var range = (lo, hi, loOpen = false) => (v) => typeof v === "number" && (loOpen ? v > lo : v >= lo) && v <= hi ? null : `expected a number in ${loOpen ? "(" : "["}${lo}, ${hi}]`;
|
|
111
|
+
var tuple = (n, item = num) => (v) => {
|
|
112
|
+
if (!Array.isArray(v) || v.length !== n) return `expected an array of ${n}`;
|
|
113
|
+
for (const x of v) if (item(x)) return `expected an array of ${n} numbers`;
|
|
114
|
+
return null;
|
|
115
|
+
};
|
|
116
|
+
var list = (item, min = 0) => (v) => {
|
|
117
|
+
if (!Array.isArray(v)) return "expected an array";
|
|
118
|
+
if (v.length < min) return `expected at least ${min} items`;
|
|
119
|
+
for (let i = 0; i < v.length; i++) {
|
|
120
|
+
const e = item(v[i]);
|
|
121
|
+
if (e) return `[${i}]: ${e}`;
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
};
|
|
125
|
+
var color = (v) => typeof v === "number" && Number.isInteger(v) && v >= 0 && v <= 16777215 || typeof v === "string" && /^#[0-9a-fA-F]{6}$/.test(v) ? null : 'expected 0xRRGGBB or "#rrggbb"';
|
|
126
|
+
var oneOf = (values) => (v) => values.includes(v) ? null : `expected one of ${values.map((x) => JSON.stringify(x)).join(", ")}`;
|
|
127
|
+
var object = (fields, required = []) => (v) => {
|
|
128
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) return "expected an object";
|
|
129
|
+
const record = v;
|
|
130
|
+
for (const key of required) if (record[key] === void 0) return `${key}: required`;
|
|
131
|
+
for (const key of Object.keys(record)) {
|
|
132
|
+
if (record[key] === void 0) continue;
|
|
133
|
+
const check = fields[key];
|
|
134
|
+
if (!check) return `${key}: unknown field`;
|
|
135
|
+
const e = check(record[key]);
|
|
136
|
+
if (e) return `${key}: ${e}`;
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
};
|
|
140
|
+
var ORDERS = ["XYZ", "YXZ", "ZXY", "ZYX", "YZX", "XZY"];
|
|
141
|
+
var TRANSFORM = {
|
|
142
|
+
position: tuple(3),
|
|
143
|
+
rotation: tuple(3),
|
|
144
|
+
rotationOrder: oneOf(ORDERS),
|
|
145
|
+
scale: (v) => typeof v === "number" ? num(v) : tuple(3)(v),
|
|
146
|
+
heading: num,
|
|
147
|
+
matrix: tuple(16)
|
|
148
|
+
};
|
|
149
|
+
var UV = object({ u0: num, v0: num, u1: num, v1: num }, ["u0", "v0", "u1", "v1"]);
|
|
150
|
+
var INSTANCE = object({ ...TRANSFORM, color });
|
|
151
|
+
var COMMON = {
|
|
152
|
+
...TRANSFORM,
|
|
153
|
+
kind: str,
|
|
154
|
+
name: str,
|
|
155
|
+
part: str,
|
|
156
|
+
material: str,
|
|
157
|
+
color,
|
|
158
|
+
uv: UV,
|
|
159
|
+
instances: list(INSTANCE),
|
|
160
|
+
minDetail: range(0, 1, true),
|
|
161
|
+
tags: list(str)
|
|
162
|
+
};
|
|
163
|
+
var vec2 = tuple(2);
|
|
164
|
+
var BEVEL = (v) => v === false ? null : object({ thickness: num, size: num, offset: num, segments: int(1) })(v);
|
|
165
|
+
var KINDS = {
|
|
166
|
+
group: { fields: {} },
|
|
167
|
+
box: { fields: { size: tuple(3), segments: tuple(3, int(1)) } },
|
|
168
|
+
cylinder: { fields: { radiusTop: num, radiusBottom: num, height: num, radialSegments: int(1), heightSegments: int(1), openEnded: bool, thetaStart: num, thetaLength: num } },
|
|
169
|
+
cone: { fields: { radius: num, height: num, radialSegments: int(1), heightSegments: int(1), openEnded: bool, thetaStart: num, thetaLength: num } },
|
|
170
|
+
sphere: { fields: { radius: num, widthSegments: int(3), heightSegments: int(2), phiStart: num, phiLength: num, thetaStart: num, thetaLength: num } },
|
|
171
|
+
plane: { fields: { width: num, height: num, widthSegments: int(1), heightSegments: int(1) } },
|
|
172
|
+
circle: { fields: { radius: num, segments: int(3), thetaStart: num, thetaLength: num } },
|
|
173
|
+
ring: { fields: { innerRadius: num, outerRadius: num, thetaSegments: int(3), phiSegments: int(1), thetaStart: num, thetaLength: num } },
|
|
174
|
+
lathe: { fields: { points: list(vec2, 2), segments: int(1), phiStart: num, phiLength: num }, required: ["points"] },
|
|
175
|
+
torus: { fields: { radius: num, tube: num, radialSegments: int(1), tubularSegments: int(1), arc: num } },
|
|
176
|
+
extrude: {
|
|
177
|
+
fields: { shape: object({ outer: list(vec2, 3), holes: list(list(vec2, 3)) }, ["outer"]), depth: num, steps: int(1), bevel: BEVEL },
|
|
178
|
+
required: ["shape"]
|
|
179
|
+
},
|
|
180
|
+
difference: { fields: { size: tuple(3), subtract: list(object({ min: vec2, max: vec2 }, ["min", "max"])) }, required: ["size", "subtract"] },
|
|
181
|
+
mesh: {
|
|
182
|
+
fields: {
|
|
183
|
+
positions: (v) => list(num)(v) ?? (v.length % 3 === 0 ? null : "expected a multiple of 3 numbers"),
|
|
184
|
+
normals: list(num),
|
|
185
|
+
uvs: list(num),
|
|
186
|
+
indices: list(int(0))
|
|
187
|
+
},
|
|
188
|
+
required: ["positions"]
|
|
189
|
+
},
|
|
190
|
+
point: { fields: { data: () => null } },
|
|
191
|
+
custom: { fields: { generator: str, params: () => null }, required: ["generator"] }
|
|
192
|
+
};
|
|
193
|
+
function mergeTransformed(pieces) {
|
|
194
|
+
let total = 0;
|
|
195
|
+
for (const piece2 of pieces) total += piece2.indices ? piece2.indices.length : piece2.positions.length / 3;
|
|
196
|
+
const positions = new Float32Array(total * 3);
|
|
197
|
+
const normals = new Float32Array(total * 3);
|
|
198
|
+
const uvs = new Float32Array(total * 2);
|
|
199
|
+
let at = 0;
|
|
200
|
+
for (const piece2 of pieces) {
|
|
201
|
+
const e = piece2.matrix;
|
|
202
|
+
const nm = normalMatrix(e);
|
|
203
|
+
const count = piece2.indices ? piece2.indices.length : piece2.positions.length / 3;
|
|
204
|
+
const p = new Float32Array(count * 3);
|
|
205
|
+
const n = new Float32Array(count * 3);
|
|
206
|
+
for (let k = 0; k < count; k++) {
|
|
207
|
+
const i = piece2.indices ? piece2.indices[k] : k;
|
|
208
|
+
for (let c = 0; c < 3; c++) {
|
|
209
|
+
p[k * 3 + c] = piece2.positions[i * 3 + c];
|
|
210
|
+
if (piece2.normals) n[k * 3 + c] = piece2.normals[i * 3 + c];
|
|
211
|
+
}
|
|
212
|
+
if (piece2.uvs) {
|
|
213
|
+
uvs[(at + k) * 2] = piece2.uvs[i * 2];
|
|
214
|
+
uvs[(at + k) * 2 + 1] = piece2.uvs[i * 2 + 1];
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
for (let k = 0; k < count; k++) {
|
|
218
|
+
const q = transformPoint(e, p[k * 3], p[k * 3 + 1], p[k * 3 + 2]);
|
|
219
|
+
positions[(at + k) * 3] = q[0];
|
|
220
|
+
positions[(at + k) * 3 + 1] = q[1];
|
|
221
|
+
positions[(at + k) * 3 + 2] = q[2];
|
|
222
|
+
const x = n[k * 3];
|
|
223
|
+
const y = n[k * 3 + 1];
|
|
224
|
+
const z = n[k * 3 + 2];
|
|
225
|
+
const vx = nm[0] * x + nm[3] * y + nm[6] * z;
|
|
226
|
+
const vy = nm[1] * x + nm[4] * y + nm[7] * z;
|
|
227
|
+
const vz = nm[2] * x + nm[5] * y + nm[8] * z;
|
|
228
|
+
const s = 1 / (Math.sqrt(vx * vx + vy * vy + vz * vz) || 1);
|
|
229
|
+
normals[(at + k) * 3] = vx * s;
|
|
230
|
+
normals[(at + k) * 3 + 1] = vy * s;
|
|
231
|
+
normals[(at + k) * 3 + 2] = vz * s;
|
|
232
|
+
}
|
|
233
|
+
at += count;
|
|
234
|
+
}
|
|
235
|
+
return { positions, normals, uvs };
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// ../game-shapes-three/dist/index.js
|
|
239
|
+
var isVisible = (object2) => {
|
|
240
|
+
for (let node = object2; node; node = node.parent) if (!node.visible) return false;
|
|
241
|
+
return true;
|
|
242
|
+
};
|
|
243
|
+
var plain = (attribute) => attribute !== void 0 && !attribute.isInterleavedBufferAttribute && attribute.array instanceof Float32Array && !attribute.normalized;
|
|
244
|
+
function piece(geometry, matrix) {
|
|
245
|
+
const position = geometry.getAttribute("position");
|
|
246
|
+
const normal = geometry.getAttribute("normal");
|
|
247
|
+
const uv = geometry.getAttribute("uv");
|
|
248
|
+
const ok = plain(position) && (normal === void 0 || plain(normal)) && (uv === void 0 || plain(uv)) && position.itemSize === 3 && (uv === void 0 || uv.itemSize === 2);
|
|
249
|
+
if (ok) {
|
|
250
|
+
return { positions: position.array, ...normal ? { normals: normal.array } : {}, ...uv ? { uvs: uv.array } : {}, indices: geometry.index ? geometry.index.array : null, matrix: matrix.elements };
|
|
251
|
+
}
|
|
252
|
+
const flat = geometry.index ? geometry.toNonIndexed() : geometry;
|
|
253
|
+
const read = (name, size) => {
|
|
254
|
+
const attribute = flat.getAttribute(name);
|
|
255
|
+
if (!attribute) return void 0;
|
|
256
|
+
const out = new Float32Array(attribute.count * size);
|
|
257
|
+
for (let i = 0; i < attribute.count; i++) for (let c = 0; c < size; c++) out[i * size + c] = c === 0 ? attribute.getX(i) : c === 1 ? attribute.getY(i) : attribute.getZ(i);
|
|
258
|
+
return out;
|
|
259
|
+
};
|
|
260
|
+
const positions = read("position", 3);
|
|
261
|
+
const normals = read("normal", 3);
|
|
262
|
+
const uvs = read("uv", 2);
|
|
263
|
+
if (flat !== geometry) flat.dispose();
|
|
264
|
+
return { positions, ...normals ? { normals } : {}, ...uvs ? { uvs } : {}, indices: null, matrix: matrix.elements };
|
|
265
|
+
}
|
|
266
|
+
function mergeByMaterial(THREE, root, space) {
|
|
267
|
+
const toSpace = space.matrixWorld.clone().invert();
|
|
268
|
+
const byMaterial = /* @__PURE__ */ new Map();
|
|
269
|
+
root.traverse((object2) => {
|
|
270
|
+
const mesh = object2;
|
|
271
|
+
if (!mesh.isMesh || Array.isArray(mesh.material) || !isVisible(mesh)) return;
|
|
272
|
+
const list2 = byMaterial.get(mesh.material) ?? [];
|
|
273
|
+
list2.push(piece(mesh.geometry, new THREE.Matrix4().multiplyMatrices(toSpace, mesh.matrixWorld)));
|
|
274
|
+
byMaterial.set(mesh.material, list2);
|
|
275
|
+
});
|
|
276
|
+
return [...byMaterial].map(([material, pieces]) => {
|
|
277
|
+
const merged = mergeTransformed(pieces);
|
|
278
|
+
const geometry = new THREE.BufferGeometry();
|
|
279
|
+
geometry.setAttribute("position", new THREE.BufferAttribute(merged.positions, 3));
|
|
280
|
+
geometry.setAttribute("normal", new THREE.BufferAttribute(merged.normals, 3));
|
|
281
|
+
geometry.setAttribute("uv", new THREE.BufferAttribute(merged.uvs, 2));
|
|
282
|
+
const mesh = new THREE.Mesh(geometry, material);
|
|
283
|
+
mesh.castShadow = false;
|
|
284
|
+
mesh.receiveShadow = true;
|
|
285
|
+
return mesh;
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// ../game-props3d/dist/index.js
|
|
67
290
|
function rng(seed) {
|
|
68
291
|
let s = seed >>> 0;
|
|
69
292
|
return () => {
|
|
@@ -567,10 +790,10 @@ var GameFloorplanThree = (() => {
|
|
|
567
790
|
if (on) K.light(0, t - 0.15, 0, 16771256, 6, "ceiling_light");
|
|
568
791
|
};
|
|
569
792
|
B.pendant = (M, a) => {
|
|
570
|
-
const K = kit(M, a), t = K.ceiling(), { h } = K.dim("pendant"), ys = t - h,
|
|
793
|
+
const K = kit(M, a), t = K.ceiling(), { h } = K.dim("pendant"), ys = t - h, color2 = K.main(2763306);
|
|
571
794
|
K.box("plain", 0, ys + 0.1, 0, 0.012, h - 0.1, 0.012, 1710618);
|
|
572
795
|
K.cyl("plain", 0, t - 0.03, 0, 0.05, 0.03, 15262940);
|
|
573
|
-
K.cyl("plain", 0, ys, 0, 0.17, 0.14,
|
|
796
|
+
K.cyl("plain", 0, ys, 0, 0.17, 0.14, color2, 0, 0, "sphere");
|
|
574
797
|
K.cyl("emissive", 0, ys - 0.035, 0, 0.045, 0.09, 16769184, 0, 0, "sphere");
|
|
575
798
|
if (M.light) K.light(0, ys - 0.1, 0, 16763008, 6, "pendant");
|
|
576
799
|
};
|
|
@@ -939,9 +1162,9 @@ var GameFloorplanThree = (() => {
|
|
|
939
1162
|
K.box("plain", sx + 0.15, 0.012, sz + 0.05, 0.09, 0.07, 0.27, 2763306, 0.9);
|
|
940
1163
|
};
|
|
941
1164
|
B.fallen_chair = (M, a) => {
|
|
942
|
-
const g = Math.PI / 2, dy = 0.23, api = { box: (Mm, mat, x, y, z, w, h, d,
|
|
1165
|
+
const g = Math.PI / 2, dy = 0.23, api = { box: (Mm, mat, x, y, z, w, h, d, color2, ry, rx, rz) => {
|
|
943
1166
|
const cy = y + h / 2;
|
|
944
|
-
a.box(Mm, mat, -cy + 0, dy + x - h / 2 + 0 - 0, z, w, h, d,
|
|
1167
|
+
a.box(Mm, mat, -cy + 0, dy + x - h / 2 + 0 - 0, z, w, h, d, color2, ry, rx, g + (rz || 0));
|
|
945
1168
|
} };
|
|
946
1169
|
const K = kit(M, api), c = K.main(6965808);
|
|
947
1170
|
K.box("wood", 0, 0.44, 0, 0.42, 0.04, 0.42, c);
|
|
@@ -1031,20 +1254,20 @@ var GameFloorplanThree = (() => {
|
|
|
1031
1254
|
K.plane("atlas_picture", 0, y + h / 2, d / 2 + 3e-3, w - 0.05, h - 0.05, 16777215, 0, 0, 0, A.mirror());
|
|
1032
1255
|
};
|
|
1033
1256
|
B.curtain = (M, a) => {
|
|
1034
|
-
const K = kit(M, a), { w, h } = K.dim("curtain"), y = M.y != null && M.y > 0 ? M.y : 0.1,
|
|
1257
|
+
const K = kit(M, a), { w, h } = K.dim("curtain"), y = M.y != null && M.y > 0 ? M.y : 0.1, color2 = K.fabric(pick(K, [14208436, 10465470, 12953740, 14736592])), isOpen = M.open !== false, top = y + h;
|
|
1035
1258
|
K.box("metal", 0, top, 0, w + 0.1, 0.025, 0.025, K.metal(5918792));
|
|
1036
1259
|
for (const s of [-1, 1]) K.cyl("metal", s * (w / 2 + 0.07), top - 0.02, 0, 0.03, 0.07, 5918792, 0, 0, "sphere");
|
|
1037
1260
|
const pw = isOpen ? Math.min(0.5, w * 0.3) : w / 2 + 0.03, n = Math.max(4, Math.round(pw / 0.08));
|
|
1038
1261
|
for (const s of [-1, 1]) for (let i = 0; i < n; i++) {
|
|
1039
1262
|
const ux = isOpen ? s * (w / 2 + 0.03 - pw + (i + 0.5) * pw / n) : s * ((i + 0.5) * pw / n);
|
|
1040
|
-
K.box("fabric", ux, y, i % 2 ? 0.025 : -0.01, pw / n * 1.15, h - 0.02, 0.02, i % 2 ? shade(
|
|
1263
|
+
K.box("fabric", ux, y, i % 2 ? 0.025 : -0.01, pw / n * 1.15, h - 0.02, 0.02, i % 2 ? shade(color2, 0.9) : color2);
|
|
1041
1264
|
}
|
|
1042
|
-
if (isOpen) for (const s of [-1, 1]) K.box("fabric", s * (w / 2 - pw * 0.25), y + h * 0.4, 0.04, pw * 0.5, 0.05, 0.02, shade(
|
|
1265
|
+
if (isOpen) for (const s of [-1, 1]) K.box("fabric", s * (w / 2 - pw * 0.25), y + h * 0.4, 0.04, pw * 0.5, 0.05, 0.02, shade(color2, 0.7));
|
|
1043
1266
|
};
|
|
1044
1267
|
B.blinds = (M, a) => {
|
|
1045
|
-
const K = kit(M, a), { w, h } = K.dim("blinds"), y = M.y || 1, retract = M.retracted != null ? M.retracted : 0.15, isWood = M.variant === "wood",
|
|
1268
|
+
const K = kit(M, a), { w, h } = K.dim("blinds"), y = M.y || 1, retract = M.retracted != null ? M.retracted : 0.15, isWood = M.variant === "wood", color2 = isWood ? K.wood(10123858) : K.color("wall_living", 15262420), mat = isWood ? "wood" : "plain", yb = y + h * retract, n = Math.floor((y + h - yb) / 0.055);
|
|
1046
1269
|
K.box("plain", 0, y + h - 0.05, 0, w, 0.05, 0.06, 14473424);
|
|
1047
|
-
for (let i = 0; i < n; i++) K.box(mat, 0, y + h - 0.06 - (i + 1) * 0.055, 0, w - 0.05, 0.01, 0.035,
|
|
1270
|
+
for (let i = 0; i < n; i++) K.box(mat, 0, y + h - 0.06 - (i + 1) * 0.055, 0, w - 0.05, 0.01, 0.035, color2, 0, 0.3);
|
|
1048
1271
|
for (const s of [-1, 1]) K.box("plain", s * (w / 2 - 0.05), yb, 0.02, 8e-3, y + h - 0.05 - yb, 8e-3, 12104876);
|
|
1049
1272
|
K.box("plain", 0, yb - 0.02, 0, w - 0.03, 0.025, 0.04, 14473424);
|
|
1050
1273
|
};
|
|
@@ -1337,13 +1560,13 @@ var GameFloorplanThree = (() => {
|
|
|
1337
1560
|
const size = o.size || A.size(kind);
|
|
1338
1561
|
const nv = A.variants(kind);
|
|
1339
1562
|
const y = o.y != null ? o.y : HEIGHTS[kind] || 0.03;
|
|
1340
|
-
const
|
|
1563
|
+
const color2 = o.color != null ? hex(o.color) : 16777215;
|
|
1341
1564
|
const poly = o.poly || M.poly;
|
|
1342
1565
|
const sd = seedOf(M);
|
|
1343
1566
|
const rnd = rng(sd);
|
|
1344
1567
|
const tint = () => {
|
|
1345
1568
|
const v = 0.93 + rnd() * 0.07;
|
|
1346
|
-
return mix(0,
|
|
1569
|
+
return mix(0, color2, v);
|
|
1347
1570
|
};
|
|
1348
1571
|
const quad = (cx, cz, qw, qd, uv) => api.plane(M, "atlas_floor", cx, y, cz, qw, qd, tint(), 0, -Math.PI / 2, 0, uv);
|
|
1349
1572
|
if (!poly) {
|
|
@@ -1393,13 +1616,13 @@ var GameFloorplanThree = (() => {
|
|
|
1393
1616
|
M,
|
|
1394
1617
|
api,
|
|
1395
1618
|
rnd: rng(seedOf(M)),
|
|
1396
|
-
box: (material, x, y, z, w, h, d,
|
|
1397
|
-
cyl: (material, x, y, z, r, h,
|
|
1398
|
-
leaf: (x, y, z, w, h,
|
|
1399
|
-
plane: (material, x, y, z, w, h,
|
|
1400
|
-
light: (x, y, z,
|
|
1401
|
-
if (api.light) api.light(M, x, y, z, hex(
|
|
1402
|
-
else emit("light", { M, x, y, z, color: hex(
|
|
1619
|
+
box: (material, x, y, z, w, h, d, color2, ry, rx, rz) => api.box(M, material, x, y, z, w, h, d, hex(color2), ry || 0, rx || 0, rz || 0),
|
|
1620
|
+
cyl: (material, x, y, z, r, h, color2, rx, rz, shape) => api.cylinder(M, material, x, y, z, r, h, hex(color2), rx || 0, rz || 0, shape),
|
|
1621
|
+
leaf: (x, y, z, w, h, color2, ry, rx) => api.leaf(M, x, y, z, w, h, hex(color2), ry || 0, rx || 0),
|
|
1622
|
+
plane: (material, x, y, z, w, h, color2, ry, rx, rz, uv) => api.plane(M, material, x, y, z, w, h, hex(color2), ry || 0, rx || 0, rz || 0, uv),
|
|
1623
|
+
light: (x, y, z, color2, range2, kind) => {
|
|
1624
|
+
if (api.light) api.light(M, x, y, z, hex(color2), range2, kind);
|
|
1625
|
+
else emit("light", { M, x, y, z, color: hex(color2), range: range2, kind });
|
|
1403
1626
|
},
|
|
1404
1627
|
// colours: role in the house palette (M.palette) or the default; main = M.color
|
|
1405
1628
|
color: (name, fallback) => role(name) ?? hex(fallback),
|
|
@@ -1414,10 +1637,10 @@ var GameFloorplanThree = (() => {
|
|
|
1414
1637
|
},
|
|
1415
1638
|
ceiling: () => M.ceiling || 2.9,
|
|
1416
1639
|
// long tilted box: starts at (x, y, z) and follows u = (0, sin a, -cos a) for L meters
|
|
1417
|
-
ramp(material, x, y, z, w, t, L,
|
|
1640
|
+
ramp(material, x, y, z, w, t, L, color2, alpha) {
|
|
1418
1641
|
const cy = y + Math.sin(alpha) * L / 2;
|
|
1419
1642
|
const cz = z - Math.cos(alpha) * L / 2;
|
|
1420
|
-
K.box(material, x, cy - t / 2, cz, w, t, L,
|
|
1643
|
+
K.box(material, x, cy - t / 2, cz, w, t, L, color2, 0, alpha + Math.PI, 0);
|
|
1421
1644
|
}
|
|
1422
1645
|
};
|
|
1423
1646
|
return K;
|
|
@@ -1598,19 +1821,19 @@ var GameFloorplanThree = (() => {
|
|
|
1598
1821
|
for (const key in owner) if (!skip.includes(key)) walk(owner[key], 0);
|
|
1599
1822
|
return found;
|
|
1600
1823
|
};
|
|
1601
|
-
var isVisibleInTree = (
|
|
1602
|
-
for (let node =
|
|
1824
|
+
var isVisibleInTree = (object2) => {
|
|
1825
|
+
for (let node = object2; node; node = node.parent) if (!node.visible) return false;
|
|
1603
1826
|
return true;
|
|
1604
1827
|
};
|
|
1605
1828
|
var createNodeSkin = (THREE, root, options = {}) => {
|
|
1606
1829
|
const referenced = new Set(options.nodes ?? []);
|
|
1607
1830
|
const nodes = [];
|
|
1608
1831
|
const indexOf = /* @__PURE__ */ new Map();
|
|
1609
|
-
root.traverse((
|
|
1610
|
-
const mesh2 =
|
|
1611
|
-
if (!mesh2.isMesh ||
|
|
1612
|
-
indexOf.set(
|
|
1613
|
-
nodes.push(
|
|
1832
|
+
root.traverse((object2) => {
|
|
1833
|
+
const mesh2 = object2;
|
|
1834
|
+
if (!mesh2.isMesh || object2.children.length > 0 || referenced.has(object2)) {
|
|
1835
|
+
indexOf.set(object2, nodes.length);
|
|
1836
|
+
nodes.push(object2);
|
|
1614
1837
|
}
|
|
1615
1838
|
});
|
|
1616
1839
|
const positions = [];
|
|
@@ -1619,7 +1842,7 @@ var GameFloorplanThree = (() => {
|
|
|
1619
1842
|
const surfaces = [];
|
|
1620
1843
|
const nodeIndices = [];
|
|
1621
1844
|
const samples = /* @__PURE__ */ new Map();
|
|
1622
|
-
const
|
|
1845
|
+
const color2 = new THREE.Color();
|
|
1623
1846
|
const vertex = new THREE.Vector3();
|
|
1624
1847
|
const normal = new THREE.Vector3();
|
|
1625
1848
|
const sampleOf = (texture) => {
|
|
@@ -1633,22 +1856,22 @@ var GameFloorplanThree = (() => {
|
|
|
1633
1856
|
samples.set(texture, sample);
|
|
1634
1857
|
return sample;
|
|
1635
1858
|
};
|
|
1636
|
-
root.traverse((
|
|
1637
|
-
const mesh2 =
|
|
1638
|
-
if (!mesh2.isMesh || !isVisibleInTree(
|
|
1859
|
+
root.traverse((object2) => {
|
|
1860
|
+
const mesh2 = object2;
|
|
1861
|
+
if (!mesh2.isMesh || !isVisibleInTree(object2)) return;
|
|
1639
1862
|
const material2 = Array.isArray(mesh2.material) ? mesh2.material[0] : mesh2.material;
|
|
1640
1863
|
const geometry2 = mesh2.geometry;
|
|
1641
1864
|
const position = geometry2.attributes.position;
|
|
1642
1865
|
const normalAttribute = geometry2.attributes.normal;
|
|
1643
1866
|
const uv = geometry2.attributes.uv;
|
|
1644
1867
|
const matrix = new THREE.Matrix4();
|
|
1645
|
-
let nodeIndex = indexOf.get(
|
|
1868
|
+
let nodeIndex = indexOf.get(object2);
|
|
1646
1869
|
if (nodeIndex === void 0) {
|
|
1647
|
-
nodeIndex = indexOf.get(
|
|
1648
|
-
|
|
1649
|
-
matrix.copy(
|
|
1870
|
+
nodeIndex = indexOf.get(object2.parent) ?? 0;
|
|
1871
|
+
object2.updateMatrix();
|
|
1872
|
+
matrix.copy(object2.matrix);
|
|
1650
1873
|
}
|
|
1651
|
-
const
|
|
1874
|
+
const normalMatrix2 = new THREE.Matrix3().getNormalMatrix(matrix);
|
|
1652
1875
|
const sample = material2.map ? sampleOf(material2.map) : void 0;
|
|
1653
1876
|
const emissive = material2.emissive ? (material2.emissive.r + material2.emissive.g + material2.emissive.b) * (material2.emissiveIntensity ?? 1) : 0;
|
|
1654
1877
|
const index = geometry2.index ? geometry2.index.array : null;
|
|
@@ -1657,10 +1880,10 @@ var GameFloorplanThree = (() => {
|
|
|
1657
1880
|
const at = index ? index[item] : item;
|
|
1658
1881
|
vertex.fromBufferAttribute(position, at).applyMatrix4(matrix);
|
|
1659
1882
|
positions.push(vertex.x, vertex.y, vertex.z);
|
|
1660
|
-
if (normalAttribute) normal.fromBufferAttribute(normalAttribute, at).applyMatrix3(
|
|
1883
|
+
if (normalAttribute) normal.fromBufferAttribute(normalAttribute, at).applyMatrix3(normalMatrix2).normalize();
|
|
1661
1884
|
else normal.set(0, 1, 0);
|
|
1662
1885
|
normals.push(normal.x, normal.y, normal.z);
|
|
1663
|
-
|
|
1886
|
+
color2.copy(material2.color || color2.set(1, 1, 1)).convertLinearToSRGB();
|
|
1664
1887
|
if (sample && uv && material2.map) {
|
|
1665
1888
|
const repeat = material2.map.repeat;
|
|
1666
1889
|
const u = (uv.getX(at) * repeat.x % 1 + 1) % 1;
|
|
@@ -1668,10 +1891,10 @@ var GameFloorplanThree = (() => {
|
|
|
1668
1891
|
const pixelX = Math.min(sample.width - 1, u * sample.width | 0);
|
|
1669
1892
|
const pixelY = Math.min(sample.height - 1, (1 - v) * sample.height | 0);
|
|
1670
1893
|
const offset = (pixelY * sample.width + pixelX) * 4;
|
|
1671
|
-
|
|
1894
|
+
color2.multiply(new THREE.Color().setRGB(sample.data[offset] / 255, sample.data[offset + 1] / 255, sample.data[offset + 2] / 255, THREE.SRGBColorSpace));
|
|
1672
1895
|
}
|
|
1673
|
-
if (emissive > 0.3)
|
|
1674
|
-
tints.push(
|
|
1896
|
+
if (emissive > 0.3) color2.lerp(material2.emissive, 0.7);
|
|
1897
|
+
tints.push(color2.r, color2.g, color2.b);
|
|
1675
1898
|
surfaces.push(material2.roughness ?? 0.8, material2.metalness ?? 0, emissive > 0.3 ? 1 : 0);
|
|
1676
1899
|
nodeIndices.push(nodeIndex);
|
|
1677
1900
|
}
|
|
@@ -1718,64 +1941,120 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
1718
1941
|
function createRecorder(options = {}) {
|
|
1719
1942
|
const primitives = [];
|
|
1720
1943
|
const api = {
|
|
1721
|
-
box: (M, material, x, y, z, w, h, d,
|
|
1722
|
-
cylinder: (M, material, x, y, z, r, h,
|
|
1723
|
-
leaf: (M, x, y, z, w, h,
|
|
1724
|
-
plane: (M, material, x, y, z, w, h,
|
|
1944
|
+
box: (M, material, x, y, z, w, h, d, color2, ry, rx, rz) => void primitives.push({ kind: "box", M, material, x, y, z, w, h, d, color: color2, ry, rx, rz }),
|
|
1945
|
+
cylinder: (M, material, x, y, z, r, h, color2, rx, rz, shape) => void primitives.push({ kind: "cylinder", M, material, x, y, z, r, h, color: color2, rx, rz, shape }),
|
|
1946
|
+
leaf: (M, x, y, z, w, h, color2, ry, rx) => void primitives.push({ kind: "leaf", M, x, y, z, w, h, color: color2, ry, rx }),
|
|
1947
|
+
plane: (M, material, x, y, z, w, h, color2, ry, rx, rz, uv) => void primitives.push({ kind: "plane", M, material, x, y, z, w, h, color: color2, ry, rx, rz, uv })
|
|
1725
1948
|
};
|
|
1726
1949
|
if (options.light !== false) {
|
|
1727
|
-
api.light = (M, x, y, z,
|
|
1950
|
+
api.light = (M, x, y, z, color2, range2, lightKind) => void primitives.push({ kind: "light", M, x, y, z, color: color2, range: range2, lightKind });
|
|
1728
1951
|
}
|
|
1729
1952
|
return { api, primitives };
|
|
1730
1953
|
}
|
|
1731
|
-
var
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
const
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1954
|
+
var LEAF = (() => {
|
|
1955
|
+
const f = [0, 0, 0, -0.5, 0.4, 0, 0.5, 0.4, 0, 0, 1, 0];
|
|
1956
|
+
const positions = [];
|
|
1957
|
+
const normals = [];
|
|
1958
|
+
const uvs = [];
|
|
1959
|
+
const indices = [];
|
|
1960
|
+
for (const side of [1, -1]) {
|
|
1961
|
+
const base = positions.length / 3;
|
|
1962
|
+
for (let i = 0; i < 4; i++) {
|
|
1963
|
+
positions.push(f[i * 3], f[i * 3 + 1], f[i * 3 + 2]);
|
|
1964
|
+
normals.push(0, 0, side);
|
|
1965
|
+
uvs.push(f[i * 3] + 0.5, f[i * 3 + 1]);
|
|
1966
|
+
}
|
|
1967
|
+
if (side === 1) indices.push(base, base + 2, base + 1, base + 1, base + 2, base + 3);
|
|
1968
|
+
else indices.push(base, base + 1, base + 2, base + 1, base + 3, base + 2);
|
|
1969
|
+
}
|
|
1970
|
+
return { positions, normals, uvs, indices };
|
|
1971
|
+
})();
|
|
1972
|
+
function createShapeRecorder(options = {}) {
|
|
1973
|
+
const cyl = options.cylinderSegments ?? 12;
|
|
1974
|
+
const hex2 = options.hexSegments ?? 6;
|
|
1975
|
+
const [sphereW, sphereH] = options.sphereSegments ?? [12, 8];
|
|
1976
|
+
const root = [];
|
|
1977
|
+
const parts = [];
|
|
1978
|
+
const partChildren = /* @__PURE__ */ new Map();
|
|
1979
|
+
let current = root;
|
|
1980
|
+
let lastFrame = null;
|
|
1981
|
+
const into = (M) => {
|
|
1982
|
+
const x = M?.x ?? 0;
|
|
1983
|
+
const z = M?.z ?? 0;
|
|
1984
|
+
const ry = M?.ry ?? 0;
|
|
1985
|
+
const last = lastFrame;
|
|
1986
|
+
if (last && last.list === current && current[current.length - 1] === last.group && Object.is(last.x, x) && Object.is(last.z, z) && Object.is(last.ry, ry)) return last.group.children;
|
|
1987
|
+
const group = { kind: "group", position: [x, 0, z], heading: ry, children: [] };
|
|
1988
|
+
current.push(group);
|
|
1989
|
+
lastFrame = { list: current, group, x, z, ry };
|
|
1990
|
+
return group.children;
|
|
1991
|
+
};
|
|
1992
|
+
const api = {
|
|
1993
|
+
box(M, material, x, y, z, w, h, d, color2, ry, rx, rz) {
|
|
1994
|
+
into(M).push({ kind: "box", material, color: color2, position: [x, y + h / 2, z], rotation: [rx, ry, rz], rotationOrder: "YXZ", scale: [w, h, d] });
|
|
1995
|
+
},
|
|
1996
|
+
cylinder(M, material, x, y, z, r, h, color2, rx, rz, shape) {
|
|
1997
|
+
const tilted = rx !== 0 || rz !== 0;
|
|
1998
|
+
const cy = shape === "sphere" ? y + h / 2 : tilted ? y : y + h / 2;
|
|
1999
|
+
const sy = shape === "sphere" ? h / 2 : h;
|
|
2000
|
+
const place = { material, color: color2, position: [x, cy, z], rotation: [rx, 0, rz], rotationOrder: "YXZ", scale: [r, sy, r] };
|
|
2001
|
+
const list2 = into(M);
|
|
2002
|
+
switch (shape) {
|
|
2003
|
+
case "cyl6":
|
|
2004
|
+
list2.push({ kind: "cylinder", radiusTop: 1, radiusBottom: 1, height: 1, radialSegments: hex2, ...place });
|
|
2005
|
+
break;
|
|
2006
|
+
case "cone":
|
|
2007
|
+
list2.push({ kind: "cylinder", radiusTop: 0, radiusBottom: 1, height: 1, radialSegments: cyl, ...place });
|
|
2008
|
+
break;
|
|
2009
|
+
case "sphere":
|
|
2010
|
+
list2.push({ kind: "sphere", radius: 1, widthSegments: sphereW, heightSegments: sphereH, ...place });
|
|
2011
|
+
break;
|
|
2012
|
+
default:
|
|
2013
|
+
list2.push({ kind: "cylinder", radiusTop: 1, radiusBottom: 1, height: 1, radialSegments: cyl, ...place });
|
|
2014
|
+
}
|
|
2015
|
+
},
|
|
2016
|
+
leaf(M, x, y, z, w, h, color2, ry, rx) {
|
|
2017
|
+
into(M).push({ kind: "mesh", ...LEAF, material: "plant", color: color2, position: [x, y, z], rotation: [rx, ry, 0], rotationOrder: "YXZ", scale: [w, h, 1] });
|
|
2018
|
+
},
|
|
2019
|
+
plane(M, material, x, y, z, w, h, color2, ry, rx, rz, uv) {
|
|
2020
|
+
into(M).push({
|
|
2021
|
+
kind: "plane",
|
|
2022
|
+
width: 1,
|
|
2023
|
+
height: 1,
|
|
2024
|
+
material,
|
|
2025
|
+
color: color2,
|
|
2026
|
+
position: [x, y, z],
|
|
2027
|
+
rotation: [rx, ry, rz],
|
|
2028
|
+
rotationOrder: "YXZ",
|
|
2029
|
+
scale: [w, h, 1],
|
|
2030
|
+
...uv ? { uv: { u0: uv.u0, v0: uv.v0, u1: uv.u1, v1: uv.v1 } } : {}
|
|
2031
|
+
});
|
|
2032
|
+
},
|
|
2033
|
+
light(M, x, y, z, color2, range2, kind) {
|
|
2034
|
+
into(M).push({ kind: "point", position: [x, y, z], data: { light: true, color: color2, range: range2, kind } });
|
|
2035
|
+
},
|
|
2036
|
+
part(id, pivot, ry, draw) {
|
|
2037
|
+
let children = partChildren.get(id);
|
|
2038
|
+
if (!children) {
|
|
2039
|
+
children = [];
|
|
2040
|
+
partChildren.set(id, children);
|
|
2041
|
+
parts.push({ id, pivot: [pivot[0], pivot[1], pivot[2]], ry });
|
|
2042
|
+
current.push({ kind: "group", part: id, position: [pivot[0], pivot[1], pivot[2]], rotation: [0, ry, 0], children });
|
|
2043
|
+
}
|
|
2044
|
+
const outer = current;
|
|
2045
|
+
current = children;
|
|
2046
|
+
try {
|
|
2047
|
+
draw();
|
|
2048
|
+
} finally {
|
|
2049
|
+
current = outer;
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
};
|
|
2053
|
+
return {
|
|
2054
|
+
api,
|
|
2055
|
+
parts,
|
|
2056
|
+
schema: () => ({ version: 1, ...options.name !== void 0 ? { name: options.name } : {}, root: { kind: "group", children: root } })
|
|
2057
|
+
};
|
|
1779
2058
|
}
|
|
1780
2059
|
|
|
1781
2060
|
// src/locale.ts
|
|
@@ -1795,7 +2074,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
1795
2074
|
"what.fridge": "fridge",
|
|
1796
2075
|
"what.pantry": "pantry",
|
|
1797
2076
|
"what.cabinet": "cabinet",
|
|
1798
|
-
"warn.interactablesIncomplete": "floorplan-three: cfg.interactives is incomplete (GameInteractables, GameInteractablesHousehold, GameInteractablesThree
|
|
2077
|
+
"warn.interactablesIncomplete": "floorplan-three: cfg.interactives is incomplete (GameInteractables, GameInteractablesHousehold, GameInteractablesThree)",
|
|
1799
2078
|
"message.locked": "Locked.",
|
|
1800
2079
|
"message.boarded": "Locked: the door is boarded up.",
|
|
1801
2080
|
"message.pickedUp": "Picked up: {name}{qty}",
|
|
@@ -1820,7 +2099,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
1820
2099
|
"what.fridge": "geladeira",
|
|
1821
2100
|
"what.pantry": "despensa",
|
|
1822
2101
|
"what.cabinet": "arm\xE1rio",
|
|
1823
|
-
"warn.interactablesIncomplete": "floorplan-three: cfg.interactives incompleto (GameInteractables, GameInteractablesHousehold, GameInteractablesThree
|
|
2102
|
+
"warn.interactablesIncomplete": "floorplan-three: cfg.interactives incompleto (GameInteractables, GameInteractablesHousehold, GameInteractablesThree)",
|
|
1824
2103
|
"message.locked": "Trancada.",
|
|
1825
2104
|
"message.boarded": "Trancada: a porta est\xE1 bloqueada com t\xE1buas.",
|
|
1826
2105
|
"message.pickedUp": "Pegou: {name}{qty}",
|
|
@@ -1987,7 +2266,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
1987
2266
|
_col.setHex(h);
|
|
1988
2267
|
return [_col.r, _col.g, _col.b];
|
|
1989
2268
|
};
|
|
1990
|
-
function put(mat, geo, px, py, pz, q, sx, sy, sz,
|
|
2269
|
+
function put(mat, geo, px, py, pz, q, sx, sy, sz, color2, uvr) {
|
|
1991
2270
|
{
|
|
1992
2271
|
const O = cursor.org, RY = cursor.ry;
|
|
1993
2272
|
if (RY) {
|
|
@@ -2009,7 +2288,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2009
2288
|
const x = q.x, y = q.y, z = q.z, w = q.w, x2 = x + x, y2 = y + y, z2 = z + z;
|
|
2010
2289
|
const xx = x * x2, xy = x * y2, xz = x * z2, yy = y * y2, yz = y * z2, zz = z * z2, wx = w * x2, wy = w * y2, wz = w * z2;
|
|
2011
2290
|
const m00 = 1 - (yy + zz), m01 = xy - wz, m02 = xz + wy, m10 = xy + wz, m11 = 1 - (xx + zz), m12 = yz - wx, m20 = xz - wy, m21 = yz + wx, m22 = 1 - (xx + yy);
|
|
2012
|
-
const [cr, cg, cb] = rgbOf(
|
|
2291
|
+
const [cr, cg, cb] = rgbOf(color2), scale = UV_SCALE[mat], b = A.nv;
|
|
2013
2292
|
for (let k = 0; k < G.nv; k++) {
|
|
2014
2293
|
const lx = G.p[k * 3] * sx, ly = G.p[k * 3 + 1] * sy, lz = G.p[k * 3 + 2] * sz;
|
|
2015
2294
|
const wx_ = m00 * lx + m01 * ly + m02 * lz + px, wy_ = m10 * lx + m11 * ly + m12 * lz + py, wz_ = m20 * lx + m21 * ly + m22 * lz + pz;
|
|
@@ -2064,21 +2343,21 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2064
2343
|
A.nv += G.nv;
|
|
2065
2344
|
A.ni += G.i ? G.i.length : G.nv;
|
|
2066
2345
|
}
|
|
2067
|
-
function boxC(mat, cx, cy, cz, sx, sy, sz,
|
|
2346
|
+
function boxC(mat, cx, cy, cz, sx, sy, sz, color2, rx = 0, ry = 0, rz = 0, uvr) {
|
|
2068
2347
|
if (rx || ry || rz) _q.setFromEuler(_e.set(rx, ry, rz, "YXZ"));
|
|
2069
2348
|
else _q.identity();
|
|
2070
|
-
put(mat, "box", cx, cy, cz, _q, sx, sy, sz,
|
|
2349
|
+
put(mat, "box", cx, cy, cz, _q, sx, sy, sz, color2, uvr);
|
|
2071
2350
|
}
|
|
2072
|
-
function bxBase(mat, x0, y0, z0, x1, y1, z1,
|
|
2351
|
+
function bxBase(mat, x0, y0, z0, x1, y1, z1, color2) {
|
|
2073
2352
|
if (x1 - x0 < 1e-4 || y1 - y0 < 1e-4 || z1 - z0 < 1e-4) return;
|
|
2074
2353
|
_q.identity();
|
|
2075
|
-
put(mat, "box", (x0 + x1) / 2, (y0 + y1) / 2, (z0 + z1) / 2, _q, x1 - x0, y1 - y0, z1 - z0,
|
|
2354
|
+
put(mat, "box", (x0 + x1) / 2, (y0 + y1) / 2, (z0 + z1) / 2, _q, x1 - x0, y1 - y0, z1 - z0, color2);
|
|
2076
2355
|
}
|
|
2077
|
-
function cylBase(mat, x, y, z, r, h,
|
|
2356
|
+
function cylBase(mat, x, y, z, r, h, color2, seg = "cyl") {
|
|
2078
2357
|
_q.identity();
|
|
2079
|
-
put(mat, seg, x, y + h / 2, z, _q, r * 2, h, r * 2,
|
|
2358
|
+
put(mat, seg, x, y + h / 2, z, _q, r * 2, h, r * 2, color2);
|
|
2080
2359
|
}
|
|
2081
|
-
function polyFace(mat, pts,
|
|
2360
|
+
function polyFace(mat, pts, color2, hint) {
|
|
2082
2361
|
const A = accFor(mat), n = pts.length, O = cursor.org, RY = cursor.ry;
|
|
2083
2362
|
A.ensure(n, (n - 2) * 3);
|
|
2084
2363
|
if (RY) {
|
|
@@ -2105,7 +2384,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2105
2384
|
nz = -nz;
|
|
2106
2385
|
[a, b] = [pts[0], pts[1]];
|
|
2107
2386
|
}
|
|
2108
|
-
const [cr, cg, cb] = rgbOf(
|
|
2387
|
+
const [cr, cg, cb] = rgbOf(color2), scale = UV_SCALE[mat] || 1, base = A.nv;
|
|
2109
2388
|
let e1x = b[0] - a[0], e1y = b[1] - a[1], e1z = b[2] - a[2];
|
|
2110
2389
|
const l1 = Math.hypot(e1x, e1y, e1z) || 1;
|
|
2111
2390
|
e1x /= l1;
|
|
@@ -2564,16 +2843,16 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2564
2843
|
const R = shared.ctx.r, F = R.facade;
|
|
2565
2844
|
if (id === "outside" || !shared.ctx.roomById[id]) {
|
|
2566
2845
|
const ac = F.finish;
|
|
2567
|
-
let mat = "plaster",
|
|
2846
|
+
let mat = "plaster", color2 = shared.ctx.colors.facade;
|
|
2568
2847
|
if (ac === "roughcast") mat = "roughcast";
|
|
2569
2848
|
else if (ac === "exposed_block") {
|
|
2570
2849
|
mat = "block";
|
|
2571
|
-
|
|
2850
|
+
color2 = 12894392;
|
|
2572
2851
|
} else if (ac === "partial_plaster" && !frontLine) {
|
|
2573
2852
|
mat = "block";
|
|
2574
|
-
|
|
2853
|
+
color2 = 12894392;
|
|
2575
2854
|
}
|
|
2576
|
-
return { color, mat, exterior: true };
|
|
2855
|
+
return { color: color2, mat, exterior: true };
|
|
2577
2856
|
}
|
|
2578
2857
|
return { color: wallColor(shared.ctx.roomById[id]), mat: "plaster", exterior: false };
|
|
2579
2858
|
}
|
|
@@ -2683,7 +2962,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2683
2962
|
wallBox(alongU, L, a, b, y0 + dH, y0 + effectiveHeight(f, wallHeight), th, lL.color, lH.color, lL.mat, lH.mat);
|
|
2684
2963
|
cursor.pc = null;
|
|
2685
2964
|
}
|
|
2686
|
-
const fb = (u0, y_0, u1, y_1, tt = th + 0.02,
|
|
2965
|
+
const fb = (u0, y_0, u1, y_1, tt = th + 0.02, color2 = frame) => alongU ? bx("wood", u0, y0 + y_0, L - tt / 2, u1, y0 + y_1, L + tt / 2, color2) : bx("wood", L - tt / 2, y0 + y_0, u0, L + tt / 2, y0 + y_1, u1, color2);
|
|
2687
2966
|
const jw = 0.05;
|
|
2688
2967
|
cursor.pc = pieceRecord("jamb:" + p.id, "wood_hard", null, { floor: f });
|
|
2689
2968
|
fb(a, 0, a + jw, visH);
|
|
@@ -2697,7 +2976,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2697
2976
|
if (cL && cL.id === p.opensTo) sw = -1;
|
|
2698
2977
|
else if (cH && cH.id === p.opensTo) sw = 1;
|
|
2699
2978
|
}
|
|
2700
|
-
const leaf = (u0, u1, y_0, y_1, tt,
|
|
2979
|
+
const leaf = (u0, u1, y_0, y_1, tt, color2, mat = "wood") => alongU ? bx(mat, u0, y0 + y_0, L - tt / 2, u1, y0 + y_1, L + tt / 2, color2) : bx(mat, L - tt / 2, y0 + y_0, u0, L + tt / 2, y0 + y_1, u1, color2);
|
|
2701
2980
|
const extC = wood;
|
|
2702
2981
|
const open0 = p.blocked ? false : shared.doorState.has(p.id) ? shared.doorState.get(p.id) : !!p.open;
|
|
2703
2982
|
shared.doorState.set(p.id, open0);
|
|
@@ -2706,19 +2985,19 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2706
2985
|
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 };
|
|
2707
2986
|
shared.ctx.colliders.push(colR);
|
|
2708
2987
|
fo.col = colR;
|
|
2709
|
-
const leafBox = (hu, d0, d1, y_0, y_1, tt,
|
|
2988
|
+
const leafBox = (hu, d0, d1, y_0, y_1, tt, color2, mat) => alongU ? bx(mat, d0, y_0, -tt / 2, d1, y_1, tt / 2, color2) : bx(mat, -tt / 2, y_0, d0, tt / 2, y_1, d1, color2);
|
|
2710
2989
|
const newGroup = (k, hu, topY) => {
|
|
2711
2990
|
cursor.group = "dyn:" + p.id + ":" + k;
|
|
2712
2991
|
fo.groups.push({ name: cursor.group, pos: alongU ? [hu, topY != null ? y0 + topY : y0, L] : [L, topY != null ? y0 + topY : y0, hu] });
|
|
2713
2992
|
};
|
|
2714
2993
|
if (p.model === "steel") {
|
|
2715
|
-
const light = [14276044, 13223615, 14999766], pal = ((R.seed | 0) + p.id.length * 7) % 4,
|
|
2994
|
+
const light = [14276044, 13223615, 14999766], pal = ((R.seed | 0) + p.id.length * 7) % 4, color2 = pal === 3 ? wood : light[pal], mid = (a + b) / 2;
|
|
2716
2995
|
newGroup(0, mid, visH);
|
|
2717
|
-
const la = a + jw - mid, lb = b - jw - mid, nSec = Math.max(4, Math.round(visH / 0.5)), hs = visH / nSec, grv = sh(
|
|
2718
|
-
leafBox(0, la, lb, -visH, 0, 0.05,
|
|
2996
|
+
const la = a + jw - mid, lb = b - jw - mid, nSec = Math.max(4, Math.round(visH / 0.5)), hs = visH / nSec, grv = sh(color2, 0.55);
|
|
2997
|
+
leafBox(0, la, lb, -visH, 0, 0.05, color2, "metal");
|
|
2719
2998
|
for (let k = 1; k < nSec; k++) leafBox(0, la, lb, -k * hs - 0.012, -k * hs + 0.012, 0.07, grv, "metal");
|
|
2720
2999
|
const np = Math.max(2, Math.round((lb - la) / 0.8)), pw = (lb - la) / np;
|
|
2721
|
-
for (let k = 0; k < nSec; k++) for (let i = 0; i < np; i++) leafBox(0, la + i * pw + 0.07, la + (i + 1) * pw - 0.07, -(k + 1) * hs + 0.07, -k * hs - 0.07, 0.062, sh(
|
|
3000
|
+
for (let k = 0; k < nSec; k++) for (let i = 0; i < np; i++) leafBox(0, la + i * pw + 0.07, la + (i + 1) * pw - 0.07, -(k + 1) * hs + 0.07, -k * hs - 0.07, 0.062, sh(color2, k % 2 ? 0.93 : 1.06), "metal");
|
|
2722
3001
|
for (let i = 0; i < np; i++) leafBox(0, la + i * pw + 0.14, la + (i + 1) * pw - 0.14, -hs + 0.12, -0.12, 0.072, 5924464, "glass");
|
|
2723
3002
|
leafBox(0, -0.1, 0.1, -visH + 0.5, -visH + 0.55, 0.085, 3815998, "metal");
|
|
2724
3003
|
fo.minScale = Math.min(1, 0.28 / visH);
|
|
@@ -2726,13 +3005,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2726
3005
|
} else {
|
|
2727
3006
|
const nf = p.model === "double" ? 2 : 1, aa = a + jw, bb = b - jw;
|
|
2728
3007
|
for (let k = 0; k < nf; k++) {
|
|
2729
|
-
const u0 = nf === 2 ? k ? (aa + bb) / 2 : aa : aa, u1 = nf === 2 ? k ? bb : (aa + bb) / 2 : bb,
|
|
3008
|
+
const u0 = nf === 2 ? k ? (aa + bb) / 2 : aa : aa, u1 = nf === 2 ? k ? bb : (aa + bb) / 2 : bb, color2 = p.exterior ? extC : wood;
|
|
2730
3009
|
const hingeAt = nf === 2 ? k ? u1 : u0 : p.hinge === "end" ? u1 : u0, dir = hingeAt === u0 ? 1 : -1, len = u1 - u0;
|
|
2731
3010
|
newGroup(k, hingeAt);
|
|
2732
3011
|
const d0 = dir > 0 ? 5e-3 : -len + 5e-3, d1 = dir > 0 ? len - 5e-3 : -5e-3;
|
|
2733
|
-
leafBox(hingeAt, d0, d1, 0, visH, 0.04,
|
|
3012
|
+
leafBox(hingeAt, d0, d1, 0, visH, 0.04, color2, PMAT);
|
|
2734
3013
|
{
|
|
2735
|
-
const e0 = Math.min(d0, d1) + 0.1, e1 = Math.max(d0, d1) - 0.1, pc = sh(
|
|
3014
|
+
const e0 = Math.min(d0, d1) + 0.1, e1 = Math.max(d0, d1) - 0.1, pc = sh(color2, 0.82);
|
|
2736
3015
|
if (e1 - e0 > 0.2 && visH > 1.2) {
|
|
2737
3016
|
leafBox(hingeAt, e0, e1, 0.15, visH * 0.45, 0.055, pc, PMAT);
|
|
2738
3017
|
leafBox(hingeAt, e0, e1, visH * 0.5, visH - 0.15, 0.055, pc, PMAT);
|
|
@@ -2769,9 +3048,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2769
3048
|
if (p.blocked) {
|
|
2770
3049
|
part("window_boards", [0, 0, 0], () => {
|
|
2771
3050
|
const rb = rngString(SEED() + "|" + seedKey(p.id) + "|tabua"), cx0 = alongU ? p.at : L, cz0 = alongU ? L : p.at, nT = Math.max(4, Math.round((visH - 0.3) / 0.3)), Lg = p.width + 0.34, WOODS = [8017460, 7031338, 9071172, 6177320, 7559746];
|
|
2772
|
-
const puts = (along, y, off, comp, alt, thickness,
|
|
3051
|
+
const puts = (along, y, off, comp, alt, thickness, color2, tilt) => {
|
|
2773
3052
|
const x = alongU ? along : L + off, z = alongU ? L + off : along;
|
|
2774
|
-
boxC("wood", x, y0 + y, z, comp, alt, thickness,
|
|
3053
|
+
boxC("wood", x, y0 + y, z, comp, alt, thickness, color2, 0, alongU ? 0 : K.PE, tilt);
|
|
2775
3054
|
};
|
|
2776
3055
|
const nailColor = (along, y, off) => {
|
|
2777
3056
|
const x = alongU ? along : L + off, z = alongU ? L + off : along;
|
|
@@ -2784,8 +3063,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2784
3063
|
puts(alongU ? cx0 : cz0, visH / 2, o1, Math.hypot(p.width + 0.2, visH - 0.4) + 0.1, 0.12, 0.028, sh(WOODS[rb() * 5 | 0], 0.85), a2);
|
|
2785
3064
|
}
|
|
2786
3065
|
for (let k = 0; k < nT; k++) {
|
|
2787
|
-
const y = 0.18 + k * (visH - 0.4) / (nT - 1) + (rb() - 0.5) * 0.04, comp = Lg + (rb() - 0.5) * 0.12, tilt = (rb() - 0.5) * 0.05, alt = 0.13 + rb() * 0.03, c0 = alongU ? cx0 : cz0,
|
|
2788
|
-
puts(c0 + (rb() - 0.5) * 0.06, y, o2, comp, alt, 0.03,
|
|
3066
|
+
const y = 0.18 + k * (visH - 0.4) / (nT - 1) + (rb() - 0.5) * 0.04, comp = Lg + (rb() - 0.5) * 0.12, tilt = (rb() - 0.5) * 0.05, alt = 0.13 + rb() * 0.03, c0 = alongU ? cx0 : cz0, color2 = WOODS[rb() * WOODS.length | 0];
|
|
3067
|
+
puts(c0 + (rb() - 0.5) * 0.06, y, o2, comp, alt, 0.03, color2, tilt);
|
|
2789
3068
|
for (const e of [-1, 1]) {
|
|
2790
3069
|
nailColor(c0 + e * (comp / 2 - 0.07), y + Math.sin(tilt) * e * comp / 2, o2 + sd * 0.019);
|
|
2791
3070
|
}
|
|
@@ -2817,7 +3096,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2817
3096
|
yb = Math.min(yb, 1.2);
|
|
2818
3097
|
}
|
|
2819
3098
|
const wref = R.walls.find((w) => w.floor === f && w.axis === j.axis && Math.abs((alongU ? w.v0 : w.u0) - L) < EPS), th = wref ? wref.thickness || 0.15 : 0.15, t = 0.05, tt = th + 0.02;
|
|
2820
|
-
const bar = (u0, y_0, u1, y_1, mat,
|
|
3099
|
+
const bar = (u0, y_0, u1, y_1, mat, color2, tw = tt) => alongU ? bx(mat, u0, y0 + y_0, L - tw / 2, u1, y0 + y_1, L + tw / 2, color2) : bx(mat, L - tw / 2, y0 + y_0, u0, L + tw / 2, y0 + y_1, u1, color2);
|
|
2821
3100
|
cursor.pc = pieceRecord("window_frame:" + j.id, "aluminium", null, { floor: f });
|
|
2822
3101
|
bar(a, ya, a + t, yb, "metal", fr);
|
|
2823
3102
|
bar(b - t, ya, b, yb, "metal", fr);
|
|
@@ -2929,9 +3208,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2929
3208
|
const y0 = Y0(f), H = Y0(m.link.to) - y0, n = Math.max(8, Math.round(H / 0.18)), c = Math.cos(m.ry), s = Math.sin(m.ry);
|
|
2930
3209
|
const wood = shared.ctx.colors.wood != null ? shared.ctx.colors.wood : 9071176, under = sh(wood, 0.7);
|
|
2931
3210
|
const P = (lx, lz) => [m.x + lx * c + lz * s, m.z - lx * s + lz * c];
|
|
2932
|
-
const boxL = (mat, lx, y, lz, w, h, d,
|
|
3211
|
+
const boxL = (mat, lx, y, lz, w, h, d, color2, rx = 0) => {
|
|
2933
3212
|
const [px, pz] = P(lx, lz);
|
|
2934
|
-
boxC(mat, px, y, pz, w, h, d,
|
|
3213
|
+
boxC(mat, px, y, pz, w, h, d, color2, rx, m.ry, 0);
|
|
2935
3214
|
};
|
|
2936
3215
|
for (let i = 0; i < n; i++) {
|
|
2937
3216
|
const top = (i + 1) * H / n, lz = m.d / 2 - (i + 0.5) * Dr / n;
|
|
@@ -3002,20 +3281,20 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
3002
3281
|
get A() {
|
|
3003
3282
|
return api;
|
|
3004
3283
|
},
|
|
3005
|
-
b: (mat, x, y, z, w, h, d,
|
|
3006
|
-
c: (mat, x, y, z, r, h,
|
|
3007
|
-
e: (mat, x, y, z, r, h,
|
|
3008
|
-
t(mat, p, q, r,
|
|
3284
|
+
b: (mat, x, y, z, w, h, d, color2, ry, rx, rz) => api.box(M, mat, x, y0 + y, z, w, h, d, color2, ry || 0, rx || 0, rz || 0),
|
|
3285
|
+
c: (mat, x, y, z, r, h, color2, seg) => api.cylinder(M, mat, x, y0 + y, z, r, h, color2, 0, 0, seg),
|
|
3286
|
+
e: (mat, x, y, z, r, h, color2) => api.cylinder(M, mat, x, y0 + y - h / 2, z, r, h, color2, 0, 0, "sphere"),
|
|
3287
|
+
t(mat, p, q, r, color2, seg) {
|
|
3009
3288
|
const dx = q[0] - p[0], dy = q[1] - p[1], dz = q[2] - p[2], L = Math.hypot(dx, dy, dz);
|
|
3010
3289
|
if (L < 1e-5) return;
|
|
3011
3290
|
const nx = dx / L, ny = dy / L, nz = dz / L;
|
|
3012
3291
|
if (Math.abs(nx) < 1e-4 && Math.abs(nz) < 1e-4) {
|
|
3013
|
-
api.cylinder(M, mat, p[0], y0 + Math.min(p[1], q[1]), p[2], r, L,
|
|
3292
|
+
api.cylinder(M, mat, p[0], y0 + Math.min(p[1], q[1]), p[2], r, L, color2, 0, 0, seg);
|
|
3014
3293
|
return;
|
|
3015
3294
|
}
|
|
3016
|
-
api.cylinder(M, mat, (p[0] + q[0]) / 2, y0 + (p[1] + q[1]) / 2, (p[2] + q[2]) / 2, r, L,
|
|
3295
|
+
api.cylinder(M, mat, (p[0] + q[0]) / 2, y0 + (p[1] + q[1]) / 2, (p[2] + q[2]) / 2, r, L, color2, Math.atan2(nz, ny), -Math.asin(nx), seg);
|
|
3017
3296
|
},
|
|
3018
|
-
polyFace: (mat, pts,
|
|
3297
|
+
polyFace: (mat, pts, color2, hint) => polyFace(mat, pts.map((p) => W(p[0], p[1], p[2])), color2, hint && [hint[0] * c + hint[2] * s, hint[1], -hint[0] * s + hint[2] * c]),
|
|
3019
3298
|
part(type, lx, ly, lz, fn, meta) {
|
|
3020
3299
|
if (type === "lamp" && String(cursor.group).startsWith("ix:light:")) {
|
|
3021
3300
|
fn();
|
|
@@ -3056,28 +3335,28 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
3056
3335
|
return v < 0.28 ? "recessed" : v < 0.5 ? "track" : v < 0.75 ? social ? "pendant" : "recessed" : /living|dining|hall/.test(tp) ? "chandelier" : "recessed";
|
|
3057
3336
|
}
|
|
3058
3337
|
function ceilingLamp(M, A, type) {
|
|
3059
|
-
const K2 = kit2(M, A, 0), t = M.ceiling || 2.8,
|
|
3060
|
-
const id = "lamp_" + (M.seed || hashString(M.x + "," + M.z)), meta = { id, room: M.room, on: !!M.on, color, lightType: type, hidden: !M.on };
|
|
3338
|
+
const K2 = kit2(M, A, 0), t = M.ceiling || 2.8, color2 = colorTemperature(M), r = rngString(SEED() + "|" + seedKey(M.seed) + "|lz");
|
|
3339
|
+
const id = "lamp_" + (M.seed || hashString(M.x + "," + M.z)), meta = { id, room: M.room, on: !!M.on, color: color2, lightType: type, hidden: !M.on };
|
|
3061
3340
|
const white = 16052972, offset = 15329247;
|
|
3062
|
-
let yLight = t - 0.18,
|
|
3341
|
+
let yLight = t - 0.18, range2 = 6;
|
|
3063
3342
|
const emitter = (fn) => K2.part("lamp", 0, t, 0, fn, meta);
|
|
3064
3343
|
if (type === "bare") {
|
|
3065
3344
|
K2.c("plain", 0, t - 0.03, 0, 0.05, 0.03, white);
|
|
3066
3345
|
K2.c("metal", 0, t - 0.085, 0, 0.022, 0.055, 6974054);
|
|
3067
3346
|
K2.c("plain", 0, t - 0.105, 0, 0.026, 0.02, 14209208);
|
|
3068
3347
|
K2.e("plain", 0, t - 0.165, 0, 0.036, 0.085, 15987178);
|
|
3069
|
-
emitter(() => K2.e("emissive", 0, t - 0.165, 0, 0.0385, 0.088,
|
|
3348
|
+
emitter(() => K2.e("emissive", 0, t - 0.165, 0, 0.0385, 0.088, color2));
|
|
3070
3349
|
yLight = t - 0.22;
|
|
3071
|
-
|
|
3350
|
+
range2 = 5.5;
|
|
3072
3351
|
} else if (type === "round") {
|
|
3073
3352
|
K2.c("plain", 0, t - 0.05, 0, 0.19, 0.05, white);
|
|
3074
3353
|
K2.c("plain", 0, t - 0.07, 0, 0.165, 0.02, offset);
|
|
3075
|
-
emitter(() => K2.c("emissive", 0, t - 0.073, 0, 0.1675, 0.023,
|
|
3354
|
+
emitter(() => K2.c("emissive", 0, t - 0.073, 0, 0.1675, 0.023, color2));
|
|
3076
3355
|
yLight = t - 0.2;
|
|
3077
3356
|
} else if (type === "square") {
|
|
3078
3357
|
K2.b("plain", 0, t - 0.05, 0, 0.36, 0.05, 0.36, white);
|
|
3079
3358
|
K2.b("plain", 0, t - 0.07, 0, 0.3, 0.02, 0.3, offset);
|
|
3080
|
-
emitter(() => K2.b("emissive", 0, t - 0.073, 0, 0.3025, 0.023, 0.3025,
|
|
3359
|
+
emitter(() => K2.b("emissive", 0, t - 0.073, 0, 0.3025, 0.023, 0.3025, color2));
|
|
3081
3360
|
yLight = t - 0.2;
|
|
3082
3361
|
} else if (type === "recessed") {
|
|
3083
3362
|
const o = 0.5;
|
|
@@ -3086,10 +3365,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
3086
3365
|
K2.c("plain", x, t - 0.026, z, 0.05, 0.012, offset);
|
|
3087
3366
|
}
|
|
3088
3367
|
emitter(() => {
|
|
3089
|
-
for (const [x, z] of [[-o, -o], [o, -o], [-o, o], [o, o]]) K2.c("emissive", x, t - 0.028, z, 0.0505, 0.014,
|
|
3368
|
+
for (const [x, z] of [[-o, -o], [o, -o], [-o, o], [o, o]]) K2.c("emissive", x, t - 0.028, z, 0.0505, 0.014, color2);
|
|
3090
3369
|
});
|
|
3091
3370
|
yLight = t - 0.3;
|
|
3092
|
-
|
|
3371
|
+
range2 = 6.5;
|
|
3093
3372
|
} else if (type === "track") {
|
|
3094
3373
|
const len = 1.1, angle = r() < 0.5 ? 0 : Math.PI / 2, c = Math.cos(angle), s = Math.sin(angle);
|
|
3095
3374
|
K2.b("metal", 0, t - 0.03, 0, angle ? 0.035 : len, 0.03, angle ? len : 0.035, 2763308);
|
|
@@ -3105,16 +3384,16 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
3105
3384
|
for (const [q, d] of cab) K2.t("emissive", [q[0] - d[0] * 3e-3, q[1] - d[1] * 3e-3, q[2] - d[2] * 3e-3], [q[0] + d[0] * 0.012, q[1] + d[1] * 0.012, q[2] + d[2] * 0.012], 0.029);
|
|
3106
3385
|
});
|
|
3107
3386
|
yLight = t - 0.3;
|
|
3108
|
-
|
|
3387
|
+
range2 = 6.5;
|
|
3109
3388
|
} else if (type === "pendant") {
|
|
3110
3389
|
const drop = Math.max(0.4, Math.min(1.1, t - 2.05)), yc = t - drop, cs = [2763308, 15262420, 12094036, 3495534][r() * 4 | 0];
|
|
3111
3390
|
K2.c("plain", 0, t - 0.025, 0, 0.05, 0.025, white);
|
|
3112
3391
|
K2.c("metal", 0, yc, 0, 6e-3, drop - 0.02, 1710618);
|
|
3113
3392
|
K2.e("plain", 0, yc - 0.09, 0, 0.19, 0.2, cs);
|
|
3114
3393
|
K2.e("plain", 0, yc - 0.2, 0, 0.065, 0.085, 15987178);
|
|
3115
|
-
emitter(() => K2.e("emissive", 0, yc - 0.2, 0, 0.069, 0.089,
|
|
3394
|
+
emitter(() => K2.e("emissive", 0, yc - 0.2, 0, 0.069, 0.089, color2));
|
|
3116
3395
|
yLight = yc - 0.3;
|
|
3117
|
-
|
|
3396
|
+
range2 = 6.5;
|
|
3118
3397
|
} else if (type === "chandelier") {
|
|
3119
3398
|
const yc = t - 0.5, gold = shared.ctx.colors && shared.ctx.colors.metal != null ? shared.ctx.colors.metal : 9075290, N = 6;
|
|
3120
3399
|
K2.c("metal", 0, yc, 0, 0.012, 0.5, gold);
|
|
@@ -3131,57 +3410,57 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
3131
3410
|
emitter(() => {
|
|
3132
3411
|
for (let i = 0; i < N; i++) {
|
|
3133
3412
|
const an = i * Math.PI * 2 / N;
|
|
3134
|
-
K2.e("emissive", Math.cos(an) * 0.28, yc + 0.07, Math.sin(an) * 0.28, 0.0155, 0.036,
|
|
3413
|
+
K2.e("emissive", Math.cos(an) * 0.28, yc + 0.07, Math.sin(an) * 0.28, 0.0155, 0.036, color2);
|
|
3135
3414
|
}
|
|
3136
3415
|
});
|
|
3137
3416
|
yLight = yc - 0.05;
|
|
3138
|
-
|
|
3417
|
+
range2 = 7;
|
|
3139
3418
|
} else if (type === "trough") {
|
|
3140
3419
|
K2.b("metal", 0, t - 0.045, 0, 1.2, 0.045, 0.1, 14474456);
|
|
3141
3420
|
K2.b("plain", 0, t - 0.058, 0, 1.12, 0.013, 0.06, 15329764);
|
|
3142
|
-
emitter(() => K2.b("emissive", 0, t - 0.0605, 0, 1.125, 0.0155, 0.0625,
|
|
3421
|
+
emitter(() => K2.b("emissive", 0, t - 0.0605, 0, 1.125, 0.0155, 0.0625, color2));
|
|
3143
3422
|
yLight = t - 0.2;
|
|
3144
|
-
|
|
3423
|
+
range2 = 7;
|
|
3145
3424
|
}
|
|
3146
|
-
if (M.on && A.light) A.light(Object.assign({}, M, { lampId: id }), 0, yLight, 0,
|
|
3425
|
+
if (M.on && A.light) A.light(Object.assign({}, M, { lampId: id }), 0, yLight, 0, color2, range2, "ceiling_light");
|
|
3147
3426
|
}
|
|
3148
3427
|
function tableLamp(M, A, y) {
|
|
3149
|
-
const K2 = kit2(M, A, 0),
|
|
3428
|
+
const K2 = kit2(M, A, 0), color2 = colorTemperature(M), id = "lamp_ab_" + M.seed, cp = [15786688, 15262420, 13621470][hashString(seedKey(M.seed) + "cp") % 3], meta = { id, room: M.room, on: !!M.on, color: color2, lightType: "table_lamp", hidden: !M.on };
|
|
3150
3429
|
K2.e("plain", 0, y + 0.045, 0, 0.065, 0.09, 3813928);
|
|
3151
3430
|
K2.c("metal", 0, y + 0.08, 0, 8e-3, 0.14, 9075290);
|
|
3152
3431
|
K2.c("plain", 0, y + 0.2, 0, 0.115, 0.15, cp);
|
|
3153
|
-
K2.part("lamp", 0, y + 0.2, 0, () => K2.c("emissive", 0, y + 0.2, 0, 0.118, 0.152,
|
|
3154
|
-
if (M.on && A.light) A.light(Object.assign({}, M, { lampId: id }), 0, y + 0.3, 0,
|
|
3432
|
+
K2.part("lamp", 0, y + 0.2, 0, () => K2.c("emissive", 0, y + 0.2, 0, 0.118, 0.152, color2), meta);
|
|
3433
|
+
if (M.on && A.light) A.light(Object.assign({}, M, { lampId: id }), 0, y + 0.3, 0, color2, 3.5, "table_lamp");
|
|
3155
3434
|
}
|
|
3156
3435
|
function floorLamp(M, A) {
|
|
3157
|
-
const K2 = kit2(M, A, M.y || 0),
|
|
3436
|
+
const K2 = kit2(M, A, M.y || 0), color2 = colorTemperature(M), id = "lamp_pe_" + M.seed, h = Math.min(1.6, M.h || 1.5), meta = { id, room: M.room, on: !!M.on, color: color2, lightType: "floor", hidden: !M.on };
|
|
3158
3437
|
K2.c("metal", 0, 0, 0, 0.13, 0.025, 2763308);
|
|
3159
3438
|
K2.c("metal", 0, 0.025, 0, 0.011, h - 0.3, 2763308);
|
|
3160
3439
|
K2.c("plain", 0, h - 0.28, 0, 0.17, 0.26, 15656656);
|
|
3161
|
-
K2.part("lamp", 0, h - 0.28, 0, () => K2.c("emissive", 0, h - 0.28, 0, 0.173, 0.262,
|
|
3162
|
-
if (M.on && A.light) A.light(Object.assign({}, M, { lampId: id }), 0, h - 0.15, 0,
|
|
3440
|
+
K2.part("lamp", 0, h - 0.28, 0, () => K2.c("emissive", 0, h - 0.28, 0, 0.173, 0.262, color2), meta);
|
|
3441
|
+
if (M.on && A.light) A.light(Object.assign({}, M, { lampId: id }), 0, h - 0.15, 0, color2, 5, "floor");
|
|
3163
3442
|
}
|
|
3164
3443
|
function sconce(M, A) {
|
|
3165
|
-
const K2 = kit2(M, A, M.y || 1.7),
|
|
3444
|
+
const K2 = kit2(M, A, M.y || 1.7), color2 = colorTemperature(M), id = "lamp_ar_" + M.seed, meta = { id, room: M.room, on: !!M.on, color: color2, lightType: "sconce", hidden: !M.on };
|
|
3166
3445
|
K2.b("metal", 0, -0.07, 8e-3, 0.07, 0.14, 0.016, 14210248);
|
|
3167
3446
|
K2.t("metal", [0, 0, 0.016], [0, 0, 0.075], 0.011, 11577480);
|
|
3168
3447
|
K2.e("plain", 0, 0, 0.1, 0.06, 0.15, 15920348);
|
|
3169
|
-
K2.part("lamp", 0, 0, 0.1, () => K2.e("emissive", 0, 0, 0.1, 0.0625, 0.153,
|
|
3170
|
-
if (M.on && A.light) A.light(Object.assign({}, M, { lampId: id }), 0, 0.02, 0.2,
|
|
3448
|
+
K2.part("lamp", 0, 0, 0.1, () => K2.e("emissive", 0, 0, 0.1, 0.0625, 0.153, color2), meta);
|
|
3449
|
+
if (M.on && A.light) A.light(Object.assign({}, M, { lampId: id }), 0, 0.02, 0.2, color2, 3, "sconce");
|
|
3171
3450
|
}
|
|
3172
3451
|
function outdoorLamp(M, A) {
|
|
3173
|
-
const K2 = kit2(M, A, M.y || 2.2),
|
|
3452
|
+
const K2 = kit2(M, A, M.y || 2.2), color2 = colorTemperature(M), id = "lamp_ext_" + M.seed, structure = STYLE(), meta = { id, room: "outside", on: !!M.on, color: color2, lightType: "outdoor", hidden: !M.on };
|
|
3174
3453
|
if (structure === "budget") {
|
|
3175
3454
|
K2.c("plain", 0, -0, 0.01, 0.05, 0.02, 15921386);
|
|
3176
3455
|
K2.t("metal", [0, 0, 0], [0, 0, 0.07], 0.022, 6974054);
|
|
3177
3456
|
K2.e("plain", 0, 0, 0.115, 0.036, 0.085, 15987178);
|
|
3178
|
-
K2.part("lamp", 0, 0, 0.115, () => K2.e("emissive", 0, 0, 0.115, 0.0385, 0.088,
|
|
3457
|
+
K2.part("lamp", 0, 0, 0.115, () => K2.e("emissive", 0, 0, 0.115, 0.0385, 0.088, color2), meta);
|
|
3179
3458
|
} else {
|
|
3180
3459
|
K2.b("metal", 0, -0.08, 0.01, 0.12, 0.16, 0.02, 2763308);
|
|
3181
3460
|
K2.b("plain", 0, -0.09, 0.07, 0.11, 0.18, 0.1, 15263454);
|
|
3182
|
-
K2.part("lamp", 0, -0.09, 0.07, () => K2.b("emissive", 0, -0.09, 0.07, 0.1125, 0.1825, 0.1025,
|
|
3461
|
+
K2.part("lamp", 0, -0.09, 0.07, () => K2.b("emissive", 0, -0.09, 0.07, 0.1125, 0.1825, 0.1025, color2), meta);
|
|
3183
3462
|
}
|
|
3184
|
-
if (M.on && A.light) A.light(Object.assign({}, M, { lampId: id }), 0, (M.y != null ? M.y : 2.2) - (structure === "budget" ? 0 : 0.09), structure === "budget" ? 0.2 : 0.2,
|
|
3463
|
+
if (M.on && A.light) A.light(Object.assign({}, M, { lampId: id }), 0, (M.y != null ? M.y : 2.2) - (structure === "budget" ? 0 : 0.09), structure === "budget" ? 0.2 : 0.2, color2, 3.2, "outdoor", { lumens: 3.2, dist: 5.5, decay: 2 });
|
|
3185
3464
|
}
|
|
3186
3465
|
function lightSwitch(M, A) {
|
|
3187
3466
|
const K2 = kit2(M, A, M.y != null && M.y > 0 ? M.y : 1.1), two = !!M.double;
|
|
@@ -3332,13 +3611,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
3332
3611
|
for (const s of lt.perimeter) {
|
|
3333
3612
|
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);
|
|
3334
3613
|
cursor.pc = pieceRecord("lot_wall:" + s.id, s.type === "wall" ? "brick" : s.type === "fence" ? "wood_soft" : "steel", null, { tags: ["wall"] });
|
|
3335
|
-
const th = s.thickness || 0.15, h = s.height,
|
|
3614
|
+
const th = s.thickness || 0.15, h = s.height, color2 = colorOf(s.color) != null ? colorOf(s.color) : C.wall || 12104874, len = b - a;
|
|
3336
3615
|
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);
|
|
3337
3616
|
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 };
|
|
3338
3617
|
shared.ctx.colliders.push(col);
|
|
3339
3618
|
if (s.type === "wall") {
|
|
3340
|
-
B("plaster", a, 0, b, h, th,
|
|
3341
|
-
B("plaster", a, h, b, h + 0.05, th + 0.06, sh(
|
|
3619
|
+
B("plaster", a, 0, b, h, th, color2);
|
|
3620
|
+
B("plaster", a, h, b, h + 0.05, th + 0.06, sh(color2, 1.15));
|
|
3342
3621
|
} else if (s.type === "fence") {
|
|
3343
3622
|
const np = Math.max(2, Math.round(len / 2.4) + 1);
|
|
3344
3623
|
for (let k = 0; k < np; k++) {
|
|
@@ -3350,8 +3629,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
3350
3629
|
B("metal", a, 0.08, b, 0.12, 0.03, 9080466);
|
|
3351
3630
|
} else {
|
|
3352
3631
|
const gc = C.gate != null ? C.gate : 2763310, mh = 0.5;
|
|
3353
|
-
B("plaster", a, 0, b, mh, th,
|
|
3354
|
-
B("plaster", a, mh, b, mh + 0.04, th + 0.05, sh(
|
|
3632
|
+
B("plaster", a, 0, b, mh, th, color2);
|
|
3633
|
+
B("plaster", a, mh, b, mh + 0.04, th + 0.05, sh(color2, 1.15));
|
|
3355
3634
|
const n = Math.max(2, Math.round(len / 0.13));
|
|
3356
3635
|
for (let k = 0; k <= n; k++) {
|
|
3357
3636
|
const u = a + k * len / n;
|
|
@@ -3400,9 +3679,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
3400
3679
|
cursor.group = "lot";
|
|
3401
3680
|
for (const c of lt.paths) {
|
|
3402
3681
|
if (c.type === "vehicle" && c.id !== "cargo_path") continue;
|
|
3403
|
-
const
|
|
3682
|
+
const color2 = c.type === "pedestrian" ? 13617856 : 11841704;
|
|
3404
3683
|
for (const [u0, v0, u1, v1] of c.rects) {
|
|
3405
|
-
bx("sidewalk", u0, 0, v0, u1, 0.05, v1,
|
|
3684
|
+
bx("sidewalk", u0, 0, v0, u1, 0.05, v1, color2);
|
|
3406
3685
|
}
|
|
3407
3686
|
}
|
|
3408
3687
|
}
|
|
@@ -3758,7 +4037,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
3758
4037
|
const { UV_SCALE, _Y, _h2, _q, accFor, cursor, put, rgbOf, structurePiece } = K;
|
|
3759
4038
|
const sh = (...a) => K.sh(...a);
|
|
3760
4039
|
const R_STYLE = () => shared.ctx.r && shared.ctx.r.style || "budget";
|
|
3761
|
-
function tileRelief(mat, pts,
|
|
4040
|
+
function tileRelief(mat, pts, color2, type) {
|
|
3762
4041
|
const n = pts.length;
|
|
3763
4042
|
if (n < 3) return;
|
|
3764
4043
|
const [a, b, c] = pts;
|
|
@@ -3822,7 +4101,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
3822
4101
|
}
|
|
3823
4102
|
col.push(lo <= hi ? [lo, hi] : null);
|
|
3824
4103
|
}
|
|
3825
|
-
const AC = accFor(mat), m = L.length, [cr, cg, cb] = rgbOf(
|
|
4104
|
+
const AC = accFor(mat), m = L.length, [cr, cg, cb] = rgbOf(color2), O = cursor.org;
|
|
3826
4105
|
AC.ensure(m * 2, (m - 1) * 6);
|
|
3827
4106
|
const base = AC.nv, w2 = 2 * Math.PI / P;
|
|
3828
4107
|
for (let j = 0; j < m; j++) {
|
|
@@ -4200,15 +4479,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
4200
4479
|
}
|
|
4201
4480
|
});
|
|
4202
4481
|
const parts = [];
|
|
4203
|
-
for (const { m, list, vc } of byMaterial.values()) {
|
|
4482
|
+
for (const { m, list: list2, vc } of byMaterial.values()) {
|
|
4204
4483
|
let nv = 0, ni = 0;
|
|
4205
|
-
for (const e of
|
|
4484
|
+
for (const e of list2) {
|
|
4206
4485
|
nv += e.P.length / 3;
|
|
4207
4486
|
ni += e.I ? e.I.length : e.P.length / 3;
|
|
4208
4487
|
}
|
|
4209
4488
|
const P = new Float32Array(nv * 3), N = new Float32Array(nv * 3), U = new Float32Array(nv * 2), I = new Uint32Array(ni);
|
|
4210
4489
|
let ov = 0, oi = 0;
|
|
4211
|
-
for (const e of
|
|
4490
|
+
for (const e of list2) {
|
|
4212
4491
|
const n = e.P.length / 3;
|
|
4213
4492
|
P.set(e.P, ov * 3);
|
|
4214
4493
|
N.set(e.N, ov * 3);
|
|
@@ -4225,7 +4504,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
4225
4504
|
if (vc) {
|
|
4226
4505
|
const C = new Float32Array(nv * 3);
|
|
4227
4506
|
let q = 0;
|
|
4228
|
-
for (const e of
|
|
4507
|
+
for (const e of list2) {
|
|
4229
4508
|
const n = e.P.length / 3, cr = e.color;
|
|
4230
4509
|
for (let i = 0; i < n; i++, q++) {
|
|
4231
4510
|
C[q * 3] = cr.r;
|
|
@@ -4336,7 +4615,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
4336
4615
|
const x = u.ry ? [u.u - uw, u.u] : [u.u, u.u + uw], z = u.ry ? [u.v - ud, u.v] : [u.v, u.v + ud];
|
|
4337
4616
|
return [x[0], z[0], x[1], z[1]];
|
|
4338
4617
|
};
|
|
4339
|
-
const un0 = unitBox(un[0]),
|
|
4618
|
+
const un0 = unitBox(un[0]), color2 = P.corridor, hall = P.hall, el = P.elevator.rect, es = P.stairs.rect;
|
|
4340
4619
|
const sel = un[shared.ctx.pu] || un[0], selR = unitBox(sel);
|
|
4341
4620
|
const shell = (rc, y0, y1, thickness = 0.15) => {
|
|
4342
4621
|
const [a, b, c, d] = rc;
|
|
@@ -4356,10 +4635,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
4356
4635
|
bx("glass", rc[0] + 0.5, y0 + 0.9, u.ry ? rc[1] - 1e-3 : rc[3] + 1e-3, rc[2] - 0.5, y0 + 2, u.ry ? rc[1] + 1e-3 : rc[3] + 2e-3, 16777215);
|
|
4357
4636
|
}
|
|
4358
4637
|
}
|
|
4359
|
-
for (const rc of [
|
|
4638
|
+
for (const rc of [color2, hall]) {
|
|
4360
4639
|
bx("plaster", rc[0], y0 - 0.2, rc[1], rc[2], y0, rc[3], 12104874);
|
|
4361
4640
|
}
|
|
4362
|
-
shell([Math.min(
|
|
4641
|
+
shell([Math.min(color2[0], hall[0]), hall[1], color2[2], color2[3]], y0, y0 + pe - 0.2);
|
|
4363
4642
|
bx("metal", el[0] + 0.05, y0, el[1] + 0.05, el[2] - 0.05, y0 + pe, el[3] - 0.05, 8291466);
|
|
4364
4643
|
bx("building", es[0], y0, es[1], es[2], y0 + pe - 0.2, es[3], 13618114);
|
|
4365
4644
|
const ns = 16, rise = pe / ns, wl = es[2] - es[0] - 0.2;
|
|
@@ -4375,8 +4654,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
4375
4654
|
}
|
|
4376
4655
|
}
|
|
4377
4656
|
const ytop = N * pe - 0.2;
|
|
4378
|
-
bx("plaster", Math.min(hall[0] - 3,
|
|
4379
|
-
shared.ctx.limits = { x0: Math.min(hall[0] - 3,
|
|
4657
|
+
bx("plaster", Math.min(hall[0] - 3, color2[0]), ytop, Math.min(un[1] ? unitBox(un[1])[1] : 0, el[1]), Math.max(color2[2], un0[2]), ytop + 0.2, Math.max(un0[3], un[1] ? unitBox(un[1])[3] : 0), 11841704);
|
|
4658
|
+
shared.ctx.limits = { x0: Math.min(hall[0] - 3, color2[0]), z0: Math.min(el[1], un[1] ? unitBox(un[1])[1] : 0), x1: Math.max(color2[2], un0[2]), z1: Math.max(un0[3], un[1] ? unitBox(un[1])[3] : 0) };
|
|
4380
4659
|
}
|
|
4381
4660
|
Object.assign(K, { building });
|
|
4382
4661
|
}
|
|
@@ -4466,11 +4745,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
4466
4745
|
return api;
|
|
4467
4746
|
}
|
|
4468
4747
|
const PIPE_COLOR = 11897429;
|
|
4469
|
-
function pipe(a, b, diameter,
|
|
4748
|
+
function pipe(a, b, diameter, color2) {
|
|
4470
4749
|
const dx = b[0] - a[0], dy = b[1] - a[1], dz = b[2] - a[2], L = Math.hypot(dx, dy, dz);
|
|
4471
4750
|
if (L < 1e-3) return;
|
|
4472
4751
|
_q.setFromUnitVectors(_Y, _v3.set(dx / L, dy / L, dz / L));
|
|
4473
|
-
put("plain", "cyl", (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2, _q, diameter, L, diameter,
|
|
4752
|
+
put("plain", "cyl", (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2, _q, diameter, L, diameter, color2);
|
|
4474
4753
|
}
|
|
4475
4754
|
const _v3 = new THREE.Vector3();
|
|
4476
4755
|
function waterPipes() {
|
|
@@ -4515,7 +4794,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
4515
4794
|
shared.ctx.electricalInfo = null;
|
|
4516
4795
|
if (!E) return;
|
|
4517
4796
|
const R = shared.ctx.r, nA = R.floors.length, lotGroup = R.lot ? "lot" : "f0", concreteColor = 11973547, iron = 4869200, wireRun = 1842206, info = { pole: null, meter: null, panel: null, conduits: [], outlets: [], switches: [], circuits: E.circuits || [], exposed: !!E.exposed };
|
|
4518
|
-
const
|
|
4797
|
+
const en3 = E.serviceEntrance, KV = shared.ctx.iv ? shared.ctx.iv.plane : null;
|
|
4519
4798
|
const wireL = (a, b, r_ = 8e-3) => {
|
|
4520
4799
|
const L = Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
|
|
4521
4800
|
if (L < 1e-3) return;
|
|
@@ -4531,25 +4810,25 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
4531
4810
|
for (const dx of [-0.65, -0.2, 0.25, 0.7]) cylBase("plain", u + dx, h - 0.62, v, 0.025, 0.1, 13684680);
|
|
4532
4811
|
cursor.pc = null;
|
|
4533
4812
|
};
|
|
4534
|
-
if (
|
|
4535
|
-
const P =
|
|
4813
|
+
if (en3 && en3.pole) {
|
|
4814
|
+
const P = en3.pole;
|
|
4536
4815
|
if (!(KV && KV.serviceEntrance)) pole(P.u, P.v, P.h);
|
|
4537
4816
|
info.pole = { pos: [P.u, 0, P.v], h: P.h };
|
|
4538
4817
|
for (const k of [-1, 1]) pole(P.u + k * 22, P.v, P.h);
|
|
4539
4818
|
cursor.pc = pieceRecord("wiring:grid", "copper", null, { tags: ["wiring"] });
|
|
4540
4819
|
for (const dx of [-0.65, -0.2, 0.25, 0.7]) for (const k of [-1, 1]) wireL([P.u + dx, P.h - 0.5, P.v], [P.u + k * 22 + dx, P.h - 0.5, P.v], 7e-3);
|
|
4541
|
-
if (
|
|
4542
|
-
const r0 =
|
|
4820
|
+
if (en3.drop && en3.drop.length > 1 && !(KV && KV.serviceEntrance)) {
|
|
4821
|
+
const r0 = en3.drop[0], r1 = en3.drop[en3.drop.length - 1];
|
|
4543
4822
|
for (const dz of [0, 0.04]) wireL([r0[0], r0[2], r0[1]], [r1[0], r1[2], r1[1] + dz], 9e-3);
|
|
4544
4823
|
wireL([P.u - 0.2, P.h - 0.5, P.v], [r0[0], r0[2], r0[1]], 8e-3);
|
|
4545
4824
|
}
|
|
4546
4825
|
cursor.pc = null;
|
|
4547
|
-
if (
|
|
4548
|
-
const d0 =
|
|
4826
|
+
if (en3.descent && en3.descent.length > 1 && !(KV && KV.serviceEntrance)) {
|
|
4827
|
+
const d0 = en3.descent[0], d1 = en3.descent[en3.descent.length - 1];
|
|
4549
4828
|
cylBase("metal", d0[0], d1[2], d0[1], 0.02, d0[2] - d1[2], 9080466);
|
|
4550
4829
|
bx("metal", d0[0] - 0.05, d0[2] - 0.03, d0[1] - 0.05, d0[0] + 0.05, d0[2] + 0.08, d0[1] + 0.05, 8027780);
|
|
4551
4830
|
}
|
|
4552
|
-
const M =
|
|
4831
|
+
const M = en3.meter;
|
|
4553
4832
|
if (M) {
|
|
4554
4833
|
const hw = (M.w || 0.35) / 2, hd = (M.d || 0.2) / 2, hh = (M.h || 0.5) / 2, fr = M.side === "front" ? -1 : 1;
|
|
4555
4834
|
if (!(KV && KV.meter)) bx("plain", M.u - hw, M.y - hh, M.v - hd, M.u + hw, M.y + hh, M.v + hd, 14277597);
|
|
@@ -4567,9 +4846,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
4567
4846
|
const g0 = cursor.group, noDrawing = !!(KV && KV.picture);
|
|
4568
4847
|
cursor.group = "f" + Math.max(0, Math.min(nA - 1, Q.floor || 0));
|
|
4569
4848
|
const frontU = Q.frontU || 0, frontV = Q.frontV || 0, w = Q.w || 0.3, h = Q.h || 0.4, hw = w / 2, d = 0.05;
|
|
4570
|
-
const bq = (a0, y0_, a1, y1_, o0, o1, mat,
|
|
4571
|
-
if (frontV) bx(mat, Q.u + a0, Q.y + y0_, Q.v + (frontV > 0 ? o0 : -o1), Q.u + a1, Q.y + y1_, Q.v + (frontV > 0 ? o1 : -o0),
|
|
4572
|
-
else bx(mat, Q.u + (frontU > 0 ? o0 : -o1), Q.y + y0_, Q.v + a0, Q.u + (frontU > 0 ? o1 : -o0), Q.y + y1_, Q.v + a1,
|
|
4849
|
+
const bq = (a0, y0_, a1, y1_, o0, o1, mat, color2) => {
|
|
4850
|
+
if (frontV) bx(mat, Q.u + a0, Q.y + y0_, Q.v + (frontV > 0 ? o0 : -o1), Q.u + a1, Q.y + y1_, Q.v + (frontV > 0 ? o1 : -o0), color2);
|
|
4851
|
+
else bx(mat, Q.u + (frontU > 0 ? o0 : -o1), Q.y + y0_, Q.v + a0, Q.u + (frontU > 0 ? o1 : -o0), Q.y + y1_, Q.v + a1, color2);
|
|
4573
4852
|
};
|
|
4574
4853
|
if (!noDrawing) {
|
|
4575
4854
|
bq(-hw, -h / 2, hw, h / 2, -0.015, 0.06, "plain", 13619926);
|
|
@@ -4613,11 +4892,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
4613
4892
|
for (const t of E.switches || []) info.switches.push({ id: t.id, pos: [t.u, t.y, t.v], normal: [t.frontU || 0, 0, t.frontV || 0], room: t.room, floor: t.floor, controls: t.controls });
|
|
4614
4893
|
shared.ctx.electricalInfo = info;
|
|
4615
4894
|
}
|
|
4616
|
-
function pipe2(a, b, diameter,
|
|
4895
|
+
function pipe2(a, b, diameter, color2) {
|
|
4617
4896
|
const dx = b[0] - a[0], dy = b[1] - a[1], dz = b[2] - a[2], L = Math.hypot(dx, dy, dz);
|
|
4618
4897
|
if (L < 1e-3) return;
|
|
4619
4898
|
_q.setFromUnitVectors(_Y, _v3.set(dx / L, dy / L, dz / L));
|
|
4620
|
-
put("plain", "cyl", (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2, _q, diameter, L, diameter,
|
|
4899
|
+
put("plain", "cyl", (a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2, _q, diameter, L, diameter, color2);
|
|
4621
4900
|
}
|
|
4622
4901
|
Object.assign(K, { electricalStructure, pipe2 });
|
|
4623
4902
|
}
|
|
@@ -4627,7 +4906,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
4627
4906
|
const { Y0, bx, cursor, sideOf } = K;
|
|
4628
4907
|
const sh = (...a) => K.sh(...a);
|
|
4629
4908
|
function baseboardAndSidewalk() {
|
|
4630
|
-
const R = shared.ctx.r, W = 0.6, t = 0.012, ht = 0.35,
|
|
4909
|
+
const R = shared.ctx.r, W = 0.6, t = 0.012, ht = 0.35, color2 = sh(shared.ctx.colors.facade != null ? shared.ctx.colors.facade : 14209216, 0.62), y0 = Y0(0), cal = 13947078;
|
|
4631
4910
|
const ws = R.walls.filter((w) => w.floor === 0 && w.type === "wall").map((w) => {
|
|
4632
4911
|
const au = w.axis === "u";
|
|
4633
4912
|
return { w, au, L: au ? w.v0 : w.u0, a: Math.min(au ? w.u0 : w.v0, au ? w.u1 : w.v1), b: Math.max(au ? w.u0 : w.v0, au ? w.u1 : w.v1), th: w.thickness || 0.15 };
|
|
@@ -4653,7 +4932,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
4653
4932
|
if (A.au) bx(mat, s0, y1, lo, s1, y2, hi, c);
|
|
4654
4933
|
else bx(mat, lo, y1, s0, hi, y2, s1, c);
|
|
4655
4934
|
};
|
|
4656
|
-
strip(t, y0, y0 + ht, 0, t, "plaster",
|
|
4935
|
+
strip(t, y0, y0 + ht, 0, t, "plaster", color2);
|
|
4657
4936
|
strip(W, y0, y0 + 0.045, 0, W, "sidewalk", cal);
|
|
4658
4937
|
}
|
|
4659
4938
|
}
|
|
@@ -4702,7 +4981,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
4702
4981
|
tilt = Math.atan2(yA - yB, d);
|
|
4703
4982
|
yc = yC + 0.13;
|
|
4704
4983
|
}
|
|
4705
|
-
const co = Math.cos(tilt), si = Math.sin(tilt), pb = (lx, ly, lz, sx, sy, sz, mat,
|
|
4984
|
+
const co = Math.cos(tilt), si = Math.sin(tilt), pb = (lx, ly, lz, sx, sy, sz, mat, color2) => boxC(mat, p.u + lx, yc + ly * co - lz * si, p.v + ly * si + lz * co, sx, sy, sz, color2, tilt, 0, 0), L = p.length;
|
|
4706
4985
|
pb(0, 0, 0, p.w, 0.04, L, "metal", silver);
|
|
4707
4986
|
pb(0, 0.0205, 0, p.w - 0.07, 6e-3, L - 0.07, "plain", blue);
|
|
4708
4987
|
for (let k = 1; k < 4; k++) pb(-hw + 0.035 + k * (p.w - 0.07) / 4, 0.0245, 0, 6e-3, 3e-3, L - 0.07, "metal", line);
|
|
@@ -4794,39 +5073,39 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
4794
5073
|
return [M.x + lx * c + lz * s, M.z - lx * s + lz * c];
|
|
4795
5074
|
};
|
|
4796
5075
|
return {
|
|
4797
|
-
box(M, mat, x, y, z, w, h, d,
|
|
5076
|
+
box(M, mat, x, y, z, w, h, d, color2, ry = 0, rx = 0, rz = 0) {
|
|
4798
5077
|
const [px, pz] = loc(M, x, z);
|
|
4799
|
-
boxC(mm(mat), px, M.base + y + h / 2, pz, w, h, d,
|
|
5078
|
+
boxC(mm(mat), px, M.base + y + h / 2, pz, w, h, d, color2, rx, M.ry + ry, rz);
|
|
4800
5079
|
},
|
|
4801
|
-
cylinder(M, mat, x, y, z, r, h,
|
|
5080
|
+
cylinder(M, mat, x, y, z, r, h, color2, rx = 0, rz = 0, seg) {
|
|
4802
5081
|
const [px, pz] = loc(M, x, z);
|
|
4803
5082
|
_q.setFromEuler(_e.set(rx || 0, M.ry, rz || 0, "YXZ"));
|
|
4804
|
-
put(mm(mat), seg || "cyl", px, M.base + y + (rx || rz ? 0 : h / 2), pz, _q, r * 2, h, r * 2,
|
|
5083
|
+
put(mm(mat), seg || "cyl", px, M.base + y + (rx || rz ? 0 : h / 2), pz, _q, r * 2, h, r * 2, color2);
|
|
4805
5084
|
},
|
|
4806
|
-
leaf(M, x, y, z, w, h,
|
|
5085
|
+
leaf(M, x, y, z, w, h, color2, ry = 0, rx = 0) {
|
|
4807
5086
|
const [px, pz] = loc(M, x, z), a = M.ry + (ry || 0), ca = Math.cos(a), sa = Math.sin(a), t1 = (rx || 0) * 0.8, t2 = (rx || 0) * 1.5, y0 = M.base + y;
|
|
4808
5087
|
const P = (lx, ly, lz) => [px + lx * ca + lz * sa, y0 + ly, pz - lx * sa + lz * ca];
|
|
4809
5088
|
const my = Math.cos(t1) * h * 0.5, mz = Math.sin(t1) * h * 0.5, ty = my + Math.cos(t2) * h * 0.5, tz = mz + Math.sin(t2) * h * 0.5, f = w * 0.5, dn = f * 0.32;
|
|
4810
5089
|
const B = P(0, 0, 0), Mi = P(0, my + 4e-3, mz), T2 = P(0, ty, tz), L = P(-f, my - dn, mz - dn * 0.3), R = P(f, my - dn, mz - dn * 0.3);
|
|
4811
|
-
polyFace("plant", [B, L, T2, Mi],
|
|
4812
|
-
polyFace("plant", [B, Mi, T2, R], sh(
|
|
5090
|
+
polyFace("plant", [B, L, T2, Mi], color2, [0, 1, 0]);
|
|
5091
|
+
polyFace("plant", [B, Mi, T2, R], sh(color2, 0.92), [0, 1, 0]);
|
|
4813
5092
|
},
|
|
4814
|
-
plane(M, mat, x, y, z, w, h,
|
|
5093
|
+
plane(M, mat, x, y, z, w, h, color2, ry = 0, rx = 0, rz = 0, uv) {
|
|
4815
5094
|
const [px, pz] = loc(M, x, z);
|
|
4816
5095
|
_q.setFromEuler(_e.set(rx || 0, M.ry + (ry || 0), rz || 0, "YXZ"));
|
|
4817
5096
|
if (uv && mat === "atlas_floor") {
|
|
4818
5097
|
const col = Math.floor(uv.u0 * 4 + 1e-6), lin = uv.v0 < 0.5 ? 1 : 0, cell = col + 4 * lin, h0 = _h2(Math.round(px * 8), Math.round(pz * 8)), type = cell === 5 ? "dirt" : cell === 0 || cell === 1 ? "lawn" : null;
|
|
4819
5098
|
if (type === "dirt") {
|
|
4820
|
-
put("dirt", "plane", px, M.base + y, pz, _q, w, h, 1, sh(
|
|
5099
|
+
put("dirt", "plane", px, M.base + y, pz, _q, w, h, 1, sh(color2, 1 / 0.965));
|
|
4821
5100
|
return;
|
|
4822
5101
|
}
|
|
4823
5102
|
if (type) uv = { u0: uv.u0, u1: uv.u1, v0: uv.v0, v1: uv.v1, rot: h0 * 4 | 0, fx: h0 > 0.5 ? 1 : 0, vc: (wx, wz) => macroGround(wx, wz, type) };
|
|
4824
5103
|
}
|
|
4825
|
-
put(mm(mat), "plane", px, M.base + y, pz, _q, w, h, 1,
|
|
5104
|
+
put(mm(mat), "plane", px, M.base + y, pz, _q, w, h, 1, color2, uv);
|
|
4826
5105
|
},
|
|
4827
|
-
light(M, x, y, z,
|
|
5106
|
+
light(M, x, y, z, color2, range2, type, ex) {
|
|
4828
5107
|
const [px, pz] = loc(M, x, z);
|
|
4829
|
-
LIGHTS.push(Object.assign({ x: px, y: M.base + y, z: pz, color, range, type, floor: M.floor, group: cursor.group, base: M.base, room: M.room, id: M.lampId }, ex || null));
|
|
5108
|
+
LIGHTS.push(Object.assign({ x: px, y: M.base + y, z: pz, color: color2, range: range2, type, floor: M.floor, group: cursor.group, base: M.base, room: M.room, id: M.lampId }, ex || null));
|
|
4830
5109
|
}
|
|
4831
5110
|
};
|
|
4832
5111
|
}
|
|
@@ -4841,7 +5120,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
4841
5120
|
}
|
|
4842
5121
|
function kk(M, A) {
|
|
4843
5122
|
const y0 = M.y || 0;
|
|
4844
|
-
return { b: (mat, x, y, z, w, h, d,
|
|
5123
|
+
return { b: (mat, x, y, z, w, h, d, color2, ry, rx, rz) => A.box(M, mat, x, y0 + y, z, w, h, d, color2, ry || 0, rx || 0, rz || 0), c: (mat, x, y, z, r, h, color2, rx, rz, seg) => A.cylinder(M, mat, x, y0 + y, z, r, h, color2, rx || 0, rz || 0, seg), rnd: rngOf(M), wood: paletteColor(M, "wood", 8016948), met: paletteColor(M, "metal", 10133154) };
|
|
4845
5124
|
}
|
|
4846
5125
|
const PE = Math.PI / 2;
|
|
4847
5126
|
Object.assign(K, { MATERIAL_MAP: MATERIAL_MAP2, mm, LIGHTS, makeApi, sh, paletteColor, rngOf, kk, PE });
|
|
@@ -5016,13 +5295,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
5016
5295
|
lb("metal", 0, h - 0.23, d / 2 + 0.04, w - 0.12, 0.02, 0.02, 10526880);
|
|
5017
5296
|
},
|
|
5018
5297
|
kitchen_cabinet(M, A, o = {}) {
|
|
5019
|
-
const { b: lb, c: lc } = kk(M, A), w = M.w, d = M.d, h = M.h || 0.95,
|
|
5020
|
-
lb("plain", 0, 0.08, -0.02, w, h - 0.15, d - 0.05,
|
|
5298
|
+
const { b: lb, c: lc } = kk(M, A), w = M.w, d = M.d, h = M.h || 0.95, color2 = paletteColor(M, "wall_kitchen", 15262420), wood = paletteColor(M, "wood", 11571296);
|
|
5299
|
+
lb("plain", 0, 0.08, -0.02, w, h - 0.15, d - 0.05, color2);
|
|
5021
5300
|
lb("plain", 0, 0, 0, w - 0.04, 0.08, d - 0.12, 2763306);
|
|
5022
5301
|
const nd = Math.max(2, Math.round(w / 0.55));
|
|
5023
5302
|
for (let k = 0; k < nd; k++) {
|
|
5024
5303
|
const u = -w / 2 + (k + 0.5) * w / nd;
|
|
5025
|
-
lb("plain", u, 0.12, d / 2 - 0.02, w / nd - 0.03, h - 0.28, 0.02, sh(
|
|
5304
|
+
lb("plain", u, 0.12, d / 2 - 0.02, w / nd - 0.03, h - 0.28, 0.02, sh(color2, 1.06));
|
|
5026
5305
|
lb("metal", u + (k % 2 ? -0.2 : 0.2) * (w / nd), h * 0.62, d / 2, 0.012, 0.12, 0.015, 9079434);
|
|
5027
5306
|
}
|
|
5028
5307
|
if (o.noBasin) lb("plain", 0, h - 0.07, 0, w + 0.03, 0.035, d + 0.03, 4868164);
|
|
@@ -5044,13 +5323,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
5044
5323
|
}
|
|
5045
5324
|
if (!o.noOverhead && (M.overhead === true || M.overhead == null && w >= 1.2)) {
|
|
5046
5325
|
const ya = 1.55;
|
|
5047
|
-
lb("plain", 0, ya, -d / 2 + 0.18, w, 0.6, 0.35,
|
|
5048
|
-
for (let k = 0; k < 3; k++) lb("plain", -w / 2 + (k + 0.5) * w / 3, ya + 0.02, -d / 2 + 0.36, w / 3 - 0.03, 0.56, 0.015, sh(
|
|
5326
|
+
lb("plain", 0, ya, -d / 2 + 0.18, w, 0.6, 0.35, color2);
|
|
5327
|
+
for (let k = 0; k < 3; k++) lb("plain", -w / 2 + (k + 0.5) * w / 3, ya + 0.02, -d / 2 + 0.36, w / 3 - 0.03, 0.56, 0.015, sh(color2, 1.06));
|
|
5049
5328
|
}
|
|
5050
5329
|
},
|
|
5051
5330
|
counter(M, A, o = {}) {
|
|
5052
|
-
const { b: lb } = kk(M, A), w = M.w, d = M.d, h = M.h,
|
|
5053
|
-
lb("plain", 0, 0, 0, w, h * (o.glass ? 0.45 : 1) - 0.04, d,
|
|
5331
|
+
const { b: lb } = kk(M, A), w = M.w, d = M.d, h = M.h, color2 = o.color != null ? o.color : paletteColor(M, "wood", 9071176), top = o.top != null ? o.top : 14210252;
|
|
5332
|
+
lb("plain", 0, 0, 0, w, h * (o.glass ? 0.45 : 1) - 0.04, d, color2);
|
|
5054
5333
|
lb("plain", 0, h * (o.glass ? 0.45 : 1) - 0.04, 0, w + 0.03, 0.04, d + 0.03, top);
|
|
5055
5334
|
if (o.glass) {
|
|
5056
5335
|
lb("glass", 0, h * 0.45, 0, w - 0.04, h * 0.55, d - 0.04, 16777215);
|
|
@@ -5320,9 +5599,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
5320
5599
|
lb("glass", w * 0.28, 1, d / 2 + 0.01, 0.8, 0.9, 0.02, 16777215);
|
|
5321
5600
|
},
|
|
5322
5601
|
motorcycle(M, A) {
|
|
5323
|
-
const { b: lb, c: lc } = kk(M, A), d = M.d,
|
|
5602
|
+
const { b: lb, c: lc } = kk(M, A), d = M.d, color2 = M.color != null ? M.color : 11024948;
|
|
5324
5603
|
for (const s of [-1, 1]) lc("plain", 0, 0.3, s * d * 0.34, 0.3, 0.12, 1710618, 0, PE);
|
|
5325
|
-
lb("plain", 0, 0.35, 0, 0.18, 0.28, d * 0.5,
|
|
5604
|
+
lb("plain", 0, 0.35, 0, 0.18, 0.28, d * 0.5, color2);
|
|
5326
5605
|
lb("plain", 0, 0.62, -0.1, 0.22, 0.1, 0.6, 2236962);
|
|
5327
5606
|
lb("metal", 0, 0.7, d * 0.28, 0.5, 0.04, 0.04, 11580600);
|
|
5328
5607
|
},
|
|
@@ -5667,13 +5946,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
5667
5946
|
};
|
|
5668
5947
|
FURNITURE.curtain = function(M, A) {
|
|
5669
5948
|
const w = M.w || 1.6, h = M.h || 2.3, y = M.y != null && M.y > 0 ? M.y : 0.1, K2 = kit2(M, A, 0), top = y + h;
|
|
5670
|
-
const rnd = rngString(SEED() + "|" + seedKey(M.seed) + "|cort"),
|
|
5949
|
+
const rnd = rngString(SEED() + "|" + seedKey(M.seed) + "|cort"), color2 = M.color != null ? M.color : [14208436, 10465470, 12953740, 14736592][rnd() * 4 | 0], gold = M.palette && M.palette.metal != null ? M.palette.metal : 5918792;
|
|
5671
5950
|
K2.t("metal", [-w / 2 - 0.05, top + 0.02, 0], [w / 2 + 0.05, top + 0.02, 0], 0.012, gold);
|
|
5672
5951
|
for (const s of [-1, 1]) K2.e("metal", s * (w / 2 + 0.07), top + 0.02, 0, 0.022, 0.045, gold);
|
|
5673
5952
|
const pw = w / 2 + 0.03, n = Math.max(8, Math.round(pw / 0.075));
|
|
5674
5953
|
for (const s of [-1, 1]) for (let i = 0; i < n; i++) {
|
|
5675
5954
|
const ux = s * (i + 0.5) * pw / n;
|
|
5676
|
-
K2.b("fabric", ux, y, i % 2 ? 0.03 : -0.012, pw / n * 1.12, h - 0.04, 0.018, i % 2 ? sh(
|
|
5955
|
+
K2.b("fabric", ux, y, i % 2 ? 0.03 : -0.012, pw / n * 1.12, h - 0.04, 0.018, i % 2 ? sh(color2, 0.88) : color2);
|
|
5677
5956
|
}
|
|
5678
5957
|
for (const s of [-1, 1]) for (let i = 0; i < n; i += 2) K2.e("metal", s * (i + 0.5) * pw / n, top + 0.012, 0, 0.012, 0.024, gold);
|
|
5679
5958
|
};
|
|
@@ -5696,15 +5975,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
5696
5975
|
}
|
|
5697
5976
|
}
|
|
5698
5977
|
}
|
|
5699
|
-
function potModel(K2, x, y, z, r, h,
|
|
5978
|
+
function potModel(K2, x, y, z, r, h, color2, soil = true) {
|
|
5700
5979
|
const rimR = r * 1.1;
|
|
5701
|
-
K2.c("plain", x, y, z, r * 0.62, h * 0.55, sh(
|
|
5702
|
-
K2.c("plain", x, y + h * 0.5, z, r * 0.84, h * 0.34,
|
|
5703
|
-
K2.c("plain", x, y + h * 0.82, z, rimR, h * 0.18, sh(
|
|
5980
|
+
K2.c("plain", x, y, z, r * 0.62, h * 0.55, sh(color2, 0.92));
|
|
5981
|
+
K2.c("plain", x, y + h * 0.5, z, r * 0.84, h * 0.34, color2);
|
|
5982
|
+
K2.c("plain", x, y + h * 0.82, z, rimR, h * 0.18, sh(color2, 1.08));
|
|
5704
5983
|
if (soil) K2.c("plain", x, y + h * 0.995, z, r * 0.92, h * 0.012, 3811870);
|
|
5705
5984
|
return y + h;
|
|
5706
5985
|
}
|
|
5707
|
-
function arcLeaf(K2, bx_, by, bz, az, len, elev, drop, wmax,
|
|
5986
|
+
function arcLeaf(K2, bx_, by, bz, az, len, elev, drop, wmax, color2, serrated, nSeg = 6) {
|
|
5708
5987
|
const c = Math.cos(az), s = Math.sin(az), pts = [];
|
|
5709
5988
|
for (let i = 0; i <= nSeg; i++) {
|
|
5710
5989
|
const f = i / nSeg, d = f * len;
|
|
@@ -5713,14 +5992,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
5713
5992
|
const px = -s, pz = c;
|
|
5714
5993
|
for (let i = 0; i < nSeg; i++) {
|
|
5715
5994
|
const f0 = i / nSeg, f1 = (i + 1) / nSeg, w0 = wmax * Math.sin(Math.PI * Math.min(1, f0 * 0.85 + 0.12)) * (serrated && i % 2 ? 0.7 : 1), w1 = wmax * Math.sin(Math.PI * Math.min(1, f1 * 0.85 + 0.12)) * (serrated && i % 2 ? 1 : 0.7), dn = 0.35;
|
|
5716
|
-
for (const sd of [-1, 1]) K2.polyFace("plant", [pts[i], pts[i + 1], [pts[i + 1][0] + px * sd * w1, pts[i + 1][1] - w1 * dn, pts[i + 1][2] + pz * sd * w1], [pts[i][0] + px * sd * w0, pts[i][1] - w0 * dn, pts[i][2] + pz * sd * w0]], i % 2 ? sh(
|
|
5995
|
+
for (const sd of [-1, 1]) K2.polyFace("plant", [pts[i], pts[i + 1], [pts[i + 1][0] + px * sd * w1, pts[i + 1][1] - w1 * dn, pts[i + 1][2] + pz * sd * w1], [pts[i][0] + px * sd * w0, pts[i][1] - w0 * dn, pts[i][2] + pz * sd * w0]], i % 2 ? sh(color2, 0.9) : color2, [0, 1, 0]);
|
|
5717
5996
|
}
|
|
5718
5997
|
return pts[nSeg];
|
|
5719
5998
|
}
|
|
5720
|
-
function tuft(K2, x, y, z, r, n,
|
|
5999
|
+
function tuft(K2, x, y, z, r, n, color2, rnd) {
|
|
5721
6000
|
for (let i = 0; i < n; i++) {
|
|
5722
6001
|
const a = rnd() * 6.283, d0 = rnd() * r * 0.35, L = r * (0.8 + rnd() * 1.1), bw = 0.012 + rnd() * 8e-3, lean = 0.25 + rnd() * 0.5, c = Math.cos(a), s = Math.sin(a), px = -s, pz = c, x0 = x + c * d0, z0 = z + s * d0;
|
|
5723
|
-
const m = [x0 + c * lean * L * 0.35, y + L * 0.55, z0 + s * lean * L * 0.35], t = [x0 + c * lean * L, y + L * (0.95 - lean * 0.2), z0 + s * lean * L], vc = sh(
|
|
6002
|
+
const m = [x0 + c * lean * L * 0.35, y + L * 0.55, z0 + s * lean * L * 0.35], t = [x0 + c * lean * L, y + L * (0.95 - lean * 0.2), z0 + s * lean * L], vc = sh(color2, 0.78 + rnd() * 0.4);
|
|
5724
6003
|
K2.polyFace("plant", [[x0 - px * bw, y, z0 - pz * bw], [x0 + px * bw, y, z0 + pz * bw], [m[0] + px * bw * 0.6, m[1], m[2] + pz * bw * 0.6], t, [m[0] - px * bw * 0.6, m[1], m[2] - pz * bw * 0.6]], vc, [0, 1, 0]);
|
|
5725
6004
|
}
|
|
5726
6005
|
}
|
|
@@ -5811,31 +6090,31 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
5811
6090
|
const seedKey = (id) => K.seedKey(id);
|
|
5812
6091
|
const { FURNITURE, SEED, STYLE, kit2, rngString, sh, wallTap } = K;
|
|
5813
6092
|
FURNITURE.laundry_tub = function(M, A) {
|
|
5814
|
-
const K2 = kit2(M, A), w = M.w || 0.6, d = M.d || 0.55, H = M.h || 0.9, structure = STYLE(), upper = structure === "budget",
|
|
6093
|
+
const K2 = kit2(M, A), w = M.w || 0.6, d = M.d || 0.55, H = M.h || 0.9, structure = STYLE(), upper = structure === "budget", color2 = upper ? 11841700 : 15790058, int2 = upper ? 10134694 : 14870248, rim = sh(color2, 1.06);
|
|
5815
6094
|
const yb = H - 0.36, t = 0.04, rc = 0.055, zw = -d / 2;
|
|
5816
|
-
for (const sx of [-1, 1]) for (const sz of [-1, 1]) K2.c("plain", sx * (w / 2 - rc), yb, sz * (d / 2 - rc), rc, 0.36,
|
|
5817
|
-
K2.b("plain", 0, yb, d / 2 - t / 2, w - 2 * rc + 0.01, 0.36, t,
|
|
5818
|
-
K2.b("plain", 0, yb, -d / 2 + t / 2, w - 2 * rc + 0.01, 0.36, t,
|
|
5819
|
-
K2.b("plain", -w / 2 + t / 2, yb, 0, t, 0.36, d - 2 * rc + 0.01,
|
|
5820
|
-
K2.b("plain", w / 2 - t / 2, yb, 0, t, 0.36, d - 2 * rc + 0.01,
|
|
5821
|
-
K2.b("plain", 0, yb, 0, w - 2 * t, 0.06, d - 2 * t,
|
|
6095
|
+
for (const sx of [-1, 1]) for (const sz of [-1, 1]) K2.c("plain", sx * (w / 2 - rc), yb, sz * (d / 2 - rc), rc, 0.36, color2);
|
|
6096
|
+
K2.b("plain", 0, yb, d / 2 - t / 2, w - 2 * rc + 0.01, 0.36, t, color2);
|
|
6097
|
+
K2.b("plain", 0, yb, -d / 2 + t / 2, w - 2 * rc + 0.01, 0.36, t, color2);
|
|
6098
|
+
K2.b("plain", -w / 2 + t / 2, yb, 0, t, 0.36, d - 2 * rc + 0.01, color2);
|
|
6099
|
+
K2.b("plain", w / 2 - t / 2, yb, 0, t, 0.36, d - 2 * rc + 0.01, color2);
|
|
6100
|
+
K2.b("plain", 0, yb, 0, w - 2 * t, 0.06, d - 2 * t, int2);
|
|
5822
6101
|
for (const sx of [-1, 1]) for (const sz of [-1, 1]) K2.c("plain", sx * (w / 2 - rc), H - 4e-3, sz * (d / 2 - rc), rc + 8e-3, 0.012, rim);
|
|
5823
6102
|
K2.b("plain", 0, H - 4e-3, d / 2 - 0.011, w - 2 * rc, 0.012, 0.022, rim);
|
|
5824
6103
|
K2.b("plain", 0, H - 4e-3, -d / 2 + 0.011, w - 2 * rc, 0.012, 0.022, rim);
|
|
5825
6104
|
K2.b("plain", -w / 2 + 0.011, H - 4e-3, 0, 0.022, 0.012, d - 2 * rc, rim);
|
|
5826
6105
|
K2.b("plain", w / 2 - 0.011, H - 4e-3, 0, 0.022, 0.012, d - 2 * rc, rim);
|
|
5827
6106
|
const tw = Math.min(0.2, w * 0.34), tx = -w / 2 + t + tw / 2 + 0.01, zt1 = d / 2 - t - 0.01, zt0 = -d / 2 + t + 0.08, ytop = H - 0.03, ybot = yb + 0.14, L = Math.hypot(zt1 - zt0, ytop - ybot), al = Math.atan2(ytop - ybot, zt1 - zt0);
|
|
5828
|
-
K2.b("plain", tx, (ytop + ybot) / 2 - 0.015, (zt0 + zt1) / 2, tw, 0.03, L, sh(
|
|
6107
|
+
K2.b("plain", tx, (ytop + ybot) / 2 - 0.015, (zt0 + zt1) / 2, tw, 0.03, L, sh(color2, 0.96), 0, -al, 0);
|
|
5829
6108
|
const nr = 7;
|
|
5830
6109
|
for (let i = 0; i < nr; i++) {
|
|
5831
6110
|
const f = (i + 0.5) / nr, zz = zt0 + (zt1 - zt0) * f, yy = ybot + (ytop - ybot) * f;
|
|
5832
|
-
K2.b("plain", tx, yy + 3e-3, zz, tw - 0.02, 0.014, 0.018, sh(
|
|
6111
|
+
K2.b("plain", tx, yy + 3e-3, zz, tw - 0.02, 0.014, 0.018, sh(color2, 0.88), 0, -al, 0);
|
|
5833
6112
|
}
|
|
5834
6113
|
K2.c("metal", 0.1, yb + 0.06, 0, 0.034, 8e-3, 11580600);
|
|
5835
6114
|
K2.c("plain", 0.1, yb + 0.068, 0, 0.026, 0.01, 3817026);
|
|
5836
6115
|
if (upper) {
|
|
5837
|
-
for (const sx of [-1, 1]) K2.b("plain", sx * (w / 2 - 0.035), 0, 0, 0.07, yb, d - 0.05, sh(
|
|
5838
|
-
K2.b("plain", 0, yb - 0.04, 0, w - 0.1, 0.04, d - 0.06, sh(
|
|
6116
|
+
for (const sx of [-1, 1]) K2.b("plain", sx * (w / 2 - 0.035), 0, 0, 0.07, yb, d - 0.05, sh(color2, 0.94));
|
|
6117
|
+
K2.b("plain", 0, yb - 0.04, 0, w - 0.1, 0.04, d - 0.06, sh(color2, 0.9));
|
|
5839
6118
|
} else for (const sx of [-1, 1]) for (const sz of [-1, 1]) {
|
|
5840
6119
|
K2.c("metal", sx * (w / 2 - 0.07), 0, sz * (d / 2 - 0.07), 0.022, yb, 11843772);
|
|
5841
6120
|
K2.c("metal", sx * (w / 2 - 0.07), 0, sz * (d / 2 - 0.07), 0.03, 0.012, 6975090);
|
|
@@ -5843,30 +6122,30 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
5843
6122
|
wallTap(K2, 0, H + 0.14, zw + 0, 1, yb + 0.06, { laundry_tub: true });
|
|
5844
6123
|
};
|
|
5845
6124
|
const CLOTHES_COLORS = [14209208, 4876938, 12077114, 15262936, 6982234, 14856266, 9067146, 3099242, 13925002, 8038072];
|
|
5846
|
-
function strip(K2, rows, zc, rot,
|
|
6125
|
+
function strip(K2, rows, zc, rot, color2, cx) {
|
|
5847
6126
|
const c = Math.cos(rot), s = Math.sin(rot), P = (x, y) => [cx + (x - cx) * c, y, zc + (x - cx) * s];
|
|
5848
6127
|
for (let i = 0; i < rows.length - 1; i++) {
|
|
5849
6128
|
const a = rows[i], b = rows[i + 1];
|
|
5850
|
-
K2.polyFace("clothes", [P(a[1], a[0]), P(a[2], a[0]), P(b[2], b[0]), P(b[1], b[0])], i % 2 ? sh(
|
|
6129
|
+
K2.polyFace("clothes", [P(a[1], a[0]), P(a[2], a[0]), P(b[2], b[0]), P(b[1], b[0])], i % 2 ? sh(color2, 0.96) : color2, [0, 0, 1]);
|
|
5851
6130
|
}
|
|
5852
6131
|
}
|
|
5853
|
-
function garment(K2, type, cx, ly, zc, rot,
|
|
6132
|
+
function garment(K2, type, cx, ly, zc, rot, color2, rnd) {
|
|
5854
6133
|
const sh0 = (rows, dx = 0) => rows.map((r) => [ly + r[0], cx + dx + r[1], cx + dx + r[2]]);
|
|
5855
|
-
if (type === "shirt") strip(K2, sh0([[0, -0.13, 0.13], [-0.03, -0.27, 0.27], [-0.15, -0.3, 0.3], [-0.2, -0.2, 0.2], [-0.62, -0.2, 0.2], [-0.63, -0.2, 0.2]]), zc, rot,
|
|
6134
|
+
if (type === "shirt") strip(K2, sh0([[0, -0.13, 0.13], [-0.03, -0.27, 0.27], [-0.15, -0.3, 0.3], [-0.2, -0.2, 0.2], [-0.62, -0.2, 0.2], [-0.63, -0.2, 0.2]]), zc, rot, color2, cx);
|
|
5856
6135
|
else if (type === "trousers") {
|
|
5857
|
-
strip(K2, sh0([[0, -0.19, -0.01], [-0.4, -0.18, -0.02], [-0.78, -0.16, -0.03], [-0.79, -0.16, -0.03]]), zc, rot,
|
|
5858
|
-
strip(K2, sh0([[0, 0.01, 0.19], [-0.4, 0.02, 0.18], [-0.78, 0.03, 0.16], [-0.79, 0.03, 0.16]]), zc, rot, sh(
|
|
6136
|
+
strip(K2, sh0([[0, -0.19, -0.01], [-0.4, -0.18, -0.02], [-0.78, -0.16, -0.03], [-0.79, -0.16, -0.03]]), zc, rot, color2, cx);
|
|
6137
|
+
strip(K2, sh0([[0, 0.01, 0.19], [-0.4, 0.02, 0.18], [-0.78, 0.03, 0.16], [-0.79, 0.03, 0.16]]), zc, rot, sh(color2, 0.95), cx);
|
|
5859
6138
|
} else if (type === "shorts") {
|
|
5860
|
-
strip(K2, sh0([[0, -0.2, -0.01], [-0.3, -0.2, -0.02], [-0.31, -0.2, -0.02]]), zc, rot,
|
|
5861
|
-
strip(K2, sh0([[0, 0.01, 0.2], [-0.3, 0.02, 0.2], [-0.31, 0.02, 0.2]]), zc, rot, sh(
|
|
6139
|
+
strip(K2, sh0([[0, -0.2, -0.01], [-0.3, -0.2, -0.02], [-0.31, -0.2, -0.02]]), zc, rot, color2, cx);
|
|
6140
|
+
strip(K2, sh0([[0, 0.01, 0.2], [-0.3, 0.02, 0.2], [-0.31, 0.02, 0.2]]), zc, rot, sh(color2, 0.95), cx);
|
|
5862
6141
|
} else if (type === "towel") {
|
|
5863
|
-
strip(K2, sh0([[0, -0.32, 0.32], [-0.2, -0.32, 0.32], [-0.22, -0.32, 0.32], [-0.5, -0.32, 0.32], [-0.9, -0.32, 0.32], [-0.91, -0.32, 0.32]]), zc, rot,
|
|
5864
|
-
strip(K2, sh0([[-0.22, -0.32, 0.32], [-0.3, -0.32, 0.32]]), zc, rot, sh(
|
|
5865
|
-
} else if (type === "sheet") strip(K2, sh0([[0, -0.5, 0.5], [-0.35, -0.5, 0.5], [-0.7, -0.5, 0.5], [-1.05, -0.5, 0.5], [-1.06, -0.5, 0.5]]), zc, rot,
|
|
5866
|
-
else if (type === "dress") strip(K2, sh0([[0, -0.14, 0.14], [-0.06, -0.2, 0.2], [-0.3, -0.16, 0.16], [-0.62, -0.28, 0.28], [-0.63, -0.28, 0.28]]), zc, rot,
|
|
6142
|
+
strip(K2, sh0([[0, -0.32, 0.32], [-0.2, -0.32, 0.32], [-0.22, -0.32, 0.32], [-0.5, -0.32, 0.32], [-0.9, -0.32, 0.32], [-0.91, -0.32, 0.32]]), zc, rot, color2, cx);
|
|
6143
|
+
strip(K2, sh0([[-0.22, -0.32, 0.32], [-0.3, -0.32, 0.32]]), zc, rot, sh(color2, 1.25), cx);
|
|
6144
|
+
} else if (type === "sheet") strip(K2, sh0([[0, -0.5, 0.5], [-0.35, -0.5, 0.5], [-0.7, -0.5, 0.5], [-1.05, -0.5, 0.5], [-1.06, -0.5, 0.5]]), zc, rot, color2, cx);
|
|
6145
|
+
else if (type === "dress") strip(K2, sh0([[0, -0.14, 0.14], [-0.06, -0.2, 0.2], [-0.3, -0.16, 0.16], [-0.62, -0.28, 0.28], [-0.63, -0.28, 0.28]]), zc, rot, color2, cx);
|
|
5867
6146
|
else {
|
|
5868
|
-
strip(K2, sh0([[0, -0.05, 0.05], [-0.14, -0.05, 0.05], [-0.15, -0.05, 0.05]], -0.06), zc, rot,
|
|
5869
|
-
strip(K2, sh0([[0, -0.05, 0.05], [-0.14, -0.05, 0.05], [-0.15, -0.05, 0.05]], 0.06), zc, rot, sh(
|
|
6147
|
+
strip(K2, sh0([[0, -0.05, 0.05], [-0.14, -0.05, 0.05], [-0.15, -0.05, 0.05]], -0.06), zc, rot, color2, cx);
|
|
6148
|
+
strip(K2, sh0([[0, -0.05, 0.05], [-0.14, -0.05, 0.05], [-0.15, -0.05, 0.05]], 0.06), zc, rot, sh(color2, 0.9), cx);
|
|
5870
6149
|
}
|
|
5871
6150
|
K2.b("plain", cx - 0.05, ly - 0.02, zc, 0.018, 0.05, 0.016, 15261896);
|
|
5872
6151
|
K2.b("plain", cx + 0.05, ly - 0.02, zc, 0.018, 0.05, 0.016, 13125690);
|
|
@@ -5900,7 +6179,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
5900
6179
|
(shared.ctx.clotheslines || (shared.ctx.clotheslines = [])).push(M.seed);
|
|
5901
6180
|
};
|
|
5902
6181
|
FURNITURE.water_tank = function(M, A) {
|
|
5903
|
-
const K2 = kit2(M, A), w = M.w || 1, d = M.d || 1, onGround = !M.onSlab && (M.y || 0) < 0.5,
|
|
6182
|
+
const K2 = kit2(M, A), w = M.w || 1, d = M.d || 1, onGround = !M.onSlab && (M.y || 0) < 0.5, color2 = M.palette && M.palette.tank_water != null ? M.palette.tank_water : 3107496, r = Math.min(w, d) * 0.46, rc = 11841700;
|
|
5904
6183
|
let y0 = 0;
|
|
5905
6184
|
if (onGround) {
|
|
5906
6185
|
for (const sx of [-1, 1]) for (const sz of [-1, 1]) K2.b("plain", sx * (w / 2 - 0.08), 0, sz * (d / 2 - 0.08), 0.14, 1, 0.14, rc);
|
|
@@ -5912,10 +6191,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
5912
6191
|
}
|
|
5913
6192
|
const H = Math.max(0.7, (M.h || 1.8) - (onGround ? 1.12 : 0.1) - 0), th = Math.min(0.95, H * 0.88);
|
|
5914
6193
|
K2.part("water_tank", 0, y0, 0, () => {
|
|
5915
|
-
K2.c("plain", 0, y0, 0, r, th,
|
|
5916
|
-
for (const f of [0.18, 0.5, 0.82]) K2.c("plain", 0, y0 + th * f - 0.025, 0, r * 1.028, 0.05, sh(
|
|
5917
|
-
K2.e("plain", 0, y0 + th + 0.03, 0, r * 1, 0.16, sh(
|
|
5918
|
-
K2.c("plain", 0, y0 + th + 0.09, 0, r * 0.5, 0.05, sh(
|
|
6194
|
+
K2.c("plain", 0, y0, 0, r, th, color2);
|
|
6195
|
+
for (const f of [0.18, 0.5, 0.82]) K2.c("plain", 0, y0 + th * f - 0.025, 0, r * 1.028, 0.05, sh(color2, 0.88));
|
|
6196
|
+
K2.e("plain", 0, y0 + th + 0.03, 0, r * 1, 0.16, sh(color2, 0.95));
|
|
6197
|
+
K2.c("plain", 0, y0 + th + 0.09, 0, r * 0.5, 0.05, sh(color2, 0.8));
|
|
5919
6198
|
K2.c("plain", 0, y0 + th + 0.14, 0, r * 0.18, 0.035, 1916262);
|
|
5920
6199
|
}, { id: "tank_" + M.seed, breakable: true, fluid: "water", volume: Math.PI * r * r * th, radius: r, height: th });
|
|
5921
6200
|
K2.t("metal", [r * 0.7, y0 + th * 0.25, 0], [r * 0.7, y0 + 0.03, 0], 0.02, 3159096);
|
|
@@ -5924,13 +6203,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
5924
6203
|
K2.t("metal", [-r * 0.5, y0 + th + 0.35, 0], [-r * 0.2, y0 + th + 0.35, 0], 0.014, 2763306);
|
|
5925
6204
|
};
|
|
5926
6205
|
FURNITURE.cooking_gas_cylinder = function(M, A) {
|
|
5927
|
-
const K2 = kit2(M, A), r = Math.min(M.w || 0.36, M.d || 0.36) / 2, H = M.h || 0.47,
|
|
6206
|
+
const K2 = kit2(M, A), r = Math.min(M.w || 0.36, M.d || 0.36) / 2, H = M.h || 0.47, color2 = 4157096, scale = sh(color2, 0.7), brass = 13214282, c = Math.cos(M.ry || 0), s = Math.sin(M.ry || 0);
|
|
5928
6207
|
K2.part("gas_cylinder", 0, 0, 0, () => {
|
|
5929
6208
|
K2.c("plain", 0, 0, 0, r * 0.88, 0.05, scale);
|
|
5930
|
-
K2.c("plain", 0, 0.04, 0, r, H * 0.5,
|
|
5931
|
-
K2.e("plain", 0, 0.04 + H * 0.5, 0, r * 0.99, 0.08, sh(
|
|
6209
|
+
K2.c("plain", 0, 0.04, 0, r, H * 0.5, color2);
|
|
6210
|
+
K2.e("plain", 0, 0.04 + H * 0.5, 0, r * 0.99, 0.08, sh(color2, 0.9));
|
|
5932
6211
|
K2.c("plain", 0, H * 0.5 + 0.04, 0, r * 1.012, 0.018, scale);
|
|
5933
|
-
K2.e("plain", 0, H * 0.77, 0, r * 0.98, H * 0.36,
|
|
6212
|
+
K2.e("plain", 0, H * 0.77, 0, r * 0.98, H * 0.36, color2);
|
|
5934
6213
|
K2.c("metal", 0, H * 0.86, 0, 0.05, 0.05, 9080466);
|
|
5935
6214
|
for (let k = 0; k < 3; k++) {
|
|
5936
6215
|
const a = k * 2.0944 + 0.5, x = Math.cos(a) * r * 0.62, z = Math.sin(a) * r * 0.62;
|
|
@@ -5989,8 +6268,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
5989
6268
|
function extraTypes(T2, props) {
|
|
5990
6269
|
const origCar = T2.garage_car;
|
|
5991
6270
|
const car = (M, A) => {
|
|
5992
|
-
const structure = STYLE(),
|
|
5993
|
-
const k =
|
|
6271
|
+
const structure = STYLE(), list2 = CAR_BY_STYLE[structure] || CAR_BY_STYLE.mid, r = rngString(SEED() + "|" + (seedKey(M.seed) || M.id || "") + "|" + Math.round((M.x || 0) * 10) + "|" + Math.round((M.z || 0) * 10) + "|carro");
|
|
6272
|
+
const k = list2[Math.floor(r() * list2.length)], paint = 1 + Math.floor(r() * 8);
|
|
5994
6273
|
if (!carModel(k, paint)) {
|
|
5995
6274
|
if (origCar) origCar.f(M, A);
|
|
5996
6275
|
return;
|
|
@@ -6050,14 +6329,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
6050
6329
|
const vegItem = (...a) => K.vegItem(...a);
|
|
6051
6330
|
function houseItems() {
|
|
6052
6331
|
const R = shared.ctx.r, T2 = shared.ctx.types, api = makeApi(), noModel = /* @__PURE__ */ new Map();
|
|
6053
|
-
const
|
|
6332
|
+
const list2 = R.items.concat(R.stateItems.filter((e) => e.w != null && e.d != null && e.type !== "razor_wire" && e.type !== "barbed_wire"));
|
|
6054
6333
|
const rect = (poly) => {
|
|
6055
6334
|
let a = 0;
|
|
6056
6335
|
for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) a += poly[j][0] * poly[i][1] - poly[i][0] * poly[j][1];
|
|
6057
6336
|
const xs = poly.map((p) => p[0]), zs = poly.map((p) => p[1]);
|
|
6058
6337
|
return Math.abs(a) / 2 > 0.98 * (Math.max(...xs) - Math.min(...xs)) * (Math.max(...zs) - Math.min(...zs));
|
|
6059
6338
|
};
|
|
6060
|
-
for (const m of
|
|
6339
|
+
for (const m of list2) {
|
|
6061
6340
|
if (m.type === "stairs") continue;
|
|
6062
6341
|
const exterior = m.outdoor || m.floor < 0, f = exterior ? -1 : Math.min(m.floor, R.floors.length - 1);
|
|
6063
6342
|
cursor.group = exterior ? "lot" : "f" + f;
|
|
@@ -6111,19 +6390,19 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
6111
6390
|
const base = lc ? cd.platform.topY : cd.y + (shared.ctx.r.rooms.some((c) => c.id === cd.room && c.type === "terrace") ? 0 : 0.2 + (slab ? 0.03 : 0));
|
|
6112
6391
|
cursor.group = slab ? "f" + f : "attic_tank";
|
|
6113
6392
|
if (lc) {
|
|
6114
|
-
const P = cd.platform, [x0, z0, x1, z1] = P.aabb, e = P.thickness,
|
|
6393
|
+
const P = cd.platform, [x0, z0, x1, z1] = P.aabb, e = P.thickness, color2 = shared.ctx.colors.slab != null ? shared.ctx.colors.slab : 12170668;
|
|
6115
6394
|
cursor.pc = structurePiece("tank_slab");
|
|
6116
|
-
boxC("plain", (x0 + x1) / 2, P.topY - e / 2, (z0 + z1) / 2, x1 - x0, e, z1 - z0,
|
|
6395
|
+
boxC("plain", (x0 + x1) / 2, P.topY - e / 2, (z0 + z1) / 2, x1 - x0, e, z1 - z0, color2, 0, 0, 0);
|
|
6117
6396
|
P.pillars.forEach((p, k) => {
|
|
6118
6397
|
cursor.pc = structurePiece("tank_column_" + k);
|
|
6119
|
-
boxC("plain", p.u, (P.baseY + P.topY - e) / 2, p.v, p.side, P.topY - e - P.baseY, p.side,
|
|
6398
|
+
boxC("plain", p.u, (P.baseY + P.topY - e) / 2, p.v, p.side, P.topY - e - P.baseY, p.side, color2, 0, 0, 0);
|
|
6120
6399
|
});
|
|
6121
6400
|
cursor.pc = null;
|
|
6122
6401
|
}
|
|
6123
6402
|
if (!slab) {
|
|
6124
|
-
const
|
|
6125
|
-
boxC("plain", cd.u, base - 0.06, cd.v, hw * 2, 0.12, hd * 2,
|
|
6126
|
-
for (const sx of [-1, 1]) for (const sz of [-1, 1]) boxC("plain", cd.u + sx * (hw - 0.07), (yp + base - 0.12) / 2, cd.v + sz * (hd - 0.07), 0.1, base - 0.12 - yp, 0.1,
|
|
6403
|
+
const color2 = shared.ctx.colors.slab != null ? shared.ctx.colors.slab : 12170668, yp = Y0(f), hw = cd.w / 2 + 0.1, hd = cd.d / 2 + 0.1;
|
|
6404
|
+
boxC("plain", cd.u, base - 0.06, cd.v, hw * 2, 0.12, hd * 2, color2);
|
|
6405
|
+
for (const sx of [-1, 1]) for (const sz of [-1, 1]) boxC("plain", cd.u + sx * (hw - 0.07), (yp + base - 0.12) / 2, cd.v + sz * (hd - 0.07), 0.1, base - 0.12 - yp, 0.1, color2);
|
|
6127
6406
|
}
|
|
6128
6407
|
const M = { x: cd.u, z: cd.v, ry: 0, w: cd.w, d: cd.d, h: cd.h + 0.12, y: 0, base, floor: f, colors: shared.ctx.colors, seed: "water_tank", room: cd.room, onSlab: true, ceiling: 2.9 };
|
|
6129
6408
|
shared.ctx.waterTankPos = { x: cd.u, z: cd.v, y: base, group: cursor.group };
|
|
@@ -6135,8 +6414,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
6135
6414
|
return _col.setHSL((h >>> 0) % 360 / 360, 0.45, 0.55).getHex();
|
|
6136
6415
|
}
|
|
6137
6416
|
function labeledBox(m, M, group) {
|
|
6138
|
-
const
|
|
6139
|
-
boxC("plain", m.x, M.base + (m.y || 0) + h / 2, m.z, m.w, h, m.d,
|
|
6417
|
+
const color2 = M.color != null ? M.color : hashColor(m.category || m.type), h = Math.max(0.05, m.h || 0.5);
|
|
6418
|
+
boxC("plain", m.x, M.base + (m.y || 0) + h / 2, m.z, m.w, h, m.d, color2, 0, m.ry || 0, 0);
|
|
6140
6419
|
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" });
|
|
6141
6420
|
}
|
|
6142
6421
|
Object.assign(K, { houseItems, waterTankOfHouse, hashColor, labeledBox });
|
|
@@ -6650,10 +6929,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
6650
6929
|
if (!lt) return;
|
|
6651
6930
|
const cz0 = (lt.rect[1] + lt.rect[3]) / 2;
|
|
6652
6931
|
const orig = K.getBx(), gs = lt.gates, opening = gs.map((g) => g.open), reg = gs.map((g) => {
|
|
6653
|
-
const
|
|
6654
|
-
return { g, a, b, v: g.v, x0: Infinity, x1: -Infinity, y1: 0, color, dx, zc, lo:
|
|
6932
|
+
const color2 = g.model === "sliding", dx = color2 ? slideDirection(g, lt) : 0, a = g.u - g.width / 2, b = g.u + g.width / 2, zc = g.v + (cz0 - g.v >= 0 ? 1 : -1) * 0.19;
|
|
6933
|
+
return { g, a, b, v: g.v, x0: Infinity, x1: -Infinity, y1: 0, color: color2, dx, zc, lo: color2 ? dx > 0 ? a + 0.04 : a - 0.9 : a + 0.05, hi: color2 ? dx > 0 ? b + 0.9 + 0.01 : b - 0.04 : b + 0.01, zv: color2 ? 0.07 : 0.04, zm: color2 ? zc : g.v };
|
|
6655
6934
|
});
|
|
6656
|
-
K.setBx(function(mat, x0, y0, z0, x1, y1, z1,
|
|
6935
|
+
K.setBx(function(mat, x0, y0, z0, x1, y1, z1, color2) {
|
|
6657
6936
|
if (mat === "metal") {
|
|
6658
6937
|
for (const r of reg) if (r.g.axis === "u" && x0 >= r.lo && x1 <= r.hi && z0 >= r.zm - r.zv && z1 <= r.zm + r.zv && y0 >= 0.03) {
|
|
6659
6938
|
r.x0 = Math.min(r.x0, x0);
|
|
@@ -6661,12 +6940,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
6661
6940
|
r.y1 = Math.max(r.y1, y1);
|
|
6662
6941
|
const g0 = cursor.group;
|
|
6663
6942
|
cursor.group = "ix:gate:" + r.g.id;
|
|
6664
|
-
orig(mat, x0, y0, z0, x1, y1, z1,
|
|
6943
|
+
orig(mat, x0, y0, z0, x1, y1, z1, color2);
|
|
6665
6944
|
cursor.group = g0;
|
|
6666
6945
|
return;
|
|
6667
6946
|
}
|
|
6668
6947
|
}
|
|
6669
|
-
return orig(mat, x0, y0, z0, x1, y1, z1,
|
|
6948
|
+
return orig(mat, x0, y0, z0, x1, y1, z1, color2);
|
|
6670
6949
|
});
|
|
6671
6950
|
const n0 = shared.ctx.colliders.length;
|
|
6672
6951
|
try {
|
|
@@ -6741,10 +7020,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
6741
7020
|
else bx("plain", Math.min(f2, f3), yc - 0.032, u - 0.016, Math.max(f2, f3), yc + 0.032, u + 0.016, 16250092);
|
|
6742
7021
|
cursor.group = g0;
|
|
6743
7022
|
const pv = alongU ? [u, yc, f2] : [f2, yc, u];
|
|
6744
|
-
const
|
|
6745
|
-
|
|
7023
|
+
const piece2 = definePiece("ix:int:" + roomId, { kind: "light_switch", pivot: pv, ry: 0, parent: "f" + f, axis: alongU ? "x" : "z", sgn: alongU ? sd : -sd, t0: lightOn(roomId) ? 1 : 0 });
|
|
7024
|
+
piece2.t = piece2.target = lightOn(roomId) ? 1 : 0;
|
|
6746
7025
|
const an = alongU ? [u, yc, face + sd * 0.12] : [face + sd * 0.12, yc, u];
|
|
6747
|
-
shared.inter.items.push({ type: "light_switch", id: roomId, floor: f, anchor: an, range: 1.5, angle: 0.45, pieces: [
|
|
7026
|
+
shared.inter.items.push({ type: "light_switch", id: roomId, floor: f, anchor: an, range: 1.5, angle: 0.45, pieces: [piece2], text: () => t(lightOn(roomId) ? "prompt.lightOff" : "prompt.lightOn"), action: () => toggleLight(roomId) });
|
|
6748
7027
|
return true;
|
|
6749
7028
|
}
|
|
6750
7029
|
return false;
|
|
@@ -6914,11 +7193,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
6914
7193
|
const IV_WIRE = { conduit: 13618628, cable: 2762532, drop: 1381653, cord: 1776413, earth: 3111482, hose: 11556124 };
|
|
6915
7194
|
const IV_DOOR = /^(door|drawer)/;
|
|
6916
7195
|
const ivGroup = (e) => e.floor < 0 ? "lot" : "f" + Math.min(e.floor, shared.ctx.r.floors.length - 1);
|
|
6917
|
-
function ivAccumulate(mat, g, ox, oy, oz, ry,
|
|
6918
|
-
const P = g.attributes.position, N = g.attributes.normal, C =
|
|
7196
|
+
function ivAccumulate(mat, g, ox, oy, oz, ry, color2) {
|
|
7197
|
+
const P = g.attributes.position, N = g.attributes.normal, C = color2 == null ? g.attributes.color : null, U = g.attributes.uv, I = g.index, nv = P.count, ni = I ? I.count : nv;
|
|
6919
7198
|
const A = accFor(mat);
|
|
6920
7199
|
A.ensure(nv, ni);
|
|
6921
|
-
const c = Math.cos(ry), s = Math.sin(ry), b = A.nv, rgb =
|
|
7200
|
+
const c = Math.cos(ry), s = Math.sin(ry), b = A.nv, rgb = color2 != null ? rgbOf(color2) : [1, 1, 1];
|
|
6922
7201
|
for (let k = 0; k < nv; k++) {
|
|
6923
7202
|
const x = P.getX(k), y = P.getY(k), z = P.getZ(k), o = b + k;
|
|
6924
7203
|
A.p[o * 3] = x * c + z * s + ox;
|
|
@@ -6959,14 +7238,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
6959
7238
|
function ivBuild(h, water) {
|
|
6960
7239
|
const ik = K.IVK, r = shared.ctx.r, A = ik.A, world0 = null;
|
|
6961
7240
|
void world0;
|
|
6962
|
-
const
|
|
6963
|
-
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 };
|
|
7241
|
+
const plane2 = A.plan(r, { seed: r.seed });
|
|
7242
|
+
const IV = { k: ik, plane: plane2, world: null, water, entries: /* @__PURE__ */ new Map(), roots: [], replace: /* @__PURE__ */ new Set(), roomStates: /* @__PURE__ */ new Map(), lampRoom: /* @__PURE__ */ new Map(), anim: /* @__PURE__ */ new Map(), screens: /* @__PURE__ */ new Map(), efx: null, items: null, itemsDirty: true, itemsT: 0, dirty: true, list: null, listT: 0, t: 0, circuits: [], switchRooms: /* @__PURE__ */ new Set(), warnings: [], tBuild: 0 };
|
|
6964
7243
|
h.IV = IV;
|
|
6965
7244
|
const t0 = performance.now();
|
|
6966
|
-
const lamps = new Set(
|
|
6967
|
-
for (const id of
|
|
7245
|
+
const lamps = new Set(plane2.items.filter((e) => e.type === "lamp").map((e) => e.id));
|
|
7246
|
+
for (const id of plane2.mapped) if (!lamps.has(id)) IV.replace.add(id);
|
|
6968
7247
|
const furnitureById = new Map(r.items.map((m) => [m.id, m]));
|
|
6969
|
-
for (const e of
|
|
7248
|
+
for (const e of plane2.items) {
|
|
6970
7249
|
if (e.type !== "lamp") continue;
|
|
6971
7250
|
const m = furnitureById.get(e.id);
|
|
6972
7251
|
if (!m || !LIGHT_TYPES.has(m.type) || !m.room) continue;
|
|
@@ -6976,9 +7255,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
6976
7255
|
IV.lampRoom.set(e.id, m.room);
|
|
6977
7256
|
}
|
|
6978
7257
|
const wants = (roomId) => lightBase(roomId);
|
|
6979
|
-
const entById = new Map(
|
|
6980
|
-
const entByItem = new Map(
|
|
6981
|
-
IV.mats = { plain: shared.mats.plain, metal: shared.mats.metal, wood: shared.mats.wood, glass: shared.mats.glass, fabric: shared.mats.fabric, plant: shared.mats.plant, water: shared.mats.water, emissive: shared.mats.emissive, atlas_picture: shared.mats.picture, atlas_floor: shared.mats.
|
|
7258
|
+
const entById = new Map(plane2.items.map((e) => [e.id, e]));
|
|
7259
|
+
const entByItem = new Map(plane2.items.map((e) => [e.item, e]));
|
|
7260
|
+
IV.mats = { plain: shared.mats.plain, metal: shared.mats.metal, wood: shared.mats.wood, glass: shared.mats.glass, fabric: shared.mats.fabric, plant: shared.mats.plant, water: shared.mats.water, emissive: shared.mats.emissive, atlas_picture: shared.mats.picture, atlas_floor: shared.mats.floor };
|
|
6982
7261
|
const ev = (e) => ivEvent(h, e);
|
|
6983
7262
|
const world = IV.world = A.createWorld(r, { water, seed: r.seed, onEvent: ev });
|
|
6984
7263
|
const add0 = world.add;
|
|
@@ -6997,10 +7276,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
6997
7276
|
}
|
|
6998
7277
|
return add0(id, spec, tr);
|
|
6999
7278
|
};
|
|
7000
|
-
const
|
|
7279
|
+
const added = A.add(world, plane2, { isBlocked: A.blockedOf(r), build: (type, item) => ivDraw(IV, entByItem.get(item), type, item) });
|
|
7001
7280
|
world.add = add0;
|
|
7002
|
-
IV.warnings =
|
|
7003
|
-
IV.
|
|
7281
|
+
IV.warnings = added.warnings;
|
|
7282
|
+
IV.added = added;
|
|
7004
7283
|
if (h.state.iv) {
|
|
7005
7284
|
try {
|
|
7006
7285
|
const st = JSON.parse(JSON.stringify(h.state.iv));
|
|
@@ -7023,7 +7302,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
7023
7302
|
console.warn("interactables: state", err);
|
|
7024
7303
|
}
|
|
7025
7304
|
}
|
|
7026
|
-
for (const e of
|
|
7305
|
+
for (const e of plane2.items) if (e.type === "wall_switch") for (const l of e.connections.controls || []) {
|
|
7027
7306
|
const roomId = IV.lampRoom.get(l);
|
|
7028
7307
|
if (roomId) {
|
|
7029
7308
|
IV.switchRooms.add(roomId);
|
|
@@ -7050,7 +7329,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
7050
7329
|
for (const l of out.lights) l.removeFromParent();
|
|
7051
7330
|
const group = ivGroup(ent), g0 = cursor.group, root = new THREE.Group();
|
|
7052
7331
|
root.name = "iv:" + ent.id;
|
|
7053
|
-
root.position.set(item.x, ent.
|
|
7332
|
+
root.position.set(item.x, ent.floorY, item.z);
|
|
7054
7333
|
root.rotation.y = item.ry;
|
|
7055
7334
|
root.userData.iv = ent.id;
|
|
7056
7335
|
const screen = spec.devices && spec.devices.some((d) => d.kind === "screen");
|
|
@@ -7074,7 +7353,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
7074
7353
|
root.add(m);
|
|
7075
7354
|
continue;
|
|
7076
7355
|
}
|
|
7077
|
-
ivAccumulate(IV_MATERIAL[m.userData.material] || "plain", m.geometry, item.x, ent.
|
|
7356
|
+
ivAccumulate(IV_MATERIAL[m.userData.material] || "plain", m.geometry, item.x, ent.floorY, item.z, item.ry, null);
|
|
7078
7357
|
m.geometry.dispose();
|
|
7079
7358
|
} else root.add(m);
|
|
7080
7359
|
}
|
|
@@ -7095,17 +7374,17 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
7095
7374
|
roomLightMask(m);
|
|
7096
7375
|
}
|
|
7097
7376
|
});
|
|
7098
|
-
const E = { id: ent.id, type, entry: ent, floor: ent.floor, group, root, parts: out.parts, spec, screen: body, pos: [item.x, ent.
|
|
7377
|
+
const E = { id: ent.id, type, entry: ent, floor: ent.floor, group, root, parts: out.parts, spec, screen: body, pos: [item.x, ent.floorY, item.z], ry: item.ry, origin: ent.origin };
|
|
7099
7378
|
IV.entries.set(ent.id, E);
|
|
7100
7379
|
if (root.children.length) IV.roots.push(E);
|
|
7101
7380
|
return spec;
|
|
7102
7381
|
}
|
|
7103
7382
|
function ivCords(IV) {
|
|
7104
7383
|
const ik = IV.k, w = IV.world, wl = (o, p) => ik.GI.localToWorld(o.transform, p), g0 = cursor.group;
|
|
7105
|
-
const tube = (pts, radius,
|
|
7384
|
+
const tube = (pts, radius, color2, ox, oy, oz, ry) => {
|
|
7106
7385
|
try {
|
|
7107
7386
|
const m = ik.gfx.createCord(pts, radius, shared.mats.plain);
|
|
7108
|
-
ivAccumulate("plain", m.geometry, ox, oy, oz, ry,
|
|
7387
|
+
ivAccumulate("plain", m.geometry, ox, oy, oz, ry, color2);
|
|
7109
7388
|
m.geometry.dispose();
|
|
7110
7389
|
} catch (e) {
|
|
7111
7390
|
}
|
|
@@ -7288,7 +7567,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
7288
7567
|
function ivItems(IV, h) {
|
|
7289
7568
|
IV.itemsDirty = false;
|
|
7290
7569
|
IV.itemsT = IV.t;
|
|
7291
|
-
const w = IV.world, items = IV.k.A.household.items, f = IV.focus, g0 = cursor.group,
|
|
7570
|
+
const w = IV.world, items = IV.k.A.household.items, f = IV.focus, g0 = cursor.group, list2 = [];
|
|
7292
7571
|
let fl = null;
|
|
7293
7572
|
if (f) {
|
|
7294
7573
|
h.houseGroup.updateWorldMatrix(true, false);
|
|
@@ -7302,23 +7581,23 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
7302
7581
|
if (c.access && w.partT(E.id, c.access) < 0.02) continue;
|
|
7303
7582
|
const st = w.contents(E.id, c.id);
|
|
7304
7583
|
for (let i = 0; i < st.length; i++) {
|
|
7305
|
-
if (st[i] && items[st[i].type])
|
|
7584
|
+
if (st[i] && items[st[i].type]) list2.push([E, c.id, i, items[st[i].type]]);
|
|
7306
7585
|
}
|
|
7307
7586
|
}
|
|
7308
7587
|
}
|
|
7309
|
-
if (!
|
|
7588
|
+
if (!list2.length) {
|
|
7310
7589
|
if (IV.items) IV.items.visible = false;
|
|
7311
7590
|
return;
|
|
7312
7591
|
}
|
|
7313
7592
|
cursor.group = "iv-items";
|
|
7314
7593
|
try {
|
|
7315
|
-
for (const [E, cid, slot, def] of
|
|
7594
|
+
for (const [E, cid, slot, def] of list2) {
|
|
7316
7595
|
const p = w.slotPosition(E.id, cid, slot), form = IV_SHAPE[def.shape] || IV_SHAPE.box;
|
|
7317
7596
|
for (const [geo, fx, fy, fz, y0, tone] of form) {
|
|
7318
7597
|
const sx = def.size[0] * fx, sy = def.size[1] * fy, sz = def.size[2] * fz;
|
|
7319
7598
|
_q.setFromAxisAngle(_Y, E.ry);
|
|
7320
|
-
const
|
|
7321
|
-
put("plain", geo, p[0], p[1] + def.size[1] * y0 + sy / 2, p[2], _q, sx, sy, sz, tone === 1 ?
|
|
7599
|
+
const color2 = def.color == null ? 13421772 : def.color;
|
|
7600
|
+
put("plain", geo, p[0], p[1] + def.size[1] * y0 + sy / 2, p[2], _q, sx, sy, sz, tone === 1 ? color2 : sh(color2, tone));
|
|
7322
7601
|
}
|
|
7323
7602
|
}
|
|
7324
7603
|
const A = cursor.accs.get("iv-items|plain");
|
|
@@ -7443,7 +7722,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
7443
7722
|
})),
|
|
7444
7723
|
seatInfo: () => ivSeat(IV),
|
|
7445
7724
|
// {object, seat, pose: 'sit'|'lie', eye, yaw, pitch, exit, floor} if the player is sitting/lying
|
|
7446
|
-
sit: com((
|
|
7725
|
+
sit: com((object2, seatInfo) => !!w.sit(object2, seatInfo, "player")),
|
|
7447
7726
|
stand: com(() => w.stand("player")),
|
|
7448
7727
|
opens: com((mid, target) => {
|
|
7449
7728
|
for (const E of IV.entries.values()) if (E.origin === mid) {
|
|
@@ -7454,7 +7733,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
7454
7733
|
breaker: com((circuit, on) => {
|
|
7455
7734
|
if (on === void 0) return w.power.breaker(circuit);
|
|
7456
7735
|
w.power.setBreaker(circuit, !!on);
|
|
7457
|
-
const q = IV.plane.
|
|
7736
|
+
const q = IV.plane.panel && IV.entries.get(IV.plane.panel);
|
|
7458
7737
|
if (q && q.parts["breaker_" + circuit]) w.setPart(q.id, "breaker_" + circuit, on ? 1 : 0);
|
|
7459
7738
|
IV.dirty = true;
|
|
7460
7739
|
return !!on;
|
|
@@ -7523,6 +7802,1345 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
7523
7802
|
Object.assign(K, { props, TYPES, newState, enter, tagDamage });
|
|
7524
7803
|
}
|
|
7525
7804
|
|
|
7805
|
+
// ../game-floorplan-interactables/dist/index.js
|
|
7806
|
+
var en2 = {
|
|
7807
|
+
"error.missingKit": "game-floorplan-interactables: create needs GameInteractables and GameInteractablesHousehold",
|
|
7808
|
+
"error.unknownOwnType": "game-floorplan-interactables: unknown own type: {type}",
|
|
7809
|
+
"warn.cylinderNoCabinet": "cylinder {id} under the counter has no kitchen cabinet to hide it",
|
|
7810
|
+
"warn.cabinetNoDoor": "cabinet {cabinet} has no door for the cylinder {id}",
|
|
7811
|
+
"warn.switchUnknownLamp": "switch {id} controls {lamp}, which does not exist",
|
|
7812
|
+
"warn.pointNoObject": "point {id} ({kind}) has no object for {item}",
|
|
7813
|
+
"warn.buildEmpty": "build returned nothing for {id}"
|
|
7814
|
+
};
|
|
7815
|
+
var ptBR2 = {
|
|
7816
|
+
"error.missingKit": "game-floorplan-interactables: create precisa de GameInteractables e GameInteractablesHousehold",
|
|
7817
|
+
"error.unknownOwnType": "game-floorplan-interactables: tipo pr\xF3prio desconhecido: {type}",
|
|
7818
|
+
"warn.cylinderNoCabinet": "botij\xE3o {id} sob a bancada sem arm\xE1rio de cozinha para escond\xEA-lo",
|
|
7819
|
+
"warn.cabinetNoDoor": "arm\xE1rio {cabinet} sem porta para o botij\xE3o {id}",
|
|
7820
|
+
"warn.switchUnknownLamp": "interruptor {id} controla {lamp}, que n\xE3o existe",
|
|
7821
|
+
"warn.pointNoObject": "ponto {id} ({kind}) sem objeto para {item}",
|
|
7822
|
+
"warn.buildEmpty": "construir devolveu vazio para {id}"
|
|
7823
|
+
};
|
|
7824
|
+
function createTranslator2(locale, table) {
|
|
7825
|
+
const base = locale && /^pt/i.test(locale) ? ptBR2 : en2;
|
|
7826
|
+
const messages = { ...base, ...table ?? {} };
|
|
7827
|
+
return (key, params) => (messages[key] ?? key).replace(/\{(\w+)\}/g, (_m, name) => params && params[name] !== void 0 ? String(params[name]) : `{${name}}`);
|
|
7828
|
+
}
|
|
7829
|
+
var TYPE_MAP = Object.freeze({
|
|
7830
|
+
fridge: { type: "fridge" },
|
|
7831
|
+
// was `geladeira`
|
|
7832
|
+
fridge_large: { type: "fridge" },
|
|
7833
|
+
// was `geladeira2`
|
|
7834
|
+
display_fridge_medium: { type: "fridge", variant: "steel" },
|
|
7835
|
+
// was `geladeira_med`
|
|
7836
|
+
display_fridge: { type: "fridge", variant: "steel" },
|
|
7837
|
+
// was `refrig_exp`
|
|
7838
|
+
freezer: { type: "fridge_compact" },
|
|
7839
|
+
// was `freezer`
|
|
7840
|
+
kitchen_cabinet: { compound: "sink" },
|
|
7841
|
+
// was `armario_cozinha`
|
|
7842
|
+
kitchen_cabinet_small: { compound: "sink" },
|
|
7843
|
+
// was `armario_cozinha_p`
|
|
7844
|
+
kitchen_cabinet_large: { compound: "sink" },
|
|
7845
|
+
// was `armario_cozinha_g`
|
|
7846
|
+
washbasin: { compound: "basin" },
|
|
7847
|
+
// was `pia_b`
|
|
7848
|
+
pedestal_basin: { compound: "basin" },
|
|
7849
|
+
// was `pia_coluna`
|
|
7850
|
+
wardrobe: { type: "wardrobe" },
|
|
7851
|
+
// was `guarda`
|
|
7852
|
+
wardrobe_small: { type: "wardrobe" },
|
|
7853
|
+
// was `guarda_peq`
|
|
7854
|
+
wardrobe_large: { type: "wardrobe" },
|
|
7855
|
+
// was `guarda_g`
|
|
7856
|
+
closet_wardrobe: { type: "wardrobe" },
|
|
7857
|
+
// was `guarda_closet`
|
|
7858
|
+
dresser: { type: "dresser" },
|
|
7859
|
+
// was `comoda`
|
|
7860
|
+
nightstand: { type: "nightstand" },
|
|
7861
|
+
// was `criado`
|
|
7862
|
+
pantry: { type: "pantry" },
|
|
7863
|
+
// was `despensa`
|
|
7864
|
+
laundry_cabinet: { type: "pantry" },
|
|
7865
|
+
// was `armario_lav`
|
|
7866
|
+
china_cabinet: { type: "pantry" },
|
|
7867
|
+
// was `cristaleira`
|
|
7868
|
+
filing_cabinet: { type: "dresser" },
|
|
7869
|
+
// was `arquivo`
|
|
7870
|
+
console_table: { type: "dresser" },
|
|
7871
|
+
// was `aparador_c`
|
|
7872
|
+
tv_unit: { type: "kitchen_cabinet_base" },
|
|
7873
|
+
// was `rack`
|
|
7874
|
+
tv_unit_small: { type: "kitchen_cabinet_base" },
|
|
7875
|
+
// was `rack_peq`
|
|
7876
|
+
tv_unit_large: { type: "kitchen_cabinet_base" },
|
|
7877
|
+
// was `rack_grande`
|
|
7878
|
+
stove: { type: "stove" },
|
|
7879
|
+
// was `fogao`
|
|
7880
|
+
stove_4burner: { type: "stove" },
|
|
7881
|
+
// was `fogao4`
|
|
7882
|
+
cooking_gas_cylinder: { type: "gas_bottle", dim: "none" },
|
|
7883
|
+
// was `botijao_gas`
|
|
7884
|
+
gas_cylinder: { type: "gas_bottle", dim: "none" },
|
|
7885
|
+
// was `botijao`
|
|
7886
|
+
tv: { type: "tv" },
|
|
7887
|
+
// was `tv`
|
|
7888
|
+
tv_large: { type: "tv" },
|
|
7889
|
+
// was `tv_grande`
|
|
7890
|
+
microwave: { type: "microwave" },
|
|
7891
|
+
// was `microondas`
|
|
7892
|
+
washing_machine: { type: "washing_machine" },
|
|
7893
|
+
// was `maquina`
|
|
7894
|
+
shower: { type: "shower", dim: "wd" },
|
|
7895
|
+
// was `box`
|
|
7896
|
+
shower_large: { type: "shower", dim: "wd" },
|
|
7897
|
+
// was `box_g`
|
|
7898
|
+
toilet: { type: "toilet", dim: "wd" },
|
|
7899
|
+
// was `vaso`
|
|
7900
|
+
laundry_tub: { type: "utility_sink", dim: "wd" },
|
|
7901
|
+
// was `tanque`
|
|
7902
|
+
sofa_2seat: { type: "sofa" },
|
|
7903
|
+
// was `sofa2`
|
|
7904
|
+
sofa_3seat: { type: "sofa" },
|
|
7905
|
+
// was `sofa3`
|
|
7906
|
+
sofa_l: { type: "sofa" },
|
|
7907
|
+
// was `sofa_l`
|
|
7908
|
+
sofa_xl: { type: "sofa" },
|
|
7909
|
+
// was `sofa_xl`
|
|
7910
|
+
armchair: { type: "armchair" },
|
|
7911
|
+
// was `poltrona`
|
|
7912
|
+
armchair_high: { type: "armchair" },
|
|
7913
|
+
// was `poltrona_alta`
|
|
7914
|
+
stool: { type: "dining_chair" },
|
|
7915
|
+
// was `banqueta`
|
|
7916
|
+
camp_chair: { type: "camp_chair", dim: "wd" },
|
|
7917
|
+
// was `cadeira_camping`
|
|
7918
|
+
rocking_chair: { type: "armchair" },
|
|
7919
|
+
// was `cadeira_balanco`
|
|
7920
|
+
rustic_sink: { compound: "rustic_sink" },
|
|
7921
|
+
// was `pia_rustica`: the sink of the cabin or shack: the basin the whole width, no cabinet under it; a wall cabinet only if there is `overhead` content
|
|
7922
|
+
improvised_bed: { type: "bed_single", dim: "wd" },
|
|
7923
|
+
// was `cama_improvisada`
|
|
7924
|
+
log_bench: { type: "bench", dim: "wd" },
|
|
7925
|
+
// was `banco_tronco`
|
|
7926
|
+
plank_shelf: { type: "pantry", variant: "garage" },
|
|
7927
|
+
// was `prateleira_tabua`
|
|
7928
|
+
sideboard: { type: "dresser" },
|
|
7929
|
+
// was `aparador`
|
|
7930
|
+
buffet: { type: "dresser" },
|
|
7931
|
+
// was `bufe`
|
|
7932
|
+
single_bed: { type: "bed_single", dim: "wd" },
|
|
7933
|
+
// was `cama_solteiro`
|
|
7934
|
+
double_bed: { type: "bed_double", dim: "wd" },
|
|
7935
|
+
// was `cama_casal`
|
|
7936
|
+
queen_bed: { type: "bed_double", dim: "wd" },
|
|
7937
|
+
// was `cama_queen`
|
|
7938
|
+
king_bed: { type: "bed_double", dim: "wd" },
|
|
7939
|
+
// was `cama_king`
|
|
7940
|
+
bench: { type: "bench", dim: "wd" },
|
|
7941
|
+
// was `banco`
|
|
7942
|
+
garden_bench: { type: "bench", dim: "wd" },
|
|
7943
|
+
// was `banco_jardim`
|
|
7944
|
+
waiting_bench: { type: "bench", dim: "wd" },
|
|
7945
|
+
// was `espera`
|
|
7946
|
+
blinds: { type: "blinds" },
|
|
7947
|
+
// was `persiana`
|
|
7948
|
+
curtain: { type: "curtain" },
|
|
7949
|
+
// was `cortina`
|
|
7950
|
+
trash_bin: { type: "trash_bin" },
|
|
7951
|
+
// was `lixeira`
|
|
7952
|
+
outdoor_bin: { type: "wheelie_bin" },
|
|
7953
|
+
// was `lixeira_ext`
|
|
7954
|
+
mailbox: { type: "mailbox", dim: "none" },
|
|
7955
|
+
// was `caixa_correio`: the household draws the box on its post: position and rotation only
|
|
7956
|
+
doghouse: { type: "dog_house" },
|
|
7957
|
+
// was `casinha_cachorro`
|
|
7958
|
+
bbq_grill: { type: "bbq", dim: "wd" },
|
|
7959
|
+
// was `churrasqueira`
|
|
7960
|
+
bbq_simple: { type: "bbq", dim: "wd" },
|
|
7961
|
+
// was `churrasqueira_simples`
|
|
7962
|
+
clothesline: { type: "clothesline", dim: "wh" },
|
|
7963
|
+
// was `varal`
|
|
7964
|
+
tool_shelf: { type: "pantry", variant: "garage" },
|
|
7965
|
+
// was `estante_ferr`
|
|
7966
|
+
workbench: { type: "pantry", variant: "garage" },
|
|
7967
|
+
// was `bancada_ferr`
|
|
7968
|
+
// rural houses and campsite (types of the household pack: rural and camp)
|
|
7969
|
+
bunk_bed: { type: "bunk_bed", dim: "wd" },
|
|
7970
|
+
// was `beliche`
|
|
7971
|
+
wood_stove: { type: "wood_stove", dim: "wd" },
|
|
7972
|
+
// was `fogao_lenha`: the flue rises to the chimney height (cabin); the fireplace is handled in `planSimple` (it moves and changes height)
|
|
7973
|
+
fireplace: { type: "fireplace", dim: "w" },
|
|
7974
|
+
// was `lareira`
|
|
7975
|
+
outhouse: { type: "outhouse", dim: "wdh" },
|
|
7976
|
+
// was `privada`
|
|
7977
|
+
well: { type: "well", dim: "none" },
|
|
7978
|
+
// was `poco`
|
|
7979
|
+
cooler: { type: "cooler", dim: "wd" },
|
|
7980
|
+
// was `cooler`
|
|
7981
|
+
campfire: { type: "campfire", dim: "wd" },
|
|
7982
|
+
// was `fogueira`
|
|
7983
|
+
camp_stove: { type: "camp_stove", dim: "wd" },
|
|
7984
|
+
// was `fogareiro`
|
|
7985
|
+
camp_gas_canister: { type: "gas_canister", dim: "none" },
|
|
7986
|
+
// was `botijao_camping`
|
|
7987
|
+
camp_table: { type: "camp_table", dim: "wdh" },
|
|
7988
|
+
// was `mesa_camping`
|
|
7989
|
+
// kerosene/gas lanterns: a `lamp` device without electricity (the grid does not matter); the ceiling one is the `hanging` variant
|
|
7990
|
+
oil_lamp: { type: "lantern_lamp", dim: "x" },
|
|
7991
|
+
// was `lampiao`
|
|
7992
|
+
camp_lantern: { type: "lantern_lamp", dim: "x" },
|
|
7993
|
+
// was `lampiao_camping`
|
|
7994
|
+
ceiling_oil_lamp: { type: "lantern_lamp", variant: "hanging", dim: "x" },
|
|
7995
|
+
// was `lampiao_teto`
|
|
7996
|
+
// lamps: objects of the adapter (the kit has no lamp mesh; the house renderer draws the fixture)
|
|
7997
|
+
ceiling_light: { type: "lamp", watts: 15 },
|
|
7998
|
+
// was `plafon`
|
|
7999
|
+
pendant: { type: "lamp", watts: 20 },
|
|
8000
|
+
// was `pendente`
|
|
8001
|
+
track_spot: { type: "lamp", watts: 10 },
|
|
8002
|
+
// was `spot_trilho`
|
|
8003
|
+
chandelier: { type: "lamp", watts: 60 },
|
|
8004
|
+
// was `lustre`
|
|
8005
|
+
floor_lamp: { type: "lamp", watts: 12 },
|
|
8006
|
+
// was `luminaria`
|
|
8007
|
+
table_lamp: { type: "lamp", watts: 9 }
|
|
8008
|
+
// was `abajur`
|
|
8009
|
+
});
|
|
8010
|
+
var CHAIR_TABLES = Object.freeze({
|
|
8011
|
+
dining_table: "dining",
|
|
8012
|
+
// was `mesa`
|
|
8013
|
+
dining_table_small: "dining",
|
|
8014
|
+
// was `mesa_peq`
|
|
8015
|
+
dining_table_round: "dining",
|
|
8016
|
+
// was `mesa_red`
|
|
8017
|
+
dining_table_large: "dining",
|
|
8018
|
+
// was `mesa_grande`
|
|
8019
|
+
gourmet_table: "dining",
|
|
8020
|
+
// was `mesa_gourmet`
|
|
8021
|
+
gourmet_table_small: "dining",
|
|
8022
|
+
// was `mesa_gourmet_peq`
|
|
8023
|
+
outdoor_table: "dining",
|
|
8024
|
+
// was `mesa_ext`
|
|
8025
|
+
office_desk: "office",
|
|
8026
|
+
// was `mesa_escr`
|
|
8027
|
+
office_desk_large: "office",
|
|
8028
|
+
// was `mesa_escr_g`
|
|
8029
|
+
desk: "office"
|
|
8030
|
+
// was `escrivaninha`
|
|
8031
|
+
});
|
|
8032
|
+
var DINING_CHAIR_SIDE = 0.45;
|
|
8033
|
+
var CONTENT_MAP = Object.freeze({
|
|
8034
|
+
// food
|
|
8035
|
+
sugar: "sugar",
|
|
8036
|
+
// was `acucar`
|
|
8037
|
+
rice: "rice",
|
|
8038
|
+
// was `arroz`
|
|
8039
|
+
biscuits: "biscuits",
|
|
8040
|
+
// was `biscoito`
|
|
8041
|
+
coffee: "coffee",
|
|
8042
|
+
// was `cafe`
|
|
8043
|
+
raw_beef: "frozen_meat",
|
|
8044
|
+
// was `carne`
|
|
8045
|
+
packed_meat: "frozen_meat",
|
|
8046
|
+
// was `carne`
|
|
8047
|
+
flour: "flour",
|
|
8048
|
+
// was `farinha`
|
|
8049
|
+
beans: "beans",
|
|
8050
|
+
// was `feijao`
|
|
8051
|
+
apple: "apple",
|
|
8052
|
+
// was `fruta`
|
|
8053
|
+
fruit: "apple",
|
|
8054
|
+
// was `fruta`
|
|
8055
|
+
yogurt: "yogurt",
|
|
8056
|
+
// was `iogurte`
|
|
8057
|
+
canned_food: "canned_food",
|
|
8058
|
+
// was `lata_atum`
|
|
8059
|
+
canned_tuna: "canned_food",
|
|
8060
|
+
// was `lata_atum`
|
|
8061
|
+
canned_corn_and_peas: "canned_food",
|
|
8062
|
+
// was `lata_milho`
|
|
8063
|
+
canned_corn: "canned_food",
|
|
8064
|
+
// was `lata_milho`
|
|
8065
|
+
milk_carton: "milk_carton",
|
|
8066
|
+
// was `leite`
|
|
8067
|
+
pasta: "pasta",
|
|
8068
|
+
// was `macarrao`
|
|
8069
|
+
cooking_oil: "cooking_oil",
|
|
8070
|
+
// was `oleo`
|
|
8071
|
+
eggs: "eggs",
|
|
8072
|
+
// was `ovos`
|
|
8073
|
+
cheese: "cheese",
|
|
8074
|
+
// was `queijo`
|
|
8075
|
+
leftover_meal: "bowl",
|
|
8076
|
+
// was `sobras`
|
|
8077
|
+
leftovers: "bowl",
|
|
8078
|
+
// was `sobras`
|
|
8079
|
+
ice_cream: "ice_cream",
|
|
8080
|
+
// was `sorvete`
|
|
8081
|
+
seasoning: "salt",
|
|
8082
|
+
// was `tempero`
|
|
8083
|
+
spices: "salt",
|
|
8084
|
+
// was `tempero`
|
|
8085
|
+
// water and drink
|
|
8086
|
+
water_jug_5l: "water_bottle",
|
|
8087
|
+
// was `agua_galao`
|
|
8088
|
+
water_jug: "water_bottle",
|
|
8089
|
+
// was `agua_galao`
|
|
8090
|
+
water_bottle: "water_bottle",
|
|
8091
|
+
// was `agua_garrafa`
|
|
8092
|
+
soda_can: "soda_can",
|
|
8093
|
+
// was `refrigerante`
|
|
8094
|
+
soda: "soda_can",
|
|
8095
|
+
// was `refrigerante`
|
|
8096
|
+
// medicine
|
|
8097
|
+
alcohol_70: "alcohol_70",
|
|
8098
|
+
// was `alcool`
|
|
8099
|
+
rubbing_alcohol: "alcohol_70",
|
|
8100
|
+
// was `alcool`
|
|
8101
|
+
adhesive_bandages: "bandage",
|
|
8102
|
+
// was `curativo`
|
|
8103
|
+
bandages: "bandage",
|
|
8104
|
+
// was `curativo`
|
|
8105
|
+
insulin: "first_aid_kit",
|
|
8106
|
+
// was `insulina`
|
|
8107
|
+
painkillers: "painkillers",
|
|
8108
|
+
// was `paracetamol`
|
|
8109
|
+
painkiller: "painkillers",
|
|
8110
|
+
// was `paracetamol`
|
|
8111
|
+
maintenance_medication: "painkillers",
|
|
8112
|
+
// was `remedio`
|
|
8113
|
+
medicine: "painkillers",
|
|
8114
|
+
// was `remedio`
|
|
8115
|
+
// cleaning and hygiene
|
|
8116
|
+
bleach: "bleach",
|
|
8117
|
+
// was `agua_sanitaria`
|
|
8118
|
+
disinfectant: "bleach",
|
|
8119
|
+
// was `desinfetante`
|
|
8120
|
+
detergent: "detergent",
|
|
8121
|
+
// was `detergente`
|
|
8122
|
+
dish_soap: "detergent",
|
|
8123
|
+
// was `detergente`
|
|
8124
|
+
toothbrush: "toothbrush",
|
|
8125
|
+
// was `escova_dente`
|
|
8126
|
+
sponge: "sponge",
|
|
8127
|
+
// was `esponja`
|
|
8128
|
+
rubber_gloves: "sponge",
|
|
8129
|
+
// was `luvas`
|
|
8130
|
+
toilet_paper: "toilet_paper",
|
|
8131
|
+
// was `papel_higienico`
|
|
8132
|
+
laundry_powder: "detergent",
|
|
8133
|
+
// was `sabao_po`
|
|
8134
|
+
washing_powder: "detergent",
|
|
8135
|
+
// was `sabao_po`
|
|
8136
|
+
soap: "soap",
|
|
8137
|
+
// was `sabonete`
|
|
8138
|
+
shampoo: "shampoo",
|
|
8139
|
+
// was `shampoo`
|
|
8140
|
+
// clothes
|
|
8141
|
+
jeans: "jeans",
|
|
8142
|
+
// was `calca`
|
|
8143
|
+
trousers: "jeans",
|
|
8144
|
+
// was `calca`
|
|
8145
|
+
tshirt: "tshirt",
|
|
8146
|
+
// was `camisa`
|
|
8147
|
+
shirt: "tshirt",
|
|
8148
|
+
// was `camisa`
|
|
8149
|
+
t_shirt: "tshirt",
|
|
8150
|
+
// was `camiseta`
|
|
8151
|
+
jacket: "jacket",
|
|
8152
|
+
// was `casaco`
|
|
8153
|
+
coat: "jacket",
|
|
8154
|
+
// was `casaco`
|
|
8155
|
+
blanket: "blanket",
|
|
8156
|
+
// was `cobertor`
|
|
8157
|
+
socks: "socks",
|
|
8158
|
+
// was `meias`
|
|
8159
|
+
underwear: "underwear",
|
|
8160
|
+
// was `roupa_intima`
|
|
8161
|
+
sneakers: "sneakers",
|
|
8162
|
+
// was `sapato`
|
|
8163
|
+
shoes: "sneakers",
|
|
8164
|
+
// was `sapato`
|
|
8165
|
+
// utensils
|
|
8166
|
+
cup: "cup",
|
|
8167
|
+
// was `caneca`
|
|
8168
|
+
mug: "cup",
|
|
8169
|
+
// was `caneca`
|
|
8170
|
+
plate: "plate",
|
|
8171
|
+
// was `prato`
|
|
8172
|
+
china_plates: "plate",
|
|
8173
|
+
// was `prato`
|
|
8174
|
+
plates: "plate",
|
|
8175
|
+
// was `prato`
|
|
8176
|
+
wine_glass: "cup",
|
|
8177
|
+
// was `taca`
|
|
8178
|
+
wine_glasses: "cup",
|
|
8179
|
+
// was `taca`
|
|
8180
|
+
pot: "pot",
|
|
8181
|
+
// was `panela`
|
|
8182
|
+
// tools and electronics
|
|
8183
|
+
pliers: "screwdriver",
|
|
8184
|
+
// was `alicate`
|
|
8185
|
+
bucket: "paint_can",
|
|
8186
|
+
// was `balde`
|
|
8187
|
+
cable_bundle: "phone_charger",
|
|
8188
|
+
// was `cabos`
|
|
8189
|
+
cables: "phone_charger",
|
|
8190
|
+
// was `cabos`
|
|
8191
|
+
pen: "pen",
|
|
8192
|
+
// was `caneta`
|
|
8193
|
+
phone_charger: "phone_charger",
|
|
8194
|
+
// was `carregador`
|
|
8195
|
+
charger: "phone_charger",
|
|
8196
|
+
// was `carregador`
|
|
8197
|
+
screwdriver: "screwdriver",
|
|
8198
|
+
// was `chave_fenda`
|
|
8199
|
+
house_key: "wallet",
|
|
8200
|
+
// was `chaves`
|
|
8201
|
+
keys: "wallet",
|
|
8202
|
+
// was `chaves`
|
|
8203
|
+
remote_control: "batteries",
|
|
8204
|
+
// was `controle_remoto`
|
|
8205
|
+
rope: "rope",
|
|
8206
|
+
// was `corda`
|
|
8207
|
+
electrical_tape: "duct_tape",
|
|
8208
|
+
// was `fita_isolante`
|
|
8209
|
+
insulating_tape: "duct_tape",
|
|
8210
|
+
// was `fita_isolante`
|
|
8211
|
+
flashlight: "flashlight",
|
|
8212
|
+
// was `lanterna`
|
|
8213
|
+
backpack: "backpack",
|
|
8214
|
+
// was `mochila`
|
|
8215
|
+
eyeglasses: "wallet",
|
|
8216
|
+
// was `oculos`
|
|
8217
|
+
glasses: "wallet",
|
|
8218
|
+
// was `oculos`
|
|
8219
|
+
screws: "duct_tape",
|
|
8220
|
+
// was `parafusos`
|
|
8221
|
+
batteries: "batteries",
|
|
8222
|
+
// was `pilhas`
|
|
8223
|
+
nails: "duct_tape",
|
|
8224
|
+
// was `pregos`
|
|
8225
|
+
// improvised weapons
|
|
8226
|
+
knife: "knife",
|
|
8227
|
+
// was `faca`
|
|
8228
|
+
kitchen_knife: "knife",
|
|
8229
|
+
// was `faca`
|
|
8230
|
+
stapler: "scissors",
|
|
8231
|
+
// was `grampeador`
|
|
8232
|
+
hammer: "hammer",
|
|
8233
|
+
// was `martelo`
|
|
8234
|
+
handsaw: "hammer",
|
|
8235
|
+
// was `serrote`
|
|
8236
|
+
hand_saw: "hammer",
|
|
8237
|
+
// was `serrote`
|
|
8238
|
+
scissors: "scissors",
|
|
8239
|
+
// was `tesoura`
|
|
8240
|
+
broom: "rope",
|
|
8241
|
+
// was `vassoura`
|
|
8242
|
+
// papers
|
|
8243
|
+
letter: "letter",
|
|
8244
|
+
// was `carta`
|
|
8245
|
+
bill: "bill",
|
|
8246
|
+
// was `conta`
|
|
8247
|
+
documents: "documents",
|
|
8248
|
+
// was `documento`
|
|
8249
|
+
dvd: "notebook",
|
|
8250
|
+
// was `dvd`
|
|
8251
|
+
dvds: "notebook",
|
|
8252
|
+
// was `dvd`
|
|
8253
|
+
book: "notebook",
|
|
8254
|
+
// was `livro`
|
|
8255
|
+
// trash
|
|
8256
|
+
food_packaging: "plastic_bag",
|
|
8257
|
+
// was `embalagem`
|
|
8258
|
+
packaging: "plastic_bag",
|
|
8259
|
+
// was `embalagem`
|
|
8260
|
+
paint_can: "paint_can",
|
|
8261
|
+
// was `lata_tinta`
|
|
8262
|
+
empty_can: "empty_can",
|
|
8263
|
+
// was `lata_vazia`
|
|
8264
|
+
flyer: "flyer",
|
|
8265
|
+
// was `panfleto`
|
|
8266
|
+
crumpled_paper: "crumpled_paper",
|
|
8267
|
+
// was `papel_amassado`
|
|
8268
|
+
trash_bag: "plastic_bag",
|
|
8269
|
+
// was `saco_lixo`
|
|
8270
|
+
full_trash_bag: "plastic_bag"
|
|
8271
|
+
// was `saco_lixo_cheio`
|
|
8272
|
+
});
|
|
8273
|
+
var CONTENT_BY_GROUP = Object.freeze({
|
|
8274
|
+
food: "canned_food",
|
|
8275
|
+
// was `comida`
|
|
8276
|
+
water: "water_bottle",
|
|
8277
|
+
// was `agua`
|
|
8278
|
+
medicine: "painkillers",
|
|
8279
|
+
// was `remedio`
|
|
8280
|
+
tool: "duct_tape",
|
|
8281
|
+
// was `ferramenta`
|
|
8282
|
+
improvised_weapon: "hammer",
|
|
8283
|
+
// was `arma_improvisada`
|
|
8284
|
+
clothes: "tshirt",
|
|
8285
|
+
// was `roupa`
|
|
8286
|
+
document: "documents",
|
|
8287
|
+
// was `documento`
|
|
8288
|
+
cleaning: "detergent",
|
|
8289
|
+
// was `limpeza`
|
|
8290
|
+
trash: "crumpled_paper",
|
|
8291
|
+
// was `lixo`
|
|
8292
|
+
utensil: "plate"
|
|
8293
|
+
// was `utensilio`
|
|
8294
|
+
});
|
|
8295
|
+
var CONTENT_FALLBACK = "crumpled_paper";
|
|
8296
|
+
var FROZEN_ITEMS = Object.freeze(["ice_cream", "frozen_meat"]);
|
|
8297
|
+
var DRAWER_ITEMS = Object.freeze(["underwear", "socks"]);
|
|
8298
|
+
var DRAWER_GROUPS = Object.freeze(["improvised_weapon", "tool"]);
|
|
8299
|
+
var OBJECT_SUBSTITUTES = Object.freeze({ mailbox: ["flyer", "postcard", "letter"] });
|
|
8300
|
+
var FIXTURES_OF_POINT = Object.freeze({
|
|
8301
|
+
tap: ["tap"],
|
|
8302
|
+
// was `torneira`
|
|
8303
|
+
shower: ["shower"],
|
|
8304
|
+
// was `chuveiro`
|
|
8305
|
+
flush: ["flush"],
|
|
8306
|
+
// was `descarga`
|
|
8307
|
+
tub: ["tap", "basin"],
|
|
8308
|
+
// was `tanque`
|
|
8309
|
+
machine: ["inlet"]
|
|
8310
|
+
// was `maquina`
|
|
8311
|
+
});
|
|
8312
|
+
var OWN_TYPES = Object.freeze({ lamp: true, gas_piped: true });
|
|
8313
|
+
var ADAPTER_VERSION = "0.3.0";
|
|
8314
|
+
var r3 = (n) => Math.round(n * 1e3) / 1e3;
|
|
8315
|
+
function mergeRegistry(base, extra) {
|
|
8316
|
+
const out = { ...base };
|
|
8317
|
+
if (extra) {
|
|
8318
|
+
for (const [key, value] of Object.entries(extra)) {
|
|
8319
|
+
if (value == null) delete out[key];
|
|
8320
|
+
else out[key] = value;
|
|
8321
|
+
}
|
|
8322
|
+
}
|
|
8323
|
+
return out;
|
|
8324
|
+
}
|
|
8325
|
+
var PREFERENCE = Object.freeze({
|
|
8326
|
+
fridge: (s, c) => c.frozen(s) ? ["freezer", "fridge"] : ["fridge", "freezer"],
|
|
8327
|
+
fridge_compact: (s, c) => c.frozen(s) ? ["freezer", "fridge"] : ["fridge", "freezer"],
|
|
8328
|
+
kitchen_cabinet_base: (s, c) => DRAWER_GROUPS.includes(c.group(s)) ? ["drawer", "cupboard"] : ["cupboard", "drawer"],
|
|
8329
|
+
wardrobe: (s, c) => c.drawerItem(s) ? ["drawer_1", "drawer_2", "drawer_3", "shelves"] : ["shelves", "drawer_1", "drawer_2", "drawer_3"]
|
|
8330
|
+
});
|
|
8331
|
+
function create2(options = {}) {
|
|
8332
|
+
const opts = options || {};
|
|
8333
|
+
const GI = opts.GameInteractables;
|
|
8334
|
+
const HH = opts.GameInteractablesHousehold;
|
|
8335
|
+
const locale = opts.locale || "pt-BR";
|
|
8336
|
+
const msg = createTranslator2(locale, opts.messages);
|
|
8337
|
+
if (!GI || !HH) throw new Error(msg("error.missingKit"));
|
|
8338
|
+
const region = opts.region || "br";
|
|
8339
|
+
const hh = HH.createHousehold({ locale, region });
|
|
8340
|
+
const householdTypes = new Set(hh.types.map((t) => t.id));
|
|
8341
|
+
const worlds = /* @__PURE__ */ new WeakMap();
|
|
8342
|
+
const typeMap = mergeRegistry(TYPE_MAP, opts.typeMap);
|
|
8343
|
+
const contentMap = mergeRegistry(CONTENT_MAP, opts.contentMap);
|
|
8344
|
+
const contentByGroup = mergeRegistry(CONTENT_BY_GROUP, opts.contentByGroup);
|
|
8345
|
+
const chairTables = mergeRegistry(CHAIR_TABLES, opts.chairTables);
|
|
8346
|
+
const fixturesOfPoint = mergeRegistry(FIXTURES_OF_POINT, opts.fixturesOfPoint);
|
|
8347
|
+
const substitutes = mergeRegistry(OBJECT_SUBSTITUTES, opts.substitutes);
|
|
8348
|
+
const preference = mergeRegistry(PREFERENCE, opts.preference);
|
|
8349
|
+
const ownTypes = mergeRegistry(OWN_TYPES, opts.ownTypes);
|
|
8350
|
+
const frozenItems = new Set(opts.frozenItems ?? FROZEN_ITEMS);
|
|
8351
|
+
const drawerItems = new Set(opts.drawerItems ?? DRAWER_ITEMS);
|
|
8352
|
+
const chairSide = opts.chairSide ?? DINING_CHAIR_SIDE;
|
|
8353
|
+
const contentFallback = opts.contentFallback ?? CONTENT_FALLBACK;
|
|
8354
|
+
const seedKey = (id) => {
|
|
8355
|
+
if (!opts.seedKey) return id;
|
|
8356
|
+
const key = opts.seedKey(id);
|
|
8357
|
+
return key == null ? id : key;
|
|
8358
|
+
};
|
|
8359
|
+
function conv(o) {
|
|
8360
|
+
return {
|
|
8361
|
+
x: (u) => r3(o.ox + u),
|
|
8362
|
+
z: (v) => r3(o.oz + o.inw * v),
|
|
8363
|
+
ry: (fu, fv) => r3(Math.atan2(fu, o.inw * fv)),
|
|
8364
|
+
// local offset (lx, lz) of an object with rotation ry -> offset in the world (same convention as three.js)
|
|
8365
|
+
off: (ry, lx, lz) => [Math.cos(ry) * lx + Math.sin(ry) * lz, -Math.sin(ry) * lx + Math.cos(ry) * lz]
|
|
8366
|
+
};
|
|
8367
|
+
}
|
|
8368
|
+
function floorYOf(res, o, floor) {
|
|
8369
|
+
if (floor == null || floor < 0) return o.base;
|
|
8370
|
+
const f = (res.floors || []).find((x) => x.index === floor);
|
|
8371
|
+
return r3(o.base + (f ? f.y0 : 0));
|
|
8372
|
+
}
|
|
8373
|
+
function colorOf(res, color2) {
|
|
8374
|
+
if (color2 == null) return void 0;
|
|
8375
|
+
if (typeof color2 === "number") return color2;
|
|
8376
|
+
const v = res.colors && res.colors[color2];
|
|
8377
|
+
return typeof v === "number" ? v : void 0;
|
|
8378
|
+
}
|
|
8379
|
+
function paletteOf(res) {
|
|
8380
|
+
const c = res.colors || {};
|
|
8381
|
+
const p = {};
|
|
8382
|
+
if (c.wood != null) p.wood = c.wood;
|
|
8383
|
+
if (c.fabric_main != null) p.fabric_main = c.fabric_main;
|
|
8384
|
+
if (c.fabric_accent != null) p.fabric_accent = c.fabric_accent;
|
|
8385
|
+
if (c.metal != null) p.metal = c.metal;
|
|
8386
|
+
return p;
|
|
8387
|
+
}
|
|
8388
|
+
function lightsOfState(res) {
|
|
8389
|
+
const electrical = res.utilities && res.utilities.electrical;
|
|
8390
|
+
return res.state !== "abandoned" && !!electrical && electrical.mode !== "offgrid";
|
|
8391
|
+
}
|
|
8392
|
+
function initialLight(res, popts, id, entry2) {
|
|
8393
|
+
const v = popts && popts.lightsOn;
|
|
8394
|
+
if (typeof v === "function") return !!v(id, entry2);
|
|
8395
|
+
if (typeof v === "boolean") return v;
|
|
8396
|
+
return !!(popts && popts.night) && lightsOfState(res);
|
|
8397
|
+
}
|
|
8398
|
+
const stackGroup = (s) => s.group ?? (opts.groupOf ? opts.groupOf(s.itemId) : null) ?? null;
|
|
8399
|
+
const preferenceContext = {
|
|
8400
|
+
frozen: (s) => frozenItems.has(s.itemId),
|
|
8401
|
+
group: stackGroup,
|
|
8402
|
+
drawerItem: (s) => drawerItems.has(s.itemId)
|
|
8403
|
+
};
|
|
8404
|
+
const itemOfContent = (c) => {
|
|
8405
|
+
const id = contentMap[c.itemId] || (hh.items[c.itemId] ? c.itemId : null) || contentByGroup[stackGroup(c)] || contentFallback;
|
|
8406
|
+
return hh.items[id] ? id : contentFallback;
|
|
8407
|
+
};
|
|
8408
|
+
const volume = (d) => d.size[0] * d.size[1] * d.size[2];
|
|
8409
|
+
const candidates = (id, objectType) => {
|
|
8410
|
+
const def = hh.items[id];
|
|
8411
|
+
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));
|
|
8412
|
+
return [id].concat(siblings.map((i) => i.id), substitutes[objectType] || []);
|
|
8413
|
+
};
|
|
8414
|
+
function distribute(type, probeItem, stacks) {
|
|
8415
|
+
const spec = hh.build(type, probeItem, HH.createRecorder().api);
|
|
8416
|
+
const conts = spec.containers || [];
|
|
8417
|
+
const contents = {};
|
|
8418
|
+
for (const c of conts) contents[c.id] = c.slots.map(() => null);
|
|
8419
|
+
const rejected = [];
|
|
8420
|
+
const pref = preference[type];
|
|
8421
|
+
for (const p of stacks || []) {
|
|
8422
|
+
const original = itemOfContent(p);
|
|
8423
|
+
const order = (pref ? pref(p, preferenceContext) : []).concat(conts.map((c) => c.id));
|
|
8424
|
+
let placed = false;
|
|
8425
|
+
for (const id of candidates(original, type)) {
|
|
8426
|
+
const def = hh.items[id];
|
|
8427
|
+
const qty = Math.max(1, Math.min(p.count || 1, def && def.stack || 1));
|
|
8428
|
+
for (const cid of order) {
|
|
8429
|
+
const c = conts.find((x) => x.id === cid);
|
|
8430
|
+
if (!c) continue;
|
|
8431
|
+
for (let i = 0; i < c.slots.length && !placed; i++) {
|
|
8432
|
+
if (contents[cid][i] || !GI.fitsSlot(id, c.slots[i], hh.items)) continue;
|
|
8433
|
+
const data = { source: p.itemId, group: p.group, pickable: p.pickable !== false };
|
|
8434
|
+
if (id !== original) data.substituteFor = original;
|
|
8435
|
+
contents[cid][i] = { type: id, qty, data };
|
|
8436
|
+
placed = true;
|
|
8437
|
+
}
|
|
8438
|
+
if (placed) break;
|
|
8439
|
+
}
|
|
8440
|
+
if (placed) break;
|
|
8441
|
+
}
|
|
8442
|
+
if (!placed) rejected.push(p);
|
|
8443
|
+
}
|
|
8444
|
+
return { contents, rejected };
|
|
8445
|
+
}
|
|
8446
|
+
function plan(res, popts = {}) {
|
|
8447
|
+
popts = popts || {};
|
|
8448
|
+
const o = { ox: popts.originX || 0, oz: popts.originZ || 0, inw: popts.inw || 1, base: popts.base || 0 };
|
|
8449
|
+
const K = conv(o);
|
|
8450
|
+
const floorSel = popts.floor;
|
|
8451
|
+
const externals = popts.externals !== false;
|
|
8452
|
+
const seed = popts.seed != null ? popts.seed : res.seed;
|
|
8453
|
+
const palette = paletteOf(res);
|
|
8454
|
+
const onFloor = (f, outdoor) => floorSel == null || f === floorSel || (outdoor || f < 0) && externals;
|
|
8455
|
+
const utilities = res.utilities || {};
|
|
8456
|
+
const electrical = utilities.electrical || null;
|
|
8457
|
+
const circuits = electrical && electrical.circuits || [];
|
|
8458
|
+
const contents = res.contents || {};
|
|
8459
|
+
const result = {
|
|
8460
|
+
version: ADAPTER_VERSION,
|
|
8461
|
+
template: res.template,
|
|
8462
|
+
seed: res.seed,
|
|
8463
|
+
floor: floorSel == null ? null : floorSel,
|
|
8464
|
+
items: [],
|
|
8465
|
+
outlets: [],
|
|
8466
|
+
// ids of the wall_socket entries
|
|
8467
|
+
switches: [],
|
|
8468
|
+
// ids of the wall_switch entries
|
|
8469
|
+
lights: [],
|
|
8470
|
+
// ids of the lamps (inside and outside)
|
|
8471
|
+
lanterns: [],
|
|
8472
|
+
// ids of the lanterns (lantern_lamp): kerosene/gas light, no grid
|
|
8473
|
+
canisters: [],
|
|
8474
|
+
// ids of the small camping cylinders (gas_canister)
|
|
8475
|
+
serviceEntrance: null,
|
|
8476
|
+
panel: null,
|
|
8477
|
+
// id of the electrical_panel entry (distribution board)
|
|
8478
|
+
meter: null,
|
|
8479
|
+
// id of the power_meter entry (meter box on the facade or the pillar)
|
|
8480
|
+
conduits: [],
|
|
8481
|
+
cylinders: [],
|
|
8482
|
+
// { id, stove, place }
|
|
8483
|
+
stoves: [],
|
|
8484
|
+
fixtures: [],
|
|
8485
|
+
// { object, fixture, global, point, pointKind }
|
|
8486
|
+
points: {},
|
|
8487
|
+
// global fixture -> point of the plumbing
|
|
8488
|
+
mapped: [],
|
|
8489
|
+
// ids of furniture of the plan that became objects of the kit (the renderer does not need to draw them)
|
|
8490
|
+
chairs: [],
|
|
8491
|
+
// ids of the chairs the adapter put around the tables (origin = the table, which the renderer keeps drawing)
|
|
8492
|
+
unmapped: {},
|
|
8493
|
+
// "category/type" -> count
|
|
8494
|
+
discarded: 0,
|
|
8495
|
+
// stacks of content that fit no slot
|
|
8496
|
+
warnings: [],
|
|
8497
|
+
origin: { x: o.ox, z: o.oz, inw: o.inw, base: o.base }
|
|
8498
|
+
};
|
|
8499
|
+
const byOrigin = /* @__PURE__ */ new Map();
|
|
8500
|
+
const seedOf2 = (id) => GI.hashString(String(seed) + ":" + seedKey(id));
|
|
8501
|
+
function push(e) {
|
|
8502
|
+
result.items.push(e);
|
|
8503
|
+
if (!byOrigin.has(e.origin)) byOrigin.set(e.origin, []);
|
|
8504
|
+
byOrigin.get(e.origin).push(e);
|
|
8505
|
+
return e;
|
|
8506
|
+
}
|
|
8507
|
+
function baseItem(m) {
|
|
8508
|
+
const item = {
|
|
8509
|
+
x: K.x(m.x),
|
|
8510
|
+
z: K.z(m.z),
|
|
8511
|
+
ry: m.frontU != null ? K.ry(m.frontU, m.frontV) : r3(m.ry || 0),
|
|
8512
|
+
w: m.w,
|
|
8513
|
+
d: m.d,
|
|
8514
|
+
h: m.h,
|
|
8515
|
+
y: m.y || 0,
|
|
8516
|
+
seed: seedOf2(m.id),
|
|
8517
|
+
palette
|
|
8518
|
+
};
|
|
8519
|
+
const color2 = colorOf(res, m.color);
|
|
8520
|
+
if (color2 != null) item.color = color2;
|
|
8521
|
+
return item;
|
|
8522
|
+
}
|
|
8523
|
+
function entry2(id, type, item, origin, floor, extra) {
|
|
8524
|
+
return Object.assign({ id, type, item, origin, floor, floorY: floorYOf(res, o, floor), connections: {} }, extra || {});
|
|
8525
|
+
}
|
|
8526
|
+
function store(targets, stacks) {
|
|
8527
|
+
let rest = stacks || [];
|
|
8528
|
+
for (const [type, item] of targets) {
|
|
8529
|
+
const d = distribute(type, item, rest);
|
|
8530
|
+
item.contents = Object.assign(item.contents || {}, d.contents);
|
|
8531
|
+
rest = d.rejected;
|
|
8532
|
+
}
|
|
8533
|
+
result.discarded += rest.length;
|
|
8534
|
+
}
|
|
8535
|
+
const hidden = [];
|
|
8536
|
+
function distRect(c, x, z) {
|
|
8537
|
+
const dx = x - c.item.x;
|
|
8538
|
+
const dz = z - c.item.z;
|
|
8539
|
+
const s = Math.sin(c.item.ry);
|
|
8540
|
+
const co = Math.cos(c.item.ry);
|
|
8541
|
+
const lx = dx * co - dz * s;
|
|
8542
|
+
const lz = dx * s + dz * co;
|
|
8543
|
+
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));
|
|
8544
|
+
}
|
|
8545
|
+
function hideCylinders() {
|
|
8546
|
+
for (const b of hidden) {
|
|
8547
|
+
let target = null;
|
|
8548
|
+
for (const c2 of result.items) {
|
|
8549
|
+
if (c2.type !== "kitchen_cabinet_base" || c2.floor !== b.floor) continue;
|
|
8550
|
+
const dist = distRect(c2, b.item.x, b.item.z);
|
|
8551
|
+
if (!target || dist < target.dist) target = { c: c2, dist };
|
|
8552
|
+
}
|
|
8553
|
+
if (!target) {
|
|
8554
|
+
result.warnings.push(msg("warn.cylinderNoCabinet", { id: b.id }));
|
|
8555
|
+
continue;
|
|
8556
|
+
}
|
|
8557
|
+
const c = target.c;
|
|
8558
|
+
const spec = hh.build(c.type, c.item, HH.createRecorder().api);
|
|
8559
|
+
const sn = Math.sin(c.item.ry);
|
|
8560
|
+
const cs = Math.cos(c.item.ry);
|
|
8561
|
+
let door = null;
|
|
8562
|
+
for (const it of spec.interactions || []) {
|
|
8563
|
+
const pt = it.action && it.action.do === "toggle_part" ? (spec.parts || []).find((q) => q.id === it.action.part) : null;
|
|
8564
|
+
if (!pt || pt.motion.kind !== "hinge") continue;
|
|
8565
|
+
const wx = c.item.x + it.pos[0] * cs + it.pos[2] * sn;
|
|
8566
|
+
const wz = c.item.z - it.pos[0] * sn + it.pos[2] * cs;
|
|
8567
|
+
const dist = Math.hypot(wx - b.item.x, wz - b.item.z);
|
|
8568
|
+
if (!door || dist < door.dist) door = { id: pt.id, dist };
|
|
8569
|
+
}
|
|
8570
|
+
if (!door) {
|
|
8571
|
+
result.warnings.push(msg("warn.cabinetNoDoor", { cabinet: c.id, id: b.id }));
|
|
8572
|
+
continue;
|
|
8573
|
+
}
|
|
8574
|
+
b.item.requires = { object: c.id, part: door.id };
|
|
8575
|
+
}
|
|
8576
|
+
}
|
|
8577
|
+
function initialLanternLight(id, e) {
|
|
8578
|
+
const v = popts.lightsOn;
|
|
8579
|
+
if (typeof v === "function") return !!v(id, e);
|
|
8580
|
+
if (typeof v === "boolean") return v;
|
|
8581
|
+
return !!popts.night && res.state !== "abandoned";
|
|
8582
|
+
}
|
|
8583
|
+
const chimney = res.structureExtras && res.structureExtras.chimney || null;
|
|
8584
|
+
const firstOfType = (type) => (res.items || []).find((m) => typeMap[m.type] && typeMap[m.type].type === type);
|
|
8585
|
+
function chimneyOf(m, role) {
|
|
8586
|
+
if (!chimney) return null;
|
|
8587
|
+
const named = role === "fireplace" ? chimney.fireplace : chimney.stove;
|
|
8588
|
+
if (named != null) return named === m.id ? chimney : null;
|
|
8589
|
+
const first = firstOfType(role === "fireplace" ? "fireplace" : "wood_stove");
|
|
8590
|
+
return chimney.kind === (role === "fireplace" ? "fireplace" : "flue") && first && first.id === m.id ? chimney : null;
|
|
8591
|
+
}
|
|
8592
|
+
const chimneyHeight = (ch) => ch.height != null ? ch.height : ch.top;
|
|
8593
|
+
const campStove = firstOfType("camp_stove");
|
|
8594
|
+
const campCylinder = firstOfType("gas_canister");
|
|
8595
|
+
function planFireplace(m, e, item) {
|
|
8596
|
+
const def = hh.types.find((t) => t.id === "fireplace");
|
|
8597
|
+
const lack = (def.d - m.d) / 2;
|
|
8598
|
+
item.x = r3(item.x + Math.sin(item.ry) * lack);
|
|
8599
|
+
item.z = r3(item.z + Math.cos(item.ry) * lack);
|
|
8600
|
+
const room = (res.rooms || []).find((c) => c.id === m.room && c.floor === m.floor);
|
|
8601
|
+
const f = (res.floors || []).find((x) => x.index === m.floor);
|
|
8602
|
+
item.h = r3(room && room.ceiling || f && f.ceiling || 2.6);
|
|
8603
|
+
const ch = chimneyOf(m, "fireplace");
|
|
8604
|
+
if (ch) {
|
|
8605
|
+
if (ch.material === "stone") item.variant = "stone";
|
|
8606
|
+
const cx = K.x((ch.aabb[0] + ch.aabb[2]) / 2);
|
|
8607
|
+
const cz = K.z((ch.aabb[1] + ch.aabb[3]) / 2);
|
|
8608
|
+
e.connections.chimneyTop = [cx, r3(o.base + chimneyHeight(ch)), cz];
|
|
8609
|
+
}
|
|
8610
|
+
}
|
|
8611
|
+
function planSimple(m, map) {
|
|
8612
|
+
const item = baseItem(m);
|
|
8613
|
+
const dim = map.dim === "none" ? "" : map.dim || "wdh";
|
|
8614
|
+
for (const k of ["w", "d", "h"]) if (dim.indexOf(k) < 0) delete item[k];
|
|
8615
|
+
if (map.dim === "none") delete item.y;
|
|
8616
|
+
if (map.variant) item.variant = map.variant;
|
|
8617
|
+
if (map.type === "tv") item.d = Math.max(item.d || 0, 0.2);
|
|
8618
|
+
const e = entry2(m.id, map.type, item, m.id, m.floor);
|
|
8619
|
+
if (contents[m.id]) store([[map.type, item]], contents[m.id]);
|
|
8620
|
+
if (m.outlet) e.connections.outlet = m.outlet;
|
|
8621
|
+
if (map.type === "shower") e.connections.shower = m.showerHeater || { electric: false };
|
|
8622
|
+
if (map.type === "stove") {
|
|
8623
|
+
result.stoves.push(e.id);
|
|
8624
|
+
e.connections.gas = m.gas || "cylinder";
|
|
8625
|
+
e.connections.cylinder = m.cylinder || null;
|
|
8626
|
+
}
|
|
8627
|
+
if (map.type === "gas_bottle") result.cylinders.push({ id: e.id, stove: m.link || null, place: m.placement || null });
|
|
8628
|
+
if (map.type === "gas_canister") {
|
|
8629
|
+
result.canisters.push(e.id);
|
|
8630
|
+
if (campCylinder && campCylinder.id === m.id && campStove) result.cylinders.push({ id: e.id, stove: campStove.id, place: null });
|
|
8631
|
+
}
|
|
8632
|
+
if (map.type === "wood_stove") {
|
|
8633
|
+
const ch = chimneyOf(m, "stove");
|
|
8634
|
+
if (ch && chimneyHeight(ch)) {
|
|
8635
|
+
const f = (res.floors || []).find((x) => x.index === m.floor);
|
|
8636
|
+
const high = r3(chimneyHeight(ch) - (f ? f.y0 : 0) - (m.y || 0));
|
|
8637
|
+
item.h = high;
|
|
8638
|
+
item.flueHeight = high;
|
|
8639
|
+
}
|
|
8640
|
+
}
|
|
8641
|
+
if (map.type === "fireplace") planFireplace(m, e, item);
|
|
8642
|
+
if (map.type === "lantern_lamp") {
|
|
8643
|
+
e.lit = initialLanternLight(m.id, e);
|
|
8644
|
+
item.on = e.lit;
|
|
8645
|
+
result.lanterns.push(e.id);
|
|
8646
|
+
}
|
|
8647
|
+
if (map.type === "gas_bottle" && m.placement === "under_counter") hidden.push(e);
|
|
8648
|
+
push(e);
|
|
8649
|
+
}
|
|
8650
|
+
function planCompound(m, kind) {
|
|
8651
|
+
const ry = m.frontU != null ? K.ry(m.frontU, m.frontV) : r3(m.ry || 0);
|
|
8652
|
+
const cx = K.x(m.x);
|
|
8653
|
+
const cz = K.z(m.z);
|
|
8654
|
+
const part = (id, type, w, d, h, y, lx, lz) => {
|
|
8655
|
+
const [dx, dz] = K.off(ry, lx, lz);
|
|
8656
|
+
const item = baseItem(m);
|
|
8657
|
+
item.x = r3(cx + dx);
|
|
8658
|
+
item.z = r3(cz + dz);
|
|
8659
|
+
item.ry = ry;
|
|
8660
|
+
item.w = r3(w);
|
|
8661
|
+
item.d = r3(d);
|
|
8662
|
+
item.h = r3(h);
|
|
8663
|
+
item.y = y;
|
|
8664
|
+
item.seed = seedOf2(id);
|
|
8665
|
+
return entry2(id, type, item, m.id, m.floor);
|
|
8666
|
+
};
|
|
8667
|
+
const list2 = [];
|
|
8668
|
+
const overhead = contents[m.id + "#overhead"];
|
|
8669
|
+
if (kind === "rustic_sink") {
|
|
8670
|
+
const dd = Math.max(m.d, 0.56);
|
|
8671
|
+
const basin = part(m.id, "sink_kitchen", m.w, dd, m.h + 0.3, 0, 0, -(dd - m.d) / 2);
|
|
8672
|
+
list2.push(basin);
|
|
8673
|
+
const over = overhead || [];
|
|
8674
|
+
if (m.overhead !== false && over.length) {
|
|
8675
|
+
const wall = part(m.id + "#overhead", "kitchen_cabinet_wall", m.w, 0.35, 0.6, 1.55, 0, -(m.d / 2) + 0.175);
|
|
8676
|
+
store([["kitchen_cabinet_wall", wall.item]], over);
|
|
8677
|
+
list2.push(wall);
|
|
8678
|
+
}
|
|
8679
|
+
if (contents[m.id]) store([["sink_kitchen", basin.item]], contents[m.id]);
|
|
8680
|
+
if (m.outlet) basin.connections.outlet = m.outlet;
|
|
8681
|
+
} else if (kind === "sink") {
|
|
8682
|
+
const width = m.w;
|
|
8683
|
+
const basinW = width >= 1.5 ? 1 : Math.max(0.6, Math.min(0.8, width - 0.3));
|
|
8684
|
+
const rest = r3(width - basinW);
|
|
8685
|
+
const left = seedOf2(m.id) % 2 === 0;
|
|
8686
|
+
const sink = part(m.id, "sink_kitchen", basinW, m.d, m.h + 0.25, 0, left ? -(width / 2) + basinW / 2 : width / 2 - basinW / 2, 0);
|
|
8687
|
+
list2.push(sink);
|
|
8688
|
+
let cabinet = null;
|
|
8689
|
+
if (rest >= 0.35) {
|
|
8690
|
+
cabinet = part(m.id + "#cabinet", "kitchen_cabinet_base", rest, m.d, m.h, 0, left ? width / 2 - rest / 2 : -(width / 2) + rest / 2, 0);
|
|
8691
|
+
list2.push(cabinet);
|
|
8692
|
+
}
|
|
8693
|
+
if (contents[m.id]) store(cabinet ? [["kitchen_cabinet_base", cabinet.item], ["sink_kitchen", sink.item]] : [["sink_kitchen", sink.item]], contents[m.id]);
|
|
8694
|
+
if (m.overhead !== false) {
|
|
8695
|
+
const wall = part(m.id + "#overhead", "kitchen_cabinet_wall", width, 0.35, 0.6, 1.55, 0, -(m.d / 2) + 0.175);
|
|
8696
|
+
store([["kitchen_cabinet_wall", wall.item]], overhead || []);
|
|
8697
|
+
list2.push(wall);
|
|
8698
|
+
}
|
|
8699
|
+
if (m.outlet) sink.connections.outlet = m.outlet;
|
|
8700
|
+
} else {
|
|
8701
|
+
const basin = part(m.id, "sink_bathroom", m.w, m.d, m.h + 0.2, 0, 0, 0);
|
|
8702
|
+
list2.push(basin);
|
|
8703
|
+
if (contents[m.id]) {
|
|
8704
|
+
if (contents[m.id].length) {
|
|
8705
|
+
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);
|
|
8706
|
+
list2.push(cabinet);
|
|
8707
|
+
store([["bathroom_cabinet", cabinet.item], ["sink_bathroom", basin.item]], contents[m.id]);
|
|
8708
|
+
} else {
|
|
8709
|
+
store([["sink_bathroom", basin.item]], []);
|
|
8710
|
+
}
|
|
8711
|
+
}
|
|
8712
|
+
}
|
|
8713
|
+
for (const e of list2) push(e);
|
|
8714
|
+
}
|
|
8715
|
+
function circuitOfLight(id) {
|
|
8716
|
+
const direct = circuits.find((c) => (c.lamps || []).indexOf(id) >= 0);
|
|
8717
|
+
if (direct) return direct.id;
|
|
8718
|
+
const sw = (electrical && electrical.switches || []).find((s) => (s.controls || []).indexOf(id) >= 0);
|
|
8719
|
+
const viaSwitch = sw && circuits.find((c) => (c.switches || []).indexOf(sw.id) >= 0);
|
|
8720
|
+
return viaSwitch ? viaSwitch.id : "standalone_circuit";
|
|
8721
|
+
}
|
|
8722
|
+
function planLamp(m, map) {
|
|
8723
|
+
const item = baseItem(m);
|
|
8724
|
+
delete item.palette;
|
|
8725
|
+
const e = entry2(m.id, "lamp", item, m.id, m.floor, { watts: map.watts });
|
|
8726
|
+
e.connections.circuit = circuitOfLight(m.id);
|
|
8727
|
+
e.lit = initialLight(res, popts, m.id, e);
|
|
8728
|
+
push(e);
|
|
8729
|
+
result.lights.push(e.id);
|
|
8730
|
+
}
|
|
8731
|
+
for (const m of res.items || []) {
|
|
8732
|
+
if (!onFloor(m.floor, m.outdoor)) continue;
|
|
8733
|
+
const map = typeMap[m.type];
|
|
8734
|
+
if (!map) {
|
|
8735
|
+
const k = m.category + "/" + m.type;
|
|
8736
|
+
result.unmapped[k] = (result.unmapped[k] || 0) + 1;
|
|
8737
|
+
continue;
|
|
8738
|
+
}
|
|
8739
|
+
result.mapped.push(m.id);
|
|
8740
|
+
if (map.type === "lamp") planLamp(m, map);
|
|
8741
|
+
else if (map.compound) planCompound(m, map.compound);
|
|
8742
|
+
else planSimple(m, map);
|
|
8743
|
+
}
|
|
8744
|
+
result.chairs = [];
|
|
8745
|
+
if (opts.chairs !== false && popts.chairs !== false) {
|
|
8746
|
+
const blocked = blockedOf(res, { originX: o.ox, originZ: o.oz, inw: o.inw });
|
|
8747
|
+
const floorKind = (q) => !q.decor && !q.flat && (q.y || 0) < 0.9 && q.aabb;
|
|
8748
|
+
const placed = [];
|
|
8749
|
+
const free = (m, cu, cv, half) => {
|
|
8750
|
+
const a = [cu - half + 0.03, cv - half + 0.03, cu + half - 0.03, cv + half - 0.03];
|
|
8751
|
+
for (const [dx, dz] of [[-1, -1], [1, -1], [-1, 1], [1, 1], [0, 0]]) if (blocked(K.x(cu + dx * half * 0.9), K.z(cv + dz * half * 0.9), m.floor)) return false;
|
|
8752
|
+
for (const q of res.items || []) {
|
|
8753
|
+
if (q === m || !floorKind(q) || q.floor !== m.floor && !(q.outdoor && m.outdoor)) continue;
|
|
8754
|
+
if (a[0] < q.aabb[2] && a[2] > q.aabb[0] && a[1] < q.aabb[3] && a[3] > q.aabb[1]) return false;
|
|
8755
|
+
}
|
|
8756
|
+
for (const c of placed) if (a[0] < c[2] && a[2] > c[0] && a[1] < c[3] && a[3] > c[1] && c[4] === m.floor) return false;
|
|
8757
|
+
placed.push([a[0], a[1], a[2], a[3], m.floor]);
|
|
8758
|
+
return true;
|
|
8759
|
+
};
|
|
8760
|
+
for (const m of res.items || []) {
|
|
8761
|
+
const mode = chairTables[m.type];
|
|
8762
|
+
if (!mode || !onFloor(m.floor, m.outdoor) || m.frontU == null) continue;
|
|
8763
|
+
const f = [m.frontU, m.frontV];
|
|
8764
|
+
const pp = [-m.frontV, m.frontU];
|
|
8765
|
+
const seats = [];
|
|
8766
|
+
if (mode === "dining") {
|
|
8767
|
+
const n = Math.max(1, Math.min(3, Math.floor((m.w - 0.1) / 0.55)));
|
|
8768
|
+
for (const side of [1, -1]) {
|
|
8769
|
+
for (let i = 0; i < n; i++) seats.push([(i - (n - 1) / 2) * (m.w / n), side * (m.d / 2 + 0.17), [-side * f[0], -side * f[1]]]);
|
|
8770
|
+
}
|
|
8771
|
+
if (m.w >= 1.6) for (const side of [1, -1]) seats.push([side * (m.w / 2 + 0.17), 0, [-side * pp[0], -side * pp[1]]]);
|
|
8772
|
+
} else {
|
|
8773
|
+
seats.push([0, m.d / 2 + 0.2, [-f[0], -f[1]]]);
|
|
8774
|
+
}
|
|
8775
|
+
seats.forEach((lg, i) => {
|
|
8776
|
+
const cu = r3(m.x + pp[0] * lg[0] + f[0] * lg[1]);
|
|
8777
|
+
const cv = r3(m.z + pp[1] * lg[0] + f[1] * lg[1]);
|
|
8778
|
+
const half = mode === "dining" ? chairSide / 2 : 0.3;
|
|
8779
|
+
if (!free(m, cu, cv, half)) return;
|
|
8780
|
+
const id = m.id + "#chair" + (i + 1);
|
|
8781
|
+
const item = { x: K.x(cu), z: K.z(cv), ry: K.ry(lg[2][0], lg[2][1]), seed: seedOf2(id), palette };
|
|
8782
|
+
if (mode !== "dining") {
|
|
8783
|
+
item.w = 0.6;
|
|
8784
|
+
item.d = 0.6;
|
|
8785
|
+
item.h = 0.95;
|
|
8786
|
+
}
|
|
8787
|
+
const e = push(entry2(id, mode === "dining" ? "dining_chair" : "armchair", item, m.id, m.floor));
|
|
8788
|
+
result.chairs.push(e.id);
|
|
8789
|
+
});
|
|
8790
|
+
}
|
|
8791
|
+
}
|
|
8792
|
+
function conduit(id, pts, floor) {
|
|
8793
|
+
const x0 = K.x(pts[0][0]);
|
|
8794
|
+
const z0 = K.z(pts[0][1]);
|
|
8795
|
+
const item = {
|
|
8796
|
+
x: x0,
|
|
8797
|
+
z: z0,
|
|
8798
|
+
ry: 0,
|
|
8799
|
+
seed: seedOf2(id),
|
|
8800
|
+
// the points of the plan already have the absolute y of the world: the object stays on the base ground and not on the floor of the storey
|
|
8801
|
+
points: pts.map((p) => [r3(K.x(p[0]) - x0), p[2], r3(K.z(p[1]) - z0)])
|
|
8802
|
+
};
|
|
8803
|
+
const e = entry2(id, "conduit_run", item, id, floor);
|
|
8804
|
+
e.floorY = o.base;
|
|
8805
|
+
push(e);
|
|
8806
|
+
result.conduits.push(e.id);
|
|
8807
|
+
}
|
|
8808
|
+
if (electrical) {
|
|
8809
|
+
for (const l of electrical.outdoorLamps || []) {
|
|
8810
|
+
if (!onFloor(-1, true)) continue;
|
|
8811
|
+
const e = entry2(l.id, "lamp", { x: K.x(l.u), z: K.z(l.v), ry: 0, y: l.y, seed: seedOf2(l.id) }, l.id, -1, { watts: 15 });
|
|
8812
|
+
e.connections.circuit = circuitOfLight(l.id);
|
|
8813
|
+
e.lit = initialLight(res, popts, l.id, e);
|
|
8814
|
+
push(e);
|
|
8815
|
+
result.lights.push(e.id);
|
|
8816
|
+
}
|
|
8817
|
+
for (const t of electrical.outlets || []) {
|
|
8818
|
+
if (!onFloor(t.floor, false)) continue;
|
|
8819
|
+
const c = circuits.find((x) => (x.outlets || []).indexOf(t.id) >= 0);
|
|
8820
|
+
const item = { x: K.x(t.u), z: K.z(t.v), ry: K.ry(t.frontU, t.frontV), y: t.y, seed: seedOf2(t.id) };
|
|
8821
|
+
if (c) item.circuit = c.id;
|
|
8822
|
+
const e = entry2(t.id, "wall_socket", item, t.id, t.floor);
|
|
8823
|
+
e.connections.circuit = c ? c.id : null;
|
|
8824
|
+
push(e);
|
|
8825
|
+
result.outlets.push(e.id);
|
|
8826
|
+
}
|
|
8827
|
+
const lights = new Set(result.lights);
|
|
8828
|
+
for (const s of electrical.switches || []) {
|
|
8829
|
+
if (!onFloor(s.floor, false)) continue;
|
|
8830
|
+
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) };
|
|
8831
|
+
item.controls = (s.controls || []).map((id) => id + ":lamp");
|
|
8832
|
+
const e = entry2(s.id, "wall_switch", item, s.id, s.floor);
|
|
8833
|
+
e.connections.controls = (s.controls || []).slice();
|
|
8834
|
+
e.lit = e.connections.controls.some((id) => (result.items.find((x) => x.id === id) || {}).lit === true);
|
|
8835
|
+
if (floorSel == null) {
|
|
8836
|
+
for (const id of s.controls || []) if (!lights.has(id)) result.warnings.push(msg("warn.switchUnknownLamp", { id: s.id, lamp: id }));
|
|
8837
|
+
}
|
|
8838
|
+
push(e);
|
|
8839
|
+
result.switches.push(e.id);
|
|
8840
|
+
}
|
|
8841
|
+
const ee = electrical.serviceEntrance;
|
|
8842
|
+
if (ee && ee.pole && onFloor(-1, true)) {
|
|
8843
|
+
const drop = ee.drop || [];
|
|
8844
|
+
const end = drop.length ? drop[drop.length - 1] : [ee.pole.u, ee.pole.v, 2.6];
|
|
8845
|
+
const px = K.x(ee.pole.u);
|
|
8846
|
+
const pz = K.z(ee.pole.v);
|
|
8847
|
+
const item = {
|
|
8848
|
+
x: px,
|
|
8849
|
+
z: pz,
|
|
8850
|
+
ry: 0,
|
|
8851
|
+
h: ee.pole.h,
|
|
8852
|
+
seed: seedOf2("service_entrance"),
|
|
8853
|
+
// point where the drop reaches the house, in local coordinates of the pole (absolute y)
|
|
8854
|
+
house: [r3(K.x(end[0]) - px), end[2], r3(K.z(end[1]) - pz)]
|
|
8855
|
+
};
|
|
8856
|
+
if (ee.tap || electrical.mode === "tap") item.variant = "gato";
|
|
8857
|
+
const e = entry2("service_entrance", "service_entrance", item, "service_entrance", -1);
|
|
8858
|
+
push(e);
|
|
8859
|
+
result.serviceEntrance = e.id;
|
|
8860
|
+
if (ee.descent && ee.descent.length > 1) conduit("conduit_descent", ee.descent, -1);
|
|
8861
|
+
}
|
|
8862
|
+
const q = electrical.panel;
|
|
8863
|
+
if (q && onFloor(q.floor, false)) {
|
|
8864
|
+
const hdq = 0.06;
|
|
8865
|
+
const ryq = K.ry(q.frontU, q.frontV);
|
|
8866
|
+
const item = {
|
|
8867
|
+
x: r3(K.x(q.u) + Math.sin(ryq) * hdq),
|
|
8868
|
+
z: r3(K.z(q.v) + Math.cos(ryq) * hdq),
|
|
8869
|
+
ry: ryq,
|
|
8870
|
+
y: q.y,
|
|
8871
|
+
seed: seedOf2("panel"),
|
|
8872
|
+
circuits: circuits.map((c) => ({ id: c.id, label: c.room }))
|
|
8873
|
+
};
|
|
8874
|
+
if (!item.circuits.length) delete item.circuits;
|
|
8875
|
+
const e = entry2("panel", "electrical_panel", item, "panel", q.floor);
|
|
8876
|
+
push(e);
|
|
8877
|
+
result.panel = e.id;
|
|
8878
|
+
}
|
|
8879
|
+
const med = ee && ee.meter;
|
|
8880
|
+
if (med && onFloor(-1, true)) {
|
|
8881
|
+
const hdm = 0.08;
|
|
8882
|
+
const item = { x: K.x(med.u), z: r3(K.z(med.v) - o.inw * hdm), ry: K.ry(0, -1), y: med.y, seed: seedOf2("meter") };
|
|
8883
|
+
const e = entry2("meter", "power_meter", item, "meter", -1);
|
|
8884
|
+
push(e);
|
|
8885
|
+
result.meter = e.id;
|
|
8886
|
+
}
|
|
8887
|
+
for (const ed of electrical.conduits || []) {
|
|
8888
|
+
if (!ed.exposed || !ed.points || ed.points.length < 2) continue;
|
|
8889
|
+
const circ = circuits.find((c) => c.id === ed.circuit);
|
|
8890
|
+
const floor = circ ? circ.floor : 0;
|
|
8891
|
+
if (!onFloor(floor, false)) continue;
|
|
8892
|
+
conduit(ed.id, ed.points, floor);
|
|
8893
|
+
}
|
|
8894
|
+
}
|
|
8895
|
+
const piped = result.items.filter((e) => e.type === "stove" && e.connections.gas === "piped");
|
|
8896
|
+
if (piped.length) {
|
|
8897
|
+
const med = utilities.gas && utilities.gas.meter;
|
|
8898
|
+
const ref = med ? { x: K.x(med.u), z: K.z(med.v), y: med.y || 1 } : { x: piped[0].item.x, z: piped[0].item.z, y: 0.3 };
|
|
8899
|
+
const e = entry2("piped_gas", "gas_piped", { x: ref.x, z: ref.z, ry: 0, y: ref.y, seed: seedOf2("piped_gas") }, "piped_gas", piped[0].floor);
|
|
8900
|
+
e.floorY = o.base;
|
|
8901
|
+
push(e);
|
|
8902
|
+
for (const f of piped) f.connections.fuel = "piped_gas:gas";
|
|
8903
|
+
}
|
|
8904
|
+
for (const b of result.cylinders) {
|
|
8905
|
+
const stove = result.items.find((e) => e.id === b.stove);
|
|
8906
|
+
if (stove) stove.connections.fuel = b.id + ":gas";
|
|
8907
|
+
}
|
|
8908
|
+
const plumbing = utilities.plumbing;
|
|
8909
|
+
if (plumbing) {
|
|
8910
|
+
const isCabinet = (t) => t === "kitchen_cabinet_base" || t === "kitchen_cabinet_wall" || t === "bathroom_cabinet";
|
|
8911
|
+
for (const p of plumbing.points || []) {
|
|
8912
|
+
const target = (byOrigin.get(p.item) || []).filter((e) => !isCabinet(e.type))[0];
|
|
8913
|
+
if (!target) {
|
|
8914
|
+
if (floorSel == null) result.warnings.push(msg("warn.pointNoObject", { id: p.id, kind: p.kind, item: p.item }));
|
|
8915
|
+
continue;
|
|
8916
|
+
}
|
|
8917
|
+
target.point = p.id;
|
|
8918
|
+
target.connections.flowLpm = p.flowLpm;
|
|
8919
|
+
for (const f of fixturesOfPoint[p.kind] || []) {
|
|
8920
|
+
result.fixtures.push({ object: target.id, fixture: f, global: target.id + ":" + f, point: p.id, pointKind: p.kind });
|
|
8921
|
+
result.points[target.id + ":" + f] = p.id;
|
|
8922
|
+
}
|
|
8923
|
+
}
|
|
8924
|
+
}
|
|
8925
|
+
hideCylinders();
|
|
8926
|
+
return result;
|
|
8927
|
+
}
|
|
8928
|
+
function ownSpec(entry2) {
|
|
8929
|
+
if (entry2.type === "lamp") {
|
|
8930
|
+
const dev = { id: "lamp", kind: "lamp", watts: entry2.watts || 15, on: !!entry2.lit };
|
|
8931
|
+
if (entry2.connections.circuit) dev.circuit = entry2.connections.circuit;
|
|
8932
|
+
return { type: "lamp", devices: [dev] };
|
|
8933
|
+
}
|
|
8934
|
+
if (entry2.type === "gas_piped") return { type: "gas_piped", fuels: [{ id: "gas", kind: "gas", capacity: 1e3, level: 1e3 }] };
|
|
8935
|
+
throw new Error(msg("error.unknownOwnType", { type: entry2.type }));
|
|
8936
|
+
}
|
|
8937
|
+
function connect(entry2, spec) {
|
|
8938
|
+
const L = entry2.connections || {};
|
|
8939
|
+
if (entry2.type === "wall_switch") {
|
|
8940
|
+
for (const p of spec.parts || []) if (p.id === "rocker") p.t0 = entry2.lit ? 1 : 0;
|
|
8941
|
+
}
|
|
8942
|
+
if (entry2.type !== "shower") {
|
|
8943
|
+
for (const dv of spec.devices || []) if (L.outlet && dv.socket === "auto") dv.socket = L.outlet + ":socket";
|
|
8944
|
+
} else {
|
|
8945
|
+
const sh = L.shower || {};
|
|
8946
|
+
const heater = (spec.devices || []).find((d) => d.id === "heater");
|
|
8947
|
+
if (heater && sh.electric === false) {
|
|
8948
|
+
spec.devices = spec.devices.filter((d) => d !== heater);
|
|
8949
|
+
for (const f of spec.fixtures || []) if (f.heater === "heater") delete f.heater;
|
|
8950
|
+
} else if (heater) {
|
|
8951
|
+
if (sh.powerW) heater.watts = sh.powerW;
|
|
8952
|
+
if (L.outletCircuit) heater.circuit = L.outletCircuit;
|
|
8953
|
+
}
|
|
8954
|
+
}
|
|
8955
|
+
if ((entry2.type === "stove" || entry2.type === "camp_stove") && L.fuel) {
|
|
8956
|
+
for (const b of spec.burners || []) if (b.fuel === "auto") b.fuel = L.fuel;
|
|
8957
|
+
}
|
|
8958
|
+
if (entry2.type === "fireplace" && L.chimneyTop) {
|
|
8959
|
+
const it = entry2.item;
|
|
8960
|
+
const dx = L.chimneyTop[0] - it.x;
|
|
8961
|
+
const dz = L.chimneyTop[2] - it.z;
|
|
8962
|
+
const lx = Math.cos(it.ry) * dx - Math.sin(it.ry) * dz;
|
|
8963
|
+
const lz = Math.sin(it.ry) * dx + Math.cos(it.ry) * dz;
|
|
8964
|
+
for (const em of spec.emitters || []) if (em.kind === "smoke") em.pos = [r3(lx), r3(L.chimneyTop[1] - entry2.floorY + 0.02), r3(lz)];
|
|
8965
|
+
}
|
|
8966
|
+
if (entry2.type === "washing_machine" && entry2.point) {
|
|
8967
|
+
spec.fixtures = spec.fixtures || [];
|
|
8968
|
+
const inlet = spec.fixtures.find((f) => f.id === "inlet");
|
|
8969
|
+
if (inlet) {
|
|
8970
|
+
if (L.flowLpm) inlet.flow = L.flowLpm;
|
|
8971
|
+
inlet.tank = "auto";
|
|
8972
|
+
} else {
|
|
8973
|
+
spec.fixtures.push({ id: "inlet", kind: "hose", outlet: [0, 0.3, -(entry2.item.d || 0.6) / 2], flow: L.flowLpm || 8, tank: "auto" });
|
|
8974
|
+
}
|
|
8975
|
+
}
|
|
8976
|
+
return spec;
|
|
8977
|
+
}
|
|
8978
|
+
function createWorld(res, copts = {}) {
|
|
8979
|
+
copts = copts || {};
|
|
8980
|
+
const info = { points: /* @__PURE__ */ new Map(), water: copts.water || null, lightsOn: copts.lightsOn };
|
|
8981
|
+
const electrical = res.utilities && res.utilities.electrical;
|
|
8982
|
+
const world = GI.createWorld({
|
|
8983
|
+
locale,
|
|
8984
|
+
strings: hh.strings,
|
|
8985
|
+
items: hh.items,
|
|
8986
|
+
loot: hh.loot,
|
|
8987
|
+
seed: copts.seed != null ? copts.seed : res.seed,
|
|
8988
|
+
// no grid: the cabin and the off-grid campsite have no service entrance, sockets or electric lamps (lanterns do not need a grid)
|
|
8989
|
+
grid: copts.grid != null ? !!copts.grid : !!electrical && electrical.mode !== "offgrid",
|
|
8990
|
+
onEvent: copts.onEvent,
|
|
8991
|
+
canInteract: copts.canInteract,
|
|
8992
|
+
waterSupply: {
|
|
8993
|
+
draw(fixtureId, l) {
|
|
8994
|
+
if (!info.water) return l;
|
|
8995
|
+
const point = info.points.get(fixtureId);
|
|
8996
|
+
return point == null ? l : info.water.consume(point, l);
|
|
8997
|
+
}
|
|
8998
|
+
}
|
|
8999
|
+
});
|
|
9000
|
+
worlds.set(world, info);
|
|
9001
|
+
return world;
|
|
9002
|
+
}
|
|
9003
|
+
function pointOf(world, fixtureId) {
|
|
9004
|
+
const info = worlds.get(world);
|
|
9005
|
+
return info ? info.points.get(fixtureId) : void 0;
|
|
9006
|
+
}
|
|
9007
|
+
function blockedOf(res, bopts = {}) {
|
|
9008
|
+
bopts = bopts || {};
|
|
9009
|
+
const ox = bopts.originX || 0;
|
|
9010
|
+
const oz = bopts.originZ || 0;
|
|
9011
|
+
const inw = bopts.inw || 1;
|
|
9012
|
+
const margin = bopts.margin != null ? bopts.margin : 0.02;
|
|
9013
|
+
const segs = (res.walls || []).map((p) => {
|
|
9014
|
+
const e = Math.max(0, p.thickness / 2 - margin);
|
|
9015
|
+
const u0 = Math.min(p.u0, p.u1) - (p.axis === "u" ? 0 : e);
|
|
9016
|
+
const u1 = Math.max(p.u0, p.u1) + (p.axis === "u" ? 0 : e);
|
|
9017
|
+
const v0 = Math.min(p.v0, p.v1) - (p.axis === "v" ? 0 : e);
|
|
9018
|
+
const v1 = Math.max(p.v0, p.v1) + (p.axis === "v" ? 0 : e);
|
|
9019
|
+
const za = oz + inw * v0;
|
|
9020
|
+
const zb = oz + inw * v1;
|
|
9021
|
+
return { floor: p.floor, x0: ox + u0, x1: ox + u1, z0: Math.min(za, zb), z1: Math.max(za, zb) };
|
|
9022
|
+
});
|
|
9023
|
+
const CELL2 = 0.5;
|
|
9024
|
+
const grid = /* @__PURE__ */ new Map();
|
|
9025
|
+
const key = (a, i, j) => (a * 4096 + (i + 2048)) * 4096 + (j + 2048);
|
|
9026
|
+
for (const s of segs) {
|
|
9027
|
+
for (let i = Math.floor(s.x0 / CELL2); i <= Math.floor(s.x1 / CELL2); i++) {
|
|
9028
|
+
for (let j = Math.floor(s.z0 / CELL2); j <= Math.floor(s.z1 / CELL2); j++) {
|
|
9029
|
+
const k = key(s.floor, i, j);
|
|
9030
|
+
if (!grid.has(k)) grid.set(k, []);
|
|
9031
|
+
grid.get(k).push(s);
|
|
9032
|
+
}
|
|
9033
|
+
}
|
|
9034
|
+
}
|
|
9035
|
+
return function blocked(x, z, floor) {
|
|
9036
|
+
const a = floor == null || floor < 0 ? 0 : floor;
|
|
9037
|
+
const list2 = grid.get(key(a, Math.floor(x / CELL2), Math.floor(z / CELL2)));
|
|
9038
|
+
if (!list2) return false;
|
|
9039
|
+
for (const s of list2) if (x > s.x0 && x < s.x1 && z > s.z0 && z < s.z1) return true;
|
|
9040
|
+
return false;
|
|
9041
|
+
};
|
|
9042
|
+
}
|
|
9043
|
+
function add(world, planned, aopts = {}) {
|
|
9044
|
+
aopts = aopts || {};
|
|
9045
|
+
const info = worlds.get(world);
|
|
9046
|
+
const build = aopts.build || ((type, item) => hh.build(type, item, HH.createRecorder().api));
|
|
9047
|
+
const isBlocked = aopts.isBlocked || null;
|
|
9048
|
+
const out = { added: 0, parts: [], hinges: {}, moved: {}, warnings: [] };
|
|
9049
|
+
const override = aopts.lightsOn !== void 0 ? aopts.lightsOn : info && info.lightsOn;
|
|
9050
|
+
if (override !== void 0) {
|
|
9051
|
+
for (const e of planned.items) if (e.type === "lamp") e.lit = typeof override === "function" ? !!override(e.id, e) : !!override;
|
|
9052
|
+
for (const e of planned.items) if (e.type === "lantern_lamp") e.lit = typeof override === "function" ? !!override(e.id, e) : !!override;
|
|
9053
|
+
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);
|
|
9054
|
+
}
|
|
9055
|
+
for (const e of planned.items) if (e.type === "lantern_lamp") e.item.on = !!e.lit;
|
|
9056
|
+
let scratch = null;
|
|
9057
|
+
function probe(e, hinge, setback) {
|
|
9058
|
+
if (!scratch) scratch = GI.createWorld({ locale, strings: hh.strings, items: hh.items, loot: hh.loot, grid: false });
|
|
9059
|
+
const it = e.item;
|
|
9060
|
+
const x = it.x + Math.sin(it.ry) * setback;
|
|
9061
|
+
const z = it.z + Math.cos(it.ry) * setback;
|
|
9062
|
+
const spec = hh.build(e.type, Object.assign({}, it, { hinge }), HH.createRecorder().api);
|
|
9063
|
+
scratch.add("__probe", spec, { x, y: e.floorY, z, ry: it.ry });
|
|
9064
|
+
const blocks = (px, pz) => isBlocked(px, pz, e.floor);
|
|
9065
|
+
let sum = 0;
|
|
9066
|
+
let min = 1;
|
|
9067
|
+
let n = 0;
|
|
9068
|
+
for (const p of spec.parts || []) {
|
|
9069
|
+
if (p.motion.kind !== "hinge" || !(p.bounds || p.sweep)) continue;
|
|
9070
|
+
const t = scratch.fitSweep("__probe", p.id, blocks);
|
|
9071
|
+
sum += t;
|
|
9072
|
+
min = Math.min(min, t);
|
|
9073
|
+
n++;
|
|
9074
|
+
}
|
|
9075
|
+
scratch.remove("__probe");
|
|
9076
|
+
return { sum, min, n };
|
|
9077
|
+
}
|
|
9078
|
+
const better = (a, b) => a.sum > b.sum + 1e-9 || Math.abs(a.sum - b.sum) <= 1e-9 && a.min > b.min + 1e-9;
|
|
9079
|
+
function fitDoors(e) {
|
|
9080
|
+
if (!isBlocked || !householdTypes.has(e.type)) return;
|
|
9081
|
+
const standard = probe(e, void 0, 0);
|
|
9082
|
+
if (!standard.n || standard.min >= 1) return;
|
|
9083
|
+
let bestSide;
|
|
9084
|
+
let m = standard;
|
|
9085
|
+
for (const side of ["left", "right"]) {
|
|
9086
|
+
const r = probe(e, side, 0);
|
|
9087
|
+
if (better(r, m)) {
|
|
9088
|
+
m = r;
|
|
9089
|
+
bestSide = side;
|
|
9090
|
+
}
|
|
9091
|
+
}
|
|
9092
|
+
if (bestSide) {
|
|
9093
|
+
e.item.hinge = bestSide;
|
|
9094
|
+
out.hinges[e.id] = bestSide;
|
|
9095
|
+
}
|
|
9096
|
+
if (m.min >= 1) return;
|
|
9097
|
+
let target = { setback: 0, r: m };
|
|
9098
|
+
for (const setback of [0.01, 0.02, 0.03, 0.04]) {
|
|
9099
|
+
const r = probe(e, bestSide, setback);
|
|
9100
|
+
if (better(r, target.r)) target = { setback, r };
|
|
9101
|
+
if (r.min >= 1) break;
|
|
9102
|
+
}
|
|
9103
|
+
if (target.setback > 0 && target.r.sum > m.sum + 0.2) {
|
|
9104
|
+
e.item.x = r3(e.item.x + Math.sin(e.item.ry) * target.setback);
|
|
9105
|
+
e.item.z = r3(e.item.z + Math.cos(e.item.ry) * target.setback);
|
|
9106
|
+
e.moved = target.setback;
|
|
9107
|
+
out.moved[e.id] = target.setback;
|
|
9108
|
+
}
|
|
9109
|
+
}
|
|
9110
|
+
for (const e of planned.items) {
|
|
9111
|
+
if (e.type !== "shower" || !e.connections.outlet) continue;
|
|
9112
|
+
const t = planned.items.find((x) => x.id === e.connections.outlet);
|
|
9113
|
+
if (t && t.connections.circuit) e.connections.outletCircuit = t.connections.circuit;
|
|
9114
|
+
}
|
|
9115
|
+
for (const e of planned.items) {
|
|
9116
|
+
let spec;
|
|
9117
|
+
if (ownTypes[e.type]) {
|
|
9118
|
+
spec = ownSpec(e);
|
|
9119
|
+
} else {
|
|
9120
|
+
fitDoors(e);
|
|
9121
|
+
spec = build(e.type, e.item);
|
|
9122
|
+
if (!spec) {
|
|
9123
|
+
out.warnings.push(msg("warn.buildEmpty", { id: e.id }));
|
|
9124
|
+
continue;
|
|
9125
|
+
}
|
|
9126
|
+
}
|
|
9127
|
+
connect(e, spec);
|
|
9128
|
+
world.add(e.id, spec, { x: e.item.x, y: e.floorY, z: e.item.z, ry: e.item.ry });
|
|
9129
|
+
out.added++;
|
|
9130
|
+
if (!isBlocked) continue;
|
|
9131
|
+
for (const p of spec.parts || []) {
|
|
9132
|
+
if (!(p.bounds || p.sweep)) continue;
|
|
9133
|
+
const t = world.fitSweep(e.id, p.id, (x, z) => isBlocked(x, z, e.floor));
|
|
9134
|
+
if (t < 1) out.parts.push({ object: e.id, part: p.id, t });
|
|
9135
|
+
}
|
|
9136
|
+
}
|
|
9137
|
+
if (info) for (const f of planned.fixtures) info.points.set(f.global, f.point);
|
|
9138
|
+
return out;
|
|
9139
|
+
}
|
|
9140
|
+
return { version: ADAPTER_VERSION, household: hh, plan, createWorld, add, blockedOf, pointOf, ownSpec, registries: { typeMap, contentMap, contentByGroup, chairTables, fixturesOfPoint, substitutes, preference, ownTypes } };
|
|
9141
|
+
}
|
|
9142
|
+
var FloorplanInteractables = { version: ADAPTER_VERSION, create: create2, TYPE_MAP, CONTENT_MAP, CONTENT_BY_GROUP, CHAIR_TABLES, PREFERENCE, mergeRegistry };
|
|
9143
|
+
|
|
7526
9144
|
// src/interactables/kit.ts
|
|
7527
9145
|
function installInteractablesKit(K, shared) {
|
|
7528
9146
|
const { t, THREE, DOC, cfg, Reflector } = K;
|
|
@@ -7530,12 +9148,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
7530
9148
|
const IVK = (() => {
|
|
7531
9149
|
const o = cfg.interactives;
|
|
7532
9150
|
if (!o) return null;
|
|
7533
|
-
const GI = o.GameInteractables || null, HH = o.GameInteractablesHousehold || null, GT = o.GameInteractablesThree || null, AD = o.adapter ||
|
|
7534
|
-
if (!GI || !HH || !GT
|
|
9151
|
+
const GI = o.GameInteractables || null, HH = o.GameInteractablesHousehold || null, GT = o.GameInteractablesThree || null, AD = o.adapter || FloorplanInteractables;
|
|
9152
|
+
if (!GI || !HH || !GT) {
|
|
7535
9153
|
console.warn(t("warn.interactablesIncomplete"));
|
|
7536
9154
|
return null;
|
|
7537
9155
|
}
|
|
7538
|
-
const A = AD.plan ? AD : AD.create({ GameInteractables: GI, GameInteractablesHousehold: HH, locale: o.locale, region: o.region });
|
|
9156
|
+
const A = AD.plan ? AD : AD.create({ ...o.adapterOptions || {}, GameInteractables: GI, GameInteractablesHousehold: HH, locale: o.locale || cfg.locale, region: o.region, ...cfg.seedKey ? { seedKey: cfg.seedKey } : {} });
|
|
7539
9157
|
return { GI, HH, GT, A, gfx: GT.createThreeAdapter(THREE, { document: DOC, Reflector }), items: o.items !== false, effects: o.effects !== false, camera: o.camera || null, onEvent: o.onEvent || null, onSeat: o.onSeat || null };
|
|
7540
9158
|
})();
|
|
7541
9159
|
const VEG = (() => {
|
|
@@ -7636,13 +9254,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
7636
9254
|
}
|
|
7637
9255
|
for (const g of by.values()) {
|
|
7638
9256
|
const ls = g.ls, n = ls.length;
|
|
7639
|
-
let cx = 0, cy = 0, cz = 0,
|
|
9257
|
+
let cx = 0, cy = 0, cz = 0, range2 = 0;
|
|
7640
9258
|
for (const l of ls) {
|
|
7641
9259
|
_p.set(l.x, l.y, l.z).applyMatrix4(M);
|
|
7642
9260
|
cx += _p.x;
|
|
7643
9261
|
cy += _p.y;
|
|
7644
9262
|
cz += _p.z;
|
|
7645
|
-
|
|
9263
|
+
range2 = Math.max(range2, l.range || 5);
|
|
7646
9264
|
}
|
|
7647
9265
|
cx /= n;
|
|
7648
9266
|
cy /= n;
|
|
@@ -7650,7 +9268,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
7650
9268
|
g.pos = [cx, cy, cz];
|
|
7651
9269
|
g.color = ls[0].color;
|
|
7652
9270
|
g.n = n;
|
|
7653
|
-
g.range =
|
|
9271
|
+
g.range = range2;
|
|
7654
9272
|
if (g.exterior) {
|
|
7655
9273
|
g.rects = [[cx - 7, cz - 7, cx + 7, cz + 7]];
|
|
7656
9274
|
g.y = [cy - 3.2, cy + 4];
|
|
@@ -8923,8 +10541,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
8923
10541
|
const resting = /* @__PURE__ */ new Map();
|
|
8924
10542
|
const carrying = /* @__PURE__ */ new Map();
|
|
8925
10543
|
const push = (map, key, value) => {
|
|
8926
|
-
const
|
|
8927
|
-
if (
|
|
10544
|
+
const list2 = map.get(key);
|
|
10545
|
+
if (list2) list2.push(value);
|
|
8928
10546
|
else map.set(key, [value]);
|
|
8929
10547
|
};
|
|
8930
10548
|
for (const support of supports) {
|
|
@@ -8980,7 +10598,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
8980
10598
|
if (!splits.size) return input;
|
|
8981
10599
|
const boxes = new Map(input.parts.map((part) => [part.id, part.aabb]));
|
|
8982
10600
|
const pieceBox = /* @__PURE__ */ new Map();
|
|
8983
|
-
for (const split of splits.values()) for (const
|
|
10601
|
+
for (const split of splits.values()) for (const piece2 of split.pieces) pieceBox.set(piece2.id, piece2.aabb);
|
|
8984
10602
|
const parts = input.parts.flatMap((part) => splits.get(part.id)?.pieces ?? [part]);
|
|
8985
10603
|
const supports = [];
|
|
8986
10604
|
for (const support of input.supports) {
|
|
@@ -9028,12 +10646,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9028
10646
|
for (const [a, b] of cutAt(from, to, openings.filter((o) => o.wall === wall.id), y0, y1)) for (const [x0, x1] of unitsOf(a, b, row, spec)) cells.push({ from: x0, to: x1, row, y0, y1 });
|
|
9029
10647
|
}
|
|
9030
10648
|
const total = cells.reduce((sum, cell) => sum + (cell.to - cell.from) * (cell.y1 - cell.y0), 0);
|
|
9031
|
-
const
|
|
10649
|
+
const box2 = (cell) => alongU ? [cell.from, cross[0], cell.to, cross[1]] : [cross[0], cell.from, cross[1], cell.to];
|
|
9032
10650
|
const pieces = cells.map((cell, index) => ({
|
|
9033
10651
|
id: `${wall.id}_${spec.unitLength ? "u" : "log"}${cell.row}_${index}`,
|
|
9034
10652
|
role: wall.role,
|
|
9035
10653
|
material: wall.material,
|
|
9036
|
-
aabb:
|
|
10654
|
+
aabb: box2(cell),
|
|
9037
10655
|
y0: cell.y0,
|
|
9038
10656
|
y1: cell.y1,
|
|
9039
10657
|
floor: wall.floor,
|
|
@@ -9159,9 +10777,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9159
10777
|
const capacity = input.capacities.get(id);
|
|
9160
10778
|
capacities.delete(id);
|
|
9161
10779
|
if (capacity === void 0) continue;
|
|
9162
|
-
const along = (
|
|
10780
|
+
const along = (box2) => Math.max(box2[2] - box2[0], box2[3] - box2[1]);
|
|
9163
10781
|
const length = along(input.parts.find((part) => part.id === id).aabb);
|
|
9164
|
-
for (const
|
|
10782
|
+
for (const piece2 of split.pieces) capacities.set(piece2.id, Math.max(1, capacity * along(piece2.aabb) / length));
|
|
9165
10783
|
}
|
|
9166
10784
|
return { ...next, capacities };
|
|
9167
10785
|
}
|
|
@@ -9438,7 +11056,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9438
11056
|
const per = Math.max(1, Math.round(len / ul));
|
|
9439
11057
|
const w = len / per;
|
|
9440
11058
|
const edge = fragmentMaterial(part.material).color.getHex();
|
|
9441
|
-
const
|
|
11059
|
+
const list2 = [];
|
|
9442
11060
|
for (let r = 0; r < rows; r++) {
|
|
9443
11061
|
const shift = units.bond === "running" && r & 1 ? w / 2 : 0;
|
|
9444
11062
|
const cells = per + (shift ? 1 : 0);
|
|
@@ -9453,10 +11071,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9453
11071
|
const y = part.y0 + (r + 0.5) * rowH;
|
|
9454
11072
|
const d = Math.hypot(x - opening.center[0], y - opening.center[1], z - opening.center[2]);
|
|
9455
11073
|
if (d < opening.radius) continue;
|
|
9456
|
-
|
|
11074
|
+
list2.push({ x, y, z, sx: alongU ? b - a : thick, sy: rowH, sz: alongU ? thick : b - a, colour: d < opening.radius + 0.25 || paint === null ? edge : paint });
|
|
9457
11075
|
}
|
|
9458
11076
|
}
|
|
9459
|
-
return
|
|
11077
|
+
return list2;
|
|
9460
11078
|
}
|
|
9461
11079
|
function open(event) {
|
|
9462
11080
|
if (lod !== 0 || views.has(event.part) || !event.opening) return false;
|
|
@@ -9465,27 +11083,27 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9465
11083
|
if (!part || !spec || !spec.units) return false;
|
|
9466
11084
|
const items = structure.meshesOf(event.part).filter((it) => it.mesh);
|
|
9467
11085
|
if (!items.length) return false;
|
|
9468
|
-
const
|
|
9469
|
-
const mesh = new THREE.InstancedMesh(unitGeometry, unitMaterial, Math.max(1,
|
|
11086
|
+
const list2 = courses(part, spec.units, event.opening, wallColour(items));
|
|
11087
|
+
const mesh = new THREE.InstancedMesh(unitGeometry, unitMaterial, Math.max(1, list2.length));
|
|
9470
11088
|
mesh.name = "breach:" + event.part;
|
|
9471
|
-
|
|
11089
|
+
list2.forEach((u, i) => {
|
|
9472
11090
|
tmp.m.compose(tmp.p.set(u.x, u.y, u.z), tmp.q.identity(), tmp.s.set(u.sx, u.sy, u.sz));
|
|
9473
11091
|
mesh.setMatrixAt(i, tmp.m);
|
|
9474
11092
|
mesh.setColorAt(i, tmp.c.setHex(u.colour));
|
|
9475
11093
|
});
|
|
9476
|
-
mesh.count =
|
|
11094
|
+
mesh.count = list2.length;
|
|
9477
11095
|
mesh.instanceMatrix.needsUpdate = true;
|
|
9478
11096
|
if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true;
|
|
9479
11097
|
mesh.castShadow = true;
|
|
9480
11098
|
mesh.receiveShadow = true;
|
|
9481
11099
|
house.add(mesh);
|
|
9482
11100
|
const saved = items.map((it) => ({ it, v0: it.v0, data: collapseRange(it.mesh, it.v0, it.v1) }));
|
|
9483
|
-
views.set(event.part, { mesh, saved, units:
|
|
11101
|
+
views.set(event.part, { mesh, saved, units: list2.length, opening: event.opening });
|
|
9484
11102
|
invalidate();
|
|
9485
11103
|
invalidateShadow();
|
|
9486
11104
|
return true;
|
|
9487
11105
|
}
|
|
9488
|
-
function
|
|
11106
|
+
function plain2(view, shown) {
|
|
9489
11107
|
for (const s of view.saved) {
|
|
9490
11108
|
if (shown) restoreRange(s.it.mesh, s.v0, s.data);
|
|
9491
11109
|
else s.data = collapseRange(s.it.mesh, s.v0, s.it.v1);
|
|
@@ -9511,7 +11129,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9511
11129
|
if (was === 0 === (level === 0)) return;
|
|
9512
11130
|
for (const v of views.values()) {
|
|
9513
11131
|
v.mesh.visible = level === 0;
|
|
9514
|
-
|
|
11132
|
+
plain2(v, level !== 0);
|
|
9515
11133
|
}
|
|
9516
11134
|
invalidate();
|
|
9517
11135
|
invalidateShadow();
|
|
@@ -9521,7 +11139,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9521
11139
|
for (const v of views.values()) {
|
|
9522
11140
|
v.mesh.removeFromParent();
|
|
9523
11141
|
v.mesh.dispose();
|
|
9524
|
-
if (lod === 0)
|
|
11142
|
+
if (lod === 0) plain2(v, true);
|
|
9525
11143
|
}
|
|
9526
11144
|
views.clear();
|
|
9527
11145
|
},
|
|
@@ -9628,7 +11246,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9628
11246
|
};
|
|
9629
11247
|
D.dropPiece = (id) => {
|
|
9630
11248
|
if (hiddenPieces.has(id) || bodies.has(id)) return;
|
|
9631
|
-
const
|
|
11249
|
+
const list2 = [], rr = rngString(id);
|
|
9632
11250
|
for (const it of structure.meshesOf(id)) {
|
|
9633
11251
|
if (it.obj) {
|
|
9634
11252
|
hide(it);
|
|
@@ -9637,10 +11255,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9637
11255
|
const m = extract(it);
|
|
9638
11256
|
hide(it);
|
|
9639
11257
|
const hy = (m.geometry.boundingBox.max.y - m.geometry.boundingBox.min.y) / 2;
|
|
9640
|
-
|
|
11258
|
+
list2.push({ mesh: m, vy: 0, hy, y0: m.position.y, rot: 0, w: [(rr() - 0.5) * 0.5, (rr() - 0.5) * 0.3, (rr() - 0.5) * 0.5], landing: false });
|
|
9641
11259
|
}
|
|
9642
11260
|
hiddenPieces.add(id);
|
|
9643
|
-
if (
|
|
11261
|
+
if (list2.length) bodies.set(id, list2);
|
|
9644
11262
|
invalidate();
|
|
9645
11263
|
invalidateShadow();
|
|
9646
11264
|
};
|
|
@@ -9812,8 +11430,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9812
11430
|
D.animate = (dt) => {
|
|
9813
11431
|
if (R) return;
|
|
9814
11432
|
let moved = false;
|
|
9815
|
-
for (const [id,
|
|
9816
|
-
for (const b of
|
|
11433
|
+
for (const [id, list2] of bodies) {
|
|
11434
|
+
for (const b of list2) {
|
|
9817
11435
|
if (b.landing) continue;
|
|
9818
11436
|
moved = true;
|
|
9819
11437
|
b.vy -= 9.8 * dt;
|
|
@@ -9829,10 +11447,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9829
11447
|
b.landing = true;
|
|
9830
11448
|
}
|
|
9831
11449
|
}
|
|
9832
|
-
if (!
|
|
9833
|
-
|
|
11450
|
+
if (!list2.impacted && list2.every((b) => b.landing)) {
|
|
11451
|
+
list2.impacted = true;
|
|
9834
11452
|
const ps = D.active ? D.world.part(D.id, id) : null;
|
|
9835
|
-
const b =
|
|
11453
|
+
const b = list2[0];
|
|
9836
11454
|
if (ps && ps.status !== "broken") {
|
|
9837
11455
|
const h = Math.max(0.5, b.y0 - b.hy), c = worldPoint(b.mesh.parent, b.mesh.position);
|
|
9838
11456
|
D.world.hitPart(D.id, id, { type: "blunt", point: [c.x, c.y, c.z], energy: ps.mass * 9.8 * h, radius: 0.5, source: "fall" });
|
|
@@ -10413,7 +12031,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10413
12031
|
|
|
10414
12032
|
// src/create.ts
|
|
10415
12033
|
var VERSION = "1.0.0";
|
|
10416
|
-
function
|
|
12034
|
+
function create3(THREE, options = {}) {
|
|
10417
12035
|
const cfg = Object.assign({}, options || {});
|
|
10418
12036
|
const DOC = cfg.document || (typeof document !== "undefined" ? document : null);
|
|
10419
12037
|
const PROPS = cfg.props || dist_exports;
|
|
@@ -10763,20 +12381,20 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10763
12381
|
const g = c.grids[floor];
|
|
10764
12382
|
if (!g) return 0;
|
|
10765
12383
|
let x0, z0, x1, z1;
|
|
10766
|
-
const
|
|
10767
|
-
if (
|
|
10768
|
-
x0 =
|
|
10769
|
-
z0 =
|
|
10770
|
-
x1 =
|
|
10771
|
-
z1 =
|
|
12384
|
+
const circle2 = "circle" in shape ? shape.circle : null;
|
|
12385
|
+
if (circle2) {
|
|
12386
|
+
x0 = circle2[0] - circle2[2];
|
|
12387
|
+
z0 = circle2[1] - circle2[2];
|
|
12388
|
+
x1 = circle2[0] + circle2[2];
|
|
12389
|
+
z1 = circle2[1] + circle2[2];
|
|
10772
12390
|
} else [x0, z0, x1, z1] = shape.rect;
|
|
10773
12391
|
const i0 = Math.max(0, Math.ceil((Math.min(x0, x1) - c.ox) / CELL - 0.5)), i1 = Math.min(c.nx - 1, Math.floor((Math.max(x0, x1) - c.ox) / CELL - 0.5));
|
|
10774
12392
|
const j0 = Math.max(0, Math.ceil((Math.min(z0, z1) - c.oz) / CELL - 0.5)), j1 = Math.min(c.nz - 1, Math.floor((Math.max(z0, z1) - c.oz) / CELL - 0.5));
|
|
10775
12393
|
let n = 0;
|
|
10776
12394
|
for (let j = j0; j <= j1; j++) for (let i = i0; i <= i1; i++) {
|
|
10777
|
-
if (
|
|
10778
|
-
const dx = c.ox + (i + 0.5) * CELL -
|
|
10779
|
-
if (dx * dx + dz * dz >
|
|
12395
|
+
if (circle2) {
|
|
12396
|
+
const dx = c.ox + (i + 0.5) * CELL - circle2[0], dz = c.oz + (j + 0.5) * CELL - circle2[1];
|
|
12397
|
+
if (dx * dx + dz * dz > circle2[2] * circle2[2]) continue;
|
|
10780
12398
|
}
|
|
10781
12399
|
fn(g, j * c.nx + i);
|
|
10782
12400
|
n++;
|
|
@@ -11013,11 +12631,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11013
12631
|
};
|
|
11014
12632
|
const role = (p) => p.structure && p.structure.role;
|
|
11015
12633
|
const events = (room) => {
|
|
11016
|
-
const
|
|
11017
|
-
room.world.on("*", (e) =>
|
|
11018
|
-
return
|
|
12634
|
+
const list2 = [];
|
|
12635
|
+
room.world.on("*", (e) => list2.push(e));
|
|
12636
|
+
return list2;
|
|
11019
12637
|
};
|
|
11020
|
-
const collapsed = (
|
|
12638
|
+
const collapsed = (list2) => list2.filter((e) => e.type === "collapse").flatMap((e) => e.parts.map((p) => p.id || p));
|
|
11021
12639
|
const whole = (room, oid, pid) => {
|
|
11022
12640
|
const p = room.world.part(oid, pid);
|
|
11023
12641
|
return !!p && p.status !== "broken" && !p.stripped;
|
|
@@ -11036,14 +12654,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11036
12654
|
name: text.scenarios.house_one_pillar,
|
|
11037
12655
|
run({ room, step, expect }) {
|
|
11038
12656
|
const { oid, parts, centre } = spawn(room, "house_casa_portico");
|
|
11039
|
-
const
|
|
12657
|
+
const list2 = events(room);
|
|
11040
12658
|
const columns = groundColumns(parts);
|
|
11041
12659
|
const laj = slabs(parts);
|
|
11042
12660
|
blunt(room, oid, columns[0].id, centre(columns[0].id), 3e6);
|
|
11043
12661
|
step(20);
|
|
11044
12662
|
expect(!whole(room, oid, columns[0].id), fill(T2.one_pillar_broke, { id: columns[0].id }));
|
|
11045
12663
|
expect(laj.length > 0 && laj.every((id) => whole(room, oid, id)), T2.slabs_whole);
|
|
11046
|
-
expect(!collapsed(
|
|
12664
|
+
expect(!collapsed(list2).some((id) => laj.includes(id)), T2.no_slab_fell);
|
|
11047
12665
|
}
|
|
11048
12666
|
},
|
|
11049
12667
|
{
|
|
@@ -11051,17 +12669,17 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11051
12669
|
name: text.scenarios.house_two_pillars,
|
|
11052
12670
|
run({ room, step, expect }) {
|
|
11053
12671
|
const { oid, parts, centre } = spawn(room, "house_casa_portico");
|
|
11054
|
-
const
|
|
12672
|
+
const list2 = events(room);
|
|
11055
12673
|
const columns = groundColumns(parts);
|
|
11056
12674
|
const laj = slabs(parts);
|
|
11057
12675
|
blunt(room, oid, columns[0].id, centre(columns[0].id), 3e6);
|
|
11058
12676
|
blunt(room, oid, columns[1].id, centre(columns[1].id), 3e6);
|
|
11059
12677
|
step(90);
|
|
11060
|
-
for (let next = 2; next < columns.length && !slabs(parts).some((id) => collapsed(
|
|
12678
|
+
for (let next = 2; next < columns.length && !slabs(parts).some((id) => collapsed(list2).includes(id)); next++) {
|
|
11061
12679
|
blunt(room, oid, columns[next].id, centre(columns[next].id), 3e6);
|
|
11062
12680
|
step(90);
|
|
11063
12681
|
}
|
|
11064
|
-
const fell = collapsed(
|
|
12682
|
+
const fell = collapsed(list2);
|
|
11065
12683
|
expect(laj.some((id) => fell.includes(id)), fill(T2.two_slab_fell, { n: fell.length }));
|
|
11066
12684
|
expect(parts.filter((p) => role(p) === "roof").some((p) => fell.includes(p.id)), T2.two_roof_fell);
|
|
11067
12685
|
}
|
|
@@ -11071,13 +12689,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11071
12689
|
name: text.scenarios.house_partition,
|
|
11072
12690
|
run({ room, step, expect }) {
|
|
11073
12691
|
const { oid, parts, centre } = spawn(room, "house_casa_inteira");
|
|
11074
|
-
const
|
|
12692
|
+
const list2 = events(room);
|
|
11075
12693
|
const partition = parts.find((p) => role(p) === "partition");
|
|
11076
12694
|
const laj = slabs(parts);
|
|
11077
12695
|
blunt(room, oid, partition.id, centre(partition.id), 3e6);
|
|
11078
12696
|
step(20);
|
|
11079
12697
|
expect(!whole(room, oid, partition.id), fill(T2.partition_broke, { id: partition.id }));
|
|
11080
|
-
expect(laj.every((id) => whole(room, oid, id)) && !collapsed(
|
|
12698
|
+
expect(laj.every((id) => whole(room, oid, id)) && !collapsed(list2).some((id) => laj.includes(id)), T2.slab_stayed);
|
|
11081
12699
|
}
|
|
11082
12700
|
},
|
|
11083
12701
|
{
|
|
@@ -11116,12 +12734,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11116
12734
|
name: text.scenarios.house_gas_explodes,
|
|
11117
12735
|
run({ room, step, expect }) {
|
|
11118
12736
|
const { oid, parts, centre } = spawn(room, "house_casa_inteira");
|
|
11119
|
-
const
|
|
12737
|
+
const list2 = events(room);
|
|
11120
12738
|
const bottle = parts.find((p) => p.explodes);
|
|
11121
12739
|
room.world.hitPart(oid, bottle.id, { type: "fire", point: centre(bottle.id), temperature: 900, radius: 0.6, duration: 8 });
|
|
11122
12740
|
step(12);
|
|
11123
|
-
expect(
|
|
11124
|
-
const damage =
|
|
12741
|
+
expect(list2.filter((e) => e.type === "explode").length > 0, T2.gas_exploded);
|
|
12742
|
+
const damage = list2.filter((e) => e.type === "damage" && e.part !== bottle.id && e.damageType === "explosive");
|
|
11125
12743
|
expect(damage.length > 0, fill(T2.gas_damaged, { n: new Set(damage.map((e) => e.part)).size }));
|
|
11126
12744
|
}
|
|
11127
12745
|
}
|
|
@@ -11162,7 +12780,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11162
12780
|
let made = byId.get(key);
|
|
11163
12781
|
if (!made) {
|
|
11164
12782
|
const plan = engine.generate(def.template, { seed: def.seed ?? 1, ...def.state ? { state: def.state } : {} });
|
|
11165
|
-
const house =
|
|
12783
|
+
const house = create3(THREE, { ...houseOptions, destruction: void 0, destructionRenderer: void 0, interactives: void 0, vegetation: void 0, fleet: null }).build(plan, { quality: "game", terrain: false, noPerimeter: true });
|
|
11166
12784
|
const spec = house.structure.spec({ wallDetail: "coarse", ...def.portico ? { portico: true } : {} });
|
|
11167
12785
|
house.dispose();
|
|
11168
12786
|
made = { spec, plan };
|
|
@@ -11258,7 +12876,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11258
12876
|
const key = `${settings.quality}|${locale}`;
|
|
11259
12877
|
if (!houseRenderer || houseRendererKey !== key) {
|
|
11260
12878
|
houseRenderer?.dispose?.();
|
|
11261
|
-
houseRenderer =
|
|
12879
|
+
houseRenderer = create3(THREE, {
|
|
11262
12880
|
locale,
|
|
11263
12881
|
lod: { interior: 10, hide: 40 },
|
|
11264
12882
|
...options.house,
|
|
@@ -11588,7 +13206,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11588
13206
|
for (const group of groups) {
|
|
11589
13207
|
for (const id of group.templates) {
|
|
11590
13208
|
const plan = engine.generate(id, { seed: 1 });
|
|
11591
|
-
const house =
|
|
13209
|
+
const house = create3(THREE ?? host?.THREE, { locale, ...options.house, destruction: void 0, destructionRenderer: void 0, interactives: void 0, vegetation: void 0, fleet: null }).build(plan, { quality: "game", terrain: false, noPerimeter: true });
|
|
11592
13210
|
const ok = house.structure.parts.length > 0 && house.floors.length >= 1 && house.colliders.length > 0;
|
|
11593
13211
|
expect(ok, `${groupName(group)}: ${templateName(id)} (${house.structure.parts.length})`);
|
|
11594
13212
|
house.dispose();
|