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,100 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'cactus',
|
|
6
|
+
name: 'Cactus',
|
|
7
|
+
category: 'nature',
|
|
8
|
+
icon: 'Ca',
|
|
9
|
+
gridW: 1, gridD: 1, height: 0.5,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
// Terracotta pot — warm dark tone
|
|
14
|
+
var pot = new THREE.Mesh(
|
|
15
|
+
new THREE.CylinderGeometry(0.095, 0.072, 0.165, 16),
|
|
16
|
+
mat(0x3d1f10, { roughness: 0.85 })
|
|
17
|
+
);
|
|
18
|
+
pot.position.y = 0.083;
|
|
19
|
+
pot.castShadow = true;
|
|
20
|
+
pot.receiveShadow = true;
|
|
21
|
+
g.add(pot);
|
|
22
|
+
|
|
23
|
+
// Pot rim detail
|
|
24
|
+
var rim = new THREE.Mesh(
|
|
25
|
+
new THREE.TorusGeometry(0.098, 0.013, 8, 20),
|
|
26
|
+
mat(0x2a1208, { roughness: 0.80 })
|
|
27
|
+
);
|
|
28
|
+
rim.rotation.x = Math.PI / 2;
|
|
29
|
+
rim.position.y = 0.163;
|
|
30
|
+
g.add(rim);
|
|
31
|
+
|
|
32
|
+
// Gravel / soil surface
|
|
33
|
+
var soil = new THREE.Mesh(
|
|
34
|
+
new THREE.CylinderGeometry(0.083, 0.083, 0.014, 16),
|
|
35
|
+
mat(0x1e1c18, { roughness: 0.99 })
|
|
36
|
+
);
|
|
37
|
+
soil.position.y = 0.175;
|
|
38
|
+
g.add(soil);
|
|
39
|
+
|
|
40
|
+
// Cactus main body — fat cylinder, green
|
|
41
|
+
var cactusMat = mat(0x2a6030, { roughness: 0.70 });
|
|
42
|
+
var body = new THREE.Mesh(
|
|
43
|
+
new THREE.CylinderGeometry(0.055, 0.065, 0.30, 10),
|
|
44
|
+
cactusMat
|
|
45
|
+
);
|
|
46
|
+
body.position.y = 0.33;
|
|
47
|
+
body.castShadow = true;
|
|
48
|
+
g.add(body);
|
|
49
|
+
|
|
50
|
+
// Cactus rib lines (darker vertical strips)
|
|
51
|
+
var ribMat = mat(0x1e4a22, { roughness: 0.75 });
|
|
52
|
+
for (var i = 0; i < 5; i++) {
|
|
53
|
+
var ribAngle = (i / 5) * Math.PI * 2;
|
|
54
|
+
var rib = new THREE.Mesh(
|
|
55
|
+
new THREE.BoxGeometry(0.012, 0.28, 0.014),
|
|
56
|
+
ribMat
|
|
57
|
+
);
|
|
58
|
+
rib.position.set(
|
|
59
|
+
Math.sin(ribAngle) * 0.048,
|
|
60
|
+
0.33,
|
|
61
|
+
Math.cos(ribAngle) * 0.048
|
|
62
|
+
);
|
|
63
|
+
rib.rotation.y = -ribAngle;
|
|
64
|
+
g.add(rib);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Spines — small white/cream cones
|
|
68
|
+
var spineMat = mat(0xe8e0cc, { roughness: 0.60 });
|
|
69
|
+
var spineRows = [{ y: 0.22, r: 0.062 }, { y: 0.32, r: 0.060 }, { y: 0.42, r: 0.056 }];
|
|
70
|
+
spineRows.forEach(function(row) {
|
|
71
|
+
for (var s = 0; s < 8; s++) {
|
|
72
|
+
var sa = (s / 8) * Math.PI * 2;
|
|
73
|
+
var spine = new THREE.Mesh(
|
|
74
|
+
new THREE.ConeGeometry(0.004, 0.025, 4),
|
|
75
|
+
spineMat
|
|
76
|
+
);
|
|
77
|
+
spine.position.set(
|
|
78
|
+
Math.sin(sa) * row.r,
|
|
79
|
+
row.y,
|
|
80
|
+
Math.cos(sa) * row.r
|
|
81
|
+
);
|
|
82
|
+
spine.rotation.z = Math.PI / 2 - 0.2;
|
|
83
|
+
spine.rotation.y = -sa;
|
|
84
|
+
g.add(spine);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Top of cactus — slightly rounded cap
|
|
89
|
+
var cap = new THREE.Mesh(
|
|
90
|
+
new THREE.SphereGeometry(0.055, 10, 8),
|
|
91
|
+
cactusMat
|
|
92
|
+
);
|
|
93
|
+
cap.scale.y = 0.55;
|
|
94
|
+
cap.position.y = 0.480;
|
|
95
|
+
cap.castShadow = true;
|
|
96
|
+
g.add(cap);
|
|
97
|
+
|
|
98
|
+
return g;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'carpet-tile',
|
|
6
|
+
name: 'Carpet Tile',
|
|
7
|
+
category: 'structural',
|
|
8
|
+
icon: 'CT',
|
|
9
|
+
gridW: 2, gridD: 2, height: 0.03,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
// Carpet base — charcoal fabric
|
|
14
|
+
var carpet = new THREE.Mesh(
|
|
15
|
+
new THREE.BoxGeometry(1.98, 0.03, 1.98),
|
|
16
|
+
mat(0x2e3040, { roughness: 0.98 })
|
|
17
|
+
);
|
|
18
|
+
carpet.receiveShadow = true;
|
|
19
|
+
g.add(carpet);
|
|
20
|
+
|
|
21
|
+
// Subtle pattern — directional nap lines (darker strips)
|
|
22
|
+
var napMat = mat(0x272938, { roughness: 1.0 });
|
|
23
|
+
var i;
|
|
24
|
+
for (i = -3; i <= 3; i++) {
|
|
25
|
+
var nap = new THREE.Mesh(
|
|
26
|
+
new THREE.BoxGeometry(1.96, 0.031, 0.04),
|
|
27
|
+
napMat
|
|
28
|
+
);
|
|
29
|
+
nap.position.z = i * 0.28;
|
|
30
|
+
g.add(nap);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Thin border edge reveal (slightly lighter)
|
|
34
|
+
var edgeMat = mat(0x3a3d50, { roughness: 0.95 });
|
|
35
|
+
var edgeN = new THREE.Mesh(new THREE.BoxGeometry(2, 0.032, 0.04), edgeMat);
|
|
36
|
+
edgeN.position.z = -0.98;
|
|
37
|
+
g.add(edgeN);
|
|
38
|
+
var edgeS = edgeN.clone(); edgeS.position.z = 0.98; g.add(edgeS);
|
|
39
|
+
var edgeW = new THREE.Mesh(new THREE.BoxGeometry(0.04, 0.032, 2), edgeMat);
|
|
40
|
+
edgeW.position.x = -0.98;
|
|
41
|
+
g.add(edgeW);
|
|
42
|
+
var edgeE = edgeW.clone(); edgeE.position.x = 0.98; g.add(edgeE);
|
|
43
|
+
|
|
44
|
+
return g;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'chair',
|
|
6
|
+
name: 'Office Chair',
|
|
7
|
+
category: 'furniture',
|
|
8
|
+
icon: 'Ch',
|
|
9
|
+
gridW: 1, gridD: 1, height: 1.1,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
// 5-star base — chrome disc
|
|
14
|
+
var baseDisc = new THREE.Mesh(
|
|
15
|
+
new THREE.CylinderGeometry(0.28, 0.28, 0.025, 5),
|
|
16
|
+
PAL.chrome()
|
|
17
|
+
);
|
|
18
|
+
baseDisc.position.y = 0.02;
|
|
19
|
+
baseDisc.castShadow = true;
|
|
20
|
+
g.add(baseDisc);
|
|
21
|
+
|
|
22
|
+
// 5 arms radiating outward
|
|
23
|
+
var armMat = PAL.chrome();
|
|
24
|
+
for (var i = 0; i < 5; i++) {
|
|
25
|
+
var arm = new THREE.Mesh(
|
|
26
|
+
new THREE.BoxGeometry(0.26, 0.025, 0.045),
|
|
27
|
+
armMat
|
|
28
|
+
);
|
|
29
|
+
arm.position.y = 0.02;
|
|
30
|
+
arm.rotation.y = (i / 5) * Math.PI * 2;
|
|
31
|
+
arm.castShadow = true;
|
|
32
|
+
g.add(arm);
|
|
33
|
+
|
|
34
|
+
// Wheel at each arm tip
|
|
35
|
+
var wheel = new THREE.Mesh(
|
|
36
|
+
new THREE.CylinderGeometry(0.03, 0.03, 0.04, 10),
|
|
37
|
+
mat(0x1a1a1a, { roughness: 0.9 })
|
|
38
|
+
);
|
|
39
|
+
var angle = (i / 5) * Math.PI * 2;
|
|
40
|
+
wheel.position.set(Math.sin(angle) * 0.26, 0.018, Math.cos(angle) * 0.26);
|
|
41
|
+
wheel.rotation.z = Math.PI / 2;
|
|
42
|
+
g.add(wheel);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Central post (pneumatic cylinder)
|
|
46
|
+
var post = new THREE.Mesh(
|
|
47
|
+
new THREE.CylinderGeometry(0.04, 0.05, 0.46, 12),
|
|
48
|
+
PAL.chromeBrushed()
|
|
49
|
+
);
|
|
50
|
+
post.position.y = 0.26;
|
|
51
|
+
post.castShadow = true;
|
|
52
|
+
g.add(post);
|
|
53
|
+
|
|
54
|
+
// Seat cushion
|
|
55
|
+
var seat = new THREE.Mesh(
|
|
56
|
+
new THREE.BoxGeometry(0.5, 0.08, 0.48),
|
|
57
|
+
PAL.leatherBlack()
|
|
58
|
+
);
|
|
59
|
+
seat.position.y = 0.52;
|
|
60
|
+
seat.castShadow = true;
|
|
61
|
+
seat.receiveShadow = true;
|
|
62
|
+
g.add(seat);
|
|
63
|
+
|
|
64
|
+
// Seat shell (underside)
|
|
65
|
+
var seatShell = new THREE.Mesh(
|
|
66
|
+
new THREE.BoxGeometry(0.52, 0.03, 0.50),
|
|
67
|
+
mat(0x1e2128, { roughness: 0.6 })
|
|
68
|
+
);
|
|
69
|
+
seatShell.position.y = 0.475;
|
|
70
|
+
g.add(seatShell);
|
|
71
|
+
|
|
72
|
+
// Back lower cushion
|
|
73
|
+
var backLow = new THREE.Mesh(
|
|
74
|
+
new THREE.BoxGeometry(0.48, 0.34, 0.07),
|
|
75
|
+
PAL.leatherBlack()
|
|
76
|
+
);
|
|
77
|
+
backLow.position.set(0, 0.77, -0.21);
|
|
78
|
+
backLow.castShadow = true;
|
|
79
|
+
g.add(backLow);
|
|
80
|
+
|
|
81
|
+
// Back upper cushion
|
|
82
|
+
var backUp = new THREE.Mesh(
|
|
83
|
+
new THREE.BoxGeometry(0.48, 0.28, 0.07),
|
|
84
|
+
PAL.leatherBlack()
|
|
85
|
+
);
|
|
86
|
+
backUp.position.set(0, 1.03, -0.19);
|
|
87
|
+
backUp.castShadow = true;
|
|
88
|
+
g.add(backUp);
|
|
89
|
+
|
|
90
|
+
// Back frame
|
|
91
|
+
var backFrame = new THREE.Mesh(
|
|
92
|
+
new THREE.BoxGeometry(0.52, 0.66, 0.04),
|
|
93
|
+
mat(0x17191f, { roughness: 0.5, metalness: 0.1 })
|
|
94
|
+
);
|
|
95
|
+
backFrame.position.set(0, 0.89, -0.25);
|
|
96
|
+
g.add(backFrame);
|
|
97
|
+
|
|
98
|
+
// Left armrest
|
|
99
|
+
var armrestMat = mat(0x1a1a1a, { roughness: 0.75 });
|
|
100
|
+
var leftArm = new THREE.Mesh(
|
|
101
|
+
new THREE.BoxGeometry(0.07, 0.04, 0.22),
|
|
102
|
+
armrestMat
|
|
103
|
+
);
|
|
104
|
+
leftArm.position.set(-0.26, 0.72, -0.05);
|
|
105
|
+
leftArm.castShadow = true;
|
|
106
|
+
g.add(leftArm);
|
|
107
|
+
|
|
108
|
+
var rightArm = leftArm.clone();
|
|
109
|
+
rightArm.position.x = 0.26;
|
|
110
|
+
g.add(rightArm);
|
|
111
|
+
|
|
112
|
+
// Armrest posts
|
|
113
|
+
var postMat = PAL.chromeBrushed();
|
|
114
|
+
var leftPost = new THREE.Mesh(new THREE.BoxGeometry(0.025, 0.2, 0.025), postMat);
|
|
115
|
+
leftPost.position.set(-0.26, 0.62, -0.05);
|
|
116
|
+
g.add(leftPost);
|
|
117
|
+
var rightPost = leftPost.clone();
|
|
118
|
+
rightPost.position.x = 0.26;
|
|
119
|
+
g.add(rightPost);
|
|
120
|
+
|
|
121
|
+
return g;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'chandelier',
|
|
6
|
+
name: 'Chandelier',
|
|
7
|
+
category: 'lighting',
|
|
8
|
+
icon: 'CH',
|
|
9
|
+
gridW: 1, gridD: 1, height: 3.0,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
var ringY = 2.50;
|
|
14
|
+
var ringR = 0.40;
|
|
15
|
+
var armCount = 6;
|
|
16
|
+
var chromeMat = PAL.chrome();
|
|
17
|
+
|
|
18
|
+
// Ceiling canopy (mount disk)
|
|
19
|
+
var canopy = new THREE.Mesh(new THREE.CylinderGeometry(0.075, 0.075, 0.022, 24), chromeMat);
|
|
20
|
+
canopy.position.y = 3.0;
|
|
21
|
+
g.add(canopy);
|
|
22
|
+
|
|
23
|
+
// Main drop rod from ceiling to ring
|
|
24
|
+
var rod = new THREE.Mesh(
|
|
25
|
+
new THREE.CylinderGeometry(0.010, 0.010, 3.0 - ringY - 0.011, 12),
|
|
26
|
+
chromeMat
|
|
27
|
+
);
|
|
28
|
+
rod.position.y = ringY + (3.0 - ringY - 0.011) / 2 + 0.011;
|
|
29
|
+
g.add(rod);
|
|
30
|
+
|
|
31
|
+
// Chrome ring
|
|
32
|
+
var ring = new THREE.Mesh(
|
|
33
|
+
new THREE.TorusGeometry(ringR, 0.012, 10, 64),
|
|
34
|
+
chromeMat
|
|
35
|
+
);
|
|
36
|
+
ring.position.y = ringY;
|
|
37
|
+
g.add(ring);
|
|
38
|
+
|
|
39
|
+
// Ring center hub
|
|
40
|
+
var hub = new THREE.Mesh(new THREE.CylinderGeometry(0.025, 0.025, 0.040, 16), chromeMat);
|
|
41
|
+
hub.position.y = ringY;
|
|
42
|
+
g.add(hub);
|
|
43
|
+
|
|
44
|
+
// 6 pendant arms radiating from ring
|
|
45
|
+
for (var i = 0; i < armCount; i++) {
|
|
46
|
+
var angle = (i / armCount) * Math.PI * 2;
|
|
47
|
+
var ax = Math.sin(angle) * ringR;
|
|
48
|
+
var az = Math.cos(angle) * ringR;
|
|
49
|
+
|
|
50
|
+
// Arm spoke (from hub to ring)
|
|
51
|
+
var spokeLen = ringR - 0.026;
|
|
52
|
+
var spoke = new THREE.Mesh(
|
|
53
|
+
new THREE.CylinderGeometry(0.006, 0.006, spokeLen, 8),
|
|
54
|
+
chromeMat
|
|
55
|
+
);
|
|
56
|
+
spoke.position.set(Math.sin(angle) * (ringR / 2), ringY, Math.cos(angle) * (ringR / 2));
|
|
57
|
+
spoke.rotation.z = Math.PI / 2;
|
|
58
|
+
spoke.rotation.y = angle;
|
|
59
|
+
g.add(spoke);
|
|
60
|
+
|
|
61
|
+
// Pendant drop wire
|
|
62
|
+
var dropLen = 0.18;
|
|
63
|
+
var wire = new THREE.Mesh(
|
|
64
|
+
new THREE.CylinderGeometry(0.004, 0.004, dropLen, 8),
|
|
65
|
+
mat(0x999999, { roughness: 0.30, metalness: 0.70 })
|
|
66
|
+
);
|
|
67
|
+
wire.position.set(ax, ringY - dropLen / 2, az);
|
|
68
|
+
g.add(wire);
|
|
69
|
+
|
|
70
|
+
// Globe bulb shade
|
|
71
|
+
var globe = new THREE.Mesh(
|
|
72
|
+
new THREE.SphereGeometry(0.040, 18, 12),
|
|
73
|
+
mat(0xfff5e0, { transparent: true, opacity: 0.55, roughness: 0.05, side: THREE.DoubleSide })
|
|
74
|
+
);
|
|
75
|
+
globe.position.set(ax, ringY - dropLen - 0.040, az);
|
|
76
|
+
g.add(globe);
|
|
77
|
+
|
|
78
|
+
// Warm filament glow inside globe
|
|
79
|
+
var filament = new THREE.Mesh(
|
|
80
|
+
new THREE.SphereGeometry(0.016, 10, 8),
|
|
81
|
+
mat(0xffe8a0, { emissive: 0xffdd80, emissiveIntensity: 1.5, transparent: true, opacity: 0.95 })
|
|
82
|
+
);
|
|
83
|
+
filament.position.set(ax, ringY - dropLen - 0.040, az);
|
|
84
|
+
g.add(filament);
|
|
85
|
+
|
|
86
|
+
// Globe chrome neck fitting
|
|
87
|
+
var globeNeck = new THREE.Mesh(
|
|
88
|
+
new THREE.CylinderGeometry(0.010, 0.010, 0.015, 10),
|
|
89
|
+
chromeMat
|
|
90
|
+
);
|
|
91
|
+
globeNeck.position.set(ax, ringY - dropLen - 0.004, az);
|
|
92
|
+
g.add(globeNeck);
|
|
93
|
+
|
|
94
|
+
// Per-arm warm point light (low intensity, many = soft fill)
|
|
95
|
+
var armLight = new THREE.PointLight(0xffe8a0, 0.09, 3.5);
|
|
96
|
+
armLight.position.set(ax, ringY - dropLen - 0.040, az);
|
|
97
|
+
g.add(armLight);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Centre ambient fill light at ring level
|
|
101
|
+
var fillLight = new THREE.PointLight(0xfff0cc, 0.18, 5);
|
|
102
|
+
fillLight.position.y = ringY;
|
|
103
|
+
g.add(fillLight);
|
|
104
|
+
|
|
105
|
+
return g;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'coffee_machine',
|
|
6
|
+
name: 'Coffee Machine',
|
|
7
|
+
category: 'kitchen',
|
|
8
|
+
icon: 'CM',
|
|
9
|
+
gridW: 1, gridD: 1, height: 0.5,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
// Main body — dark boxy form
|
|
14
|
+
var body = new THREE.Mesh(
|
|
15
|
+
new THREE.BoxGeometry(0.40, 0.42, 0.36),
|
|
16
|
+
mat(0x111318, { roughness: 0.40, metalness: 0.20 })
|
|
17
|
+
);
|
|
18
|
+
body.position.y = 0.21;
|
|
19
|
+
body.castShadow = true;
|
|
20
|
+
body.receiveShadow = true;
|
|
21
|
+
g.add(body);
|
|
22
|
+
|
|
23
|
+
// Chrome top cap
|
|
24
|
+
var topCap = new THREE.Mesh(
|
|
25
|
+
new THREE.BoxGeometry(0.40, 0.035, 0.36),
|
|
26
|
+
PAL.chrome()
|
|
27
|
+
);
|
|
28
|
+
topCap.position.y = 0.435;
|
|
29
|
+
topCap.castShadow = true;
|
|
30
|
+
g.add(topCap);
|
|
31
|
+
|
|
32
|
+
// Front face plate (slightly recessed dark panel)
|
|
33
|
+
var faceplate = new THREE.Mesh(
|
|
34
|
+
new THREE.BoxGeometry(0.32, 0.30, 0.01),
|
|
35
|
+
mat(0x1a1c22, { roughness: 0.55, metalness: 0.10 })
|
|
36
|
+
);
|
|
37
|
+
faceplate.position.set(0, 0.24, 0.185);
|
|
38
|
+
g.add(faceplate);
|
|
39
|
+
|
|
40
|
+
// Small display screen (emissive blue)
|
|
41
|
+
var screen = new THREE.Mesh(
|
|
42
|
+
new THREE.BoxGeometry(0.14, 0.07, 0.008),
|
|
43
|
+
mat(0x002244, { emissive: 0x004488, emissiveIntensity: 0.9, roughness: 0.1 })
|
|
44
|
+
);
|
|
45
|
+
screen.position.set(0.06, 0.32, 0.19);
|
|
46
|
+
g.add(screen);
|
|
47
|
+
|
|
48
|
+
// Group of 3 control buttons
|
|
49
|
+
var btnMat = PAL.chrome();
|
|
50
|
+
var btnGeo = new THREE.CylinderGeometry(0.018, 0.018, 0.015, 10);
|
|
51
|
+
[-0.07, 0, 0.07].forEach(function(x) {
|
|
52
|
+
var btn = new THREE.Mesh(btnGeo, btnMat);
|
|
53
|
+
btn.rotation.x = Math.PI / 2;
|
|
54
|
+
btn.position.set(x, 0.20, 0.192);
|
|
55
|
+
g.add(btn);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Steam nozzle (chrome tube angled out)
|
|
59
|
+
var nozzle = new THREE.Mesh(
|
|
60
|
+
new THREE.CylinderGeometry(0.012, 0.014, 0.14, 8),
|
|
61
|
+
PAL.chrome()
|
|
62
|
+
);
|
|
63
|
+
nozzle.rotation.z = -0.35;
|
|
64
|
+
nozzle.position.set(-0.16, 0.32, 0.10);
|
|
65
|
+
nozzle.castShadow = true;
|
|
66
|
+
g.add(nozzle);
|
|
67
|
+
|
|
68
|
+
// Nozzle tip cap
|
|
69
|
+
var nozzleTip = new THREE.Mesh(
|
|
70
|
+
new THREE.CylinderGeometry(0.018, 0.012, 0.022, 8),
|
|
71
|
+
PAL.chromeBrushed()
|
|
72
|
+
);
|
|
73
|
+
nozzleTip.position.set(-0.205, 0.36, 0.10);
|
|
74
|
+
nozzleTip.rotation.z = -0.35;
|
|
75
|
+
g.add(nozzleTip);
|
|
76
|
+
|
|
77
|
+
// Drip tray (chrome grill plate)
|
|
78
|
+
var tray = new THREE.Mesh(
|
|
79
|
+
new THREE.BoxGeometry(0.28, 0.014, 0.18),
|
|
80
|
+
PAL.chromeBrushed()
|
|
81
|
+
);
|
|
82
|
+
tray.position.set(0, 0.048, 0.04);
|
|
83
|
+
g.add(tray);
|
|
84
|
+
|
|
85
|
+
// Water reservoir at back (dark translucent)
|
|
86
|
+
var reservoir = new THREE.Mesh(
|
|
87
|
+
new THREE.BoxGeometry(0.12, 0.28, 0.10),
|
|
88
|
+
mat(0x1a2030, { transparent: true, opacity: 0.80, roughness: 0.25 })
|
|
89
|
+
);
|
|
90
|
+
reservoir.position.set(0.13, 0.28, -0.14);
|
|
91
|
+
g.add(reservoir);
|
|
92
|
+
|
|
93
|
+
return g;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'coffee-table',
|
|
6
|
+
name: 'Coffee Table',
|
|
7
|
+
category: 'furniture',
|
|
8
|
+
icon: 'CT',
|
|
9
|
+
gridW: 1, gridD: 1, height: 0.45,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
// Glass top
|
|
14
|
+
var glassTop = new THREE.Mesh(
|
|
15
|
+
new THREE.BoxGeometry(1.0, 0.012, 0.5),
|
|
16
|
+
mat(0xaaccee, { transparent: true, opacity: 0.35, roughness: 0.04, metalness: 0.08 })
|
|
17
|
+
);
|
|
18
|
+
glassTop.position.y = 0.45;
|
|
19
|
+
glassTop.receiveShadow = true;
|
|
20
|
+
g.add(glassTop);
|
|
21
|
+
|
|
22
|
+
// Chrome frame around glass top
|
|
23
|
+
var frameMat = PAL.chrome();
|
|
24
|
+
var frontBar = new THREE.Mesh(new THREE.BoxGeometry(1.0, 0.018, 0.018), frameMat);
|
|
25
|
+
frontBar.position.set(0, 0.444, 0.241);
|
|
26
|
+
frontBar.castShadow = true;
|
|
27
|
+
g.add(frontBar);
|
|
28
|
+
|
|
29
|
+
var backBar = frontBar.clone();
|
|
30
|
+
backBar.position.z = -0.241;
|
|
31
|
+
g.add(backBar);
|
|
32
|
+
|
|
33
|
+
var leftBar = new THREE.Mesh(new THREE.BoxGeometry(0.018, 0.018, 0.5), frameMat);
|
|
34
|
+
leftBar.position.set(-0.491, 0.444, 0);
|
|
35
|
+
leftBar.castShadow = true;
|
|
36
|
+
g.add(leftBar);
|
|
37
|
+
|
|
38
|
+
var rightBar = leftBar.clone();
|
|
39
|
+
rightBar.position.x = 0.491;
|
|
40
|
+
g.add(rightBar);
|
|
41
|
+
|
|
42
|
+
// Lower shelf (smoked glass)
|
|
43
|
+
var shelf = new THREE.Mesh(
|
|
44
|
+
new THREE.BoxGeometry(0.88, 0.010, 0.40),
|
|
45
|
+
mat(0x445566, { transparent: true, opacity: 0.55, roughness: 0.12 })
|
|
46
|
+
);
|
|
47
|
+
shelf.position.y = 0.18;
|
|
48
|
+
shelf.receiveShadow = true;
|
|
49
|
+
g.add(shelf);
|
|
50
|
+
|
|
51
|
+
// 4 chrome legs — slim round
|
|
52
|
+
var legMat = PAL.chrome();
|
|
53
|
+
var legGeo = new THREE.CylinderGeometry(0.018, 0.014, 0.44, 10);
|
|
54
|
+
[[-0.44, 0.22], [0.44, 0.22], [-0.44, -0.22], [0.44, -0.22]].forEach(function(p) {
|
|
55
|
+
var leg = new THREE.Mesh(legGeo, legMat);
|
|
56
|
+
leg.position.set(p[0], 0.22, p[1]);
|
|
57
|
+
leg.castShadow = true;
|
|
58
|
+
g.add(leg);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Horizontal stretcher bars connecting legs (lower)
|
|
62
|
+
var stretcherMat = PAL.chromeBrushed();
|
|
63
|
+
var hStretch1 = new THREE.Mesh(new THREE.BoxGeometry(0.88, 0.015, 0.015), stretcherMat);
|
|
64
|
+
hStretch1.position.set(0, 0.12, 0.22);
|
|
65
|
+
g.add(hStretch1);
|
|
66
|
+
|
|
67
|
+
var hStretch2 = hStretch1.clone();
|
|
68
|
+
hStretch2.position.z = -0.22;
|
|
69
|
+
g.add(hStretch2);
|
|
70
|
+
|
|
71
|
+
var vStretch1 = new THREE.Mesh(new THREE.BoxGeometry(0.015, 0.015, 0.44), stretcherMat);
|
|
72
|
+
vStretch1.position.set(-0.44, 0.12, 0);
|
|
73
|
+
g.add(vStretch1);
|
|
74
|
+
|
|
75
|
+
var vStretch2 = vStretch1.clone();
|
|
76
|
+
vStretch2.position.x = 0.44;
|
|
77
|
+
g.add(vStretch2);
|
|
78
|
+
|
|
79
|
+
return g;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'column',
|
|
6
|
+
name: 'Column',
|
|
7
|
+
category: 'structural',
|
|
8
|
+
icon: 'Co',
|
|
9
|
+
gridW: 1, gridD: 1, height: 4,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
var marble = PAL.marbleWhite();
|
|
14
|
+
var gold = PAL.gold();
|
|
15
|
+
|
|
16
|
+
// Main shaft — cylinder
|
|
17
|
+
var shaft = new THREE.Mesh(
|
|
18
|
+
new THREE.CylinderGeometry(0.15, 0.17, 3.6, 16),
|
|
19
|
+
marble
|
|
20
|
+
);
|
|
21
|
+
shaft.position.y = 0;
|
|
22
|
+
shaft.castShadow = true;
|
|
23
|
+
shaft.receiveShadow = true;
|
|
24
|
+
g.add(shaft);
|
|
25
|
+
|
|
26
|
+
// Base plinth (square)
|
|
27
|
+
var base = new THREE.Mesh(
|
|
28
|
+
new THREE.BoxGeometry(0.42, 0.2, 0.42),
|
|
29
|
+
marble
|
|
30
|
+
);
|
|
31
|
+
base.position.y = -1.9;
|
|
32
|
+
base.castShadow = true;
|
|
33
|
+
g.add(base);
|
|
34
|
+
|
|
35
|
+
// Base plinth bottom step
|
|
36
|
+
var baseStep = new THREE.Mesh(
|
|
37
|
+
new THREE.BoxGeometry(0.48, 0.1, 0.48),
|
|
38
|
+
marble
|
|
39
|
+
);
|
|
40
|
+
baseStep.position.y = -2.0;
|
|
41
|
+
g.add(baseStep);
|
|
42
|
+
|
|
43
|
+
// Capital block (top)
|
|
44
|
+
var capital = new THREE.Mesh(
|
|
45
|
+
new THREE.BoxGeometry(0.44, 0.2, 0.44),
|
|
46
|
+
marble
|
|
47
|
+
);
|
|
48
|
+
capital.position.y = 1.9;
|
|
49
|
+
capital.castShadow = true;
|
|
50
|
+
g.add(capital);
|
|
51
|
+
|
|
52
|
+
// Capital abacus (wider flat top)
|
|
53
|
+
var abacus = new THREE.Mesh(
|
|
54
|
+
new THREE.BoxGeometry(0.5, 0.08, 0.5),
|
|
55
|
+
marble
|
|
56
|
+
);
|
|
57
|
+
abacus.position.y = 2.0;
|
|
58
|
+
g.add(abacus);
|
|
59
|
+
|
|
60
|
+
// Gold capital ring torus
|
|
61
|
+
var ring = new THREE.Mesh(
|
|
62
|
+
new THREE.TorusGeometry(0.165, 0.025, 8, 24),
|
|
63
|
+
gold
|
|
64
|
+
);
|
|
65
|
+
ring.rotation.x = Math.PI / 2;
|
|
66
|
+
ring.position.y = 1.72;
|
|
67
|
+
ring.castShadow = true;
|
|
68
|
+
g.add(ring);
|
|
69
|
+
|
|
70
|
+
// Second gold ring (lower accent)
|
|
71
|
+
var ringLow = new THREE.Mesh(
|
|
72
|
+
new THREE.TorusGeometry(0.175, 0.018, 8, 24),
|
|
73
|
+
gold
|
|
74
|
+
);
|
|
75
|
+
ringLow.rotation.x = Math.PI / 2;
|
|
76
|
+
ringLow.position.y = -1.72;
|
|
77
|
+
g.add(ringLow);
|
|
78
|
+
|
|
79
|
+
// Subtle fluting grooves (flat vertical strips on shaft)
|
|
80
|
+
var fluteMat = mat(0xddd8cc, { roughness: 0.2, metalness: 0.05 });
|
|
81
|
+
var i;
|
|
82
|
+
for (i = 0; i < 8; i++) {
|
|
83
|
+
var angle = (i / 8) * Math.PI * 2;
|
|
84
|
+
var flute = new THREE.Mesh(
|
|
85
|
+
new THREE.BoxGeometry(0.018, 3.4, 0.018),
|
|
86
|
+
fluteMat
|
|
87
|
+
);
|
|
88
|
+
flute.position.x = Math.cos(angle) * 0.15;
|
|
89
|
+
flute.position.z = Math.sin(angle) * 0.15;
|
|
90
|
+
g.add(flute);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return g;
|
|
94
|
+
}
|
|
95
|
+
};
|