@adatechnology/game-items-three 0.5.0 → 0.6.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/README.md +1 -0
- package/dist/index.d.ts +48 -3
- package/dist/index.global.js +1161 -548
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +221 -21
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/dist/index.global.js
CHANGED
|
@@ -29,6 +29,7 @@ var GameItemsThree = (() => {
|
|
|
29
29
|
ITEM_FAMILIES: () => ITEM_FAMILIES,
|
|
30
30
|
ITEM_PREFIX: () => ITEM_PREFIX,
|
|
31
31
|
MODEL_BUDGET_DEVIATIONS: () => MODEL_BUDGET_DEVIATIONS,
|
|
32
|
+
OPENING_NAME: () => OPENING_NAME,
|
|
32
33
|
ROW_LIMIT: () => ROW_LIMIT,
|
|
33
34
|
RULER_HEIGHT: () => RULER_HEIGHT,
|
|
34
35
|
RULER_ID: () => RULER_ID,
|
|
@@ -42,6 +43,7 @@ var GameItemsThree = (() => {
|
|
|
42
43
|
WEAR_AMOUNT: () => WEAR_AMOUNT,
|
|
43
44
|
WEAR_TAGS: () => WEAR_TAGS,
|
|
44
45
|
WEAR_TARGET: () => WEAR_TARGET,
|
|
46
|
+
asLid: () => asLid,
|
|
45
47
|
buildItem: () => buildItem,
|
|
46
48
|
buildItemLod: () => buildItemLod,
|
|
47
49
|
canonicalFrame: () => canonicalFrame,
|
|
@@ -60,14 +62,18 @@ var GameItemsThree = (() => {
|
|
|
60
62
|
itemFamily: () => itemFamily,
|
|
61
63
|
itemModelBuilder: () => itemModelBuilder,
|
|
62
64
|
itemModelEntry: () => itemModelEntry,
|
|
65
|
+
itemOpening: () => itemOpening,
|
|
63
66
|
itemThumbnail: () => itemThumbnail,
|
|
64
67
|
itemThumbnailSvg: () => itemThumbnailSvg,
|
|
65
68
|
listItemModels: () => listItemModels,
|
|
66
69
|
mergeItem: () => mergeItem,
|
|
70
|
+
openItem: () => openItem,
|
|
67
71
|
registerItemModel: () => registerItemModel,
|
|
68
72
|
renderItemThumbnail: () => renderItemThumbnail,
|
|
73
|
+
setOpeningContents: () => setOpeningContents,
|
|
69
74
|
setWear: () => setWear,
|
|
70
75
|
shade: () => shade,
|
|
76
|
+
shapeDestruction: () => shapeDestruction,
|
|
71
77
|
shapeOf: () => shapeOf,
|
|
72
78
|
shapeThumbnailSvg: () => shapeThumbnailSvg,
|
|
73
79
|
shelvesLayout: () => shelvesLayout,
|
|
@@ -75,6 +81,7 @@ var GameItemsThree = (() => {
|
|
|
75
81
|
tagForDestruction: () => tagForDestruction,
|
|
76
82
|
thumbnailPatch: () => thumbnailPatch,
|
|
77
83
|
triangleBudgetOf: () => triangleBudgetOf,
|
|
84
|
+
turnItem: () => turnItem,
|
|
78
85
|
unregisterItemModel: () => unregisterItemModel,
|
|
79
86
|
wearableMaterials: () => wearableMaterials
|
|
80
87
|
});
|
|
@@ -1724,6 +1731,90 @@ var GameItemsThree = (() => {
|
|
|
1724
1731
|
return mesh2;
|
|
1725
1732
|
});
|
|
1726
1733
|
}
|
|
1734
|
+
var isTexture = (v) => !!v && typeof v === "object" && v.isTexture === true;
|
|
1735
|
+
function texturesOf(material, out) {
|
|
1736
|
+
for (const value of Object.values(material)) if (isTexture(value)) out.add(value);
|
|
1737
|
+
const uniforms = material.uniforms;
|
|
1738
|
+
if (uniforms) {
|
|
1739
|
+
for (const u of Object.values(uniforms)) if (isTexture(u?.value)) out.add(u.value);
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
function collect(roots) {
|
|
1743
|
+
const geometries = /* @__PURE__ */ new Set();
|
|
1744
|
+
const materials = /* @__PURE__ */ new Set();
|
|
1745
|
+
const textures = /* @__PURE__ */ new Set();
|
|
1746
|
+
const skeletons = /* @__PURE__ */ new Set();
|
|
1747
|
+
for (const root of roots) {
|
|
1748
|
+
root.traverse((object2) => {
|
|
1749
|
+
const o = object2;
|
|
1750
|
+
if (o.geometry && typeof o.geometry.dispose === "function") geometries.add(o.geometry);
|
|
1751
|
+
if (o.skeleton && typeof o.skeleton.dispose === "function") skeletons.add(o.skeleton);
|
|
1752
|
+
const list2 = Array.isArray(o.material) ? o.material : o.material ? [o.material] : [];
|
|
1753
|
+
for (const m of list2) {
|
|
1754
|
+
if (!m || typeof m.dispose !== "function") continue;
|
|
1755
|
+
materials.add(m);
|
|
1756
|
+
texturesOf(m, textures);
|
|
1757
|
+
}
|
|
1758
|
+
});
|
|
1759
|
+
}
|
|
1760
|
+
return { geometries, materials, textures, skeletons };
|
|
1761
|
+
}
|
|
1762
|
+
var marked = /* @__PURE__ */ new WeakSet();
|
|
1763
|
+
var shared = (r) => r.userData?.shared === true || marked.has(r);
|
|
1764
|
+
function releaseObject3D(roots, options = {}) {
|
|
1765
|
+
const list2 = Array.isArray(roots) ? roots : [roots];
|
|
1766
|
+
const report = { geometries: 0, materials: 0, textures: 0 };
|
|
1767
|
+
if (list2.length === 0) return report;
|
|
1768
|
+
const found = collect(list2);
|
|
1769
|
+
const keepRoots = options.keep === void 0 ? [] : Array.isArray(options.keep) ? options.keep : [options.keep];
|
|
1770
|
+
const releasing = new Set(list2);
|
|
1771
|
+
for (const keep of keepRoots) {
|
|
1772
|
+
const walk = (o) => {
|
|
1773
|
+
if (releasing.has(o)) return;
|
|
1774
|
+
const owner = o;
|
|
1775
|
+
if (owner.geometry) found.geometries.delete(owner.geometry);
|
|
1776
|
+
if (owner.skeleton) found.skeletons.delete(owner.skeleton);
|
|
1777
|
+
const mats = Array.isArray(owner.material) ? owner.material : owner.material ? [owner.material] : [];
|
|
1778
|
+
for (const m of mats) {
|
|
1779
|
+
if (!m) continue;
|
|
1780
|
+
found.materials.delete(m);
|
|
1781
|
+
const t = /* @__PURE__ */ new Set();
|
|
1782
|
+
texturesOf(m, t);
|
|
1783
|
+
for (const x of t) found.textures.delete(x);
|
|
1784
|
+
}
|
|
1785
|
+
for (const c of o.children) walk(c);
|
|
1786
|
+
};
|
|
1787
|
+
walk(keep);
|
|
1788
|
+
}
|
|
1789
|
+
for (const g of found.geometries) {
|
|
1790
|
+
if (shared(g)) continue;
|
|
1791
|
+
g.dispose();
|
|
1792
|
+
report.geometries++;
|
|
1793
|
+
}
|
|
1794
|
+
for (const m of found.materials) {
|
|
1795
|
+
if (shared(m)) continue;
|
|
1796
|
+
m.dispose();
|
|
1797
|
+
report.materials++;
|
|
1798
|
+
}
|
|
1799
|
+
for (const t of found.textures) {
|
|
1800
|
+
if (shared(t)) continue;
|
|
1801
|
+
t.dispose();
|
|
1802
|
+
report.textures++;
|
|
1803
|
+
}
|
|
1804
|
+
for (const s of found.skeletons) s.dispose();
|
|
1805
|
+
return report;
|
|
1806
|
+
}
|
|
1807
|
+
function discardObject3D(objects, options = {}) {
|
|
1808
|
+
const list2 = Array.isArray(objects) ? objects : [objects];
|
|
1809
|
+
const keep = options.keep === void 0 ? [] : Array.isArray(options.keep) ? [...options.keep] : [options.keep];
|
|
1810
|
+
for (const object2 of list2) {
|
|
1811
|
+
let top = object2;
|
|
1812
|
+
while (top.parent) top = top.parent;
|
|
1813
|
+
object2.removeFromParent();
|
|
1814
|
+
if (top !== object2 && !keep.includes(top)) keep.push(top);
|
|
1815
|
+
}
|
|
1816
|
+
return releaseObject3D(list2, { keep });
|
|
1817
|
+
}
|
|
1727
1818
|
|
|
1728
1819
|
// src/kit.ts
|
|
1729
1820
|
var WEAR_TAGS = ["metal", "wood", "cloth", "plastic", "paper", "food", "glass"];
|
|
@@ -2958,6 +3049,12 @@ var GameItemsThree = (() => {
|
|
|
2958
3049
|
liquid: "honey",
|
|
2959
3050
|
fill: 0.9
|
|
2960
3051
|
}
|
|
3052
|
+
},
|
|
3053
|
+
shapes: {
|
|
3054
|
+
box: {
|
|
3055
|
+
hollow: true,
|
|
3056
|
+
welded: true
|
|
3057
|
+
}
|
|
2961
3058
|
}
|
|
2962
3059
|
};
|
|
2963
3060
|
|
|
@@ -2973,6 +3070,8 @@ var GameItemsThree = (() => {
|
|
|
2973
3070
|
};
|
|
2974
3071
|
var FAMILIES = destruction_default.families;
|
|
2975
3072
|
var CONTENTS = destruction_default.contents;
|
|
3073
|
+
var SHAPES2 = destruction_default.shapes;
|
|
3074
|
+
var shapeDestruction = (shapeId) => SHAPES2[shapeId];
|
|
2976
3075
|
var FAMILY_OF_MODEL = new Map(Object.entries(FAMILIES).flatMap(([family, entry2]) => entry2.models.map((model) => [model, family])));
|
|
2977
3076
|
var itemFamily = (modelId) => FAMILY_OF_MODEL.get(modelId);
|
|
2978
3077
|
var itemDestruction = (modelId) => {
|
|
@@ -3088,9 +3187,9 @@ var GameItemsThree = (() => {
|
|
|
3088
3187
|
root.userData.tessellationTriangles = added;
|
|
3089
3188
|
}
|
|
3090
3189
|
function tagForDestruction(root, options = {}) {
|
|
3091
|
-
const { modelId, weight, size, three } = options;
|
|
3190
|
+
const { modelId, shapeId, weight, size, powder, three } = options;
|
|
3092
3191
|
if (weight !== void 0 && weight > 0) root.userData.destructionMass = weight;
|
|
3093
|
-
const rule = modelId
|
|
3192
|
+
const rule = modelId !== void 0 ? itemDestruction(modelId) : shapeId !== void 0 ? shapeDestruction(shapeId) : void 0;
|
|
3094
3193
|
if (rule?.tessellate) tessellateShapes(root, rule.tessellate, three);
|
|
3095
3194
|
const solid = [];
|
|
3096
3195
|
root.traverse((object2) => {
|
|
@@ -3105,6 +3204,7 @@ var GameItemsThree = (() => {
|
|
|
3105
3204
|
return;
|
|
3106
3205
|
}
|
|
3107
3206
|
if (rule?.hollow) mesh2.userData.hollow = true;
|
|
3207
|
+
if (powder) mesh2.userData.destructionPowder = { color: powder.color };
|
|
3108
3208
|
solid.push(mesh2);
|
|
3109
3209
|
});
|
|
3110
3210
|
if (!rule?.welded || solid.length < 2) return;
|
|
@@ -5587,8 +5687,168 @@ var GameItemsThree = (() => {
|
|
|
5587
5687
|
return G(mesh2(cyl(0.32, 0.32, 0.52), m), mesh2(cyl(0.326, 0.326, 0.34, 14), food(10172964)), mesh2(cyl(0.33, 0.33, 0.06), paper2(14861162), [0, 0.02, 0]), mesh2(torus2(0.31, 0.025), m, [0, 0.26, 0], [Math.PI / 2, 0, 0]), mesh2(torus2(0.31, 0.025), m, [0, -0.26, 0], [Math.PI / 2, 0, 0]));
|
|
5588
5688
|
};
|
|
5589
5689
|
|
|
5690
|
+
// src/data/opening.json
|
|
5691
|
+
var opening_default = {
|
|
5692
|
+
families: {
|
|
5693
|
+
drink_can: { style: "pull_tab" },
|
|
5694
|
+
food_tin: { style: "cut_lid" }
|
|
5695
|
+
},
|
|
5696
|
+
models: {
|
|
5697
|
+
empty_can: { style: "none" },
|
|
5698
|
+
canned_beans: { food: "#7a2e1c" },
|
|
5699
|
+
canned_corn_and_peas: { food: "#c7b03c" },
|
|
5700
|
+
canned_sausages: { food: "#c98d5c" },
|
|
5701
|
+
canned_sardines: { style: "peel_lid", food: "#8e979c" },
|
|
5702
|
+
condensed_milk: { food: "#e3cf9c" },
|
|
5703
|
+
energy_drink: { style: "pull_tab" },
|
|
5704
|
+
honey_jar: { style: "screw_cap", food: "#d99a1c" },
|
|
5705
|
+
home_preserves: { style: "screw_cap", food: "#8e1f3a" },
|
|
5706
|
+
cooking_oil: { style: "screw_cap", food: "#e3b830" },
|
|
5707
|
+
water_bottle: { style: "screw_cap" },
|
|
5708
|
+
water_jug_5l: { style: "screw_cap" },
|
|
5709
|
+
dirty_water: { style: "screw_cap" },
|
|
5710
|
+
sports_drink: { style: "screw_cap" },
|
|
5711
|
+
coconut_water: { style: "screw_cap" },
|
|
5712
|
+
cachaca: { style: "screw_cap" },
|
|
5713
|
+
communion_wine: { style: "screw_cap" }
|
|
5714
|
+
}
|
|
5715
|
+
};
|
|
5716
|
+
|
|
5717
|
+
// src/opening.ts
|
|
5718
|
+
var FAMILIES2 = opening_default.families;
|
|
5719
|
+
var MODELS = opening_default.models;
|
|
5720
|
+
var itemOpening = (modelId) => {
|
|
5721
|
+
const family = itemFamily(modelId);
|
|
5722
|
+
const row = { ...family === void 0 ? {} : FAMILIES2[family], ...MODELS[modelId] };
|
|
5723
|
+
if (row.style === void 0 || row.style === "none") return void 0;
|
|
5724
|
+
return { style: row.style, ...row.food === void 0 ? {} : { food: row.food } };
|
|
5725
|
+
};
|
|
5726
|
+
var OPENING_NAME = "opening";
|
|
5727
|
+
var INSIDE = 1315086;
|
|
5728
|
+
var CUT_EDGE = 14278114;
|
|
5729
|
+
var LID = 12172996;
|
|
5730
|
+
var isLid = (o) => o.userData.itemLid === true;
|
|
5731
|
+
var asLid = (mesh2) => {
|
|
5732
|
+
mesh2.userData.itemLid = true;
|
|
5733
|
+
return mesh2;
|
|
5734
|
+
};
|
|
5735
|
+
var localBox = (T2, root, only) => {
|
|
5736
|
+
root.updateMatrixWorld(true);
|
|
5737
|
+
const toRoot = new T2.Matrix4().copy(root.matrixWorld).invert();
|
|
5738
|
+
const box4 = new T2.Box3();
|
|
5739
|
+
const part = new T2.Box3();
|
|
5740
|
+
const m = new T2.Matrix4();
|
|
5741
|
+
root.traverse((o) => {
|
|
5742
|
+
const mesh2 = o;
|
|
5743
|
+
if (!mesh2.isMesh || mesh2.userData.destructionDebris || mesh2.name === OPENING_NAME || mesh2.parent?.name === OPENING_NAME) return;
|
|
5744
|
+
if (only && !only(mesh2)) return;
|
|
5745
|
+
if (!mesh2.geometry.boundingBox) mesh2.geometry.computeBoundingBox();
|
|
5746
|
+
part.copy(mesh2.geometry.boundingBox).applyMatrix4(m.multiplyMatrices(toRoot, mesh2.matrixWorld));
|
|
5747
|
+
box4.union(part);
|
|
5748
|
+
});
|
|
5749
|
+
return box4;
|
|
5750
|
+
};
|
|
5751
|
+
function openItem(T2, root, modelId) {
|
|
5752
|
+
const look = itemOpening(modelId);
|
|
5753
|
+
if (!look) return false;
|
|
5754
|
+
if (root.userData.itemOpened) return true;
|
|
5755
|
+
const box4 = look.style === "screw_cap" ? localBox(T2, root, isLid) : localBox(T2, root);
|
|
5756
|
+
if (box4.isEmpty()) return false;
|
|
5757
|
+
const size = box4.getSize(new T2.Vector3());
|
|
5758
|
+
const centre = box4.getCenter(new T2.Vector3());
|
|
5759
|
+
const top = look.style === "screw_cap" ? box4.min.y : box4.max.y;
|
|
5760
|
+
const lift = size.y * 3e-3;
|
|
5761
|
+
const sheet = Math.max(size.y * 6e-3, 1e-4);
|
|
5762
|
+
const group = new T2.Group();
|
|
5763
|
+
group.name = OPENING_NAME;
|
|
5764
|
+
group.position.set(centre.x, top, centre.z);
|
|
5765
|
+
const material = (color2, metal = 0) => new T2.MeshStandardMaterial({ color: color2, metalness: metal, roughness: metal ? 0.45 : 0.85, polygonOffset: true, polygonOffsetFactor: -2, polygonOffsetUnits: -2 });
|
|
5766
|
+
const add = (geometry, mat, y, parent = group) => {
|
|
5767
|
+
const mesh2 = new T2.Mesh(geometry, mat);
|
|
5768
|
+
mesh2.position.y = y;
|
|
5769
|
+
mesh2.renderOrder = 2;
|
|
5770
|
+
mesh2.userData.destructionDebris = true;
|
|
5771
|
+
mesh2.userData.itemOpening = true;
|
|
5772
|
+
parent.add(mesh2);
|
|
5773
|
+
return mesh2;
|
|
5774
|
+
};
|
|
5775
|
+
const flat = (geometry) => geometry.rotateX(-Math.PI / 2);
|
|
5776
|
+
const food = look.food ?? INSIDE;
|
|
5777
|
+
if (look.style === "screw_cap") {
|
|
5778
|
+
const r = Math.min(size.x, size.z) / 2;
|
|
5779
|
+
root.traverse((o) => isLid(o) && (o.visible = false));
|
|
5780
|
+
add(flat(new T2.CircleGeometry(r * 0.85, 24)), material(INSIDE), lift);
|
|
5781
|
+
if (look.food !== void 0) add(flat(new T2.CircleGeometry(r * 0.7, 24)), material(look.food), lift * 2).userData.itemFood = true;
|
|
5782
|
+
} else if (look.style === "pull_tab") {
|
|
5783
|
+
const r = Math.min(size.x, size.z) / 2;
|
|
5784
|
+
const mouth = add(flat(new T2.CircleGeometry(r * 0.2, 24)), material(INSIDE), lift);
|
|
5785
|
+
mouth.scale.set(1.15, 1, 0.85);
|
|
5786
|
+
mouth.position.z = r * 0.52;
|
|
5787
|
+
} else if (look.style === "cut_lid") {
|
|
5788
|
+
const r = Math.min(size.x, size.z) / 2;
|
|
5789
|
+
add(flat(new T2.CircleGeometry(r * 0.88, 40)), material(INSIDE), lift);
|
|
5790
|
+
add(flat(new T2.CircleGeometry(r * 0.76, 40)), material(food), lift * 2).userData.itemFood = true;
|
|
5791
|
+
add(flat(new T2.RingGeometry(r * 0.86, r * 0.9, 40)), material(CUT_EDGE, 0.9), lift * 3);
|
|
5792
|
+
const hinge = new T2.Group();
|
|
5793
|
+
hinge.position.set(0, lift, -r * 0.86);
|
|
5794
|
+
hinge.rotation.x = -1.95;
|
|
5795
|
+
group.add(hinge);
|
|
5796
|
+
const lid = add(new T2.CylinderGeometry(r * 0.86, r * 0.86, sheet, 40), material(LID, 0.4), 0, hinge);
|
|
5797
|
+
lid.position.z = r * 0.86;
|
|
5798
|
+
} else {
|
|
5799
|
+
const long = size.x >= size.z ? "x" : "z";
|
|
5800
|
+
const length = Math.max(size.x, size.z);
|
|
5801
|
+
const width = Math.min(size.x, size.z);
|
|
5802
|
+
const plane2 = (a, b) => flat(long === "x" ? new T2.PlaneGeometry(a, b) : new T2.PlaneGeometry(b, a));
|
|
5803
|
+
add(plane2(length * 0.92, width * 0.86), material(INSIDE), lift);
|
|
5804
|
+
add(plane2(length * 0.84, width * 0.76), material(food), lift * 2).userData.itemFood = true;
|
|
5805
|
+
const hinge = new T2.Group();
|
|
5806
|
+
const end = length * 0.46;
|
|
5807
|
+
if (long === "x") {
|
|
5808
|
+
hinge.position.set(end, lift, 0);
|
|
5809
|
+
hinge.rotation.z = -1.7;
|
|
5810
|
+
} else {
|
|
5811
|
+
hinge.position.set(0, lift, end);
|
|
5812
|
+
hinge.rotation.x = 1.7;
|
|
5813
|
+
}
|
|
5814
|
+
group.add(hinge);
|
|
5815
|
+
const lid = add(long === "x" ? new T2.BoxGeometry(length * 0.9, sheet, width * 0.84) : new T2.BoxGeometry(width * 0.84, sheet, length * 0.9), material(LID, 0.4), 0, hinge);
|
|
5816
|
+
if (long === "x") lid.position.x = -length * 0.45;
|
|
5817
|
+
else lid.position.z = -length * 0.45;
|
|
5818
|
+
}
|
|
5819
|
+
root.add(group);
|
|
5820
|
+
root.userData.itemOpened = true;
|
|
5821
|
+
return true;
|
|
5822
|
+
}
|
|
5823
|
+
var CAP_OFF = 1.6;
|
|
5824
|
+
function turnItem(root, modelId, state) {
|
|
5825
|
+
if (itemOpening(modelId)?.style !== "screw_cap") return false;
|
|
5826
|
+
root.traverse((o) => {
|
|
5827
|
+
var _a;
|
|
5828
|
+
if (!isLid(o)) return;
|
|
5829
|
+
const mesh2 = o;
|
|
5830
|
+
const base = (_a = mesh2.userData).lidBase ?? (_a.lidBase = { y: mesh2.position.y, turn: mesh2.rotation.y });
|
|
5831
|
+
if (!mesh2.geometry.boundingBox) mesh2.geometry.computeBoundingBox();
|
|
5832
|
+
const height = (mesh2.geometry.boundingBox.max.y - mesh2.geometry.boundingBox.min.y) * mesh2.scale.y;
|
|
5833
|
+
mesh2.rotation.y = base.turn + state.turned;
|
|
5834
|
+
mesh2.position.y = base.y + Math.min(1, Math.max(0, state.lift)) * height * CAP_OFF;
|
|
5835
|
+
});
|
|
5836
|
+
return true;
|
|
5837
|
+
}
|
|
5838
|
+
function setOpeningContents(root, share) {
|
|
5839
|
+
const opening = root.getObjectByName(OPENING_NAME);
|
|
5840
|
+
if (!opening) return;
|
|
5841
|
+
const left = Math.max(0, Math.min(1, share));
|
|
5842
|
+
opening.traverse((o) => {
|
|
5843
|
+
if (!o.userData.itemFood) return;
|
|
5844
|
+
o.visible = left > 0.02;
|
|
5845
|
+
const k = 0.35 + 0.65 * left;
|
|
5846
|
+
o.scale.set(k, 1, k);
|
|
5847
|
+
});
|
|
5848
|
+
}
|
|
5849
|
+
|
|
5590
5850
|
// src/models/water-bottle.ts
|
|
5591
|
-
var waterBottle = ({ mesh: mesh2, cyl, lathe: lathe2, G, plastic, paper: paper2, glass }) => G(mesh2(lathe2([[0, -0.6], [0.2, -0.6], [0.22, -0.5], [0.22, 0.2], [0.19, 0.32], [0.09, 0.45], [0.08, 0.55], [0, 0.55]]), glass(9421788, 0.55)), mesh2(cyl(0.085, 0.085, 0.1, 12), plastic(2907530), [0, 0.6, 0]), mesh2(cyl(0.225, 0.225, 0.22, 16), paper2(15330543), [0, -0.15, 0]), mesh2(cyl(0.226, 0.226, 0.05, 16), plastic(3831976), [0, -0.12, 0]));
|
|
5851
|
+
var waterBottle = ({ mesh: mesh2, cyl, lathe: lathe2, G, plastic, paper: paper2, glass }) => G(mesh2(lathe2([[0, -0.6], [0.2, -0.6], [0.22, -0.5], [0.22, 0.2], [0.19, 0.32], [0.09, 0.45], [0.08, 0.55], [0, 0.55]]), glass(9421788, 0.55)), asLid(mesh2(cyl(0.085, 0.085, 0.1, 12), plastic(2907530), [0, 0.6, 0])), mesh2(cyl(0.225, 0.225, 0.22, 16), paper2(15330543), [0, -0.15, 0]), mesh2(cyl(0.226, 0.226, 0.05, 16), plastic(3831976), [0, -0.12, 0]));
|
|
5592
5852
|
|
|
5593
5853
|
// src/models/rice.ts
|
|
5594
5854
|
var rice = ({ mesh: mesh2, bx, G, paper: paper2, food }) => G(mesh2(bx(0.7, 0.95, 0.28), paper2(15129792)), mesh2(bx(0.72, 0.12, 0.1), paper2(14010792), [0, 0.52, 0]), mesh2(bx(0.5, 0.3, 0.02), food(11883039), [0, 0.05, 0.15]), mesh2(bx(0.3, 0.1, 0.02), paper2(4160069), [0, -0.25, 0.15]));
|
|
@@ -5597,7 +5857,7 @@ var GameItemsThree = (() => {
|
|
|
5597
5857
|
var militaryRation = ({ mesh: mesh2, bx, G, plastic, paper: paper2 }) => G(mesh2(bx(0.75, 1, 0.22), plastic(5923142)), mesh2(bx(0.77, 0.1, 0.23), plastic(4672823), [0, 0.48, 0]), mesh2(bx(0.5, 0.14, 0.01), paper2(2237727), [0, 0.18, 0.115]), mesh2(bx(0.36, 0.06, 0.01), paper2(2237727), [0, -0.02, 0.115]));
|
|
5598
5858
|
|
|
5599
5859
|
// src/models/cachaca.ts
|
|
5600
|
-
var cachaca = ({ mesh: mesh2, cyl, lathe: lathe2, G, wood, paper: paper2, food, glass }) => G(mesh2(lathe2([[0, -0.6], [0.25, -0.6], [0.27, -0.52], [0.27, 0.1], [0.2, 0.25], [0.09, 0.35], [0.09, 0.58], [0, 0.58]]), glass(12749354, 0.78)), mesh2(cyl(0.08, 0.07, 0.14, 10), wood(9071172), [0, 0.64, 0]), mesh2(cyl(0.275, 0.275, 0.34, 16), paper2(15327692), [0, -0.25, 0]), mesh2(cyl(0.276, 0.276, 0.06, 16), food(8007455), [0, -0.15, 0]));
|
|
5860
|
+
var cachaca = ({ mesh: mesh2, cyl, lathe: lathe2, G, wood, paper: paper2, food, glass }) => G(mesh2(lathe2([[0, -0.6], [0.25, -0.6], [0.27, -0.52], [0.27, 0.1], [0.2, 0.25], [0.09, 0.35], [0.09, 0.58], [0, 0.58]]), glass(12749354, 0.78)), asLid(mesh2(cyl(0.08, 0.07, 0.14, 10), wood(9071172), [0, 0.64, 0])), mesh2(cyl(0.275, 0.275, 0.34, 16), paper2(15327692), [0, -0.25, 0]), mesh2(cyl(0.276, 0.276, 0.06, 16), food(8007455), [0, -0.15, 0]));
|
|
5601
5861
|
|
|
5602
5862
|
// src/models/first-aid-kit.ts
|
|
5603
5863
|
var firstAidKit = ({ mesh: mesh2, bx, torus: torus2, G, plastic }) => {
|
|
@@ -5813,7 +6073,7 @@ var GameItemsThree = (() => {
|
|
|
5813
6073
|
mesh2(cyl(0.41, 0.41, 0.86, 12), food(9314106), [0, -0.2, 0]),
|
|
5814
6074
|
mesh2(cyl(0.34, 0.445, 0.12, 12), glass(13625070, 0.5), [0, 0.39, 0]),
|
|
5815
6075
|
mesh2(cyl(0.34, 0.34, 0.05, 12), glass(13625070, 0.5), [0, 0.475, 0]),
|
|
5816
|
-
mesh2(cyl(0.38, 0.38, 0.15, 12), metal(12163644), [0, 0.575, 0]),
|
|
6076
|
+
asLid(mesh2(cyl(0.38, 0.38, 0.15, 12), metal(12163644), [0, 0.575, 0])),
|
|
5817
6077
|
mesh2(cyl(0.45, 0.45, 0.4, 12), paper2(15327172), [0, -0.2, 0]),
|
|
5818
6078
|
mesh2(cyl(0.452, 0.452, 0.08, 12), cloth2(10172986), [0, -0.2, 0])
|
|
5819
6079
|
);
|
|
@@ -6018,7 +6278,7 @@ var GameItemsThree = (() => {
|
|
|
6018
6278
|
mesh2(cyl(0.395, 0.395, 0.68, 12), glass(14925936, 0.55), [0, -0.16, 0]),
|
|
6019
6279
|
mesh2(cyl(0.37, 0.37, 0.6, 12), food(14260764), [0, -0.2, 0]),
|
|
6020
6280
|
mesh2(cyl(0.3, 0.395, 0.14, 12), glass(14925936, 0.55), [0, 0.25, 0]),
|
|
6021
|
-
mesh2(cyl(0.3, 0.3, 0.18, 12), metal(7031324), [0, 0.41, 0]),
|
|
6281
|
+
asLid(mesh2(cyl(0.3, 0.3, 0.18, 12), metal(7031324), [0, 0.41, 0])),
|
|
6022
6282
|
mesh2(cyl(0.4, 0.4, 0.34, 12), paper2(15853512), [0, -0.2, 0]),
|
|
6023
6283
|
mesh2(cyl(0.402, 0.402, 0.05, 12), paper2(9067028), [0, -0.1, 0]),
|
|
6024
6284
|
mesh2(cyl(0.402, 0.402, 0.05, 12), paper2(9067028), [0, -0.3, 0])
|
|
@@ -6122,7 +6382,7 @@ var GameItemsThree = (() => {
|
|
|
6122
6382
|
mesh2(cyl(0.345, 0.345, 1.7, 12), glass(14923824, 0.65), [0, -0.45, 0]),
|
|
6123
6383
|
mesh2(cyl(0.12, 0.345, 0.5, 12), glass(14923824, 0.65), [0, 0.65, 0]),
|
|
6124
6384
|
mesh2(cyl(0.12, 0.12, 0.25, 12), glass(14923824, 0.65), [0, 1.025, 0]),
|
|
6125
|
-
mesh2(cyl(0.14, 0.14, 0.15, 12), plastic(4160042), [0, 1.225, 0]),
|
|
6385
|
+
asLid(mesh2(cyl(0.14, 0.14, 0.15, 12), plastic(4160042), [0, 1.225, 0])),
|
|
6126
6386
|
mesh2(cyl(0.35, 0.35, 0.8, 12), paper2(15853512), [0, -0.5, 0]),
|
|
6127
6387
|
mesh2(cyl(0.352, 0.352, 0.2, 12), paper2(4160042), [0, -0.5, 0])
|
|
6128
6388
|
);
|
|
@@ -6160,7 +6420,7 @@ var GameItemsThree = (() => {
|
|
|
6160
6420
|
const body = mesh2(bx(1.5, 2.3, 1.5), glass(10473710, 0.75), [0, -0.5, 0]);
|
|
6161
6421
|
const shoulder = mesh2(bx(1.2, 0.45, 1.2), glass(10473710, 0.75), [0, 0.875, 0]);
|
|
6162
6422
|
const neck = mesh2(cyl(0.34, 0.34, 0.3, 12), dark, [0, 1.25, 0]);
|
|
6163
|
-
const cap = mesh2(cyl(0.4, 0.4, 0.25, 12), dark, [0, 1.525, 0]);
|
|
6423
|
+
const cap = asLid(mesh2(cyl(0.4, 0.4, 0.25, 12), dark, [0, 1.525, 0]));
|
|
6164
6424
|
const grip = mesh2(bx(0.16, 0.9, 0.3), dark, [1.07, 0.6, 0]);
|
|
6165
6425
|
const upperBar = mesh2(bx(0.45, 0.16, 0.3), dark, [0.925, 0.97, 0]);
|
|
6166
6426
|
const lowerBar = mesh2(bx(0.45, 0.16, 0.3), dark, [0.925, 0.23, 0]);
|
|
@@ -6175,7 +6435,7 @@ var GameItemsThree = (() => {
|
|
|
6175
6435
|
const label = mesh2(cyl(0.332, 0.332, 0.7, 12), paper2(1448738), [0, -0.12, 0]);
|
|
6176
6436
|
const stripe = mesh2(cyl(0.332, 0.332, 0.1, 12), paper2(15753232), [0, 0.28, 0]);
|
|
6177
6437
|
const collar = mesh2(cyl(0.2, 0.2, 0.04, 12), plastic(15263976), [0, 0.705, 0]);
|
|
6178
|
-
const cap = mesh2(cyl(0.19, 0.19, 0.2, 12), plastic(15753232), [0, 0.815, 0]);
|
|
6438
|
+
const cap = asLid(mesh2(cyl(0.19, 0.19, 0.2, 12), plastic(15753232), [0, 0.815, 0]));
|
|
6179
6439
|
return G(bottle2, label, stripe, collar, cap);
|
|
6180
6440
|
};
|
|
6181
6441
|
|
|
@@ -6222,7 +6482,7 @@ var GameItemsThree = (() => {
|
|
|
6222
6482
|
const goldBand = mesh2(cyl(0.382, 0.382, 0.05, 12), metal(11896880), [0, 0.075, 0]);
|
|
6223
6483
|
const crossUpright = mesh2(bx(0.06, 0.26, 0.02), paper2(8003371), [0, -0.35, 0.375]);
|
|
6224
6484
|
const crossArm = mesh2(bx(0.18, 0.06, 0.02), paper2(8003371), [0, -0.3, 0.375]);
|
|
6225
|
-
const foil = mesh2(cyl(0.15, 0.15, 0.46, 12), metal(11896880), [0, 1.27, 0]);
|
|
6485
|
+
const foil = asLid(mesh2(cyl(0.15, 0.15, 0.46, 12), metal(11896880), [0, 1.27, 0]));
|
|
6226
6486
|
return G(bottle2, label, goldBand, crossUpright, crossArm, foil);
|
|
6227
6487
|
};
|
|
6228
6488
|
|
|
@@ -6233,7 +6493,7 @@ var GameItemsThree = (() => {
|
|
|
6233
6493
|
const nut = mesh2(cyl(0.11, 0.11, 0.03, 10), paper2(7031339), [0, -0.12, 0.285], [Math.PI / 2, 0, 0]);
|
|
6234
6494
|
const leafLeft = mesh2(bx(0.2, 0.05, 0.01), paper2(15135448), [-0.12, 0.08, 0.292], [0, 0, 0.5]);
|
|
6235
6495
|
const leafRight = mesh2(bx(0.2, 0.05, 0.01), paper2(15135448), [0.12, 0.08, 0.292], [0, 0, -0.5]);
|
|
6236
|
-
const cap = mesh2(cyl(0.14, 0.14, 0.2, 12), plastic(4165450), [0, 0.75, 0]);
|
|
6496
|
+
const cap = asLid(mesh2(cyl(0.14, 0.14, 0.2, 12), plastic(4165450), [0, 0.75, 0]));
|
|
6237
6497
|
return G(bottle2, label, nut, leafLeft, leafRight, cap);
|
|
6238
6498
|
};
|
|
6239
6499
|
|
|
@@ -6243,7 +6503,7 @@ var GameItemsThree = (() => {
|
|
|
6243
6503
|
const murk = mesh2(lathe2([[0, -0.89], [0.27, -0.89], [0.315, -0.84], [0.315, 0.1], [0, 0.1]], 12), food(7035444));
|
|
6244
6504
|
const sediment = mesh2(cyl(0.31, 0.27, 0.12, 8), food(4865314), [0, -0.82, 0]);
|
|
6245
6505
|
const label = mesh2(cyl(0.332, 0.332, 0.22, 12), paper2(13617588), [0, 0.38, 0]);
|
|
6246
|
-
const cap = mesh2(cyl(0.19, 0.19, 0.2, 8), plastic(5922920), [0, 0.815, 0]);
|
|
6506
|
+
const cap = asLid(mesh2(cyl(0.19, 0.19, 0.2, 8), plastic(5922920), [0, 0.815, 0]));
|
|
6247
6507
|
return G(bottle2, murk, sediment, label, cap);
|
|
6248
6508
|
};
|
|
6249
6509
|
|
|
@@ -9232,7 +9492,7 @@ var GameItemsThree = (() => {
|
|
|
9232
9492
|
const materials = kit.materials.slice(first);
|
|
9233
9493
|
if (options.wear) setWear(materials, options.wear);
|
|
9234
9494
|
root.userData.wear = options.wear ?? 0;
|
|
9235
|
-
if (options.destructible) tagForDestruction(root, { ...kind === "model" && item.model !== void 0 ? { modelId: item.model } : {}, ...item.weight === void 0 ? {} : { weight: item.weight }, size: item.size, three: T2 });
|
|
9495
|
+
if (options.destructible) tagForDestruction(root, { ...kind === "model" && item.model !== void 0 ? { modelId: item.model } : {}, ...shape === void 0 ? {} : { shapeId: shape }, ...item.weight === void 0 ? {} : { weight: item.weight }, size: item.size, ...item.powder ? { powder: item.powder } : {}, three: T2 });
|
|
9236
9496
|
markKitOrigin(root, { owner: "game-items-three", kind: "item", id: item.id, ...kind === "shape" ? { standIn: true } : {} });
|
|
9237
9497
|
return { root, kind, ...shape ? { shape } : {}, size: item.size, materials };
|
|
9238
9498
|
}
|
|
@@ -15147,6 +15407,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
15147
15407
|
var FLAMMABLE_FLUIDS = ["gas", "fuel"];
|
|
15148
15408
|
var VENT_DIAMETER = 8e-3;
|
|
15149
15409
|
var FLAME_LIGHTS_LEAK_C = 470;
|
|
15410
|
+
var RESTING_HOLD_COS = Math.cos(Math.PI / 6);
|
|
15150
15411
|
var BREACH_RADIUS = 0.55;
|
|
15151
15412
|
var BREACH_BLAST_FACTOR = 6;
|
|
15152
15413
|
var BREACH_AREA = 0.25;
|
|
@@ -15162,6 +15423,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
15162
15423
|
var BREACH_GRID_CAP = 4096;
|
|
15163
15424
|
var CHIP_ENERGY = 200;
|
|
15164
15425
|
var CHIP_SPLASH = 0.5;
|
|
15426
|
+
var CRATER_SPENT = 0.6;
|
|
15427
|
+
var EDGE_REACH = 1.5;
|
|
15165
15428
|
var BAR_BOW = 0.08;
|
|
15166
15429
|
var BULLET_JOINT_SPAN = 0.3;
|
|
15167
15430
|
var CUT_SLICE = 1;
|
|
@@ -15182,12 +15445,22 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
15182
15445
|
const cells = p.st.chipped;
|
|
15183
15446
|
if (!cells?.length) return 0;
|
|
15184
15447
|
const [u, v] = planeAxes(p.thin);
|
|
15185
|
-
const
|
|
15448
|
+
const role = p.spec.structure?.role;
|
|
15449
|
+
const up = rotateVec(p.q, [0, 0, 0].map((_, k) => k === v ? 1 : 0));
|
|
15450
|
+
const upright = Math.abs(up[1]) > 0.7 ? v : Math.abs(rotateVec(p.q, [0, 0, 0].map((_, k) => k === u ? 1 : 0))[1]) > 0.7 ? u : -1;
|
|
15451
|
+
const along = (role === "wall" || role === "partition" || role === "column") && upright >= 0 ? upright : p.dims[u] >= p.dims[v] ? u : v;
|
|
15186
15452
|
const across2 = along === u ? v : u;
|
|
15187
15453
|
let worst = 0;
|
|
15188
15454
|
for (const c of cells) {
|
|
15189
|
-
|
|
15190
|
-
for (const d of cells) if (Math.abs(d.center[along] - c.center[along]) < d.size[along] / 2 + 1e-6)
|
|
15455
|
+
const spans = [];
|
|
15456
|
+
for (const d of cells) if (Math.abs(d.center[along] - c.center[along]) < d.size[along] / 2 + 1e-6) spans.push([d.center[across2] - d.size[across2] / 2, d.center[across2] + d.size[across2] / 2]);
|
|
15457
|
+
spans.sort((a, b) => a[0] - b[0]);
|
|
15458
|
+
let gone = 0, end = -Infinity;
|
|
15459
|
+
for (const [a, b] of spans) {
|
|
15460
|
+
if (b <= end) continue;
|
|
15461
|
+
gone += b - Math.max(a, end);
|
|
15462
|
+
end = b;
|
|
15463
|
+
}
|
|
15191
15464
|
worst = Math.max(worst, gone / Math.max(p.dims[across2], 1e-6));
|
|
15192
15465
|
}
|
|
15193
15466
|
return Math.min(1, worst);
|
|
@@ -15483,7 +15756,18 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
15483
15756
|
if (k < 0 || j.spec.kind !== "tie") return k;
|
|
15484
15757
|
return partXf(o, o.parts[k]).c[1] > partXf(o, o.parts[r]).c[1] + 1e-6 ? k : -1;
|
|
15485
15758
|
};
|
|
15759
|
+
let poseVersion = 0;
|
|
15760
|
+
const contactMemo = /* @__PURE__ */ new WeakMap();
|
|
15486
15761
|
const contactBox = (p, support) => {
|
|
15762
|
+
let byTouching = contactMemo.get(p);
|
|
15763
|
+
if (!byTouching) contactMemo.set(p, byTouching = /* @__PURE__ */ new Map());
|
|
15764
|
+
const known = byTouching.get(support);
|
|
15765
|
+
if (known && known.version === poseVersion) return known.box;
|
|
15766
|
+
const box4 = measureContact(p, support);
|
|
15767
|
+
byTouching.set(support, { version: poseVersion, box: box4 });
|
|
15768
|
+
return box4;
|
|
15769
|
+
};
|
|
15770
|
+
const measureContact = (p, support) => {
|
|
15487
15771
|
const A = aabbOf(p.spec.shape, p.pos, p.q), B = aabbOf(support.spec.shape, support.pos, support.q);
|
|
15488
15772
|
const lo = [0, 0, 0], hi = [0, 0, 0];
|
|
15489
15773
|
for (let k = 0; k < 3; k++) {
|
|
@@ -16278,7 +16562,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16278
16562
|
p.st.holes.push(hole);
|
|
16279
16563
|
if (p.st.holes.length > maxHoles) p.st.holes.shift();
|
|
16280
16564
|
markDamaged(p);
|
|
16281
|
-
emit({ ...base(o, src), type: "hole", part: p.spec.id, hole, worldPoint: wp, ...exit ? { exitPoint: exit } : {} });
|
|
16565
|
+
emit({ ...base(o, src), type: "hole", part: p.spec.id, hole, worldPoint: wp, ...exit ? { exitPoint: exit } : {}, ...p.spec.powder ? { powder: { ...p.spec.powder } } : {} });
|
|
16282
16566
|
setStage(o, p, 1, {}, src);
|
|
16283
16567
|
return hole;
|
|
16284
16568
|
};
|
|
@@ -16295,6 +16579,22 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16295
16579
|
const detachEvents = (o, opened, by, src) => {
|
|
16296
16580
|
for (const j of opened) emit({ ...base(o, src), type: "detach", joint: j.spec.id, parts: [j.spec.a, j.spec.b], by, groups: o.st.groups.map((g) => [...g]) });
|
|
16297
16581
|
};
|
|
16582
|
+
const slideOffResting = (o, rotation) => {
|
|
16583
|
+
const upY = 1 - 2 * (rotation[0] * rotation[0] + rotation[2] * rotation[2]);
|
|
16584
|
+
if (upY >= RESTING_HOLD_COS) return;
|
|
16585
|
+
const opened = o.joints.filter((j) => j.spec.kind === "resting" && !j.st.open);
|
|
16586
|
+
if (opened.length === 0) return;
|
|
16587
|
+
run(() => {
|
|
16588
|
+
for (const j of opened) {
|
|
16589
|
+
j.st.open = true;
|
|
16590
|
+
j.st.openedBy = "break";
|
|
16591
|
+
}
|
|
16592
|
+
solveStructure(o);
|
|
16593
|
+
recomputeGroups(o);
|
|
16594
|
+
detachEvents(o, opened, "break");
|
|
16595
|
+
collapseCheck(o);
|
|
16596
|
+
});
|
|
16597
|
+
};
|
|
16298
16598
|
const checkDestroyed = (o, src) => {
|
|
16299
16599
|
if (!o.st.destroyed && o.parts.length > 0 && o.parts.every(isLost)) {
|
|
16300
16600
|
o.st.destroyed = true;
|
|
@@ -16395,7 +16695,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16395
16695
|
const localHolesOf = (p) => p.st.holes.map((h) => ({ point: toLocal(p.pos, p.q, h.point), normal: rotateVec(quat.conjugate(p.q), h.normal), diameter: h.diameter }));
|
|
16396
16696
|
const unitsOf2 = (p) => p.spec.units ?? { size: [p.mat.fragmentSize?.[1] ?? 0.2, p.mat.fragmentSize?.[1] ?? 0.2, p.thickness], bond: "stack" };
|
|
16397
16697
|
const FRAGMENT_SHAPE = { shatter: "shard", splinter: "splinter", tear: "scrap" };
|
|
16398
|
-
const cellFragments = (o, p, cells, hitW, dir, speed, mass, tag) => {
|
|
16698
|
+
const cellFragments = (o, p, cells, hitW, dir, speed, mass, tag, inner = false) => {
|
|
16399
16699
|
const { c, q } = partXf(o, p);
|
|
16400
16700
|
const holes = p.st.holes.length > 0 ? localHolesOf(p) : [];
|
|
16401
16701
|
const [u, v] = planeAxes(p.thin);
|
|
@@ -16419,7 +16719,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16419
16719
|
velocity: [dv[0] * k, dv[1] * k + 0.5 * rnd(), dv[2] * k],
|
|
16420
16720
|
angularVelocity: [(rnd() - 0.5) * 8, (rnd() - 0.5) * 8, (rnd() - 0.5) * 8],
|
|
16421
16721
|
mass: mass * faceArea(cell) / total,
|
|
16422
|
-
...marks.length > 0 ? { marks } : {}
|
|
16722
|
+
...marks.length > 0 ? { marks } : {},
|
|
16723
|
+
...inner ? { inner } : {}
|
|
16423
16724
|
};
|
|
16424
16725
|
});
|
|
16425
16726
|
};
|
|
@@ -16460,7 +16761,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16460
16761
|
return cells.some((c) => Math.abs(lp[u] - c.center[u]) <= c.size[u] / 2 && Math.abs(lp[v] - c.center[v]) <= c.size[v] / 2);
|
|
16461
16762
|
};
|
|
16462
16763
|
const chipUnits = (o, p, kind, wp, hitEnergy, dir, radius, src) => {
|
|
16463
|
-
var _a, _b;
|
|
16764
|
+
var _a, _b, _c;
|
|
16464
16765
|
if (!p.spec.units || !p.staged || chipEnergy <= 0 || p.st.stripped || isLost(p) || (p.st.stage ?? 0) >= 2) return;
|
|
16465
16766
|
const rule = p.mat.hits?.[kind];
|
|
16466
16767
|
const perKg = rule?.unitJoules ?? chipEnergy;
|
|
@@ -16470,7 +16771,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16470
16771
|
const lp = toLocal(p.pos, p.q, objLocal(o, wp));
|
|
16471
16772
|
const grid = gridOf(p);
|
|
16472
16773
|
const worn = (_a = p.rt).chips ?? (_a.chips = {});
|
|
16774
|
+
const cut = (_b = p.rt).craters ?? (_b.craters = {});
|
|
16473
16775
|
const out = [];
|
|
16776
|
+
const shot = kind === "ballistic";
|
|
16474
16777
|
for (let i = 0; i < grid.length; i++) {
|
|
16475
16778
|
const cell = grid[i];
|
|
16476
16779
|
if (worn[i] === -1) continue;
|
|
@@ -16483,18 +16786,42 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16483
16786
|
worn[i] = total;
|
|
16484
16787
|
continue;
|
|
16485
16788
|
}
|
|
16486
|
-
|
|
16487
|
-
|
|
16789
|
+
if (!shot) {
|
|
16790
|
+
worn[i] = -1;
|
|
16791
|
+
out.push(cell);
|
|
16792
|
+
continue;
|
|
16793
|
+
}
|
|
16794
|
+
const size = [cell.size[0], cell.size[1], cell.size[2]];
|
|
16795
|
+
const center = [cell.center[0], cell.center[1], cell.center[2]];
|
|
16796
|
+
for (const a of [u, v]) {
|
|
16797
|
+
const w = Math.min(cell.size[a], craterAcross(hitEnergy) * (0.85 + 0.3 * rnd()));
|
|
16798
|
+
const lo = cell.center[a] - cell.size[a] / 2 + w / 2, hi = cell.center[a] + cell.size[a] / 2 - w / 2;
|
|
16799
|
+
size[a] = w;
|
|
16800
|
+
center[a] = clamp2(lp[a], lo, hi);
|
|
16801
|
+
const [from, to] = tornToEdge({ p, cell, a, b: a === u ? v : u, at: lp[a], crater: [center[a] - w / 2, center[a] + w / 2], reach: w * EDGE_REACH, gone: (k) => worn[k] === -1 });
|
|
16802
|
+
size[a] = to - from;
|
|
16803
|
+
center[a] = (from + to) / 2;
|
|
16804
|
+
}
|
|
16805
|
+
const taken2 = (cut[i] ?? 0) + size[u] * size[v];
|
|
16806
|
+
if (taken2 >= cell.size[u] * cell.size[v] * CRATER_SPENT) {
|
|
16807
|
+
worn[i] = -1;
|
|
16808
|
+
out.push({ ...cell, crater: true });
|
|
16809
|
+
continue;
|
|
16810
|
+
}
|
|
16811
|
+
worn[i] = 0;
|
|
16812
|
+
cut[i] = taken2;
|
|
16813
|
+
out.push({ center, size, crater: true });
|
|
16488
16814
|
}
|
|
16489
16815
|
if (out.length === 0) return;
|
|
16490
16816
|
const { c, q } = partXf(o, p);
|
|
16491
|
-
const chipped = (
|
|
16817
|
+
const chipped = (_c = p.st).chipped ?? (_c.chipped = []);
|
|
16492
16818
|
const holes = localHolesOf(p);
|
|
16493
16819
|
for (const cell of out) {
|
|
16494
16820
|
const mass = Math.min(p.st.mass, p.mat.density * cell.size[0] * cell.size[1] * cell.size[2]);
|
|
16495
16821
|
const center = toWorld(c, q, cell.center);
|
|
16496
16822
|
const speed = clamp2(Math.sqrt(2 * energy * 0.05 / Math.max(mass, 0.05)), 0.5, 6);
|
|
16497
|
-
const
|
|
16823
|
+
const tag = `c${chipped.length}_`;
|
|
16824
|
+
const fragments = cell.crater ? craterFragments(o, p, cell, dir, speed, mass, tag) : cellFragments(o, p, [cell], wp, dir, speed, mass, tag, true);
|
|
16498
16825
|
p.st.holes = p.st.holes.filter((_, k) => marksInBox(cell.center, cell.size, void 0, [holes[k]]).length === 0);
|
|
16499
16826
|
chipped.push({ center: [cell.center[0], cell.center[1], cell.center[2]], size: [cell.size[0], cell.size[1], cell.size[2]] });
|
|
16500
16827
|
p.st.mass = Math.max(0, p.st.mass - mass);
|
|
@@ -16511,6 +16838,57 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16511
16838
|
collapseCheck(o, src);
|
|
16512
16839
|
}
|
|
16513
16840
|
};
|
|
16841
|
+
const tornToEdge = (o) => {
|
|
16842
|
+
const { p, cell, a, b, at, crater: crater2, reach, gone } = o;
|
|
16843
|
+
const half = p.dims[a] / 2;
|
|
16844
|
+
const lo = cell.center[a] - cell.size[a] / 2, hi = cell.center[a] + cell.size[a] / 2;
|
|
16845
|
+
const free = (side, sign2) => {
|
|
16846
|
+
if (sign2 > 0 ? side >= half - 1e-6 : side <= -half + 1e-6) return sign2 > 0 || a !== planeAxes(p.thin)[1];
|
|
16847
|
+
const probe = side + sign2 * 1e-3;
|
|
16848
|
+
return gridOf(p).some((c, k) => gone(k) && Math.abs(probe - c.center[a]) <= c.size[a] / 2 && Math.abs(cell.center[b] - c.center[b]) <= c.size[b] / 2);
|
|
16849
|
+
};
|
|
16850
|
+
if (at - lo <= reach && free(lo, -1)) return [lo, Math.max(crater2[1], lo)];
|
|
16851
|
+
if (hi - at <= reach && free(hi, 1)) return [Math.min(crater2[0], hi), hi];
|
|
16852
|
+
return crater2;
|
|
16853
|
+
};
|
|
16854
|
+
const craterAcross = (energy) => clamp2(0.03 + 12e-4 * Math.sqrt(Math.max(0, energy)), 0.03, 0.14);
|
|
16855
|
+
const craterFragments = (o, p, cell, dir, speed, mass, tag) => {
|
|
16856
|
+
const { c, q } = partXf(o, p);
|
|
16857
|
+
const [u, v] = planeAxes(p.thin);
|
|
16858
|
+
const d = dir ?? rotateVec(q, [p.thin === 0 ? 1 : 0, p.thin === 1 ? 1 : 0, p.thin === 2 ? 1 : 0]);
|
|
16859
|
+
const exitSign = Math.sign(rotateVec(quat.conjugate(q), d)[p.thin]) || 1;
|
|
16860
|
+
const bit = Math.max(0.01, Math.min(cell.size[u], cell.size[v]) / 3);
|
|
16861
|
+
const n = clamp2(Math.round(cell.size[u] * cell.size[v] / (bit * bit * 3)), 4, 10) + Math.floor(rnd() * 3);
|
|
16862
|
+
const out = [];
|
|
16863
|
+
for (let i = 0; i < n; i++) {
|
|
16864
|
+
const back = i % 3 === 2;
|
|
16865
|
+
const lc = [cell.center[0], cell.center[1], cell.center[2]];
|
|
16866
|
+
lc[u] += (rnd() - 0.5) * cell.size[u] * 0.7;
|
|
16867
|
+
lc[v] += (rnd() - 0.5) * cell.size[v] * 0.7;
|
|
16868
|
+
lc[p.thin] += (back ? -exitSign : exitSign) * (p.thickness / 2 + 0.01);
|
|
16869
|
+
const size = [0, 0, 0];
|
|
16870
|
+
size[u] = bit * (0.6 + 0.8 * rnd());
|
|
16871
|
+
size[v] = bit * (0.5 + 0.7 * rnd());
|
|
16872
|
+
size[p.thin] = bit * (0.4 + 0.6 * rnd());
|
|
16873
|
+
const spread3 = [(rnd() - 0.5) * 0.9, (rnd() - 0.3) * 0.9, (rnd() - 0.5) * 0.9];
|
|
16874
|
+
const k = speed * (back ? 0.4 + 0.4 * rnd() : 0.7 + 0.8 * rnd());
|
|
16875
|
+
const vdir = vec.normalize(vec.add(back ? vec.scale(d, -1) : d, spread3));
|
|
16876
|
+
out.push({
|
|
16877
|
+
id: `${p.spec.id}#${tag}${i}`,
|
|
16878
|
+
part: p.spec.id,
|
|
16879
|
+
material: p.spec.material,
|
|
16880
|
+
shape: "chunk",
|
|
16881
|
+
center: toWorld(c, q, lc),
|
|
16882
|
+
size,
|
|
16883
|
+
rotation: q,
|
|
16884
|
+
velocity: [vdir[0] * k, vdir[1] * k + 0.5 * rnd(), vdir[2] * k],
|
|
16885
|
+
angularVelocity: [(rnd() - 0.5) * 20, (rnd() - 0.5) * 20, (rnd() - 0.5) * 20],
|
|
16886
|
+
mass: mass / n,
|
|
16887
|
+
inner: true
|
|
16888
|
+
});
|
|
16889
|
+
}
|
|
16890
|
+
return out;
|
|
16891
|
+
};
|
|
16514
16892
|
const exposeRebar = (o, p, src) => {
|
|
16515
16893
|
const r = p.spec.reinforcement;
|
|
16516
16894
|
if (!r) return;
|
|
@@ -16798,7 +17176,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16798
17176
|
});
|
|
16799
17177
|
}
|
|
16800
17178
|
const patch = [scale * 4, scale * 4, scale * 4];
|
|
16801
|
-
emit({ ...base(o, src), type: "chip", part: p.spec.id, center: exit ?? entry2, size: patch, rotation: q, fragments });
|
|
17179
|
+
emit({ ...base(o, src), type: "chip", part: p.spec.id, center: exit ?? entry2, size: patch, rotation: q, fragments, torn: true });
|
|
16802
17180
|
};
|
|
16803
17181
|
const ballistic = (o, p, entry2, n, d, E, caliber, pathLen, src, round3 = {}) => {
|
|
16804
17182
|
const mat = p.mat;
|
|
@@ -16857,12 +17235,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16857
17235
|
} else if (mat.ductility >= 0.5) {
|
|
16858
17236
|
addDent(o, p, entry2, n, Math.max(caliber * 3 / 1e3, 0.012), clamp2(Math.min(Math.max(p.thickness * 3, 3e-3), ratio * 0.01), 1e-3, 0.05), src);
|
|
16859
17237
|
} else if (brittle) {
|
|
16860
|
-
addCrack(o, p, entry2, n, crackLen, src);
|
|
17238
|
+
if (!p.spec.units) addCrack(o, p, entry2, n, crackLen, src);
|
|
16861
17239
|
if (mat.fracture !== "shatter") addHole(o, p, entry2, n, caliber / 1e3, false, void 0, src);
|
|
16862
17240
|
} else addHole(o, p, entry2, n, caliber / 1e3, false, void 0, src);
|
|
16863
17241
|
debris(o, p, mat.hitDebris, entry2, n, clamp2(Math.round(E / 60) + 2, 2, 14), clamp2(Math.sqrt(E) / 6, 1, 8), src);
|
|
16864
17242
|
wearJoints(o, p, (penetrated ? thr : E) * 0.02, void 0, 0, src, true, BULLET_JOINT_SPAN);
|
|
16865
|
-
const
|
|
17243
|
+
const hollowTear = mat.fracture === "tear" && p.spec.fill !== void 0 && p.spec.fill < 0.5;
|
|
17244
|
+
const absorbed = penetrated && (mat.ductility >= 0.5 && mat.fracture !== "tear" || hollowTear) ? Math.min(E, thr) : E;
|
|
16866
17245
|
const dmg = applyDamage(o, p, absorbed * DMG_PER_J * scale, "ballistic", entry2, d, absorbed * 0.1, 12, src);
|
|
16867
17246
|
if (!isLost(p)) tearAt(o, p, "ballistic", entry2, penetrated ? exitPoint : void 0, d, E, caliber / 1e3, src);
|
|
16868
17247
|
chipUnits(o, p, "ballistic", entry2, penetrated ? Math.min(E, Math.max(thr, E * 0.5)) : E, d, Math.max(0.05, caliber / 1e3 * 8), src);
|
|
@@ -16947,10 +17326,25 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16947
17326
|
if (dist <= BREACH_BLAST_REACH * Math.cbrt(Math.max(0, energy) / 1e3)) addBreach(o, p, wp, breachAreaOf(p, dealt, true), Ein, null, src);
|
|
16948
17327
|
return reach;
|
|
16949
17328
|
};
|
|
17329
|
+
const blastProbe = { partsTested: 0, partsNear: 0 };
|
|
17330
|
+
const blastCandidates = (o, point, radius) => {
|
|
17331
|
+
const local = toLocal(o.st.position, o.st.rotation, point);
|
|
17332
|
+
const near = [];
|
|
17333
|
+
for (const p of o.parts) {
|
|
17334
|
+
const reach = radius + p.bound;
|
|
17335
|
+
const dx = local[0] - p.pos[0];
|
|
17336
|
+
const dy = local[1] - p.pos[1];
|
|
17337
|
+
const dz = local[2] - p.pos[2];
|
|
17338
|
+
if (dx * dx + dy * dy + dz * dz < reach * reach) near.push(p);
|
|
17339
|
+
}
|
|
17340
|
+
blastProbe.partsTested += o.parts.length;
|
|
17341
|
+
blastProbe.partsNear += near.length;
|
|
17342
|
+
return near;
|
|
17343
|
+
};
|
|
16950
17344
|
const blastObject = (o, point, energy, radius, src) => {
|
|
16951
17345
|
const start = cur.length;
|
|
16952
17346
|
const res = { object: o.id, damage: 0, penetrated: false, exitEnergy: 0, events: [] };
|
|
16953
|
-
for (const p of o
|
|
17347
|
+
for (const p of blastCandidates(o, point, radius)) blastPart(o, p, point, energy, radius, src, res);
|
|
16954
17348
|
res.events = cur.slice(start);
|
|
16955
17349
|
return res;
|
|
16956
17350
|
};
|
|
@@ -17074,7 +17468,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
17074
17468
|
let order = 0;
|
|
17075
17469
|
for (const o of inRange) {
|
|
17076
17470
|
if (only && only !== o) continue;
|
|
17077
|
-
for (const p of o
|
|
17471
|
+
for (const p of blastCandidates(o, point, radius)) {
|
|
17078
17472
|
if (isLost(p)) continue;
|
|
17079
17473
|
const dist = distToPart(o, p, point);
|
|
17080
17474
|
if (dist < radius) items.push({ dist, order: order++, o, p });
|
|
@@ -17621,6 +18015,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
17621
18015
|
const p = getPart(o, partId);
|
|
17622
18016
|
p.pos = [position[0], position[1], position[2]];
|
|
17623
18017
|
p.q = q;
|
|
18018
|
+
poseVersion++;
|
|
17624
18019
|
updateBound(o);
|
|
17625
18020
|
},
|
|
17626
18021
|
remove(id) {
|
|
@@ -17639,6 +18034,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
17639
18034
|
const o = getObj(id);
|
|
17640
18035
|
o.base = { pos: [position[0], position[1], position[2]], rot: [rotation[0], rotation[1], rotation[2], rotation[3]] };
|
|
17641
18036
|
applySoilPose(o);
|
|
18037
|
+
slideOffResting(o, rotation);
|
|
17642
18038
|
},
|
|
17643
18039
|
splitGroup(id, group, newId) {
|
|
17644
18040
|
if (impls.has(id)) throw new Error(`object "${id}" is a registered DestructibleImpl and cannot be split; its module owns its pieces`);
|
|
@@ -17662,7 +18058,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
17662
18058
|
if (o.spec.name !== void 0) s.name = o.spec.name;
|
|
17663
18059
|
if (o.spec.tags) s.tags = [...o.spec.tags];
|
|
17664
18060
|
if (o.spec.soil !== void 0) s.soil = o.spec.soil;
|
|
17665
|
-
return
|
|
18061
|
+
return s;
|
|
17666
18062
|
};
|
|
17667
18063
|
const inNew = (pid) => moved.has(pid);
|
|
17668
18064
|
const inOld = (pid) => !moved.has(pid);
|
|
@@ -17689,7 +18085,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
17689
18085
|
const p = getPart(o, partId);
|
|
17690
18086
|
return whole(() => doHit(o, h, p));
|
|
17691
18087
|
},
|
|
18088
|
+
blastProbe() {
|
|
18089
|
+
return { ...blastProbe };
|
|
18090
|
+
},
|
|
17692
18091
|
explode(point, energy, radius, source, blast) {
|
|
18092
|
+
blastProbe.partsTested = 0;
|
|
18093
|
+
blastProbe.partsNear = 0;
|
|
17693
18094
|
return withCollapses(run(() => blastWorld(point, energy, radius, source, blast)));
|
|
17694
18095
|
},
|
|
17695
18096
|
raycast(origin, direction, maxDistance = Infinity) {
|
|
@@ -17699,7 +18100,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
17699
18100
|
sweepBox(box4, direction, distance2, options2 = {}) {
|
|
17700
18101
|
const d = vec.normalize(direction);
|
|
17701
18102
|
const ignored = options2.ignore === void 0 ? void 0 : objects.get(options2.ignore);
|
|
17702
|
-
const
|
|
18103
|
+
const hosted = options2.ignore === void 0 || ignored ? void 0 : impls.get(options2.ignore);
|
|
18104
|
+
const ignore = ignored ? new Set(ignored.parts.map((p) => `${ignored.id}\0${p.spec.id}`)) : hosted ? new Set(hosted.impl.describe().parts.map((p) => `${hosted.impl.id}\0${p.id}`)) : void 0;
|
|
17703
18105
|
let best = null;
|
|
17704
18106
|
for (const origin of sweepOrigins(box4, d, options2.spacing ?? 0.2)) {
|
|
17705
18107
|
const r = raycastInternal(origin, d, distance2 + SWEEP_BACK, ignore);
|
|
@@ -21142,9 +21544,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21142
21544
|
var SHARED_ROOMS = { west: { type: "laundry", label: "laundry_room" }, east: { type: "storage", label: "storage_room" } };
|
|
21143
21545
|
var apartments = (plan) => (strip, { floor, plate, ceiling }) => {
|
|
21144
21546
|
if (strip.length < plan.apartmentMin) {
|
|
21145
|
-
const
|
|
21146
|
-
const id = `${
|
|
21147
|
-
return { rooms: [{ id, type:
|
|
21547
|
+
const shared2 = SHARED_ROOMS[strip.id] ?? SHARED_ROOMS.east;
|
|
21548
|
+
const id = `${shared2.label}_${floor}_${strip.id}`;
|
|
21549
|
+
return { rooms: [{ id, type: shared2.type, label: shared2.label, rect: [...strip.rect] }], doors: [stripDoor(id, strip, floor, 0.9)], windows: exteriorWindows(id, strip.rect, plate, ceiling, { ...plan.window, width: 1.2 }) };
|
|
21148
21550
|
}
|
|
21149
21551
|
const count = Math.max(1, Math.round(strip.length / plan.apartment)), wide = strip.length / count;
|
|
21150
21552
|
const parts = Array.from({ length: count }, (_, k) => apartment(strip, floor, k, r22(k * wide), r22((k + 1) * wide), plate, ceiling, plan.window));
|
|
@@ -21258,7 +21660,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21258
21660
|
var OPEN_ROOM_TYPES2 = /* @__PURE__ */ new Set(["balcony", "terrace", "veranda", "balcony_gourmet"]);
|
|
21259
21661
|
var rectsOf = (c) => c.parts && c.parts.length ? c.parts : [[c.u0, c.v0, c.u1, c.v1]];
|
|
21260
21662
|
var isOpenArea = (c) => OPEN_ROOM_TYPES2.has(c.type) || c.outdoor === true;
|
|
21261
|
-
function installKernelGeometry(K,
|
|
21663
|
+
function installKernelGeometry(K, shared2) {
|
|
21262
21664
|
const { THREE } = K;
|
|
21263
21665
|
const GEO = {};
|
|
21264
21666
|
{
|
|
@@ -21317,9 +21719,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21317
21719
|
const cursor = { group: "lot", accs: /* @__PURE__ */ new Map(), rot: [], org: [0, 0, 0], ry: 0 };
|
|
21318
21720
|
const PARTS = [];
|
|
21319
21721
|
const MIRRORS = [];
|
|
21320
|
-
|
|
21722
|
+
shared2.partCount = 0;
|
|
21321
21723
|
function part(type, pos, fn, meta = {}, parent, ry = 0) {
|
|
21322
|
-
const gA = cursor.group, oA = cursor.org, rA = cursor.ry, pieceA = cursor.pc, name = "part:" + (meta.id || type) + ":" +
|
|
21724
|
+
const gA = cursor.group, oA = cursor.org, rA = cursor.ry, pieceA = cursor.pc, name = "part:" + (meta.id || type) + ":" + shared2.partCount++;
|
|
21323
21725
|
PARTS.push({ name, parent: parent || gA, pos: pos.slice(), type, meta, ry });
|
|
21324
21726
|
cursor.group = name;
|
|
21325
21727
|
cursor.org = pos;
|
|
@@ -21354,7 +21756,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21354
21756
|
}
|
|
21355
21757
|
const _Y = new THREE.Vector3(0, 1, 0), _qa = new THREE.Quaternion(), _qb = new THREE.Quaternion();
|
|
21356
21758
|
function pieceRecord(id, mat, role, extra) {
|
|
21357
|
-
const M =
|
|
21759
|
+
const M = shared2.ctx.pieces;
|
|
21358
21760
|
let p = M.get(id);
|
|
21359
21761
|
if (!p) {
|
|
21360
21762
|
p = Object.assign({ id, mat, role: role || null }, extra);
|
|
@@ -21363,7 +21765,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21363
21765
|
return p;
|
|
21364
21766
|
}
|
|
21365
21767
|
const structurePiece = (id) => {
|
|
21366
|
-
const e =
|
|
21768
|
+
const e = shared2.ctx.structureIndex && shared2.ctx.structureIndex[id];
|
|
21367
21769
|
return e ? pieceRecord(id, e.material, e.role, { floor: e.floor }) : null;
|
|
21368
21770
|
};
|
|
21369
21771
|
function accFor(mat) {
|
|
@@ -21812,7 +22214,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21812
22214
|
const NO_SHADOW = /* @__PURE__ */ new Set(["dirt", "glass", "water", "screen", "building", "picture", "floor", "emissive"]);
|
|
21813
22215
|
Object.assign(K, { createMaterials, antiTile, dirtMaterial, CLOTHES_UNIFORMS, clothesMaterial, ORDER, NO_SHADOW });
|
|
21814
22216
|
}
|
|
21815
|
-
function installKernelCloseScene(K,
|
|
22217
|
+
function installKernelCloseScene(K, shared2) {
|
|
21816
22218
|
const { THREE, NO_SHADOW, ORDER, PARTS, applyPart, cursor } = K;
|
|
21817
22219
|
const assembleCars = (...a) => K.assembleCars(...a);
|
|
21818
22220
|
const assembleMirrors = (...a) => K.assembleMirrors(...a);
|
|
@@ -21827,7 +22229,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21827
22229
|
if (!fx.length) return;
|
|
21828
22230
|
const u = m.userData, ids = [...new Set(fx.map((f) => f.id))], weight = {};
|
|
21829
22231
|
for (const f of fx) {
|
|
21830
|
-
const mt =
|
|
22232
|
+
const mt = shared2.ctx.pieces.get(f.id).mat;
|
|
21831
22233
|
weight[mt] = (weight[mt] || 0) + f.v1 - f.v0;
|
|
21832
22234
|
}
|
|
21833
22235
|
u.ranges = fx;
|
|
@@ -21835,7 +22237,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21835
22237
|
u.destructionMaterial = Object.keys(weight).sort((a, b) => weight[b] - weight[a])[0];
|
|
21836
22238
|
if (ids.length === 1) {
|
|
21837
22239
|
u.destructionPart = ids[0];
|
|
21838
|
-
const pc =
|
|
22240
|
+
const pc = shared2.ctx.pieces.get(ids[0]);
|
|
21839
22241
|
if (pc.role) u.structuralRole = pc.role;
|
|
21840
22242
|
}
|
|
21841
22243
|
}
|
|
@@ -21878,7 +22280,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21878
22280
|
if (P.meta.t0) applyPart(g, P.meta.t0);
|
|
21879
22281
|
}
|
|
21880
22282
|
(groups[P.parent] || (groups[P.parent] = new THREE.Group())).add(g);
|
|
21881
|
-
if (P.meta.id) (
|
|
22283
|
+
if (P.meta.id) (shared2.ctx.parts || (shared2.ctx.parts = {}))[P.meta.id] = g;
|
|
21882
22284
|
}
|
|
21883
22285
|
PARTS.length = 0;
|
|
21884
22286
|
assembleMirrors(groups);
|
|
@@ -21888,20 +22290,20 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21888
22290
|
}
|
|
21889
22291
|
Object.assign(K, { markMesh, closeScene });
|
|
21890
22292
|
}
|
|
21891
|
-
function installHouseHelpers(K,
|
|
21892
|
-
|
|
22293
|
+
function installHouseHelpers(K, shared2) {
|
|
22294
|
+
shared2.ctx = {};
|
|
21893
22295
|
const OPEN_ROOM_TYPES22 = /* @__PURE__ */ new Set(["balcony", "terrace", "veranda", "balcony_gourmet"]);
|
|
21894
22296
|
const NO_CEILING = OPEN_ROOM_TYPES22;
|
|
21895
22297
|
const OPEN_AREA = (c) => OPEN_ROOM_TYPES22.has(c.type) || c.outdoor === true;
|
|
21896
22298
|
const EPS3 = 1e-3;
|
|
21897
22299
|
const Y0 = (f) => {
|
|
21898
|
-
const A =
|
|
22300
|
+
const A = shared2.ctx.r.floors;
|
|
21899
22301
|
return A[Math.max(0, Math.min(A.length - 1, f))].y0;
|
|
21900
22302
|
};
|
|
21901
|
-
const colorOf = (v) => typeof v === "number" ? v : typeof v === "string" &&
|
|
22303
|
+
const colorOf = (v) => typeof v === "number" ? v : typeof v === "string" && shared2.ctx.colors[v] != null ? shared2.ctx.colors[v] : null;
|
|
21902
22304
|
const rectsOf2 = (c) => c.parts && c.parts.length ? c.parts : [[c.u0, c.v0, c.u1, c.v1]];
|
|
21903
22305
|
function roomAt(f, u, v) {
|
|
21904
|
-
for (const c of
|
|
22306
|
+
for (const c of shared2.ctx.r.rooms) if (c.floor === f) {
|
|
21905
22307
|
for (const [a, b, c2, d] of rectsOf2(c)) if (u > a + EPS3 && u < c2 - EPS3 && v > b + EPS3 && v < d - EPS3) return c;
|
|
21906
22308
|
}
|
|
21907
22309
|
return null;
|
|
@@ -21929,14 +22331,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21929
22331
|
return [Math.min(...pts.map((p) => p[0])), Math.min(...pts.map((p) => p[1])), Math.max(...pts.map((p) => p[0])), Math.max(...pts.map((p) => p[1]))];
|
|
21930
22332
|
}
|
|
21931
22333
|
function effectiveHeight(f, h) {
|
|
21932
|
-
const A =
|
|
22334
|
+
const A = shared2.ctx.r.floors;
|
|
21933
22335
|
if (f + 1 >= A.length) return h;
|
|
21934
22336
|
const pitch = A[f + 1].y0 - A[f].y0;
|
|
21935
22337
|
return h > pitch && h - pitch <= 0.45 ? pitch : h;
|
|
21936
22338
|
}
|
|
21937
22339
|
Object.assign(K, { OPEN_ROOM_TYPES: OPEN_ROOM_TYPES22, NO_CEILING, OPEN_AREA, EPS: EPS3, Y0, colorOf, rectsOf: rectsOf2, roomAt, subRect, subRects, wallColor, floorColor, stairFootprint, effectiveHeight });
|
|
21938
22340
|
}
|
|
21939
|
-
function installHouseWalls(K,
|
|
22341
|
+
function installHouseWalls(K, shared2) {
|
|
21940
22342
|
const { EPS: EPS3, Y0, boxC, bx, cursor, effectiveHeight, pieceRecord, structurePiece, wallColor } = K;
|
|
21941
22343
|
function wallBox(alongU, L, a, b, ya, yb, th, cL, cH, mL, mH) {
|
|
21942
22344
|
if (yb - ya < 1e-4 || b - a < 1e-4) return;
|
|
@@ -21949,10 +22351,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21949
22351
|
}
|
|
21950
22352
|
}
|
|
21951
22353
|
function sideOf(id, frontLine) {
|
|
21952
|
-
const R =
|
|
21953
|
-
if (id === "outside" || !
|
|
22354
|
+
const R = shared2.ctx.r, F = R.facade;
|
|
22355
|
+
if (id === "outside" || !shared2.ctx.roomById[id]) {
|
|
21954
22356
|
const ac = F.finish;
|
|
21955
|
-
let mat = "plaster", color2 =
|
|
22357
|
+
let mat = "plaster", color2 = shared2.ctx.colors.facade;
|
|
21956
22358
|
if (ac === "roughcast") mat = "roughcast";
|
|
21957
22359
|
else if (ac === "exposed_block") {
|
|
21958
22360
|
mat = "block";
|
|
@@ -21963,12 +22365,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21963
22365
|
}
|
|
21964
22366
|
return { color: color2, mat, exterior: true };
|
|
21965
22367
|
}
|
|
21966
|
-
return { color: wallColor(
|
|
22368
|
+
return { color: wallColor(shared2.ctx.roomById[id]), mat: "plaster", exterior: false };
|
|
21967
22369
|
}
|
|
21968
22370
|
const pieceOf = (w) => !w.id ? null : structurePiece(w.id) || pieceRecord(w.id, w.material || "brick", w.role || "partition", { floor: w.floor });
|
|
21969
22371
|
function nearestWall(f, axis, L, c) {
|
|
21970
22372
|
let m = null, md = 1e9;
|
|
21971
|
-
for (const w of
|
|
22373
|
+
for (const w of shared2.ctx.r.walls) {
|
|
21972
22374
|
if (w.floor !== f || w.axis !== axis || w.type !== "wall" || Math.abs((axis === "u" ? w.v0 : w.u0) - L) > EPS3) continue;
|
|
21973
22375
|
const a = Math.min(axis === "u" ? w.u0 : w.v0, axis === "u" ? w.u1 : w.v1), b = Math.max(axis === "u" ? w.u0 : w.v0, axis === "u" ? w.u1 : w.v1), d = c < a ? a - c : c > b ? c - b : 0;
|
|
21974
22376
|
if (d < md) {
|
|
@@ -21979,7 +22381,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21979
22381
|
return m;
|
|
21980
22382
|
}
|
|
21981
22383
|
function walls() {
|
|
21982
|
-
const R =
|
|
22384
|
+
const R = shared2.ctx.r, cut = shared2.ctx.cut, nA = R.floors.length, vMin = Math.min(...R.walls.map((w) => w.axis === "u" ? w.v0 : Math.min(w.v0, w.v1)));
|
|
21983
22385
|
const corners = /* @__PURE__ */ new Map();
|
|
21984
22386
|
for (const w of R.walls) {
|
|
21985
22387
|
const f = w.floor;
|
|
@@ -21990,9 +22392,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21990
22392
|
const hh = cut ? Math.min(h, 1.2) : h, L = alongU ? w.v0 : w.u0, s0 = Math.min(alongU ? w.u0 : w.v0, alongU ? w.u1 : w.v1), s1 = Math.max(alongU ? w.u0 : w.v0, alongU ? w.u1 : w.v1);
|
|
21991
22393
|
const front = alongU && Math.abs(L - vMin) < 0.05;
|
|
21992
22394
|
const sideL = sideOf(w.sides[0], front), sideH = sideOf(w.sides[1], front);
|
|
21993
|
-
|
|
22395
|
+
shared2.ctx.colliders.push({ type: "wall", piece: w.id, f, x0: alongU ? s0 : L - th / 2, z0: alongU ? L - th / 2 : s0, x1: alongU ? s1 : L + th / 2, z1: alongU ? L + th / 2 : s1 });
|
|
21994
22396
|
if (w.type === "railing") {
|
|
21995
|
-
const c0 =
|
|
22397
|
+
const c0 = shared2.ctx.colors.metal != null ? shared2.ctx.colors.metal : 9080466;
|
|
21996
22398
|
const sx = alongU ? 1 : 0, sz = alongU ? 0 : 1, len = s1 - s0, n = Math.max(1, Math.round(len / 1.4));
|
|
21997
22399
|
const cx_ = alongU ? (s0 + s1) / 2 : L, cz_ = alongU ? L : (s0 + s1) / 2;
|
|
21998
22400
|
boxC("glass", cx_, y0 + 0.55, cz_, alongU ? len : 0.02, 0.85, alongU ? 0.02 : len, 16777215);
|
|
@@ -22039,7 +22441,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22039
22441
|
}
|
|
22040
22442
|
Object.assign(K, { wallBox, sideOf, pieceOf, nearestWall, walls });
|
|
22041
22443
|
}
|
|
22042
|
-
function installHouseDoors(K,
|
|
22444
|
+
function installHouseDoors(K, shared2) {
|
|
22043
22445
|
const seedKey = (id) => K.seedKey(id);
|
|
22044
22446
|
const { EPS: EPS3, Y0, boxC, bx, cursor, effectiveHeight, nearestWall, part, pieceOf, pieceRecord, roomAt, sideOf, wallBox } = K;
|
|
22045
22447
|
const SEED = (...a) => K.SEED(...a);
|
|
@@ -22047,15 +22449,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22047
22449
|
const rngString = (...a) => K.rngString(...a);
|
|
22048
22450
|
const sh = (...a) => K.sh(...a);
|
|
22049
22451
|
function doorLineSides(p) {
|
|
22050
|
-
const R =
|
|
22452
|
+
const R = shared2.ctx.r, alongU = p.axis === "u", a = p.at - p.width / 2, b = p.at + p.width / 2;
|
|
22051
22453
|
const w = R.walls.find((w2) => w2.floor === p.floor && w2.axis === p.axis && Math.abs((alongU ? w2.v0 : w2.u0) - p.pos) < EPS3 && w2.type === "wall" && (Math.abs((alongU ? w2.u1 : w2.v1) - a) < 0.02 || Math.abs((alongU ? w2.u0 : w2.v0) - b) < 0.02));
|
|
22052
22454
|
const sides = w ? w.sides : [p.a, p.b];
|
|
22053
22455
|
return [sideOf(sides[0], false), sideOf(sides[1], false)];
|
|
22054
22456
|
}
|
|
22055
|
-
|
|
22457
|
+
shared2.doorState = /* @__PURE__ */ new Map();
|
|
22056
22458
|
function doors() {
|
|
22057
|
-
|
|
22058
|
-
const R =
|
|
22459
|
+
shared2.ctx.leaves = [];
|
|
22460
|
+
const R = shared2.ctx.r, cut = shared2.ctx.cut, C = shared2.ctx.colors, wood = C.wood != null ? C.wood : 8016948, frame2 = sh(wood, 0.55);
|
|
22059
22461
|
for (const p of R.doors) {
|
|
22060
22462
|
const f = p.floor;
|
|
22061
22463
|
cursor.group = "f" + f;
|
|
@@ -22085,12 +22487,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22085
22487
|
}
|
|
22086
22488
|
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);
|
|
22087
22489
|
const extC = wood;
|
|
22088
|
-
const open0 = p.blocked ? false :
|
|
22089
|
-
|
|
22490
|
+
const open0 = p.blocked ? false : shared2.doorState.has(p.id) ? shared2.doorState.get(p.id) : !!p.open;
|
|
22491
|
+
shared2.doorState.set(p.id, open0);
|
|
22090
22492
|
const dc = alongU ? [p.at, L] : [L, p.at];
|
|
22091
22493
|
const fo = { id: p.id, floor: f, type: p.model === "steel" ? "steel" : "swing", open: open0, t: open0 ? 1 : 0, blockedFlag: !!p.blocked, locked: R.state === "fortified" && !!p.exterior, handleNames: [], hT: 0, cx: dc[0], cz: dc[1], visH, groups: [], col: null };
|
|
22092
22494
|
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 };
|
|
22093
|
-
|
|
22495
|
+
shared2.ctx.colliders.push(colR);
|
|
22094
22496
|
fo.col = colR;
|
|
22095
22497
|
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);
|
|
22096
22498
|
const newGroup = (k, hu, topY) => {
|
|
@@ -22150,7 +22552,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22150
22552
|
fo.rot = Math.atan2(n[0] * A[1] - n[1] * A[0], A[0] * n[0] + A[1] * n[1]);
|
|
22151
22553
|
}
|
|
22152
22554
|
}
|
|
22153
|
-
|
|
22555
|
+
shared2.ctx.leaves.push(fo);
|
|
22154
22556
|
cursor.group = "f" + f;
|
|
22155
22557
|
if (p.blocked) {
|
|
22156
22558
|
part("window_boards", [0, 0, 0], () => {
|
|
@@ -22178,18 +22580,18 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22178
22580
|
}
|
|
22179
22581
|
}
|
|
22180
22582
|
}, { id: "boards:" + p.id }, "f" + f);
|
|
22181
|
-
|
|
22583
|
+
shared2.ctx.colliders.push({ type: "board", f, x0: alongU ? a : L - th / 2, z0: alongU ? L - th / 2 : a, x1: alongU ? b : L + th / 2, z1: alongU ? L + th / 2 : b });
|
|
22182
22584
|
}
|
|
22183
22585
|
}
|
|
22184
22586
|
}
|
|
22185
22587
|
Object.assign(K, { doorLineSides, doors });
|
|
22186
22588
|
}
|
|
22187
|
-
function installHouseWindows(K,
|
|
22589
|
+
function installHouseWindows(K, shared2) {
|
|
22188
22590
|
const { EPS: EPS3, Y0, boxC, bx, cursor, pieceRecord, roomAt } = K;
|
|
22189
22591
|
const FRAME_COLORS = { budget: 15856110, mid: 12830924, high: 2829875, commercial: 11844287 };
|
|
22190
22592
|
const SILL_COLORS = { budget: 15131870, mid: 14277076, high: 3816770, commercial: 13225166 };
|
|
22191
22593
|
function windows() {
|
|
22192
|
-
const R =
|
|
22594
|
+
const R = shared2.ctx.r, cut = shared2.ctx.cut, C = shared2.ctx.colors, structure = R.style, fr = FRAME_COLORS[structure] || FRAME_COLORS.budget, pe_ = SILL_COLORS[structure] || SILL_COLORS.budget;
|
|
22193
22595
|
const boardItems = new Set(R.stateItems.filter((e) => e.type === "window_boards" && e.window).map((e) => e.window));
|
|
22194
22596
|
for (const j of R.windows) {
|
|
22195
22597
|
const f = j.floor;
|
|
@@ -22242,11 +22644,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22242
22644
|
}
|
|
22243
22645
|
Object.assign(K, { FRAME_COLORS, SILL_COLORS, windows });
|
|
22244
22646
|
}
|
|
22245
|
-
function installHouseFloors(K,
|
|
22647
|
+
function installHouseFloors(K, shared2) {
|
|
22246
22648
|
const { rectsOf: rectsOf2, EPS: EPS3, OPEN_AREA, Y0, bx, cursor, floorColor, stairFootprint, structurePiece, subRects } = K;
|
|
22247
22649
|
function flights() {
|
|
22248
|
-
if (
|
|
22249
|
-
const R =
|
|
22650
|
+
if (shared2.ctx._flights && shared2.ctx._flights.r === shared2.ctx.r) return shared2.ctx._flights.l;
|
|
22651
|
+
const R = shared2.ctx.r, mp = /* @__PURE__ */ new Map();
|
|
22250
22652
|
for (const m of R.items) {
|
|
22251
22653
|
if (m.type !== "stairs" || !m.link) continue;
|
|
22252
22654
|
const k = [m.link.from, m.link.to, m.x.toFixed(2), m.z.toFixed(2), (m.ry || 0).toFixed(2)].join("|");
|
|
@@ -22262,12 +22664,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22262
22664
|
v.LP = LP;
|
|
22263
22665
|
v.top = stairFootprint({ x: m.x + lz * Math.sin(m.ry), z: m.z + lz * Math.cos(m.ry), ry: m.ry, w: m.w, d: LP });
|
|
22264
22666
|
}
|
|
22265
|
-
|
|
22667
|
+
shared2.ctx._flights = { r: R, l };
|
|
22266
22668
|
return l;
|
|
22267
22669
|
}
|
|
22268
22670
|
const panelRects = (p) => p.footprint && p.footprint.length ? p.footprint : [p.aabb];
|
|
22269
22671
|
function tilesOf(parent, rc) {
|
|
22270
|
-
const ps = parent &&
|
|
22672
|
+
const ps = parent && shared2.ctx.panelsOf && shared2.ctx.panelsOf.get(parent);
|
|
22271
22673
|
if (!ps) return [[parent ? structurePiece(parent) : null, rc]];
|
|
22272
22674
|
const out = [], taken = [];
|
|
22273
22675
|
for (const p of ps) for (const q of panelRects(p)) {
|
|
@@ -22281,14 +22683,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22281
22683
|
return out;
|
|
22282
22684
|
}
|
|
22283
22685
|
function panelAt(parent, x, z) {
|
|
22284
|
-
const ps =
|
|
22686
|
+
const ps = shared2.ctx.panelsOf && shared2.ctx.panelsOf.get(parent);
|
|
22285
22687
|
if (!ps) return structurePiece(parent);
|
|
22286
22688
|
for (const p of ps) for (const q of panelRects(p)) if (x >= q[0] - EPS3 && x <= q[2] + EPS3 && z >= q[1] - EPS3 && z <= q[3] + EPS3) return structurePiece(p.id);
|
|
22287
22689
|
return null;
|
|
22288
22690
|
}
|
|
22289
|
-
const hasSlab = (id) => !!(
|
|
22691
|
+
const hasSlab = (id) => !!(shared2.ctx.structureIndex[id] || shared2.ctx.panelsOf && shared2.ctx.panelsOf.has(id));
|
|
22290
22692
|
function floorsAndSlabs() {
|
|
22291
|
-
const R =
|
|
22693
|
+
const R = shared2.ctx.r, nA = R.floors.length, C = shared2.ctx.colors;
|
|
22292
22694
|
const V = flights(), holes = (f) => V.filter((v) => v.to === f).flatMap((v) => {
|
|
22293
22695
|
let rs = [v.rect];
|
|
22294
22696
|
if (v.top) rs = subRects(rs, [v.top]);
|
|
@@ -22325,18 +22727,18 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22325
22727
|
}
|
|
22326
22728
|
Object.assign(K, { flights, floorsAndSlabs, tilesOf, panelAt });
|
|
22327
22729
|
}
|
|
22328
|
-
function installHouseStairs(K,
|
|
22730
|
+
function installHouseStairs(K, shared2) {
|
|
22329
22731
|
const { rectsOf: rectsOf2, Y0, boxC, bx, cursor, flights, stairFootprint, structurePiece } = K;
|
|
22330
22732
|
const sh = (...a) => K.sh(...a);
|
|
22331
22733
|
function buildStairs() {
|
|
22332
|
-
const R =
|
|
22333
|
-
|
|
22734
|
+
const R = shared2.ctx.r;
|
|
22735
|
+
shared2.ctx.stairs = [];
|
|
22334
22736
|
for (const vo of flights()) {
|
|
22335
22737
|
const m = vo.m, f = vo.from, Dr = m.d - (vo.LP || 0);
|
|
22336
22738
|
cursor.group = "f" + f;
|
|
22337
22739
|
cursor.pc = structurePiece("stairs_" + vo.from + "_" + vo.to);
|
|
22338
22740
|
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);
|
|
22339
|
-
const wood =
|
|
22741
|
+
const wood = shared2.ctx.colors.wood != null ? shared2.ctx.colors.wood : 9071176, under = sh(wood, 0.7);
|
|
22340
22742
|
const P = (lx, lz) => [m.x + lx * c + lz * s, m.z - lx * s + lz * c];
|
|
22341
22743
|
const boxL = (mat, lx, y, lz, w, h, d, color2, rx = 0) => {
|
|
22342
22744
|
const [px, pz] = P(lx, lz);
|
|
@@ -22358,16 +22760,16 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22358
22760
|
}
|
|
22359
22761
|
}
|
|
22360
22762
|
cursor.pc = null;
|
|
22361
|
-
|
|
22763
|
+
shared2.ctx.stairs.push({ m, f, to: vo.to, y0, H, rect: stairFootprint(m), landingPoint: (vo.LP || 0) / m.d });
|
|
22362
22764
|
}
|
|
22363
22765
|
}
|
|
22364
22766
|
function elevator() {
|
|
22365
|
-
const R =
|
|
22767
|
+
const R = shared2.ctx.r;
|
|
22366
22768
|
for (const c of R.rooms.filter((c2) => c2.type === "elevator" && c2.floor === 0)) {
|
|
22367
22769
|
cursor.group = "f0";
|
|
22368
22770
|
const [u0, v0, u1, v1] = rectsOf2(c)[0], y0 = Y0(0);
|
|
22369
22771
|
bx("metal", u0 + 0.15, y0 + 0.05, v0 + 0.15, u1 - 0.15, y0 + 2.3, v1 - 0.15, 10133670);
|
|
22370
|
-
bx("emissive", u0 + 0.3, y0 + 2.28, v0 + 0.3, u1 - 0.3, y0 + 2.3, v1 - 0.3,
|
|
22772
|
+
bx("emissive", u0 + 0.3, y0 + 2.28, v0 + 0.3, u1 - 0.3, y0 + 2.3, v1 - 0.3, shared2.ctx.night ? 16773320 : 13619924);
|
|
22371
22773
|
for (const f of R.floors) {
|
|
22372
22774
|
const yy = Y0(f.index);
|
|
22373
22775
|
cursor.group = "f" + f.index;
|
|
@@ -22377,7 +22779,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22377
22779
|
}
|
|
22378
22780
|
Object.assign(K, { buildStairs, elevator });
|
|
22379
22781
|
}
|
|
22380
|
-
function installLightsFixtures(K,
|
|
22782
|
+
function installLightsFixtures(K, shared2) {
|
|
22381
22783
|
const seedKey = (id) => K.seedKey(id);
|
|
22382
22784
|
const { cursor, part, polyFace } = K;
|
|
22383
22785
|
const makeApi = (...a) => K.makeApi(...a);
|
|
@@ -22395,9 +22797,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22395
22797
|
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
22396
22798
|
};
|
|
22397
22799
|
}
|
|
22398
|
-
const SEED = () =>
|
|
22399
|
-
const STYLE = () =>
|
|
22400
|
-
|
|
22800
|
+
const SEED = () => shared2.ctx.r && shared2.ctx.r.seed || 0;
|
|
22801
|
+
const STYLE = () => shared2.ctx.r && shared2.ctx.r.style || "budget";
|
|
22802
|
+
shared2.api0 = null;
|
|
22401
22803
|
function kit2(M, A, y0 = M.y || 0) {
|
|
22402
22804
|
const c = Math.cos(M.ry), s = Math.sin(M.ry);
|
|
22403
22805
|
let api = A;
|
|
@@ -22429,7 +22831,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22429
22831
|
return null;
|
|
22430
22832
|
}
|
|
22431
22833
|
const a0 = api;
|
|
22432
|
-
api =
|
|
22834
|
+
api = shared2.api0 || (shared2.api0 = makeApi());
|
|
22433
22835
|
try {
|
|
22434
22836
|
return part(type, W(lx, ly, lz), fn, meta || {}, void 0, M.ry);
|
|
22435
22837
|
} finally {
|
|
@@ -22523,7 +22925,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22523
22925
|
yLight = yc - 0.3;
|
|
22524
22926
|
range2 = 6.5;
|
|
22525
22927
|
} else if (type === "chandelier") {
|
|
22526
|
-
const yc = t - 0.5, gold =
|
|
22928
|
+
const yc = t - 0.5, gold = shared2.ctx.colors && shared2.ctx.colors.metal != null ? shared2.ctx.colors.metal : 9075290, N = 6;
|
|
22527
22929
|
K2.c("metal", 0, yc, 0, 0.012, 0.5, gold);
|
|
22528
22930
|
K2.e("metal", 0, yc - 0.03, 0, 0.055, 0.08, gold);
|
|
22529
22931
|
K2.c("metal", 0, yc - 0.06, 0, 0.14, 0.015, gold);
|
|
@@ -22601,24 +23003,24 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22601
23003
|
}
|
|
22602
23004
|
Object.assign(K, { hashString: hashString2, rngString, SEED, STYLE, kit2, arcPoints, TEMP_WARM, TEMP_NEUTRAL, TEMP_COOL, colorTemperature, lightStyle, ceilingLamp, tableLamp, floorLamp, sconce, outdoorLamp, lightSwitch });
|
|
22603
23005
|
}
|
|
22604
|
-
function installLightsDecor(K,
|
|
23006
|
+
function installLightsDecor(K, shared2) {
|
|
22605
23007
|
const { EPS: EPS3, OPEN_AREA, SEED, Y0, cursor, rngString, roomAt, stairFootprint } = K;
|
|
22606
23008
|
const lightItem = (...a) => K.lightItem(...a);
|
|
22607
23009
|
function decorLights(api) {
|
|
22608
|
-
const R =
|
|
23010
|
+
const R = shared2.ctx.r, T2 = shared2.ctx.types, structure = R.style, chance = structure === "budget" ? 0.35 : structure === "mid" ? 0.75 : 1, rnd = rngString(SEED() + "|decorluz");
|
|
22609
23011
|
const itemsF = (f) => R.items.filter((m) => (m.outdoor ? -1 : m.floor) === f && m.type !== "stairs");
|
|
22610
23012
|
const rectsF = (f) => itemsF(f).filter((m) => (m.h || 0) > 0.3 && !/rug|floor|concrete|dirt|lawn|ceiling_light|curtain|blinds|picture|mirror|pendant|chandelier|spot/.test(m.type)).map((m) => stairFootprint(m));
|
|
22611
23013
|
const free = (f, x, z, margin) => {
|
|
22612
23014
|
if (!roomAt(f, x, z)) return false;
|
|
22613
|
-
for (const c of
|
|
23015
|
+
for (const c of shared2.ctx.colliders) if (c.f === f && x > c.x0 - margin && x < c.x1 + margin && z > c.z0 - margin && z < c.z1 + margin) return false;
|
|
22614
23016
|
for (const r of rectsF(f)) if (x > r[0] - margin && x < r[2] + margin && z > r[1] - margin && z < r[3] + margin) return false;
|
|
22615
23017
|
return true;
|
|
22616
23018
|
};
|
|
22617
23019
|
const puts = (f, type, m0, extra) => {
|
|
22618
23020
|
const ent = T2[type];
|
|
22619
23021
|
if (!ent) return;
|
|
22620
|
-
const com =
|
|
22621
|
-
const M = Object.assign({ x: m0.x, z: m0.z, ry: m0.ry || 0, w: m0.w || 0.3, d: m0.d || 0.3, h: m0.h || 0.3, y: 0, base, floor: f, colors:
|
|
23022
|
+
const com = shared2.ctx.roomById[m0.room], g = "f" + f, base = Y0(f);
|
|
23023
|
+
const M = Object.assign({ x: m0.x, z: m0.z, ry: m0.ry || 0, w: m0.w || 0.3, d: m0.d || 0.3, h: m0.h || 0.3, y: 0, base, floor: f, colors: shared2.ctx.colors, seed: m0.id, room: m0.room, typeWith: com ? com.type : null, ceiling: com ? com.ceiling : 2.8, on: shared2.ctx.night, light: shared2.ctx.night, lit: shared2.ctx.night }, extra || {});
|
|
22622
23024
|
cursor.group = g;
|
|
22623
23025
|
lightItem({ id: m0.id, room: m0.room }, M, ent, api, g);
|
|
22624
23026
|
};
|
|
@@ -22666,18 +23068,18 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22666
23068
|
}
|
|
22667
23069
|
Object.assign(K, { decorLights });
|
|
22668
23070
|
}
|
|
22669
|
-
function installLotTerrain(K,
|
|
23071
|
+
function installLotTerrain(K, shared2) {
|
|
22670
23072
|
const { rectsOf: rectsOf2, MIRRORS, PARTS, bx, cursor } = K;
|
|
22671
23073
|
function terrain() {
|
|
22672
23074
|
PARTS.length = 0;
|
|
22673
23075
|
MIRRORS.length = 0;
|
|
22674
23076
|
K.CARS.length = 0;
|
|
22675
|
-
|
|
22676
|
-
|
|
22677
|
-
|
|
22678
|
-
|
|
22679
|
-
if (
|
|
22680
|
-
const R =
|
|
23077
|
+
shared2.partCount = 0;
|
|
23078
|
+
shared2.ctx.parts = {};
|
|
23079
|
+
shared2.tapCount = 0;
|
|
23080
|
+
shared2.ctx.clotheslines = [];
|
|
23081
|
+
if (shared2.ctx.noTerrain) return;
|
|
23082
|
+
const R = shared2.ctx.r, lt = R.lot, C = shared2.ctx.colors;
|
|
22681
23083
|
cursor.group = "floor";
|
|
22682
23084
|
const light = (c, f) => {
|
|
22683
23085
|
const m = (k) => Math.round((c >> k & 255) * (1 - f) + 255 * f);
|
|
@@ -22691,13 +23093,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22691
23093
|
bx("sidewalk", u0 - 40, -0.06, v0 - 1.8, u1 + 40, 0.02, v0, 14999766);
|
|
22692
23094
|
for (let x = u0 - 38; x < u1 + 40; x += 6) bx("plaster", x, 0, v0 - 5.6, x + 2.6, 5e-3, v0 - 5.4, 15262904);
|
|
22693
23095
|
} else {
|
|
22694
|
-
const b =
|
|
23096
|
+
const b = shared2.ctx.limits;
|
|
22695
23097
|
bx("sidewalk", b.x0 - 6, -0.09, b.z0 - 6, b.x1 + 6, -0.03, b.z1 + 6, 14605010);
|
|
22696
23098
|
}
|
|
22697
23099
|
}
|
|
22698
23100
|
function freeSpans(alongU, L, a, b) {
|
|
22699
23101
|
const blocks = [];
|
|
22700
|
-
for (const c of
|
|
23102
|
+
for (const c of shared2.ctx.r.rooms) {
|
|
22701
23103
|
if (c.type === "void" || c.floor < 0) continue;
|
|
22702
23104
|
for (const [u0, v0, u1, v1] of rectsOf2(c)) {
|
|
22703
23105
|
const c0 = alongU ? v0 : u0, c1 = alongU ? v1 : u1, lo = alongU ? u0 : v0, hi = alongU ? u1 : v1;
|
|
@@ -22717,12 +23119,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22717
23119
|
}
|
|
22718
23120
|
Object.assign(K, { terrain, freeSpans });
|
|
22719
23121
|
}
|
|
22720
|
-
function installLotPerimeter(K,
|
|
23122
|
+
function installLotPerimeter(K, shared2) {
|
|
22721
23123
|
const { EPS: EPS3, boxC, bx, colorOf, cursor, freeSpans, pieceRecord } = K;
|
|
22722
23124
|
const makeApi = (...a) => K.makeApi(...a);
|
|
22723
23125
|
const sh = (...a) => K.sh(...a);
|
|
22724
23126
|
function perimeter() {
|
|
22725
|
-
const R =
|
|
23127
|
+
const R = shared2.ctx.r, lt = R.lot, C = shared2.ctx.colors;
|
|
22726
23128
|
if (!lt) return;
|
|
22727
23129
|
cursor.group = "lot";
|
|
22728
23130
|
const rnd = /* @__PURE__ */ (() => {
|
|
@@ -22736,7 +23138,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22736
23138
|
const th = s.thickness || 0.15, h = s.height, color2 = colorOf(s.color) != null ? colorOf(s.color) : C.wall || 12104874, len = b - a;
|
|
22737
23139
|
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);
|
|
22738
23140
|
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 };
|
|
22739
|
-
|
|
23141
|
+
shared2.ctx.colliders.push(col);
|
|
22740
23142
|
if (s.type === "wall") {
|
|
22741
23143
|
B("plaster", a, 0, b, h, th, color2);
|
|
22742
23144
|
B("plaster", a, h, b, h + 0.05, th + 0.06, sh(color2, 1.15));
|
|
@@ -22775,7 +23177,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22775
23177
|
const w2 = x1 - x0, cm = (x0 + x1) / 2;
|
|
22776
23178
|
const M = top === "razor_wire" ? { x: alongU ? cm : L, z: alongU ? L : cm, ry: alongU ? 0 : K.PE, w: w2, d: 0.4, h: 0.4, y: ym, base: 0, floor: -1, colors: C, seed: s.id } : { x: alongU ? cm : L, z: alongU ? L : cm, ry: alongU ? 0 : K.PE, w: w2, d: 0.1, h: 0.3, y: 0, base: ym, floor: -1, colors: C, seed: s.id };
|
|
22777
23179
|
try {
|
|
22778
|
-
|
|
23180
|
+
shared2.ctx.mv.builders[top](M, api);
|
|
22779
23181
|
} catch (e) {
|
|
22780
23182
|
console.warn(e);
|
|
22781
23183
|
}
|
|
@@ -22796,7 +23198,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22796
23198
|
}
|
|
22797
23199
|
}
|
|
22798
23200
|
function paths() {
|
|
22799
|
-
const lt =
|
|
23201
|
+
const lt = shared2.ctx.r.lot;
|
|
22800
23202
|
if (!lt || !lt.paths) return;
|
|
22801
23203
|
cursor.group = "lot";
|
|
22802
23204
|
for (const c of lt.paths) {
|
|
@@ -22809,14 +23211,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22809
23211
|
}
|
|
22810
23212
|
Object.assign(K, { perimeter, paths });
|
|
22811
23213
|
}
|
|
22812
|
-
function installLotGates(K,
|
|
23214
|
+
function installLotGates(K, shared2) {
|
|
22813
23215
|
const { bx, colorOf, cursor, cylBase } = K;
|
|
22814
23216
|
const sh = (...a) => K.sh(...a);
|
|
22815
23217
|
function slideDirection(g, lt) {
|
|
22816
23218
|
return g.u + g.width / 2 + g.width + 1.2 <= lt.rect[2] ? 1 : -1;
|
|
22817
23219
|
}
|
|
22818
23220
|
function gates() {
|
|
22819
|
-
const R =
|
|
23221
|
+
const R = shared2.ctx.r, lt = R.lot, C = shared2.ctx.colors;
|
|
22820
23222
|
if (!lt) return;
|
|
22821
23223
|
cursor.group = "lot";
|
|
22822
23224
|
const structure = R.style, auto = structure !== "budget", wall = colorOf("wall") || 12104874, cu = (lt.rect[0] + lt.rect[2]) / 2, cz = (lt.rect[1] + lt.rect[3]) / 2;
|
|
@@ -22890,12 +23292,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22890
23292
|
bx("emissive", mx + 0.1, 0.28, zc + sd * 0.452, mx + 0.14, 0.31, zc + sd * 0.455, 6479994);
|
|
22891
23293
|
}
|
|
22892
23294
|
}
|
|
22893
|
-
if (!g.open || ped)
|
|
23295
|
+
if (!g.open || ped) shared2.ctx.colliders.push({ type: "gate", f: -1, x0: a, z0: v - 0.1, x1: b, z1: v + 0.1 });
|
|
22894
23296
|
}
|
|
22895
23297
|
}
|
|
22896
23298
|
Object.assign(K, { slideDirection, gates });
|
|
22897
23299
|
}
|
|
22898
|
-
function installRoofRoofs(K,
|
|
23300
|
+
function installRoofRoofs(K, shared2) {
|
|
22899
23301
|
const { rectsOf: rectsOf2, EPS: EPS3, OPEN_AREA, Y0, bx, cursor } = K;
|
|
22900
23302
|
const gutter = (...a) => K.gutter(...a);
|
|
22901
23303
|
const gutterConfig = (...a) => K.gutterConfig(...a);
|
|
@@ -22903,14 +23305,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22903
23305
|
const sh = (...a) => K.sh(...a);
|
|
22904
23306
|
const slabs = (...a) => K.slabs(...a);
|
|
22905
23307
|
function roofs() {
|
|
22906
|
-
const R =
|
|
23308
|
+
const R = shared2.ctx.r, F = R.facade, C = shared2.ctx.colors, nA = R.floors.length, type = F.roof;
|
|
22907
23309
|
cursor.group = "roof";
|
|
22908
|
-
|
|
22909
|
-
|
|
22910
|
-
|
|
22911
|
-
|
|
22912
|
-
|
|
22913
|
-
|
|
23310
|
+
shared2.ctx.roofRects = [];
|
|
23311
|
+
shared2.ctx.gutter = gutterConfig();
|
|
23312
|
+
shared2.ctx.gutter.ncond = 0;
|
|
23313
|
+
shared2.ctx.gutter.nbuz = 0;
|
|
23314
|
+
shared2.ctx.gutter.bz = /* @__PURE__ */ new Set();
|
|
23315
|
+
shared2.ctx.gutterInfo = { gutters: [], downpipes: [], drains: [] };
|
|
22914
23316
|
const roofColor = C.roof != null ? C.roof : 11031610, gable = (R.seed | 0) % 2 === 0;
|
|
22915
23317
|
for (let f = 0; f < nA; f++) {
|
|
22916
23318
|
const rs = R.rooms.filter((c) => c.floor === f && c.type !== "void" && !c.outbuilding && !OPEN_AREA(c)).flatMap(rectsOf2), up = R.rooms.filter((c) => c.floor === f + 1 && c.type !== "void").flatMap(rectsOf2);
|
|
@@ -22933,7 +23335,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22933
23335
|
return Y0(f) + Math.max(...cs.map((c) => c.ceiling)) + 0.2;
|
|
22934
23336
|
};
|
|
22935
23337
|
if (type === "slab") {
|
|
22936
|
-
for (let j = 0; j < nz; j++) for (let i = 0; i < nx; i++) if (O(j, i))
|
|
23338
|
+
for (let j = 0; j < nz; j++) for (let i = 0; i < nx; i++) if (O(j, i)) shared2.ctx.roofRects.push({ f, r: [xs[i], zs[j], xs[i + 1], zs[j + 1]], slab: true, yb: pe(xs[i], zs[j], xs[i + 1], zs[j + 1]) + 0.03 });
|
|
22937
23339
|
slabs(f, xs, zs, O, U, nx, nz, full, pe, C);
|
|
22938
23340
|
cursor.pc = null;
|
|
22939
23341
|
continue;
|
|
@@ -22956,36 +23358,36 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22956
23358
|
if (U(q.j0 - 1, i)) touchesU[1] = 1;
|
|
22957
23359
|
if (U(q.j1 + 1, i)) touchesU[3] = 1;
|
|
22958
23360
|
}
|
|
22959
|
-
|
|
23361
|
+
shared2.ctx.roofRects.push({ f, r: [x0, z0, x1, z1], touchesU });
|
|
22960
23362
|
const ybq = pe(x0, z0, x1, z1);
|
|
22961
23363
|
roofRect(type, x0, z0, x1, z1, ybq, roofColor, gable && single, F, touchesU);
|
|
22962
23364
|
cursor.pc = null;
|
|
22963
|
-
if (
|
|
23365
|
+
if (shared2.ctx.gutter.on) gutter(type, f, x0, z0, x1, z1, ybq, touchesU);
|
|
22964
23366
|
}
|
|
22965
23367
|
}
|
|
22966
|
-
for (const e of
|
|
23368
|
+
for (const e of shared2.ctx.outbuildingList || []) {
|
|
22967
23369
|
const [x0, z0, x1, z1] = e.aabb, yb = Y0(0) + (e.ceiling || 2.6) + 0.2;
|
|
22968
|
-
|
|
23370
|
+
shared2.ctx.roofRects.push({ f: 0, r: [x0, z0, x1, z1], outbuilding: e.id });
|
|
22969
23371
|
if (type === "slab") {
|
|
22970
23372
|
const c = C.facade != null ? C.facade : 14209216;
|
|
22971
23373
|
bx("plaster", x0 - 0.08, yb, z0 - 0.08, x1 + 0.08, yb + 0.03, z1 + 0.08, sh(C.ceiling != null ? C.ceiling : 12104876, 0.85));
|
|
22972
23374
|
for (const [a, b, c2, d] of [[x0 - 0.08, z0 - 0.08, x1 + 0.08, z0 - 0.04], [x0 - 0.08, z1 + 0.04, x1 + 0.08, z1 + 0.08], [x0 - 0.08, z0 - 0.08, x0 - 0.04, z1 + 0.08], [x1 + 0.04, z0 - 0.08, x1 + 0.08, z1 + 0.08]]) bx("plaster", a, yb, b, c2, yb + 0.4, d, c);
|
|
22973
23375
|
continue;
|
|
22974
23376
|
}
|
|
22975
|
-
|
|
23377
|
+
shared2.ctx.noPiece = true;
|
|
22976
23378
|
roofRect(type, x0, z0, x1, z1, yb, roofColor, true, F, [0, 0, 0, 0]);
|
|
22977
23379
|
cursor.pc = null;
|
|
22978
|
-
|
|
22979
|
-
if (
|
|
23380
|
+
shared2.ctx.noPiece = false;
|
|
23381
|
+
if (shared2.ctx.gutter.on) gutter(type, 0, x0, z0, x1, z1, yb, [0, 0, 0, 0]);
|
|
22980
23382
|
}
|
|
22981
23383
|
}
|
|
22982
23384
|
Object.assign(K, { roofs });
|
|
22983
23385
|
}
|
|
22984
|
-
function installRoofGutters(K,
|
|
23386
|
+
function installRoofGutters(K, shared2) {
|
|
22985
23387
|
const { boxC, bx, cursor, roomAt } = K;
|
|
22986
23388
|
const sh = (...a) => K.sh(...a);
|
|
22987
23389
|
function gutterConfig() {
|
|
22988
|
-
const R =
|
|
23390
|
+
const R = shared2.ctx.r, structure = R.style, high = structure === "high" || structure === "luxury", p = high || structure === "mid" ? 0.6 : 0.3;
|
|
22989
23391
|
let h = 2166136261;
|
|
22990
23392
|
for (const ch of String(R.seed) + "|" + K.seedKey(R.template) + "|calha") h = Math.imul(h ^ ch.charCodeAt(0), 16777619);
|
|
22991
23393
|
const rnd = () => {
|
|
@@ -22997,10 +23399,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22997
23399
|
const draw2 = rnd() < p, light = rnd() < 0.6;
|
|
22998
23400
|
void draw2;
|
|
22999
23401
|
const on = true;
|
|
23000
|
-
return { on, rnd, color: high ? 3816770 : light ? 15527921 : 10857392, bad: (
|
|
23402
|
+
return { on, rnd, color: high ? 3816770 : light ? 15527921 : 10857392, bad: (shared2.ctx.colors.meta && shared2.ctx.colors.meta.state) === "abandoned" || R.state === "abandoned", fallback: false };
|
|
23001
23403
|
}
|
|
23002
23404
|
function gutter(type, f, X0, Z0, X1, Z1, yb, touchesU) {
|
|
23003
|
-
const G =
|
|
23405
|
+
const G = shared2.ctx.gutter, o = type === "fiber_cement" ? 0.3 : 0.45, x0 = X0 - (touchesU[0] ? 0 : o), x1 = X1 + (touchesU[2] ? 0 : o), z0 = Z0 - (touchesU[1] ? 0 : o), z1 = Z1 + (touchesU[3] ? 0 : o), c = G.color, y = yb - 0.05;
|
|
23004
23406
|
const run = (ax, a, b, p, outside, breaks) => {
|
|
23005
23407
|
const seg2 = (u0, u1, tilt) => {
|
|
23006
23408
|
const L = u1 - u0, m = (u0 + u1) / 2, dy = tilt ? -Math.abs(tilt) * L * 0.5 : 0;
|
|
@@ -23024,7 +23426,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23024
23426
|
sides.forEach((l, i) => {
|
|
23025
23427
|
if (l[0]) run(l[1], l[2], l[3], l[4], l[5], G.bad && !G.fallback && i === larger && (G.fallback = true));
|
|
23026
23428
|
});
|
|
23027
|
-
const INF =
|
|
23429
|
+
const INF = shared2.ctx.gutterInfo || (shared2.ctx.gutterInfo = { gutters: [], downpipes: [], drains: [] });
|
|
23028
23430
|
sides.forEach((l, i) => {
|
|
23029
23431
|
if (l[0]) INF.gutters.push({ f, side: ["z0", "z1", "x0", "x1"][i], axis: l[1], a: l[2], b: l[3], p: l[4], y });
|
|
23030
23432
|
});
|
|
@@ -23086,7 +23488,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23086
23488
|
}
|
|
23087
23489
|
Object.assign(K, { gutterConfig, gutter, drain });
|
|
23088
23490
|
}
|
|
23089
|
-
function installRoofSlabs(K,
|
|
23491
|
+
function installRoofSlabs(K, shared2) {
|
|
23090
23492
|
const { boxC, bx, cursor, drain, roomAt, structurePiece } = K;
|
|
23091
23493
|
const sh = (...a) => K.sh(...a);
|
|
23092
23494
|
function slabs(f, xs, zs, O, U, nx, nz, full, pe, C) {
|
|
@@ -23116,15 +23518,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23116
23518
|
side(free(j, i + 1), x1 + o - t, z0 - ez0, x1 + o, z1 + ez1);
|
|
23117
23519
|
side(free(j - 1, i), x0 - ex0, z0 - o, x1 + ex1, z0 - o + t);
|
|
23118
23520
|
side(free(j + 1, i), x0 - ex0, z1 + o - t, x1 + ex1, z1 + o);
|
|
23119
|
-
if (
|
|
23521
|
+
if (shared2.ctx.gutter && shared2.ctx.gutter.on) for (const [ok, dx, dz] of [[free(j - 1, i), 0, -1], [free(j + 1, i), 0, 1], [free(j, i - 1), -1, 0], [free(j, i + 1), 1, 0]]) {
|
|
23120
23522
|
const kd = f + ":" + dx + ":" + dz;
|
|
23121
|
-
if (!ok ||
|
|
23122
|
-
|
|
23123
|
-
|
|
23124
|
-
const mx = (x0 + x1) / 2, mz = (z0 + z1) / 2, ex = dx ? dx < 0 ? x0 - o : x1 + o : mx, ez = dz ? dz < 0 ? z0 - o : z1 + o : mz, cc =
|
|
23523
|
+
if (!ok || shared2.ctx.gutter.bz.has(kd)) continue;
|
|
23524
|
+
shared2.ctx.gutter.bz.add(kd);
|
|
23525
|
+
shared2.ctx.gutter.nbuz++;
|
|
23526
|
+
const mx = (x0 + x1) / 2, mz = (z0 + z1) / 2, ex = dx ? dx < 0 ? x0 - o : x1 + o : mx, ez = dz ? dz < 0 ? z0 - o : z1 + o : mz, cc = shared2.ctx.gutter.color;
|
|
23125
23527
|
boxC("plain", ex + dx * 0.15, yb + 0.1, ez + dz * 0.15, dx ? 0.42 : 0.14, 0.1, dz ? 0.42 : 0.14, cc);
|
|
23126
23528
|
boxC("plain", ex + dx * 0.36, yb + 0.1, ez + dz * 0.36, dx ? 0.04 : 0.18, 0.14, dz ? 0.04 : 0.18, sh(cc, 0.8));
|
|
23127
|
-
if (
|
|
23529
|
+
if (shared2.ctx.gutter.bad) boxC("plain", ex + dx * 0.05, yb + 0.5 * 0, ez + dz * 0.05, dx ? 0.06 : 0.3, 0.02, dz ? 0.06 : 0.3, 4868674);
|
|
23128
23530
|
{
|
|
23129
23531
|
const tx = ex + dx * 0.38, tz = ez + dz * 0.38;
|
|
23130
23532
|
let lv = true;
|
|
@@ -23137,8 +23539,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23137
23539
|
boxC("plain", tx, 0.9, tz, 0.12, 0.04, 0.12, sh(cc, 0.8));
|
|
23138
23540
|
const rx = tx + dx * 0.24, rz = tz + dz * 0.24;
|
|
23139
23541
|
drain(rx, rz, tx, tz, cc);
|
|
23140
|
-
(
|
|
23141
|
-
|
|
23542
|
+
(shared2.ctx.gutterInfo || (shared2.ctx.gutterInfo = { gutters: [], downpipes: [], drains: [] })).downpipes.push({ f, x: tx, z: tz, y0: 0.045, y1: yb + 0.04, drain: [rx, rz], hornBox: true });
|
|
23543
|
+
shared2.ctx.gutterInfo.drains.push({ x: rx, z: rz });
|
|
23142
23544
|
}
|
|
23143
23545
|
}
|
|
23144
23546
|
}
|
|
@@ -23146,10 +23548,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23146
23548
|
}
|
|
23147
23549
|
Object.assign(K, { slabs });
|
|
23148
23550
|
}
|
|
23149
|
-
function installRoofTiles(K,
|
|
23551
|
+
function installRoofTiles(K, shared2) {
|
|
23150
23552
|
const { UV_SCALE, _Y, _h2, _q, accFor, cursor, put, rgbOf, structurePiece } = K;
|
|
23151
23553
|
const sh = (...a) => K.sh(...a);
|
|
23152
|
-
const R_STYLE = () =>
|
|
23554
|
+
const R_STYLE = () => shared2.ctx.r && shared2.ctx.r.style || "budget";
|
|
23153
23555
|
function tileRelief(mat, pts, color2, type) {
|
|
23154
23556
|
const n = pts.length;
|
|
23155
23557
|
if (n < 3) return;
|
|
@@ -23190,7 +23592,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23190
23592
|
S.push(rx * ex + ry * ey + rz * ez);
|
|
23191
23593
|
T2.push(rx * dx + ry * dy + rz * dz);
|
|
23192
23594
|
}
|
|
23193
|
-
const colonial = type !== "fiber_cement", P = colonial ? 0.2 : 0.177, A = colonial ? 0.032 : 0.0255, seg2 =
|
|
23595
|
+
const colonial = type !== "fiber_cement", P = colonial ? 0.2 : 0.177, A = colonial ? 0.032 : 0.0255, seg2 = shared2.quality === "game" ? colonial ? 4 : 4 : colonial ? 8 : 6, h = P / seg2;
|
|
23194
23596
|
const smin = Math.min(...S), smax = Math.max(...S);
|
|
23195
23597
|
if (smax - smin < 1e-4) return;
|
|
23196
23598
|
const xs = new Set(S.map((v) => +v.toFixed(5)));
|
|
@@ -23262,9 +23664,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23262
23664
|
}
|
|
23263
23665
|
}
|
|
23264
23666
|
function pieceOfPane(x, z) {
|
|
23265
|
-
if (
|
|
23667
|
+
if (shared2.ctx.noPiece || !shared2.ctx.panes.length) return null;
|
|
23266
23668
|
let m = null, md = 1e9;
|
|
23267
|
-
for (const a of
|
|
23669
|
+
for (const a of shared2.ctx.panes) {
|
|
23268
23670
|
const b = a.aabb;
|
|
23269
23671
|
if (!b) continue;
|
|
23270
23672
|
const dx = x < b[0] ? b[0] - x : x > b[2] ? x - b[2] : 0, dz = z < b[1] ? b[1] - z : z > b[3] ? z - b[3] : 0, d = Math.hypot(dx, dz) * 1e3 + (b[2] - b[0]) * (b[3] - b[1]) * 1e-3;
|
|
@@ -23277,11 +23679,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23277
23679
|
}
|
|
23278
23680
|
Object.assign(K, { R_STYLE, tileRelief, ridge, pieceOfPane });
|
|
23279
23681
|
}
|
|
23280
|
-
function installRoofRect(K,
|
|
23682
|
+
function installRoofRect(K, shared2) {
|
|
23281
23683
|
const { R_STYLE, bx, cursor, pieceOfPane, polyFace, ridge, tileRelief } = K;
|
|
23282
23684
|
const sh = (...a) => K.sh(...a);
|
|
23283
23685
|
function roofRect(type, X0, Z0, X1, Z1, yb, roofColor, gable, F, touchesU = [0, 0, 0, 0]) {
|
|
23284
|
-
const C =
|
|
23686
|
+
const C = shared2.ctx.colors, o = type === "fiber_cement" ? 0.3 : 0.45, x0 = X0 - (touchesU[0] ? 0 : o), x1 = X1 + (touchesU[2] ? 0 : o), z0 = Z0 - (touchesU[1] ? 0 : o), z1 = Z1 + (touchesU[3] ? 0 : o), dx = x1 - x0, dz = z1 - z0, xm = (x0 + x1) / 2, zm = (z0 + z1) / 2;
|
|
23285
23687
|
const mat = type === "fiber_cement" ? "fiber_cement" : "tile", tp = type === "fiber_cement" ? 0.2 : 0.5, alongX = dx >= dz, up = [0, 1, 0];
|
|
23286
23688
|
const Q = (pts) => {
|
|
23287
23689
|
let cx = 0, cz = 0;
|
|
@@ -23319,7 +23721,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23319
23721
|
}
|
|
23320
23722
|
const rm = alongX ? dz / 2 : dx / 2;
|
|
23321
23723
|
{
|
|
23322
|
-
const rr =
|
|
23724
|
+
const rr = shared2.ctx.roofRects[shared2.ctx.roofRects.length - 1];
|
|
23323
23725
|
if (rr && !rr.yb) Object.assign(rr, { yb, tp, gable: !!gable, alongX, exterior: [x0, z0, x1, z1], rm });
|
|
23324
23726
|
}
|
|
23325
23727
|
if (gable) {
|
|
@@ -23358,12 +23760,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23358
23760
|
}
|
|
23359
23761
|
Object.assign(K, { roofRect });
|
|
23360
23762
|
}
|
|
23361
|
-
function installMirrors(K,
|
|
23763
|
+
function installMirrors(K, shared2) {
|
|
23362
23764
|
const { DOC, THREE, Reflector, MIRRORS, Y0, _Y, roomAt } = K;
|
|
23363
|
-
|
|
23364
|
-
|
|
23765
|
+
shared2.mirrorEnv = null;
|
|
23766
|
+
shared2.mirrorMat = null;
|
|
23365
23767
|
function mirrorEnv() {
|
|
23366
|
-
if (
|
|
23768
|
+
if (shared2.mirrorEnv) return shared2.mirrorEnv;
|
|
23367
23769
|
const mk = (f) => {
|
|
23368
23770
|
const c = DOC.createElement("canvas");
|
|
23369
23771
|
c.width = c.height = 64;
|
|
@@ -23399,18 +23801,18 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23399
23801
|
const t = new THREE.CubeTexture(faces);
|
|
23400
23802
|
t.colorSpace = THREE.SRGBColorSpace;
|
|
23401
23803
|
t.needsUpdate = true;
|
|
23402
|
-
|
|
23403
|
-
|
|
23804
|
+
shared2.mirrorEnv = t;
|
|
23805
|
+
shared2.mirrorMat = new THREE.MeshStandardMaterial({ color: 16054008, metalness: 1, roughness: 0.06, envMap: t, envMapIntensity: 1 });
|
|
23404
23806
|
return t;
|
|
23405
23807
|
}
|
|
23406
23808
|
const newMirrorState = () => ({ list: [], active: null, tmp: new THREE.Vector3(), house: null });
|
|
23407
|
-
|
|
23809
|
+
shared2.mirrors = newMirrorState();
|
|
23408
23810
|
function assembleMirrors(groups) {
|
|
23409
|
-
|
|
23410
|
-
|
|
23811
|
+
shared2.mirrors.list.length = 0;
|
|
23812
|
+
shared2.mirrors.active = null;
|
|
23411
23813
|
if (!MIRRORS.length) return;
|
|
23412
23814
|
mirrorEnv();
|
|
23413
|
-
if (
|
|
23815
|
+
if (shared2.quality === "game" || !Reflector) {
|
|
23414
23816
|
const by = /* @__PURE__ */ new Map(), m4 = new THREE.Matrix4(), qy = new THREE.Quaternion(), um = new THREE.Vector3(1, 1, 1), ps = new THREE.Vector3(), nm = new THREE.Matrix3(), v = new THREE.Vector3();
|
|
23415
23817
|
for (const E of MIRRORS) {
|
|
23416
23818
|
const geo = new THREE.PlaneGeometry(E.w, E.h);
|
|
@@ -23437,7 +23839,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23437
23839
|
g.setAttribute("uv", new THREE.Float32BufferAttribute(B.U, 2));
|
|
23438
23840
|
g.setIndex(B.I);
|
|
23439
23841
|
g.computeBoundingSphere();
|
|
23440
|
-
const m = new THREE.Mesh(g,
|
|
23842
|
+
const m = new THREE.Mesh(g, shared2.mirrorMat);
|
|
23441
23843
|
m.name = "mirror/environment";
|
|
23442
23844
|
m.userData.part = "mirror";
|
|
23443
23845
|
(groups[parent] || (groups[parent] = new THREE.Group())).add(m);
|
|
@@ -23452,7 +23854,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23452
23854
|
g.userData.part = "mirror";
|
|
23453
23855
|
g.userData.room = E.room;
|
|
23454
23856
|
const geo = new THREE.PlaneGeometry(E.w, E.h);
|
|
23455
|
-
const fake = new THREE.Mesh(geo,
|
|
23857
|
+
const fake = new THREE.Mesh(geo, shared2.mirrorMat);
|
|
23456
23858
|
fake.userData.part = "mirror";
|
|
23457
23859
|
fake.name = "mirror/environment";
|
|
23458
23860
|
g.add(fake);
|
|
@@ -23468,27 +23870,27 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23468
23870
|
console.warn("mirror real", e);
|
|
23469
23871
|
}
|
|
23470
23872
|
(groups[E.parent] || (groups[E.parent] = new THREE.Group())).add(g);
|
|
23471
|
-
|
|
23873
|
+
shared2.mirrors.list.push({ E, g, fake, real });
|
|
23472
23874
|
}
|
|
23473
23875
|
}
|
|
23474
23876
|
function floorAtY(y) {
|
|
23475
|
-
const A =
|
|
23877
|
+
const A = shared2.ctx.r.floors;
|
|
23476
23878
|
let f = 0;
|
|
23477
23879
|
for (let i = 0; i < A.length; i++) if (y >= A[i].y0 - 0.2) f = i;
|
|
23478
23880
|
return f;
|
|
23479
23881
|
}
|
|
23480
23882
|
function chooseMirror(camera) {
|
|
23481
|
-
if (!
|
|
23883
|
+
if (!shared2.mirrors.list.length) return;
|
|
23482
23884
|
let target = null;
|
|
23483
|
-
if (
|
|
23484
|
-
|
|
23485
|
-
|
|
23486
|
-
const f = floorAtY(
|
|
23487
|
-
if (c &&
|
|
23885
|
+
if (shared2.mirrors.house && shared2.ctx.r) {
|
|
23886
|
+
shared2.mirrors.tmp.copy(camera.position);
|
|
23887
|
+
shared2.mirrors.house.worldToLocal(shared2.mirrors.tmp);
|
|
23888
|
+
const f = floorAtY(shared2.mirrors.tmp.y), c = roomAt(f, shared2.mirrors.tmp.x, shared2.mirrors.tmp.z);
|
|
23889
|
+
if (c && shared2.mirrors.tmp.y > Y0(f) && shared2.mirrors.tmp.y < Y0(f) + 4) {
|
|
23488
23890
|
let best = 1e9;
|
|
23489
|
-
for (const m of
|
|
23891
|
+
for (const m of shared2.mirrors.list) {
|
|
23490
23892
|
if (m.E.room !== c.id || m.E.floor !== f || !m.g.parent || !m.g.parent.visible) continue;
|
|
23491
|
-
const d = Math.hypot(m.E.x -
|
|
23893
|
+
const d = Math.hypot(m.E.x - shared2.mirrors.tmp.x, m.E.z - shared2.mirrors.tmp.z);
|
|
23492
23894
|
if (d < best) {
|
|
23493
23895
|
best = d;
|
|
23494
23896
|
target = m;
|
|
@@ -23496,9 +23898,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23496
23898
|
}
|
|
23497
23899
|
}
|
|
23498
23900
|
}
|
|
23499
|
-
if (target ===
|
|
23500
|
-
|
|
23501
|
-
for (const m of
|
|
23901
|
+
if (target === shared2.mirrors.active) return;
|
|
23902
|
+
shared2.mirrors.active = target;
|
|
23903
|
+
for (const m of shared2.mirrors.list) {
|
|
23502
23904
|
const on = m === target && !!m.real;
|
|
23503
23905
|
if (m.real) m.real.visible = on;
|
|
23504
23906
|
m.fake.visible = !on;
|
|
@@ -23506,7 +23908,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23506
23908
|
}
|
|
23507
23909
|
Object.assign(K, { mirrorEnv, newMirrorState, assembleMirrors, floorAtY, chooseMirror });
|
|
23508
23910
|
}
|
|
23509
|
-
function installCars(K,
|
|
23911
|
+
function installCars(K, shared2) {
|
|
23510
23912
|
const { THREE, FLEET, _Y } = K;
|
|
23511
23913
|
const CARS = [];
|
|
23512
23914
|
const CAR_BY_STYLE = Object.assign({
|
|
@@ -23532,12 +23934,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23532
23934
|
return b;
|
|
23533
23935
|
}
|
|
23534
23936
|
function carModel(k, seed) {
|
|
23535
|
-
const kc = k + "|" +
|
|
23937
|
+
const kc = k + "|" + shared2.quality + "|" + (seed || 0);
|
|
23536
23938
|
if (CAR_CACHE.has(kc)) return CAR_CACHE.get(kc);
|
|
23537
23939
|
if (!FLEET) return null;
|
|
23538
23940
|
let res = null;
|
|
23539
23941
|
try {
|
|
23540
|
-
const v0 = FLEET.build(k, { quality:
|
|
23942
|
+
const v0 = FLEET.build(k, { quality: shared2.quality, seed: seed || 0 }), c = { root: v0.group, g: v0.group };
|
|
23541
23943
|
c.root.updateMatrixWorld(true);
|
|
23542
23944
|
const inv = new THREE.Matrix4();
|
|
23543
23945
|
const byMaterial = /* @__PURE__ */ new Map(), tmp = new THREE.Matrix4(), v = new THREE.Vector3(), nm = new THREE.Matrix3(), bb = new THREE.Box3();
|
|
@@ -23657,7 +24059,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23657
24059
|
return g;
|
|
23658
24060
|
}
|
|
23659
24061
|
function assembleCars(groups) {
|
|
23660
|
-
if (
|
|
24062
|
+
if (shared2.quality === "game") return assembleMergedCars(groups);
|
|
23661
24063
|
for (const C of CARS) {
|
|
23662
24064
|
const g = carGroup(C.k, C.w, C.d, C.seed);
|
|
23663
24065
|
if (!g) continue;
|
|
@@ -23710,10 +24112,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23710
24112
|
}
|
|
23711
24113
|
Object.assign(K, { CARS, CAR_BY_STYLE, CAR_CACHE, materialSignature, BUCKETS, bucketMaterial, carModel, carGroup, assembleCars, assembleMergedCars });
|
|
23712
24114
|
}
|
|
23713
|
-
function installHouseBuilding(K,
|
|
24115
|
+
function installHouseBuilding(K, shared2) {
|
|
23714
24116
|
const { bx, cursor } = K;
|
|
23715
24117
|
function building() {
|
|
23716
|
-
const R =
|
|
24118
|
+
const R = shared2.ctx.r, P = R.building, C = shared2.ctx.colors, N = shared2.ctx.pa, uf = shared2.ctx.pf, pe = P.ceilingHeight, fa = C.facade != null ? C.facade : 14209216;
|
|
23717
24119
|
cursor.group = "building";
|
|
23718
24120
|
const uw = P.unit.w, ud = P.unit.d, un = P.units;
|
|
23719
24121
|
const unitBox = (u) => {
|
|
@@ -23721,7 +24123,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23721
24123
|
return [x[0], z[0], x[1], z[1]];
|
|
23722
24124
|
};
|
|
23723
24125
|
const un0 = unitBox(un[0]), color2 = P.corridor, hall = P.hall, el = P.elevator.rect, es = P.stairs.rect;
|
|
23724
|
-
const sel = un[
|
|
24126
|
+
const sel = un[shared2.ctx.pu] || un[0], selR = unitBox(sel);
|
|
23725
24127
|
const shell = (rc, y0, y1, thickness = 0.15) => {
|
|
23726
24128
|
const [a, b, c, d] = rc;
|
|
23727
24129
|
bx("building", a, y0, b, c, y1, b + thickness, fa);
|
|
@@ -23760,11 +24162,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23760
24162
|
}
|
|
23761
24163
|
const ytop = N * pe - 0.2;
|
|
23762
24164
|
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);
|
|
23763
|
-
|
|
24165
|
+
shared2.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) };
|
|
23764
24166
|
}
|
|
23765
24167
|
Object.assign(K, { building });
|
|
23766
24168
|
}
|
|
23767
|
-
function installUtilitiesWater(K,
|
|
24169
|
+
function installUtilitiesWater(K, shared2) {
|
|
23768
24170
|
const { THREE, _Y, _q, cursor, cylBase, part, pieceRecord, put } = K;
|
|
23769
24171
|
function createWater(r, state) {
|
|
23770
24172
|
const H = r.utilities.plumbing, cap = H ? +H.capacityL || 0 : 0, ls = { dry: [], full: [] }, points = {}, itemPoint = {};
|
|
@@ -23856,14 +24258,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23856
24258
|
}
|
|
23857
24259
|
const _v3 = new THREE.Vector3();
|
|
23858
24260
|
function waterPipes() {
|
|
23859
|
-
const H =
|
|
24261
|
+
const H = shared2.ctx.r.utilities.plumbing;
|
|
23860
24262
|
if (!H || !H.visibleRuns) return;
|
|
23861
|
-
const nA =
|
|
24263
|
+
const nA = shared2.ctx.r.floors.length;
|
|
23862
24264
|
const groupOf = (c) => c && c.floor >= 0 ? "f" + Math.min(c.floor, nA - 1) : "lot", xyz = (p) => [p[0], p[2], p[1]];
|
|
23863
24265
|
for (const tr of H.visibleRuns) {
|
|
23864
24266
|
const pts = tr.points.map(xyz), d = tr.diameter || 0.025;
|
|
23865
24267
|
if (tr.exposed === "wall") {
|
|
23866
|
-
const pt = H.points.find((p) => p.run === tr.id), com =
|
|
24268
|
+
const pt = H.points.find((p) => p.run === tr.id), com = shared2.ctx.roomById[tr.to], g2 = groupOf(com || pt && { floor: pt.floor });
|
|
23867
24269
|
part("wall_pipe", [0, 0, 0], () => {
|
|
23868
24270
|
for (let i = 0; i + 1 < pts.length; i++) pipe(pts[i], pts[i + 1], d, PIPE_COLOR);
|
|
23869
24271
|
for (const p of pts) cylBase("plain", p[0], p[1] - d, p[2], d * 0.7, d * 2, PIPE_COLOR);
|
|
@@ -23871,7 +24273,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23871
24273
|
continue;
|
|
23872
24274
|
}
|
|
23873
24275
|
let g;
|
|
23874
|
-
if (tr.exposed === "tank_outlet") g =
|
|
24276
|
+
if (tr.exposed === "tank_outlet") g = shared2.ctx.waterTankPos && shared2.ctx.waterTankPos.group || "f0";
|
|
23875
24277
|
else {
|
|
23876
24278
|
const pt = H.points.find((p) => p.id === tr.to);
|
|
23877
24279
|
g = groupOf(pt);
|
|
@@ -23887,15 +24289,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23887
24289
|
}
|
|
23888
24290
|
Object.assign(K, { createWater, PIPE_COLOR, pipe, _v3, waterPipes });
|
|
23889
24291
|
}
|
|
23890
|
-
function installUtilitiesElectrical(K,
|
|
24292
|
+
function installUtilitiesElectrical(K, shared2) {
|
|
23891
24293
|
const { _Y, _q, _v3, bx, cursor, cylBase, pieceRecord, put } = K;
|
|
23892
24294
|
const sh = (...a) => K.sh(...a);
|
|
23893
24295
|
function electricalStructure() {
|
|
23894
|
-
const E =
|
|
23895
|
-
|
|
24296
|
+
const E = shared2.ctx.r.utilities.electrical;
|
|
24297
|
+
shared2.ctx.electricalInfo = null;
|
|
23896
24298
|
if (!E) return;
|
|
23897
|
-
const R =
|
|
23898
|
-
const en22 = E.serviceEntrance, KV =
|
|
24299
|
+
const R = shared2.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 };
|
|
24300
|
+
const en22 = E.serviceEntrance, KV = shared2.ctx.iv ? shared2.ctx.iv.plane : null;
|
|
23899
24301
|
const wireL = (a, b, r_ = 8e-3) => {
|
|
23900
24302
|
const L = Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
|
|
23901
24303
|
if (L < 1e-3) return;
|
|
@@ -23973,7 +24375,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23973
24375
|
info.conduits.push(t.id);
|
|
23974
24376
|
continue;
|
|
23975
24377
|
}
|
|
23976
|
-
const c = circ[t.circuit], com = c &&
|
|
24378
|
+
const c = circ[t.circuit], com = c && shared2.ctx.roomById[c.room];
|
|
23977
24379
|
cursor.group = "f" + Math.max(0, Math.min(nA - 1, com ? com.floor : 0));
|
|
23978
24380
|
const d = t.diameter || 0.02, P = t.points.map((p) => [p[0], p[2], p[1]]), seg2 = [];
|
|
23979
24381
|
for (let i = 0; i + 1 < P.length; i++) {
|
|
@@ -23991,7 +24393,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23991
24393
|
}
|
|
23992
24394
|
for (const t of E.outlets || []) info.outlets.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, type: t.type, voltage: t.voltage });
|
|
23993
24395
|
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 });
|
|
23994
|
-
|
|
24396
|
+
shared2.ctx.electricalInfo = info;
|
|
23995
24397
|
}
|
|
23996
24398
|
function pipe2(a, b, diameter, color2) {
|
|
23997
24399
|
const dx = b[0] - a[0], dy = b[1] - a[1], dz = b[2] - a[2], L = Math.hypot(dx, dy, dz);
|
|
@@ -24001,11 +24403,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
24001
24403
|
}
|
|
24002
24404
|
Object.assign(K, { electricalStructure, pipe2 });
|
|
24003
24405
|
}
|
|
24004
|
-
function installHouseBaseboard(K,
|
|
24406
|
+
function installHouseBaseboard(K, shared2) {
|
|
24005
24407
|
const { Y0, bx, cursor, sideOf } = K;
|
|
24006
24408
|
const sh = (...a) => K.sh(...a);
|
|
24007
24409
|
function baseboardAndSidewalk() {
|
|
24008
|
-
const R =
|
|
24410
|
+
const R = shared2.ctx.r, W = 0.6, t = 0.012, ht = 0.35, color2 = sh(shared2.ctx.colors.facade != null ? shared2.ctx.colors.facade : 14209216, 0.62), y0 = Y0(0), cal = 13947078;
|
|
24009
24411
|
const ws = R.walls.filter((w) => w.floor === 0 && w.type === "wall").map((w) => {
|
|
24010
24412
|
const au = w.axis === "u";
|
|
24011
24413
|
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 };
|
|
@@ -24037,11 +24439,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
24037
24439
|
}
|
|
24038
24440
|
Object.assign(K, { baseboardAndSidewalk });
|
|
24039
24441
|
}
|
|
24040
|
-
function installUtilitiesSolar(K,
|
|
24442
|
+
function installUtilitiesSolar(K, shared2) {
|
|
24041
24443
|
const { Y0, boxC, bx, cursor, cylBase } = K;
|
|
24042
24444
|
function roofHeightAt(u, v, f) {
|
|
24043
24445
|
let y = null;
|
|
24044
|
-
for (const rr of
|
|
24446
|
+
for (const rr of shared2.ctx.roofRects || []) {
|
|
24045
24447
|
if (rr.yb == null || f != null && rr.f !== f) continue;
|
|
24046
24448
|
if (rr.slab) {
|
|
24047
24449
|
const [a, b, c, d] = rr.r;
|
|
@@ -24056,8 +24458,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
24056
24458
|
return y;
|
|
24057
24459
|
}
|
|
24058
24460
|
function solar() {
|
|
24059
|
-
const R =
|
|
24060
|
-
|
|
24461
|
+
const R = shared2.ctx.r, S = R.utilities.solar;
|
|
24462
|
+
shared2.ctx.solarInfo = null;
|
|
24061
24463
|
if (!S || !S.panels || !S.panels.length) return;
|
|
24062
24464
|
cursor.group = "roof";
|
|
24063
24465
|
const silver = 13225426, blue = 1780302, line = 9279142, sv = S.north === "front" ? -1 : 1, info = { type: S.type, panels: [], inverter: null }, onRack = S.type === "slab_rack";
|
|
@@ -24099,15 +24501,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
24099
24501
|
bx("plain", iv.u - W * 0.6, y0 + 0.05, iv.v + fa0, iv.u + W * 0.6, y0 + 0.17, iv.v + fa1, 2106924);
|
|
24100
24502
|
bx("emissive", iv.u - 0.03, y0 - 0.12, iv.v + fa0, iv.u + 0.03, y0 - 0.09, iv.v + fa1, 6479994);
|
|
24101
24503
|
}
|
|
24102
|
-
const top = Math.max(...(
|
|
24504
|
+
const top = Math.max(...(shared2.ctx.roofRects || []).filter((t2) => t2.yb != null).map((t2) => t2.yb), Y0(fa) + 2.8);
|
|
24103
24505
|
cylBase("plain", iv.u, y0 + h / 2, iv.v, 0.016, Math.max(0.2, top - 0.2 - (y0 + h / 2)), 15262936);
|
|
24104
24506
|
info.inverter = { id: iv.id, pos: [iv.u, y0, iv.v], side: iv.side, link: iv.link };
|
|
24105
24507
|
}
|
|
24106
|
-
|
|
24508
|
+
shared2.ctx.solarInfo = info;
|
|
24107
24509
|
}
|
|
24108
24510
|
Object.assign(K, { roofHeightAt, solar });
|
|
24109
24511
|
}
|
|
24110
|
-
function installHouseOutbuildings(K,
|
|
24512
|
+
function installHouseOutbuildings(K, shared2) {
|
|
24111
24513
|
const { t, bx, cursor, floorColor } = K;
|
|
24112
24514
|
const sh = (...a) => K.sh(...a);
|
|
24113
24515
|
const OUTBUILDING_USE = { guest_room: ["bedroom", "bedroom", t("outbuilding.guest_room")], office: ["office", "office", t("outbuilding.office")], storage: ["stockroom", "stockroom", t("outbuilding.storage")], gourmet: ["living", "gourmet", t("outbuilding.gourmet")] };
|
|
@@ -24139,17 +24541,17 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
24139
24541
|
return Object.assign({}, r, { rooms, walls, doors, windows, items });
|
|
24140
24542
|
}
|
|
24141
24543
|
function outbuildings() {
|
|
24142
|
-
const E = (
|
|
24143
|
-
|
|
24544
|
+
const E = (shared2.ctx.r.outbuildings || []).filter((e) => shared2.ctx.roomById[e.id] && shared2.ctx.roomById[e.id].outbuilding);
|
|
24545
|
+
shared2.ctx.outbuildingList = E;
|
|
24144
24546
|
if (!E.length) return;
|
|
24145
24547
|
cursor.group = "f0";
|
|
24146
24548
|
for (const e of E) {
|
|
24147
|
-
const c =
|
|
24549
|
+
const c = shared2.ctx.roomById[e.id], col = floorColor(c);
|
|
24148
24550
|
for (const [a, b, c2, d] of e.interior) bx("plaster", a - 0.075, 0, b - 0.075, c2 + 0.075, 0.04, d + 0.075, col);
|
|
24149
24551
|
for (const p of e.doors || []) {
|
|
24150
24552
|
const alongU = p.axis === "u", th = e.thickness || 0.15;
|
|
24151
|
-
if (alongU) bx("plaster", p.at - p.width / 2, 0, p.pos - th / 2 - 0.12, p.at + p.width / 2, 0.03, p.pos + th / 2 + 0.12, sh(
|
|
24152
|
-
else bx("plaster", p.pos - th / 2 - 0.12, 0, p.at - p.width / 2, p.pos + th / 2 + 0.12, 0.03, p.at + p.width / 2, sh(
|
|
24553
|
+
if (alongU) bx("plaster", p.at - p.width / 2, 0, p.pos - th / 2 - 0.12, p.at + p.width / 2, 0.03, p.pos + th / 2 + 0.12, sh(shared2.ctx.colors.facade || 14209216, 0.8));
|
|
24554
|
+
else bx("plaster", p.pos - th / 2 - 0.12, 0, p.at - p.width / 2, p.pos + th / 2 + 0.12, 0.03, p.at + p.width / 2, sh(shared2.ctx.colors.facade || 14209216, 0.8));
|
|
24153
24555
|
}
|
|
24154
24556
|
}
|
|
24155
24557
|
}
|
|
@@ -24883,10 +25285,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
24883
25285
|
}
|
|
24884
25286
|
Object.assign(K, { typeTable });
|
|
24885
25287
|
}
|
|
24886
|
-
function installFurnitureTaps(K,
|
|
24887
|
-
|
|
25288
|
+
function installFurnitureTaps(K, shared2) {
|
|
25289
|
+
shared2.tapCount = 0;
|
|
24888
25290
|
function counterTap(K2, x, y, z, reach, back, meta = {}) {
|
|
24889
|
-
const cr = 12896460, id = "tap_" + (K2.M.seed || "") + "_" +
|
|
25291
|
+
const cr = 12896460, id = "tap_" + (K2.M.seed || "") + "_" + shared2.tapCount++;
|
|
24890
25292
|
K2.c("metal", x, y, z, 0.028, 0.012, cr);
|
|
24891
25293
|
K2.c("metal", x, y + 0.012, z, 0.014, 0.12, cr);
|
|
24892
25294
|
const pts = [];
|
|
@@ -24917,7 +25319,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
24917
25319
|
return id;
|
|
24918
25320
|
}
|
|
24919
25321
|
function wallTap(K2, x, y, zw, direction, back, meta = {}) {
|
|
24920
|
-
const cr = 12896460, id = "tap_" + (K2.M.seed || "") + "_" +
|
|
25322
|
+
const cr = 12896460, id = "tap_" + (K2.M.seed || "") + "_" + shared2.tapCount++, s = direction || 1;
|
|
24921
25323
|
K2.t("metal", [x, y, zw], [x, y, zw + s * 0.025], 0.03, cr);
|
|
24922
25324
|
K2.t("metal", [x, y, zw + s * 0.02], [x, y, zw + s * 0.1], 0.016, cr);
|
|
24923
25325
|
K2.e("metal", x, y, zw + s * 0.105, 0.019, 0.04, cr);
|
|
@@ -25167,7 +25569,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25167
25569
|
}
|
|
25168
25570
|
Object.assign(K, { GREENS: GREENS2, FLOWERS, blobs, potModel, arcLeaf, tuft, palm_tree, treeModel, shrubModel, potPlant, tablePot, planterModel });
|
|
25169
25571
|
}
|
|
25170
|
-
function installFurnitureYard(K,
|
|
25572
|
+
function installFurnitureYard(K, shared2) {
|
|
25171
25573
|
const seedKey = (id) => K.seedKey(id);
|
|
25172
25574
|
const { FURNITURE, SEED, STYLE, kit2, rngString, sh, wallTap } = K;
|
|
25173
25575
|
FURNITURE.laundry_tub = function(M, A) {
|
|
@@ -25257,7 +25659,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25257
25659
|
}
|
|
25258
25660
|
}
|
|
25259
25661
|
}, { id: "laundry_" + M.seed, swing: true, room: "yard" });
|
|
25260
|
-
(
|
|
25662
|
+
(shared2.ctx.clotheslines || (shared2.ctx.clotheslines = [])).push(M.seed);
|
|
25261
25663
|
};
|
|
25262
25664
|
FURNITURE.water_tank = function(M, A) {
|
|
25263
25665
|
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;
|
|
@@ -25399,13 +25801,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25399
25801
|
}
|
|
25400
25802
|
Object.assign(K, { extraTypes });
|
|
25401
25803
|
}
|
|
25402
|
-
function installFurniturePlaceItems(K,
|
|
25804
|
+
function installFurniturePlaceItems(K, shared2) {
|
|
25403
25805
|
const { THREE, Y0, _col, boxC, colorOf, cursor, decorLights, makeApi, structurePiece } = K;
|
|
25404
25806
|
const buildItem2 = (...a) => K.buildItem(...a);
|
|
25405
25807
|
const registerCollision = (...a) => K.registerCollision(...a);
|
|
25406
25808
|
const vegItem = (...a) => K.vegItem(...a);
|
|
25407
25809
|
function houseItems() {
|
|
25408
|
-
const R =
|
|
25810
|
+
const R = shared2.ctx.r, T2 = shared2.ctx.types, api = makeApi(), noModel = /* @__PURE__ */ new Map();
|
|
25409
25811
|
const list2 = R.items.concat(R.stateItems.filter((e) => e.w != null && e.d != null && e.type !== "razor_wire" && e.type !== "barbed_wire"));
|
|
25410
25812
|
const rect = (poly) => {
|
|
25411
25813
|
let a = 0;
|
|
@@ -25417,8 +25819,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25417
25819
|
if (m.type === "stairs") continue;
|
|
25418
25820
|
const exterior = m.outdoor || m.floor < 0, f = exterior ? -1 : Math.min(m.floor, R.floors.length - 1);
|
|
25419
25821
|
cursor.group = exterior ? "lot" : "f" + f;
|
|
25420
|
-
const com =
|
|
25421
|
-
const M = { x: m.x, z: m.z, ry: m.ry || 0, w: m.w, d: m.d, h: m.h, y: m.y || 0, base, floor: exterior ? -1 : f, palette:
|
|
25822
|
+
const com = shared2.ctx.roomById[m.room], base = exterior ? 0 : Y0(f);
|
|
25823
|
+
const M = { x: m.x, z: m.z, ry: m.ry || 0, w: m.w, d: m.d, h: m.h, y: m.y || 0, base, floor: exterior ? -1 : f, palette: shared2.ctx.colors, color: m.category === "ground_cover" ? void 0 : colorOf(m.color) != null ? colorOf(m.color) : void 0, seed: m.id, room: m.room, typeWith: com ? com.type : null, ceiling: com ? com.ceiling : 2.9, on: shared2.ctx.night, light: shared2.ctx.night, lit: shared2.ctx.night, open: !!m.doorOpen, overhead: m.overhead, assembly: m.assembly, hose: m.hose };
|
|
25422
25824
|
if (m.category === "ground_cover" && m.polygon) {
|
|
25423
25825
|
const xs = m.polygon.map((p) => p[0]), zs = m.polygon.map((p) => p[1]);
|
|
25424
25826
|
M.x = (Math.min(...xs) + Math.max(...xs)) / 2;
|
|
@@ -25428,8 +25830,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25428
25830
|
M.ry = 0;
|
|
25429
25831
|
if (!rect(m.polygon)) M.poly = m.polygon.map((p) => [p[0] - M.x, p[1] - M.z]);
|
|
25430
25832
|
}
|
|
25431
|
-
if (
|
|
25432
|
-
if (
|
|
25833
|
+
if (shared2.ctx.veg && vegItem(m, M, exterior ? "lot" : "f" + f)) continue;
|
|
25834
|
+
if (shared2.ctx.iv && shared2.ctx.iv.replace.has(m.id)) {
|
|
25433
25835
|
registerCollision(m, M);
|
|
25434
25836
|
continue;
|
|
25435
25837
|
}
|
|
@@ -25461,13 +25863,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25461
25863
|
return noModel;
|
|
25462
25864
|
}
|
|
25463
25865
|
function waterTankOfHouse(api) {
|
|
25464
|
-
const cd =
|
|
25465
|
-
if (!cd || !
|
|
25466
|
-
const lc = cd.place === "raised_slab" && cd.platform, slab = cd.place === "slab" || !!lc, nA =
|
|
25467
|
-
const base = lc ? cd.platform.topY : cd.y + (
|
|
25866
|
+
const cd = shared2.ctx.r.waterTank;
|
|
25867
|
+
if (!cd || !shared2.ctx.types.water_tank) return;
|
|
25868
|
+
const lc = cd.place === "raised_slab" && cd.platform, slab = cd.place === "slab" || !!lc, nA = shared2.ctx.r.floors.length, f = Math.max(0, Math.min(nA - 1, cd.floor));
|
|
25869
|
+
const base = lc ? cd.platform.topY : cd.y + (shared2.ctx.r.rooms.some((c) => c.id === cd.room && c.type === "terrace") ? 0 : 0.2 + (slab ? 0.03 : 0));
|
|
25468
25870
|
cursor.group = slab ? "f" + f : "attic_tank";
|
|
25469
25871
|
if (lc) {
|
|
25470
|
-
const P = cd.platform, [x0, z0, x1, z1] = P.aabb, e = P.thickness, color2 =
|
|
25872
|
+
const P = cd.platform, [x0, z0, x1, z1] = P.aabb, e = P.thickness, color2 = shared2.ctx.colors.slab != null ? shared2.ctx.colors.slab : 12170668;
|
|
25471
25873
|
cursor.pc = structurePiece("tank_slab");
|
|
25472
25874
|
boxC("plain", (x0 + x1) / 2, P.topY - e / 2, (z0 + z1) / 2, x1 - x0, e, z1 - z0, color2, 0, 0, 0);
|
|
25473
25875
|
P.pillars.forEach((p, k) => {
|
|
@@ -25477,13 +25879,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25477
25879
|
cursor.pc = null;
|
|
25478
25880
|
}
|
|
25479
25881
|
if (!slab) {
|
|
25480
|
-
const color2 =
|
|
25882
|
+
const color2 = shared2.ctx.colors.slab != null ? shared2.ctx.colors.slab : 12170668, yp = Y0(f), hw = cd.w / 2 + 0.1, hd = cd.d / 2 + 0.1;
|
|
25481
25883
|
boxC("plain", cd.u, base - 0.06, cd.v, hw * 2, 0.12, hd * 2, color2);
|
|
25482
25884
|
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);
|
|
25483
25885
|
}
|
|
25484
|
-
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:
|
|
25485
|
-
|
|
25486
|
-
|
|
25886
|
+
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: shared2.ctx.colors, seed: "water_tank", room: cd.room, onSlab: true, ceiling: 2.9 };
|
|
25887
|
+
shared2.ctx.waterTankPos = { x: cd.u, z: cd.v, y: base, group: cursor.group };
|
|
25888
|
+
shared2.ctx.types.water_tank.f(M, api);
|
|
25487
25889
|
}
|
|
25488
25890
|
function hashColor(s) {
|
|
25489
25891
|
let h = 7;
|
|
@@ -25493,11 +25895,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25493
25895
|
function labeledBox(m, M, group) {
|
|
25494
25896
|
const color2 = M.color != null ? M.color : hashColor(m.category || m.type), h = Math.max(0.05, m.h || 0.5);
|
|
25495
25897
|
boxC("plain", m.x, M.base + (m.y || 0) + h / 2, m.z, m.w, h, m.d, color2, 0, m.ry || 0, 0);
|
|
25496
|
-
|
|
25898
|
+
shared2.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" });
|
|
25497
25899
|
}
|
|
25498
25900
|
Object.assign(K, { houseItems, waterTankOfHouse, hashColor, labeledBox });
|
|
25499
25901
|
}
|
|
25500
|
-
function installVegetationBridge(K,
|
|
25902
|
+
function installVegetationBridge(K, shared2) {
|
|
25501
25903
|
const seedKey = (id) => K.seedKey(id);
|
|
25502
25904
|
const { THREE, SEED, rngString } = K;
|
|
25503
25905
|
const VEG_POT = ["potted_areca", "potted_snake_plant", "potted_fern"], VEG_CACTUS = { cactus_mandacaru: "mandacaru", cactus_palm: "prickly_pear", cactus_crown: "crown_cactus", cactus_xique: "xique_xique", cactus_pot: "potted_cactus" };
|
|
@@ -25523,7 +25925,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25523
25925
|
for (const k of Object.keys(VEG_CACTUS)) VEG_MAP[k] = [VEG_CACTUS[k]];
|
|
25524
25926
|
const VEG_PLANTER = { planter_bed: ["rose_bush_red", "rose_bush_pink", "rose_bush_white", "marigold", "periwinkle_pink", "periwinkle_white", "daisy"], planter_bed_small: ["rose_bush_red", "marigold", "periwinkle_pink", "daisy"], garden_bed: ["lawn_tuft", "wild_flowers"] };
|
|
25525
25927
|
function vegItem(m, M, group) {
|
|
25526
|
-
const V =
|
|
25928
|
+
const V = shared2.ctx.veg;
|
|
25527
25929
|
if (!V) return false;
|
|
25528
25930
|
const ids = VEG_MAP[m.type], can2 = VEG_PLANTER[m.type];
|
|
25529
25931
|
if (!ids && !can2) return false;
|
|
@@ -25564,7 +25966,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25564
25966
|
return true;
|
|
25565
25967
|
}
|
|
25566
25968
|
function assembleVegetation(groups) {
|
|
25567
|
-
const V =
|
|
25969
|
+
const V = shared2.ctx.veg;
|
|
25568
25970
|
if (!V) return;
|
|
25569
25971
|
let pl = 0, tri = 0;
|
|
25570
25972
|
const col = [], lod = [0, 0, 0], mats = V.mats();
|
|
@@ -25587,17 +25989,17 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25587
25989
|
for (const c of lot.colliders) col.push(Object.assign({ y: G.y, group: G.group }, c));
|
|
25588
25990
|
for (let i = 0; i < 3; i++) lod[i] += lot.lodCounts[i];
|
|
25589
25991
|
}
|
|
25590
|
-
|
|
25992
|
+
shared2.ctx.vegInfo = { plants: pl, triangles: tri, colliders: col, lodCounts: lod, materials: mats };
|
|
25591
25993
|
}
|
|
25592
25994
|
Object.assign(K, { VEG_POT, VEG_CACTUS, VEG_MAP, VEG_PLANTER, vegItem, assembleVegetation });
|
|
25593
25995
|
}
|
|
25594
|
-
function installInteractionState(K,
|
|
25996
|
+
function installInteractionState(K, shared2) {
|
|
25595
25997
|
const { THREE, cfg, colliderChanged, invalidateShadow, invalidate, UV_SCALE, applyPart, texture } = K;
|
|
25596
25998
|
const ivRoomEffective = (...a) => K.ivRoomEffective(...a);
|
|
25597
25999
|
const ivRoomLight = (...a) => K.ivRoomLight(...a);
|
|
25598
|
-
|
|
26000
|
+
shared2.partState = /* @__PURE__ */ new Map();
|
|
25599
26001
|
const newInteractiveState = () => ({ defs: /* @__PURE__ */ new Map(), items: [], pieces: [], lights: /* @__PURE__ */ new Map(), litRooms: /* @__PURE__ */ new Set(), objs: [], anim: /* @__PURE__ */ new Set(), msg: null, target: null });
|
|
25600
|
-
|
|
26002
|
+
shared2.inter = newInteractiveState();
|
|
25601
26003
|
const MESSAGE_MS = 2200;
|
|
25602
26004
|
UV_SCALE.doorWood = 1;
|
|
25603
26005
|
UV_SCALE.doorPaint = 1;
|
|
@@ -25652,15 +26054,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25652
26054
|
}
|
|
25653
26055
|
const _EY = new THREE.Vector3(0, 1, 0), _UM3 = new THREE.Vector3(1, 1, 1);
|
|
25654
26056
|
const hudMessage = (text) => {
|
|
25655
|
-
|
|
26057
|
+
shared2.inter.msg = { text, until: performance.now() + MESSAGE_MS };
|
|
25656
26058
|
if (cfg.onMessage) cfg.onMessage(text);
|
|
25657
26059
|
};
|
|
25658
26060
|
function definePiece(name, def) {
|
|
25659
26061
|
def.name = name;
|
|
25660
26062
|
def.meshes = [];
|
|
25661
|
-
def.t = def.target =
|
|
25662
|
-
|
|
25663
|
-
|
|
26063
|
+
def.t = def.target = shared2.partState.has(name) ? shared2.partState.get(name) : def.t0 || 0;
|
|
26064
|
+
shared2.inter.defs.set(name, def);
|
|
26065
|
+
shared2.inter.pieces.push(def);
|
|
25664
26066
|
return def;
|
|
25665
26067
|
}
|
|
25666
26068
|
const localOf = (M, lx, lz) => {
|
|
@@ -25672,7 +26074,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25672
26074
|
return true;
|
|
25673
26075
|
}
|
|
25674
26076
|
function assembleInteractive(gs) {
|
|
25675
|
-
for (const [name, def] of
|
|
26077
|
+
for (const [name, def] of shared2.inter.defs) {
|
|
25676
26078
|
const g = gs[name];
|
|
25677
26079
|
if (!g) continue;
|
|
25678
26080
|
delete gs[name];
|
|
@@ -25694,13 +26096,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25694
26096
|
const parent = def.leaf ? def.leaf.gs[def.k] : gs[def.parent] || (gs[def.parent] = new THREE.Group());
|
|
25695
26097
|
if (parent) parent.add(outer);
|
|
25696
26098
|
if (def.roomId) {
|
|
25697
|
-
if (!
|
|
25698
|
-
|
|
26099
|
+
if (!shared2.inter.lights.has(def.roomId)) shared2.inter.lights.set(def.roomId, []);
|
|
26100
|
+
shared2.inter.lights.get(def.roomId).push(def);
|
|
25699
26101
|
}
|
|
25700
26102
|
applyPiece(def);
|
|
25701
26103
|
}
|
|
25702
|
-
for (const roomId of
|
|
25703
|
-
|
|
26104
|
+
for (const roomId of shared2.inter.litRooms) applyLight(roomId);
|
|
26105
|
+
shared2.inter.defs.forEach((d) => {
|
|
25704
26106
|
if (d.col) d.col.off = d.t > 0.5;
|
|
25705
26107
|
});
|
|
25706
26108
|
}
|
|
@@ -25740,8 +26142,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25740
26142
|
}
|
|
25741
26143
|
const DURATION = { swing: 0.55, drawer: 0.4, curtain: 0.9, gate_swing: 0.9, gate_tilt: 1.4, gate_slide: 1.6, lightSwitch: 0.12, part: 0.4 };
|
|
25742
26144
|
function animateInteractive(dt) {
|
|
25743
|
-
if (!
|
|
25744
|
-
for (const p of
|
|
26145
|
+
if (!shared2.inter.anim.size) return;
|
|
26146
|
+
for (const p of shared2.inter.anim) {
|
|
25745
26147
|
const step = dt / (DURATION[p.kind] || 0.5), d = p.target - p.t;
|
|
25746
26148
|
p.t = Math.abs(d) <= step ? p.target : p.t + Math.sign(d) * step;
|
|
25747
26149
|
applyPiece(p);
|
|
@@ -25749,39 +26151,39 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25749
26151
|
p.col.off = p.target > 0.5;
|
|
25750
26152
|
colliderChanged(p.col);
|
|
25751
26153
|
}
|
|
25752
|
-
if (p.t === p.target)
|
|
26154
|
+
if (p.t === p.target) shared2.inter.anim.delete(p);
|
|
25753
26155
|
}
|
|
25754
26156
|
invalidateShadow();
|
|
25755
26157
|
}
|
|
25756
26158
|
function togglePiece(p) {
|
|
25757
26159
|
p.target = p.target > 0.5 ? 0 : 1;
|
|
25758
|
-
|
|
26160
|
+
shared2.partState.set(p.name, p.target);
|
|
25759
26161
|
if (p.col && p.col.off !== p.target > 0.5) {
|
|
25760
26162
|
p.col.off = p.target > 0.5;
|
|
25761
26163
|
colliderChanged(p.col);
|
|
25762
26164
|
}
|
|
25763
|
-
|
|
26165
|
+
shared2.inter.anim.add(p);
|
|
25764
26166
|
}
|
|
25765
|
-
const lightBase = (roomId) => roomId == null ? true :
|
|
26167
|
+
const lightBase = (roomId) => roomId == null ? true : shared2.partState.has("light:" + roomId) ? !!shared2.partState.get("light:" + roomId) : !!shared2.ctx.night;
|
|
25766
26168
|
const lightOn = (roomId) => {
|
|
25767
|
-
const S = roomId != null &&
|
|
26169
|
+
const S = roomId != null && shared2.ctx.iv && shared2.ctx.iv.roomStates.get(roomId);
|
|
25768
26170
|
return S ? S.ef : lightBase(roomId);
|
|
25769
26171
|
};
|
|
25770
26172
|
function applyLight(roomId) {
|
|
25771
26173
|
const on = lightOn(roomId);
|
|
25772
|
-
for (const d of
|
|
25773
|
-
const sw =
|
|
26174
|
+
for (const d of shared2.inter.lights.get(roomId) || []) for (const m of d.meshes) if (m.name.endsWith("/emissive")) m.material = on ? shared2.mats.emissive : shared2.mats.off;
|
|
26175
|
+
const sw = shared2.inter.defs.get("ix:int:" + roomId);
|
|
25774
26176
|
if (sw) {
|
|
25775
26177
|
sw.target = on ? 1 : 0;
|
|
25776
|
-
if (sw.t !== sw.target)
|
|
26178
|
+
if (sw.t !== sw.target) shared2.inter.anim.add(sw);
|
|
25777
26179
|
}
|
|
25778
26180
|
invalidate();
|
|
25779
26181
|
}
|
|
25780
26182
|
function toggleLight(roomId) {
|
|
25781
|
-
const S =
|
|
26183
|
+
const S = shared2.ctx.iv && shared2.ctx.iv.roomStates.get(roomId);
|
|
25782
26184
|
if (S) {
|
|
25783
|
-
ivRoomLight(
|
|
25784
|
-
const ef = ivRoomEffective(
|
|
26185
|
+
ivRoomLight(shared2.ctx.iv, roomId, !S.ef);
|
|
26186
|
+
const ef = ivRoomEffective(shared2.ctx.iv, S);
|
|
25785
26187
|
if (ef !== S.ef) {
|
|
25786
26188
|
S.ef = ef;
|
|
25787
26189
|
applyLight(roomId);
|
|
@@ -25789,13 +26191,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25789
26191
|
}
|
|
25790
26192
|
return;
|
|
25791
26193
|
}
|
|
25792
|
-
|
|
26194
|
+
shared2.partState.set("light:" + roomId, !lightOn(roomId));
|
|
25793
26195
|
applyLight(roomId);
|
|
25794
26196
|
if (cfg.onLight) cfg.onLight(roomId, lightOn(roomId));
|
|
25795
26197
|
}
|
|
25796
26198
|
Object.assign(K, { newInteractiveState, MESSAGE_MS, createInteractiveMaterials, _EY, _UM3, hudMessage, definePiece, localOf, visibleChain, assembleInteractive, applyPiece, DURATION, animateInteractive, togglePiece, lightBase, lightOn, applyLight, toggleLight });
|
|
25797
26199
|
}
|
|
25798
|
-
function installInteractionCollision(K,
|
|
26200
|
+
function installInteractionCollision(K, shared2) {
|
|
25799
26201
|
const NO_COLLIDE = /(^|_)(rug|floor|concrete|dirt|lawn|deck|ceiling_light|pendant|chandelier|spot|picture|curtain|blinds|wall_shelving|plank_shelf|wall_ac|ac_condenser|pool|soaking_tub|pergola|stairs|mirror)/;
|
|
25800
26202
|
function registerCollision(m, M) {
|
|
25801
26203
|
const h = m.h || 0, y = M.y || 0;
|
|
@@ -25805,7 +26207,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25805
26207
|
w = Math.min(w, 0.5);
|
|
25806
26208
|
d = Math.min(d, 0.5);
|
|
25807
26209
|
}
|
|
25808
|
-
|
|
26210
|
+
shared2.inter.objs.push({ f: M.floor, cx: m.x, cz: m.z, c: Math.cos(M.ry), s: Math.sin(M.ry), hw: w / 2, hd: d / 2, type: m.type });
|
|
25809
26211
|
}
|
|
25810
26212
|
function objectDistance(o, x, z) {
|
|
25811
26213
|
const dx = x - o.cx, dz = z - o.cz, lx = dx * o.c - dz * o.s, lz = dx * o.s + dz * o.c, ex = Math.abs(lx) - o.hw, ez = Math.abs(lz) - o.hd;
|
|
@@ -25813,7 +26215,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25813
26215
|
}
|
|
25814
26216
|
function collideObject(x, z, fx, fz, floor) {
|
|
25815
26217
|
const R = 0.2;
|
|
25816
|
-
for (const o of
|
|
26218
|
+
for (const o of shared2.inter.objs) {
|
|
25817
26219
|
if (o.f !== -1 ? o.f !== floor : floor !== 0) continue;
|
|
25818
26220
|
const d1 = objectDistance(o, x, z);
|
|
25819
26221
|
if (d1 < R && d1 < objectDistance(o, fx, fz) - 1e-6) return true;
|
|
@@ -25823,7 +26225,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25823
26225
|
function collideAt(x, z, floor, opt) {
|
|
25824
26226
|
opt = opt || {};
|
|
25825
26227
|
const R = opt.radius != null ? opt.radius : 0.24;
|
|
25826
|
-
for (const c of
|
|
26228
|
+
for (const c of shared2.ctx.colliders) {
|
|
25827
26229
|
if (c.off) continue;
|
|
25828
26230
|
if (c.f !== -1 && c.f !== floor) continue;
|
|
25829
26231
|
if (c.f === -1 && floor !== 0) continue;
|
|
@@ -25835,7 +26237,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25835
26237
|
}
|
|
25836
26238
|
Object.assign(K, { NO_COLLIDE, registerCollision, objectDistance, collideObject, collideAt });
|
|
25837
26239
|
}
|
|
25838
|
-
function installInteractionItems(K,
|
|
26240
|
+
function installInteractionItems(K, shared2) {
|
|
25839
26241
|
const { t, LIGHTS, cursor, definePiece, localOf, registerCollision, togglePiece } = K;
|
|
25840
26242
|
const DOOR_ITEM = /^(tv_unit|tv_unit_small|tv_unit_large|sideboard|china_cabinet|filing_cabinet|pantry|laundry_cabinet|wardrobe|wardrobe_small|wardrobe_large|closet_wardrobe|kitchen_cabinet|kitchen_cabinet_large|kitchen_cabinet_small|fridge|fridge_large|display_fridge_medium|display_fridge)$/;
|
|
25841
26243
|
const DRAWER_ITEM = /^(console_table|dresser|nightstand|vanity_table)$/;
|
|
@@ -25860,7 +26262,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25860
26262
|
}
|
|
25861
26263
|
function lightItem(m, M, ent, api, parent) {
|
|
25862
26264
|
M.on = M.light = M.lit = true;
|
|
25863
|
-
const n0 = LIGHTS.length, name =
|
|
26265
|
+
const n0 = LIGHTS.length, name = shared2.quality === "game" ? "ix:light:" + m.room + "@" + parent : "ix:light:" + m.id;
|
|
25864
26266
|
cursor.group = name;
|
|
25865
26267
|
try {
|
|
25866
26268
|
ent.f(M, api);
|
|
@@ -25868,8 +26270,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25868
26270
|
cursor.group = parent;
|
|
25869
26271
|
}
|
|
25870
26272
|
for (let i = n0; i < LIGHTS.length; i++) LIGHTS[i].roomId = m.room;
|
|
25871
|
-
if (!
|
|
25872
|
-
|
|
26273
|
+
if (!shared2.inter.defs.has(name)) definePiece(name, { kind: "light", pivot: [0, 0, 0], ry: 0, parent, roomId: m.room });
|
|
26274
|
+
shared2.inter.litRooms.add(m.room);
|
|
25873
26275
|
}
|
|
25874
26276
|
function curtainItem(m, M, ent, api, parent) {
|
|
25875
26277
|
M.open = false;
|
|
@@ -25897,12 +26299,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25897
26299
|
for (const c of body) api[c[0]](M, ...c[1]);
|
|
25898
26300
|
if (!parts.length) return;
|
|
25899
26301
|
const [ax, az] = localOf(M, 0, 0.2);
|
|
25900
|
-
|
|
26302
|
+
shared2.inter.items.push({ type: "curtain", id: m.id, floor: M.floor, anchor: [ax, M.base + (M.y || 0) + (m.h || 2) * 0.5, az], range: 2.4, angle: 1, pieces: parts, text: () => t(parts[0].target > 0.5 ? "prompt.close" : "prompt.open", { what: t("what.curtain") }), action: () => {
|
|
25901
26303
|
const al = parts[0].target > 0.5 ? 0 : 1;
|
|
25902
26304
|
for (const p of parts) {
|
|
25903
26305
|
p.target = al;
|
|
25904
|
-
|
|
25905
|
-
|
|
26306
|
+
shared2.partState.set(p.name, al);
|
|
26307
|
+
shared2.inter.anim.add(p);
|
|
25906
26308
|
}
|
|
25907
26309
|
} });
|
|
25908
26310
|
}
|
|
@@ -25972,8 +26374,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25972
26374
|
p.def = def;
|
|
25973
26375
|
parts.push(def);
|
|
25974
26376
|
const [ax, az] = localOf(M, cx, front + 0.08);
|
|
25975
|
-
|
|
25976
|
-
def.item =
|
|
26377
|
+
shared2.inter.items.push({ type: drawer ? "drawer" : "cabinet", id: m.id, floor: M.floor, anchor: [ax, M.base + (M.y || 0) + (p.y0 + p.y1) / 2, az], range: 1.6, angle: 0.4, pieces: [def], text: () => t(def.target > 0.5 ? "prompt.close" : "prompt.open", { what: t("what." + name) }), action: () => togglePiece(def) });
|
|
26378
|
+
def.item = shared2.inter.items[shared2.inter.items.length - 1];
|
|
25977
26379
|
});
|
|
25978
26380
|
calls.forEach((c, i) => {
|
|
25979
26381
|
const p = owner.get(i);
|
|
@@ -25989,10 +26391,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
25989
26391
|
}
|
|
25990
26392
|
Object.assign(K, { DOOR_ITEM, DRAWER_ITEM, LIGHT_TYPES, objectName, recordApi, buildItem: buildItem2, lightItem, curtainItem, furnitureItem });
|
|
25991
26393
|
}
|
|
25992
|
-
function installInteractionFittings(K,
|
|
26394
|
+
function installInteractionFittings(K, shared2) {
|
|
25993
26395
|
const { t, EPS: EPS3, OPEN_AREA, Y0, applyPiece, bx, cursor, definePiece, gates, lightOn, roomAt, slideDirection, toggleLight, togglePiece } = K;
|
|
25994
26396
|
function gatesInteractive() {
|
|
25995
|
-
const lt =
|
|
26397
|
+
const lt = shared2.ctx.r.lot;
|
|
25996
26398
|
if (!lt) return;
|
|
25997
26399
|
const cz0 = (lt.rect[1] + lt.rect[3]) / 2;
|
|
25998
26400
|
const orig = K.getBx(), gs = lt.gates, opening = gs.map((g) => g.open), reg = gs.map((g) => {
|
|
@@ -26014,7 +26416,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26014
26416
|
}
|
|
26015
26417
|
return orig(mat, x0, y0, z0, x1, y1, z1, color2);
|
|
26016
26418
|
});
|
|
26017
|
-
const n0 =
|
|
26419
|
+
const n0 = shared2.ctx.colliders.length;
|
|
26018
26420
|
try {
|
|
26019
26421
|
gs.forEach((g) => {
|
|
26020
26422
|
g.open = false;
|
|
@@ -26026,7 +26428,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26026
26428
|
g.open = opening[i];
|
|
26027
26429
|
});
|
|
26028
26430
|
}
|
|
26029
|
-
const cols =
|
|
26431
|
+
const cols = shared2.ctx.colliders.slice(n0), cz = (lt.rect[1] + lt.rect[3]) / 2, cu = (lt.rect[0] + lt.rect[2]) / 2;
|
|
26030
26432
|
reg.forEach((r, i) => {
|
|
26031
26433
|
const g = r.g;
|
|
26032
26434
|
if (!isFinite(r.x0)) return;
|
|
@@ -26035,25 +26437,25 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26035
26437
|
const p = ped ? definePiece(name, Object.assign(base, { kind: "gate_swing", pivot: [r.x0, 0, g.v], angle: -sd * 1.65 })) : tilt ? definePiece(name, Object.assign(base, { kind: "gate_tilting", pivot: [(r.x0 + r.x1) / 2, r.y1, g.v], angle: -sd * 1.45 })) : definePiece(name, Object.assign(base, { kind: "gate_sliding", pivot: [r.x0, 0, r.zm], travel: r.dx * g.width }));
|
|
26036
26438
|
if (p.col) p.col.off = p.target > 0.5;
|
|
26037
26439
|
const text = () => t(p.target > 0.5 ? "prompt.close" : "prompt.open", { what: t(ped ? "what.pedestrianGate" : "what.garageGate") });
|
|
26038
|
-
|
|
26440
|
+
shared2.inter.items.push({ type: "gate", id: g.id, floor: -1, anchor: [g.u, 1, g.v + sd * 0.4], range: 2.8, angle: 0.9, pieces: [p], text, action: () => togglePiece(p), noWall: true });
|
|
26039
26441
|
});
|
|
26040
26442
|
}
|
|
26041
26443
|
function mailboxInteractive() {
|
|
26042
|
-
for (const m of
|
|
26444
|
+
for (const m of shared2.ctx.r.items) {
|
|
26043
26445
|
if (m.type !== "mailbox") continue;
|
|
26044
|
-
const g =
|
|
26446
|
+
const g = shared2.ctx.parts && shared2.ctx.parts["mailbox_" + m.id];
|
|
26045
26447
|
if (!g) continue;
|
|
26046
26448
|
const name = "ix:correio:" + m.id, def = definePiece(name, { kind: "part", pivot: [0, 0, 0], ry: 0, parent: "lot" });
|
|
26047
26449
|
def.inner = g;
|
|
26048
26450
|
const fx = Math.sin(m.ry || 0), fz = Math.cos(m.ry || 0), ay = (m.y || 1) + (m.h || 0.3) * 0.4;
|
|
26049
|
-
|
|
26451
|
+
shared2.inter.items.push({ type: "mailbox", id: m.id, floor: -1, anchor: [m.x + fx * 0.2, ay, m.z + fz * 0.2], range: 2.2, angle: 0.7, pieces: [def], text: () => t(def.target > 0.5 ? "prompt.close" : "prompt.open", { what: t("what.mailbox") }), action: () => togglePiece(def), noWall: true });
|
|
26050
26452
|
applyPiece(def);
|
|
26051
26453
|
}
|
|
26052
26454
|
}
|
|
26053
26455
|
function placeSwitches() {
|
|
26054
|
-
const R =
|
|
26456
|
+
const R = shared2.ctx.r, used = /* @__PURE__ */ new Set();
|
|
26055
26457
|
for (const c of R.rooms) {
|
|
26056
|
-
if (c.type === "void" || OPEN_AREA(c) || !
|
|
26458
|
+
if (c.type === "void" || OPEN_AREA(c) || !shared2.inter.litRooms.has(c.id) || used.has(c.id) || shared2.ctx.iv && shared2.ctx.iv.switchRooms.has(c.id)) continue;
|
|
26057
26459
|
const doors = R.doors.filter((p) => p.floor === c.floor && (p.a === c.id || p.b === c.id));
|
|
26058
26460
|
doors.sort((p, q) => ((q.exterior ? 1 : 0) - (p.exterior ? 1 : 0)) * (c.type === "living" ? 1 : -1));
|
|
26059
26461
|
for (const p of doors) if (putSwitch(c, p)) {
|
|
@@ -26063,7 +26465,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26063
26465
|
}
|
|
26064
26466
|
}
|
|
26065
26467
|
function putSwitch(c, p) {
|
|
26066
|
-
const R =
|
|
26468
|
+
const R = shared2.ctx.r, f = p.floor, alongU = p.axis === "u", L = p.pos, a = p.at - p.width / 2, b = p.at + p.width / 2;
|
|
26067
26469
|
const wref = R.walls.find((w) => w.floor === f && w.axis === p.axis && Math.abs((alongU ? w.v0 : w.u0) - L) < EPS3), th = wref ? wref.thickness || 0.15 : 0.15;
|
|
26068
26470
|
const inside2 = (sd2) => {
|
|
26069
26471
|
const cc = roomAt(f, alongU ? p.at : L + sd2 * 0.4, alongU ? L + sd2 * 0.4 : p.at);
|
|
@@ -26090,17 +26492,17 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26090
26492
|
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 });
|
|
26091
26493
|
piece2.t = piece2.target = lightOn(roomId) ? 1 : 0;
|
|
26092
26494
|
const an = alongU ? [u, yc, face + sd * 0.12] : [face + sd * 0.12, yc, u];
|
|
26093
|
-
|
|
26495
|
+
shared2.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) });
|
|
26094
26496
|
return true;
|
|
26095
26497
|
}
|
|
26096
26498
|
return false;
|
|
26097
26499
|
}
|
|
26098
26500
|
Object.assign(K, { gatesInteractive, mailboxInteractive, placeSwitches, putSwitch });
|
|
26099
26501
|
}
|
|
26100
|
-
function installInteractionDoors(K,
|
|
26502
|
+
function installInteractionDoors(K, shared2) {
|
|
26101
26503
|
const { t, colliderChanged, invalidateShadow, applyPiece, hudMessage } = K;
|
|
26102
26504
|
function linkDoorLeaves() {
|
|
26103
|
-
for (const fo of
|
|
26505
|
+
for (const fo of shared2.ctx.leaves) fo.handles = (fo.handleNames || []).map((n) => shared2.inter.defs.get(n)).filter(Boolean);
|
|
26104
26506
|
}
|
|
26105
26507
|
function handleApply(fo) {
|
|
26106
26508
|
for (const mc of fo.handles || []) {
|
|
@@ -26112,7 +26514,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26112
26514
|
if (fo.phase === "rattle") return;
|
|
26113
26515
|
if (fo.phase === "handle" || fo.phase === "swing") {
|
|
26114
26516
|
fo.open = !fo.open;
|
|
26115
|
-
|
|
26517
|
+
shared2.doorState.set(fo.id, fo.open);
|
|
26116
26518
|
fo.col.off = fo.open;
|
|
26117
26519
|
colliderChanged(fo.col);
|
|
26118
26520
|
fo.anim = true;
|
|
@@ -26122,25 +26524,25 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26122
26524
|
if (fo.blockedFlag || fo.locked) {
|
|
26123
26525
|
fo.phase = "rattle";
|
|
26124
26526
|
fo.jig = 0.7;
|
|
26125
|
-
|
|
26527
|
+
shared2.ctx.animateDoorsOn = true;
|
|
26126
26528
|
hudMessage(t(fo.blockedFlag ? "message.boarded" : "message.locked"));
|
|
26127
26529
|
return;
|
|
26128
26530
|
}
|
|
26129
26531
|
fo.open = !fo.open;
|
|
26130
|
-
|
|
26532
|
+
shared2.doorState.set(fo.id, fo.open);
|
|
26131
26533
|
fo.col.off = fo.open;
|
|
26132
26534
|
colliderChanged(fo.col);
|
|
26133
26535
|
fo.anim = true;
|
|
26134
|
-
|
|
26536
|
+
shared2.ctx.animateDoorsOn = true;
|
|
26135
26537
|
if (fo.handles && fo.handles.length) {
|
|
26136
26538
|
fo.phase = "handle";
|
|
26137
26539
|
fo.hT = fo.hT || 0;
|
|
26138
26540
|
} else fo.phase = "swing";
|
|
26139
26541
|
}
|
|
26140
26542
|
function animateDoors(dt) {
|
|
26141
|
-
if (!
|
|
26543
|
+
if (!shared2.ctx.animateDoorsOn) return;
|
|
26142
26544
|
let active = false;
|
|
26143
|
-
for (const fo of
|
|
26545
|
+
for (const fo of shared2.ctx.leaves) {
|
|
26144
26546
|
if (!fo.phase) continue;
|
|
26145
26547
|
active = true;
|
|
26146
26548
|
if (fo.phase === "handle") {
|
|
@@ -26170,13 +26572,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26170
26572
|
}
|
|
26171
26573
|
}
|
|
26172
26574
|
}
|
|
26173
|
-
|
|
26575
|
+
shared2.ctx.animateDoorsOn = active;
|
|
26174
26576
|
invalidateShadow();
|
|
26175
26577
|
}
|
|
26176
26578
|
function wallBlocks(ex, ez, ax, az, floor) {
|
|
26177
|
-
const n =
|
|
26579
|
+
const n = shared2.ctx.wallColliders != null ? shared2.ctx.wallColliders : 0;
|
|
26178
26580
|
for (let i = 0; i < n; i++) {
|
|
26179
|
-
const c =
|
|
26581
|
+
const c = shared2.ctx.colliders[i];
|
|
26180
26582
|
if (c.f !== floor && !(c.f === -1 && floor === 0)) continue;
|
|
26181
26583
|
let t0 = 0, t1 = 1;
|
|
26182
26584
|
const dx = ax - ex, dz = az - ez;
|
|
@@ -26208,7 +26610,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26208
26610
|
}
|
|
26209
26611
|
Object.assign(K, { linkDoorLeaves, handleApply, toggleDoor, animateDoors, wallBlocks, doorText, applyLeaf });
|
|
26210
26612
|
}
|
|
26211
|
-
function installInteractionTarget(K,
|
|
26613
|
+
function installInteractionTarget(K, shared2) {
|
|
26212
26614
|
const { doorText, toggleDoor, visibleChain, wallBlocks } = K;
|
|
26213
26615
|
const ivTarget = (...a) => K.ivTarget(...a);
|
|
26214
26616
|
function targetOf(o, opt) {
|
|
@@ -26219,7 +26621,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26219
26621
|
const tries = (score, text, action, target) => {
|
|
26220
26622
|
if (!best || score < best.score) best = { score, text, action, target };
|
|
26221
26623
|
};
|
|
26222
|
-
for (const fo of
|
|
26624
|
+
for (const fo of shared2.ctx.leaves) {
|
|
26223
26625
|
if (fo.floor !== floor) continue;
|
|
26224
26626
|
const d = Math.hypot(fo.cx - ex, fo.cz - ez);
|
|
26225
26627
|
if (d > 1.7) continue;
|
|
@@ -26227,11 +26629,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26227
26629
|
if (angle > 1.35 && d > 0.9) continue;
|
|
26228
26630
|
tries(angle * 1.6 + d * 0.5 + (angle < 0.25 ? 0 : 0.6), doorText(fo), () => toggleDoor(fo), fo);
|
|
26229
26631
|
}
|
|
26230
|
-
const vis =
|
|
26231
|
-
const kitA =
|
|
26632
|
+
const vis = shared2.inter.pieces.flatMap((p) => p.meshes).filter(visibleChain), hit = vis.length && opt.strike ? opt.strike(vis) : null;
|
|
26633
|
+
const kitA = shared2.ctx.iv ? ivTarget(shared2.ctx.iv, o, opt && opt.interactives) : null;
|
|
26232
26634
|
const nearKit = kitA && hit && Math.hypot(kitA.target.pos[0] - ex, kitA.target.pos[1] - ey, kitA.target.pos[2] - ez) < hit.distance + 0.1;
|
|
26233
26635
|
const pieceHit = hit && !nearKit && hit.object.userData.piece;
|
|
26234
|
-
for (const it of
|
|
26636
|
+
for (const it of shared2.inter.items) {
|
|
26235
26637
|
if (it.floor !== floor && !(it.floor === -1 && floor === 0)) continue;
|
|
26236
26638
|
const [ax, ay, az] = it.anchor, dx = ax - ex, dy = ay - ey, dz = az - ez, d = Math.hypot(dx, dy, dz), dh = Math.hypot(dx, dz);
|
|
26237
26639
|
if (dh > it.range + 0.4) continue;
|
|
@@ -26246,14 +26648,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26246
26648
|
}
|
|
26247
26649
|
Object.assign(K, { targetOf });
|
|
26248
26650
|
}
|
|
26249
|
-
function installInteractablesBridge(K,
|
|
26651
|
+
function installInteractablesBridge(K, shared2) {
|
|
26250
26652
|
const { t, THREE, invalidate, invalidateShadow, cfg, DOC, LIGHT_TYPES, _Y, _q, _v3, accFor, applyLight, cursor, hashString: hashString2, hudMessage, lightBase, pieceRecord, put, rgbOf, sh, wallBlocks } = K;
|
|
26251
26653
|
const enter = (...a) => K.enter(...a);
|
|
26252
26654
|
const roomLightMask = (...a) => K.roomLightMask(...a);
|
|
26253
26655
|
const IV_MATERIAL = { plain: "plain", metal: "metal", wood: "wood", glass: "glass", fabric: "fabric", plant: "plant", water: "water", emissive: "emissive", atlas_picture: "picture", atlas_floor: "floor" };
|
|
26254
26656
|
const IV_WIRE = { conduit: 13618628, cable: 2762532, drop: 1381653, cord: 1776413, earth: 3111482, hose: 11556124 };
|
|
26255
26657
|
const IV_DOOR = /^(door|drawer)/;
|
|
26256
|
-
const ivGroup = (e) => e.floor < 0 ? "lot" : "f" + Math.min(e.floor,
|
|
26658
|
+
const ivGroup = (e) => e.floor < 0 ? "lot" : "f" + Math.min(e.floor, shared2.ctx.r.floors.length - 1);
|
|
26257
26659
|
function ivAccumulate(mat, g, ox, oy, oz, ry, color2) {
|
|
26258
26660
|
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;
|
|
26259
26661
|
const A = accFor(mat);
|
|
@@ -26297,7 +26699,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26297
26699
|
A.ni += ni;
|
|
26298
26700
|
}
|
|
26299
26701
|
function ivBuild(h, water) {
|
|
26300
|
-
const ik = K.IVK, r =
|
|
26702
|
+
const ik = K.IVK, r = shared2.ctx.r, A = ik.A, world0 = null;
|
|
26301
26703
|
void world0;
|
|
26302
26704
|
const plane2 = A.plan(r, { seed: r.seed });
|
|
26303
26705
|
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 };
|
|
@@ -26318,7 +26720,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26318
26720
|
const wants = (roomId) => lightBase(roomId);
|
|
26319
26721
|
const entById = new Map(plane2.items.map((e) => [e.id, e]));
|
|
26320
26722
|
const entByItem = new Map(plane2.items.map((e) => [e.item, e]));
|
|
26321
|
-
IV.mats = { plain:
|
|
26723
|
+
IV.mats = { plain: shared2.mats.plain, metal: shared2.mats.metal, wood: shared2.mats.wood, glass: shared2.mats.glass, fabric: shared2.mats.fabric, plant: shared2.mats.plant, water: shared2.mats.water, emissive: shared2.mats.emissive, atlas_picture: shared2.mats.picture, atlas_floor: shared2.mats.floor };
|
|
26322
26724
|
const ev = (e) => ivEvent(h, e);
|
|
26323
26725
|
const world = IV.world = A.createWorld(r, { water, seed: r.seed, onEvent: ev });
|
|
26324
26726
|
const add0 = world.add;
|
|
@@ -26326,7 +26728,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26326
26728
|
const e = entById.get(id);
|
|
26327
26729
|
if (e && e.type === "lamp") {
|
|
26328
26730
|
const roomId = IV.lampRoom.get(id);
|
|
26329
|
-
spec.devices[0].on = roomId ? wants(roomId) : !!
|
|
26731
|
+
spec.devices[0].on = roomId ? wants(roomId) : !!shared2.ctx.night;
|
|
26330
26732
|
spec.parts = (spec.parts || []).concat([{ id: "_x", pivot: [0, 0, 0], motion: { kind: "slide", axis: [0, 1, 0], distance: 1e-3 }, label: "" }]);
|
|
26331
26733
|
spec.interactions = [{ id: "device.lamp", pos: [0, 0, 0], action: { do: "toggle_device", device: "lamp" }, label: "", requires: { object: id, part: "_x" } }];
|
|
26332
26734
|
} else if (e && e.type === "wall_switch") {
|
|
@@ -26352,7 +26754,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26352
26754
|
}
|
|
26353
26755
|
if (e.type === "lamp" && o.devices && o.devices.lamp) {
|
|
26354
26756
|
const roomId = IV.lampRoom.get(id);
|
|
26355
|
-
o.devices.lamp.on = roomId ? wants(roomId) : !!
|
|
26757
|
+
o.devices.lamp.on = roomId ? wants(roomId) : !!shared2.ctx.night;
|
|
26356
26758
|
} else if (e.type === "wall_switch" && o.parts && o.parts.rocker !== void 0) {
|
|
26357
26759
|
const l = (e.connections.controls || [])[0], roomId = l && IV.lampRoom.get(l);
|
|
26358
26760
|
if (roomId) o.parts.rocker = wants(roomId) ? 1 : 0;
|
|
@@ -26444,7 +26846,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26444
26846
|
const ik = IV.k, w = IV.world, wl = (o, p) => ik.GI.localToWorld(o.transform, p), g0 = cursor.group;
|
|
26445
26847
|
const tube2 = (pts, radius, color2, ox, oy, oz, ry) => {
|
|
26446
26848
|
try {
|
|
26447
|
-
const m = ik.gfx.createCord(pts, radius,
|
|
26849
|
+
const m = ik.gfx.createCord(pts, radius, shared2.mats.plain);
|
|
26448
26850
|
ivAccumulate("plain", m.geometry, ox, oy, oz, ry, color2);
|
|
26449
26851
|
m.geometry.dispose();
|
|
26450
26852
|
} catch (e) {
|
|
@@ -26487,7 +26889,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26487
26889
|
for (const E of IV.roots) {
|
|
26488
26890
|
(gs[E.group] || (gs[E.group] = new THREE.Group())).add(E.root);
|
|
26489
26891
|
}
|
|
26490
|
-
for (const [roomId] of IV.roomStates) if (!
|
|
26892
|
+
for (const [roomId] of IV.roomStates) if (!shared2.inter.litRooms.has(roomId)) IV.roomStates.delete(roomId);
|
|
26491
26893
|
for (const E of IV.entries.values()) if (E.parts && Object.keys(E.parts).length) IV.k.gfx.syncObject(IV.world, E.id, E.parts, { time: 0 });
|
|
26492
26894
|
for (const E of IV.entries.values()) if (E.screen) ivScreen(IV, E);
|
|
26493
26895
|
}
|
|
@@ -26518,7 +26920,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26518
26920
|
break;
|
|
26519
26921
|
case "device": {
|
|
26520
26922
|
const roomId = IV.lampRoom.get(e.object);
|
|
26521
|
-
if (roomId)
|
|
26923
|
+
if (roomId) shared2.partState.set("light:" + roomId, !!e.on);
|
|
26522
26924
|
invalidate();
|
|
26523
26925
|
break;
|
|
26524
26926
|
}
|
|
@@ -26671,7 +27073,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26671
27073
|
gm.setIndex(new THREE.BufferAttribute(A.i.slice(0, A.ni), 1));
|
|
26672
27074
|
gm.computeBoundingSphere();
|
|
26673
27075
|
if (!IV.items) {
|
|
26674
|
-
IV.items = new THREE.Mesh(gm,
|
|
27076
|
+
IV.items = new THREE.Mesh(gm, shared2.mats.plain);
|
|
26675
27077
|
IV.items.name = "iv-items";
|
|
26676
27078
|
IV.items.castShadow = false;
|
|
26677
27079
|
IV.items.receiveShadow = true;
|
|
@@ -26812,17 +27214,17 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26812
27214
|
}
|
|
26813
27215
|
Object.assign(K, { IV_MATERIAL, IV_WIRE, IV_DOOR, ivGroup, ivAccumulate, ivBuild, ivRoomEffective, ivDraw, ivCords, ivAssemble, ivScreen, ivEvent, ivSeat, ivUpdate, IV_SHAPE, ivItems, ivTarget, ivRoomLight, ivParts, ivDispose, ivPublish });
|
|
26814
27216
|
}
|
|
26815
|
-
function installAnimationClotheslines(K,
|
|
27217
|
+
function installAnimationClotheslines(K, shared2) {
|
|
26816
27218
|
const { invalidate, CLOTHES_UNIFORMS } = K;
|
|
26817
27219
|
const WIND = { t0: performance.now(), last: 0, base: 0.55 };
|
|
26818
27220
|
function animateClotheslines(now) {
|
|
26819
|
-
if (!
|
|
27221
|
+
if (!shared2.ctx.clotheslines || !shared2.ctx.clotheslines.length) return;
|
|
26820
27222
|
if (now - WIND.last < 33) return;
|
|
26821
27223
|
WIND.last = now;
|
|
26822
27224
|
const t = (now - WIND.t0) / 1e3;
|
|
26823
27225
|
CLOTHES_UNIFORMS.uTime.value = t;
|
|
26824
27226
|
CLOTHES_UNIFORMS.uVento.value = WIND.base + 0.45 * Math.sin(t * 0.23) * Math.sin(t * 0.11 + 1.3) + 0.25 * Math.max(0, Math.sin(t * 0.57));
|
|
26825
|
-
const g =
|
|
27227
|
+
const g = shared2.ctx.parts && shared2.ctx.parts["laundry_" + shared2.ctx.clotheslines[0]];
|
|
26826
27228
|
if (g) {
|
|
26827
27229
|
let vis = true;
|
|
26828
27230
|
for (let n = g; n; n = n.parent) if (!n.visible) {
|
|
@@ -26835,30 +27237,30 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26835
27237
|
}
|
|
26836
27238
|
Object.assign(K, { WIND, animateClotheslines });
|
|
26837
27239
|
}
|
|
26838
|
-
function installBuildInstance(K,
|
|
27240
|
+
function installBuildInstance(K, shared2) {
|
|
26839
27241
|
const { PROPS, THREE, DOC, cfg, HP, createInteractiveMaterials, createMaterials, typeTable } = K;
|
|
26840
27242
|
const props = PROPS.create(THREE, { document: DOC, emit: () => {
|
|
26841
27243
|
} });
|
|
26842
27244
|
const TYPES = typeTable(props);
|
|
26843
|
-
|
|
26844
|
-
createInteractiveMaterials(
|
|
27245
|
+
shared2.mats = createMaterials(props);
|
|
27246
|
+
createInteractiveMaterials(shared2.mats);
|
|
26845
27247
|
if (cfg.materials) for (const k of Object.keys(cfg.materials)) {
|
|
26846
27248
|
const v = cfg.materials[k];
|
|
26847
|
-
|
|
27249
|
+
shared2.mats[k] = typeof v === "function" ? v(shared2.mats[k], k) || shared2.mats[k] : v;
|
|
26848
27250
|
}
|
|
26849
27251
|
const newState = () => ({ doors: /* @__PURE__ */ new Map(), inter: /* @__PURE__ */ new Map(), water: null, iv: null });
|
|
26850
27252
|
function enter(h) {
|
|
26851
|
-
|
|
26852
|
-
|
|
26853
|
-
|
|
26854
|
-
|
|
26855
|
-
|
|
26856
|
-
|
|
27253
|
+
shared2.ctx = h.ctx;
|
|
27254
|
+
shared2.inter = h.inter;
|
|
27255
|
+
shared2.doorState = h.state.doors;
|
|
27256
|
+
shared2.partState = h.state.inter;
|
|
27257
|
+
shared2.mirrors = h.mirrors;
|
|
27258
|
+
shared2.quality = h.quality;
|
|
26857
27259
|
}
|
|
26858
27260
|
const tagDamage = (type) => ({ type, hp: HP[type], hpMax: HP[type] });
|
|
26859
27261
|
Object.assign(K, { props, TYPES, newState, enter, tagDamage });
|
|
26860
27262
|
}
|
|
26861
|
-
function installInteractablesKit(K,
|
|
27263
|
+
function installInteractablesKit(K, shared2) {
|
|
26862
27264
|
const { t, THREE, DOC, cfg, Reflector } = K;
|
|
26863
27265
|
const roomLightMask = (...a) => K.roomLightMask(...a);
|
|
26864
27266
|
const IVK = (() => {
|
|
@@ -26876,15 +27278,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26876
27278
|
const l = cfg.vegetation || null, G = l && (l.GameVegetation || (l.buildLot ? l : null)), S = l && (l.GameVegetationSpecies || (l.toSpec ? l : null));
|
|
26877
27279
|
return G && S && G.buildLot && S.toSpec ? { G, S } : null;
|
|
26878
27280
|
})();
|
|
26879
|
-
|
|
26880
|
-
const vegMaterials = () =>
|
|
27281
|
+
shared2.vegMaterials = null;
|
|
27282
|
+
const vegMaterials = () => shared2.vegMaterials || (shared2.vegMaterials = (() => {
|
|
26881
27283
|
const m = VEG.G.createVegetationMaterials(THREE);
|
|
26882
27284
|
for (const k of ["wood", "foliage", "flowers", "fruit", "spines"]) roomLightMask(m[k]);
|
|
26883
27285
|
return m;
|
|
26884
27286
|
})());
|
|
26885
27287
|
Object.assign(K, { IVK, VEG, vegMaterials });
|
|
26886
27288
|
}
|
|
26887
|
-
function installLightsRoomLight(K,
|
|
27289
|
+
function installLightsRoomLight(K, shared2) {
|
|
26888
27290
|
const { THREE, rectsOf: rectsOf2 } = K;
|
|
26889
27291
|
const MAX_LIGHTS = 12, EMPTY = [1e9, 1e9, -1e9, -1e9];
|
|
26890
27292
|
const LZU = { uRB0: { value: new Float32Array(MAX_LIGHTS * 4) }, uRB1: { value: new Float32Array(MAX_LIGHTS * 4) }, uRB2: { value: new Float32Array(MAX_LIGHTS * 4) }, uRBY: { value: new Float32Array(MAX_LIGHTS * 2) }, uREx: { value: new Float32Array(MAX_LIGHTS * 4) }, uIndK: { value: 0.06 } };
|
|
@@ -26923,7 +27325,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
26923
27325
|
function lighting(o) {
|
|
26924
27326
|
o = o || {};
|
|
26925
27327
|
const scene = o.scene, N = Math.max(1, Math.min(MAX_LIGHTS, o.n || 6)), NS = Math.max(0, Math.min(N, o.shadows != null ? o.shadows : 2)), size = o.shadowSize || 512, MAX_EXTERNAL = o.external != null ? o.external : 2;
|
|
26926
|
-
for (const k of Object.keys(
|
|
27328
|
+
for (const k of Object.keys(shared2.mats)) roomLightMask(shared2.mats[k]);
|
|
26927
27329
|
const PL = [], sig = new Array(N).fill(""), seg2 = { n: 0 };
|
|
26928
27330
|
for (let i = 0; i < N; i++) {
|
|
26929
27331
|
const l = new THREE.PointLight(16763008, 0, 8, 1.6);
|
|
@@ -27116,9 +27518,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27116
27518
|
}
|
|
27117
27519
|
return view;
|
|
27118
27520
|
}
|
|
27119
|
-
function installDestructionPieces(K,
|
|
27521
|
+
function installDestructionPieces(K, shared2) {
|
|
27120
27522
|
const { THREE, floorAtY, pieceRecord } = K;
|
|
27121
|
-
|
|
27523
|
+
shared2.destructionSeq = 0;
|
|
27122
27524
|
const FRAGMENT_COLOR = { brick: 11031866, concrete: 10132118, plaster: 14210248, ceramic: 11821630, glass: 11456472, tempered_glass: 11456472, wood_soft: 11569752, wood_hard: 8016948, plywood: 12098154, mdf: 12098154, steel: 9080466, aluminium: 12106944, plastic: 3107496, copper: 12088115, stone: 9079428, fabric: 13616296 };
|
|
27123
27525
|
const FRAGMENT_GEO = new THREE.BoxGeometry(1, 1, 1), FRAGMENT_MAT = {};
|
|
27124
27526
|
const fragmentMaterial = (m) => FRAGMENT_MAT[m] || (FRAGMENT_MAT[m] = new THREE.MeshLambertMaterial({ color: FRAGMENT_COLOR[m] != null ? FRAGMENT_COLOR[m] : 9079428 }));
|
|
@@ -27127,7 +27529,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27127
27529
|
objs = objs.filter(Boolean);
|
|
27128
27530
|
if (!objs.length) return;
|
|
27129
27531
|
const pc = pieceRecord(id, mat, role, extra);
|
|
27130
|
-
|
|
27532
|
+
shared2.ctx.pieceObjects.set(id, objs);
|
|
27131
27533
|
for (const o of objs) o.traverse((m) => {
|
|
27132
27534
|
if (!m.isMesh) return;
|
|
27133
27535
|
const u = m.userData;
|
|
@@ -27138,22 +27540,22 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27138
27540
|
if (pc.explodes) u.destructionExplodes = pc.explodes;
|
|
27139
27541
|
});
|
|
27140
27542
|
};
|
|
27141
|
-
for (const fo of
|
|
27543
|
+
for (const fo of shared2.ctx.leaves) {
|
|
27142
27544
|
const pr = r.doors.find((p) => p.id === fo.id);
|
|
27143
27545
|
tagObject("door:" + fo.id, fo.gs, fo.type === "steel" ? "steel" : pr && pr.exterior ? "wood_hard" : "mdf", null, { floor: fo.floor, mass: fo.type === "steel" ? 60 : 18, tags: ["door"] });
|
|
27144
27546
|
}
|
|
27145
27547
|
const cap = r.utilities.plumbing ? +r.utilities.plumbing.capacityL || 0 : 0;
|
|
27146
|
-
for (const [id, g] of Object.entries(
|
|
27548
|
+
for (const [id, g] of Object.entries(shared2.ctx.parts || {})) {
|
|
27147
27549
|
const tp = g.userData.part;
|
|
27148
27550
|
if (tp === "water_tank") {
|
|
27149
|
-
const e =
|
|
27551
|
+
const e = shared2.ctx.structureIndex.water_tank, L = cap || (g.userData.volume ? Math.round(g.userData.volume * 1e3) : 0);
|
|
27150
27552
|
tagObject("water_tank", [g], "plastic", e ? e.role : null, { floor: e ? e.floor : 0, contains: L ? { fluid: "water", liters: L } : void 0, mass: e ? e.mass : 25, thickness: 4e-3, fill: 0.05, tags: ["tank"] });
|
|
27151
27553
|
} else if (tp === "gas_cylinder") tagObject(id, [g], "steel", null, { mass: 11, form: "cylinder", thickness: 3e-3, fill: 0.03, contains: { fluid: "gas", liters: 13, pressurized: true }, explodes: { energy: 12e4, radius: 5, atC: 300 }, tags: ["gas_bottle"] });
|
|
27152
27554
|
else if (tp === "wall_pipe") tagObject(id, [g], "plastic", null, { mass: 3, tags: ["pipe"] });
|
|
27153
27555
|
else if (tp === "shower_door") tagObject(id, [g], "tempered_glass", null, { mass: 25 });
|
|
27154
27556
|
else if (tp === "gate_leaf" || tp === "mailbox_door") tagObject(id, [g], "steel", null, { mass: 30 });
|
|
27155
27557
|
}
|
|
27156
|
-
for (const def of
|
|
27558
|
+
for (const def of shared2.inter.defs.values()) {
|
|
27157
27559
|
if (!def.outer) continue;
|
|
27158
27560
|
if (/^gate/.test(def.kind)) tagObject(def.name, [def.outer], "steel", null, { mass: 80, tags: ["gate"] });
|
|
27159
27561
|
else if (def.kind === "swing" || def.kind === "drawer") tagObject(def.name, [def.outer], "mdf", null, { mass: 6 });
|
|
@@ -27172,13 +27574,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27172
27574
|
for (const f of o.userData.ranges) add(f.id, { mesh: o, v0: f.v0, v1: f.v1, i0: f.i0, i1: f.i1, whole: f.v0 === 0 && f.v1 === nv });
|
|
27173
27575
|
}
|
|
27174
27576
|
});
|
|
27175
|
-
for (const [id, objs] of
|
|
27577
|
+
for (const [id, objs] of shared2.ctx.pieceObjects) for (const o of objs) add(id, { obj: o });
|
|
27176
27578
|
const box32 = (id) => {
|
|
27177
27579
|
const b = new THREE.Box3(), v = new THREE.Vector3();
|
|
27178
27580
|
for (const it of meshes.get(id) || []) {
|
|
27179
27581
|
if (it.obj) {
|
|
27180
27582
|
const bb = new THREE.Box3().setFromObject(it.obj);
|
|
27181
|
-
if (!bb.isEmpty()) for (const x of [bb.min.x, bb.max.x]) for (const y of [bb.min.y, bb.max.y]) for (const z of [bb.min.z, bb.max.z]) b.expandByPoint(v.set(x, y, z).applyMatrix4(
|
|
27583
|
+
if (!bb.isEmpty()) for (const x of [bb.min.x, bb.max.x]) for (const y of [bb.min.y, bb.max.y]) for (const z of [bb.min.z, bb.max.z]) b.expandByPoint(v.set(x, y, z).applyMatrix4(shared2.ctx.unitInverse));
|
|
27182
27584
|
} else {
|
|
27183
27585
|
const P = it.mesh.geometry.attributes.position.array;
|
|
27184
27586
|
for (let k = it.v0; k < it.v1; k++) b.expandByPoint(v.set(P[k * 3], P[k * 3 + 1], P[k * 3 + 2]));
|
|
@@ -27188,15 +27590,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27188
27590
|
};
|
|
27189
27591
|
const parts = [], byId = /* @__PURE__ */ new Map(), supports = E0.supports.map((a) => Object.assign({}, a));
|
|
27190
27592
|
for (const e of E0.parts) {
|
|
27191
|
-
const p = Object.assign({}, e, { meshes: (meshes.get(e.id) || []).length, extra: false }), pc =
|
|
27593
|
+
const p = Object.assign({}, e, { meshes: (meshes.get(e.id) || []).length, extra: false }), pc = shared2.ctx.pieces.get(e.id);
|
|
27192
27594
|
if (pc) {
|
|
27193
27595
|
for (const k of ["contains", "explodes", "tags", "form", "thickness", "fill"]) if (pc[k] != null && p[k] == null) p[k] = pc[k];
|
|
27194
27596
|
}
|
|
27195
27597
|
parts.push(p);
|
|
27196
27598
|
byId.set(p.id, p);
|
|
27197
27599
|
}
|
|
27198
|
-
const base = parts.length, view =
|
|
27199
|
-
for (const [id, pc] of
|
|
27600
|
+
const base = parts.length, view = shared2.ctx.panelView || panelViewOf(null, false), panelIds = new Set(view.panels.map((e) => e.id));
|
|
27601
|
+
for (const [id, pc] of shared2.ctx.pieces) {
|
|
27200
27602
|
if (byId.has(id) || panelIds.has(id) || !meshes.has(id)) continue;
|
|
27201
27603
|
const b = box32(id);
|
|
27202
27604
|
if (!b) continue;
|
|
@@ -27230,7 +27632,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27230
27632
|
parts.splice(0, parts.length, ...parts.filter((p) => !gone.has(p.id)));
|
|
27231
27633
|
for (const id of gone) byId.delete(id);
|
|
27232
27634
|
for (const e of view.panels) {
|
|
27233
|
-
const p = Object.assign({}, e, { meshes: (meshes.get(e.id) || []).length, extra: false }), pc =
|
|
27635
|
+
const p = Object.assign({}, e, { meshes: (meshes.get(e.id) || []).length, extra: false }), pc = shared2.ctx.pieces.get(e.id);
|
|
27234
27636
|
if (pc) {
|
|
27235
27637
|
for (const k of ["contains", "explodes", "tags", "form", "thickness", "fill"]) if (pc[k] != null && p[k] == null) p[k] = pc[k];
|
|
27236
27638
|
}
|
|
@@ -27302,6 +27704,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27302
27704
|
function collapseRange(mesh2, v0, v1) {
|
|
27303
27705
|
const pos = mesh2.geometry.attributes.position;
|
|
27304
27706
|
const a = pos.array;
|
|
27707
|
+
const u = mesh2.userData;
|
|
27708
|
+
if (!u._p0) u._p0 = a.slice();
|
|
27709
|
+
const list2 = u.collapsedRanges ?? (u.collapsedRanges = []);
|
|
27710
|
+
if (!list2.some((r) => r[0] === v0 && r[1] === v1)) list2.push([v0, v1]);
|
|
27305
27711
|
const saved = a.slice(v0 * 3, v1 * 3);
|
|
27306
27712
|
const x = a[v0 * 3], y = a[v0 * 3 + 1], z = a[v0 * 3 + 2];
|
|
27307
27713
|
for (let k = v0; k < v1; k++) {
|
|
@@ -27316,6 +27722,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27316
27722
|
const pos = mesh2.geometry.attributes.position;
|
|
27317
27723
|
pos.array.set(saved, v0 * 3);
|
|
27318
27724
|
pos.needsUpdate = true;
|
|
27725
|
+
const list2 = mesh2.userData.collapsedRanges;
|
|
27726
|
+
if (list2) mesh2.userData.collapsedRanges = list2.filter((r) => r[0] !== v0);
|
|
27319
27727
|
}
|
|
27320
27728
|
function noise2(x, y, cell) {
|
|
27321
27729
|
const h = (i2, j2) => {
|
|
@@ -27330,13 +27738,22 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27330
27738
|
var SPALL_MIN = 0.025;
|
|
27331
27739
|
var SPALL_RAGGED = 0.045;
|
|
27332
27740
|
var COVER2 = 0.015;
|
|
27741
|
+
var MAX_FLAKES = 64;
|
|
27742
|
+
function clipToBox(unit, box4) {
|
|
27743
|
+
const lo = [Math.max(unit.x - unit.sx / 2, box4[0]), Math.max(unit.y - unit.sy / 2, box4[1]), Math.max(unit.z - unit.sz / 2, box4[2])];
|
|
27744
|
+
const hi = [Math.min(unit.x + unit.sx / 2, box4[3]), Math.min(unit.y + unit.sy / 2, box4[4]), Math.min(unit.z + unit.sz / 2, box4[5])];
|
|
27745
|
+
if (hi[0] - lo[0] <= 1e-4 || hi[1] - lo[1] <= 1e-4 || hi[2] - lo[2] <= 1e-4) return null;
|
|
27746
|
+
return { x: (lo[0] + hi[0]) / 2, y: (lo[1] + hi[1]) / 2, z: (lo[2] + hi[2]) / 2, sx: hi[0] - lo[0], sy: hi[1] - lo[1], sz: hi[2] - lo[2], colour: unit.colour };
|
|
27747
|
+
}
|
|
27333
27748
|
function installDestructionBreach(K, _shared) {
|
|
27334
27749
|
const { THREE, fragmentMaterial, invalidate, invalidateShadow } = K;
|
|
27335
27750
|
function createBreachView(opts) {
|
|
27336
27751
|
const { house, structure } = opts;
|
|
27337
27752
|
const views = /* @__PURE__ */ new Map();
|
|
27753
|
+
const dirty = /* @__PURE__ */ new Set();
|
|
27754
|
+
const paintBudgetMs = opts.paintBudgetMs ?? Infinity;
|
|
27755
|
+
const dropped = [];
|
|
27338
27756
|
let lod = 0;
|
|
27339
|
-
const unitMaterial = new THREE.MeshLambertMaterial({ color: 16777215 });
|
|
27340
27757
|
const unitGeometry = new THREE.BoxGeometry(1, 1, 1);
|
|
27341
27758
|
const tmp = { m: new THREE.Matrix4(), q: new THREE.Quaternion(), p: new THREE.Vector3(), s: new THREE.Vector3(), c: new THREE.Color() };
|
|
27342
27759
|
const local = (p) => {
|
|
@@ -27405,6 +27822,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27405
27822
|
const mesh2 = new THREE.Mesh(g, material);
|
|
27406
27823
|
mesh2.name = "breach-shell";
|
|
27407
27824
|
mesh2.userData.breachMask = mask;
|
|
27825
|
+
mesh2.userData.cutAt = (p) => {
|
|
27826
|
+
const v = local([p.x, p.y, p.z]);
|
|
27827
|
+
const i = Math.floor(((mask.alongU ? v[0] : v[2]) - mask.start) / mask.len * mask.w), j = Math.floor((v[1] - mask.y0) / mask.height * mask.h);
|
|
27828
|
+
return i >= 0 && i < mask.w && j >= 0 && j < mask.h && mask.data[j * mask.w + i] > 127;
|
|
27829
|
+
};
|
|
27408
27830
|
mesh2.position.copy(it.mesh.position);
|
|
27409
27831
|
mesh2.quaternion.copy(it.mesh.quaternion);
|
|
27410
27832
|
mesh2.scale.copy(it.mesh.scale);
|
|
@@ -27420,6 +27842,29 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27420
27842
|
toHouse.value.copy(house.matrixWorld).invert().multiply(mesh2.matrixWorld);
|
|
27421
27843
|
return mesh2;
|
|
27422
27844
|
}
|
|
27845
|
+
function unitsMaterial(core) {
|
|
27846
|
+
const material = new THREE.MeshLambertMaterial({ color: 16777215, side: THREE.DoubleSide });
|
|
27847
|
+
material.onBeforeCompile = (sh) => {
|
|
27848
|
+
sh.uniforms.uCore = { value: core.texture };
|
|
27849
|
+
sh.uniforms.uCoreRect = { value: core.rect };
|
|
27850
|
+
sh.uniforms.uCoreAlongX = { value: core.alongU ? 1 : 0 };
|
|
27851
|
+
sh.vertexShader = sh.vertexShader.replace("void main() {", "varying vec3 vHousePos;\nvoid main() {").replace("#include <begin_vertex>", "#include <begin_vertex>\n#ifdef USE_INSTANCING\nvHousePos = (instanceMatrix * vec4(transformed, 1.0)).xyz;\n#else\nvHousePos = transformed;\n#endif");
|
|
27852
|
+
sh.fragmentShader = sh.fragmentShader.replace("void main() {", "uniform sampler2D uCore;\nuniform vec4 uCoreRect;\nuniform float uCoreAlongX;\nvarying vec3 vHousePos;\nvoid main() {\n vec2 cUv = vec2(((uCoreAlongX > 0.5 ? vHousePos.x : vHousePos.z) - uCoreRect.x) / uCoreRect.z, (vHousePos.y - uCoreRect.y) / uCoreRect.w);\n if (cUv.x >= 0.0 && cUv.x <= 1.0 && cUv.y >= 0.0 && cUv.y <= 1.0 && texture2D(uCore, cUv).r > 0.5) discard;").replace("#include <color_fragment>", "#include <color_fragment>\nif (!gl_FrontFacing) diffuseColor.rgb *= 0.55;");
|
|
27853
|
+
};
|
|
27854
|
+
material.customProgramCacheKey = () => "breachCore";
|
|
27855
|
+
material.userData.breachCore = core;
|
|
27856
|
+
return material;
|
|
27857
|
+
}
|
|
27858
|
+
function drawnBounds(items) {
|
|
27859
|
+
house.updateMatrixWorld(true);
|
|
27860
|
+
const box4 = new THREE.Box3(), toHouse = new THREE.Matrix4().copy(house.matrixWorld).invert();
|
|
27861
|
+
for (const it of items) {
|
|
27862
|
+
const a = it.mesh.userData._p0 || it.mesh.geometry.attributes.position.array;
|
|
27863
|
+
tmp.m.multiplyMatrices(toHouse, it.mesh.matrixWorld);
|
|
27864
|
+
for (let k = it.v0; k < it.v1; k++) box4.expandByPoint(tmp.p.set(a[k * 3], a[k * 3 + 1], a[k * 3 + 2]).applyMatrix4(tmp.m));
|
|
27865
|
+
}
|
|
27866
|
+
return [box4.min.x, box4.min.y, box4.min.z, box4.max.x, box4.max.y, box4.max.z];
|
|
27867
|
+
}
|
|
27423
27868
|
function maskOf(hostId, parts) {
|
|
27424
27869
|
const host = structure.byId.get(hostId);
|
|
27425
27870
|
const [u0, v0, u1, v1] = host.aabb;
|
|
@@ -27435,51 +27880,86 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27435
27880
|
return { data, texture, w, h, alongU, start: alongU ? u0 : v0, len, y0, height: y1 - y0, rect: new THREE.Vector4(alongU ? u0 : v0, y0, len, y1 - y0) };
|
|
27436
27881
|
}
|
|
27437
27882
|
const boxDistance = (s, y, a, b, c, d) => Math.hypot(Math.max(a - s, 0, s - b), Math.max(c - y, 0, y - d));
|
|
27883
|
+
const ellipseDistance = (s, y, cs, cy, rs, ry) => (Math.hypot((s - cs) / Math.max(rs, 1e-4), (y - cy) / Math.max(ry, 1e-4)) - 1) * Math.min(rs, ry);
|
|
27884
|
+
function covered(c, boxes) {
|
|
27885
|
+
const n = 8;
|
|
27886
|
+
let hit = 0;
|
|
27887
|
+
for (let j = 0; j < n; j++) {
|
|
27888
|
+
const y = c.y0 + (j + 0.5) / n * (c.y1 - c.y0);
|
|
27889
|
+
for (let i = 0; i < n; i++) {
|
|
27890
|
+
const s = c.a + (i + 0.5) / n * (c.b - c.a);
|
|
27891
|
+
if (boxes.some((k) => s >= k.s0 && s <= k.s1 && y >= k.y0 && y <= k.y1)) hit++;
|
|
27892
|
+
}
|
|
27893
|
+
}
|
|
27894
|
+
return hit / (n * n);
|
|
27895
|
+
}
|
|
27438
27896
|
function paint(view) {
|
|
27439
|
-
const { mask } = view;
|
|
27897
|
+
const { mask, core } = view;
|
|
27440
27898
|
const along = (p) => (mask.alongU ? p[0] : p[2]) - mask.start;
|
|
27441
27899
|
const holes = [];
|
|
27900
|
+
const pits = [];
|
|
27442
27901
|
const discs = [];
|
|
27902
|
+
const flakes = [];
|
|
27443
27903
|
const shown = [];
|
|
27444
27904
|
for (const id of view.parts) {
|
|
27445
|
-
const part = structure.byId.get(id), units2 = specOf(id).units, chips = view.chips.get(id), opening = view.openings.get(id);
|
|
27905
|
+
const part = structure.byId.get(id), units2 = specOf(id).units, chips = view.chips.get(id), opening = view.openings.get(id), spalls = view.spalls.get(id);
|
|
27446
27906
|
const all = cells(part, units2);
|
|
27447
27907
|
const thick = mask.alongU ? part.aabb[3] - part.aabb[1] : part.aabb[2] - part.aabb[0];
|
|
27448
27908
|
const mid = mask.alongU ? (part.aabb[1] + part.aabb[3]) / 2 : (part.aabb[0] + part.aabb[2]) / 2;
|
|
27449
27909
|
if (opening) discs.push({ s: along(opening.center), y: opening.center[1], r: opening.radius });
|
|
27450
|
-
|
|
27910
|
+
for (const k of spalls) flakes.push({ s: along(k.center), y: k.center[1], r: k.radius });
|
|
27911
|
+
const boxes = chips.map((k) => ({ s0: along(k.center) - k.along, s1: along(k.center) + k.along, y0: k.center[1] - k.up, y1: k.center[1] + k.up }));
|
|
27912
|
+
const gone = (c) => covered(c, boxes.filter((k) => k.s1 > c.a && k.s0 < c.b && k.y1 > c.y0 && k.y0 < c.y1)) >= 0.9 || opening && Math.hypot((c.a + c.b) / 2 - along(opening.center), (c.y0 + c.y1) / 2 - opening.center[1]) < opening.radius;
|
|
27451
27913
|
const kept = [];
|
|
27452
27914
|
for (const c of all) (gone(c) ? holes : kept).push(c);
|
|
27453
27915
|
for (const c of kept) shown.push({ c, part, units: units2, thick, mid });
|
|
27916
|
+
for (const k of boxes) {
|
|
27917
|
+
if (holes.some((h) => k.s0 >= h.a - 1e-4 && k.s1 <= h.b + 1e-4 && k.y0 >= h.y0 - 1e-4 && k.y1 <= h.y1 + 1e-4)) continue;
|
|
27918
|
+
pits.push({ s: (k.s0 + k.s1) / 2, y: (k.y0 + k.y1) / 2, rs: (k.s1 - k.s0) / 2, ry: (k.y1 - k.y0) / 2 });
|
|
27919
|
+
}
|
|
27454
27920
|
}
|
|
27455
27921
|
const reach = SPALL_MIN + SPALL_RAGGED;
|
|
27922
|
+
const ragged = (s, y) => 0.6 * noise2(s, y, 0.03) + 0.4 * noise2(s + 7.3, y - 3.1, 0.011);
|
|
27456
27923
|
mask.data.fill(0);
|
|
27457
|
-
|
|
27458
|
-
|
|
27459
|
-
const
|
|
27924
|
+
core.data.fill(0);
|
|
27925
|
+
const stamp = (m, s0, s1, y0, y1, inside2) => {
|
|
27926
|
+
const i0 = Math.max(0, Math.floor((s0 - reach) / m.len * m.w)), i1 = Math.min(m.w - 1, Math.ceil((s1 + reach) / m.len * m.w));
|
|
27927
|
+
const j0 = Math.max(0, Math.floor((y0 - reach - m.y0) / m.height * m.h)), j1 = Math.min(m.h - 1, Math.ceil((y1 + reach - m.y0) / m.height * m.h));
|
|
27460
27928
|
for (let j = j0; j <= j1; j++) {
|
|
27461
|
-
const y =
|
|
27929
|
+
const y = m.y0 + (j + 0.5) / m.h * m.height;
|
|
27462
27930
|
for (let i = i0; i <= i1; i++) {
|
|
27463
|
-
const s = (i + 0.5) /
|
|
27464
|
-
|
|
27465
|
-
if (inside2(s, y) <= edge) mask.data[j * mask.w + i] = 255;
|
|
27931
|
+
const s = (i + 0.5) / m.w * m.len;
|
|
27932
|
+
if (inside2(s, y)) m.data[j * m.w + i] = 255;
|
|
27466
27933
|
}
|
|
27467
27934
|
}
|
|
27468
27935
|
};
|
|
27469
|
-
|
|
27470
|
-
for (const
|
|
27936
|
+
const plaster = (d, s, y) => d <= SPALL_MIN + SPALL_RAGGED * ragged(s, y);
|
|
27937
|
+
for (const c of holes) stamp(mask, c.a, c.b, c.y0, c.y1, (s, y) => plaster(boxDistance(s, y, c.a, c.b, c.y0, c.y1), s, y));
|
|
27938
|
+
for (const d of discs) stamp(mask, d.s - d.r, d.s + d.r, d.y - d.r, d.y + d.r, (s, y) => plaster(Math.max(0, Math.hypot(s - d.s, y - d.y) - d.r), s, y));
|
|
27939
|
+
for (const f of flakes) {
|
|
27940
|
+
const rough = (s, y) => Math.hypot(s - f.s, y - f.y) - f.r * (0.65 + 0.7 * ragged(s * 2.3, y * 2.3));
|
|
27941
|
+
stamp(mask, f.s - 2 * f.r, f.s + 2 * f.r, f.y - 2 * f.r, f.y + 2 * f.r, (s, y) => rough(s, y) <= 0);
|
|
27942
|
+
}
|
|
27943
|
+
for (const p of pits) {
|
|
27944
|
+
stamp(mask, p.s - p.rs, p.s + p.rs, p.y - p.ry, p.y + p.ry, (s, y) => plaster(Math.max(0, ellipseDistance(s, y, p.s, p.y, p.rs, p.ry)), s, y));
|
|
27945
|
+
stamp(core, p.s - p.rs, p.s + p.rs, p.y - p.ry, p.y + p.ry, (s, y) => ellipseDistance(s, y, p.s, p.y, p.rs, p.ry) <= -0.35 * Math.min(p.rs, p.ry) * noise2(s * 1.7, y * 1.3, 0.012));
|
|
27946
|
+
}
|
|
27471
27947
|
mask.texture.needsUpdate = true;
|
|
27472
|
-
|
|
27948
|
+
core.texture.needsUpdate = true;
|
|
27949
|
+
const near = (c) => holes.some((h) => boxDistance((c.a + c.b) / 2, (c.y0 + c.y1) / 2, h.a - (c.b - c.a) / 2, h.b + (c.b - c.a) / 2, h.y0 - (c.y1 - c.y0) / 2, h.y1 + (c.y1 - c.y0) / 2) <= reach) || discs.some((d) => boxDistance(d.s, d.y, c.a, c.b, c.y0, c.y1) <= d.r + reach) || pits.some((p) => boxDistance(p.s, p.y, c.a, c.b, c.y0, c.y1) <= Math.max(p.rs, p.ry) + reach) || flakes.some((f) => boxDistance(f.s, f.y, c.a, c.b, c.y0, c.y1) <= 2 * f.r);
|
|
27473
27950
|
const list2 = [];
|
|
27474
27951
|
const tone = (hex3, k) => tmp.c.setHex(hex3).multiplyScalar(k).getHex();
|
|
27475
27952
|
for (const { c, part, units: units2, thick, mid } of shown) {
|
|
27476
27953
|
if (!near(c)) continue;
|
|
27477
27954
|
const centre = mask.start + (c.a + c.b) / 2, y = (c.y0 + c.y1) / 2, len = c.b - c.a, h = c.y1 - c.y0;
|
|
27478
|
-
const at = (s, dy, d, colour) =>
|
|
27955
|
+
const at = (s, dy, d, colour) => {
|
|
27956
|
+
const unit = clipToBox({ x: mask.alongU ? centre : mid, y, z: mask.alongU ? mid : centre, sx: mask.alongU ? s : d, sy: dy, sz: mask.alongU ? d : s, colour }, view.bounds);
|
|
27957
|
+
if (unit) list2.push(unit);
|
|
27958
|
+
};
|
|
27479
27959
|
const base = fragmentMaterial(part.material).color.getHex();
|
|
27480
27960
|
const n = noise2(centre * 3.1, y * 2.7, 0.07);
|
|
27481
27961
|
if (units2.mortar === "concrete") {
|
|
27482
|
-
at(len, h, thick - 2 * COVER2
|
|
27962
|
+
at(len, h, thick - 2 * COVER2, tone(base, 0.9 + 0.04 * n));
|
|
27483
27963
|
} else {
|
|
27484
27964
|
at(len, h, thick - 2 * COVER2 - 0.012, 10327948);
|
|
27485
27965
|
at(len - 0.012, h - 0.012, thick - 2 * COVER2, tone(base, 0.8 + 0.35 * n));
|
|
@@ -27489,7 +27969,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27489
27969
|
view.units.removeFromParent();
|
|
27490
27970
|
view.units.dispose();
|
|
27491
27971
|
}
|
|
27492
|
-
const units = new THREE.InstancedMesh(unitGeometry, unitMaterial, Math.max(1, list2.length));
|
|
27972
|
+
const units = new THREE.InstancedMesh(unitGeometry, view.unitMaterial, Math.max(1, list2.length));
|
|
27493
27973
|
units.name = "breach:" + view.host;
|
|
27494
27974
|
list2.forEach((u, i) => {
|
|
27495
27975
|
tmp.m.compose(tmp.p.set(u.x, u.y, u.z), tmp.q.identity(), tmp.s.set(u.sx, u.sy, u.sz));
|
|
@@ -27505,6 +27985,19 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27505
27985
|
house.add(units);
|
|
27506
27986
|
view.units = units;
|
|
27507
27987
|
view.gone = holes.length;
|
|
27988
|
+
view.pits = pits.length;
|
|
27989
|
+
view.flakes = flakes.length;
|
|
27990
|
+
}
|
|
27991
|
+
function chipBox(chip, alongU) {
|
|
27992
|
+
house.updateMatrixWorld(true);
|
|
27993
|
+
const q = tmp.q.set(chip.rotation[0], chip.rotation[1], chip.rotation[2], chip.rotation[3]).premultiply(house.getWorldQuaternion(new THREE.Quaternion()).invert());
|
|
27994
|
+
let a = 0, u = 0;
|
|
27995
|
+
for (let k = 0; k < 3; k++) {
|
|
27996
|
+
const axis = tmp.p.set(k === 0 ? 1 : 0, k === 1 ? 1 : 0, k === 2 ? 1 : 0).applyQuaternion(q);
|
|
27997
|
+
a += Math.abs(alongU ? axis.x : axis.z) * chip.size[k] / 2;
|
|
27998
|
+
u += Math.abs(axis.y) * chip.size[k] / 2;
|
|
27999
|
+
}
|
|
28000
|
+
return { center: local(chip.center), along: a, up: u };
|
|
27508
28001
|
}
|
|
27509
28002
|
function draw2(partId, change) {
|
|
27510
28003
|
if (lod !== 0) return false;
|
|
@@ -27516,23 +28009,50 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27516
28009
|
if (!items.length) return false;
|
|
27517
28010
|
const parts = [hostId, ...riders(hostId)].filter((id) => structure.byId.get(id) && specOf(id)?.units);
|
|
27518
28011
|
if (!parts.includes(partId)) return false;
|
|
27519
|
-
const mask = maskOf(hostId, parts);
|
|
27520
|
-
view = {
|
|
28012
|
+
const mask = maskOf(hostId, parts), core = maskOf(hostId, parts);
|
|
28013
|
+
view = {
|
|
28014
|
+
host: hostId,
|
|
28015
|
+
parts,
|
|
28016
|
+
items,
|
|
28017
|
+
mask,
|
|
28018
|
+
core,
|
|
28019
|
+
unitMaterial: unitsMaterial(core),
|
|
28020
|
+
shells: [],
|
|
28021
|
+
saved: null,
|
|
28022
|
+
units: null,
|
|
28023
|
+
gone: 0,
|
|
28024
|
+
pits: 0,
|
|
28025
|
+
bounds: drawnBounds(items),
|
|
28026
|
+
chips: new Map(parts.map((id) => [id, []])),
|
|
28027
|
+
spalls: new Map(parts.map((id) => [id, []])),
|
|
28028
|
+
openings: /* @__PURE__ */ new Map(),
|
|
28029
|
+
flakes: 0
|
|
28030
|
+
};
|
|
27521
28031
|
}
|
|
27522
28032
|
if (!view.chips.has(partId)) return false;
|
|
27523
28033
|
if (change.opening) {
|
|
27524
28034
|
if (view.openings.has(partId)) return false;
|
|
27525
28035
|
view.openings.set(partId, { center: local(change.opening.center), radius: change.opening.radius });
|
|
27526
28036
|
}
|
|
27527
|
-
if (change.chip) view.chips.get(partId).push(
|
|
28037
|
+
if (change.chip) view.chips.get(partId).push(chipBox(change.chip, view.mask.alongU));
|
|
28038
|
+
if (change.spall) {
|
|
28039
|
+
const list2 = view.spalls.get(partId);
|
|
28040
|
+
list2.push({ center: local(change.spall.center), radius: change.spall.radius });
|
|
28041
|
+
if (list2.length > MAX_FLAKES) list2.shift();
|
|
28042
|
+
}
|
|
27528
28043
|
if (!view.saved) {
|
|
27529
28044
|
view.shells = view.items.map((it) => shell(it, view.mask));
|
|
28045
|
+
for (const m of view.shells) m.userData.behind = () => view.units;
|
|
27530
28046
|
view.saved = view.items.map((it) => ({ it, v0: it.v0, data: collapseRange(it.mesh, it.v0, it.v1) }));
|
|
27531
28047
|
}
|
|
27532
|
-
paint(view);
|
|
27533
28048
|
views.set(hostId, view);
|
|
27534
|
-
|
|
27535
|
-
|
|
28049
|
+
if (opts.deferPaint && change.spall) dirty.add(view);
|
|
28050
|
+
else {
|
|
28051
|
+
dirty.delete(view);
|
|
28052
|
+
paint(view);
|
|
28053
|
+
invalidate();
|
|
28054
|
+
invalidateShadow();
|
|
28055
|
+
}
|
|
27536
28056
|
return true;
|
|
27537
28057
|
}
|
|
27538
28058
|
function plain2(view, shown) {
|
|
@@ -27541,24 +28061,70 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27541
28061
|
else s.data = collapseRange(s.it.mesh, s.v0, s.it.v1);
|
|
27542
28062
|
}
|
|
27543
28063
|
}
|
|
28064
|
+
function flush(budgetMs = paintBudgetMs) {
|
|
28065
|
+
if (dirty.size === 0) return 0;
|
|
28066
|
+
const deadline = performance.now() + budgetMs;
|
|
28067
|
+
for (const view of dirty) {
|
|
28068
|
+
dirty.delete(view);
|
|
28069
|
+
paint(view);
|
|
28070
|
+
if (performance.now() >= deadline) break;
|
|
28071
|
+
}
|
|
28072
|
+
invalidate();
|
|
28073
|
+
invalidateShadow();
|
|
28074
|
+
return dirty.size;
|
|
28075
|
+
}
|
|
27544
28076
|
function dispose(view) {
|
|
27545
|
-
|
|
27546
|
-
view.units
|
|
28077
|
+
dirty.delete(view);
|
|
28078
|
+
if (view.units) {
|
|
28079
|
+
view.units.removeFromParent();
|
|
28080
|
+
view.units.dispose();
|
|
28081
|
+
}
|
|
28082
|
+
view.unitMaterial.dispose();
|
|
27547
28083
|
for (const m of view.shells) {
|
|
27548
28084
|
m.removeFromParent();
|
|
27549
28085
|
m.geometry.dispose();
|
|
27550
28086
|
m.material.dispose();
|
|
27551
28087
|
}
|
|
27552
28088
|
view.mask.texture.dispose();
|
|
28089
|
+
view.core.texture.dispose();
|
|
27553
28090
|
}
|
|
27554
28091
|
return {
|
|
27555
28092
|
/** Handles a `stage` event of the house's object. Returns true when the wall was cut. */
|
|
27556
28093
|
stage(event) {
|
|
27557
28094
|
return event.stage === 2 && !!event.opening ? draw2(event.part, { opening: event.opening }) : false;
|
|
27558
28095
|
},
|
|
27559
|
-
/**
|
|
28096
|
+
/**
|
|
28097
|
+
* Handles a `spall` of a wall of units: the coat comes off in a ragged patch and the units show under it, drawn by the house (the destruction
|
|
28098
|
+
* renderer leaves its flat patch out on the meshes `claim` marked). Returns true when the wall was cut.
|
|
28099
|
+
*/
|
|
28100
|
+
spall(event) {
|
|
28101
|
+
const r = Math.sqrt(Math.max(0, event.area) / Math.PI);
|
|
28102
|
+
return r > 0 ? draw2(event.part, { spall: { center: event.point, radius: r } }) : false;
|
|
28103
|
+
},
|
|
28104
|
+
/**
|
|
28105
|
+
* Marks the meshes that draw a wall of units as drawing its spalls itself (`userData.drawnSpalls`, the part ids): the destruction renderer then
|
|
28106
|
+
* throws the bits and leaves its patch out. Call it once the spec is known.
|
|
28107
|
+
*/
|
|
28108
|
+
claim() {
|
|
28109
|
+
var _a;
|
|
28110
|
+
for (const q of opts.spec()?.parts ?? []) {
|
|
28111
|
+
if (!q.units) continue;
|
|
28112
|
+
const host = hostOf(q.id);
|
|
28113
|
+
if (!host) continue;
|
|
28114
|
+
for (const it of structure.meshesOf(host)) {
|
|
28115
|
+
if (!it.mesh) continue;
|
|
28116
|
+
const list2 = (_a = it.mesh.userData).drawnSpalls ?? (_a.drawnSpalls = []);
|
|
28117
|
+
if (!list2.includes(q.id)) list2.push(q.id);
|
|
28118
|
+
}
|
|
28119
|
+
}
|
|
28120
|
+
},
|
|
28121
|
+
/**
|
|
28122
|
+
* Handles a `chip` event: what came out (a unit, or a crater a shot broke through one) leaves a hole in the wall where it was; a `torn` chip (what a blow
|
|
28123
|
+
* tore off a face) leaves the marks the renderer drew. Returns true when the wall was cut.
|
|
28124
|
+
*/
|
|
27560
28125
|
chip(event) {
|
|
27561
|
-
|
|
28126
|
+
if (event.torn) return false;
|
|
28127
|
+
return draw2(event.part, { chip: { center: event.center, size: event.size ?? [0, 0, 0], rotation: event.rotation ?? [0, 0, 0, 1] } });
|
|
27562
28128
|
},
|
|
27563
28129
|
/** The part broke or fell: its damage goes (the plain range stays collapsed, the renderer hides the part). */
|
|
27564
28130
|
drop(partId) {
|
|
@@ -27566,9 +28132,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27566
28132
|
if (!v) return;
|
|
27567
28133
|
dispose(v);
|
|
27568
28134
|
views.delete(partId);
|
|
28135
|
+
if (v.saved) dropped.push(v);
|
|
27569
28136
|
},
|
|
27570
28137
|
/** LOD 0 draws the cut wall; LOD 1 and 2 give the wall its box back. */
|
|
27571
28138
|
setLod(level) {
|
|
28139
|
+
flush(Infinity);
|
|
27572
28140
|
const was = lod;
|
|
27573
28141
|
lod = level;
|
|
27574
28142
|
if (was === 0 === (level === 0)) return;
|
|
@@ -27587,22 +28155,28 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27587
28155
|
if (lod === 0) plain2(v, true);
|
|
27588
28156
|
}
|
|
27589
28157
|
views.clear();
|
|
28158
|
+
for (const v of dropped) plain2(v, true);
|
|
28159
|
+
dropped.length = 0;
|
|
27590
28160
|
},
|
|
28161
|
+
flush,
|
|
27591
28162
|
/** The wall has damage drawn. */
|
|
27592
28163
|
has(partId) {
|
|
27593
28164
|
return views.has(partId);
|
|
27594
28165
|
},
|
|
27595
|
-
/** Walls with damage drawn, units out of them, and units laid bare at the edge of the cuts. */
|
|
27596
|
-
statistics: () => ({
|
|
28166
|
+
/** Walls with damage drawn, units out of them, craters shots broke through units that stay, and units laid bare at the edge of the cuts. */
|
|
28167
|
+
statistics: () => (flush(Infinity), {
|
|
27597
28168
|
walls: views.size,
|
|
27598
28169
|
gone: [...views.values()].reduce((n, v) => n + v.gone, 0),
|
|
28170
|
+
craters: [...views.values()].reduce((n, v) => n + v.pits, 0),
|
|
28171
|
+
flakes: [...views.values()].reduce((n, v) => n + v.flakes, 0),
|
|
27599
28172
|
units: [...views.values()].reduce((n, v) => n + v.units.count, 0)
|
|
27600
28173
|
})
|
|
27601
28174
|
};
|
|
27602
28175
|
}
|
|
27603
28176
|
Object.assign(K, { createBreachView });
|
|
27604
28177
|
}
|
|
27605
|
-
|
|
28178
|
+
var FOLLOW_FLUSH_FALLBACK_MS = 100;
|
|
28179
|
+
function installDestructionWorld(K, shared2) {
|
|
27606
28180
|
const { THREE, cfg, invalidateShadow, invalidate, rngString, FRAGMENT_GEO, fragmentMaterial, createBreachView } = K;
|
|
27607
28181
|
function createHouseDestruction(root, house, structure, parts, colliders, water) {
|
|
27608
28182
|
const D = { world: cfg.destruction || null, id: null, active: false }, hiddenPieces = /* @__PURE__ */ new Set(), bodies = /* @__PURE__ */ new Map(), frags = [], facets = /* @__PURE__ */ new Map();
|
|
@@ -27610,7 +28184,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27610
28184
|
const R = cfg.destructionRenderer || null, listeners = /* @__PURE__ */ new Set();
|
|
27611
28185
|
D.renderer = R;
|
|
27612
28186
|
D.spec = null;
|
|
27613
|
-
const breach = createBreachView({ house, structure, spec: () => D.spec });
|
|
28187
|
+
const breach = createBreachView({ house, structure, spec: () => D.spec, deferPaint: true, ...cfg.breachPaintBudgetMs !== void 0 ? { paintBudgetMs: cfg.breachPaintBudgetMs } : {} });
|
|
27614
28188
|
D.breach = breach;
|
|
27615
28189
|
D.onEvent = (fn) => {
|
|
27616
28190
|
listeners.add(fn);
|
|
@@ -27795,6 +28369,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27795
28369
|
case "chip":
|
|
27796
28370
|
breach.chip(e);
|
|
27797
28371
|
break;
|
|
28372
|
+
case "spall":
|
|
28373
|
+
breach.spall(e);
|
|
28374
|
+
break;
|
|
27798
28375
|
case "collapse":
|
|
27799
28376
|
for (const id of e.parts) {
|
|
27800
28377
|
breach.drop(id);
|
|
@@ -27835,8 +28412,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27835
28412
|
house.matrixWorld.decompose(p, q, sc);
|
|
27836
28413
|
D.specOptions = specOptions || null;
|
|
27837
28414
|
D.spec = structure.spec(specOptions);
|
|
27838
|
-
D.id = D.world.add(D.spec, { id: "house3d:" + ++
|
|
27839
|
-
|
|
28415
|
+
D.id = D.world.add(D.spec, { id: "house3d:" + ++shared2.destructionSeq, position: [p.x, p.y, p.z], rotation: [q.x, q.y, q.z, q.w] });
|
|
28416
|
+
breach.claim();
|
|
28417
|
+
if (R) R.bind(D.id, house, { parts: rangesOf(), onFrame: () => breach.flush() });
|
|
27840
28418
|
off = D.world.on("*", handleEvent);
|
|
27841
28419
|
D.active = true;
|
|
27842
28420
|
return D;
|
|
@@ -27851,6 +28429,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27851
28429
|
};
|
|
27852
28430
|
D.follow = (world, id, spec) => {
|
|
27853
28431
|
D.spec = spec;
|
|
28432
|
+
breach.claim();
|
|
28433
|
+
let fallback = null;
|
|
27854
28434
|
const offFollow = world.on("*", (e) => {
|
|
27855
28435
|
if (e.object !== id) return;
|
|
27856
28436
|
switch (e.type) {
|
|
@@ -27860,6 +28440,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27860
28440
|
case "chip":
|
|
27861
28441
|
breach.chip(e);
|
|
27862
28442
|
break;
|
|
28443
|
+
case "spall":
|
|
28444
|
+
breach.spall(e);
|
|
28445
|
+
break;
|
|
27863
28446
|
case "fracture":
|
|
27864
28447
|
breach.drop(e.part);
|
|
27865
28448
|
break;
|
|
@@ -27869,10 +28452,16 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27869
28452
|
default:
|
|
27870
28453
|
break;
|
|
27871
28454
|
}
|
|
28455
|
+
if (!fallback && typeof setTimeout === "function") fallback = setTimeout(() => {
|
|
28456
|
+
fallback = null;
|
|
28457
|
+
breach.flush(Infinity);
|
|
28458
|
+
}, FOLLOW_FLUSH_FALLBACK_MS);
|
|
27872
28459
|
});
|
|
27873
28460
|
return { restore: () => breach.restore(), dispose: () => {
|
|
27874
28461
|
offFollow();
|
|
27875
28462
|
breach.restore();
|
|
28463
|
+
}, update: () => {
|
|
28464
|
+
breach.flush();
|
|
27876
28465
|
} };
|
|
27877
28466
|
};
|
|
27878
28467
|
D.piece = (id) => D.active ? D.world.part(D.id, id) : null;
|
|
@@ -27905,6 +28494,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27905
28494
|
return r;
|
|
27906
28495
|
};
|
|
27907
28496
|
D.animate = (dt) => {
|
|
28497
|
+
breach.flush();
|
|
27908
28498
|
if (R) return;
|
|
27909
28499
|
let moved = false;
|
|
27910
28500
|
for (const [id, list2] of bodies) {
|
|
@@ -27968,7 +28558,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27968
28558
|
}
|
|
27969
28559
|
Object.assign(K, { createHouseDestruction });
|
|
27970
28560
|
}
|
|
27971
|
-
function installBuildBuild(K,
|
|
28561
|
+
function installBuildBuild(K, shared2) {
|
|
27972
28562
|
const { THREE, cfg, rectsOf: rectsOf2, invalidateShadow, colliderChanged, VERSION: VERSION2, CARS, EPS: EPS3, LIGHTS, MIRRORS, Y0, animateClotheslines, animateDoors, animateInteractive, applyLeaf, applyOutbuildings, applyPart, applyPiece, assembleInteractive, baseboardAndSidewalk, buildStairs, building, carModel, chooseMirror, closeScene, collideAt, createWater, cursor, doorText, doors, electricalStructure, elevator, floorsAndSlabs, gatesInteractive, houseItems, ivAssemble, ivBuild, ivDispose, ivParts, ivPublish, ivUpdate, lightOn, linkDoorLeaves, mailboxInteractive, newInteractiveState, newMirrorState, outbuildings, paths, perimeter, placeSwitches, roofs, roomAt, solar, targetOf, terrain, toggleDoor, toggleLight, walls, waterPipes, windows, props, TYPES, IVK, VEG, vegMaterials, markGroups, assembleStructure, createHouseDestruction, newState, enter, tagDamage } = K;
|
|
27973
28563
|
function build(r0, opts) {
|
|
27974
28564
|
opts = opts || {};
|
|
@@ -27979,43 +28569,43 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
27979
28569
|
cursor.accs.clear();
|
|
27980
28570
|
LIGHTS.length = 0;
|
|
27981
28571
|
const pr = opts.building || {};
|
|
27982
|
-
|
|
27983
|
-
|
|
27984
|
-
|
|
27985
|
-
|
|
27986
|
-
|
|
27987
|
-
|
|
27988
|
-
|
|
27989
|
-
|
|
27990
|
-
|
|
27991
|
-
for (const c of r.rooms)
|
|
27992
|
-
|
|
27993
|
-
|
|
27994
|
-
|
|
27995
|
-
for (const e of r0.structure && r0.structure.parts || [])
|
|
28572
|
+
shared2.ctx.r = r;
|
|
28573
|
+
shared2.ctx.colors = r.colors;
|
|
28574
|
+
shared2.ctx.cut = !!opts.cut;
|
|
28575
|
+
shared2.ctx.night = !!opts.night;
|
|
28576
|
+
shared2.ctx.labels = [];
|
|
28577
|
+
shared2.ctx.colliders = [];
|
|
28578
|
+
shared2.ctx.stairs = [];
|
|
28579
|
+
shared2.ctx.noTerrain = opts.terrain === false;
|
|
28580
|
+
shared2.ctx.roomById = {};
|
|
28581
|
+
for (const c of r.rooms) shared2.ctx.roomById[c.id] = c;
|
|
28582
|
+
shared2.ctx.pieces = /* @__PURE__ */ new Map();
|
|
28583
|
+
shared2.ctx.pieceObjects = /* @__PURE__ */ new Map();
|
|
28584
|
+
shared2.ctx.structureIndex = {};
|
|
28585
|
+
for (const e of r0.structure && r0.structure.parts || []) shared2.ctx.structureIndex[e.id] = e;
|
|
27996
28586
|
{
|
|
27997
|
-
const view =
|
|
27998
|
-
|
|
27999
|
-
for (const id of view.replaced) delete
|
|
28587
|
+
const view = shared2.ctx.panelView = panelViewOf(r0.structure, !!cfg.destruction);
|
|
28588
|
+
shared2.ctx.panelsOf = /* @__PURE__ */ new Map();
|
|
28589
|
+
for (const id of view.replaced) delete shared2.ctx.structureIndex[id];
|
|
28000
28590
|
for (const e of view.panels) {
|
|
28001
|
-
|
|
28002
|
-
const l =
|
|
28591
|
+
shared2.ctx.structureIndex[e.id] = e;
|
|
28592
|
+
const l = shared2.ctx.panelsOf.get(e.slab);
|
|
28003
28593
|
if (l) l.push(e);
|
|
28004
|
-
else
|
|
28594
|
+
else shared2.ctx.panelsOf.set(e.slab, [e]);
|
|
28005
28595
|
}
|
|
28006
28596
|
}
|
|
28007
|
-
|
|
28008
|
-
|
|
28597
|
+
shared2.ctx.panes = r0.roof && r0.roof.panes || [];
|
|
28598
|
+
shared2.ctx.noPiece = false;
|
|
28009
28599
|
cursor.separate = opts.pieces === "meshes";
|
|
28010
28600
|
cursor.pc = null;
|
|
28011
|
-
|
|
28012
|
-
|
|
28013
|
-
|
|
28014
|
-
|
|
28015
|
-
|
|
28016
|
-
|
|
28017
|
-
|
|
28018
|
-
|
|
28601
|
+
shared2.ctx.apartment = r.template === "apartment_modern";
|
|
28602
|
+
shared2.ctx.pa = Math.max(3, Math.min(20, pr.floors != null ? pr.floors : 5));
|
|
28603
|
+
shared2.ctx.pf = Math.max(1, Math.min(shared2.ctx.pa, pr.floor != null ? pr.floor : 3));
|
|
28604
|
+
shared2.ctx.pu = Math.max(0, pr.unit != null ? pr.unit : 0);
|
|
28605
|
+
shared2.ctx.showBuilding = shared2.ctx.apartment && (pr.showIt == null ? true : !!pr.showIt);
|
|
28606
|
+
shared2.ctx.limits = { x0: -2, z0: -2, x1: r.w + 2, z1: r.d + 2 };
|
|
28607
|
+
shared2.ctx.veg = VEG ? { G: VEG.G, S: VEG.S, mats: vegMaterials, groups: /* @__PURE__ */ new Map(), ok: /* @__PURE__ */ new Map(), opts: shared2.quality === "game" ? { quality: "game" } : { lod: 0, triangleBudget: 6e4 } } : null;
|
|
28608
|
+
shared2.ctx.vegInfo = null;
|
|
28019
28609
|
terrain();
|
|
28020
28610
|
if (r.lot) {
|
|
28021
28611
|
if (!opts.noPerimeter) {
|
|
@@ -28026,7 +28616,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28026
28616
|
}
|
|
28027
28617
|
walls();
|
|
28028
28618
|
baseboardAndSidewalk();
|
|
28029
|
-
|
|
28619
|
+
shared2.ctx.wallColliders = shared2.ctx.colliders.length;
|
|
28030
28620
|
doors();
|
|
28031
28621
|
windows();
|
|
28032
28622
|
floorsAndSlabs();
|
|
@@ -28034,14 +28624,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28034
28624
|
buildStairs();
|
|
28035
28625
|
elevator();
|
|
28036
28626
|
const water = createWater(r, h.state);
|
|
28037
|
-
|
|
28627
|
+
shared2.ctx.iv = null;
|
|
28038
28628
|
h.IV = null;
|
|
28039
28629
|
if (IVK) {
|
|
28040
28630
|
try {
|
|
28041
|
-
h.IV =
|
|
28631
|
+
h.IV = shared2.ctx.iv = ivBuild(h, water);
|
|
28042
28632
|
} catch (e) {
|
|
28043
28633
|
console.warn("interactables", e);
|
|
28044
|
-
|
|
28634
|
+
shared2.ctx.iv = h.IV = null;
|
|
28045
28635
|
}
|
|
28046
28636
|
}
|
|
28047
28637
|
const noModel = houseItems();
|
|
@@ -28050,14 +28640,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28050
28640
|
electricalStructure();
|
|
28051
28641
|
roofs();
|
|
28052
28642
|
solar();
|
|
28053
|
-
if (
|
|
28643
|
+
if (shared2.ctx.showBuilding) building();
|
|
28054
28644
|
for (const c of r.rooms) {
|
|
28055
28645
|
if (c.type === "void") continue;
|
|
28056
28646
|
const [a, b, c2, d] = rectsOf2(c)[0];
|
|
28057
|
-
|
|
28647
|
+
shared2.ctx.labels.push({ pos: new THREE.Vector3((a + c2) / 2, Y0(c.floor) + 1.1, (b + d) / 2), text: c.name, group: "f" + c.floor, type: "room", floor: c.floor });
|
|
28058
28648
|
}
|
|
28059
|
-
const mirrorsCopy = MIRRORS.map((E, i) => Object.assign({ i }, E)), gs = closeScene(
|
|
28060
|
-
for (const fo of
|
|
28649
|
+
const mirrorsCopy = MIRRORS.map((E, i) => Object.assign({ i }, E)), gs = closeScene(shared2.mats);
|
|
28650
|
+
for (const fo of shared2.ctx.leaves) {
|
|
28061
28651
|
const parent = gs["f" + fo.floor] || (gs["f" + fo.floor] = new THREE.Group());
|
|
28062
28652
|
fo.gs = [];
|
|
28063
28653
|
for (const gd of fo.groups) {
|
|
@@ -28070,22 +28660,22 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28070
28660
|
}
|
|
28071
28661
|
applyLeaf(fo);
|
|
28072
28662
|
}
|
|
28073
|
-
if (
|
|
28663
|
+
if (shared2.ctx.iv) ivAssemble(shared2.ctx.iv, gs);
|
|
28074
28664
|
assembleInteractive(gs);
|
|
28075
28665
|
linkDoorLeaves();
|
|
28076
28666
|
mailboxInteractive();
|
|
28077
28667
|
const root = markKitOrigin(new THREE.Group(), { owner: "game-floorplan-three", kind: "structure", id: r.template }), house = new THREE.Group();
|
|
28078
28668
|
root.name = "house3d";
|
|
28079
28669
|
root.add(house);
|
|
28080
|
-
|
|
28081
|
-
if (
|
|
28082
|
-
const u = r.building.units[Math.min(
|
|
28083
|
-
house.position.set(u.u,
|
|
28670
|
+
shared2.mirrors.house = house;
|
|
28671
|
+
if (shared2.ctx.apartment) {
|
|
28672
|
+
const u = r.building.units[Math.min(shared2.ctx.pu, r.building.units.length - 1)];
|
|
28673
|
+
house.position.set(u.u, shared2.ctx.showBuilding ? 0 : -r.floors[0].y0, u.v);
|
|
28084
28674
|
house.rotation.y = u.ry;
|
|
28085
|
-
|
|
28675
|
+
shared2.ctx.unitRy = u.ry;
|
|
28086
28676
|
}
|
|
28087
28677
|
house.updateMatrixWorld(true);
|
|
28088
|
-
|
|
28678
|
+
shared2.ctx.unitInverse = house.matrixWorld.clone().invert();
|
|
28089
28679
|
for (const [k, g] of Object.entries(gs)) {
|
|
28090
28680
|
g.name = k;
|
|
28091
28681
|
(k === "floor" || k === "building" ? root : house).add(g);
|
|
@@ -28094,31 +28684,31 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28094
28684
|
h.root = root;
|
|
28095
28685
|
h.house = house;
|
|
28096
28686
|
h.houseGroup = house;
|
|
28097
|
-
|
|
28098
|
-
|
|
28099
|
-
|
|
28100
|
-
for (const c of
|
|
28687
|
+
shared2.ctx.noModel = noModel;
|
|
28688
|
+
shared2.ctx.lights = LIGHTS.filter((l) => l.type !== "lantern" && l.type !== "candles" || shared2.ctx.night).map((l) => ({ ...l }));
|
|
28689
|
+
shared2.ctx.animateDoorsOn = shared2.ctx.animateDoorsOn || false;
|
|
28690
|
+
for (const c of shared2.ctx.colliders) {
|
|
28101
28691
|
c.aabb = [c.x0, c.z0, c.x1, c.z1];
|
|
28102
28692
|
if (c.type === "wall") c.damageable = tagDamage("masonry");
|
|
28103
28693
|
}
|
|
28104
|
-
const colliders =
|
|
28694
|
+
const colliders = shared2.ctx.colliders.concat(shared2.inter.objs.map((o) => ({ type: "furniture", f: o.f, obb: { cx: o.cx, cz: o.cz, hw: o.hw, hd: o.hd, c: o.c, s: o.s }, item: o.type, off: false })));
|
|
28105
28695
|
const parts = {}, setOpen = (def, t) => {
|
|
28106
28696
|
def.target = t;
|
|
28107
28697
|
def.t = t;
|
|
28108
|
-
|
|
28698
|
+
shared2.partState.set(def.name, t);
|
|
28109
28699
|
if (def.col) {
|
|
28110
28700
|
def.col.off = t > 0.5;
|
|
28111
28701
|
colliderChanged(def.col);
|
|
28112
28702
|
}
|
|
28113
28703
|
applyPiece(def);
|
|
28114
|
-
|
|
28704
|
+
shared2.inter.anim.delete(def);
|
|
28115
28705
|
invalidateShadow();
|
|
28116
28706
|
};
|
|
28117
28707
|
const mark = (o, id) => {
|
|
28118
28708
|
if (o) o.userData.partId = id;
|
|
28119
28709
|
};
|
|
28120
28710
|
const PART_DAMAGE = { water_tank: "water", shower_door: "glass", gate_leaf: "metal", mailbox_door: "metal", mirror: "glass", cooking_gas_cylinder: "gas" };
|
|
28121
|
-
for (const [id, g] of Object.entries(
|
|
28711
|
+
for (const [id, g] of Object.entries(shared2.ctx.parts || {})) {
|
|
28122
28712
|
const tp = g.userData.part, dn = PART_DAMAGE[tp];
|
|
28123
28713
|
if (dn) g.userData.damageable = tagDamage(dn);
|
|
28124
28714
|
mark(g, id);
|
|
@@ -28138,7 +28728,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28138
28728
|
return g.userData.t || 0;
|
|
28139
28729
|
}, meta: g.userData };
|
|
28140
28730
|
}
|
|
28141
|
-
for (const fo of
|
|
28731
|
+
for (const fo of shared2.ctx.leaves) {
|
|
28142
28732
|
const id = "door:" + fo.id, dn = tagDamage(fo.type === "steel" ? "metal" : "wood");
|
|
28143
28733
|
fo.damageable = dn;
|
|
28144
28734
|
for (const g of fo.gs) mark(g, id);
|
|
@@ -28150,14 +28740,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28150
28740
|
fo.col.off = fo.open;
|
|
28151
28741
|
colliderChanged(fo.col);
|
|
28152
28742
|
}
|
|
28153
|
-
|
|
28743
|
+
shared2.doorState.set(fo.id, fo.open);
|
|
28154
28744
|
applyLeaf(fo);
|
|
28155
28745
|
invalidateShadow();
|
|
28156
28746
|
}, get t() {
|
|
28157
28747
|
return fo.t;
|
|
28158
28748
|
}, leaf: fo };
|
|
28159
28749
|
}
|
|
28160
|
-
for (const def of
|
|
28750
|
+
for (const def of shared2.inter.defs.values()) {
|
|
28161
28751
|
if (!def.outer) continue;
|
|
28162
28752
|
const cab = def.kind === "swing" || def.kind === "drawer", gate = /^gate/.test(def.kind);
|
|
28163
28753
|
const dn = cab ? tagDamage("wood") : gate ? tagDamage("metal") : null;
|
|
@@ -28167,7 +28757,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28167
28757
|
return def.t;
|
|
28168
28758
|
}, def };
|
|
28169
28759
|
}
|
|
28170
|
-
if (
|
|
28760
|
+
if (shared2.ctx.iv) ivParts(shared2.ctx.iv, parts, tagDamage);
|
|
28171
28761
|
const cars = [];
|
|
28172
28762
|
CARS.forEach((C, i) => {
|
|
28173
28763
|
const mod = carModel(C.k, C.seed);
|
|
@@ -28207,18 +28797,18 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28207
28797
|
const actOn = (e, a) => {
|
|
28208
28798
|
enter(h);
|
|
28209
28799
|
if (cfg.onInteract && cfg.onInteract(e, a) === false) return false;
|
|
28210
|
-
|
|
28800
|
+
shared2.inter.target = a || { target: e.ref, text: e.label, action: e._action };
|
|
28211
28801
|
e._action();
|
|
28212
28802
|
return true;
|
|
28213
28803
|
};
|
|
28214
|
-
for (const fo of
|
|
28804
|
+
for (const fo of shared2.ctx.leaves) {
|
|
28215
28805
|
const e = { id: "door:" + fo.id, type: fo.type === "steel" ? "garage_door" : "door", floor: fo.floor, pos: [fo.cx, Y0(fo.floor) + 1, fo.cz], radius: 1.7, get label() {
|
|
28216
28806
|
return doorText(fo);
|
|
28217
28807
|
}, ref: fo, _action: () => toggleDoor(fo) };
|
|
28218
28808
|
e.act = () => actOn(e);
|
|
28219
28809
|
interactables.push(e);
|
|
28220
28810
|
}
|
|
28221
|
-
for (const it of
|
|
28811
|
+
for (const it of shared2.inter.items) {
|
|
28222
28812
|
const k = it.type + ":" + it.id, n = usedMap.get(k) || 0;
|
|
28223
28813
|
usedMap.set(k, n + 1);
|
|
28224
28814
|
const e = { id: n ? k + "#" + n : k, type: it.type, floor: it.floor, pos: it.anchor.slice(), radius: it.range, angle: it.angle, get label() {
|
|
@@ -28228,12 +28818,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28228
28818
|
interactables.push(e);
|
|
28229
28819
|
it.pub = e;
|
|
28230
28820
|
}
|
|
28231
|
-
for (const fo of
|
|
28821
|
+
for (const fo of shared2.ctx.leaves) fo.pub = interactables.find((e) => e.ref === fo);
|
|
28232
28822
|
const lodObjects = [];
|
|
28233
|
-
for (const def of
|
|
28234
|
-
for (const [id, g] of Object.entries(
|
|
28235
|
-
if (
|
|
28236
|
-
for (const E of
|
|
28823
|
+
for (const def of shared2.inter.defs.values()) if (def.outer && /^(light|drawer|swing|curtain|light_switch|handle)$/.test(def.kind)) lodObjects.push(def.outer);
|
|
28824
|
+
for (const [id, g] of Object.entries(shared2.ctx.parts || {})) if (/^(handle|shower_door)$/.test(g.userData.part) && g.visible !== false) lodObjects.push(g);
|
|
28825
|
+
if (shared2.ctx.iv) {
|
|
28826
|
+
for (const E of shared2.ctx.iv.roots) lodObjects.push(E.root);
|
|
28237
28827
|
}
|
|
28238
28828
|
const countDraw = () => {
|
|
28239
28829
|
let n = 0, t = 0;
|
|
@@ -28251,7 +28841,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28251
28841
|
for (const o of lodObjects) o.visible = true;
|
|
28252
28842
|
const budget = opts.drawCallBudget != null ? opts.drawCallBudget : cfg.drawCallBudget;
|
|
28253
28843
|
const stats2 = { quality: h.quality, drawCalls: s0.n, drawCallsLOD1: s1.n, triangles: s0.t, trianglesLod1: s1.t, budget: budget || null, overBudget: !!budget && s0.n > budget, tBuild: performance.now() - t0 };
|
|
28254
|
-
|
|
28844
|
+
shared2.ctx.tBuild = stats2.tBuild;
|
|
28255
28845
|
const applyLod = (n) => {
|
|
28256
28846
|
n = Math.max(0, Math.min(2, n | 0));
|
|
28257
28847
|
if (n === h.lodCurrent) return;
|
|
@@ -28317,39 +28907,39 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28317
28907
|
building: gs.building || null,
|
|
28318
28908
|
waterTank: r.waterTank ? (() => {
|
|
28319
28909
|
const pt = Object.values(parts).find((p) => p.type === "water_tank") || null;
|
|
28320
|
-
return { part: pt, group: pt ? pt.group : null, pos:
|
|
28910
|
+
return { part: pt, group: pt ? pt.group : null, pos: shared2.ctx.waterTankPos || null, plant: r.waterTank };
|
|
28321
28911
|
})() : null,
|
|
28322
28912
|
colliders,
|
|
28323
28913
|
parts,
|
|
28324
28914
|
cars,
|
|
28325
28915
|
interactables,
|
|
28326
|
-
doors:
|
|
28327
|
-
stairs:
|
|
28328
|
-
labels:
|
|
28916
|
+
doors: shared2.ctx.leaves,
|
|
28917
|
+
stairs: shared2.ctx.stairs,
|
|
28918
|
+
labels: shared2.ctx.labels,
|
|
28329
28919
|
noModel,
|
|
28330
28920
|
lights: (() => {
|
|
28331
28921
|
const by = {};
|
|
28332
|
-
for (const l of
|
|
28922
|
+
for (const l of shared2.ctx.lights) {
|
|
28333
28923
|
const k = l.roomId != null ? l.roomId : l.room;
|
|
28334
28924
|
(by[k] || (by[k] = [])).push(l);
|
|
28335
28925
|
}
|
|
28336
|
-
return { list:
|
|
28926
|
+
return { list: shared2.ctx.lights, byRoom: by };
|
|
28337
28927
|
})(),
|
|
28338
|
-
limits:
|
|
28339
|
-
apartment:
|
|
28340
|
-
showBuilding:
|
|
28341
|
-
buildingConfig: { floors:
|
|
28342
|
-
unitRy:
|
|
28343
|
-
night:
|
|
28344
|
-
cut:
|
|
28928
|
+
limits: shared2.ctx.limits,
|
|
28929
|
+
apartment: shared2.ctx.apartment,
|
|
28930
|
+
showBuilding: shared2.ctx.showBuilding,
|
|
28931
|
+
buildingConfig: { floors: shared2.ctx.pa, floor: shared2.ctx.pf, unit: shared2.ctx.pu },
|
|
28932
|
+
unitRy: shared2.ctx.unitRy || 0,
|
|
28933
|
+
night: shared2.ctx.night,
|
|
28934
|
+
cut: shared2.ctx.cut,
|
|
28345
28935
|
interactives: h.IV ? ivPublish(h) : null,
|
|
28346
28936
|
state: h.state,
|
|
28347
28937
|
stats: stats2,
|
|
28348
|
-
vegetation:
|
|
28349
|
-
solar:
|
|
28938
|
+
vegetation: shared2.ctx.vegInfo || null,
|
|
28939
|
+
solar: shared2.ctx.solarInfo || null,
|
|
28350
28940
|
water,
|
|
28351
|
-
electrical:
|
|
28352
|
-
gutters:
|
|
28941
|
+
electrical: shared2.ctx.electricalInfo || null,
|
|
28942
|
+
gutters: shared2.ctx.gutterInfo || null,
|
|
28353
28943
|
// per frame: doors, parts, wind-blown laundry and (with a focus) distance LOD; dt in seconds, time in ms (rAF); focus = {x,y,z} in world coordinates
|
|
28354
28944
|
update(dt, time, focus) {
|
|
28355
28945
|
enter(h);
|
|
@@ -28359,9 +28949,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28359
28949
|
if (destruction.active || destruction.statistics().falling || destruction.statistics().fragments) destruction.animate(dt);
|
|
28360
28950
|
if (h.IV) ivUpdate(h, dt, time, focus);
|
|
28361
28951
|
if (time != null) animateClotheslines(time);
|
|
28362
|
-
if (
|
|
28363
|
-
|
|
28364
|
-
|
|
28952
|
+
if (shared2.vegMaterials) {
|
|
28953
|
+
shared2.vegMaterials.update((time != null ? time : performance.now()) / 1e3);
|
|
28954
|
+
shared2.vegMaterials.setActors(focus ? [{ x: focus.x, y: focus.y, z: focus.z, radius: 0.9 }] : []);
|
|
28365
28955
|
}
|
|
28366
28956
|
if (focus && cfg.lod !== false) {
|
|
28367
28957
|
const L = Object.assign({ interior: 45, hide: 220 }, cfg.lod), d = distance2(focus), at = h.lodCurrent;
|
|
@@ -28373,12 +28963,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28373
28963
|
show(o) {
|
|
28374
28964
|
enter(h);
|
|
28375
28965
|
o = o || {};
|
|
28376
|
-
const rr =
|
|
28966
|
+
const rr = shared2.ctx.r, nA = rr.floors.length, a = o.floor == null ? -1 : o.floor, sel = a >= nA ? -1 : a, cut = !!o.cut;
|
|
28377
28967
|
for (const [k, g] of Object.entries(gs)) {
|
|
28378
28968
|
let v = true;
|
|
28379
28969
|
if (k[0] === "f") v = sel < 0 || +k.slice(1) <= sel;
|
|
28380
28970
|
else if (k[0] === "t") v = !cut && (sel < 0 || +k.slice(1) < sel);
|
|
28381
|
-
else if (k === "roof") v = !cut && sel < 0 && (!
|
|
28971
|
+
else if (k === "roof") v = !cut && sel < 0 && (!shared2.ctx.apartment || !shared2.ctx.showBuilding || shared2.ctx.pf === shared2.ctx.pa);
|
|
28382
28972
|
else if (k === "attic_tank") v = (cut || sel >= 0) && (sel < 0 || nA - 1 <= sel);
|
|
28383
28973
|
else if (k === "lot") v = o.lot == null ? true : !!o.lot;
|
|
28384
28974
|
g.visible = v;
|
|
@@ -28395,11 +28985,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28395
28985
|
return actOn(a.target && a.target.pub ? a.target.pub : { id: a.target && a.target.id || a.text, type: a.target && a.target.kit ? a.target.type : "door", label: a.text, ref: a.target, _action: a.action }, a);
|
|
28396
28986
|
},
|
|
28397
28987
|
message() {
|
|
28398
|
-
return
|
|
28988
|
+
return shared2.inter.msg && performance.now() < shared2.inter.msg.until ? shared2.inter.msg.text : null;
|
|
28399
28989
|
},
|
|
28400
28990
|
toggleDoor(fo) {
|
|
28401
28991
|
enter(h);
|
|
28402
|
-
toggleDoor(typeof fo === "string" ?
|
|
28992
|
+
toggleDoor(typeof fo === "string" ? shared2.ctx.leaves.find((f) => f.id === fo) : fo);
|
|
28403
28993
|
},
|
|
28404
28994
|
lightOn(roomId) {
|
|
28405
28995
|
enter(h);
|
|
@@ -28471,13 +29061,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28471
29061
|
});
|
|
28472
29062
|
root.removeFromParent();
|
|
28473
29063
|
},
|
|
28474
|
-
internal: { h, ctx:
|
|
29064
|
+
internal: { h, ctx: shared2.ctx, inter: shared2.inter, partState: shared2.partState, doorState: shared2.doorState, mirrors: shared2.mirrors }
|
|
28475
29065
|
};
|
|
28476
29066
|
return res;
|
|
28477
29067
|
}
|
|
28478
29068
|
Object.assign(K, { build });
|
|
28479
29069
|
}
|
|
28480
|
-
function buildApi(K,
|
|
29070
|
+
function buildApi(K, shared2) {
|
|
28481
29071
|
const { cfg, VERSION: VERSION2, ATLAS, TEX, applyPart, carGroup, carModel, props, TYPES, roomLightMask, lighting, newState, build } = K;
|
|
28482
29072
|
return {
|
|
28483
29073
|
version: VERSION2,
|
|
@@ -28487,26 +29077,26 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28487
29077
|
mv: props,
|
|
28488
29078
|
applyPart,
|
|
28489
29079
|
// the kernel and the shared state, for recorders that run the team's builders into something else than the house (`furnitureSpec`, `tapSpec`): not a stable api
|
|
28490
|
-
internals: { K, shared },
|
|
29080
|
+
internals: { K, shared: shared2 },
|
|
28491
29081
|
get materials() {
|
|
28492
|
-
return
|
|
29082
|
+
return shared2.mats;
|
|
28493
29083
|
},
|
|
28494
29084
|
roomLightMask,
|
|
28495
29085
|
lighting,
|
|
28496
29086
|
setNight(n) {
|
|
28497
|
-
|
|
28498
|
-
|
|
29087
|
+
shared2.mats.glass.emissive.set(n ? 9067040 : 0);
|
|
29088
|
+
shared2.mats.glass.opacity = n ? 0.4 : 0.24;
|
|
28499
29089
|
},
|
|
28500
29090
|
cars: { model: carModel, group: carGroup, info: (k, seed) => {
|
|
28501
29091
|
const m = carModel(k, seed);
|
|
28502
29092
|
return m && { parts: m.parts.length, tris: m.tris, L: m.L, W: m.W, H: m.H };
|
|
28503
29093
|
} },
|
|
28504
29094
|
dispose() {
|
|
28505
|
-
if (
|
|
28506
|
-
|
|
28507
|
-
|
|
29095
|
+
if (shared2.vegMaterials) {
|
|
29096
|
+
shared2.vegMaterials.dispose();
|
|
29097
|
+
shared2.vegMaterials = null;
|
|
28508
29098
|
}
|
|
28509
|
-
for (const m of Object.values(
|
|
29099
|
+
for (const m of Object.values(shared2.mats)) {
|
|
28510
29100
|
if (m && m.dispose) m.dispose();
|
|
28511
29101
|
}
|
|
28512
29102
|
for (const [k, t] of Object.entries(TEX)) if (t && t.dispose && !(cfg.textures && cfg.textures[k])) t.dispose();
|
|
@@ -28531,7 +29121,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28531
29121
|
const colliderChanged = (c) => {
|
|
28532
29122
|
if (c && cfg.onCollider) cfg.onCollider(c);
|
|
28533
29123
|
};
|
|
28534
|
-
const
|
|
29124
|
+
const shared2 = { mats: null, quality: cfg.quality === "game" ? "game" : "high" };
|
|
28535
29125
|
const seedKey = (id) => {
|
|
28536
29126
|
if (cfg.seedKey && id != null) {
|
|
28537
29127
|
const k = cfg.seedKey(String(id));
|
|
@@ -28540,61 +29130,61 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28540
29130
|
return id;
|
|
28541
29131
|
};
|
|
28542
29132
|
const K = { t: createTranslator2(cfg.locale), seedKey, THREE: shapeGeometries(THREE), cfg, DOC, PROPS, Reflector, FLEET, HP, invalidate, invalidateShadow, colliderChanged, VERSION, rectsOf, isOpenArea, OPEN_ROOM_TYPES: OPEN_ROOM_TYPES2 };
|
|
28543
|
-
installKernelGeometry(K,
|
|
28544
|
-
installKernelNoise(K,
|
|
28545
|
-
installMaterialsTextures(K,
|
|
28546
|
-
installMaterialsMaterials(K,
|
|
28547
|
-
installKernelCloseScene(K,
|
|
28548
|
-
installHouseHelpers(K,
|
|
28549
|
-
installHouseWalls(K,
|
|
28550
|
-
installHouseDoors(K,
|
|
28551
|
-
installHouseWindows(K,
|
|
28552
|
-
installHouseFloors(K,
|
|
28553
|
-
installHouseStairs(K,
|
|
28554
|
-
installLightsFixtures(K,
|
|
28555
|
-
installLightsDecor(K,
|
|
28556
|
-
installLotTerrain(K,
|
|
28557
|
-
installLotPerimeter(K,
|
|
28558
|
-
installLotGates(K,
|
|
28559
|
-
installRoofRoofs(K,
|
|
28560
|
-
installRoofGutters(K,
|
|
28561
|
-
installRoofSlabs(K,
|
|
28562
|
-
installRoofTiles(K,
|
|
28563
|
-
installRoofRect(K,
|
|
28564
|
-
installMirrors(K,
|
|
28565
|
-
installCars(K,
|
|
28566
|
-
installHouseBuilding(K,
|
|
28567
|
-
installUtilitiesWater(K,
|
|
28568
|
-
installUtilitiesElectrical(K,
|
|
28569
|
-
installHouseBaseboard(K,
|
|
28570
|
-
installUtilitiesSolar(K,
|
|
28571
|
-
installHouseOutbuildings(K,
|
|
28572
|
-
installFurnitureApi(K,
|
|
28573
|
-
installFurnitureBuilders(K,
|
|
28574
|
-
installFurnitureTypeTable(K,
|
|
28575
|
-
installFurnitureTaps(K,
|
|
28576
|
-
installFurnitureFixtures(K,
|
|
28577
|
-
installFurniturePlants(K,
|
|
28578
|
-
installFurnitureYard(K,
|
|
28579
|
-
installFurnitureExtraTypes(K,
|
|
28580
|
-
installFurniturePlaceItems(K,
|
|
28581
|
-
installVegetationBridge(K,
|
|
28582
|
-
installInteractionState(K,
|
|
28583
|
-
installInteractionCollision(K,
|
|
28584
|
-
installInteractionItems(K,
|
|
28585
|
-
installInteractionFittings(K,
|
|
28586
|
-
installInteractionDoors(K,
|
|
28587
|
-
installInteractionTarget(K,
|
|
28588
|
-
installInteractablesBridge(K,
|
|
28589
|
-
installAnimationClotheslines(K,
|
|
28590
|
-
installBuildInstance(K,
|
|
28591
|
-
installInteractablesKit(K,
|
|
28592
|
-
installLightsRoomLight(K,
|
|
28593
|
-
installDestructionPieces(K,
|
|
28594
|
-
installDestructionBreach(K,
|
|
28595
|
-
installDestructionWorld(K,
|
|
28596
|
-
installBuildBuild(K,
|
|
28597
|
-
return buildApi(K,
|
|
29133
|
+
installKernelGeometry(K, shared2);
|
|
29134
|
+
installKernelNoise(K, shared2);
|
|
29135
|
+
installMaterialsTextures(K, shared2);
|
|
29136
|
+
installMaterialsMaterials(K, shared2);
|
|
29137
|
+
installKernelCloseScene(K, shared2);
|
|
29138
|
+
installHouseHelpers(K, shared2);
|
|
29139
|
+
installHouseWalls(K, shared2);
|
|
29140
|
+
installHouseDoors(K, shared2);
|
|
29141
|
+
installHouseWindows(K, shared2);
|
|
29142
|
+
installHouseFloors(K, shared2);
|
|
29143
|
+
installHouseStairs(K, shared2);
|
|
29144
|
+
installLightsFixtures(K, shared2);
|
|
29145
|
+
installLightsDecor(K, shared2);
|
|
29146
|
+
installLotTerrain(K, shared2);
|
|
29147
|
+
installLotPerimeter(K, shared2);
|
|
29148
|
+
installLotGates(K, shared2);
|
|
29149
|
+
installRoofRoofs(K, shared2);
|
|
29150
|
+
installRoofGutters(K, shared2);
|
|
29151
|
+
installRoofSlabs(K, shared2);
|
|
29152
|
+
installRoofTiles(K, shared2);
|
|
29153
|
+
installRoofRect(K, shared2);
|
|
29154
|
+
installMirrors(K, shared2);
|
|
29155
|
+
installCars(K, shared2);
|
|
29156
|
+
installHouseBuilding(K, shared2);
|
|
29157
|
+
installUtilitiesWater(K, shared2);
|
|
29158
|
+
installUtilitiesElectrical(K, shared2);
|
|
29159
|
+
installHouseBaseboard(K, shared2);
|
|
29160
|
+
installUtilitiesSolar(K, shared2);
|
|
29161
|
+
installHouseOutbuildings(K, shared2);
|
|
29162
|
+
installFurnitureApi(K, shared2);
|
|
29163
|
+
installFurnitureBuilders(K, shared2);
|
|
29164
|
+
installFurnitureTypeTable(K, shared2);
|
|
29165
|
+
installFurnitureTaps(K, shared2);
|
|
29166
|
+
installFurnitureFixtures(K, shared2);
|
|
29167
|
+
installFurniturePlants(K, shared2);
|
|
29168
|
+
installFurnitureYard(K, shared2);
|
|
29169
|
+
installFurnitureExtraTypes(K, shared2);
|
|
29170
|
+
installFurniturePlaceItems(K, shared2);
|
|
29171
|
+
installVegetationBridge(K, shared2);
|
|
29172
|
+
installInteractionState(K, shared2);
|
|
29173
|
+
installInteractionCollision(K, shared2);
|
|
29174
|
+
installInteractionItems(K, shared2);
|
|
29175
|
+
installInteractionFittings(K, shared2);
|
|
29176
|
+
installInteractionDoors(K, shared2);
|
|
29177
|
+
installInteractionTarget(K, shared2);
|
|
29178
|
+
installInteractablesBridge(K, shared2);
|
|
29179
|
+
installAnimationClotheslines(K, shared2);
|
|
29180
|
+
installBuildInstance(K, shared2);
|
|
29181
|
+
installInteractablesKit(K, shared2);
|
|
29182
|
+
installLightsRoomLight(K, shared2);
|
|
29183
|
+
installDestructionPieces(K, shared2);
|
|
29184
|
+
installDestructionBreach(K, shared2);
|
|
29185
|
+
installDestructionWorld(K, shared2);
|
|
29186
|
+
installBuildBuild(K, shared2);
|
|
29187
|
+
return buildApi(K, shared2);
|
|
28598
29188
|
}
|
|
28599
29189
|
var WOOD_THIN = 0.035;
|
|
28600
29190
|
var BOARD_TOP_THICK = 0.07;
|
|
@@ -28817,21 +29407,21 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
28817
29407
|
const seed = Math.round(opts.seed ?? 1);
|
|
28818
29408
|
const plain2 = SHELVING.test(type) ? "paper" : "plastic";
|
|
28819
29409
|
const root = { x: seed, z: 0, ry: 0, w, d, h, y: 0, base: 0, palette: o.palette, seed: `furniture_${type}_${seed}` };
|
|
28820
|
-
const { K, shared } = renderer.internals;
|
|
29410
|
+
const { K, shared: shared2 } = renderer.internals;
|
|
28821
29411
|
const before = K.PARTS.length;
|
|
28822
29412
|
const made = recordSpec(
|
|
28823
29413
|
THREE,
|
|
28824
29414
|
type,
|
|
28825
29415
|
root,
|
|
28826
29416
|
(A) => {
|
|
28827
|
-
const saved = { api0:
|
|
28828
|
-
|
|
28829
|
-
|
|
29417
|
+
const saved = { api0: shared2.api0, ctx: shared2.ctx };
|
|
29418
|
+
shared2.api0 = A;
|
|
29419
|
+
shared2.ctx = shared2.ctx ?? {};
|
|
28830
29420
|
try {
|
|
28831
29421
|
ent.f(root, A);
|
|
28832
29422
|
} finally {
|
|
28833
|
-
|
|
28834
|
-
|
|
29423
|
+
shared2.api0 = saved.api0;
|
|
29424
|
+
shared2.ctx = saved.ctx;
|
|
28835
29425
|
}
|
|
28836
29426
|
},
|
|
28837
29427
|
{ materials: { plain: plain2, ...o.materials }, chairs: o.chairs, carcass: SHELVING.test(type) }
|
|
@@ -29400,7 +29990,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
29400
29990
|
const provider = options.provider ?? createFindsProvider(catalog);
|
|
29401
29991
|
const items = catalog.list();
|
|
29402
29992
|
const categories = [...ITEM_CATEGORIES.map((c) => c.id), ...[...catalog.categories.keys()].filter((id) => !ITEM_CATEGORIES.some((c) => c.id === id))].filter((id) => items.some((item) => item.category === id));
|
|
29403
|
-
const
|
|
29993
|
+
const openerOf = (item) => {
|
|
29994
|
+
const id = item.seal?.openWith?.find((tool2) => catalog.has(tool2));
|
|
29995
|
+
return id === void 0 ? void 0 : catalog.get(id);
|
|
29996
|
+
};
|
|
29997
|
+
const laid = items.flatMap((item) => {
|
|
29998
|
+
const opener = openerOf(item);
|
|
29999
|
+
return opener ? [item, { id: opener.id, category: item.category, size: opener.size }] : [item];
|
|
30000
|
+
});
|
|
30001
|
+
const shelves = shelvesLayout(laid, categories);
|
|
29404
30002
|
const showcase = listItemModels().map((id) => ({ id, size: sizeOfModel(id), def: catalog.has(id) ? catalog.get(id) : void 0 }));
|
|
29405
30003
|
const state = {
|
|
29406
30004
|
category: CATEGORY_ALL,
|
|
@@ -29451,12 +30049,27 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
29451
30049
|
const contents = itemContents(subject);
|
|
29452
30050
|
return contents ? { fluid: { container: contents.container, part: SHELL_PART_ID } } : {};
|
|
29453
30051
|
};
|
|
30052
|
+
const sealOf = (def, fluid) => {
|
|
30053
|
+
const model = def.model;
|
|
30054
|
+
if (!def.seal || model === void 0 || !itemOpening(model)) return fluid;
|
|
30055
|
+
const openWith = def.seal.openWith ? [...def.seal.openWith, ...def.seal.openWith.map((id) => `${ITEM_PREFIX}${id}`)] : void 0;
|
|
30056
|
+
const seal = {
|
|
30057
|
+
...def.seal,
|
|
30058
|
+
...openWith ? { openWith } : {},
|
|
30059
|
+
open: (root) => void (latestTHREE && openItem(latestTHREE, root, model)),
|
|
30060
|
+
contents: (root, share) => setOpeningContents(root, share),
|
|
30061
|
+
// a screw cap is turned off by the other hand before the first bite or sip
|
|
30062
|
+
...itemOpening(model)?.style === "screw_cap" ? { openUse: "unscrew", turn: (root, state2) => void turnItem(root, model, state2) } : {}
|
|
30063
|
+
};
|
|
30064
|
+
const eaten = def.category === "food" && fluid.fluid ? { fluid: { ...fluid.fluid, uses: ["eat", "pour_out"] } } : fluid;
|
|
30065
|
+
return { ...eaten, seal };
|
|
30066
|
+
};
|
|
29454
30067
|
const itemOf = (def) => ({
|
|
29455
30068
|
id: `${ITEM_PREFIX}${def.id}`,
|
|
29456
30069
|
name: nameOf(def),
|
|
29457
30070
|
movable: true,
|
|
29458
30071
|
thumbnail: itemThumbnailSvg(drawable(def)),
|
|
29459
|
-
...fluidOf({ ...def.model === void 0 ? {} : { model: def.model }, size: def.size, weight: def.weight }),
|
|
30072
|
+
...sealOf(def, fluidOf({ ...def.model === void 0 ? {} : { model: def.model }, size: def.size, weight: def.weight })),
|
|
29460
30073
|
build: (THREE) => {
|
|
29461
30074
|
const T2 = THREE;
|
|
29462
30075
|
latestTHREE = T2;
|
|
@@ -29553,9 +30166,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
29553
30166
|
}
|
|
29554
30167
|
};
|
|
29555
30168
|
const clearBoxes = () => {
|
|
29556
|
-
|
|
29557
|
-
box4.parent?.remove(box4);
|
|
29558
|
-
}
|
|
30169
|
+
discardObject3D(boxes);
|
|
29559
30170
|
boxes = [];
|
|
29560
30171
|
};
|
|
29561
30172
|
const applyBoxes = () => {
|
|
@@ -29574,7 +30185,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
29574
30185
|
};
|
|
29575
30186
|
const clearFinds = () => {
|
|
29576
30187
|
if (findsGroup) {
|
|
29577
|
-
|
|
30188
|
+
discardObject3D(findsGroup);
|
|
29578
30189
|
findsGroup = null;
|
|
29579
30190
|
}
|
|
29580
30191
|
};
|
|
@@ -29820,7 +30431,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
29820
30431
|
id: "modeled",
|
|
29821
30432
|
name: text.metrics.modeled,
|
|
29822
30433
|
read: () => {
|
|
29823
|
-
const shown = visibleEntries().filter((entry2) => entry2.group === "shelf");
|
|
30434
|
+
const shown = [...new Map(visibleEntries().filter((entry2) => entry2.group === "shelf").map((entry2) => [entry2.itemId, entry2])).values()];
|
|
29824
30435
|
return `${shown.filter((entry2) => entry2.kind === "model").length}/${shown.length}`;
|
|
29825
30436
|
}
|
|
29826
30437
|
},
|
|
@@ -29832,7 +30443,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
29832
30443
|
latestTHREE = lent.THREE;
|
|
29833
30444
|
const offChange = lent.bench?.onChange(onChange);
|
|
29834
30445
|
const offFrame = lent.onFrame((dt) => {
|
|
29835
|
-
for (
|
|
30446
|
+
for (let i = entries2.length - 1; i >= 0; i--) if (!entries2[i].root.parent) entries2.splice(i, 1);
|
|
30447
|
+
for (let i = shelfRoots.length - 1; i >= 0; i--) if (!shelfRoots[i].parent) shelfRoots.splice(i, 1);
|
|
30448
|
+
for (const entry2 of entries2) if (entry2.group === "showcase") entry2.root.rotation.y += dt * SPIN;
|
|
29836
30449
|
});
|
|
29837
30450
|
return () => {
|
|
29838
30451
|
offChange?.();
|