@chatlychat/world 0.0.0-stage → 0.2.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.
Files changed (88) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/LICENSE +21 -0
  3. package/README.md +184 -2
  4. package/dist/agent.d.ts +63 -0
  5. package/dist/agent.d.ts.map +1 -0
  6. package/dist/agent.js +251 -0
  7. package/dist/agent.js.map +1 -0
  8. package/dist/bubble.d.ts +36 -0
  9. package/dist/bubble.d.ts.map +1 -0
  10. package/dist/bubble.js +108 -0
  11. package/dist/bubble.js.map +1 -0
  12. package/dist/capabilities.d.ts +77 -0
  13. package/dist/capabilities.d.ts.map +1 -0
  14. package/dist/capabilities.js +129 -0
  15. package/dist/capabilities.js.map +1 -0
  16. package/dist/cards.d.ts +51 -0
  17. package/dist/cards.d.ts.map +1 -0
  18. package/dist/cards.js +136 -0
  19. package/dist/cards.js.map +1 -0
  20. package/dist/composer.d.ts +25 -0
  21. package/dist/composer.d.ts.map +1 -0
  22. package/dist/composer.js +53 -0
  23. package/dist/composer.js.map +1 -0
  24. package/dist/handlers.d.ts +26 -0
  25. package/dist/handlers.d.ts.map +1 -0
  26. package/dist/handlers.js +41 -0
  27. package/dist/handlers.js.map +1 -0
  28. package/dist/index.d.ts +27 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +25 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/input.d.ts +46 -0
  33. package/dist/input.d.ts.map +1 -0
  34. package/dist/input.js +89 -0
  35. package/dist/input.js.map +1 -0
  36. package/dist/layout.d.ts +24 -0
  37. package/dist/layout.d.ts.map +1 -0
  38. package/dist/layout.js +69 -0
  39. package/dist/layout.js.map +1 -0
  40. package/dist/model.d.ts +57 -0
  41. package/dist/model.d.ts.map +1 -0
  42. package/dist/model.js +86 -0
  43. package/dist/model.js.map +1 -0
  44. package/dist/motion.d.ts +27 -0
  45. package/dist/motion.d.ts.map +1 -0
  46. package/dist/motion.js +65 -0
  47. package/dist/motion.js.map +1 -0
  48. package/dist/panel.d.ts +77 -0
  49. package/dist/panel.d.ts.map +1 -0
  50. package/dist/panel.js +214 -0
  51. package/dist/panel.js.map +1 -0
  52. package/dist/picks.d.ts +45 -0
  53. package/dist/picks.d.ts.map +1 -0
  54. package/dist/picks.js +186 -0
  55. package/dist/picks.js.map +1 -0
  56. package/dist/selection.d.ts +14 -0
  57. package/dist/selection.d.ts.map +1 -0
  58. package/dist/selection.js +21 -0
  59. package/dist/selection.js.map +1 -0
  60. package/dist/text.d.ts +26 -0
  61. package/dist/text.d.ts.map +1 -0
  62. package/dist/text.js +100 -0
  63. package/dist/text.js.map +1 -0
  64. package/dist/theme-apply.d.ts +19 -0
  65. package/dist/theme-apply.d.ts.map +1 -0
  66. package/dist/theme-apply.js +88 -0
  67. package/dist/theme-apply.js.map +1 -0
  68. package/dist/types.d.ts +108 -0
  69. package/dist/types.d.ts.map +1 -0
  70. package/dist/types.js +41 -0
  71. package/dist/types.js.map +1 -0
  72. package/dist/visemes.d.ts +28 -0
  73. package/dist/visemes.d.ts.map +1 -0
  74. package/dist/visemes.js +42 -0
  75. package/dist/visemes.js.map +1 -0
  76. package/dist/vrm.d.ts +97 -0
  77. package/dist/vrm.d.ts.map +1 -0
  78. package/dist/vrm.js +212 -0
  79. package/dist/vrm.js.map +1 -0
  80. package/dist/world-api.d.ts +39 -0
  81. package/dist/world-api.d.ts.map +1 -0
  82. package/dist/world-api.js +2 -0
  83. package/dist/world-api.js.map +1 -0
  84. package/dist/world.d.ts +5 -0
  85. package/dist/world.d.ts.map +1 -0
  86. package/dist/world.js +414 -0
  87. package/dist/world.js.map +1 -0
  88. package/package.json +75 -3
