@laplace.live/persona-sdk 0.10.0 → 0.12.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 type { SceneEffects } from '../wire/types.ts';
1
+ import type { SceneEffects, ToggleEffectKey } from '../wire/types.ts';
2
2
  /** Slider + healing metadata for one numeric effect parameter. */
3
3
  export interface EffectParamSpec {
4
4
  default: number;
@@ -14,12 +14,6 @@ export interface EffectParamSpec {
14
14
  export interface EffectColorSpec {
15
15
  default: string;
16
16
  }
17
- /** Keys of {@link SceneEffects} that follow the `{ enabled } + params` pattern. */
18
- export type ToggleEffectKey = {
19
- [K in keyof SceneEffects]: SceneEffects[K] extends {
20
- enabled: boolean;
21
- } ? K : never;
22
- }[keyof SceneEffects];
23
17
  export declare const EFFECT_SPECS: Record<ToggleEffectKey, Readonly<Record<string, EffectParamSpec>>>;
24
18
  /**
25
19
  * Hex-color params, keyed like {@link EFFECT_SPECS} — generic walkers (healing,
@@ -36,5 +30,12 @@ export declare const TOGGLE_EFFECT_KEYS: readonly ToggleEffectKey[];
36
30
  export declare const SCENE_SPACE_EFFECT_KEYS: readonly ToggleEffectKey[];
37
31
  /** Registry effects the post chain composes — {@link TOGGLE_EFFECT_KEYS} minus the scene-space ones. */
38
32
  export declare const POST_EFFECT_KEYS: readonly ToggleEffectKey[];
33
+ /** The canonical `effectLayers`: registry order, junk dropped, every switched-on effect included. */
34
+ export declare function effectLayerKeys(listed: readonly unknown[], effects: Pick<SceneEffects, ToggleEffectKey>): ToggleEffectKey[];
35
+ /**
36
+ * Composition order, bottom to top, with user-authored effects as one `'custom'` group.
37
+ * Display-only: the desktop chain's `rebuild()` is the order that runs — a stage moved there moves here too.
38
+ */
39
+ export declare const EFFECT_STACK_ORDER: readonly (ToggleEffectKey | 'custom')[];
39
40
  /** Every registry effect at its defaults — the derived half of a fresh {@link SceneEffects}. */
40
41
  export declare function defaultToggleEffects(): Pick<SceneEffects, ToggleEffectKey>;
@@ -177,6 +177,32 @@ export const TOGGLE_EFFECT_KEYS = Object.keys(EFFECT_SPECS);
177
177
  export const SCENE_SPACE_EFFECT_KEYS = ['rain', 'snow'];
178
178
  /** Registry effects the post chain composes — {@link TOGGLE_EFFECT_KEYS} minus the scene-space ones. */
179
179
  export const POST_EFFECT_KEYS = TOGGLE_EFFECT_KEYS.filter(key => !SCENE_SPACE_EFFECT_KEYS.includes(key));
180
+ /** The canonical `effectLayers`: registry order, junk dropped, every switched-on effect included. */
181
+ export function effectLayerKeys(listed, effects) {
182
+ return TOGGLE_EFFECT_KEYS.filter(key => listed.includes(key) || effects[key].enabled);
183
+ }
184
+ /**
185
+ * Composition order, bottom to top, with user-authored effects as one `'custom'` group.
186
+ * Display-only: the desktop chain's `rebuild()` is the order that runs — a stage moved there moves here too.
187
+ */
188
+ export const EFFECT_STACK_ORDER = [
189
+ 'rain',
190
+ 'snow',
191
+ 'dof',
192
+ 'rim',
193
+ 'outline',
194
+ 'dropShadow',
195
+ 'chromaticAberration',
196
+ 'bloom',
197
+ 'diffusion',
198
+ 'color',
199
+ 'pixelate',
200
+ 'glitch',
201
+ 'droplets',
202
+ 'custom',
203
+ 'grain',
204
+ 'vignette',
205
+ ];
180
206
  /** Every registry effect at its defaults — the derived half of a fresh {@link SceneEffects}. */
181
207
  export function defaultToggleEffects() {
182
208
  const out = {};
@@ -52,6 +52,8 @@ export declare const PLACE_3D_SCALE_MIN = 0.01;
52
52
  export declare const PLACE_3D_SCALE_MAX = 100;
53
53
  /** A prop is a mesh, so it only exists in the three.js scene; every other kind renders in both. */
54
54
  export declare function objectSupportsSpace(kind: ObjectContent['kind'], space: ObjectSpace): boolean;
55
+ /** The asset an object streams from, or null for kinds that carry their source inline (web, capture). */
56
+ export declare function contentAssetId(content: ObjectContent): string | null;
55
57
  /**
56
58
  * The one model format a space's objects can ride: the renderers never mix, and
57
59
  * the three canvas always composites over the Pixi one, so a cross-space pin
@@ -61,6 +63,8 @@ export declare function attachableParentFormat(space: ObjectSpace): ModelFormat;
61
63
  export declare const DEFAULT_HEAD_ANGLE: NonNullable<Attach['headAngle']>;
62
64
  export declare const ATTACH_MULTIPLIER_MIN = -2;
63
65
  export declare const ATTACH_MULTIPLIER_MAX = 2;
66
+ /** Parallax slider ceiling, symmetric: stage px at a full head turn. */
67
+ export declare const ATTACH_PARALLAX_MAX = 300;
64
68
  export declare const ATTACH_SMOOTHING_MAX = 50;
65
69
  export declare const DEFAULT_ELASTICITY: NonNullable<Attach['elasticity']>;
66
70
  export declare const ELASTICITY_STIFFNESS_MAX = 100;
@@ -90,6 +90,10 @@ export const PLACE_3D_SCALE_MAX = 100;
90
90
  export function objectSupportsSpace(kind, space) {
91
91
  return kind === 'prop' ? space === '3d' : true;
92
92
  }
93
+ /** The asset an object streams from, or null for kinds that carry their source inline (web, capture). */
94
+ export function contentAssetId(content) {
95
+ return content.kind === 'image' || content.kind === 'video' || content.kind === 'prop' ? content.assetId : null;
96
+ }
93
97
  /**
94
98
  * The one model format a space's objects can ride: the renderers never mix, and
95
99
  * the three canvas always composites over the Pixi one, so a cross-space pin
@@ -98,9 +102,16 @@ export function objectSupportsSpace(kind, space) {
98
102
  export function attachableParentFormat(space) {
99
103
  return space === '2d' ? 'live2d' : 'vrm';
100
104
  }
101
- export const DEFAULT_HEAD_ANGLE = { multiplier: 1, smoothing: 15 };
105
+ export const DEFAULT_HEAD_ANGLE = {
106
+ multiplier: 1,
107
+ parallaxX: 0,
108
+ parallaxY: 0,
109
+ smoothing: 15,
110
+ };
102
111
  export const ATTACH_MULTIPLIER_MIN = -2;
103
112
  export const ATTACH_MULTIPLIER_MAX = 2;
113
+ /** Parallax slider ceiling, symmetric: stage px at a full head turn. */
114
+ export const ATTACH_PARALLAX_MAX = 300;
104
115
  export const ATTACH_SMOOTHING_MAX = 50;
105
116
  // Warudo Attachable defaults and slider ceilings, verbatim.
106
117
  export const DEFAULT_ELASTICITY = { stiffness: 2, damping: 3, maxSpeed: 2 };
@@ -1,5 +1,5 @@
1
1
  import type { EventName } from './events.ts';
2
- import type { AnchorOption, AppCapability, AssetKind, AssetRef, Attach, Expression, ExpressionPersistence, HotkeyConfig, HotkeyState, InjectEntry, InjectTarget, InstanceRuntime, JsonValue, ModelInfo, ModelRef, MotionGroup, MToonTuning, ObjectContent, ObjectLightOverride, ObjectSpace, Place2D, Place3D, PlayingMotion, PoseSourceId, PoseStatus, Scene, SceneItem, ScenePatch, SceneState, ScreenPlacement, Settings, SettingsPatch, ShortcutInfo, TrackingSourceConfig, TrackingSourceId, TrackingSourceKind, TrackingStatus, VrmPlacement } from './types.ts';
2
+ import type { AnchorOption, AppCapability, AssetKind, AssetRef, Attach, AttachHeadAngle, Expression, ExpressionPersistence, HotkeyConfig, HotkeyState, InjectEntry, InjectTarget, InstanceRuntime, JsonValue, ModelInfo, ModelRef, MotionGroup, MToonTuning, ObjectContent, ObjectLightOverride, ObjectSpace, Place2D, Place3D, PlayingMotion, PoseSourceId, PoseStatus, Scene, SceneItem, ScenePatch, SceneState, ScreenPlacement, Settings, SettingsPatch, ShortcutInfo, TrackingSourceConfig, TrackingSourceId, TrackingSourceKind, TrackingStatus, VrmPlacement } from './types.ts';
3
3
  /** Marker for methods that take no parameters; the client lets you omit the argument. */
4
4
  export type EmptyRequest = Record<never, never>;
5
5
  /** Marker for methods whose success response carries no data. */
@@ -149,10 +149,14 @@ export interface ObjectSetPlacementRequest {
149
149
  place3d?: Partial<Place3D>;
150
150
  }
151
151
  export type ObjectSetPlacementResponse = EmptyResponse;
152
+ /** {@link Attach} as `object.attach` accepts it: head-angle fields may be omitted and heal to their defaults. */
153
+ export type AttachInput = Omit<Attach, 'headAngle'> & {
154
+ headAngle: Partial<AttachHeadAngle> | null;
155
+ };
152
156
  export interface ObjectAttachRequest {
153
157
  instanceId: string;
154
158
  /** Null detaches. */
155
- attach: Attach | null;
159
+ attach: AttachInput | null;
156
160
  }
157
161
  export type ObjectAttachResponse = EmptyResponse;
158
162
  export interface ObjectSetLightOverridesRequest {
@@ -2,9 +2,15 @@ export type ModelFormat = 'live2d' | 'vrm';
2
2
  /** Where an item came from: shipped with the app, or added by the user. */
3
3
  export type ContentOrigin = 'bundled' | 'user';
4
4
  /** How a registered file is labelled. Wider than an object's content kinds: `.hdr` is only ever an environment map. */
5
- export type AssetKind = 'image' | 'video' | 'prop' | 'ibl' | 'lut' | 'animation';
6
- /** Every content kind the Inventory can list. `pngtuber` is schema-ready before any producer exists. */
7
- export type InventoryKind = ModelFormat | 'pngtuber' | AssetKind;
5
+ export declare const ASSET_KINDS: readonly ["image", "video", "prop", "ibl", "lut", "animation"];
6
+ export type AssetKind = (typeof ASSET_KINDS)[number];
7
+ /** Narrow a kind string to the set the asset registry owns — models and effects have their own. */
8
+ export declare function isAssetKind(v: unknown): v is AssetKind;
9
+ /**
10
+ * Every content kind the Inventory can list. `pngtuber` is schema-ready before any
11
+ * producer exists; `effect` rows are post-processing effects (built-in or installed), not files.
12
+ */
13
+ export type InventoryKind = ModelFormat | 'pngtuber' | AssetKind | 'effect';
8
14
  /**
9
15
  * What every registry entry carries, model or asset alike. `kind` is always *what
10
16
  * the thing is* and `origin` always *where it came from* — the two were once
@@ -171,9 +177,12 @@ export type AttachAnchor = {
171
177
  verts: [number, number, number];
172
178
  weights: [number, number, number];
173
179
  };
174
- /** Live2D only: smoothed ParamAngleZ × multiplier turns the pinned item (X/Y ride the mesh). */
180
+ /** Live2D only: ParamAngleZ × multiplier turns the pinned item; ParamAngleX/Y × parallax shift it (smoothed). */
175
181
  export interface AttachHeadAngle {
176
182
  multiplier: number;
183
+ /** Stage px at a full head turn (model at scale 1); positive = in front of the mesh, negative = behind. */
184
+ parallaxX: number;
185
+ parallaxY: number;
177
186
  /** VTS-style 0..50; ~frames of lag at 60 fps (0 = instant). */
178
187
  smoothing: number;
179
188
  }
@@ -247,7 +256,7 @@ export type SceneLightType = 'directional' | 'point' | 'ambient';
247
256
  * shadow-map resolution. A point light pays 6 cube faces for the same tier a
248
257
  * directional light covers with one map, so it gets the smaller of the pair.
249
258
  */
250
- export declare const SHADOW_QUALITY_LEVELS: readonly ["off", "low", "medium", "high", "extra"];
259
+ export declare const SHADOW_QUALITY_LEVELS: readonly ["off", "low", "medium", "high", "ultra"];
251
260
  export type ShadowQuality = (typeof SHADOW_QUALITY_LEVELS)[number];
252
261
  /**
253
262
  * One scene light. Angles are degrees. Directional lights aim with
@@ -539,6 +548,12 @@ export interface SceneEffects {
539
548
  rain: SceneRain;
540
549
  snow: SceneSnow;
541
550
  }
551
+ /** Keys of {@link SceneEffects} that follow the `{ enabled } + params` pattern. */
552
+ export type ToggleEffectKey = {
553
+ [K in keyof SceneEffects]: SceneEffects[K] extends {
554
+ enabled: boolean;
555
+ } ? K : never;
556
+ }[keyof SceneEffects];
542
557
  /**
543
558
  * One user-authored effect's placement in a scene. Deliberately a sibling of
544
559
  * {@link SceneEffects} rather than a key inside it: `ToggleEffectKey` is derived
@@ -568,6 +583,11 @@ export interface SceneEnvironment {
568
583
  showSkybox: boolean;
569
584
  fog: SceneFog;
570
585
  effects: SceneEffects;
586
+ /**
587
+ * Built-in effects added as layers, in registry order — one keeps its row and tuning while
588
+ * switched off. Healing lists every switched-on effect, so a patch that switches one on adds its layer.
589
+ */
590
+ effectLayers: ToggleEffectKey[];
571
591
  /**
572
592
  * User-authored effects, in the order they compose. They run as a group at one
573
593
  * fixed point in the post chain — after grading and the screen-space warps,
@@ -1,12 +1,18 @@
1
1
  // The API's data model: the entity shapes that requests, responses, and events
2
2
  // carry. Structural mirrors of the app's scene/settings models, minus anything
3
3
  // filesystem-shaped — model refs are sanitized to ids, never directories.
4
+ /** How a registered file is labelled. Wider than an object's content kinds: `.hdr` is only ever an environment map. */
5
+ export const ASSET_KINDS = ['image', 'video', 'prop', 'ibl', 'lut', 'animation'];
6
+ /** Narrow a kind string to the set the asset registry owns — models and effects have their own. */
7
+ export function isAssetKind(v) {
8
+ return typeof v === 'string' && ASSET_KINDS.includes(v);
9
+ }
4
10
  /**
5
11
  * Per-light shadow tier. `off` is the old `castShadow: false`; the rest raise
6
12
  * shadow-map resolution. A point light pays 6 cube faces for the same tier a
7
13
  * directional light covers with one map, so it gets the smaller of the pair.
8
14
  */
9
- export const SHADOW_QUALITY_LEVELS = ['off', 'low', 'medium', 'high', 'extra'];
15
+ export const SHADOW_QUALITY_LEVELS = ['off', 'low', 'medium', 'high', 'ultra'];
10
16
  // ---- Runtime state -------------------------------------------------------------
11
17
  /**
12
18
  * App-level features a client gates on (never version-sniff): `hello` and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@laplace.live/persona-sdk",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "TypeScript SDK and wire schema for the LAPLACE Persona plugin API",
5
5
  "license": "MIT",
6
6
  "type": "module",