let-them-talk 5.2.5 → 5.4.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/CHANGELOG.md +3 -1
- package/README.md +158 -592
- package/SECURITY.md +3 -3
- package/USAGE.md +151 -0
- package/agent-contracts.js +447 -0
- package/api-agents.js +760 -0
- package/autonomy/decision-v2.js +380 -0
- package/autonomy/watchdog-policy.js +572 -0
- package/cli.js +454 -298
- package/conversation-templates/autonomous-feature.json +83 -22
- package/conversation-templates/code-review.json +69 -21
- package/conversation-templates/debug-squad.json +69 -21
- package/conversation-templates/feature-build.json +69 -21
- package/conversation-templates/research-write.json +69 -21
- package/dashboard.html +3148 -174
- package/dashboard.js +823 -786
- package/data-dir.js +58 -0
- package/docs/architecture/branch-semantics.md +157 -0
- package/docs/architecture/canonical-event-schema.md +88 -0
- package/docs/architecture/markdown-workspace.md +183 -0
- package/docs/architecture/runtime-contract.md +459 -0
- package/docs/architecture/runtime-migration-hardening.md +64 -0
- package/events/hooks.js +154 -0
- package/events/log.js +457 -0
- package/events/replay.js +33 -0
- package/events/schema.js +432 -0
- package/managed-team-integration.js +261 -0
- package/office/agents.js +704 -597
- package/office/animation.js +1 -1
- package/office/assets/arcade-cabinet.js +141 -0
- package/office/assets/archway.js +77 -0
- package/office/assets/bar-counter.js +91 -0
- package/office/assets/bar-stool.js +71 -0
- package/office/assets/beanbag.js +64 -0
- package/office/assets/bench.js +99 -0
- package/office/assets/bollard.js +87 -0
- package/office/assets/cactus.js +100 -0
- package/office/assets/carpet-tile.js +46 -0
- package/office/assets/chair.js +123 -0
- package/office/assets/chandelier.js +107 -0
- package/office/assets/coffee-machine.js +95 -0
- package/office/assets/coffee-table.js +81 -0
- package/office/assets/column.js +95 -0
- package/office/assets/desk-lamp.js +102 -0
- package/office/assets/desk.js +76 -0
- package/office/assets/dining-table.js +105 -0
- package/office/assets/door.js +70 -0
- package/office/assets/dual-monitor.js +72 -0
- package/office/assets/fence.js +76 -0
- package/office/assets/filing-cabinet.js +111 -0
- package/office/assets/floor-lamp.js +69 -0
- package/office/assets/floor-tile.js +54 -0
- package/office/assets/flower-pot.js +76 -0
- package/office/assets/foosball.js +95 -0
- package/office/assets/fridge.js +99 -0
- package/office/assets/gaming-chair.js +154 -0
- package/office/assets/gaming-desk.js +105 -0
- package/office/assets/glass-door.js +72 -0
- package/office/assets/glass-wall.js +64 -0
- package/office/assets/half-wall.js +49 -0
- package/office/assets/hanging-plant.js +112 -0
- package/office/assets/index.js +151 -0
- package/office/assets/indoor-tree.js +90 -0
- package/office/assets/l-sofa.js +153 -0
- package/office/assets/marble-floor.js +64 -0
- package/office/assets/materials.js +40 -0
- package/office/assets/meeting-table.js +88 -0
- package/office/assets/microwave.js +94 -0
- package/office/assets/monitor.js +67 -0
- package/office/assets/neon-strip.js +73 -0
- package/office/assets/painting.js +84 -0
- package/office/assets/palm-tree.js +108 -0
- package/office/assets/pc-tower.js +91 -0
- package/office/assets/pendant-light.js +67 -0
- package/office/assets/ping-pong.js +114 -0
- package/office/assets/plant.js +72 -0
- package/office/assets/planter-box.js +95 -0
- package/office/assets/pool-table.js +94 -0
- package/office/assets/printer.js +113 -0
- package/office/assets/reception-desk.js +133 -0
- package/office/assets/rug.js +78 -0
- package/office/assets/sculpture.js +85 -0
- package/office/assets/server-rack.js +98 -0
- package/office/assets/sink.js +109 -0
- package/office/assets/sofa.js +106 -0
- package/office/assets/speaker.js +83 -0
- package/office/assets/spotlight.js +83 -0
- package/office/assets/street-lamp.js +97 -0
- package/office/assets/trash-can.js +83 -0
- package/office/assets/treadmill.js +126 -0
- package/office/assets/trophy.js +89 -0
- package/office/assets/tv-screen.js +79 -0
- package/office/assets/vase.js +84 -0
- package/office/assets/wall-clock.js +84 -0
- package/office/assets/wall.js +53 -0
- package/office/assets/water-cooler.js +146 -0
- package/office/assets/whiteboard.js +115 -0
- package/office/assets.js +3 -431
- package/office/builder.js +791 -355
- package/office/campus-env.js +1012 -1119
- package/office/environment.js +2 -0
- package/office/gallery.js +997 -0
- package/office/index.js +165 -61
- package/office/navigation.js +173 -152
- package/office/player.js +178 -68
- package/office/robot-character.js +272 -0
- package/office/spectator-camera.js +33 -10
- package/office/state.js +2 -0
- package/office/world-save.js +35 -4
- package/package.json +57 -3
- package/providers/comfyui.js +383 -0
- package/providers/dalle.js +79 -0
- package/providers/gemini.js +181 -0
- package/providers/ollama.js +184 -0
- package/providers/replicate.js +115 -0
- package/providers/zai.js +183 -0
- package/runtime-descriptor.js +270 -0
- package/scripts/check-agent-contract-advisory.js +132 -0
- package/scripts/check-api-agent-parity.js +277 -0
- package/scripts/check-autonomy-v2-decision.js +207 -0
- package/scripts/check-autonomy-v2-execution.js +588 -0
- package/scripts/check-autonomy-v2-watchdog.js +224 -0
- package/scripts/check-branch-fork-snapshot.js +337 -0
- package/scripts/check-branch-isolation.js +787 -0
- package/scripts/check-branch-semantics.js +139 -0
- package/scripts/check-dashboard-control-plane.js +1304 -0
- package/scripts/check-docs-onboarding.js +490 -0
- package/scripts/check-event-schema.js +276 -0
- package/scripts/check-evidence-completion.js +239 -0
- package/scripts/check-invariants.js +992 -0
- package/scripts/check-lifecycle-hooks.js +525 -0
- package/scripts/check-managed-team-integration.js +166 -0
- package/scripts/check-markdown-workspace-export.js +548 -0
- package/scripts/check-markdown-workspace-safety.js +347 -0
- package/scripts/check-markdown-workspace.js +136 -0
- package/scripts/check-message-replay.js +429 -0
- package/scripts/check-migration-hardening.js +300 -0
- package/scripts/check-performance-indexing.js +272 -0
- package/scripts/check-provider-capabilities.js +316 -0
- package/scripts/check-runtime-contract.js +109 -0
- package/scripts/check-session-aware-context.js +172 -0
- package/scripts/check-session-lifecycle.js +210 -0
- package/scripts/export-markdown-workspace.js +84 -0
- package/scripts/fixtures/message-replay/clean.jsonl +2 -0
- package/scripts/fixtures/message-replay/corrupt-correction-payload.jsonl +1 -0
- package/scripts/fixtures/message-replay/corrupt-jsonl.jsonl +1 -0
- package/scripts/fixtures/message-replay/corrupt-payload.jsonl +1 -0
- package/scripts/fixtures/message-replay/out-of-order.jsonl +2 -0
- package/scripts/migrate-legacy-to-canonical.js +201 -0
- package/scripts/run-verification-suite.js +242 -0
- package/scripts/sync-packaged-docs.js +69 -0
- package/server.js +9546 -7214
- package/state/agents.js +161 -0
- package/state/canonical.js +3068 -0
- package/state/dashboard-queries.js +441 -0
- package/state/evidence.js +56 -0
- package/state/io.js +69 -0
- package/state/markdown-workspace.js +951 -0
- package/state/messages.js +669 -0
- package/state/sessions.js +683 -0
- package/state/tasks-workflows.js +92 -0
- package/templates/debate.json +2 -2
- package/templates/managed.json +4 -4
- package/templates/pair.json +2 -2
- package/templates/review.json +2 -2
- package/templates/team.json +3 -3
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'desk_lamp',
|
|
6
|
+
name: 'Desk Lamp',
|
|
7
|
+
category: 'lighting',
|
|
8
|
+
icon: 'DL',
|
|
9
|
+
gridW: 1, gridD: 1, height: 0.5,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
var chromeMat = PAL.chrome();
|
|
14
|
+
var darkMat = PAL.darkMetal();
|
|
15
|
+
var shadeMat = mat(0xe8dcc8, { transparent: true, opacity: 0.75, roughness: 0.45, side: THREE.DoubleSide });
|
|
16
|
+
|
|
17
|
+
// Clamp/weighted base block
|
|
18
|
+
var base = new THREE.Mesh(
|
|
19
|
+
new THREE.BoxGeometry(0.10, 0.035, 0.10),
|
|
20
|
+
darkMat
|
|
21
|
+
);
|
|
22
|
+
base.position.y = 0.018;
|
|
23
|
+
base.castShadow = true;
|
|
24
|
+
g.add(base);
|
|
25
|
+
|
|
26
|
+
// Base chrome collar
|
|
27
|
+
var baseCollar = new THREE.Mesh(
|
|
28
|
+
new THREE.CylinderGeometry(0.018, 0.018, 0.030, 12),
|
|
29
|
+
chromeMat
|
|
30
|
+
);
|
|
31
|
+
baseCollar.position.y = 0.050;
|
|
32
|
+
g.add(baseCollar);
|
|
33
|
+
|
|
34
|
+
// Lower arm (angled backward at ~70 deg)
|
|
35
|
+
var armLow = new THREE.Mesh(
|
|
36
|
+
new THREE.BoxGeometry(0.012, 0.22, 0.012),
|
|
37
|
+
chromeMat
|
|
38
|
+
);
|
|
39
|
+
armLow.position.set(0, 0.165, -0.06);
|
|
40
|
+
armLow.rotation.x = -0.35;
|
|
41
|
+
armLow.castShadow = true;
|
|
42
|
+
g.add(armLow);
|
|
43
|
+
|
|
44
|
+
// Elbow joint knuckle
|
|
45
|
+
var elbow = new THREE.Mesh(
|
|
46
|
+
new THREE.SphereGeometry(0.018, 14, 10),
|
|
47
|
+
chromeMat
|
|
48
|
+
);
|
|
49
|
+
elbow.position.set(0, 0.300, -0.11);
|
|
50
|
+
g.add(elbow);
|
|
51
|
+
|
|
52
|
+
// Upper arm (angled forward and up)
|
|
53
|
+
var armUp = new THREE.Mesh(
|
|
54
|
+
new THREE.BoxGeometry(0.010, 0.20, 0.010),
|
|
55
|
+
chromeMat
|
|
56
|
+
);
|
|
57
|
+
armUp.position.set(0, 0.415, -0.045);
|
|
58
|
+
armUp.rotation.x = 0.55;
|
|
59
|
+
armUp.castShadow = true;
|
|
60
|
+
g.add(armUp);
|
|
61
|
+
|
|
62
|
+
// Head joint
|
|
63
|
+
var headJoint = new THREE.Mesh(
|
|
64
|
+
new THREE.SphereGeometry(0.015, 12, 8),
|
|
65
|
+
chromeMat
|
|
66
|
+
);
|
|
67
|
+
headJoint.position.set(0, 0.500, 0.030);
|
|
68
|
+
g.add(headJoint);
|
|
69
|
+
|
|
70
|
+
// Shade (small cone, opening downward)
|
|
71
|
+
var shade = new THREE.Mesh(
|
|
72
|
+
new THREE.ConeGeometry(0.080, 0.095, 28, 1, true),
|
|
73
|
+
shadeMat
|
|
74
|
+
);
|
|
75
|
+
shade.position.set(0, 0.465, 0.030);
|
|
76
|
+
shade.rotation.x = Math.PI;
|
|
77
|
+
g.add(shade);
|
|
78
|
+
|
|
79
|
+
// Shade chrome rim
|
|
80
|
+
var shadeRim = new THREE.Mesh(
|
|
81
|
+
new THREE.TorusGeometry(0.078, 0.004, 8, 28),
|
|
82
|
+
chromeMat
|
|
83
|
+
);
|
|
84
|
+
shadeRim.position.set(0, 0.422, 0.030);
|
|
85
|
+
g.add(shadeRim);
|
|
86
|
+
|
|
87
|
+
// Warm bulb inside shade
|
|
88
|
+
var bulb = new THREE.Mesh(
|
|
89
|
+
new THREE.SphereGeometry(0.018, 12, 8),
|
|
90
|
+
mat(0xfff0cc, { emissive: 0xfff0cc, emissiveIntensity: 1.3, transparent: true, opacity: 0.90 })
|
|
91
|
+
);
|
|
92
|
+
bulb.position.set(0, 0.455, 0.030);
|
|
93
|
+
g.add(bulb);
|
|
94
|
+
|
|
95
|
+
// Point light
|
|
96
|
+
var light = new THREE.PointLight(0xffeedd, 0.2, 3);
|
|
97
|
+
light.position.set(0, 0.42, 0.030);
|
|
98
|
+
g.add(light);
|
|
99
|
+
|
|
100
|
+
return g;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'desk',
|
|
6
|
+
name: 'Desk',
|
|
7
|
+
category: 'furniture',
|
|
8
|
+
icon: 'Dk',
|
|
9
|
+
gridW: 2, gridD: 1, height: 0.76,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
// Tabletop
|
|
14
|
+
var top = new THREE.Mesh(
|
|
15
|
+
new THREE.BoxGeometry(2, 0.05, 0.9),
|
|
16
|
+
mat(0x1e2128, { roughness: 0.35, metalness: 0.05 })
|
|
17
|
+
);
|
|
18
|
+
top.position.y = 0.755;
|
|
19
|
+
top.castShadow = true;
|
|
20
|
+
top.receiveShadow = true;
|
|
21
|
+
g.add(top);
|
|
22
|
+
|
|
23
|
+
// Thin edge trim on front
|
|
24
|
+
var edgeTrim = new THREE.Mesh(
|
|
25
|
+
new THREE.BoxGeometry(2, 0.03, 0.02),
|
|
26
|
+
mat(0xd4af37, { roughness: 0.25, metalness: 0.75 })
|
|
27
|
+
);
|
|
28
|
+
edgeTrim.position.y = 0.73;
|
|
29
|
+
edgeTrim.position.z = 0.46;
|
|
30
|
+
g.add(edgeTrim);
|
|
31
|
+
|
|
32
|
+
// Left side panel (apron)
|
|
33
|
+
var leftApron = new THREE.Mesh(
|
|
34
|
+
new THREE.BoxGeometry(0.03, 0.12, 0.86),
|
|
35
|
+
mat(0x17191f, { roughness: 0.5 })
|
|
36
|
+
);
|
|
37
|
+
leftApron.position.set(-0.975, 0.665, 0);
|
|
38
|
+
leftApron.castShadow = true;
|
|
39
|
+
g.add(leftApron);
|
|
40
|
+
|
|
41
|
+
// Right side panel
|
|
42
|
+
var rightApron = leftApron.clone();
|
|
43
|
+
rightApron.position.x = 0.975;
|
|
44
|
+
g.add(rightApron);
|
|
45
|
+
|
|
46
|
+
// Back apron
|
|
47
|
+
var backApron = new THREE.Mesh(
|
|
48
|
+
new THREE.BoxGeometry(1.94, 0.12, 0.03),
|
|
49
|
+
mat(0x17191f, { roughness: 0.5 })
|
|
50
|
+
);
|
|
51
|
+
backApron.position.set(0, 0.665, -0.44);
|
|
52
|
+
g.add(backApron);
|
|
53
|
+
|
|
54
|
+
// 4 legs — dark metal, tapered feel via scale
|
|
55
|
+
var legMat = mat(0x2a2d35, { roughness: 0.4, metalness: 0.15 });
|
|
56
|
+
var legGeo = new THREE.BoxGeometry(0.07, 0.73, 0.07);
|
|
57
|
+
var positions = [[-0.92, 0.365, 0.38], [0.92, 0.365, 0.38], [-0.92, 0.365, -0.38], [0.92, 0.365, -0.38]];
|
|
58
|
+
positions.forEach(function(p) {
|
|
59
|
+
var leg = new THREE.Mesh(legGeo, legMat);
|
|
60
|
+
leg.position.set(p[0], p[1], p[2]);
|
|
61
|
+
leg.castShadow = true;
|
|
62
|
+
g.add(leg);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Floor glides (small feet pads)
|
|
66
|
+
var glideMat = mat(0x111111, { roughness: 0.9 });
|
|
67
|
+
var glideGeo = new THREE.CylinderGeometry(0.04, 0.04, 0.015, 8);
|
|
68
|
+
positions.forEach(function(p) {
|
|
69
|
+
var glide = new THREE.Mesh(glideGeo, glideMat);
|
|
70
|
+
glide.position.set(p[0], 0.008, p[2]);
|
|
71
|
+
g.add(glide);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return g;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'dining-table',
|
|
6
|
+
name: 'Dining Table',
|
|
7
|
+
category: 'furniture',
|
|
8
|
+
icon: 'DT',
|
|
9
|
+
gridW: 3, gridD: 2, height: 0.78,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
// Walnut tabletop
|
|
14
|
+
var top = new THREE.Mesh(
|
|
15
|
+
new THREE.BoxGeometry(3.0, 0.06, 1.2),
|
|
16
|
+
PAL.walnutDark()
|
|
17
|
+
);
|
|
18
|
+
top.position.y = 0.78;
|
|
19
|
+
top.castShadow = true;
|
|
20
|
+
top.receiveShadow = true;
|
|
21
|
+
g.add(top);
|
|
22
|
+
|
|
23
|
+
// Thin edge band (darker walnut contrast)
|
|
24
|
+
var edgeFront = new THREE.Mesh(
|
|
25
|
+
new THREE.BoxGeometry(3.0, 0.055, 0.018),
|
|
26
|
+
mat(0x2a1808, { roughness: 0.6 })
|
|
27
|
+
);
|
|
28
|
+
edgeFront.position.set(0, 0.778, 0.609);
|
|
29
|
+
g.add(edgeFront);
|
|
30
|
+
|
|
31
|
+
var edgeBack = edgeFront.clone();
|
|
32
|
+
edgeBack.position.z = -0.609;
|
|
33
|
+
g.add(edgeBack);
|
|
34
|
+
|
|
35
|
+
// Apron/torsion box under top
|
|
36
|
+
var apronFront = new THREE.Mesh(
|
|
37
|
+
new THREE.BoxGeometry(2.86, 0.09, 0.04),
|
|
38
|
+
PAL.walnutDark()
|
|
39
|
+
);
|
|
40
|
+
apronFront.position.set(0, 0.705, 0.54);
|
|
41
|
+
apronFront.castShadow = true;
|
|
42
|
+
g.add(apronFront);
|
|
43
|
+
|
|
44
|
+
var apronBack = apronFront.clone();
|
|
45
|
+
apronBack.position.z = -0.54;
|
|
46
|
+
g.add(apronBack);
|
|
47
|
+
|
|
48
|
+
var apronLeft = new THREE.Mesh(
|
|
49
|
+
new THREE.BoxGeometry(0.04, 0.09, 1.08),
|
|
50
|
+
PAL.walnutDark()
|
|
51
|
+
);
|
|
52
|
+
apronLeft.position.set(-1.43, 0.705, 0);
|
|
53
|
+
g.add(apronLeft);
|
|
54
|
+
|
|
55
|
+
var apronRight = apronLeft.clone();
|
|
56
|
+
apronRight.position.x = 1.43;
|
|
57
|
+
g.add(apronRight);
|
|
58
|
+
|
|
59
|
+
// 6 chrome legs in 3 pairs
|
|
60
|
+
var legMat = PAL.chrome();
|
|
61
|
+
var legGeo = new THREE.CylinderGeometry(0.038, 0.032, 0.75, 12);
|
|
62
|
+
var legPositions = [
|
|
63
|
+
[-1.32, -0.46], [-1.32, 0.46],
|
|
64
|
+
[0, -0.46], [0, 0.46],
|
|
65
|
+
[1.32, -0.46], [1.32, 0.46]
|
|
66
|
+
];
|
|
67
|
+
legPositions.forEach(function(p) {
|
|
68
|
+
var leg = new THREE.Mesh(legGeo, legMat);
|
|
69
|
+
leg.position.set(p[0], 0.375, p[1]);
|
|
70
|
+
leg.castShadow = true;
|
|
71
|
+
g.add(leg);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Horizontal stretcher bars connecting each pair
|
|
75
|
+
var stretchMat = PAL.chromeBrushed();
|
|
76
|
+
[[-1.32], [0], [1.32]].forEach(function(px) {
|
|
77
|
+
var bar = new THREE.Mesh(new THREE.BoxGeometry(0.03, 0.03, 0.9), stretchMat);
|
|
78
|
+
bar.position.set(px[0], 0.22, 0);
|
|
79
|
+
g.add(bar);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Longitudinal bars connecting front legs
|
|
83
|
+
var longBarFront = new THREE.Mesh(
|
|
84
|
+
new THREE.BoxGeometry(2.64, 0.025, 0.025),
|
|
85
|
+
stretchMat
|
|
86
|
+
);
|
|
87
|
+
longBarFront.position.set(0, 0.22, -0.46);
|
|
88
|
+
g.add(longBarFront);
|
|
89
|
+
|
|
90
|
+
var longBarBack = longBarFront.clone();
|
|
91
|
+
longBarBack.position.z = 0.46;
|
|
92
|
+
g.add(longBarBack);
|
|
93
|
+
|
|
94
|
+
// Floor glides
|
|
95
|
+
var glideMat = mat(0x111111, { roughness: 0.9 });
|
|
96
|
+
var glideGeo = new THREE.CylinderGeometry(0.04, 0.04, 0.012, 8);
|
|
97
|
+
legPositions.forEach(function(p) {
|
|
98
|
+
var glide = new THREE.Mesh(glideGeo, glideMat);
|
|
99
|
+
glide.position.set(p[0], 0.006, p[1]);
|
|
100
|
+
g.add(glide);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
return g;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'door',
|
|
6
|
+
name: 'Door',
|
|
7
|
+
category: 'structural',
|
|
8
|
+
icon: 'Dr',
|
|
9
|
+
gridW: 1, gridD: 1, height: 2.5,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
// Door slab — walnut
|
|
14
|
+
var slab = new THREE.Mesh(
|
|
15
|
+
new THREE.BoxGeometry(1, 2.5, 0.08),
|
|
16
|
+
PAL.walnutDark()
|
|
17
|
+
);
|
|
18
|
+
slab.castShadow = true;
|
|
19
|
+
slab.receiveShadow = true;
|
|
20
|
+
g.add(slab);
|
|
21
|
+
|
|
22
|
+
// Recessed panel (upper)
|
|
23
|
+
var panelU = new THREE.Mesh(
|
|
24
|
+
new THREE.BoxGeometry(0.75, 1.0, 0.01),
|
|
25
|
+
PAL.walnutLight()
|
|
26
|
+
);
|
|
27
|
+
panelU.position.y = 0.6;
|
|
28
|
+
panelU.position.z = 0.045;
|
|
29
|
+
g.add(panelU);
|
|
30
|
+
|
|
31
|
+
// Recessed panel (lower)
|
|
32
|
+
var panelL = new THREE.Mesh(
|
|
33
|
+
new THREE.BoxGeometry(0.75, 0.75, 0.01),
|
|
34
|
+
PAL.walnutLight()
|
|
35
|
+
);
|
|
36
|
+
panelL.position.y = -0.6;
|
|
37
|
+
panelL.position.z = 0.045;
|
|
38
|
+
g.add(panelL);
|
|
39
|
+
|
|
40
|
+
// Chrome handle bar
|
|
41
|
+
var handle = new THREE.Mesh(
|
|
42
|
+
new THREE.CylinderGeometry(0.018, 0.018, 0.12, 8),
|
|
43
|
+
PAL.chrome()
|
|
44
|
+
);
|
|
45
|
+
handle.rotation.z = Math.PI / 2;
|
|
46
|
+
handle.position.set(0.38, 0, 0.07);
|
|
47
|
+
handle.castShadow = true;
|
|
48
|
+
g.add(handle);
|
|
49
|
+
|
|
50
|
+
// Handle back plate
|
|
51
|
+
var plate = new THREE.Mesh(
|
|
52
|
+
new THREE.BoxGeometry(0.04, 0.18, 0.015),
|
|
53
|
+
PAL.chromeBrushed()
|
|
54
|
+
);
|
|
55
|
+
plate.position.set(0.38, 0, 0.048);
|
|
56
|
+
g.add(plate);
|
|
57
|
+
|
|
58
|
+
// Door frame surround
|
|
59
|
+
var frameMat = mat(0x1a1c22, { roughness: 0.6 });
|
|
60
|
+
var frameTop = new THREE.Mesh(new THREE.BoxGeometry(1.1, 0.07, 0.1), frameMat);
|
|
61
|
+
frameTop.position.y = 1.285;
|
|
62
|
+
g.add(frameTop);
|
|
63
|
+
var frameL = new THREE.Mesh(new THREE.BoxGeometry(0.07, 2.5, 0.1), frameMat);
|
|
64
|
+
frameL.position.x = -0.535;
|
|
65
|
+
g.add(frameL);
|
|
66
|
+
var frameR = frameL.clone(); frameR.position.x = 0.535; g.add(frameR);
|
|
67
|
+
|
|
68
|
+
return g;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'dual_monitor',
|
|
6
|
+
name: 'Dual Monitor',
|
|
7
|
+
category: 'tech',
|
|
8
|
+
icon: 'DM',
|
|
9
|
+
gridW: 1, gridD: 1, height: 0.5,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
var chromeMat = PAL.chrome();
|
|
14
|
+
var bezelMat = mat(0x111214, { roughness: 0.45, metalness: 0.10 });
|
|
15
|
+
var screenMat = mat(0x0a1628, { emissive: 0x1a4a8a, emissiveIntensity: 0.55, roughness: 0.05 });
|
|
16
|
+
|
|
17
|
+
// Build one monitor panel (reused twice)
|
|
18
|
+
function makePanel(xOffset) {
|
|
19
|
+
var grp = new THREE.Group();
|
|
20
|
+
|
|
21
|
+
var bezel = new THREE.Mesh(new THREE.BoxGeometry(0.44, 0.30, 0.025), bezelMat);
|
|
22
|
+
bezel.position.y = 0.38;
|
|
23
|
+
bezel.castShadow = true;
|
|
24
|
+
grp.add(bezel);
|
|
25
|
+
|
|
26
|
+
var screen = new THREE.Mesh(new THREE.BoxGeometry(0.38, 0.25, 0.010), screenMat);
|
|
27
|
+
screen.position.set(0, 0.38, 0.013);
|
|
28
|
+
grp.add(screen);
|
|
29
|
+
|
|
30
|
+
// thin side border accent
|
|
31
|
+
var accent = new THREE.Mesh(new THREE.BoxGeometry(0.005, 0.30, 0.026), chromeMat);
|
|
32
|
+
accent.position.set(0.22, 0.38, 0);
|
|
33
|
+
grp.add(accent);
|
|
34
|
+
|
|
35
|
+
grp.position.x = xOffset;
|
|
36
|
+
return grp;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
g.add(makePanel(-0.235));
|
|
40
|
+
g.add(makePanel( 0.235));
|
|
41
|
+
|
|
42
|
+
// Shared horizontal arm bar
|
|
43
|
+
var arm = new THREE.Mesh(new THREE.BoxGeometry(0.52, 0.022, 0.022), chromeMat);
|
|
44
|
+
arm.position.y = 0.22;
|
|
45
|
+
arm.castShadow = true;
|
|
46
|
+
g.add(arm);
|
|
47
|
+
|
|
48
|
+
// Vertical pole from arm to base
|
|
49
|
+
var pole = new THREE.Mesh(new THREE.BoxGeometry(0.025, 0.22, 0.025), chromeMat);
|
|
50
|
+
pole.position.y = 0.11;
|
|
51
|
+
pole.castShadow = true;
|
|
52
|
+
g.add(pole);
|
|
53
|
+
|
|
54
|
+
// Heavy weighted base
|
|
55
|
+
var base = new THREE.Mesh(new THREE.BoxGeometry(0.28, 0.028, 0.18), chromeMat);
|
|
56
|
+
base.position.y = 0.014;
|
|
57
|
+
base.castShadow = true;
|
|
58
|
+
g.add(base);
|
|
59
|
+
|
|
60
|
+
// Two LED dots (one per screen)
|
|
61
|
+
[-0.235, 0.235].forEach(function(x) {
|
|
62
|
+
var led = new THREE.Mesh(
|
|
63
|
+
new THREE.SphereGeometry(0.007, 8, 8),
|
|
64
|
+
mat(0x00e5ff, { emissive: 0x00e5ff, emissiveIntensity: 1.0 })
|
|
65
|
+
);
|
|
66
|
+
led.position.set(x + 0.16, 0.215, 0.014);
|
|
67
|
+
g.add(led);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
return g;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'fence',
|
|
6
|
+
name: 'Metal Fence',
|
|
7
|
+
category: 'exterior',
|
|
8
|
+
icon: 'Fn',
|
|
9
|
+
gridW: 2, gridD: 1, height: 1.2,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
var chrome = PAL.chrome();
|
|
14
|
+
var darkMetal = PAL.darkMetal();
|
|
15
|
+
|
|
16
|
+
// Left post
|
|
17
|
+
var postGeo = new THREE.BoxGeometry(0.048, 1.20, 0.048);
|
|
18
|
+
var leftPost = new THREE.Mesh(postGeo, chrome);
|
|
19
|
+
leftPost.position.set(-0.97, 0.60, 0);
|
|
20
|
+
leftPost.castShadow = true;
|
|
21
|
+
g.add(leftPost);
|
|
22
|
+
|
|
23
|
+
// Right post
|
|
24
|
+
var rightPost = leftPost.clone();
|
|
25
|
+
rightPost.position.x = 0.97;
|
|
26
|
+
g.add(rightPost);
|
|
27
|
+
|
|
28
|
+
// Post caps (small pyramidal tops)
|
|
29
|
+
var capGeo = new THREE.CylinderGeometry(0.0, 0.034, 0.055, 4);
|
|
30
|
+
var capMat = PAL.chromeBrushed();
|
|
31
|
+
[-0.97, 0.97].forEach(function(x) {
|
|
32
|
+
var cap = new THREE.Mesh(capGeo, capMat);
|
|
33
|
+
cap.position.set(x, 1.228, 0);
|
|
34
|
+
g.add(cap);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// 4 horizontal bars at varying heights
|
|
38
|
+
var barGeo = new THREE.BoxGeometry(1.94, 0.030, 0.030);
|
|
39
|
+
[0.16, 0.52, 0.88, 1.14].forEach(function(y) {
|
|
40
|
+
var bar = new THREE.Mesh(barGeo, darkMetal);
|
|
41
|
+
bar.position.y = y;
|
|
42
|
+
g.add(bar);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Vertical pickets (7 between posts)
|
|
46
|
+
var picketMat = darkMetal;
|
|
47
|
+
var picketGeo = new THREE.BoxGeometry(0.022, 0.98, 0.022);
|
|
48
|
+
var picketCount = 7;
|
|
49
|
+
for (var i = 0; i < picketCount; i++) {
|
|
50
|
+
var x = -0.84 + (i / (picketCount - 1)) * 1.68;
|
|
51
|
+
var picket = new THREE.Mesh(picketGeo, picketMat);
|
|
52
|
+
picket.position.set(x, 0.60, 0);
|
|
53
|
+
picket.castShadow = true;
|
|
54
|
+
g.add(picket);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Picket spear tips (sharp top points)
|
|
58
|
+
var spearGeo = new THREE.CylinderGeometry(0.0, 0.016, 0.055, 4);
|
|
59
|
+
for (var j = 0; j < picketCount; j++) {
|
|
60
|
+
var sx = -0.84 + (j / (picketCount - 1)) * 1.68;
|
|
61
|
+
var spear = new THREE.Mesh(spearGeo, PAL.chrome());
|
|
62
|
+
spear.position.set(sx, 1.12, 0);
|
|
63
|
+
g.add(spear);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Base footer (ground anchor bar)
|
|
67
|
+
var footer = new THREE.Mesh(
|
|
68
|
+
new THREE.BoxGeometry(1.98, 0.040, 0.06),
|
|
69
|
+
mat(0x0e1014, { roughness: 0.60 })
|
|
70
|
+
);
|
|
71
|
+
footer.position.y = 0.020;
|
|
72
|
+
g.add(footer);
|
|
73
|
+
|
|
74
|
+
return g;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'filing-cabinet',
|
|
6
|
+
name: 'Filing Cabinet',
|
|
7
|
+
category: 'office',
|
|
8
|
+
icon: 'FC',
|
|
9
|
+
gridW: 1, gridD: 1, height: 1.2,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
// Main body
|
|
14
|
+
var body = new THREE.Mesh(
|
|
15
|
+
new THREE.BoxGeometry(0.5, 1.2, 0.5),
|
|
16
|
+
mat(0x1e2128, { roughness: 0.55, metalness: 0.20 })
|
|
17
|
+
);
|
|
18
|
+
body.position.y = 0.6;
|
|
19
|
+
body.castShadow = true;
|
|
20
|
+
body.receiveShadow = true;
|
|
21
|
+
g.add(body);
|
|
22
|
+
|
|
23
|
+
// Top cap
|
|
24
|
+
var topCap = new THREE.Mesh(
|
|
25
|
+
new THREE.BoxGeometry(0.52, 0.02, 0.52),
|
|
26
|
+
mat(0x252830, { roughness: 0.4, metalness: 0.25 })
|
|
27
|
+
);
|
|
28
|
+
topCap.position.y = 1.21;
|
|
29
|
+
topCap.castShadow = true;
|
|
30
|
+
g.add(topCap);
|
|
31
|
+
|
|
32
|
+
// 3 drawer faces
|
|
33
|
+
var drawerMat = mat(0x252830, { roughness: 0.45, metalness: 0.22 });
|
|
34
|
+
var handleMat = PAL.chrome();
|
|
35
|
+
var drawerHeights = [0.22, 0.62, 1.02];
|
|
36
|
+
|
|
37
|
+
drawerHeights.forEach(function(y) {
|
|
38
|
+
// Drawer face panel
|
|
39
|
+
var drawer = new THREE.Mesh(
|
|
40
|
+
new THREE.BoxGeometry(0.46, 0.34, 0.01),
|
|
41
|
+
drawerMat
|
|
42
|
+
);
|
|
43
|
+
drawer.position.set(0, y, 0.256);
|
|
44
|
+
g.add(drawer);
|
|
45
|
+
|
|
46
|
+
// Drawer inset shadow line (top)
|
|
47
|
+
var topLine = new THREE.Mesh(
|
|
48
|
+
new THREE.BoxGeometry(0.46, 0.008, 0.012),
|
|
49
|
+
mat(0x111318, { roughness: 0.8 })
|
|
50
|
+
);
|
|
51
|
+
topLine.position.set(0, y + 0.171, 0.257);
|
|
52
|
+
g.add(topLine);
|
|
53
|
+
|
|
54
|
+
// Drawer inset shadow line (bottom)
|
|
55
|
+
var botLine = topLine.clone();
|
|
56
|
+
botLine.position.y = y - 0.171;
|
|
57
|
+
g.add(botLine);
|
|
58
|
+
|
|
59
|
+
// Handle bar
|
|
60
|
+
var handle = new THREE.Mesh(
|
|
61
|
+
new THREE.BoxGeometry(0.22, 0.022, 0.022),
|
|
62
|
+
handleMat
|
|
63
|
+
);
|
|
64
|
+
handle.position.set(0, y, 0.268);
|
|
65
|
+
handle.castShadow = true;
|
|
66
|
+
g.add(handle);
|
|
67
|
+
|
|
68
|
+
// Handle end brackets
|
|
69
|
+
var bracket = new THREE.Mesh(
|
|
70
|
+
new THREE.BoxGeometry(0.022, 0.04, 0.025),
|
|
71
|
+
handleMat
|
|
72
|
+
);
|
|
73
|
+
bracket.position.set(-0.11, y - 0.01, 0.266);
|
|
74
|
+
g.add(bracket);
|
|
75
|
+
var bracketR = bracket.clone();
|
|
76
|
+
bracketR.position.x = 0.11;
|
|
77
|
+
g.add(bracketR);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Lock cylinder on top drawer
|
|
81
|
+
var lock = new THREE.Mesh(
|
|
82
|
+
new THREE.CylinderGeometry(0.015, 0.015, 0.015, 12),
|
|
83
|
+
mat(0xb8860b, { roughness: 0.3, metalness: 0.8 })
|
|
84
|
+
);
|
|
85
|
+
lock.rotation.x = Math.PI / 2;
|
|
86
|
+
lock.position.set(0.14, 1.02, 0.258);
|
|
87
|
+
g.add(lock);
|
|
88
|
+
|
|
89
|
+
// Side ventilation slots (decorative lines)
|
|
90
|
+
var slotMat = mat(0x17191f, { roughness: 0.8 });
|
|
91
|
+
[0.2, 0.6, 1.0].forEach(function(y) {
|
|
92
|
+
var slot = new THREE.Mesh(new THREE.BoxGeometry(0.008, 0.04, 0.42), slotMat);
|
|
93
|
+
slot.position.set(-0.252, y, 0);
|
|
94
|
+
g.add(slot);
|
|
95
|
+
var slotR = slot.clone();
|
|
96
|
+
slotR.position.x = 0.252;
|
|
97
|
+
g.add(slotR);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Small base feet
|
|
101
|
+
var footMat = mat(0x111111, { roughness: 0.9 });
|
|
102
|
+
var footGeo = new THREE.BoxGeometry(0.08, 0.04, 0.08);
|
|
103
|
+
[[-0.18, -0.18], [0.18, -0.18], [-0.18, 0.18], [0.18, 0.18]].forEach(function(p) {
|
|
104
|
+
var foot = new THREE.Mesh(footGeo, footMat);
|
|
105
|
+
foot.position.set(p[0], 0.02, p[1]);
|
|
106
|
+
g.add(foot);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
return g;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'floor_lamp',
|
|
6
|
+
name: 'Floor Lamp',
|
|
7
|
+
category: 'lighting',
|
|
8
|
+
icon: 'FL',
|
|
9
|
+
gridW: 1, gridD: 1, height: 1.8,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
var poleMat = PAL.chromeBrushed();
|
|
14
|
+
var shadeMat = mat(0xf5e8d0, { transparent: true, opacity: 0.70, roughness: 0.50, side: THREE.DoubleSide });
|
|
15
|
+
var baseMat = mat(0x1a1c22, { roughness: 0.40, metalness: 0.55 });
|
|
16
|
+
|
|
17
|
+
// Round weighted base disk
|
|
18
|
+
var base = new THREE.Mesh(new THREE.CylinderGeometry(0.20, 0.22, 0.04, 32), baseMat);
|
|
19
|
+
base.position.y = 0.020;
|
|
20
|
+
base.castShadow = true;
|
|
21
|
+
g.add(base);
|
|
22
|
+
|
|
23
|
+
// Base rim chrome ring
|
|
24
|
+
var rim = new THREE.Mesh(new THREE.TorusGeometry(0.21, 0.010, 8, 32), PAL.chrome());
|
|
25
|
+
rim.position.y = 0.040;
|
|
26
|
+
g.add(rim);
|
|
27
|
+
|
|
28
|
+
// Tall pole (two sections for realism)
|
|
29
|
+
var poleBot = new THREE.Mesh(new THREE.CylinderGeometry(0.016, 0.018, 1.05, 16), poleMat);
|
|
30
|
+
poleBot.position.y = 0.065 + 0.525;
|
|
31
|
+
poleBot.castShadow = true;
|
|
32
|
+
g.add(poleBot);
|
|
33
|
+
|
|
34
|
+
var poleTop = new THREE.Mesh(new THREE.CylinderGeometry(0.012, 0.016, 0.65, 16), poleMat);
|
|
35
|
+
poleTop.position.y = 0.065 + 1.05 + 0.325;
|
|
36
|
+
poleTop.castShadow = true;
|
|
37
|
+
g.add(poleTop);
|
|
38
|
+
|
|
39
|
+
// Pole join collar
|
|
40
|
+
var collar = new THREE.Mesh(new THREE.CylinderGeometry(0.022, 0.022, 0.030, 16), PAL.chrome());
|
|
41
|
+
collar.position.y = 0.065 + 1.05;
|
|
42
|
+
g.add(collar);
|
|
43
|
+
|
|
44
|
+
// Cone shade
|
|
45
|
+
var shade = new THREE.Mesh(new THREE.ConeGeometry(0.22, 0.28, 32, 1, true), shadeMat);
|
|
46
|
+
shade.position.y = 1.65;
|
|
47
|
+
g.add(shade);
|
|
48
|
+
|
|
49
|
+
// Shade top cap
|
|
50
|
+
var topCap = new THREE.Mesh(new THREE.CylinderGeometry(0.022, 0.022, 0.025, 16), poleMat);
|
|
51
|
+
topCap.position.y = 1.80;
|
|
52
|
+
g.add(topCap);
|
|
53
|
+
|
|
54
|
+
// Warm bulb glow sphere
|
|
55
|
+
var bulb = new THREE.Mesh(
|
|
56
|
+
new THREE.SphereGeometry(0.030, 16, 12),
|
|
57
|
+
mat(0xffeedd, { emissive: 0xffeedd, emissiveIntensity: 1.2, transparent: true, opacity: 0.90 })
|
|
58
|
+
);
|
|
59
|
+
bulb.position.y = 1.68;
|
|
60
|
+
g.add(bulb);
|
|
61
|
+
|
|
62
|
+
// Point light
|
|
63
|
+
var light = new THREE.PointLight(0xffeedd, 0.3, 4);
|
|
64
|
+
light.position.y = 1.65;
|
|
65
|
+
g.add(light);
|
|
66
|
+
|
|
67
|
+
return g;
|
|
68
|
+
}
|
|
69
|
+
};
|