@laplace.live/persona-sdk 1.12.0 → 1.14.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/dist/index.d.ts CHANGED
@@ -17,6 +17,7 @@ export * from './values/limits.ts';
17
17
  export * from './values/lipsync.ts';
18
18
  export * from './values/locale.ts';
19
19
  export * from './values/model-info.ts';
20
+ export * from './values/mouse.ts';
20
21
  export * from './values/scene-transition.ts';
21
22
  export * from './values/stage-info.ts';
22
23
  export * from './values/terms.ts';
package/dist/index.js CHANGED
@@ -19,6 +19,7 @@ export * from "./values/limits.js";
19
19
  export * from "./values/lipsync.js";
20
20
  export * from "./values/locale.js";
21
21
  export * from "./values/model-info.js";
22
+ export * from "./values/mouse.js";
22
23
  export * from "./values/scene-transition.js";
23
24
  export * from "./values/stage-info.js";
24
25
  export * from "./values/terms.js";
@@ -1,3 +1,4 @@
1
+ import type { BindingInput } from '../wire/types.ts';
1
2
  import type { Curve } from './curve.ts';
2
3
  import type { BindingTerm } from './terms.ts';
3
4
  /** A saved input-to-parameter rule shared by the rig editor and plugin API. */
@@ -21,6 +22,13 @@ export interface BindableParameter {
21
22
  max: number;
22
23
  default: number;
23
24
  }
25
+ /** The editor's live readout, polled as one sample. */
26
+ export interface BindingLiveValues {
27
+ /** What each tracking input reads right now; empty while nothing is measured. */
28
+ inputs: Partial<Record<BindingInput, number>>;
29
+ /** What each bound parameter reads on the model right now, by output id; empty for a host that cannot read it back. */
30
+ outputs: Record<string, number>;
31
+ }
24
32
  /** Metadata read from a rig's display and physics sidecars. */
