@laplace.live/persona-sdk 1.20.0 → 1.22.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.
@@ -1,4 +1,4 @@
1
- import { AUTOMATION_BOUNDARY_KINDS } from "../wire/types.js";
1
+ import { AUTOMATION_SETUP_KINDS } from "../wire/types.js";
2
2
  import { isOneOf } from "./guards.js";
3
3
  /** Last path segment, tolerating both `/` and `\` separators. */
4
4
  export function fileBasename(path) {
@@ -28,21 +28,27 @@ export function motionSlots(files) {
28
28
  // English fallbacks; localizing clients keep their own map and use these for unknown kinds.
29
29
  const AUTOMATION_ACTION_KIND_LABELS = {
30
30
  'effect-toggle': 'Toggle Effect',
31
- 'effect-params': 'Effect Settings',
32
- 'effect-clip': 'Effect Clip',
31
+ 'effect-params': 'Apply Effect Settings',
32
+ 'effect-clip': 'Temporary Effect',
33
33
  'camera-pose': 'Camera Position',
34
- 'reset-camera': 'Reset Camera',
34
+ 'camera-reset': 'Reset Camera',
35
35
  'layer-visibility': 'Layer Visibility',
36
+ 'text-set': 'Set Text',
37
+ 'lyrics-play': 'Lyrics',
36
38
  'stream-mode': 'Stream Mode',
37
- 'switch-scene': 'Switch Scene',
38
- 'toggle-expression': 'Toggle Expression',
39
- 'play-motion': 'Play Motion',
40
- 'play-audio': 'Play Audio',
39
+ 'scene-switch': 'Switch Scene',
40
+ 'expression-toggle': 'Toggle Expression',
41
+ 'motion-play': 'Play Motion',
42
+ 'audio-play': 'Play Audio',
41
43
  'audio-control': 'Control Audio',
42
- 'play-camera-motion': 'Play Camera Motion',
43
- 'stop-camera-motion': 'Stop Camera Motion',
44
- 'remove-all-expressions': 'Clear All Expressions',
45
- 'load-model': 'Swap Model',
44
+ 'camera-motion-play': 'Play Camera Motion',
45
+ 'camera-motion-stop': 'Stop Camera Motion',
46
+ 'camera-follow': 'Camera Follow',
47
+ 'camera-aim': 'Camera Aim',
48
+ 'camera-focus': 'Camera Focus',
49
+ 'camera-handheld': 'Handheld Movement',
50
+ 'expression-clear': 'Clear All Expressions',
51
+ 'model-load': 'Swap Model',
46
52
  'model-position': 'Model Position',
47
53
  };
48
54
  /** English label for one automation action kind; kinds newer than this SDK read `Action`. */
@@ -50,9 +56,11 @@ export function automationActionLabel(kind) {
50
56
  return AUTOMATION_ACTION_KIND_LABELS[kind] ?? 'Action';
51
57
  }
52
58
  /** True for an action that prepares the scene before playback. */
53
- export function isAutomationBoundary(kind) {
54
- return isOneOf(kind, AUTOMATION_BOUNDARY_KINDS);
59
+ export function isAutomationSetup(kind) {
60
+ return isOneOf(kind, AUTOMATION_SETUP_KINDS);
55
61
  }
62
+ /** @deprecated Use `isAutomationSetup`. */
63
+ export const isAutomationBoundary = isAutomationSetup;
56
64
  /** Join action labels without implying timing that the client summary does not carry. */
57
65
  export function joinAutomationActionLabels(labels, kinds) {
58
66
  if (labels.length !== kinds.length)
@@ -1,4 +1,4 @@
1
- import type { AssetRef, Attach, AttachDepth, EnvironmentLook, ModelFormat, MToonTuning, ObjectContent, ObjectSpace, SceneEnvironment, SceneLight, SceneLightCameraFollowOptions, SceneLightType, ScreenPlacement, VrmPlacement } from '../wire/types.ts';
1
+ import type { AssetRef, Attach, AttachDepth, CameraAnchor, CameraFollowDamping, CameraTrackTarget, EnvironmentLook, ModelFormat, MToonTuning, ObjectContent, ObjectSpace, SceneCameraAim, SceneCameraAimSettings, SceneCameraFocus, SceneCameraFocusSettings, SceneCameraFollow, SceneCameraFollowSettings, SceneCameraHandheld, SceneEnvironment, SceneLight, SceneLightCameraFollowOptions, SceneLightType, ScreenPlacement, VrmPlacement } from '../wire/types.ts';
2
2
  export declare function clamp(v: number, min: number, max: number): number;
3
3
  /** Clamp to the unit interval. */
4
4
  export declare function clamp01(v: number): number;
@@ -63,6 +63,66 @@ export declare const SCENE_FOV_MAX = 90;
63
63
  /** Nonsingular authored field of view in degrees, including every valid whole-degree VMD key. */
64
64
  export declare const CAMERA_FOV_MIN = 1;
65
65
  export declare const CAMERA_FOV_MAX = 179;
66
+ /** Ceiling for each follow and aim damping, in seconds. */
67
+ export declare const CAMERA_DAMPING_MAX = 10;
68
+ /** Ceiling for {@link SceneCameraAim}'s lookahead time, in seconds, and its smoothing. */
69
+ export declare const CAMERA_AIM_LOOKAHEAD_MAX = 1;
70
+ export declare const CAMERA_AIM_SMOOTHING_MAX = 30;
71
+ /** Ceiling for {@link SceneCameraHandheld}'s speed. */
72
+ export declare const CAMERA_HANDHELD_SPEED_MAX = 2;
73
+ /** Warudo's Handheld Movement defaults, switched off. */
74
+ export declare const DEFAULT_CAMERA_HANDHELD: SceneCameraHandheld;
75
+ /**
76
+ * A fresh follow's damping: Warudo's second of position lag, and half a second on each turn so a
77
+ * tracked head's jitter never shakes the view.
78
+ */
79
+ export declare const DEFAULT_CAMERA_FOLLOW_DAMPING: CameraFollowDamping;
80
+ /** Where a fresh follow, aim or focus tracks a model; an object is always tracked by its root. */
81
+ export declare const DEFAULT_CAMERA_ANCHOR: CameraAnchor;
82
+ /** A fresh follow's settings: position only. */
83
+ export declare function defaultCameraFollowSettings(): SceneCameraFollowSettings;
84
+ /** A fresh follow of `target`, position only. */
85
+ export declare function defaultCameraFollow(target: CameraTrackTarget): SceneCameraFollow;
86
+ /** A fresh aim's settings, Warudo's Composer defaults: centred, no dead zone, 0.8 soft zone. */
87
+ export declare function defaultCameraAimSettings(): SceneCameraAimSettings;
88
+ /** A fresh aim at `target`. */
89
+ export declare function defaultCameraAim(target: CameraTrackTarget): SceneCameraAim;
90
+ /** A fresh focus's settings, refocusing about as fast as Warudo's default focusing speed. */
91
+ export declare function defaultCameraFocusSettings(): SceneCameraFocusSettings;
92
+ /** A fresh focus on `target`. */
93
+ export declare function defaultCameraFocus(target: CameraTrackTarget): SceneCameraFocus;
94
+ /** A follow's, aim's or focus's settings alone, without the layer it names. */
95
+ export declare function cameraTrackSettingsOf<T extends CameraTrackTarget>(track: T): Omit<T, 'instanceId' | 'target'>;
96
+ /** The instance `target` tracks in a scene whose primary model is `primaryInstanceId`. */
97
+ export declare function cameraTrackInstanceId(target: CameraTrackTarget, primaryInstanceId: string | null): string | null;
98
+ /** How a camera can track `item`: by any anchor on a VRM model, by the root of a 3D object, or not at all. */
99
+ export declare function cameraTrackKind(item: {
100
+ kind: 'model';
101
+ ref: {
102
+ kind: string;
103
+ };
104
+ } | {
105
+ kind: 'object';
106
+ space: ObjectSpace;
107
+ }): 'model' | 'object' | null;
108
+ /** Rows for the camera's follow, aim and focus pickers, in layer order. One rule, or the console offers a layer the desktop drops. */
109
+ export declare function cameraTrackCandidates(items: readonly ({
110
+ kind: 'model';
111
+ instanceId: string;
112
+ ref: {
113
+ kind: string;
114
+ name: string;
115
+ };
116
+ } | {
117
+ kind: 'object';
118
+ instanceId: string;
119
+ name: string;
120
+ space: ObjectSpace;
121
+ })[]): {
122
+ instanceId: string;
123
+ name: string;
124
+ model: boolean;
125
+ }[];
66
126
  /** Manual navigation stops short of ±90°; authored camera elevations remain unrestricted. */
67
127
  export declare const ELEVATION_LIMIT: number;
68
128
  /** Manual navigation distance bounds; authored cameras retain signed, unrestricted distances. */
@@ -172,9 +232,32 @@ export declare const WEB_SIZE_MAX = 7680;
172
232
  /** Web object paint-rate bounds, frames per second. */
173
233
  export declare const WEB_FPS_MIN = 1;
174
234
  export declare const WEB_FPS_MAX = 60;
235
+ /** Text object bounds: characters, em size in px, and the box and paint extents in px. */
236
+ export declare const TEXT_LENGTH_MAX = 10000;
237
+ export declare const TEXT_SIZE_MIN = 4;
238
+ export declare const TEXT_SIZE_MAX = 1000;
239
+ export declare const TEXT_SHEAR_MAX = 1;
240
+ /** Letter and word spacing, em. */
241
+ export declare const TEXT_SPACING_MIN = -0.5;
242
+ export declare const TEXT_SPACING_MAX = 2;
243
+ export declare const TEXT_LINE_HEIGHT_MIN = 0.5;
244
+ export declare const TEXT_LINE_HEIGHT_MAX = 4;
245
+ export declare const TEXT_BOX_MAX = 7680;
246
+ export declare const TEXT_STROKE_MAX = 100;
247
+ export declare const TEXT_SHADOW_OFFSET_MAX = 200;
248
+ export declare const TEXT_SHADOW_BLUR_MAX = 100;
249
+ export declare const TEXT_PLATE_PADDING_MAX = 500;
250
+ export declare const TEXT_PLATE_RADIUS_MAX = 500;
251
+ /** 3D text: extrusion and bevel in em, bevel segments, and emission strength. */
252
+ export declare const TEXT_EXTRUDE_MAX = 2;
253
+ export declare const TEXT_BEVEL_MAX = 0.2;
254
+ export declare const TEXT_BEVEL_RESOLUTION_MAX = 8;
255
+ export declare const TEXT_EMISSION_MAX = 4;
256
+ /** A PostScript name: printable ASCII, at most 63 chars, minus the quote and backslash that would escape `local("…")`. */
257
+ export declare const TEXT_POSTSCRIPT_NAME_RE: RegExp;
175
258
  /** A prop is a mesh, so it only exists in the three.js scene; every other kind renders in both. */
176
259
  export declare function objectSupportsSpace(kind: ObjectContent['kind'], space: ObjectSpace): boolean;
177
- /** The asset an object streams from, or null for kinds that carry their source inline (web, capture). */
260
+ /** The asset an object streams from, or null for kinds that carry their source inline (web, capture, text). */
178
261
  export declare function contentAssetId(content: ObjectContent): string | null;
179
262
  /**
180
263
  * The one model format a space's objects can ride: the screen layer always composites
@@ -212,6 +295,19 @@ export declare function pinnableParents(models: readonly {
212
295
  name: string;
213
296
  ridesThis: boolean;
214
297
  }[];
298
+ /**
299
+ * Whether pinning puts an item inside its Live2D host's ArtMesh stack, where `attach.depth` places
300
+ * it: a Live2D item, or a 2D object as one quad. A 3D object only ever paints in front.
301
+ */
302
+ export declare function pinEntersStack(item: {
303
+ kind: 'model';
304
+ ref: {
305
+ kind: ModelFormat;
306
+ };
307
+ } | {
308
+ kind: 'object';
309
+ space: ObjectSpace;
310
+ }): boolean;
215
311
  /**
216
312
  * The depth control's stops, back to front: behind the model, above each of its ArtMeshes in
217
313
  * paint order, then in front of it all. One continuous run, so depth is a slider over the host's
@@ -220,9 +316,12 @@ export declare function pinnableParents(models: readonly {
220
316
  export declare function depthStops(meshes: readonly string[]): AttachDepth[];
221
317
  /** Which stop a depth sits at; an ArtMesh the host no longer has reads as the frontmost. */
222
318
  export declare function depthStopIndex(meshes: readonly string[], depth: AttachDepth): number;
223
- /** A fresh pin onto `parentInstanceId`: root anchor, in front of the model, no response tuning. */
224
- export declare function defaultAttach(parentInstanceId: string): Attach;
225
319
  export declare const DEFAULT_HEAD_ANGLE: NonNullable<Attach['headAngle']>;
320
+ /**
321
+ * A fresh pin onto `parentInstanceId`: root anchor, in front of the model. A screen-space item (a
322
+ * Live2D model, a 2D object) follows the host's head at the default response; others take none.
323
+ */
324
+ export declare function defaultAttach(parentInstanceId: string, screenSpace?: boolean): Attach;
226
325
  export declare const ATTACH_MULTIPLIER_MIN = -2;
227
326
  export declare const ATTACH_MULTIPLIER_MAX = 2;
228
327
  /** Parallax slider ceiling, symmetric: stage px at a full head turn. */
@@ -254,5 +353,7 @@ export declare const OUTLINER_DEFAULT_WIDTH = 288;
254
353
  * split must fit inside it, or no layout satisfies both floors and the group clips instead.
255
354
  */
256
355
  export declare const TWO_COLUMN_WIDTH = 672;
356
+ /** Colors a color picker keeps saved — two rows of its swatch grid; saving more waits for a removal. */
357
+ export declare const SAVED_COLORS_MAX = 12;
257
358
  /** 3D-stage resolution multipliers offered by both performance pickers. */
258
359
  export declare const RENDER_SCALE_PRESETS: readonly [1, 0.85, 0.75, 0.66, 0.5];
@@ -94,6 +94,78 @@ export const SCENE_FOV_MAX = 90;
94
94
  /** Nonsingular authored field of view in degrees, including every valid whole-degree VMD key. */
95
95
  export const CAMERA_FOV_MIN = 1;
96
96
  export const CAMERA_FOV_MAX = 179;
97
+ /** Ceiling for each follow and aim damping, in seconds. */
98
+ export const CAMERA_DAMPING_MAX = 10;
99
+ /** Ceiling for {@link SceneCameraAim}'s lookahead time, in seconds, and its smoothing. */
100
+ export const CAMERA_AIM_LOOKAHEAD_MAX = 1;
101
+ export const CAMERA_AIM_SMOOTHING_MAX = 30;
102
+ /** Ceiling for {@link SceneCameraHandheld}'s speed. */
103
+ export const CAMERA_HANDHELD_SPEED_MAX = 2;
104
+ /** Warudo's Handheld Movement defaults, switched off. */
105
+ export const DEFAULT_CAMERA_HANDHELD = { enabled: false, intensity: 0.5, speed: 1 };
106
+ /**
107
+ * A fresh follow's damping: Warudo's second of position lag, and half a second on each turn so a
108
+ * tracked head's jitter never shakes the view.
109
+ */
110
+ export const DEFAULT_CAMERA_FOLLOW_DAMPING = { x: 1, y: 1, z: 1, yaw: 0.5, pitch: 0.5, roll: 0.5 };
111
+ /** Where a fresh follow, aim or focus tracks a model; an object is always tracked by its root. */
112
+ export const DEFAULT_CAMERA_ANCHOR = { kind: 'bone', bone: 'head' };
113
+ /** A fresh follow's settings: position only. */
114
+ export function defaultCameraFollowSettings() {
115
+ return { anchor: DEFAULT_CAMERA_ANCHOR, binding: 'world', damping: { ...DEFAULT_CAMERA_FOLLOW_DAMPING } };
116
+ }
117
+ /** A fresh follow of `target`, position only. */
118
+ export function defaultCameraFollow(target) {
119
+ return { ...target, ...defaultCameraFollowSettings() };
120
+ }
121
+ /** A fresh aim's settings, Warudo's Composer defaults: centred, no dead zone, 0.8 soft zone. */
122
+ export function defaultCameraAimSettings() {
123
+ return {
124
+ anchor: DEFAULT_CAMERA_ANCHOR,
125
+ screenX: 0.5,
126
+ screenY: 0.5,
127
+ deadZone: { width: 0, height: 0 },
128
+ softZone: { width: 0.8, height: 0.8 },
129
+ bias: { x: 0, y: 0 },
130
+ damping: { horizontal: 0.5, vertical: 0.5 },
131
+ lookahead: { time: 0, smoothing: 0.5, ignoreY: false },
132
+ };
133
+ }
134
+ /** A fresh aim at `target`. */
135
+ export function defaultCameraAim(target) {
136
+ return { ...target, ...defaultCameraAimSettings() };
137
+ }
138
+ /** A fresh focus's settings, refocusing about as fast as Warudo's default focusing speed. */
139
+ export function defaultCameraFocusSettings() {
140
+ return { anchor: DEFAULT_CAMERA_ANCHOR, damping: 0.2 };
141
+ }
142
+ /** A fresh focus on `target`. */
143
+ export function defaultCameraFocus(target) {
144
+ return { ...target, ...defaultCameraFocusSettings() };
145
+ }
146
+ /** A follow's, aim's or focus's settings alone, without the layer it names. */
147
+ export function cameraTrackSettingsOf(track) {
148
+ const { instanceId: _instanceId, target: _target, ...settings } = track;
149
+ return settings;
150
+ }
151
+ /** The instance `target` tracks in a scene whose primary model is `primaryInstanceId`. */
152
+ export function cameraTrackInstanceId(target, primaryInstanceId) {
153
+ return target.target === 'primary' ? primaryInstanceId : target.instanceId;
154
+ }
155
+ /** How a camera can track `item`: by any anchor on a VRM model, by the root of a 3D object, or not at all. */
156
+ export function cameraTrackKind(item) {
157
+ if (item.kind === 'model')
158
+ return item.ref.kind === 'vrm' ? 'model' : null;
159
+ return item.space === '3d' ? 'object' : null;
160
+ }
161
+ /** Rows for the camera's follow, aim and focus pickers, in layer order. One rule, or the console offers a layer the desktop drops. */
162
+ export function cameraTrackCandidates(items) {
163
+ return items.flatMap(item => {
164
+ const kind = cameraTrackKind(item);
165
+ const name = item.kind === 'model' ? item.ref.name : item.name;
166
+ return kind ? [{ instanceId: item.instanceId, name, model: kind === 'model' }] : [];
167
+ });
168
+ }
97
169
  /** Manual navigation stops short of ±90°; authored camera elevations remain unrestricted. */
98
170
  export const ELEVATION_LIMIT = (80 * Math.PI) / 180;
99
171
  /** Manual navigation distance bounds; authored cameras retain signed, unrestricted distances. */
@@ -292,11 +364,34 @@ export const WEB_SIZE_MAX = 7680;
292
364
  /** Web object paint-rate bounds, frames per second. */
293
365
  export const WEB_FPS_MIN = 1;
294
366
  export const WEB_FPS_MAX = 60;
367
+ /** Text object bounds: characters, em size in px, and the box and paint extents in px. */
368
+ export const TEXT_LENGTH_MAX = 10_000;
369
+ export const TEXT_SIZE_MIN = 4;
370
+ export const TEXT_SIZE_MAX = 1000;
371
+ export const TEXT_SHEAR_MAX = 1;
372
+ /** Letter and word spacing, em. */
373
+ export const TEXT_SPACING_MIN = -0.5;
374
+ export const TEXT_SPACING_MAX = 2;
375
+ export const TEXT_LINE_HEIGHT_MIN = 0.5;
376
+ export const TEXT_LINE_HEIGHT_MAX = 4;
377
+ export const TEXT_BOX_MAX = 7680;
378
+ export const TEXT_STROKE_MAX = 100;
379
+ export const TEXT_SHADOW_OFFSET_MAX = 200;
380
+ export const TEXT_SHADOW_BLUR_MAX = 100;
381
+ export const TEXT_PLATE_PADDING_MAX = 500;
382
+ export const TEXT_PLATE_RADIUS_MAX = 500;
383
+ /** 3D text: extrusion and bevel in em, bevel segments, and emission strength. */
384
+ export const TEXT_EXTRUDE_MAX = 2;
385
+ export const TEXT_BEVEL_MAX = 0.2;
386
+ export const TEXT_BEVEL_RESOLUTION_MAX = 8;
387
+ export const TEXT_EMISSION_MAX = 4;
388
+ /** A PostScript name: printable ASCII, at most 63 chars, minus the quote and backslash that would escape `local("…")`. */
389
+ export const TEXT_POSTSCRIPT_NAME_RE = /^[\x21\x23-\x5b\x5d-\x7e]{1,63}$/;
295
390
  /** A prop is a mesh, so it only exists in the three.js scene; every other kind renders in both. */
296
391
  export function objectSupportsSpace(kind, space) {
297
392
  return kind === 'prop' ? space === '3d' : true;
298
393
  }
299
- /** The asset an object streams from, or null for kinds that carry their source inline (web, capture). */
394
+ /** The asset an object streams from, or null for kinds that carry their source inline (web, capture, text). */
300
395
  export function contentAssetId(content) {
301
396
  return content.kind === 'image' || content.kind === 'video' || content.kind === 'prop' ? content.assetId : null;
302
397
  }
@@ -343,6 +438,13 @@ export function pinnableParents(models, items, instanceId) {
343
438
  }
344
439
  return out;
345
440
  }
441
+ /**
442
+ * Whether pinning puts an item inside its Live2D host's ArtMesh stack, where `attach.depth` places
443
+ * it: a Live2D item, or a 2D object as one quad. A 3D object only ever paints in front.
444
+ */
445
+ export function pinEntersStack(item) {
446
+ return item.kind === 'model' ? item.ref.kind === 'live2d' : item.space === '2d';
447
+ }
346
448
  /**
347
449
  * The depth control's stops, back to front: behind the model, above each of its ArtMeshes in
348
450
  * paint order, then in front of it all. One continuous run, so depth is a slider over the host's
@@ -360,24 +462,27 @@ export function depthStopIndex(meshes, depth) {
360
462
  const at = meshes.indexOf(depth.id);
361
463
  return at < 0 ? meshes.length + 1 : at + 1;
362
464
  }
363
- /** A fresh pin onto `parentInstanceId`: root anchor, in front of the model, no response tuning. */
364
- export function defaultAttach(parentInstanceId) {
465
+ export const DEFAULT_HEAD_ANGLE = {
466
+ multiplier: 1,
467
+ parallaxX: 0,
468
+ parallaxY: 0,
469
+ smoothing: 15,
470
+ };
471
+ /**
472
+ * A fresh pin onto `parentInstanceId`: root anchor, in front of the model. A screen-space item (a
473
+ * Live2D model, a 2D object) follows the host's head at the default response; others take none.
474
+ */
475
+ export function defaultAttach(parentInstanceId, screenSpace = false) {
365
476
  return {
366
477
  parentInstanceId,
367
478
  anchor: { kind: 'root' },
368
479
  followRotation: true,
369
480
  depth: { kind: 'front' },
370
481
  split: null,
371
- headAngle: null,
482
+ headAngle: screenSpace ? { ...DEFAULT_HEAD_ANGLE } : null,
372
483
  elasticity: null,
373
484
  };
374
485
  }
375
- export const DEFAULT_HEAD_ANGLE = {
376
- multiplier: 1,
377
- parallaxX: 0,
378
- parallaxY: 0,
379
- smoothing: 15,
380
- };
381
486
  export const ATTACH_MULTIPLIER_MIN = -2;
382
487
  export const ATTACH_MULTIPLIER_MAX = 2;
383
488
  /** Parallax slider ceiling, symmetric: stage px at a full head turn. */
@@ -411,5 +516,7 @@ export const OUTLINER_DEFAULT_WIDTH = 288;
411
516
  * split must fit inside it, or no layout satisfies both floors and the group clips instead.
412
517
  */
413
518
  export const TWO_COLUMN_WIDTH = 672;
519
+ /** Colors a color picker keeps saved — two rows of its swatch grid; saving more waits for a removal. */
520
+ export const SAVED_COLORS_MAX = 12;
414
521
  /** 3D-stage resolution multipliers offered by both performance pickers. */
415
522
  export const RENDER_SCALE_PRESETS = [1, 0.85, 0.75, 0.66, 0.5];
@@ -19,6 +19,11 @@ export interface SceneAssetInfo {
19
19
  extensions: string[] | null;
20
20
  mediaSize: ObjectMediaSize | null;
21
21
  }
22
+ /** One scene object's loaded metadata. */
23
+ export interface SceneObjectInfo extends SceneAssetInfo {
24
+ /** A text object's transient text, null while it shows the saved one; absent on other kinds and older hosts. */
25
+ liveText?: string | null;
26
+ }
22
27
  /** Metadata for the active scene, tagged so a response from a previous scene can be discarded. */
23
28
  export interface SceneInspection {
24
29
  sceneId: string;
@@ -26,5 +31,5 @@ export interface SceneInspection {
26
31
  /** The set's own bounding radius before placement scale, for `cameraDistanceLimits`; omitted by older hosts. */
27
32
  radius?: number | null;
28
33
  };
29
- objects: Record<string, SceneAssetInfo>;
34
+ objects: Record<string, SceneObjectInfo>;
30
35
  }
@@ -0,0 +1,9 @@
1
+ /** Desktop local wall-clock time, normalized over a repeating 24-hour or 12-hour cycle. */
2
+ export declare const TIME_INPUT_RANGES: {
3
+ readonly Time24h: readonly [0, 1];
4
+ readonly Time12h: readonly [0, 1];
5
+ };
6
+ export type TimeInputName = keyof typeof TIME_INPUT_RANGES;
7
+ export type TimeInputs = Readonly<Record<TimeInputName, number>>;
8
+ export declare const TIME_INPUT_NAMES: readonly TimeInputName[];
9
+ export declare function isTimeInputName(v: string): v is TimeInputName;
@@ -0,0 +1,11 @@
1
+ import { keysOf } from "./guards.js";
2
+ /** Desktop local wall-clock time, normalized over a repeating 24-hour or 12-hour cycle. */
3
+ export const TIME_INPUT_RANGES = {
4
+ Time24h: [0, 1],
5
+ Time12h: [0, 1],
6
+ };
7
+ export const TIME_INPUT_NAMES = keysOf(TIME_INPUT_RANGES);
8
+ const TIME_INPUT_SET = new Set(TIME_INPUT_NAMES);
9
+ export function isTimeInputName(v) {
10
+ return TIME_INPUT_SET.has(v);
11
+ }
@@ -30,6 +30,14 @@ export interface EventMap {
30
30
  instanceId: string;
31
31
  format: ModelFormat;
32
32
  };
33
+ /**
34
+ * An instance's motion or expression list changed without a reload — a recorded motion, an edited
35
+ * expression file, or a registered clip a VRM lists: re-run `motion.list` or `expression.list`.
36
+ */
37
+ 'instance.listing': {
38
+ instanceId: string;
39
+ listing: 'motions' | 'expressions';
40
+ };
33
41
  /** `weights` rides along on instances with `expression-weights`; a drag is not echoed (see `expression.setWeight`). */
34
42
  'expression.changed': {
35
43
  instanceId: string;
@@ -8,6 +8,7 @@ export const EVENT_NAMES = Object.keys({
8
8
  'automation.state': true,
9
9
  'tracking.status': true,
10
10
  'instance.loaded': true,
11
+ 'instance.listing': true,
11
12
  'expression.changed': true,
12
13
  'motion.started': true,
13
14
  'motion.ended': true,
@@ -5,7 +5,7 @@ import type { LipSyncCalibrationCommand, LipSyncConfig, LipSyncMode, LipSyncStat
5
5
  import type { ModelMovementConfig, ModelMovementEdit } from '../values/model-movement.ts';
6
6
  import type { SceneInspection } from '../values/stage-info.ts';
7
7
  import type { EventName } from './events.ts';
8
- import type { AnchorOption, AppCapability, AssetKind, AssetRef, Attach, AttachHeadAngle, AutomationInfo, BindingInput, Expression, ExpressionPersistence, HandTrackingMode, HotkeyConfig, HotkeyState, InjectEntry, InjectTarget, InstanceRuntime, JsonValue, LayerEffectKey, LayerEffects, LayerEffectsPatch, MediaPipeConfig, ModelInfo, ModelRef, MotionGroup, MToonTuning, ObjectContent, ObjectLightOverride, ObjectSpace, Place2D, Place3D, PlayingMotion, PoseSourceId, PoseStatus, Scene, SceneItem, SceneLight, SceneLightCameraFollowOptions, ScenePatch, SceneState, ScreenPlacement, Settings, SettingsPatch, TrackingLostBehavior, TrackingSourceConfig, TrackingSourceId, TrackingSourceKind, TrackingStatus, VrmPlacement } from './types.ts';
8
+ import type { AnchorOption, AppCapability, AssetKind, AssetRef, Attach, AttachHeadAngle, AutomationInfo, BindingInput, Expression, ExpressionPersistence, FontFamilyInfo, HandTrackingMode, HotkeyConfig, HotkeyState, InjectEntry, InjectTarget, InstanceRuntime, JsonValue, LayerEffectKey, LayerEffects, LayerEffectsPatch, MediaPipeConfig, ModelInfo, ModelRef, MotionGroup, MToonTuning, ObjectContent, ObjectLightOverride, ObjectSpace, Place2D, Place3D, PlayingMotion, PoseSourceId, PoseStatus, Scene, SceneItem, SceneLight, SceneLightCameraFollowOptions, ScenePatch, SceneState, ScreenPlacement, Settings, SettingsPatch, TrackingLostBehavior, TrackingSourceConfig, TrackingSourceId, TrackingSourceKind, TrackingStatus, VrmPlacement } from './types.ts';
9
9
  /** Marker for methods that take no parameters; the client lets you omit the argument. */
10
10
  export type EmptyRequest = Record<never, never>;
11
11
  /** Marker for methods whose success response carries no data. */
@@ -215,6 +215,15 @@ export interface ObjectSetContentRequest {
215
215
  content: ObjectContent;
216
216
  }
217
217
  export type ObjectSetContentResponse = EmptyResponse;
218
+ /** A `text` object's text alone, under `text-objects`. */
219
+ export interface ObjectSetTextRequest {
220
+ instanceId: string;
221
+ /** Null drops a transient text, showing the saved one again. */
222
+ text: string | null;
223
+ /** Show it without saving: no `scenes.json` write and no undo step. */
224
+ transient?: boolean;
225
+ }
226
+ export type ObjectSetTextResponse = EmptyResponse;
218
227
  export interface ObjectSetSpaceRequest {
219
228
  instanceId: string;
220
229
  space: ObjectSpace;
@@ -361,6 +370,11 @@ export type AssetListRequest = EmptyRequest;
361
370
  export interface AssetListResponse {
362
371
  assets: AssetRef[];
363
372
  }
373
+ export type FontsListRequest = EmptyRequest;
374
+ /** The host machine's installed families — what a text object's `font` can name. */
375
+ export interface FontsListResponse {
376
+ families: FontFamilyInfo[];
377
+ }
364
378
  /** Register a model entry file under a user-configured plugin folder. */
365
379
  export interface ModelRegisterRequest {
366
380
  path: string;
@@ -887,6 +901,10 @@ export interface MethodMap {
887
901
  request: ObjectSetContentRequest;
888
902
  response: ObjectSetContentResponse;
889
903
  };
904
+ 'object.setText': {
905
+ request: ObjectSetTextRequest;
906
+ response: ObjectSetTextResponse;
907
+ };
890
908
  'object.setSpace': {
891
909
  request: ObjectSetSpaceRequest;
892
910
  response: ObjectSetSpaceResponse;
@@ -988,6 +1006,10 @@ export interface MethodMap {
988
1006
  request: AssetListRequest;
989
1007
  response: AssetListResponse;
990
1008
  };
1009
+ 'fonts.list': {
1010
+ request: FontsListRequest;
1011
+ response: FontsListResponse;
1012
+ };
991
1013
  'model.register': {
992
1014
  request: ModelRegisterRequest;
993
1015
  response: ModelRegisterResponse;
@@ -35,6 +35,7 @@ export const METHOD_NAMES = Object.keys({
35
35
  'object.addMany': true,
36
36
  'object.rename': true,
37
37
  'object.setContent': true,
38
+ 'object.setText': true,
38
39
  'object.setSpace': true,
39
40
  'object.setPlacement': true,
40
41
  'object.attach': true,
@@ -63,6 +64,7 @@ export const METHOD_NAMES = Object.keys({
63
64
  'model.getMovement': true,
64
65
  'model.setMovement': true,
65
66
  'asset.list': true,
67
+ 'fonts.list': true,
66
68
  'asset.register': true,
67
69
  'registry.thumbnail': true,
68
70
  'settings.get': true,
@@ -234,6 +234,7 @@ export declare const requestSchemas: {
234
234
  lut: "lut";
235
235
  animation: "animation";
236
236
  cameraMotion: "cameraMotion";
237
+ lyrics: "lyrics";
237
238
  }>>;
238
239
  }, z.core.$strip>;
239
240
  'settings.patch': z.ZodObject<{
@@ -329,9 +330,9 @@ export declare const requestSchemas: {
329
330
  ttlMs: z.ZodOptional<z.ZodNumber>;
330
331
  transition: z.ZodOptional<z.ZodObject<{
331
332
  style: z.ZodOptional<z.ZodEnum<{
333
+ pop: "pop";
332
334
  glitch: "glitch";
333
335
  dither: "dither";
334
- pop: "pop";
335
336
  cut: "cut";
336
337
  }>>;
337
338
  inMs: z.ZodOptional<z.ZodNumber>;
@@ -180,9 +180,14 @@ export declare const SettingsSchema: z.ZodObject<{
180
180
  width: z.ZodNumber;
181
181
  height: z.ZodNumber;
182
182
  }, z.core.$strip>>;
183
+ stageReferenceSize: z.ZodOptional<z.ZodObject<{
184
+ width: z.ZodNumber;
185
+ height: z.ZodNumber;
186
+ }, z.core.$strip>>;
183
187
  }, z.core.$strip>;
184
188
  ui: z.ZodObject<{
185
189
  trayVisible: z.ZodBoolean;
190
+ streamMode: z.ZodOptional<z.ZodBoolean>;
186
191
  }, z.core.$strip>;
187
192
  performance: z.ZodObject<{
188
193
  showFps: z.ZodBoolean;
@@ -99,11 +99,15 @@ export const SettingsSchema = z.object({
99
99
  window: z
100
100
  .object({
101
101
  alwaysOnTop: z.boolean().describe('Keep the control-panel window above other windows.'),
102
- stageSize: StageSizeSchema.optional().describe('Read-only stage content size; absent on older hosts.'),
102
+ stageSize: StageSizeSchema.optional().describe('Read-only stage window content size; absent on older hosts.'),
103
+ stageReferenceSize: StageSizeSchema.optional().describe('Read-only initial stage size calibrating placement units and model fit; not the output aspect.'),
103
104
  })
104
105
  .describe('Public window configuration and read-only stage dimensions.'),
105
106
  ui: z
106
- .object({ trayVisible: z.boolean().describe('Show the tray or menu bar icon.') })
107
+ .object({
108
+ trayVisible: z.boolean().describe('Show the tray or menu bar icon.'),
109
+ streamMode: z.boolean().optional().describe('Read-only Stream Mode state; absent on older hosts.'),
110
+ })
107
111
  .describe('Public interface preferences.'),
108
112
  performance: PerformanceSettingsSchema.partial({ renderScale: true }).describe('Renderer settings; renderScale is absent on older hosts.'),
109
113
  tracking: TrackingSettingsSchema.describe('Network face master switch and all configured tracking sources.'),
@@ -118,6 +122,10 @@ export const SettingsPatchSchema = z.object({
118
122
  .partial()
119
123
  .optional()
120
124
  .describe('Control-panel window fields to update.'),
121
- ui: SettingsSchema.shape.ui.partial().optional().describe('Public interface fields to update.'),
125
+ ui: SettingsSchema.shape.ui
126
+ .pick({ trayVisible: true })
127
+ .partial()
128
+ .optional()
129
+ .describe('Public interface fields to update.'),
122
130
  performance: PerformanceSettingsSchema.partial().optional().describe('Renderer fields to update.'),
123
131
  });