@adatechnology/game-floorplan-three 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +11 -1
- package/dist/index.global.js +285 -68
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +98 -24
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -66,8 +66,8 @@ function createTranslator(locale) {
|
|
|
66
66
|
var OPEN_ROOM_TYPES = /* @__PURE__ */ new Set(["balcony", "terrace", "veranda", "balcony_gourmet"]);
|
|
67
67
|
var rectsOf = (c) => c.parts && c.parts.length ? c.parts : [[c.u0, c.v0, c.u1, c.v1]];
|
|
68
68
|
var isOpenArea = (c) => OPEN_ROOM_TYPES.has(c.type) || c.outdoor === true;
|
|
69
|
-
function planLod(
|
|
70
|
-
const l =
|
|
69
|
+
function planLod(houses2, focus, budget) {
|
|
70
|
+
const l = houses2.map((c) => ({ c, d: c.distance(focus), n0: c.stats.drawCalls, n1: c.stats.drawCallsLOD1, level: 0 })).sort((a, b) => a.d - b.d);
|
|
71
71
|
let total = l.reduce((s, x) => s + x.n0, 0);
|
|
72
72
|
for (let i = l.length - 1; i >= 0 && total > budget; i--) {
|
|
73
73
|
total -= l[i].n0 - l[i].n1;
|
|
@@ -5872,12 +5872,12 @@ function installLightsRoomLight(K, shared) {
|
|
|
5872
5872
|
A.invalidate = () => {
|
|
5873
5873
|
for (let i = 0; i < NS; i++) PL[i].shadow.needsUpdate = true;
|
|
5874
5874
|
};
|
|
5875
|
-
A.update = function(
|
|
5875
|
+
A.update = function(houses2, focus, op) {
|
|
5876
5876
|
op = op || {};
|
|
5877
|
-
|
|
5877
|
+
houses2 = (Array.isArray(houses2) ? houses2 : [houses2]).filter(Boolean);
|
|
5878
5878
|
_f.set(focus.x, focus.y, focus.z);
|
|
5879
5879
|
const rooms = [], exterior = [];
|
|
5880
|
-
for (const house of
|
|
5880
|
+
for (const house of houses2) {
|
|
5881
5881
|
if (house.group && !house.group.visible) continue;
|
|
5882
5882
|
house.house.updateMatrixWorld(true);
|
|
5883
5883
|
const M = house.house.matrixWorld, by = /* @__PURE__ */ new Map();
|
|
@@ -6267,7 +6267,12 @@ function installDestructionBreach(K, _shared) {
|
|
|
6267
6267
|
}
|
|
6268
6268
|
return null;
|
|
6269
6269
|
};
|
|
6270
|
-
|
|
6270
|
+
const local = (p) => {
|
|
6271
|
+
house.updateMatrixWorld(true);
|
|
6272
|
+
const v = house.worldToLocal(tmp.p.set(p[0], p[1], p[2]));
|
|
6273
|
+
return [v.x, v.y, v.z];
|
|
6274
|
+
};
|
|
6275
|
+
function courses(part, units, opening, chips, paint) {
|
|
6271
6276
|
const [u0, v0, u1, v1] = part.aabb;
|
|
6272
6277
|
const alongU = u1 - u0 >= v1 - v0;
|
|
6273
6278
|
const len = alongU ? u1 - u0 : v1 - v0;
|
|
@@ -6291,23 +6296,39 @@ function installDestructionBreach(K, _shared) {
|
|
|
6291
6296
|
const x = alongU ? u0 + mid : (u0 + u1) / 2;
|
|
6292
6297
|
const z = alongU ? (v0 + v1) / 2 : v0 + mid;
|
|
6293
6298
|
const y = part.y0 + (r + 0.5) * rowH;
|
|
6294
|
-
const d = Math.hypot(x - opening.center[0], y - opening.center[1], z - opening.center[2]);
|
|
6295
|
-
if (d < opening.radius) continue;
|
|
6296
|
-
|
|
6299
|
+
const d = opening ? Math.hypot(x - opening.center[0], y - opening.center[1], z - opening.center[2]) : Infinity;
|
|
6300
|
+
if (opening && d < opening.radius) continue;
|
|
6301
|
+
const gone = (c) => Math.abs(c[1] - y) <= rowH / 2 && (alongU ? c[0] >= u0 + a && c[0] <= u0 + b : c[2] >= v0 + a && c[2] <= v0 + b);
|
|
6302
|
+
if (chips.some(gone)) continue;
|
|
6303
|
+
const near = opening && d < opening.radius + 0.25 || chips.some((c) => Math.hypot(c[0] - x, c[1] - y, c[2] - z) < 0.15);
|
|
6304
|
+
list.push({ x, y, z, sx: alongU ? b - a : thick, sy: rowH, sz: alongU ? thick : b - a, colour: near || paint === null ? edge : paint });
|
|
6297
6305
|
}
|
|
6298
6306
|
}
|
|
6299
6307
|
return list;
|
|
6300
6308
|
}
|
|
6301
|
-
function
|
|
6302
|
-
if (lod !== 0
|
|
6303
|
-
const part = structure.byId.get(
|
|
6304
|
-
const spec = opts.spec()?.parts?.find((q) => q.id ===
|
|
6309
|
+
function draw2(partId, change) {
|
|
6310
|
+
if (lod !== 0) return false;
|
|
6311
|
+
const part = structure.byId.get(partId);
|
|
6312
|
+
const spec = opts.spec()?.parts?.find((q) => q.id === partId);
|
|
6305
6313
|
if (!part || !spec || !spec.units) return false;
|
|
6306
|
-
|
|
6307
|
-
if (!
|
|
6308
|
-
|
|
6314
|
+
let view = views.get(partId);
|
|
6315
|
+
if (!view) {
|
|
6316
|
+
const items = structure.meshesOf(partId).filter((it) => it.mesh);
|
|
6317
|
+
if (!items.length) return false;
|
|
6318
|
+
view = { mesh: null, saved: null, items, paint: wallColour(items), units: 0, opening: null, chips: [] };
|
|
6319
|
+
}
|
|
6320
|
+
if (change.opening) {
|
|
6321
|
+
if (view.opening) return false;
|
|
6322
|
+
view.opening = { center: local(change.opening.center), radius: change.opening.radius };
|
|
6323
|
+
}
|
|
6324
|
+
if (change.chip) view.chips.push(local(change.chip));
|
|
6325
|
+
const list = courses(part, spec.units, view.opening, view.chips, view.paint);
|
|
6326
|
+
if (view.mesh) {
|
|
6327
|
+
view.mesh.removeFromParent();
|
|
6328
|
+
view.mesh.dispose();
|
|
6329
|
+
}
|
|
6309
6330
|
const mesh = new THREE.InstancedMesh(unitGeometry, unitMaterial, Math.max(1, list.length));
|
|
6310
|
-
mesh.name = "breach:" +
|
|
6331
|
+
mesh.name = "breach:" + partId;
|
|
6311
6332
|
list.forEach((u, i) => {
|
|
6312
6333
|
tmp.m.compose(tmp.p.set(u.x, u.y, u.z), tmp.q.identity(), tmp.s.set(u.sx, u.sy, u.sz));
|
|
6313
6334
|
mesh.setMatrixAt(i, tmp.m);
|
|
@@ -6319,8 +6340,10 @@ function installDestructionBreach(K, _shared) {
|
|
|
6319
6340
|
mesh.castShadow = true;
|
|
6320
6341
|
mesh.receiveShadow = true;
|
|
6321
6342
|
house.add(mesh);
|
|
6322
|
-
|
|
6323
|
-
|
|
6343
|
+
if (!view.saved) view.saved = view.items.map((it) => ({ it, v0: it.v0, data: collapseRange(it.mesh, it.v0, it.v1) }));
|
|
6344
|
+
view.mesh = mesh;
|
|
6345
|
+
view.units = list.length;
|
|
6346
|
+
views.set(partId, view);
|
|
6324
6347
|
invalidate();
|
|
6325
6348
|
invalidateShadow();
|
|
6326
6349
|
return true;
|
|
@@ -6334,7 +6357,11 @@ function installDestructionBreach(K, _shared) {
|
|
|
6334
6357
|
return {
|
|
6335
6358
|
/** Handles a `stage` event of the house's object. Returns true when the wall was redrawn as courses. */
|
|
6336
6359
|
stage(event) {
|
|
6337
|
-
return event.stage === 2 ?
|
|
6360
|
+
return event.stage === 2 && !!event.opening ? draw2(event.part, { opening: event.opening }) : false;
|
|
6361
|
+
},
|
|
6362
|
+
/** Handles a `chip` event: the unit that came out leaves a gap in the courses. Returns true when the wall was redrawn. */
|
|
6363
|
+
chip(event) {
|
|
6364
|
+
return draw2(event.part, { chip: event.center });
|
|
6338
6365
|
},
|
|
6339
6366
|
/** The part broke or fell: the courses go (the plain range stays collapsed, the renderer hides the part). */
|
|
6340
6367
|
drop(partId) {
|
|
@@ -6566,6 +6593,9 @@ function installDestructionWorld(K, shared) {
|
|
|
6566
6593
|
case "stage":
|
|
6567
6594
|
breach.stage(e);
|
|
6568
6595
|
break;
|
|
6596
|
+
case "chip":
|
|
6597
|
+
breach.chip(e);
|
|
6598
|
+
break;
|
|
6569
6599
|
case "collapse":
|
|
6570
6600
|
for (const id of e.parts) {
|
|
6571
6601
|
breach.drop(id);
|
|
@@ -6620,6 +6650,32 @@ function installDestructionWorld(K, shared) {
|
|
|
6620
6650
|
if (D.active && D.world.has(D.id)) D.world.remove(D.id);
|
|
6621
6651
|
D.active = false;
|
|
6622
6652
|
};
|
|
6653
|
+
D.follow = (world, id, spec) => {
|
|
6654
|
+
D.spec = spec;
|
|
6655
|
+
const offFollow = world.on("*", (e) => {
|
|
6656
|
+
if (e.object !== id) return;
|
|
6657
|
+
switch (e.type) {
|
|
6658
|
+
case "stage":
|
|
6659
|
+
breach.stage(e);
|
|
6660
|
+
break;
|
|
6661
|
+
case "chip":
|
|
6662
|
+
breach.chip(e);
|
|
6663
|
+
break;
|
|
6664
|
+
case "fracture":
|
|
6665
|
+
breach.drop(e.part);
|
|
6666
|
+
break;
|
|
6667
|
+
case "collapse":
|
|
6668
|
+
for (const p of e.parts) breach.drop(p);
|
|
6669
|
+
break;
|
|
6670
|
+
default:
|
|
6671
|
+
break;
|
|
6672
|
+
}
|
|
6673
|
+
});
|
|
6674
|
+
return { restore: () => breach.restore(), dispose: () => {
|
|
6675
|
+
offFollow();
|
|
6676
|
+
breach.restore();
|
|
6677
|
+
} };
|
|
6678
|
+
};
|
|
6623
6679
|
D.piece = (id) => D.active ? D.world.part(D.id, id) : null;
|
|
6624
6680
|
D.state = () => D.active ? D.world.state(D.id) : null;
|
|
6625
6681
|
D.reset = () => {
|
|
@@ -8566,6 +8622,20 @@ import { inferJoints } from "@adatechnology/game-destruction";
|
|
|
8566
8622
|
import { markKitOrigin as markKitOrigin2 } from "@adatechnology/game-contracts";
|
|
8567
8623
|
import { residentialItems } from "@adatechnology/game-floorplan-residential";
|
|
8568
8624
|
var WOOD_THIN = 0.035;
|
|
8625
|
+
var SHELF_SPAN = 1.5;
|
|
8626
|
+
var SHELVING = /shelf|bookcase|rack/;
|
|
8627
|
+
function carcass(parts, drawn) {
|
|
8628
|
+
const all = [...drawn.values()];
|
|
8629
|
+
const width = Math.max(...all.map((p) => p.max[0])) - Math.min(...all.map((p) => p.min[0]));
|
|
8630
|
+
for (const part of parts) {
|
|
8631
|
+
if (LOOSE.has(part.material) || part.shape.kind !== "box" || part.rotation) continue;
|
|
8632
|
+
const [x, y, z] = part.shape.size;
|
|
8633
|
+
if (y >= x && y >= z) {
|
|
8634
|
+
if (z < x && x >= 0.6 * width) continue;
|
|
8635
|
+
part.structure = { role: "column" };
|
|
8636
|
+
} else if (y <= x && y <= z) part.structure = { role: "beam", maxSpan: SHELF_SPAN * Math.max(x, z) };
|
|
8637
|
+
}
|
|
8638
|
+
}
|
|
8569
8639
|
var FLOOR_TOUCH = 5e-3;
|
|
8570
8640
|
var LOOSE = /* @__PURE__ */ new Set(["paper"]);
|
|
8571
8641
|
var BASE_MATERIAL = {
|
|
@@ -8681,6 +8751,7 @@ function recordSpec(THREE, name, root, run, opts) {
|
|
|
8681
8751
|
if (area < 0.6 * footprint || p.max[1] < 0.2) continue;
|
|
8682
8752
|
if (!top || p.max[1] > top.y + 1e-6) top = { part: p.id, y: p.max[1] };
|
|
8683
8753
|
}
|
|
8754
|
+
if (opts.carcass) carcass(parts, byId);
|
|
8684
8755
|
const spec = { name, parts, joints, tags: ["furniture"] };
|
|
8685
8756
|
const colors = new Map(drawn.map((p) => [p.id, p.color]));
|
|
8686
8757
|
const build = (T3) => {
|
|
@@ -8724,7 +8795,7 @@ function furnitureSpec(THREE, type, opts = {}) {
|
|
|
8724
8795
|
if (w === void 0 || d === void 0 || h === void 0) throw new Error(`game-floorplan-three: furniture type "${type}" is not in the catalogue, so give w, d and h`);
|
|
8725
8796
|
const o = opts.options ?? {};
|
|
8726
8797
|
const seed = Math.round(opts.seed ?? 1);
|
|
8727
|
-
const plain =
|
|
8798
|
+
const plain = SHELVING.test(type) ? "paper" : "plastic";
|
|
8728
8799
|
const root = { x: seed, z: 0, ry: 0, w, d, h, y: 0, base: 0, palette: o.palette, seed: `furniture_${type}_${seed}` };
|
|
8729
8800
|
const { K, shared } = renderer.internals;
|
|
8730
8801
|
const before = K.PARTS.length;
|
|
@@ -8743,7 +8814,7 @@ function furnitureSpec(THREE, type, opts = {}) {
|
|
|
8743
8814
|
shared.ctx = saved.ctx;
|
|
8744
8815
|
}
|
|
8745
8816
|
},
|
|
8746
|
-
{ materials: { plain, ...o.materials }, chairs: o.chairs }
|
|
8817
|
+
{ materials: { plain, ...o.materials }, chairs: o.chairs, carcass: SHELVING.test(type) }
|
|
8747
8818
|
);
|
|
8748
8819
|
const spouts = K.PARTS.slice(before).filter((p) => p.type === "water_tap").map((p) => [p.pos[0] - root.x, p.pos[1], p.pos[2] - root.z]);
|
|
8749
8820
|
K.PARTS.length = before;
|
|
@@ -8811,7 +8882,9 @@ function wallPlan(options) {
|
|
|
8811
8882
|
function draw(THREE, plan, options) {
|
|
8812
8883
|
return create(THREE, { ...options, fleet: null }).build(plan, { quality: "game", terrain: false, noPerimeter: true, pieces: "meshes" });
|
|
8813
8884
|
}
|
|
8885
|
+
var houses = /* @__PURE__ */ new WeakMap();
|
|
8814
8886
|
function label(house) {
|
|
8887
|
+
houses.set(house.group, house);
|
|
8815
8888
|
for (const [id, items] of Object.entries(house.destruction.ranges())) {
|
|
8816
8889
|
for (const item of items) {
|
|
8817
8890
|
const object = item.isObject3D ? item : item.mesh;
|
|
@@ -8824,12 +8897,13 @@ function wallPiece(THREE, options) {
|
|
|
8824
8897
|
const plan = wallPlan(options);
|
|
8825
8898
|
const houseOptions = options.house ?? {};
|
|
8826
8899
|
const probe = draw(THREE, plan, { ...houseOptions, destruction: void 0, destructionRenderer: void 0 });
|
|
8827
|
-
const spec = probe.structure.spec(
|
|
8900
|
+
const spec = probe.structure.spec();
|
|
8828
8901
|
probe.dispose();
|
|
8829
8902
|
return {
|
|
8830
8903
|
plan,
|
|
8831
8904
|
spec,
|
|
8832
|
-
build: (T) => label(draw(T, plan, houseOptions))
|
|
8905
|
+
build: (T) => label(draw(T, plan, houseOptions)),
|
|
8906
|
+
follow: (root, world, objectId) => houses.get(root)?.destruction?.follow?.(world, objectId, spec) ?? null
|
|
8833
8907
|
};
|
|
8834
8908
|
}
|
|
8835
8909
|
export {
|