25
33
  export interface BindingEditorData {
26
34
  connections: Binding[];
@@ -7,6 +7,11 @@ export declare function fileBasename(path: string): string;
7
7
  * so the basename is the only identifier there is.
8
8
  */
9
9
  export declare function motionLabel(file: string): string;
10
+ /**
11
+ * Label for one motion of a group: the group alone when the file just repeats it (a VRM clip
12
+ * group named for its file, or a loose VTS file whose group is its basename), else both.
13
+ */
14
+ export declare function motionSlotLabel(group: string, file: string): string;
10
15
  /** Playable entries of a `MotionGroup` with their authored indices; an empty string is a missing file and keeps its slot. */
11
16
  export declare function motionSlots(files: readonly string[]): {
12
17
  file: string;
@@ -13,6 +13,14 @@ export function motionLabel(file) {
13
13
  const base = fileBasename(file);
14
14
  return base.replace(/\.motion3\.json$|\.exp3\.json$|\.vrma$|\.json$/i, '') || base;
15
15
  }
16
+ /**
17
+ * Label for one motion of a group: the group alone when the file just repeats it (a VRM clip
18
+ * group named for its file, or a loose VTS file whose group is its basename), else both.
19
+ */
20
+ export function motionSlotLabel(group, file) {
21
+ const name = motionLabel(file);
22
+ return group === file || name === group ? group : `${group} · ${name}`;
23
+ }
16
24
  /** Playable entries of a `MotionGroup` with their authored indices; an empty string is a missing file and keeps its slot. */
17
25
  export function motionSlots(files) {
18
26
  return files.flatMap((file, index) => (file === '' ? [] : [{ file, index }]));
@@ -81,6 +81,8 @@ export interface CameraDistanceLimits {
81
81
  export declare function cameraDistanceLimits(env: Pick<SceneEnvironment, 'modelAssetId' | 'modelPlace'>, setRadius: number | null): CameraDistanceLimits;
82
82
  /** ×2 doubles Cubism's own breath amplitude — past that the head sway reads as a nod, not a breath. */
83
83
  export declare const BREATH_DEPTH_MAX = 2;
84
+ /** Seconds; a minute without a face is well past any dropout worth waiting out. */
85
+ export declare const TRACKING_LOST_DELAY_MAX = 60;
84
86
  export declare const MTOON_NORMAL_SCALE_MAX = 2;
85
87
  export declare const MTOON_RIM_MAX = 2;
86
88
  /** ×0 flattens the Fresnel to a flood fill, ×4 tightens a default power-5 rim to a hairline. */
@@ -112,6 +112,8 @@ export function cameraDistanceLimits(env, setRadius) {
112
112
  }
113
113
  /** ×2 doubles Cubism's own breath amplitude — past that the head sway reads as a nod, not a breath. */
114
114
  export const BREATH_DEPTH_MAX = 2;
115
+ /** Seconds; a minute without a face is well past any dropout worth waiting out. */
116
+ export const TRACKING_LOST_DELAY_MAX = 60;
115
117
  export const MTOON_NORMAL_SCALE_MAX = 2;
116
118
  export const MTOON_RIM_MAX = 2;
117
119
  /** ×0 flattens the Fresnel to a flood fill, ×4 tightens a default power-5 rim to a hairline. */
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The OS cursor as a tracking input, in VTS's own names and span: −1..1 across the display the
3
+ * cursor is on, x growing rightward and y growing upward like `FacePositionY`.
4
+ */
5
+ export declare const MOUSE_INPUT_RANGES: {
6
+ readonly MousePositionX: readonly [-1, 1];
7
+ readonly MousePositionY: readonly [-1, 1];
8
+ };
9
+ export declare const MOUSE_INPUT_NAMES: readonly MouseInputName[];
10
+ export type MouseInputName = keyof typeof MOUSE_INPUT_RANGES;
11
+ export type MouseInputs = Partial<Record<MouseInputName, number>>;
12
+ export declare function isMouseInputName(v: string): v is MouseInputName;
@@ -0,0 +1,14 @@
1
+ import { keysOf } from "./guards.js";
2
+ /**
3
+ * The OS cursor as a tracking input, in VTS's own names and span: −1..1 across the display the
4
+ * cursor is on, x growing rightward and y growing upward like `FacePositionY`.
5
+ */
6
+ export const MOUSE_INPUT_RANGES = {
7
+ MousePositionX: [-1, 1],
8
+ MousePositionY: [-1, 1],
9
+ };
10
+ export const MOUSE_INPUT_NAMES = keysOf(MOUSE_INPUT_RANGES);
11
+ const MOUSE_INPUT_SET = new Set(MOUSE_INPUT_NAMES);
12
+ export function isMouseInputName(v) {
13
+ return MOUSE_INPUT_SET.has(v);
14
+ }
@@ -1,10 +1,10 @@
1
- import type { Binding, BindingEditorData } from '../values/bindings.ts';
1
+ import type { Binding, BindingEditorData, BindingLiveValues } from '../values/bindings.ts';
2
2
  import type { ControllerMovementConfig, ControllerState } from '../values/controller.ts';
3
3
  import type { SpawnTransition } from '../values/item-transition.ts';
4
4
  import type { LipSyncCalibrationCommand, LipSyncConfig, LipSyncMode, LipSyncState } from '../values/lipsync.ts';
5
5
  import type { SceneInspection } from '../values/stage-info.ts';
6
6
  import type { EventName } from './events.ts';
7
- 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, TrackingSourceConfig, TrackingSourceId, TrackingSourceKind, TrackingStatus, VrmPlacement } from './types.ts';
7
+ 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
8
  /** Marker for methods that take no parameters; the client lets you omit the argument. */
9
9
  export type EmptyRequest = Record<never, never>;
10
10
  /** Marker for methods whose success response carries no data. */
@@ -157,7 +157,16 @@ export type InstanceSetMToonResponse = EmptyResponse;
157
157
  export interface InstanceSetIdleRequest {
158
158
  instanceId?: string;
159
159
  idleAnimation?: boolean;
160
+ /** VRM only. */
160
161
  idleClip?: string;
162
+ /** Live2D only: a motion file from `motion.list`, or null for the model's `Idle` group. */
163
+ idleMotion?: string | null;
164
+ /** The `tracking-lost` app capability carries these three. */
165
+ trackingLostBehavior?: TrackingLostBehavior;
166
+ /** Live2D only: a motion file from `motion.list`, or null for none. */
167
+ trackingLostMotion?: string | null;
168
+ /** Seconds, 0 to `TRACKING_LOST_DELAY_MAX`. */
169
+ trackingLostDelay?: number;
161
170
  }
162
171
  export type InstanceSetIdleResponse = EmptyResponse;
163
172
  export interface InstanceInfoRequest {
@@ -581,9 +590,7 @@ export interface BindingSetResponse {
581
590
  saved: boolean;
582
591
  }
583
592
  export type BindingInputsRequest = BindingTarget;
584
- export interface BindingInputsResponse {
585
- inputs: Partial<Record<BindingInput, number>>;
586
- }
593
+ export type BindingInputsResponse = BindingLiveValues;
587
594
  export interface BindingOverrideRequest extends BindingTarget {
588
595
  input: BindingInput;
589
596
  value: number | null;
@@ -7,6 +7,7 @@ import { type ArkitInputName } from '../values/arkit.ts';
7
7
  import { type BaseControllerInputName, type ControllerInputName, type ControllerMovementConfig } from '../values/controller.ts';
8
8
  import { type HandInputName } from '../values/hands.ts';
9
9
  import { type LipSyncMode, type VoiceInputName } from '../values/lipsync.ts';
10
+ import { type MouseInputName } from '../values/mouse.ts';
10
11
  export type ModelFormat = 'live2d' | 'vrm';
11
12
  /** Where an item came from: shipped with the app, or added by the user. */
12
13
  export type ContentOrigin = 'bundled' | 'user';
@@ -166,8 +167,28 @@ export interface SceneModelItem {
166
167
  controllerMovement: ControllerMovementConfig;
167
168
  live2d: ScreenPlacement;
168
169
  vrm: VrmPlacement;
170
+ /** Whether the idle base animation plays: VRM loops `idleClip`, Live2D `idleMotion`. */
169
171
  idleAnimation: boolean;
172
+ /** VRM: a bundled `.vrma` filename or `asset:<id>`. Kept while the instance shows a Live2D model. */
170
173
  idleClip: string;
174
+ /**
175
+ * Live2D: a motion file the model lists (as `motion.list` names it), looped beneath every
176
+ * other motion, or null for the model's own `Idle` group at random. A file the model no
177
+ * longer lists degrades to that group. Kept while the instance shows a VRM.
178
+ */
179
+ idleMotion: string | null;
180
+ /**
181
+ * What the tracked parameters do while the face is lost: keep the last pose until it is
182
+ * found again (`hold`), or ease back to the idle over ~0.3 s and return the same way (`idle`).
183
+ */
184
+ trackingLostBehavior: TrackingLostBehavior;
185
+ /**
186
+ * Live2D: a listed motion that replaces the idle once the face has been lost for
187
+ * `trackingLostDelay` seconds, until it is found again; null keeps the idle playing.
188
+ */
189
+ trackingLostMotion: string | null;
190
+ /** Seconds without a face before `trackingLostMotion` takes over. */
191
+ trackingLostDelay: number;
171
192
  /**
172
193
  * Live2D only: the engine's built-in idle breath. Beyond `ParamBreath` it also sways
173
194
  * `ParamAngle*`/`ParamBodyAngleX`, so a rig whose head ranges are tuned tightly may want it off.
@@ -984,11 +1005,13 @@ export interface ScenePatch {
984
1005
  * App-level features a client gates on (never version-sniff): `hello` and
985
1006
  * `app.info` report them — the per-app mirror of {@link InstanceRuntime.capabilities}.
986
1007
  */
987
- export declare const APP_CAPABILITIES: readonly ["storage", "speech", "automations", "controllers", "model-editing", "asset-inspection", "layer-effects", "scene-transitions", "area-lights", "spot-lights", "camera-follow-lights", "shadow-filters", "environment-map-model", "spawn"];
1008
+ export declare const APP_CAPABILITIES: readonly ["storage", "speech", "automations", "controllers", "model-editing", "asset-inspection", "layer-effects", "scene-transitions", "area-lights", "spot-lights", "camera-follow-lights", "shadow-filters", "environment-map-model", "spawn", "tracking-lost"];
988
1009
  export type AppCapability = (typeof APP_CAPABILITIES)[number];
989
1010
  export declare function isAppCapability(v: unknown): v is AppCapability;
990
1011
  /** What a loaded model instance can do; absent capabilities answer `unsupported-for-format`. */
991
- export type InstanceCapability = 'motions' | 'expressions' | 'placement-2d' | 'placement-3d' | 'mtoon' | 'idle-clips' | 'pose' | 'live2d-params'
1012
+ export type InstanceCapability = 'motions' | 'expressions' | 'placement-2d' | 'placement-3d' | 'mtoon' | 'idle-clips'
1013
+ /** `instance.setIdle` with `idleMotion`: one of the model's motions loops as its idle. Live2D only. */
1014
+ | 'idle-motions' | 'pose' | 'live2d-params'
992
1015
  /** `instance.setBreath`; the idle breathing loop is Cubism's, so VRM lacks it. */
993
1016
  | 'breath'
994
1017
  /** `expression.setWeight`; Cubism expressions carry no user-settable weight, so Live2D lacks it. */
@@ -1114,6 +1137,9 @@ export declare const TRACKING_CHANNEL_FIELDS: {
1114
1137
  };
1115
1138
  export declare const TRACKING_CHANNELS: readonly TrackingChannel[];
1116
1139
  export declare const HAND_TRACKING_MODES: readonly ["arms", "fingers"];
1140
+ /** How the face drivers react to a dropout; see `SceneModelInstance.trackingLostBehavior`. */
1141
+ export declare const TRACKING_LOST_BEHAVIORS: readonly ["hold", "idle"];
1142
+ export type TrackingLostBehavior = (typeof TRACKING_LOST_BEHAVIORS)[number];
1117
1143
  export type HandTrackingMode = (typeof HAND_TRACKING_MODES)[number];
1118
1144
  export declare function isHandTrackingMode(v: unknown): v is HandTrackingMode;
1119
1145
  export declare const MEDIAPIPE_DELEGATES: readonly ["CPU", "GPU"];
@@ -1226,11 +1252,12 @@ declare const VTS_INPUT_RANGES: {
1226
1252
  };
1227
1253
  type VtsInputName = keyof typeof VTS_INPUT_RANGES;
1228
1254
  /**
1229
- * Default input vocabulary: face and hand inputs, raw ARKit channels and controller profile 1.
1230
- * Additional controller profile ids are accepted by isInputName without appearing in this list.
1255
+ * Default input vocabulary: face, hand and cursor inputs, raw ARKit channels and controller
1256
+ * profile 1. Additional controller profile ids are accepted by isInputName without appearing
1257
+ * in this list.
1231
1258
  */
1232
- export declare const INPUT_NAMES: readonly (VtsInputName | HandInputName | VoiceInputName | ArkitInputName | BaseControllerInputName)[];
1233
- export type InputName = VtsInputName | HandInputName | VoiceInputName | ArkitInputName | ControllerInputName;
1259
+ export declare const INPUT_NAMES: readonly (VtsInputName | HandInputName | VoiceInputName | MouseInputName | ArkitInputName | BaseControllerInputName)[];
1260
+ export type InputName = VtsInputName | HandInputName | VoiceInputName | MouseInputName | ArkitInputName | ControllerInputName;
1234
1261
  /** Whether an untrusted string names a tracking input — the guard every wire boundary needs. */
1235
1262
  export declare function isInputName(v: string): v is InputName;
1236
1263
  /**
@@ -1258,7 +1285,7 @@ export declare function arkitTwinOf(input: InputName): BindingInput;
1258
1285
  * Default inputs' natural spans. Use getInputRange for a dynamically numbered controller input.
1259
1286
  * Head angles are degrees; the rest are unitless.
1260
1287
  */
1261
- export declare const INPUT_RANGES: Record<VtsInputName | HandInputName | VoiceInputName | ArkitInputName | BaseControllerInputName, readonly [number, number]>;
1288
+ export declare const INPUT_RANGES: Record<VtsInputName | HandInputName | VoiceInputName | MouseInputName | ArkitInputName | BaseControllerInputName, readonly [number, number]>;
1262
1289
  /** Natural span of any valid input, including dynamically numbered controller profiles. */
1263
1290
  export declare function getInputRange(name: InputName): readonly [number, number];
1264
1291
  /**
@@ -6,6 +6,7 @@ import { BASE_CONTROLLER_INPUT_NAMES, BASE_CONTROLLER_INPUT_RANGES, controllerIn
6
6
  import { isOneOf, keysOf } from "../values/guards.js";
7
7
  import { HAND_INPUT_NAMES, HAND_INPUT_RANGES } from "../values/hands.js";
8
8
  import { VOICE_INPUT_NAMES, VOICE_INPUT_RANGES } from "../values/lipsync.js";
9
+ import { MOUSE_INPUT_NAMES, MOUSE_INPUT_RANGES } from "../values/mouse.js";
9
10
  /**
10
11
  * How a registered file is labelled. Wider than an object's content kinds: `.hdr` is only
11
12
  * ever an environment map, and a `.vmd` splits by content — `cameraMotion` for one that
@@ -46,6 +47,8 @@ export const APP_CAPABILITIES = [
46
47
  'shadow-filters',
47
48
  'environment-map-model',
48
49
  'spawn',
50
+ /** `instance.setIdle` takes `trackingLostBehavior`, `trackingLostMotion` and `trackingLostDelay`. */
51
+ 'tracking-lost',
49
52
  ];
50
53
  export function isAppCapability(v) {
51
54
  return isOneOf(v, APP_CAPABILITIES);
@@ -91,6 +94,8 @@ export const TRACKING_CHANNEL_FIELDS = {
91
94
  };
92
95
  export const TRACKING_CHANNELS = keysOf(TRACKING_CHANNEL_FIELDS);
93
96
  export const HAND_TRACKING_MODES = ['arms', 'fingers'];
97
+ /** How the face drivers react to a dropout; see `SceneModelInstance.trackingLostBehavior`. */
98
+ export const TRACKING_LOST_BEHAVIORS = ['hold', 'idle'];
94
99
  export function isHandTrackingMode(v) {
95
100
  return isOneOf(v, HAND_TRACKING_MODES);
96
101
  }
@@ -185,13 +190,15 @@ const VTS_INPUT_RANGES = {
185
190
  /** VTS's input vocabulary, plus `JawOpen` — the derived half of {@link INPUT_NAMES}. */
186
191
  const VTS_INPUT_NAMES = keysOf(VTS_INPUT_RANGES);
187
192
  /**
188
- * Default input vocabulary: face and hand inputs, raw ARKit channels and controller profile 1.
189
- * Additional controller profile ids are accepted by isInputName without appearing in this list.
193
+ * Default input vocabulary: face, hand and cursor inputs, raw ARKit channels and controller
194
+ * profile 1. Additional controller profile ids are accepted by isInputName without appearing
195
+ * in this list.
190
196
  */
191
197
  export const INPUT_NAMES = [
192
198
  ...VTS_INPUT_NAMES,
193
199
  ...VOICE_INPUT_NAMES,
194
200
  ...HAND_INPUT_NAMES,
201
+ ...MOUSE_INPUT_NAMES,
195
202
  ...ARKIT_INPUT_NAMES,
196
203
  ...BASE_CONTROLLER_INPUT_NAMES,
197
204
  ];
@@ -231,6 +238,7 @@ export const INPUT_RANGES = {
231
238
  ...VTS_INPUT_RANGES,
232
239
  ...VOICE_INPUT_RANGES,
233
240
  ...HAND_INPUT_RANGES,
241
+ ...MOUSE_INPUT_RANGES,
234
242
  ...BASE_CONTROLLER_INPUT_RANGES,
235
243
  // `fromEntries` widens the key type back to `string`; the annotation above is what keeps
236
244
  // this exhaustive, and it fails to typecheck if a name ever lacks a range.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@laplace.live/persona-sdk",
3
- "version": "1.12.0",
3
+ "version": "1.14.0",
4
4
  "description": "TypeScript SDK and wire schema for the LAPLACE Persona plugin API",
5
5
  "license": "MIT",
6
6
  "type": "module",