@laplace.live/persona-sdk 1.14.0 → 1.16.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/values/limits.d.ts +42 -1
- package/dist/values/limits.js +65 -0
- package/dist/wire/events.d.ts +2 -0
- package/dist/wire/methods.d.ts +29 -0
- package/dist/wire/types.d.ts +42 -1
- package/dist/wire/types.js +2 -0
- package/package.json +1 -1
package/dist/values/limits.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AssetRef, Attach, EnvironmentLook, ModelFormat, MToonTuning, ObjectContent, ObjectSpace, SceneEnvironment, SceneLight, SceneLightCameraFollowOptions, SceneLightType, ScreenPlacement, VrmPlacement } from '../wire/types.ts';
|
|
1
|
+
import type { AssetRef, Attach, AttachDepth, EnvironmentLook, ModelFormat, MToonTuning, ObjectContent, ObjectSpace, 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;
|
|
@@ -178,6 +178,47 @@ export declare function contentAssetId(content: ObjectContent): string | null;
|
|
|
178
178
|
* would z-fight by construction.
|
|
179
179
|
*/
|
|
180
180
|
export declare function attachableParentFormat(space: ObjectSpace): ModelFormat;
|
|
181
|
+
/**
|
|
182
|
+
* Every instance that rides `instanceId`, directly or through a chain of pins — the set it can
|
|
183
|
+
* never pin to itself, or the two would ride each other in a circle. Includes `instanceId`.
|
|
184
|
+
*/
|
|
185
|
+
export declare function pinRiders(items: readonly {
|
|
186
|
+
instanceId: string;
|
|
187
|
+
attach?: {
|
|
188
|
+
parentInstanceId: string;
|
|
189
|
+
} | null;
|
|
190
|
+
}[], instanceId: string): Set<string>;
|
|
191
|
+
/**
|
|
192
|
+
* Rows for the pin picker: every other Live2D model, each flagged when it already rides
|
|
193
|
+
* `instanceId` — picking one would put the two in a circle, so both apps offer it disabled
|
|
194
|
+
* rather than hidden. One rule, or the console offers a pin the desktop refuses.
|
|
195
|
+
*/
|
|
196
|
+
export declare function pinnableParents(models: readonly {
|
|
197
|
+
instanceId: string;
|
|
198
|
+
ref: {
|
|
199
|
+
kind: string;
|
|
200
|
+
name: string;
|
|
201
|
+
};
|
|
202
|
+
}[], items: readonly {
|
|
203
|
+
instanceId: string;
|
|
204
|
+
attach?: {
|
|
205
|
+
parentInstanceId: string;
|
|
206
|
+
} | null;
|
|
207
|
+
}[], instanceId: string): {
|
|
208
|
+
instanceId: string;
|
|
209
|
+
name: string;
|
|
210
|
+
ridesThis: boolean;
|
|
211
|
+
}[];
|
|
212
|
+
/**
|
|
213
|
+
* The depth control's stops, back to front: behind the model, above each of its ArtMeshes in
|
|
214
|
+
* paint order, then in front of it all. One continuous run, so depth is a slider over the host's
|
|
215
|
+
* stack rather than a list of ArtMesh ids nobody can read.
|
|
216
|
+
*/
|
|
217
|
+
export declare function depthStops(meshes: readonly string[]): AttachDepth[];
|
|
218
|
+
/** Which stop a depth sits at; an ArtMesh the host no longer has reads as the frontmost. */
|
|
219
|
+
export declare function depthStopIndex(meshes: readonly string[], depth: AttachDepth): number;
|
|
220
|
+
/** A fresh pin onto `parentInstanceId`: root anchor, in front of the model, no response tuning. */
|
|
221
|
+
export declare function defaultAttach(parentInstanceId: string): Attach;
|
|
181
222
|
export declare const DEFAULT_HEAD_ANGLE: NonNullable<Attach['headAngle']>;
|
|
182
223
|
export declare const ATTACH_MULTIPLIER_MIN = -2;
|
|
183
224
|
export declare const ATTACH_MULTIPLIER_MAX = 2;
|
package/dist/values/limits.js
CHANGED
|
@@ -304,6 +304,71 @@ export function contentAssetId(content) {
|
|
|
304
304
|
export function attachableParentFormat(space) {
|
|
305
305
|
return space === '2d' ? 'live2d' : 'vrm';
|
|
306
306
|
}
|
|
307
|
+
/**
|
|
308
|
+
* Every instance that rides `instanceId`, directly or through a chain of pins — the set it can
|
|
309
|
+
* never pin to itself, or the two would ride each other in a circle. Includes `instanceId`.
|
|
310
|
+
*/
|
|
311
|
+
export function pinRiders(items, instanceId) {
|
|
312
|
+
const riders = new Set([instanceId]);
|
|
313
|
+
// One pass per item is enough for a chain of any depth: each pass adopts the next level down.
|
|
314
|
+
for (let i = 0; i < items.length; i++) {
|
|
315
|
+
let grew = false;
|
|
316
|
+
for (const item of items) {
|
|
317
|
+
const parent = item.attach?.parentInstanceId;
|
|
318
|
+
if (parent !== undefined && riders.has(parent) && !riders.has(item.instanceId)) {
|
|
319
|
+
riders.add(item.instanceId);
|
|
320
|
+
grew = true;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (!grew)
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
return riders;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Rows for the pin picker: every other Live2D model, each flagged when it already rides
|
|
330
|
+
* `instanceId` — picking one would put the two in a circle, so both apps offer it disabled
|
|
331
|
+
* rather than hidden. One rule, or the console offers a pin the desktop refuses.
|
|
332
|
+
*/
|
|
333
|
+
export function pinnableParents(models, items, instanceId) {
|
|
334
|
+
const riders = pinRiders(items, instanceId);
|
|
335
|
+
const out = [];
|
|
336
|
+
for (const m of models) {
|
|
337
|
+
if (m.ref.kind !== 'live2d' || m.instanceId === instanceId)
|
|
338
|
+
continue;
|
|
339
|
+
out.push({ instanceId: m.instanceId, name: m.ref.name, ridesThis: riders.has(m.instanceId) });
|
|
340
|
+
}
|
|
341
|
+
return out;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* The depth control's stops, back to front: behind the model, above each of its ArtMeshes in
|
|
345
|
+
* paint order, then in front of it all. One continuous run, so depth is a slider over the host's
|
|
346
|
+
* stack rather than a list of ArtMesh ids nobody can read.
|
|
347
|
+
*/
|
|
348
|
+
export function depthStops(meshes) {
|
|
349
|
+
return [{ kind: 'behind' }, ...meshes.map((id) => ({ kind: 'artMesh', id })), { kind: 'front' }];
|
|
350
|
+
}
|
|
351
|
+
/** Which stop a depth sits at; an ArtMesh the host no longer has reads as the frontmost. */
|
|
352
|
+
export function depthStopIndex(meshes, depth) {
|
|
353
|
+
if (depth.kind === 'behind')
|
|
354
|
+
return 0;
|
|
355
|
+
if (depth.kind === 'front')
|
|
356
|
+
return meshes.length + 1;
|
|
357
|
+
const at = meshes.indexOf(depth.id);
|
|
358
|
+
return at < 0 ? meshes.length + 1 : at + 1;
|
|
359
|
+
}
|
|
360
|
+
/** A fresh pin onto `parentInstanceId`: root anchor, in front of the model, no response tuning. */
|
|
361
|
+
export function defaultAttach(parentInstanceId) {
|
|
362
|
+
return {
|
|
363
|
+
parentInstanceId,
|
|
364
|
+
anchor: { kind: 'root' },
|
|
365
|
+
followRotation: true,
|
|
366
|
+
depth: { kind: 'front' },
|
|
367
|
+
split: null,
|
|
368
|
+
headAngle: null,
|
|
369
|
+
elasticity: null,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
307
372
|
export const DEFAULT_HEAD_ANGLE = {
|
|
308
373
|
multiplier: 1,
|
|
309
374
|
parallaxX: 0,
|
package/dist/wire/events.d.ts
CHANGED
|
@@ -31,10 +31,12 @@ export interface EventMap {
|
|
|
31
31
|
active: string[];
|
|
32
32
|
weights?: Record<string, number>;
|
|
33
33
|
};
|
|
34
|
+
/** `oneShot`: the motion outranks the idle, so `motion.stop` would end it; hosts with `motion-stop` send it. */
|
|
34
35
|
'motion.started': {
|
|
35
36
|
instanceId: string;
|
|
36
37
|
group: string;
|
|
37
38
|
index: number;
|
|
39
|
+
oneShot?: boolean;
|
|
38
40
|
};
|
|
39
41
|
'motion.ended': {
|
|
40
42
|
instanceId: string;
|
package/dist/wire/methods.d.ts
CHANGED
|
@@ -149,6 +149,16 @@ export interface InstanceSetPlacementRequest {
|
|
|
149
149
|
vrm?: Partial<VrmPlacement>;
|
|
150
150
|
}
|
|
151
151
|
export type InstanceSetPlacementResponse = EmptyResponse;
|
|
152
|
+
/**
|
|
153
|
+
* Pin a Live2D instance to another one as an item (VTS's Live2D Items): its placement becomes an
|
|
154
|
+
* offset from the anchor, and `attach.depth` says where it paints in the host's ArtMesh stack.
|
|
155
|
+
*/
|
|
156
|
+
export interface InstanceAttachRequest {
|
|
157
|
+
instanceId?: string;
|
|
158
|
+
/** Null detaches, leaving the instance where it stands. */
|
|
159
|
+
attach: AttachInput | null;
|
|
160
|
+
}
|
|
161
|
+
export type InstanceAttachResponse = EmptyResponse;
|
|
152
162
|
export interface InstanceSetMToonRequest {
|
|
153
163
|
instanceId?: string;
|
|
154
164
|
tuning: Partial<MToonTuning>;
|
|
@@ -292,6 +302,16 @@ export interface MotionPlayingRequest {
|
|
|
292
302
|
}
|
|
293
303
|
export interface MotionPlayingResponse {
|
|
294
304
|
playing: PlayingMotion | null;
|
|
305
|
+
/** `playing` outranks the idle — what `motion.stop` ends. Absent on hosts without `motion-stop`. */
|
|
306
|
+
oneShot?: boolean;
|
|
307
|
+
}
|
|
308
|
+
/** Fade the running motion out and let the idle resume; the idle itself is left alone. */
|
|
309
|
+
export interface MotionStopRequest {
|
|
310
|
+
instanceId?: string;
|
|
311
|
+
}
|
|
312
|
+
export interface MotionStopResponse {
|
|
313
|
+
/** A motion above the idle was playing and is now fading out. */
|
|
314
|
+
stopped: boolean;
|
|
295
315
|
}
|
|
296
316
|
/** Play a clip with lip-sync. One utterance per model: a new play supersedes the current one. */
|
|
297
317
|
export interface SpeechPlayRequest {
|
|
@@ -800,6 +820,10 @@ export interface MethodMap {
|
|
|
800
820
|
request: InstanceSetPlacementRequest;
|
|
801
821
|
response: InstanceSetPlacementResponse;
|
|
802
822
|
};
|
|
823
|
+
'instance.attach': {
|
|
824
|
+
request: InstanceAttachRequest;
|
|
825
|
+
response: InstanceAttachResponse;
|
|
826
|
+
};
|
|
803
827
|
'instance.setMToon': {
|
|
804
828
|
request: InstanceSetMToonRequest;
|
|
805
829
|
response: InstanceSetMToonResponse;
|
|
@@ -884,6 +908,11 @@ export interface MethodMap {
|
|
|
884
908
|
request: MotionPlayingRequest;
|
|
885
909
|
response: MotionPlayingResponse;
|
|
886
910
|
};
|
|
911
|
+
/** Needs the `motion-stop` app capability. */
|
|
912
|
+
'motion.stop': {
|
|
913
|
+
request: MotionStopRequest;
|
|
914
|
+
response: MotionStopResponse;
|
|
915
|
+
};
|
|
887
916
|
/**
|
|
888
917
|
* Lip-synced audio on models advertising the `speech` capability. The response means
|
|
889
918
|
* playback started (else `invalid-state`); `speech.started`/`speech.ended` bracket it.
|
package/dist/wire/types.d.ts
CHANGED
|
@@ -198,6 +198,12 @@ export interface SceneModelItem {
|
|
|
198
198
|
breathDepth: number;
|
|
199
199
|
/** MToon material fine-tuning, VRM only. */
|
|
200
200
|
mtoon: MToonTuning;
|
|
201
|
+
/**
|
|
202
|
+
* Live2D only: this model rides another one as an item (VTS's Live2D Items) — its placement
|
|
203
|
+
* reads as an offset from the anchor, and `depth` says where it paints in the parent's stack.
|
|
204
|
+
* Null stands alone; a VRM instance ignores it, keeping it across a format switch.
|
|
205
|
+
*/
|
|
206
|
+
attach: Attach | null;
|
|
201
207
|
}
|
|
202
208
|
export declare const OBJECT_SPACES: readonly ["2d", "3d"];
|
|
203
209
|
export type ObjectSpace = (typeof OBJECT_SPACES)[number];
|
|
@@ -275,11 +281,41 @@ export interface AttachElasticity {
|
|
|
275
281
|
damping: number;
|
|
276
282
|
maxSpeed: number;
|
|
277
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* How deep a pinned item paints in its parent — VTube Studio's Between-Layer Item Pinning, as one
|
|
286
|
+
* value: the two ends clear the parent's whole stack, and `artMesh` slots the item in directly
|
|
287
|
+
* above that ArtMesh, so every parent mesh over it paints on top. Ids rather than positions,
|
|
288
|
+
* because Cubism re-sorts the stack as motions play, and an id carries to any rig that has it.
|
|
289
|
+
* Live2D parents on the three engine only: elsewhere an item always paints in front.
|
|
290
|
+
*/
|
|
291
|
+
export type AttachDepth = {
|
|
292
|
+
kind: 'front';
|
|
293
|
+
} | {
|
|
294
|
+
kind: 'behind';
|
|
295
|
+
} | {
|
|
296
|
+
kind: 'artMesh';
|
|
297
|
+
id: string;
|
|
298
|
+
};
|
|
299
|
+
/**
|
|
300
|
+
* VTube Studio's front/back splitting: the item is cut at one of its **own** ArtMeshes, and
|
|
301
|
+
* everything it paints below that goes to a second depth in the parent — so the parent's meshes
|
|
302
|
+
* in between wrap over it (a scarf in front of the chest and behind the hair). Live2D items only.
|
|
303
|
+
*/
|
|
304
|
+
export interface AttachSplit {
|
|
305
|
+
/** ArtMesh of the item it is cut at; the item paints everything under this as its back half. */
|
|
306
|
+
itemArtMesh: string;
|
|
307
|
+
/** How deep the back half paints — the same control as the item's own depth. */
|
|
308
|
+
depth: AttachDepth;
|
|
309
|
+
}
|
|
278
310
|
export interface Attach {
|
|
279
311
|
/** Always a model instance in the same space; anything else is cleared on load. */
|
|
280
312
|
parentInstanceId: string;
|
|
281
313
|
anchor: AttachAnchor;
|
|
282
314
|
followRotation: boolean;
|
|
315
|
+
/** Where it paints in the parent's ArtMesh stack; `front` is the plain "on top of the model". */
|
|
316
|
+
depth: AttachDepth;
|
|
317
|
+
/** Front/back splitting, independent of `depth`; null keeps the item in one piece. */
|
|
318
|
+
split: AttachSplit | null;
|
|
283
319
|
headAngle: AttachHeadAngle | null;
|
|
284
320
|
elasticity: AttachElasticity | null;
|
|
285
321
|
}
|
|
@@ -1005,7 +1041,7 @@ export interface ScenePatch {
|
|
|
1005
1041
|
* App-level features a client gates on (never version-sniff): `hello` and
|
|
1006
1042
|
* `app.info` report them — the per-app mirror of {@link InstanceRuntime.capabilities}.
|
|
1007
1043
|
*/
|
|
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"];
|
|
1044
|
+
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", "motion-stop"];
|
|
1009
1045
|
export type AppCapability = (typeof APP_CAPABILITIES)[number];
|
|
1010
1046
|
export declare function isAppCapability(v: unknown): v is AppCapability;
|
|
1011
1047
|
/** What a loaded model instance can do; absent capabilities answer `unsupported-for-format`. */
|
|
@@ -1059,6 +1095,11 @@ export interface PlayingMotion {
|
|
|
1059
1095
|
export interface AnchorOption {
|
|
1060
1096
|
anchor: AttachAnchor;
|
|
1061
1097
|
label: string;
|
|
1098
|
+
/**
|
|
1099
|
+
* Paint order when the list was taken, ascending from the backmost — what the depth control
|
|
1100
|
+
* orders its stops by. Live2D only, and absent from hosts older than depth pinning.
|
|
1101
|
+
*/
|
|
1102
|
+
order?: number;
|
|
1062
1103
|
}
|
|
1063
1104
|
export type { ModelInfo } from '../values/model-info.ts';
|
|
1064
1105
|
export interface Hotkey {
|
package/dist/wire/types.js
CHANGED
|
@@ -49,6 +49,8 @@ export const APP_CAPABILITIES = [
|
|
|
49
49
|
'spawn',
|
|
50
50
|
/** `instance.setIdle` takes `trackingLostBehavior`, `trackingLostMotion` and `trackingLostDelay`. */
|
|
51
51
|
'tracking-lost',
|
|
52
|
+
/** `motion.stop`; `motion.playing` and `motion.started` carry `oneShot`. */
|
|
53
|
+
'motion-stop',
|
|
52
54
|
];
|
|
53
55
|
export function isAppCapability(v) {
|
|
54
56
|
return isOneOf(v, APP_CAPABILITIES);
|