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,54 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'floor-tile',
|
|
6
|
+
name: 'Floor Tile',
|
|
7
|
+
category: 'structural',
|
|
8
|
+
icon: 'FT',
|
|
9
|
+
gridW: 2, gridD: 2, height: 0.02,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
// Main tile slab
|
|
14
|
+
var tile = new THREE.Mesh(
|
|
15
|
+
new THREE.BoxGeometry(2, 0.02, 2),
|
|
16
|
+
PAL.marbleBlack()
|
|
17
|
+
);
|
|
18
|
+
tile.receiveShadow = true;
|
|
19
|
+
g.add(tile);
|
|
20
|
+
|
|
21
|
+
// Thin grout lines — cross pattern
|
|
22
|
+
var groutMat = mat(0x0e1015, { roughness: 1.0 });
|
|
23
|
+
|
|
24
|
+
var groutH = new THREE.Mesh(
|
|
25
|
+
new THREE.BoxGeometry(2, 0.021, 0.025),
|
|
26
|
+
groutMat
|
|
27
|
+
);
|
|
28
|
+
g.add(groutH);
|
|
29
|
+
|
|
30
|
+
var groutV = new THREE.Mesh(
|
|
31
|
+
new THREE.BoxGeometry(0.025, 0.021, 2),
|
|
32
|
+
groutMat
|
|
33
|
+
);
|
|
34
|
+
g.add(groutV);
|
|
35
|
+
|
|
36
|
+
// Edge bevel strip (front)
|
|
37
|
+
var edgeF = new THREE.Mesh(
|
|
38
|
+
new THREE.BoxGeometry(2, 0.018, 0.015),
|
|
39
|
+
mat(0x0e1015, { roughness: 0.8 })
|
|
40
|
+
);
|
|
41
|
+
edgeF.position.z = 0.993;
|
|
42
|
+
g.add(edgeF);
|
|
43
|
+
|
|
44
|
+
// Edge bevel strip (right)
|
|
45
|
+
var edgeR = new THREE.Mesh(
|
|
46
|
+
new THREE.BoxGeometry(0.015, 0.018, 2),
|
|
47
|
+
mat(0x0e1015, { roughness: 0.8 })
|
|
48
|
+
);
|
|
49
|
+
edgeR.position.x = 0.993;
|
|
50
|
+
g.add(edgeR);
|
|
51
|
+
|
|
52
|
+
return g;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'flower_pot',
|
|
6
|
+
name: 'Flower Pot',
|
|
7
|
+
category: 'nature',
|
|
8
|
+
icon: 'Fp',
|
|
9
|
+
gridW: 1, gridD: 1, height: 0.35,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
// Terracotta-style pot body (dark glaze version for premium look)
|
|
14
|
+
var pot = new THREE.Mesh(
|
|
15
|
+
new THREE.CylinderGeometry(0.085, 0.060, 0.16, 16),
|
|
16
|
+
mat(0x2a1a14, { roughness: 0.80 })
|
|
17
|
+
);
|
|
18
|
+
pot.position.y = 0.08;
|
|
19
|
+
pot.castShadow = true;
|
|
20
|
+
pot.receiveShadow = true;
|
|
21
|
+
g.add(pot);
|
|
22
|
+
|
|
23
|
+
// Pot rim
|
|
24
|
+
var rim = new THREE.Mesh(
|
|
25
|
+
new THREE.TorusGeometry(0.088, 0.012, 8, 20),
|
|
26
|
+
mat(0x1a0f0a, { roughness: 0.75 })
|
|
27
|
+
);
|
|
28
|
+
rim.rotation.x = Math.PI / 2;
|
|
29
|
+
rim.position.y = 0.158;
|
|
30
|
+
g.add(rim);
|
|
31
|
+
|
|
32
|
+
// Soil disc
|
|
33
|
+
var soil = new THREE.Mesh(
|
|
34
|
+
new THREE.CylinderGeometry(0.076, 0.076, 0.012, 16),
|
|
35
|
+
mat(0x1a1510, { roughness: 0.99 })
|
|
36
|
+
);
|
|
37
|
+
soil.position.y = 0.168;
|
|
38
|
+
g.add(soil);
|
|
39
|
+
|
|
40
|
+
// Flower stems (3 stems)
|
|
41
|
+
var stemMat = mat(0x1a4020, { roughness: 0.85 });
|
|
42
|
+
var flowerColors = [0xd44080, 0xe8c030, 0x5888e0];
|
|
43
|
+
|
|
44
|
+
for (var i = 0; i < 3; i++) {
|
|
45
|
+
var spread = (i - 1) * 0.045;
|
|
46
|
+
var stemHeight = 0.10 + i * 0.015;
|
|
47
|
+
|
|
48
|
+
var stem = new THREE.Mesh(
|
|
49
|
+
new THREE.CylinderGeometry(0.005, 0.007, stemHeight, 6),
|
|
50
|
+
stemMat
|
|
51
|
+
);
|
|
52
|
+
stem.position.set(spread, 0.175 + stemHeight / 2, (i % 2) * 0.03 - 0.015);
|
|
53
|
+
stem.castShadow = true;
|
|
54
|
+
g.add(stem);
|
|
55
|
+
|
|
56
|
+
// Flower head (small sphere)
|
|
57
|
+
var flower = new THREE.Mesh(
|
|
58
|
+
new THREE.SphereGeometry(0.028, 10, 8),
|
|
59
|
+
mat(flowerColors[i], { roughness: 0.75 })
|
|
60
|
+
);
|
|
61
|
+
flower.position.set(spread, 0.175 + stemHeight + 0.028, (i % 2) * 0.03 - 0.015);
|
|
62
|
+
flower.castShadow = true;
|
|
63
|
+
g.add(flower);
|
|
64
|
+
|
|
65
|
+
// Flower center (yellow dot)
|
|
66
|
+
var center = new THREE.Mesh(
|
|
67
|
+
new THREE.SphereGeometry(0.011, 8, 8),
|
|
68
|
+
mat(0xf0d040, { roughness: 0.70 })
|
|
69
|
+
);
|
|
70
|
+
center.position.set(spread, 0.175 + stemHeight + 0.048, (i % 2) * 0.03 - 0.015);
|
|
71
|
+
g.add(center);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return g;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'foosball',
|
|
6
|
+
name: 'Foosball Table',
|
|
7
|
+
category: 'recreation',
|
|
8
|
+
icon: 'FB',
|
|
9
|
+
gridW: 2, gridD: 1, height: 0.85,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
// Main body box
|
|
14
|
+
var body = new THREE.Mesh(
|
|
15
|
+
new THREE.BoxGeometry(1.40, 0.22, 0.75),
|
|
16
|
+
mat(0x111318, { roughness: 0.50, metalness: 0.10 })
|
|
17
|
+
);
|
|
18
|
+
body.position.y = 0.74;
|
|
19
|
+
body.castShadow = true;
|
|
20
|
+
body.receiveShadow = true;
|
|
21
|
+
g.add(body);
|
|
22
|
+
|
|
23
|
+
// Playing field (green felt base)
|
|
24
|
+
var field = new THREE.Mesh(
|
|
25
|
+
new THREE.BoxGeometry(1.24, 0.010, 0.60),
|
|
26
|
+
PAL.greenFelt()
|
|
27
|
+
);
|
|
28
|
+
field.position.y = 0.856;
|
|
29
|
+
field.receiveShadow = true;
|
|
30
|
+
g.add(field);
|
|
31
|
+
|
|
32
|
+
// White center circle
|
|
33
|
+
var circle = new THREE.Mesh(
|
|
34
|
+
new THREE.CylinderGeometry(0.055, 0.055, 0.012, 18),
|
|
35
|
+
mat(0xffffff, { roughness: 0.80 })
|
|
36
|
+
);
|
|
37
|
+
circle.position.y = 0.864;
|
|
38
|
+
g.add(circle);
|
|
39
|
+
|
|
40
|
+
// Goals at each end (small cut-out feel — dark recess boxes)
|
|
41
|
+
var goalMat = mat(0x0a0a0a, { roughness: 0.70 });
|
|
42
|
+
[-0.62, 0.62].forEach(function(x) {
|
|
43
|
+
var goal = new THREE.Mesh(
|
|
44
|
+
new THREE.BoxGeometry(0.02, 0.10, 0.22),
|
|
45
|
+
goalMat
|
|
46
|
+
);
|
|
47
|
+
goal.position.set(x, 0.83, 0);
|
|
48
|
+
g.add(goal);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Top rails (sides of the table)
|
|
52
|
+
var topRailMat = mat(0x1c1f26, { roughness: 0.45 });
|
|
53
|
+
var topRailGeo = new THREE.BoxGeometry(1.40, 0.06, 0.04);
|
|
54
|
+
[0.375, -0.375].forEach(function(z) {
|
|
55
|
+
var rail = new THREE.Mesh(topRailGeo, topRailMat);
|
|
56
|
+
rail.position.set(0, 0.875, z);
|
|
57
|
+
g.add(rail);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// 3 chrome rods through the table (horizontal, side to side)
|
|
61
|
+
var rodMat = PAL.chrome();
|
|
62
|
+
var rodGeo = new THREE.CylinderGeometry(0.018, 0.018, 0.92, 12);
|
|
63
|
+
[-0.45, 0, 0.45].forEach(function(x) {
|
|
64
|
+
var rod = new THREE.Mesh(rodGeo, rodMat);
|
|
65
|
+
rod.rotation.z = Math.PI / 2;
|
|
66
|
+
rod.position.set(x, 0.855, 0);
|
|
67
|
+
rod.castShadow = true;
|
|
68
|
+
g.add(rod);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Player figures on rods (small dark cylinders)
|
|
72
|
+
var playerMat = mat(0x222222, { roughness: 0.60 });
|
|
73
|
+
var playerGeo = new THREE.CylinderGeometry(0.028, 0.028, 0.09, 8);
|
|
74
|
+
[-0.45, 0, 0.45].forEach(function(x) {
|
|
75
|
+
[-0.18, 0, 0.18].forEach(function(z) {
|
|
76
|
+
var player = new THREE.Mesh(playerGeo, playerMat);
|
|
77
|
+
player.rotation.z = Math.PI / 2;
|
|
78
|
+
player.position.set(x, 0.855, z);
|
|
79
|
+
g.add(player);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// 4 legs
|
|
84
|
+
var legGeo = new THREE.BoxGeometry(0.08, 0.68, 0.08);
|
|
85
|
+
var legMat = mat(0x16181d, { roughness: 0.55 });
|
|
86
|
+
[[-0.62, 0.34, 0.31], [0.62, 0.34, 0.31], [-0.62, 0.34, -0.31], [0.62, 0.34, -0.31]].forEach(function(p) {
|
|
87
|
+
var leg = new THREE.Mesh(legGeo, legMat);
|
|
88
|
+
leg.position.set(p[0], p[1], p[2]);
|
|
89
|
+
leg.castShadow = true;
|
|
90
|
+
g.add(leg);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
return g;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'fridge',
|
|
6
|
+
name: 'Fridge',
|
|
7
|
+
category: 'kitchen',
|
|
8
|
+
icon: 'Fr',
|
|
9
|
+
gridW: 1, gridD: 1, height: 1.8,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
// Main body — dark brushed metallic
|
|
14
|
+
var body = new THREE.Mesh(
|
|
15
|
+
new THREE.BoxGeometry(0.70, 1.80, 0.60),
|
|
16
|
+
mat(0x16181d, { roughness: 0.30, metalness: 0.45 })
|
|
17
|
+
);
|
|
18
|
+
body.position.y = 0.90;
|
|
19
|
+
body.castShadow = true;
|
|
20
|
+
body.receiveShadow = true;
|
|
21
|
+
g.add(body);
|
|
22
|
+
|
|
23
|
+
// Door seam line (horizontal divide — top fridge / bottom freezer)
|
|
24
|
+
var seam = new THREE.Mesh(
|
|
25
|
+
new THREE.BoxGeometry(0.68, 0.008, 0.012),
|
|
26
|
+
mat(0x333333, { roughness: 0.60 })
|
|
27
|
+
);
|
|
28
|
+
seam.position.set(0, 1.10, 0.305);
|
|
29
|
+
g.add(seam);
|
|
30
|
+
|
|
31
|
+
// Top section door face (slightly lighter)
|
|
32
|
+
var topDoor = new THREE.Mesh(
|
|
33
|
+
new THREE.BoxGeometry(0.68, 0.68, 0.01),
|
|
34
|
+
mat(0x1c1f26, { roughness: 0.28, metalness: 0.40 })
|
|
35
|
+
);
|
|
36
|
+
topDoor.position.set(0, 1.45, 0.305);
|
|
37
|
+
g.add(topDoor);
|
|
38
|
+
|
|
39
|
+
// Bottom freezer door face
|
|
40
|
+
var botDoor = new THREE.Mesh(
|
|
41
|
+
new THREE.BoxGeometry(0.68, 0.40, 0.01),
|
|
42
|
+
mat(0x1c1f26, { roughness: 0.28, metalness: 0.40 })
|
|
43
|
+
);
|
|
44
|
+
botDoor.position.set(0, 0.62, 0.305);
|
|
45
|
+
g.add(botDoor);
|
|
46
|
+
|
|
47
|
+
// Chrome handle — top door
|
|
48
|
+
var handleMat = PAL.chrome();
|
|
49
|
+
var handleGeo = new THREE.CylinderGeometry(0.014, 0.014, 0.42, 10);
|
|
50
|
+
var handleTop = new THREE.Mesh(handleGeo, handleMat);
|
|
51
|
+
handleTop.position.set(0.28, 1.50, 0.322);
|
|
52
|
+
handleTop.castShadow = true;
|
|
53
|
+
g.add(handleTop);
|
|
54
|
+
|
|
55
|
+
// Handle mounts (top)
|
|
56
|
+
var mountGeo = new THREE.BoxGeometry(0.022, 0.022, 0.025);
|
|
57
|
+
[1.29, 1.71].forEach(function(y) {
|
|
58
|
+
var mount = new THREE.Mesh(mountGeo, PAL.chromeBrushed());
|
|
59
|
+
mount.position.set(0.28, y, 0.32);
|
|
60
|
+
g.add(mount);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Chrome handle — bottom freezer door
|
|
64
|
+
var handleBot = new THREE.Mesh(
|
|
65
|
+
new THREE.CylinderGeometry(0.014, 0.014, 0.28, 10),
|
|
66
|
+
handleMat
|
|
67
|
+
);
|
|
68
|
+
handleBot.position.set(0.28, 0.62, 0.322);
|
|
69
|
+
handleBot.castShadow = true;
|
|
70
|
+
g.add(handleBot);
|
|
71
|
+
|
|
72
|
+
// Small LED status dot (green)
|
|
73
|
+
var led = new THREE.Mesh(
|
|
74
|
+
new THREE.SphereGeometry(0.012, 8, 8),
|
|
75
|
+
mat(0x22c55e, { emissive: 0x22c55e, emissiveIntensity: 1.0 })
|
|
76
|
+
);
|
|
77
|
+
led.position.set(-0.24, 1.74, 0.308);
|
|
78
|
+
g.add(led);
|
|
79
|
+
|
|
80
|
+
// Thin ventilation grill at top back
|
|
81
|
+
var vent = new THREE.Mesh(
|
|
82
|
+
new THREE.BoxGeometry(0.60, 0.06, 0.50),
|
|
83
|
+
mat(0x0e1014, { roughness: 0.70 })
|
|
84
|
+
);
|
|
85
|
+
vent.position.set(0, 1.78, -0.02);
|
|
86
|
+
g.add(vent);
|
|
87
|
+
|
|
88
|
+
// Small black feet
|
|
89
|
+
var feetMat = mat(0x0a0a0a, { roughness: 0.90 });
|
|
90
|
+
var feetGeo = new THREE.BoxGeometry(0.06, 0.03, 0.06);
|
|
91
|
+
[[-0.28, 0.015, 0.24], [0.28, 0.015, 0.24], [-0.28, 0.015, -0.24], [0.28, 0.015, -0.24]].forEach(function(p) {
|
|
92
|
+
var foot = new THREE.Mesh(feetGeo, feetMat);
|
|
93
|
+
foot.position.set(p[0], p[1], p[2]);
|
|
94
|
+
g.add(foot);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
return g;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'gaming-chair',
|
|
6
|
+
name: 'Gaming Chair',
|
|
7
|
+
category: 'furniture',
|
|
8
|
+
icon: 'GC',
|
|
9
|
+
gridW: 1, gridD: 1, height: 1.35,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
// 5-star base
|
|
14
|
+
var baseDisc = new THREE.Mesh(
|
|
15
|
+
new THREE.CylinderGeometry(0.30, 0.30, 0.025, 5),
|
|
16
|
+
PAL.chrome()
|
|
17
|
+
);
|
|
18
|
+
baseDisc.position.y = 0.02;
|
|
19
|
+
baseDisc.castShadow = true;
|
|
20
|
+
g.add(baseDisc);
|
|
21
|
+
|
|
22
|
+
for (var i = 0; i < 5; i++) {
|
|
23
|
+
var arm = new THREE.Mesh(
|
|
24
|
+
new THREE.BoxGeometry(0.28, 0.025, 0.05),
|
|
25
|
+
PAL.chrome()
|
|
26
|
+
);
|
|
27
|
+
arm.position.y = 0.02;
|
|
28
|
+
arm.rotation.y = (i / 5) * Math.PI * 2;
|
|
29
|
+
arm.castShadow = true;
|
|
30
|
+
g.add(arm);
|
|
31
|
+
|
|
32
|
+
var wheel = new THREE.Mesh(
|
|
33
|
+
new THREE.CylinderGeometry(0.035, 0.035, 0.045, 10),
|
|
34
|
+
mat(0x1a1a1a, { roughness: 0.9 })
|
|
35
|
+
);
|
|
36
|
+
var angle = (i / 5) * Math.PI * 2;
|
|
37
|
+
wheel.position.set(Math.sin(angle) * 0.28, 0.018, Math.cos(angle) * 0.28);
|
|
38
|
+
wheel.rotation.z = Math.PI / 2;
|
|
39
|
+
g.add(wheel);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Pneumatic post
|
|
43
|
+
var post = new THREE.Mesh(
|
|
44
|
+
new THREE.CylinderGeometry(0.045, 0.055, 0.44, 12),
|
|
45
|
+
PAL.chromeBrushed()
|
|
46
|
+
);
|
|
47
|
+
post.position.y = 0.255;
|
|
48
|
+
post.castShadow = true;
|
|
49
|
+
g.add(post);
|
|
50
|
+
|
|
51
|
+
// Seat shell (bucket-style, wider than office chair)
|
|
52
|
+
var seatShell = new THREE.Mesh(
|
|
53
|
+
new THREE.BoxGeometry(0.56, 0.06, 0.54),
|
|
54
|
+
mat(0x111318, { roughness: 0.5, metalness: 0.15 })
|
|
55
|
+
);
|
|
56
|
+
seatShell.position.y = 0.5;
|
|
57
|
+
seatShell.castShadow = true;
|
|
58
|
+
g.add(seatShell);
|
|
59
|
+
|
|
60
|
+
// Seat cushion — black main with red stripe
|
|
61
|
+
var seatCushion = new THREE.Mesh(
|
|
62
|
+
new THREE.BoxGeometry(0.50, 0.08, 0.50),
|
|
63
|
+
PAL.leatherBlack()
|
|
64
|
+
);
|
|
65
|
+
seatCushion.position.y = 0.545;
|
|
66
|
+
seatCushion.castShadow = true;
|
|
67
|
+
seatCushion.receiveShadow = true;
|
|
68
|
+
g.add(seatCushion);
|
|
69
|
+
|
|
70
|
+
// Center stripe on seat
|
|
71
|
+
var seatStripe = new THREE.Mesh(
|
|
72
|
+
new THREE.BoxGeometry(0.12, 0.09, 0.50),
|
|
73
|
+
mat(0xcc1111, { roughness: 0.65 })
|
|
74
|
+
);
|
|
75
|
+
seatStripe.position.y = 0.545;
|
|
76
|
+
g.add(seatStripe);
|
|
77
|
+
|
|
78
|
+
// Tall racing back (wider, taller than office chair)
|
|
79
|
+
var backBody = new THREE.Mesh(
|
|
80
|
+
new THREE.BoxGeometry(0.54, 0.76, 0.09),
|
|
81
|
+
mat(0x111318, { roughness: 0.5, metalness: 0.12 })
|
|
82
|
+
);
|
|
83
|
+
backBody.position.set(0, 0.95, -0.24);
|
|
84
|
+
backBody.castShadow = true;
|
|
85
|
+
g.add(backBody);
|
|
86
|
+
|
|
87
|
+
// Back cushion
|
|
88
|
+
var backCushion = new THREE.Mesh(
|
|
89
|
+
new THREE.BoxGeometry(0.46, 0.7, 0.07),
|
|
90
|
+
PAL.leatherBlack()
|
|
91
|
+
);
|
|
92
|
+
backCushion.position.set(0, 0.95, -0.20);
|
|
93
|
+
backCushion.castShadow = true;
|
|
94
|
+
g.add(backCushion);
|
|
95
|
+
|
|
96
|
+
// Back center accent stripe
|
|
97
|
+
var backStripe = new THREE.Mesh(
|
|
98
|
+
new THREE.BoxGeometry(0.12, 0.7, 0.08),
|
|
99
|
+
mat(0xcc1111, { roughness: 0.65 })
|
|
100
|
+
);
|
|
101
|
+
backStripe.position.set(0, 0.95, -0.19);
|
|
102
|
+
g.add(backStripe);
|
|
103
|
+
|
|
104
|
+
// Headrest (attached top)
|
|
105
|
+
var headrest = new THREE.Mesh(
|
|
106
|
+
new THREE.BoxGeometry(0.30, 0.20, 0.09),
|
|
107
|
+
PAL.leatherBlack()
|
|
108
|
+
);
|
|
109
|
+
headrest.position.set(0, 1.38, -0.24);
|
|
110
|
+
headrest.castShadow = true;
|
|
111
|
+
g.add(headrest);
|
|
112
|
+
|
|
113
|
+
// Headrest pad
|
|
114
|
+
var headPad = new THREE.Mesh(
|
|
115
|
+
new THREE.BoxGeometry(0.22, 0.15, 0.06),
|
|
116
|
+
mat(0xcc1111, { roughness: 0.65 })
|
|
117
|
+
);
|
|
118
|
+
headPad.position.set(0, 1.38, -0.20);
|
|
119
|
+
g.add(headPad);
|
|
120
|
+
|
|
121
|
+
// Lumbar support pillow
|
|
122
|
+
var lumbar = new THREE.Mesh(
|
|
123
|
+
new THREE.BoxGeometry(0.30, 0.16, 0.07),
|
|
124
|
+
mat(0xcc1111, { roughness: 0.65 })
|
|
125
|
+
);
|
|
126
|
+
lumbar.position.set(0, 0.66, -0.17);
|
|
127
|
+
lumbar.castShadow = true;
|
|
128
|
+
g.add(lumbar);
|
|
129
|
+
|
|
130
|
+
// Armrests (height-adjustable style)
|
|
131
|
+
var armMat = mat(0x1a1a1a, { roughness: 0.7 });
|
|
132
|
+
var leftArmRest = new THREE.Mesh(
|
|
133
|
+
new THREE.BoxGeometry(0.08, 0.04, 0.24),
|
|
134
|
+
armMat
|
|
135
|
+
);
|
|
136
|
+
leftArmRest.position.set(-0.30, 0.74, -0.06);
|
|
137
|
+
leftArmRest.castShadow = true;
|
|
138
|
+
g.add(leftArmRest);
|
|
139
|
+
|
|
140
|
+
var rightArmRest = leftArmRest.clone();
|
|
141
|
+
rightArmRest.position.x = 0.30;
|
|
142
|
+
g.add(rightArmRest);
|
|
143
|
+
|
|
144
|
+
// Armrest posts
|
|
145
|
+
var lPost = new THREE.Mesh(new THREE.BoxGeometry(0.03, 0.22, 0.03), PAL.chromeBrushed());
|
|
146
|
+
lPost.position.set(-0.30, 0.63, -0.06);
|
|
147
|
+
g.add(lPost);
|
|
148
|
+
var rPost = lPost.clone();
|
|
149
|
+
rPost.position.x = 0.30;
|
|
150
|
+
g.add(rPost);
|
|
151
|
+
|
|
152
|
+
return g;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'gaming-desk',
|
|
6
|
+
name: 'Gaming Desk',
|
|
7
|
+
category: 'furniture',
|
|
8
|
+
icon: 'GD',
|
|
9
|
+
gridW: 3, gridD: 1, height: 0.76,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
// Main top surface (wide section)
|
|
14
|
+
var mainTop = new THREE.Mesh(
|
|
15
|
+
new THREE.BoxGeometry(2.2, 0.04, 1.0),
|
|
16
|
+
mat(0x111318, { roughness: 0.28, metalness: 0.08 })
|
|
17
|
+
);
|
|
18
|
+
mainTop.position.y = 0.76;
|
|
19
|
+
mainTop.castShadow = true;
|
|
20
|
+
mainTop.receiveShadow = true;
|
|
21
|
+
g.add(mainTop);
|
|
22
|
+
|
|
23
|
+
// L-wing (right extension)
|
|
24
|
+
var wing = new THREE.Mesh(
|
|
25
|
+
new THREE.BoxGeometry(1.0, 0.04, 0.7),
|
|
26
|
+
mat(0x111318, { roughness: 0.28, metalness: 0.08 })
|
|
27
|
+
);
|
|
28
|
+
wing.position.set(1.1, 0.76, -0.15);
|
|
29
|
+
wing.castShadow = true;
|
|
30
|
+
wing.receiveShadow = true;
|
|
31
|
+
g.add(wing);
|
|
32
|
+
|
|
33
|
+
// Monitor riser platform
|
|
34
|
+
var riser = new THREE.Mesh(
|
|
35
|
+
new THREE.BoxGeometry(1.4, 0.08, 0.28),
|
|
36
|
+
mat(0x1a1c22, { roughness: 0.45, metalness: 0.12 })
|
|
37
|
+
);
|
|
38
|
+
riser.position.set(-0.2, 0.82, -0.28);
|
|
39
|
+
riser.castShadow = true;
|
|
40
|
+
g.add(riser);
|
|
41
|
+
|
|
42
|
+
// Riser legs (2 small supports)
|
|
43
|
+
var riserLegMat = mat(0x2a2d35, { roughness: 0.5 });
|
|
44
|
+
var riserLeg = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.08, 0.06), riserLegMat);
|
|
45
|
+
riserLeg.position.set(-0.85, 0.78, -0.28);
|
|
46
|
+
g.add(riserLeg);
|
|
47
|
+
var riserLeg2 = riserLeg.clone();
|
|
48
|
+
riserLeg2.position.x = 0.45;
|
|
49
|
+
g.add(riserLeg2);
|
|
50
|
+
|
|
51
|
+
// RGB LED strip along front edge (emissive cyan)
|
|
52
|
+
var led = new THREE.Mesh(
|
|
53
|
+
new THREE.BoxGeometry(2.2, 0.012, 0.015),
|
|
54
|
+
mat(0x06b6d4, { emissive: 0x06b6d4, emissiveIntensity: 0.9, roughness: 0.3 })
|
|
55
|
+
);
|
|
56
|
+
led.position.set(0, 0.742, 0.508);
|
|
57
|
+
g.add(led);
|
|
58
|
+
|
|
59
|
+
// LED strip on wing front edge
|
|
60
|
+
var ledWing = new THREE.Mesh(
|
|
61
|
+
new THREE.BoxGeometry(1.0, 0.012, 0.015),
|
|
62
|
+
mat(0x06b6d4, { emissive: 0x06b6d4, emissiveIntensity: 0.9, roughness: 0.3 })
|
|
63
|
+
);
|
|
64
|
+
ledWing.position.set(1.1, 0.742, 0.157);
|
|
65
|
+
g.add(ledWing);
|
|
66
|
+
|
|
67
|
+
// Cable channel tray (under desk, rear)
|
|
68
|
+
var cableTray = new THREE.Mesh(
|
|
69
|
+
new THREE.BoxGeometry(1.8, 0.04, 0.08),
|
|
70
|
+
mat(0x1a1c22, { roughness: 0.8 })
|
|
71
|
+
);
|
|
72
|
+
cableTray.position.set(0, 0.58, -0.44);
|
|
73
|
+
g.add(cableTray);
|
|
74
|
+
|
|
75
|
+
// 4 legs (angular, steel-look)
|
|
76
|
+
var legMat = mat(0x1e2128, { roughness: 0.3, metalness: 0.55 });
|
|
77
|
+
var legGeo = new THREE.BoxGeometry(0.07, 0.74, 0.07);
|
|
78
|
+
var mainLegs = [[-0.97, 0.37, 0.44], [0.77, 0.37, 0.44], [-0.97, 0.37, -0.44]];
|
|
79
|
+
mainLegs.forEach(function(p) {
|
|
80
|
+
var leg = new THREE.Mesh(legGeo, legMat);
|
|
81
|
+
leg.position.set(p[0], p[1], p[2]);
|
|
82
|
+
leg.castShadow = true;
|
|
83
|
+
g.add(leg);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Wing leg
|
|
87
|
+
var wingLeg = new THREE.Mesh(
|
|
88
|
+
new THREE.BoxGeometry(0.07, 0.74, 0.07),
|
|
89
|
+
legMat
|
|
90
|
+
);
|
|
91
|
+
wingLeg.position.set(1.55, 0.37, -0.28);
|
|
92
|
+
wingLeg.castShadow = true;
|
|
93
|
+
g.add(wingLeg);
|
|
94
|
+
|
|
95
|
+
// Connecting crossbar
|
|
96
|
+
var crossbar = new THREE.Mesh(
|
|
97
|
+
new THREE.BoxGeometry(0.04, 0.04, 0.9),
|
|
98
|
+
legMat
|
|
99
|
+
);
|
|
100
|
+
crossbar.position.set(-0.97, 0.28, 0);
|
|
101
|
+
g.add(crossbar);
|
|
102
|
+
|
|
103
|
+
return g;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { mat, PAL } from './materials.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
id: 'glass-door',
|
|
6
|
+
name: 'Glass Door',
|
|
7
|
+
category: 'structural',
|
|
8
|
+
icon: 'GD',
|
|
9
|
+
gridW: 2, gridD: 1, height: 2.5,
|
|
10
|
+
factory: function() {
|
|
11
|
+
var g = new THREE.Group();
|
|
12
|
+
|
|
13
|
+
// Frameless glass panel
|
|
14
|
+
var glass = new THREE.Mesh(
|
|
15
|
+
new THREE.BoxGeometry(1.2, 2.5, 0.015),
|
|
16
|
+
PAL.glass()
|
|
17
|
+
);
|
|
18
|
+
glass.receiveShadow = true;
|
|
19
|
+
g.add(glass);
|
|
20
|
+
|
|
21
|
+
// Chrome header bar
|
|
22
|
+
var header = new THREE.Mesh(
|
|
23
|
+
new THREE.BoxGeometry(1.3, 0.07, 0.06),
|
|
24
|
+
PAL.chrome()
|
|
25
|
+
);
|
|
26
|
+
header.position.y = 1.285;
|
|
27
|
+
header.castShadow = true;
|
|
28
|
+
g.add(header);
|
|
29
|
+
|
|
30
|
+
// Chrome floor threshold
|
|
31
|
+
var threshold = new THREE.Mesh(
|
|
32
|
+
new THREE.BoxGeometry(1.3, 0.04, 0.06),
|
|
33
|
+
PAL.chromeBrushed()
|
|
34
|
+
);
|
|
35
|
+
threshold.position.y = -1.23;
|
|
36
|
+
g.add(threshold);
|
|
37
|
+
|
|
38
|
+
// Chrome pull handle (horizontal bar, both sides)
|
|
39
|
+
var handleMat = PAL.chrome();
|
|
40
|
+
var pullBar = new THREE.Mesh(
|
|
41
|
+
new THREE.CylinderGeometry(0.02, 0.02, 0.35, 10),
|
|
42
|
+
handleMat
|
|
43
|
+
);
|
|
44
|
+
pullBar.rotation.z = Math.PI / 2;
|
|
45
|
+
pullBar.position.set(0, 0.1, 0.05);
|
|
46
|
+
pullBar.castShadow = true;
|
|
47
|
+
g.add(pullBar);
|
|
48
|
+
|
|
49
|
+
var pullBarBack = pullBar.clone();
|
|
50
|
+
pullBarBack.position.z = -0.05;
|
|
51
|
+
g.add(pullBarBack);
|
|
52
|
+
|
|
53
|
+
// Handle end caps
|
|
54
|
+
var capGeo = new THREE.SphereGeometry(0.022, 8, 6);
|
|
55
|
+
var capL = new THREE.Mesh(capGeo, handleMat);
|
|
56
|
+
capL.position.set(-0.175, 0.1, 0.05);
|
|
57
|
+
g.add(capL);
|
|
58
|
+
var capR = new THREE.Mesh(capGeo, handleMat);
|
|
59
|
+
capR.position.set(0.175, 0.1, 0.05);
|
|
60
|
+
g.add(capR);
|
|
61
|
+
|
|
62
|
+
// Subtle tint line at mid height
|
|
63
|
+
var tintLine = new THREE.Mesh(
|
|
64
|
+
new THREE.BoxGeometry(1.2, 0.02, 0.016),
|
|
65
|
+
mat(0x88aacc, { transparent: true, opacity: 0.4 })
|
|
66
|
+
);
|
|
67
|
+
tintLine.position.y = -0.3;
|
|
68
|
+
g.add(tintLine);
|
|
69
|
+
|
|
70
|
+
return g;
|
|
71
|
+
}
|
|
72
|
+
};
|