Add ES module: presets + Three.js footprint outline/plane helpers
This commit is contained in:
@@ -0,0 +1,71 @@
|
|||||||
|
// setFootprints.js
|
||||||
|
// LEGO Hidden Side set footprint presets for the Newbury Exhibit layout editor.
|
||||||
|
// Units: centimetres (1 Three.js unit = 1 cm). width = X extent, depth = Z extent.
|
||||||
|
// Fan/tribute project; not affiliated with or endorsed by the LEGO Group.
|
||||||
|
// Source: brickset.com/sets/theme-Hidden-Side (published model dimensions W x D x H;
|
||||||
|
// footprint = the two horizontal axes).
|
||||||
|
|
||||||
|
export const SET_FOOTPRINTS = [
|
||||||
|
{ setNumber: "70418", name: "J.B.'s Ghost Lab", width: 13, depth: 18, height: 9, year: 2019 },
|
||||||
|
{ setNumber: "70420", name: "Graveyard Mystery", width: 14, depth: 32, height: 10, year: 2019 },
|
||||||
|
{ setNumber: "70421", name: "El Fuego's Stunt Truck", width: 10, depth: 10, height: 17, year: 2019 },
|
||||||
|
{ setNumber: "70422", name: "Shrimp Shack Attack", width: 19, depth: 32, height: 10, year: 2019 },
|
||||||
|
{ setNumber: "70424", name: "Ghost Train Express", width: 14, depth: 61, height: 15, year: 2019 },
|
||||||
|
{ setNumber: "70425", name: "Newbury Haunted High School", width: 30, depth: 43, height: 26, year: 2019 },
|
||||||
|
{ setNumber: "70427", name: "Welcome to the Hidden Side", width: 17, depth: 22, height: 13, year: 2020 },
|
||||||
|
{ setNumber: "70428", name: "Jack's Beach Buggy", width: 10, depth: 11, height: 8, year: 2020 },
|
||||||
|
{ setNumber: "70429", name: "El Fuego's Stunt Plane", width: 22, depth: 22, height: 8, year: 2020 },
|
||||||
|
{ setNumber: "70430", name: "Newbury Subway", width: 15, depth: 26, height: 14, year: 2020 },
|
||||||
|
{ setNumber: "70431", name: "The Lighthouse of Darkness", width: 29, depth: 22, height: 18, year: 2020 },
|
||||||
|
{ setNumber: "70432", name: "Haunted Fairground", width: 28, depth: 35, height: 27, year: 2020 },
|
||||||
|
{ setNumber: "70433", name: "J.B.'s Submarine", width: 21, depth: 19, height: 10, year: 2020 },
|
||||||
|
{ setNumber: "70434", name: "Supernatural Race Car", width: 19, depth: 11, height: 7, year: 2020 },
|
||||||
|
{ setNumber: "70435", name: "Newbury Abandoned Prison", width: 19, depth: 30, height: 15, year: 2020 },
|
||||||
|
{ setNumber: "70437", name: "Mystery Castle (closed)", width: 34, depth: 31, height: 27, year: 2020 },
|
||||||
|
{ setNumber: "70437o", name: "Mystery Castle (open)", width: 45.5, depth: 26, height: 27, year: 2020 }
|
||||||
|
];
|
||||||
|
|
||||||
|
// Lookup by set number.
|
||||||
|
export function getFootprint(setNumber) {
|
||||||
|
return SET_FOOTPRINTS.find(s => s.setNumber === setNumber) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dropdown label helper: "70425 — Newbury Haunted High School (30 × 43 cm)".
|
||||||
|
export function footprintLabel(fp) {
|
||||||
|
return `${fp.setNumber} — ${fp.name} (${fp.width} × ${fp.depth} cm)`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build a THREE.LineLoop outlining the footprint on the table plane (Y = 0),
|
||||||
|
// centred on origin. Pass in your THREE namespace so this stays import-map friendly.
|
||||||
|
// Returns an object3D you can add to the scene and reposition via .position.
|
||||||
|
export function makeFootprintOutline(THREE, fp, { color = 0x51eaf1, y = 0.05 } = {}) {
|
||||||
|
const hw = fp.width / 2;
|
||||||
|
const hd = fp.depth / 2;
|
||||||
|
const pts = [
|
||||||
|
new THREE.Vector3(-hw, y, -hd),
|
||||||
|
new THREE.Vector3( hw, y, -hd),
|
||||||
|
new THREE.Vector3( hw, y, hd),
|
||||||
|
new THREE.Vector3(-hw, y, hd),
|
||||||
|
new THREE.Vector3(-hw, y, -hd)
|
||||||
|
];
|
||||||
|
const geom = new THREE.BufferGeometry().setFromPoints(pts);
|
||||||
|
const mat = new THREE.LineBasicMaterial({ color });
|
||||||
|
const loop = new THREE.Line(geom, mat);
|
||||||
|
loop.userData.setNumber = fp.setNumber;
|
||||||
|
loop.userData.footprint = { width: fp.width, depth: fp.depth };
|
||||||
|
return loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filled semi-transparent plane version (useful as a placement guide beneath the build).
|
||||||
|
export function makeFootprintPlane(THREE, fp, { color = 0x51eaf1, opacity = 0.12, y = 0.02 } = {}) {
|
||||||
|
const geom = new THREE.PlaneGeometry(fp.width, fp.depth);
|
||||||
|
const mat = new THREE.MeshBasicMaterial({
|
||||||
|
color, opacity, transparent: true, side: THREE.DoubleSide, depthWrite: false
|
||||||
|
});
|
||||||
|
const mesh = new THREE.Mesh(geom, mat);
|
||||||
|
mesh.rotation.x = -Math.PI / 2; // lay flat on the table
|
||||||
|
mesh.position.y = y;
|
||||||
|
mesh.userData.setNumber = fp.setNumber;
|
||||||
|
mesh.userData.footprint = { width: fp.width, depth: fp.depth };
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user