package/dist/motion.js ADDED
@@ -0,0 +1,65 @@
1
+ export const easeOut = (t) => 1 - (1 - t) ** 3;
2
+ export class Motion {
3
+ tweens = new Set();
4
+ reduced;
5
+ constructor(reduced) {
6
+ this.reduced = reduced;
7
+ }
8
+ /** `apply(0..1)`; always ends with `apply(1)`. */
9
+ run(durationMs, apply) {
10
+ if (this.reduced || durationMs <= 0) {
11
+ apply(1);
12
+ return;
13
+ }
14
+ apply(0);
15
+ this.tweens.add({ elapsed: 0, duration: durationMs, apply });
16
+ }
17
+ update(dtMs) {
18
+ for (const tw of [...this.tweens]) {
19
+ tw.elapsed += dtMs;
20
+ const t = Math.min(1, tw.elapsed / tw.duration);
21
+ tw.apply(easeOut(t));
22
+ if (t >= 1) {
23
+ this.tweens.delete(tw);
24
+ }
25
+ }
26
+ }
27
+ get running() {
28
+ return this.tweens.size;
29
+ }
30
+ clear() {
31
+ this.tweens.clear();
32
+ }
33
+ }
34
+ /** Set opacity on every material under `obj`. Materials are made transparent first. */
35
+ export function setOpacity(obj, k) {
36
+ obj.traverse((o) => {
37
+ const mats = o.material;
38
+ for (const m of Array.isArray(mats) ? mats : mats === undefined ? [] : [mats]) {
39
+ const mat = m;
40
+ mat.userData.base ??= mat.opacity;
41
+ mat.transparent = true;
42
+ mat.opacity = mat.userData.base * k;
43
+ }
44
+ });
45
+ }
46
+ /** The theme's `motionEntrance` applied to a freshly built object. */
47
+ export function enter(motion, obj, kind, durationMs = 250) {
48
+ if (kind === 'none') {
49
+ return;
50
+ }
51
+ const y = obj.position.y;
52
+ const s = obj.scale.x;
53
+ motion.run(durationMs, (t) => {
54
+ if (kind === 'fade') {
55
+ setOpacity(obj, t);
56
+ }
57
+ else if (kind === 'scale') {
58
+ obj.scale.setScalar(Math.max(0.001, s * t));
59
+ }
60
+ else {
61
+ obj.position.y = y - 0.1 * (1 - t);
62
+ }
63
+ });
64
+ }
65
+ //# sourceMappingURL=motion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motion.js","sourceRoot":"","sources":["../src/motion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * The world-space panel and its composer, and how they follow the viewer.
3
+ *
4
+ * A panel is NEVER head-locked. A surface welded to the head is nauseating
5
+ * within seconds, so a `locked` placement is honoured as `lazy` — the host
6
+ * abilities the world resolves against simply do not offer it. The three
7
+ * modes are:
8
+ *
9
+ * - `fixed`: placed once, where the viewer was looking, and left there;
10
+ * - `lazy`: left alone until the viewer turns or walks past a dead zone, then
11
+ * eased into place (snapped, with reduced motion);
12
+ * - `wrist`: carried on a host-supplied controller or hand.
13
+ */
14
+ import { Group, Vector3, type Camera, type Object3D } from 'three';
15
+ import type { PanelFollow } from './types.js';
16
+ import type { ComposerRenderProps, PanelRenderProps, ResolvedWorldPlacement } from '@chatlychat/core';
17
+ /** ─────────────────────────── follow math (pure) ─────────────────────────── */
18
+ export interface FollowPose {
19
+ readonly x: number;
20
+ readonly y: number;
21
+ readonly z: number;
22
+ readonly yaw: number;
23
+ }
24
+ export interface FollowState extends FollowPose {
25
+ readonly chasing: boolean;
26
+ }
27
+ export declare const DEAD_YAW: number;
28
+ export declare const DEAD_METRES = 0.5;
29
+ export declare const wrapAngle: (a: number) => number;
30
+ /**
31
+ * One step of lazy follow, with hysteresis: the panel stays put until the
32
+ * viewer leaves the dead zone, then chases until it has all but arrived, so it
33
+ * never creeps on every small head movement.
34
+ */
35
+ export declare function lazyStep(cur: FollowState, want: FollowPose, dtMs: number, reduced: boolean): FollowState;
36
+ /** The follow mode a resolved placement means. `locked` never survives resolution, but be sure. */
37
+ export declare function followMode(placement: ResolvedWorldPlacement, override?: PanelFollow): PanelFollow;
38
+ export interface RigContext {
39
+ readonly camera: Camera;
40
+ readonly reduced: boolean;
41
+ readonly agent: Object3D | null;
42
+ readonly place: Object3D | Vector3 | null;
43
+ readonly wrist: Object3D | null;
44
+ }
45
+ /** Holds the panel + composer group and moves it per the follow mode. */
46
+ export declare class PanelRig {
47
+ private readonly parent;
48
+ private readonly placement;
49
+ private mode;
50
+ readonly group: Group;
51
+ private state;
52
+ private placed;
53
+ private wristed;
54
+ constructor(parent: Object3D, placement: ResolvedWorldPlacement, mode: PanelFollow);
55
+ get follow(): PanelFollow;
56
+ /** Where the placement wants the panel, in parent-local space. */
57
+ private want;
58
+ update(dtMs: number, ctx: RigContext): void;
59
+ }
60
+ export declare const PANEL_LABELS: {
61
+ readonly you: "You";
62
+ readonly agent: "Agent";
63
+ readonly typing: "is typing…";
64
+ };
65
+ export declare function defaultPanel(props: PanelRenderProps): Object3D;
66
+ /** What the default composer reads and calls. The world owns one; an override uses `props.send`. */
67
+ export interface ComposerState {
68
+ readonly draft: string;
69
+ readonly submit: () => void;
70
+ readonly requestInput: () => void;
71
+ }
72
+ export declare const COMPOSER_LABELS: {
73
+ readonly placeholder: "Reply…";
74
+ readonly send: "Send";
75
+ };
76
+ export declare function defaultComposer(props: ComposerRenderProps, state: ComposerState, width: number): Object3D;
77
+ //# sourceMappingURL=panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../src/panel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EACL,KAAK,EAIL,OAAO,EACP,KAAK,MAAM,EACX,KAAK,QAAQ,EACd,MAAM,OAAO,CAAC;AAOf,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EACV,mBAAmB,EACnB,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,kBAAkB,CAAC;AAE1B,iFAAiF;AAEjF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,eAAO,MAAM,QAAQ,QAAuB,CAAC;AAC7C,eAAO,MAAM,WAAW,MAAM,CAAC;AAK/B,eAAO,MAAM,SAAS,MAAO,MAAM,KAAG,MAA8C,CAAC;AAErF;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,GACf,WAAW,CAiBb;AAED,mGAAmG;AACnG,wBAAgB,UAAU,CAAC,SAAS,EAAE,sBAAsB,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,WAAW,CAEjG;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI,CAAC;IAC1C,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;CACjC;AAID,yEAAyE;AACzE,qBAAa,QAAQ;IAOjB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,IAAI;IARd,SAAgB,KAAK,QAAe;IACpC,OAAO,CAAC,KAAK,CAA6D;IAC1E,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAyB;gBAGrB,MAAM,EAAE,QAAQ,EAChB,SAAS,EAAE,sBAAsB,EAC1C,IAAI,EAAE,WAAW;IAM3B,IAAW,MAAM,IAAI,WAAW,CAE/B;IAED,kEAAkE;IAClE,OAAO,CAAC,IAAI;IAqCL,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,IAAI;CA6BnD;AAKD,eAAO,MAAM,YAAY;;;;CAAgE,CAAC;AAE1F,wBAAgB,YAAY,CAAC,KAAK,EAAE,gBAAgB,GAAG,QAAQ,CA0B9D;AAED,oGAAoG;AACpG,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,IAAI,CAAC;CACnC;AAED,eAAO,MAAM,eAAe;;;CAAmD,CAAC;AAIhF,wBAAgB,eAAe,CAC7B,KAAK,EAAE,mBAAmB,EAC1B,KAAK,EAAE,aAAa,EACpB,KAAK,EAAE,MAAM,GACZ,QAAQ,CAiDV"}
package/dist/panel.js ADDED
@@ -0,0 +1,214 @@
1
+ /**
2
+ * The world-space panel and its composer, and how they follow the viewer.
3
+ *
4
+ * A panel is NEVER head-locked. A surface welded to the head is nauseating
5
+ * within seconds, so a `locked` placement is honoured as `lazy` — the host
6
+ * abilities the world resolves against simply do not offer it. The three
7
+ * modes are:
8
+ *
9
+ * - `fixed`: placed once, where the viewer was looking, and left there;
10
+ * - `lazy`: left alone until the viewer turns or walks past a dead zone, then
11
+ * eased into place (snapped, with reduced motion);
12
+ * - `wrist`: carried on a host-supplied controller or hand.
13
+ */
14
+ import { Group, Mesh, MeshBasicMaterial, PlaneGeometry, Vector3, } from 'three';
15
+ import { interactive } from './input.js';
16
+ import { createTextMesh } from './text.js';
17
+ import { panelBacking } from './theme-apply.js';
18
+ import { WORLD_CONTRACT } from './types.js';
19
+ export const DEAD_YAW = (35 * Math.PI) / 180;
20
+ export const DEAD_METRES = 0.5;
21
+ const STOP_YAW = (2 * Math.PI) / 180;
22
+ const STOP_METRES = 0.03;
23
+ const RATE_PER_S = 4;
24
+ export const wrapAngle = (a) => Math.atan2(Math.sin(a), Math.cos(a));
25
+ /**
26
+ * One step of lazy follow, with hysteresis: the panel stays put until the
27
+ * viewer leaves the dead zone, then chases until it has all but arrived, so it
28
+ * never creeps on every small head movement.
29
+ */
30
+ export function lazyStep(cur, want, dtMs, reduced) {
31
+ const dx = want.x - cur.x;
32
+ const dy = want.y - cur.y;
33
+ const dz = want.z - cur.z;
34
+ const dist = Math.hypot(dx, dy, dz);
35
+ const dyaw = wrapAngle(want.yaw - cur.yaw);
36
+ const chasing = cur.chasing || Math.abs(dyaw) > DEAD_YAW || dist > DEAD_METRES;
37
+ if (!chasing) {
38
+ return cur;
39
+ }
40
+ if (reduced) {
41
+ return { ...want, chasing: false };
42
+ }
43
+ const k = 1 - Math.exp((-RATE_PER_S * dtMs) / 1000);
44
+ const next = { x: cur.x + dx * k, y: cur.y + dy * k, z: cur.z + dz * k, yaw: cur.yaw + dyaw * k };
45
+ const arrived = dist * (1 - k) < STOP_METRES && Math.abs(dyaw) * (1 - k) < STOP_YAW;
46
+ return { ...next, chasing: !arrived };
47
+ }
48
+ /** The follow mode a resolved placement means. `locked` never survives resolution, but be sure. */
49
+ export function followMode(placement, override) {
50
+ return override ?? (placement.follow === 'none' ? 'fixed' : 'lazy');
51
+ }
52
+ const WRIST_WIDTH = 0.3;
53
+ /** Holds the panel + composer group and moves it per the follow mode. */
54
+ export class PanelRig {
55
+ parent;
56
+ placement;
57
+ mode;
58
+ group = new Group();
59
+ state = { x: 0, y: 0, z: 0, yaw: 0, chasing: false };
60
+ placed = false;
61
+ wristed = null;
62
+ constructor(parent, placement, mode) {
63
+ this.parent = parent;
64
+ this.placement = placement;
65
+ this.mode = mode;
66
+ this.group.name = 'cl3-panel-rig';
67
+ parent.add(this.group);
68
+ }
69
+ get follow() {
70
+ return this.mode;
71
+ }
72
+ /** Where the placement wants the panel, in parent-local space. */
73
+ want(ctx) {
74
+ const p = this.placement;
75
+ const cam = ctx.camera.getWorldPosition(new Vector3());
76
+ const dir = ctx.camera.getWorldDirection(new Vector3());
77
+ const fwd = new Vector3(dir.x, 0, dir.z);
78
+ if (fwd.lengthSq() < 1e-6) {
79
+ fwd.set(0, 0, -1);
80
+ }
81
+ fwd.normalize();
82
+ let pos;
83
+ if (p.anchor === 'agent' && ctx.agent !== null) {
84
+ const a = ctx.agent.getWorldPosition(new Vector3());
85
+ const toCam = new Vector3(cam.x - a.x, 0, cam.z - a.z).normalize();
86
+ pos = a.add(toCam.multiplyScalar(p.distanceMetres)).setY(a.y + 1.4 + p.heightMetres);
87
+ }
88
+ else if (p.anchor === 'place' && ctx.place !== null) {
89
+ const o = ctx.place instanceof Vector3
90
+ ? ctx.place.clone()
91
+ : ctx.place.getWorldPosition(new Vector3());
92
+ pos = o.setY(o.y + 1.2 + p.heightMetres);
93
+ }
94
+ else if (p.anchor === 'world') {
95
+ pos = this.parent.getWorldPosition(new Vector3());
96
+ pos.y += 1.4 + p.heightMetres;
97
+ pos.z -= p.distanceMetres;
98
+ }
99
+ else {
100
+ pos = cam.clone().addScaledVector(fwd, p.distanceMetres);
101
+ pos.y = cam.y + p.heightMetres;
102
+ }
103
+ this.parent.worldToLocal(pos);
104
+ const camLocal = this.parent.worldToLocal(cam.clone());
105
+ const yaw = p.billboard === 'none' && this.placed
106
+ ? this.state.yaw
107
+ : Math.atan2(camLocal.x - pos.x, camLocal.z - pos.z);
108
+ return { x: pos.x, y: pos.y, z: pos.z, yaw };
109
+ }
110
+ update(dtMs, ctx) {
111
+ if (this.mode === 'wrist' && ctx.wrist !== null) {
112
+ if (this.wristed !== ctx.wrist) {
113
+ ctx.wrist.add(this.group);
114
+ this.wristed = ctx.wrist;
115
+ this.group.position.set(0, 0.12, -0.05);
116
+ this.group.rotation.set(-Math.PI / 3, 0, 0);
117
+ this.group.scale.setScalar(WRIST_WIDTH / this.placement.widthMetres);
118
+ }
119
+ return;
120
+ }
121
+ if (this.wristed !== null) {
122
+ // The wrist went away: come back into the scene rather than vanish with it.
123
+ this.parent.add(this.group);
124
+ this.group.scale.setScalar(1);
125
+ this.group.rotation.set(0, 0, 0);
126
+ this.wristed = null;
127
+ this.placed = false;
128
+ }
129
+ const want = this.want(ctx);
130
+ if (!this.placed) {
131
+ this.state = { ...want, chasing: false };
132
+ this.placed = true;
133
+ }
134
+ else if (this.mode === 'lazy') {
135
+ this.state = lazyStep(this.state, want, dtMs, ctx.reduced);
136
+ }
137
+ this.group.position.set(this.state.x, this.state.y, this.state.z);
138
+ this.group.rotation.set(0, this.state.yaw, 0);
139
+ }
140
+ }
141
+ /** ─────────────────────────── default renderers ─────────────────────────── */
142
+ const MAX_LINES = 6;
143
+ export const PANEL_LABELS = { you: 'You', agent: 'Agent', typing: 'is typing…' };
144
+ export function defaultPanel(props) {
145
+ const { theme, placement } = props;
146
+ const width = placement.widthMetres;
147
+ const lines = props.messages
148
+ .filter((m) => m.deletedAt === null && !m.hiddenFromContact && m.kind !== 'system_event' && m.body !== '')
149
+ .slice(-MAX_LINES)
150
+ .map((m) => `${m.authorType === 'contact' ? PANEL_LABELS.you : PANEL_LABELS.agent}: ${m.body}`);
151
+ if (props.typing !== null) {
152
+ lines.push(`${props.typing.displayName ?? PANEL_LABELS.agent} ${PANEL_LABELS.typing}`);
153
+ }
154
+ const g = new Group();
155
+ g.name = WORLD_CONTRACT.objects.panel;
156
+ const text = createTextMesh(lines.join('\n'), theme, { maxWidthMetres: width - 0.04 });
157
+ const [, th] = text.userData['size'];
158
+ const height = th + 0.04;
159
+ const back = panelBacking(theme, width, height);
160
+ if (back !== null) {
161
+ g.add(back);
162
+ }
163
+ text.position.z = 0.002;
164
+ g.add(text);
165
+ g.userData['size'] = [width, height];
166
+ return g;
167
+ }
168
+ export const COMPOSER_LABELS = { placeholder: 'Reply…', send: 'Send' };
169
+ const FIELD_H = 0.07;
170
+ const SEND_W = 0.12;
171
+ export function defaultComposer(props, state, width) {
172
+ const { theme } = props;
173
+ const g = new Group();
174
+ g.name = WORLD_CONTRACT.objects.composer;
175
+ const fieldW = width - SEND_W - 0.01;
176
+ const field = new Group();
177
+ field.position.x = -(width - fieldW) / 2;
178
+ const fb = panelBacking(theme, fieldW, FIELD_H);
179
+ if (fb !== null) {
180
+ field.add(fb);
181
+ }
182
+ else {
183
+ field.add(new Mesh(new PlaneGeometry(fieldW, FIELD_H), new MeshBasicMaterial({ visible: false })));
184
+ }
185
+ const shown = state.draft === '' ? COMPOSER_LABELS.placeholder : state.draft;
186
+ const label = createTextMesh(shown, theme, {
187
+ maxWidthMetres: fieldW - 0.02,
188
+ size: 0.8,
189
+ });
190
+ label.position.z = 0.002;
191
+ field.add(label);
192
+ interactive(field, 'field', state.requestInput);
193
+ g.add(field);
194
+ const send = new Group();
195
+ send.position.x = (width - SEND_W) / 2;
196
+ const sb = panelBacking({ ...theme, panelColor: theme.accentColor, panelMaterial: 'solid' }, SEND_W, FIELD_H);
197
+ if (sb !== null) {
198
+ send.add(sb);
199
+ }
200
+ const sl = createTextMesh(COMPOSER_LABELS.send, theme, {
201
+ maxWidthMetres: SEND_W,
202
+ size: 0.8,
203
+ color: theme.accentTextColor,
204
+ });
205
+ sl.position.z = 0.002;
206
+ send.add(sl);
207
+ if (!props.disabled) {
208
+ interactive(send, 'send', state.submit);
209
+ }
210
+ g.add(send);
211
+ g.userData['size'] = [width, FIELD_H];
212
+ return g;
213
+ }
214
+ //# sourceMappingURL=panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel.js","sourceRoot":"","sources":["../src/panel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * The picks: a grid of cards drawn from the latest card message, one of which
3
+ * can be selected and held. Selection is told to the thread before the world
4
+ * claims it; a refusal puts the card back.
5
+ *
6
+ * `theme` and `reduced` are read per call because both change under a live
7
+ * world (`setTheme`, `setReducedMotion`).
8
+ */
9
+ import { type ConversationMessage, type ResolvedWorldTheme, type ResolvedWorldPlacement } from '@chatlychat/core';
10
+ import { type Object3D } from 'three';
11
+ import { type GridBuild } from './cards.js';
12
+ import { type HandlerHooks } from './handlers.js';
13
+ import { type Motion } from './motion.js';
14
+ import { type SoundKind, type WorldOptions } from './types.js';
15
+ import type { cachedLoader } from './model.js';
16
+ import type { Selection } from './selection.js';
17
+ export type PickGrid = GridBuild & {
18
+ message: ConversationMessage;
19
+ cards: readonly Record<string, unknown>[];
20
+ };
21
+ export declare const named: (node: Object3D, name: string) => Object3D;
22
+ export interface PicksDeps {
23
+ conversation: WorldOptions['conversation'];
24
+ camera: WorldOptions['camera'];
25
+ renderers: WorldOptions['renderers'];
26
+ anchors: NonNullable<WorldOptions['anchors']>;
27
+ theme: () => ResolvedWorldTheme;
28
+ reduced: () => boolean;
29
+ placement: ResolvedWorldPlacement;
30
+ root: Object3D;
31
+ motion: Motion;
32
+ selection: Selection;
33
+ hooks: HandlerHooks;
34
+ loadModel: ReturnType<typeof cachedLoader>;
35
+ onError: (err: unknown) => void;
36
+ sound: (kind: SoundKind, at?: Object3D) => void;
37
+ }
38
+ export interface Picks {
39
+ grid: () => PickGrid | null;
40
+ select: (key: string) => Promise<void>;
41
+ release: () => void;
42
+ showGrid: (message: ConversationMessage) => void;
43
+ }
44
+ export declare function createPicks(deps: PicksDeps): Picks;
45
+ //# sourceMappingURL=picks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"picks.d.ts","sourceRoot":"","sources":["../src/picks.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAGL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC5B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAW,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE/C,OAAO,EAA6C,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AACvF,OAAO,EAA6B,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAG7E,OAAO,EAAE,KAAK,MAAM,EAAqB,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAkB,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG;IACjC,OAAO,EAAE,mBAAmB,CAAC;IAC7B,KAAK,EAAE,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;CAC3C,CAAC;AAEF,eAAO,MAAM,KAAK,SAAU,QAAQ,QAAQ,MAAM,KAAG,QAGpD,CAAC;AAEF,MAAM,WAAW,SAAS;IACxB,YAAY,EAAE,YAAY,CAAC,cAAc,CAAC,CAAC;IAC3C,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC/B,SAAS,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC;IACrC,OAAO,EAAE,WAAW,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC;IAC9C,KAAK,EAAE,MAAM,kBAAkB,CAAC;IAChC,OAAO,EAAE,MAAM,OAAO,CAAC;IACvB,SAAS,EAAE,sBAAsB,CAAC;IAClC,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IAC3C,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAChC,KAAK,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,QAAQ,KAAK,IAAI,CAAC;CACjD;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,QAAQ,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;CAClD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,KAAK,CA6MlD"}
package/dist/picks.js ADDED
@@ -0,0 +1,186 @@
1
+ import { Vector3 } from 'three';
2
+ import { buildGrid, cardKey, defaultCard, readCard } from './cards.js';
3
+ import { cardActions, makeHandlers } from './handlers.js';
4
+ import { interactive } from './input.js';
5
+ import { GRID_PLACEMENTS } from './layout.js';
6
+ import { enter, setOpacity } from './motion.js';
7
+ import { WORLD_CONTRACT } from './types.js';
8
+ export const named = (node, name) => {
9
+ node.name = node.name === '' ? name : node.name;
10
+ return node;
11
+ };
12
+ export function createPicks(deps) {
13
+ const { conversation, camera, renderers: r, anchors, theme, reduced, placement, root, motion, selection, hooks, loadModel, onError, sound, } = deps;
14
+ let grid = null;
15
+ let held = null;
16
+ const drawCard = (g, index) => {
17
+ const block = g.cards[index];
18
+ const key = cardKey(g.message, block, index);
19
+ const data = readCard(block);
20
+ const props = {
21
+ theme: theme(),
22
+ placement,
23
+ reducedMotion: reduced(),
24
+ block: { type: 'card', ...block },
25
+ message: g.message,
26
+ selected: selection.id === key,
27
+ ...makeHandlers(conversation, g.message, data.title, cardActions(block), hooks),
28
+ };
29
+ const node = named(r?.renderCard !== undefined
30
+ ? r.renderCard(props)
31
+ : defaultCard(props, { loadModel, onError }), WORLD_CONTRACT.objects.card);
32
+ node.userData['cardKey'] = key;
33
+ if (node.userData['cl3Handled'] !== true) {
34
+ interactive(node, 'card', () => void toggle(key));
35
+ }
36
+ return node;
37
+ };
38
+ const redraw = (key) => {
39
+ const e = key === null ? undefined : grid?.nodes.get(key);
40
+ if (grid === null || e === undefined) {
41
+ return;
42
+ }
43
+ const next = drawCard(grid, e.index);
44
+ next.position.copy(e.node.position);
45
+ next.rotation.copy(e.node.rotation);
46
+ const parent = e.node.parent;
47
+ if (parent !== null) {
48
+ // Same slot in the child list, so traversal order stays the card order.
49
+ parent.children.splice(parent.children.indexOf(e.node), 1, next);
50
+ next.parent = parent;
51
+ e.node.parent = null;
52
+ }
53
+ grid.nodes.set(key, { node: next, index: e.index });
54
+ };
55
+ const dropHeld = () => {
56
+ held?.removeFromParent();
57
+ held = null;
58
+ };
59
+ const showHeld = (key) => {
60
+ dropHeld();
61
+ if (grid === null) {
62
+ return;
63
+ }
64
+ const index = grid.nodes.get(key)?.index ?? 0;
65
+ const block = grid.cards[index];
66
+ const data = readCard(block);
67
+ const props = {
68
+ theme: theme(),
69
+ placement,
70
+ reducedMotion: reduced(),
71
+ block: { type: 'card', ...block },
72
+ message: grid.message,
73
+ release: () => release(),
74
+ ...makeHandlers(conversation, grid.message, data.title, cardActions(block), hooks),
75
+ };
76
+ const node = r?.renderPick !== undefined
77
+ ? r.renderPick(props)
78
+ : (() => {
79
+ const n = defaultCard({ ...props, selected: true }, { loadModel, onError });
80
+ n.name = WORLD_CONTRACT.objects.pick;
81
+ n.scale.setScalar(0.6);
82
+ return n;
83
+ })();
84
+ named(node, WORLD_CONTRACT.objects.pick);
85
+ if (node.userData['cl3Handled'] !== true) {
86
+ interactive(node, 'release', release);
87
+ }
88
+ if (anchors.hand !== undefined && anchors.hand !== null) {
89
+ anchors.hand.add(node);
90
+ }
91
+ else {
92
+ // Placed once, in front of where the visitor is looking — not carried on the head.
93
+ const dir = camera.getWorldDirection(new Vector3());
94
+ const at = camera.getWorldPosition(new Vector3()).addScaledVector(dir, 0.6);
95
+ at.y -= 0.25;
96
+ root.add(node);
97
+ node.position.copy(root.worldToLocal(at));
98
+ }
99
+ const y = node.position.y;
100
+ const k = theme().motionPick;
101
+ motion.run(k === 'none' ? 0 : 250, (t) => {
102
+ if (k === 'rise') {
103
+ node.position.y = y - 0.15 * (1 - t);
104
+ }
105
+ else if (k === 'drop') {
106
+ node.position.y = y + 0.15 * (1 - t);
107
+ }
108
+ else {
109
+ setOpacity(node, t);
110
+ }
111
+ });
112
+ held = node;
113
+ };
114
+ const select = async (key) => {
115
+ const e = grid?.nodes.get(key);
116
+ if (grid === null || e === undefined || selection.id === key) {
117
+ return;
118
+ }
119
+ const prev = selection.id;
120
+ const block = grid.cards[e.index];
121
+ selection.set(key);
122
+ redraw(prev);
123
+ redraw(key);
124
+ showHeld(key);
125
+ sound('pick', e.node);
126
+ try {
127
+ await makeHandlers(conversation, grid.message, readCard(block).title, [], hooks).select({
128
+ type: 'card.select',
129
+ card: typeof block['id'] === 'string' ? block['id'] : `c${String(e.index)}`,
130
+ message: grid.message.id,
131
+ });
132
+ sound('select', e.node);
133
+ }
134
+ catch (err) {
135
+ // The thread never heard about it, so the world must not claim it was picked.
136
+ if (selection.id === key) {
137
+ release();
138
+ }
139
+ onError(err);
140
+ }
141
+ };
142
+ function release() {
143
+ const prev = selection.id;
144
+ selection.set(null);
145
+ redraw(prev);
146
+ dropHeld();
147
+ }
148
+ const toggle = (key) => {
149
+ if (selection.id === key) {
150
+ release();
151
+ return Promise.resolve();
152
+ }
153
+ return select(key);
154
+ };
155
+ const showGrid = (message) => {
156
+ const blocks = message.blocks?.blocks ?? [];
157
+ const block = [...blocks].reverse().find((b) => b.type === 'card_grid' || b.type === 'card');
158
+ grid?.group.removeFromParent();
159
+ release();
160
+ grid = null;
161
+ if (block === undefined) {
162
+ return;
163
+ }
164
+ const cards = block.type === 'card'
165
+ ? [block]
166
+ : (block['cards'] ?? []);
167
+ const want = block['placement'];
168
+ const kind = GRID_PLACEMENTS.includes(want)
169
+ ? want
170
+ : 'arc';
171
+ const draft = { message, cards };
172
+ const built = buildGrid(kind, cards.length, theme(), (i) => drawCard(draft, i), (i) => cardKey(message, cards[i], i));
173
+ grid = Object.assign(built, { message, cards });
174
+ // Spawned where the viewer stands and faces now; then left alone.
175
+ const cam = camera.getWorldPosition(new Vector3());
176
+ const dir = camera.getWorldDirection(new Vector3());
177
+ built.group.position.copy(root.worldToLocal(cam));
178
+ built.group.rotation.y = Math.atan2(-dir.x, -dir.z);
179
+ root.add(built.group);
180
+ for (const { node } of built.nodes.values()) {
181
+ enter(motion, node, theme().motionEntrance);
182
+ }
183
+ };
184
+ return { grid: () => grid, select, release, showGrid };
185
+ }
186
+ //# sourceMappingURL=picks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"picks.js","sourceRoot":"","sources":["../src/picks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The shared selection: one picked card, visible to every renderer and to the
3
+ * host. A pick the visitor taps and a pick the host selects from its own
4
+ * inventory UI are the same event.
5
+ */
6
+ export type SelectionListener = (id: string | null) => void;
7
+ export declare class Selection {
8
+ private current;
9
+ private readonly listeners;
10
+ get id(): string | null;
11
+ set(id: string | null): void;
12
+ subscribe: (l: SelectionListener) => (() => void);
13
+ }
14
+ //# sourceMappingURL=selection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../src/selection.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;AAE5D,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;IAE1D,IAAW,EAAE,IAAI,MAAM,GAAG,IAAI,CAE7B;IAEM,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAU5B,SAAS,MAAO,iBAAiB,KAAG,CAAC,MAAM,IAAI,CAAC,CAGrD;CACH"}