@laplace.live/persona-sdk 1.9.0 → 1.11.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 +28 -11
- package/dist/values/limits.js +47 -16
- package/dist/values/stage-info.d.ts +4 -1
- package/dist/values/volumetric-lighting.d.ts +1 -1
- package/dist/values/volumetric-lighting.js +1 -3
- package/dist/wire/methods.d.ts +16 -1
- package/dist/wire/schemas/requests.d.ts +9 -0
- package/dist/wire/schemas/requests.js +5 -0
- package/dist/wire/types.d.ts +51 -10
- package/dist/wire/types.js +2 -0
- package/package.json +2 -2
package/dist/values/limits.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AssetRef, Attach, EnvironmentLook, ModelFormat, MToonTuning, ObjectContent, ObjectSpace, SceneEnvironment, SceneLight, SceneLightType, ScreenPlacement, VrmPlacement } from '../wire/types.ts';
|
|
1
|
+
import type { AssetRef, Attach, 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;
|
|
@@ -13,6 +13,7 @@ export declare function hexColorOr(v: unknown, fallback: string): string;
|
|
|
13
13
|
/** Drop the alpha byte a picker's hex input can produce (`#rrggbbaa` → `#rrggbb`). */
|
|
14
14
|
export declare function opaqueHex(hex: string): string;
|
|
15
15
|
export declare const SCENE_LIGHT_INTENSITY_MAX = 2;
|
|
16
|
+
export declare const SCENE_SKYBOX_INTENSITY_MAX = 2;
|
|
16
17
|
/**
|
|
17
18
|
* Point lights need headroom against inverse-square decay; directional and ambient
|
|
18
19
|
* lights have no falloff and would wash out the stage at the same intensity.
|
|
@@ -32,6 +33,8 @@ export declare function sceneLightIntensityMax(type: SceneLightType): number;
|
|
|
32
33
|
export declare function sceneLightIsAimed(type: SceneLightType): boolean;
|
|
33
34
|
/** Whether a light of `type` can cast shadows; ambient and area lights never do. */
|
|
34
35
|
export declare function sceneLightCastsShadows(type: SceneLightType): boolean;
|
|
36
|
+
/** Whether a light of `type` can light volumetric haze; directional and ambient lights never do. */
|
|
37
|
+
export declare function sceneLightCanHaze(type: SceneLightType): boolean;
|
|
35
38
|
export declare const LIVE2D_SCALE_MIN = 0.1;
|
|
36
39
|
export declare const LIVE2D_SCALE_MAX = 24;
|
|
37
40
|
export declare const VRM_SCALE_MIN = 0.05;
|
|
@@ -63,6 +66,17 @@ export declare const ELEVATION_LIMIT: number;
|
|
|
63
66
|
/** Manual navigation distance bounds; authored cameras retain signed, unrestricted distances. */
|
|
64
67
|
export declare const DISTANCE_MIN = 0.35;
|
|
65
68
|
export declare const DISTANCE_MAX = 20;
|
|
69
|
+
/** A scene's manual navigation distance bounds, in world units. */
|
|
70
|
+
export interface CameraDistanceLimits {
|
|
71
|
+
min: number;
|
|
72
|
+
max: number;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* {@link DISTANCE_MIN} and {@link DISTANCE_MAX}, widened in proportion for an Environment Model placed larger
|
|
76
|
+
* or smaller than a ~10 m room. Neither bound ever narrows.
|
|
77
|
+
* @param setRadius The loaded set's own bounding radius, before its placement scale; null until one has loaded.
|
|
78
|
+
*/
|
|
79
|
+
export declare function cameraDistanceLimits(env: Pick<SceneEnvironment, 'modelAssetId' | 'modelPlace'>, setRadius: number | null): CameraDistanceLimits;
|
|
66
80
|
/** ×2 doubles Cubism's own breath amplitude — past that the head sway reads as a nod, not a breath. */
|
|
67
81
|
export declare const BREATH_DEPTH_MAX = 2;
|
|
68
82
|
export declare const MTOON_NORMAL_SCALE_MAX = 2;
|
|
@@ -78,6 +92,8 @@ export declare const MTOON_UV_ANIMATION_MAX = 4;
|
|
|
78
92
|
export declare function defaultMToonTuning(): MToonTuning;
|
|
79
93
|
export declare const DEFAULT_LIGHT_AZIMUTH_DEG = 45;
|
|
80
94
|
export declare const DEFAULT_LIGHT_ELEVATION_DEG: number;
|
|
95
|
+
/** What a following light tracks when `followCameraOptions` is omitted. */
|
|
96
|
+
export declare const DEFAULT_LIGHT_FOLLOW_CAMERA_OPTIONS: SceneLightCameraFollowOptions;
|
|
81
97
|
/** A fresh light of `type`, at the defaults that read sensibly for that type. */
|
|
82
98
|
export declare function defaultSceneLightOf(type: SceneLightType): SceneLight;
|
|
83
99
|
/**
|
|
@@ -115,17 +131,18 @@ export declare function applyEnvironmentLook(env: SceneEnvironment, look: Enviro
|
|
|
115
131
|
* simply arrive wearing it.
|
|
116
132
|
*/
|
|
117
133
|
export declare function environmentLookIsUntouched(env: SceneEnvironment, reference: SceneEnvironment): boolean;
|
|
134
|
+
/** An environment asset: the 3D set (`modelAssetId`) or the equirect map (`iblAssetId`). */
|
|
135
|
+
export type EnvironmentSlot = 'model' | 'map';
|
|
118
136
|
/**
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* `modelLook` stays put
|
|
128
|
-
* reads the outgoing one as what the scene wears now when deciding to adopt the next.
|
|
137
|
+
* The edit that removes one environment asset, or both for null. The model takes its baking and
|
|
138
|
+
* light overrides along; removing only the map hands lighting to a remaining model. `modelLook`
|
|
139
|
+
* stays, as in {@link environmentWithAsset}.
|
|
140
|
+
*/
|
|
141
|
+
export declare function environmentClearPatch(env: SceneEnvironment, slot: EnvironmentSlot | null): Partial<Pick<SceneEnvironment, 'iblAssetId' | 'modelAssetId' | 'bakeFromModel' | 'modelLightOverrides'>>;
|
|
142
|
+
/**
|
|
143
|
+
* Pick a model or map without removing the other; null clears both for legacy callers.
|
|
144
|
+
* A picked map becomes the lighting source. A first model generates lighting only without a map.
|
|
145
|
+
* `modelLook` stays put so the desktop can compare the outgoing look before adopting the next.
|
|
129
146
|
* @returns A new environment; the input is untouched.
|
|
130
147
|
*/
|
|
131
148
|
export declare function environmentWithAsset(env: SceneEnvironment, asset: Pick<AssetRef, 'id' | 'kind'> | null): SceneEnvironment;
|
package/dist/values/limits.js
CHANGED
|
@@ -29,6 +29,7 @@ export function opaqueHex(hex) {
|
|
|
29
29
|
return /^#[0-9a-f]{8}$/i.test(hex) ? hex.slice(0, 7) : hex;
|
|
30
30
|
}
|
|
31
31
|
export const SCENE_LIGHT_INTENSITY_MAX = 2;
|
|
32
|
+
export const SCENE_SKYBOX_INTENSITY_MAX = 2;
|
|
32
33
|
/**
|
|
33
34
|
* Point lights need headroom against inverse-square decay; directional and ambient
|
|
34
35
|
* lights have no falloff and would wash out the stage at the same intensity.
|
|
@@ -54,6 +55,10 @@ export function sceneLightIsAimed(type) {
|
|
|
54
55
|
export function sceneLightCastsShadows(type) {
|
|
55
56
|
return type !== 'ambient' && type !== 'area';
|
|
56
57
|
}
|
|
58
|
+
/** Whether a light of `type` can light volumetric haze; directional and ambient lights never do. */
|
|
59
|
+
export function sceneLightCanHaze(type) {
|
|
60
|
+
return type === 'point' || type === 'spot' || type === 'area';
|
|
61
|
+
}
|
|
57
62
|
// Live2D bounds are the zoom clamp (zoom.ts re-exports these); VRM scales a world-space root.
|
|
58
63
|
export const LIVE2D_SCALE_MIN = 0.1;
|
|
59
64
|
export const LIVE2D_SCALE_MAX = 24;
|
|
@@ -90,6 +95,17 @@ export const ELEVATION_LIMIT = (80 * Math.PI) / 180;
|
|
|
90
95
|
/** Manual navigation distance bounds; authored cameras retain signed, unrestricted distances. */
|
|
91
96
|
export const DISTANCE_MIN = 0.35;
|
|
92
97
|
export const DISTANCE_MAX = 20;
|
|
98
|
+
/** Bounding radius of the set the distance bounds are sized for: a ~10 m room {@link DISTANCE_MAX} frames whole. */
|
|
99
|
+
const DISTANCE_SET_RADIUS = 5;
|
|
100
|
+
/**
|
|
101
|
+
* {@link DISTANCE_MIN} and {@link DISTANCE_MAX}, widened in proportion for an Environment Model placed larger
|
|
102
|
+
* or smaller than a ~10 m room. Neither bound ever narrows.
|
|
103
|
+
* @param setRadius The loaded set's own bounding radius, before its placement scale; null until one has loaded.
|
|
104
|
+
*/
|
|
105
|
+
export function cameraDistanceLimits(env, setRadius) {
|
|
106
|
+
const size = env.modelAssetId === null || setRadius === null ? 1 : (setRadius * env.modelPlace.scale) / DISTANCE_SET_RADIUS;
|
|
107
|
+
return { min: DISTANCE_MIN * Math.min(1, size), max: DISTANCE_MAX * Math.max(1, size) };
|
|
108
|
+
}
|
|
93
109
|
/** ×2 doubles Cubism's own breath amplitude — past that the head sway reads as a nod, not a breath. */
|
|
94
110
|
export const BREATH_DEPTH_MAX = 2;
|
|
95
111
|
export const MTOON_NORMAL_SCALE_MAX = 2;
|
|
@@ -124,12 +140,20 @@ export function defaultMToonTuning() {
|
|
|
124
140
|
// Angles at which lightDirection reproduces (1,1,1).normalize() — the app's original hardcoded light.
|
|
125
141
|
export const DEFAULT_LIGHT_AZIMUTH_DEG = 45;
|
|
126
142
|
export const DEFAULT_LIGHT_ELEVATION_DEG = (Math.asin(1 / Math.sqrt(3)) * 180) / Math.PI;
|
|
143
|
+
/** What a following light tracks when `followCameraOptions` is omitted. */
|
|
144
|
+
export const DEFAULT_LIGHT_FOLLOW_CAMERA_OPTIONS = {
|
|
145
|
+
position: true,
|
|
146
|
+
rotation: true,
|
|
147
|
+
distance: true,
|
|
148
|
+
};
|
|
127
149
|
/** A fresh light of `type`, at the defaults that read sensibly for that type. */
|
|
128
150
|
export function defaultSceneLightOf(type) {
|
|
129
151
|
return {
|
|
130
152
|
id: crypto.randomUUID(),
|
|
131
153
|
type,
|
|
132
154
|
enabled: true,
|
|
155
|
+
followCamera: false,
|
|
156
|
+
followCameraOptions: { ...DEFAULT_LIGHT_FOLLOW_CAMERA_OPTIONS },
|
|
133
157
|
color: '#ffffff',
|
|
134
158
|
// Ambient is a flat albedo floor with no shading — 1.0 alone washes the model out.
|
|
135
159
|
intensity: type === 'ambient' ? 0.4 : 1,
|
|
@@ -144,6 +168,8 @@ export function defaultSceneLightOf(type) {
|
|
|
144
168
|
width: DEFAULT_AREA_LIGHT_SIZE,
|
|
145
169
|
height: DEFAULT_AREA_LIGHT_SIZE,
|
|
146
170
|
roll: 0,
|
|
171
|
+
// Haze is a render pass of its own; a new light joins it only when asked.
|
|
172
|
+
volumetric: false,
|
|
147
173
|
// A point light shadow is six cube faces, so it stays opt-in where a
|
|
148
174
|
// directional light's single depth pass can be on by default.
|
|
149
175
|
shadowQuality: type === 'directional' ? 'high' : 'off',
|
|
@@ -210,27 +236,32 @@ export function environmentLookIsUntouched(env, reference) {
|
|
|
210
236
|
return looked(env) === looked(reference);
|
|
211
237
|
}
|
|
212
238
|
/**
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
239
|
+
* The edit that removes one environment asset, or both for null. The model takes its baking and
|
|
240
|
+
* light overrides along; removing only the map hands lighting to a remaining model. `modelLook`
|
|
241
|
+
* stays, as in {@link environmentWithAsset}.
|
|
242
|
+
*/
|
|
243
|
+
export function environmentClearPatch(env, slot) {
|
|
244
|
+
if (slot === 'map')
|
|
245
|
+
return { iblAssetId: null, bakeFromModel: env.modelAssetId !== null };
|
|
246
|
+
const model = { modelAssetId: null, bakeFromModel: false, modelLightOverrides: {} };
|
|
247
|
+
return slot === 'model' ? model : { ...model, iblAssetId: null };
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Pick a model or map without removing the other; null clears both for legacy callers.
|
|
251
|
+
* A picked map becomes the lighting source. A first model generates lighting only without a map.
|
|
252
|
+
* `modelLook` stays put so the desktop can compare the outgoing look before adopting the next.
|
|
223
253
|
* @returns A new environment; the input is untouched.
|
|
224
254
|
*/
|
|
225
255
|
export function environmentWithAsset(env, asset) {
|
|
226
|
-
|
|
227
|
-
|
|
256
|
+
if (asset === null)
|
|
257
|
+
return { ...env, ...environmentClearPatch(env, null) };
|
|
258
|
+
if (asset.kind !== 'prop')
|
|
259
|
+
return { ...env, iblAssetId: asset.id, bakeFromModel: false };
|
|
228
260
|
return {
|
|
229
261
|
...env,
|
|
230
|
-
|
|
231
|
-
modelAssetId,
|
|
232
|
-
|
|
233
|
-
modelLightOverrides: modelAssetId === env.modelAssetId ? env.modelLightOverrides : {},
|
|
262
|
+
modelAssetId: asset.id,
|
|
263
|
+
bakeFromModel: env.modelAssetId === null ? env.iblAssetId === null : env.bakeFromModel,
|
|
264
|
+
modelLightOverrides: asset.id === env.modelAssetId ? env.modelLightOverrides : {},
|
|
234
265
|
};
|
|
235
266
|
}
|
|
236
267
|
export const PLACE_2D_SCALE_MIN = 0.01;
|
|
@@ -22,6 +22,9 @@ export interface SceneAssetInfo {
|
|
|
22
22
|
/** Metadata for the active scene, tagged so a response from a previous scene can be discarded. */
|
|
23
23
|
export interface SceneInspection {
|
|
24
24
|
sceneId: string;
|
|
25
|
-
environment: Omit<SceneAssetInfo, 'mediaSize'
|
|
25
|
+
environment: Omit<SceneAssetInfo, 'mediaSize'> & {
|
|
26
|
+
/** The set's own bounding radius before placement scale, for `cameraDistanceLimits`; omitted by older hosts. */
|
|
27
|
+
radius?: number | null;
|
|
28
|
+
};
|
|
26
29
|
objects: Record<string, SceneAssetInfo>;
|
|
27
30
|
}
|
|
@@ -30,7 +30,7 @@ export declare const SCENE_VOLUMETRIC_LIGHTING_SPECS: {
|
|
|
30
30
|
readonly digits: 2;
|
|
31
31
|
};
|
|
32
32
|
};
|
|
33
|
-
/**
|
|
33
|
+
/** How the haze looks once a light opts in; scenes with no volumetric light keep clear air. */
|
|
34
34
|
export declare function defaultSceneVolumetricLighting(): SceneVolumetricLighting;
|
|
35
35
|
/** Restore saved haze settings and clamp them to the shared editor bounds. */
|
|
36
36
|
export declare function healSceneVolumetricLighting(raw: unknown): SceneVolumetricLighting;
|
|
@@ -8,11 +8,10 @@ export const SCENE_VOLUMETRIC_LIGHTING_SPECS = {
|
|
|
8
8
|
range: { default: 20, min: 1, max: 100, step: 1, digits: 0 },
|
|
9
9
|
speed: { default: 0.2, min: 0, max: 5, step: 0.05, digits: 2 },
|
|
10
10
|
};
|
|
11
|
-
/**
|
|
11
|
+
/** How the haze looks once a light opts in; scenes with no volumetric light keep clear air. */
|
|
12
12
|
export function defaultSceneVolumetricLighting() {
|
|
13
13
|
const specs = SCENE_VOLUMETRIC_LIGHTING_SPECS;
|
|
14
14
|
return {
|
|
15
|
-
enabled: false,
|
|
16
15
|
density: specs.density.default,
|
|
17
16
|
intensity: specs.intensity.default,
|
|
18
17
|
range: specs.range.default,
|
|
@@ -27,7 +26,6 @@ export function healSceneVolumetricLighting(raw) {
|
|
|
27
26
|
return d;
|
|
28
27
|
const specs = SCENE_VOLUMETRIC_LIGHTING_SPECS;
|
|
29
28
|
return {
|
|
30
|
-
enabled: typeof raw.enabled === 'boolean' ? raw.enabled : d.enabled,
|
|
31
29
|
density: clamp(finiteOr(raw.density, d.density), specs.density.min, specs.density.max),
|
|
32
30
|
intensity: clamp(finiteOr(raw.intensity, d.intensity), specs.intensity.min, specs.intensity.max),
|
|
33
31
|
range: clamp(finiteOr(raw.range, d.range), specs.range.min, specs.range.max),
|
package/dist/wire/methods.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { ControllerMovementConfig, ControllerState } from '../values/contro
|
|
|
3
3
|
import type { LipSyncCalibrationCommand, LipSyncConfig, LipSyncMode, LipSyncState } from '../values/lipsync.ts';
|
|
4
4
|
import type { SceneInspection } from '../values/stage-info.ts';
|
|
5
5
|
import type { EventName } from './events.ts';
|
|
6
|
-
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, ScenePatch, SceneState, ScreenPlacement, Settings, SettingsPatch, TrackingSourceConfig, TrackingSourceId, TrackingSourceKind, TrackingStatus, VrmPlacement } from './types.ts';
|
|
6
|
+
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
7
|
/** Marker for methods that take no parameters; the client lets you omit the argument. */
|
|
8
8
|
export type EmptyRequest = Record<never, never>;
|
|
9
9
|
/** Marker for methods whose success response carries no data. */
|
|
@@ -40,6 +40,17 @@ export type ScenePatchRequest = ScenePatch;
|
|
|
40
40
|
export interface ScenePatchResponse {
|
|
41
41
|
scene: Scene;
|
|
42
42
|
}
|
|
43
|
+
/** Rebase one active-scene light against the displayed camera without moving or re-aiming it. */
|
|
44
|
+
export interface SceneSetLightFollowCameraRequest {
|
|
45
|
+
lightId: string;
|
|
46
|
+
followCamera: boolean;
|
|
47
|
+
/** Merges independent follow choices while preserving the light's displayed pose. */
|
|
48
|
+
options?: Partial<SceneLightCameraFollowOptions>;
|
|
49
|
+
}
|
|
50
|
+
export interface SceneSetLightFollowCameraResponse {
|
|
51
|
+
/** The rebased light, or null if it no longer exists in the active scene. */
|
|
52
|
+
light: SceneLight | null;
|
|
53
|
+
}
|
|
43
54
|
export type InstanceListRequest = EmptyRequest;
|
|
44
55
|
export interface InstanceListResponse {
|
|
45
56
|
instances: InstanceRuntime[];
|
|
@@ -667,6 +678,10 @@ export interface MethodMap {
|
|
|
667
678
|
request: ScenePatchRequest;
|
|
668
679
|
response: ScenePatchResponse;
|
|
669
680
|
};
|
|
681
|
+
'scene.setLightFollowCamera': {
|
|
682
|
+
request: SceneSetLightFollowCameraRequest;
|
|
683
|
+
response: SceneSetLightFollowCameraResponse;
|
|
684
|
+
};
|
|
670
685
|
'instance.list': {
|
|
671
686
|
request: InstanceListRequest;
|
|
672
687
|
response: InstanceListResponse;
|
|
@@ -113,6 +113,15 @@ export declare const requestSchemas: {
|
|
|
113
113
|
'scene.delete': z.ZodObject<{
|
|
114
114
|
sceneId: z.ZodString;
|
|
115
115
|
}, z.core.$strip>;
|
|
116
|
+
'scene.setLightFollowCamera': z.ZodObject<{
|
|
117
|
+
lightId: z.ZodString;
|
|
118
|
+
followCamera: z.ZodBoolean;
|
|
119
|
+
options: z.ZodOptional<z.ZodObject<{
|
|
120
|
+
position: z.ZodOptional<z.ZodBoolean>;
|
|
121
|
+
rotation: z.ZodOptional<z.ZodBoolean>;
|
|
122
|
+
distance: z.ZodOptional<z.ZodBoolean>;
|
|
123
|
+
}, z.core.$strip>>;
|
|
124
|
+
}, z.core.$strip>;
|
|
116
125
|
'instance.add': z.ZodObject<{
|
|
117
126
|
modelId: z.ZodString;
|
|
118
127
|
}, z.core.$strip>;
|
|
@@ -78,6 +78,11 @@ export const requestSchemas = {
|
|
|
78
78
|
'scene.duplicate': z.object({ sceneId: nonEmpty }),
|
|
79
79
|
'scene.rename': z.object({ sceneId: nonEmpty, name: nonEmpty }),
|
|
80
80
|
'scene.delete': z.object({ sceneId: nonEmpty }),
|
|
81
|
+
'scene.setLightFollowCamera': z.object({
|
|
82
|
+
lightId: nonEmpty,
|
|
83
|
+
followCamera: z.boolean(),
|
|
84
|
+
options: z.object({ position: z.boolean(), rotation: z.boolean(), distance: z.boolean() }).partial().optional(),
|
|
85
|
+
}),
|
|
81
86
|
'instance.add': z.object({ modelId: nonEmpty }),
|
|
82
87
|
'instance.setModel': z.object({ instanceId: nonEmpty, modelId: nonEmpty }),
|
|
83
88
|
'object.add': z.object({
|
package/dist/wire/types.d.ts
CHANGED
|
@@ -341,6 +341,25 @@ export declare const SHADOW_QUALITY_LEVELS: readonly ["off", "low", "medium", "h
|
|
|
341
341
|
export type ShadowQuality = (typeof SHADOW_QUALITY_LEVELS)[number];
|
|
342
342
|
export declare const SHADOW_FILTERS: readonly ["pcf", "pcss"];
|
|
343
343
|
export type ShadowFilter = (typeof SHADOW_FILTERS)[number];
|
|
344
|
+
/** Camera components followed by a light; omitted options default to all true. */
|
|
345
|
+
export interface SceneLightCameraFollowOptions {
|
|
346
|
+
/** Follow the camera's target/pan translation. */
|
|
347
|
+
position: boolean;
|
|
348
|
+
/** Follow the camera's world rotation, including roll. */
|
|
349
|
+
rotation: boolean;
|
|
350
|
+
/** Follow the signed orbit distance from target to camera. */
|
|
351
|
+
distance: boolean;
|
|
352
|
+
}
|
|
353
|
+
/** Frozen camera components used when the matching follow option is disabled. */
|
|
354
|
+
export interface SceneLightCameraFollowReference extends Pick<OrbitTransform, 'targetX' | 'targetY' | 'targetZ' | 'distance'> {
|
|
355
|
+
/** Unit quaternion in world space. */
|
|
356
|
+
rotation: {
|
|
357
|
+
x: number;
|
|
358
|
+
y: number;
|
|
359
|
+
z: number;
|
|
360
|
+
w: number;
|
|
361
|
+
};
|
|
362
|
+
}
|
|
344
363
|
/**
|
|
345
364
|
* One scene light. Angles are degrees. Directional lights aim with
|
|
346
365
|
* azimuth/elevation and sit at x/y/z (which moves their handle and shadow
|
|
@@ -354,6 +373,12 @@ export interface SceneLight {
|
|
|
354
373
|
type: SceneLightType;
|
|
355
374
|
/** Mutes illumination and shadows. Defaults to true; omitted by hosts without light toggles. */
|
|
356
375
|
enabled?: boolean;
|
|
376
|
+
/** Camera-relative placement and angles; defaults to false. Gate editing on `camera-follow-lights`; ambient ignores it. */
|
|
377
|
+
followCamera?: boolean;
|
|
378
|
+
/** Independent camera components; omitted means all true. */
|
|
379
|
+
followCameraOptions?: SceneLightCameraFollowOptions;
|
|
380
|
+
/** Missing references use target zero, identity rotation, and distance zero for disabled components. */
|
|
381
|
+
followCameraReference?: SceneLightCameraFollowReference;
|
|
357
382
|
color: string;
|
|
358
383
|
intensity: number;
|
|
359
384
|
azimuth: number;
|
|
@@ -371,6 +396,11 @@ export interface SceneLight {
|
|
|
371
396
|
height?: number;
|
|
372
397
|
/** Area light rotation in its rectangle's plane, in degrees; defaults to 0. */
|
|
373
398
|
roll?: number;
|
|
399
|
+
/**
|
|
400
|
+
* Light illuminated haze around this light; point, spot and area lights only.
|
|
401
|
+
* Defaults to false; omitted by hosts without per-light volumetric lighting.
|
|
402
|
+
*/
|
|
403
|
+
volumetric?: boolean;
|
|
374
404
|
/** Ambient and area lights never cast shadows. */
|
|
375
405
|
shadowQuality: ShadowQuality;
|
|
376
406
|
/** PCF disk radius in shadow-map texels; retained while PCSS is selected. */
|
|
@@ -387,9 +417,11 @@ export interface SceneFog {
|
|
|
387
417
|
/** Exponential-squared falloff; the useful band is well under 1 at avatar scale. */
|
|
388
418
|
density: number;
|
|
389
419
|
}
|
|
390
|
-
/**
|
|
420
|
+
/**
|
|
421
|
+
* How the illuminated haze looks in the 3D stage; rendered only by perspective
|
|
422
|
+
* cameras, and only while some scene light opts in through `SceneLight.volumetric`.
|
|
423
|
+
*/
|
|
391
424
|
export interface SceneVolumetricLighting {
|
|
392
|
-
enabled: boolean;
|
|
393
425
|
density: number;
|
|
394
426
|
intensity: number;
|
|
395
427
|
/** Distance from the camera in scene units. */
|
|
@@ -840,11 +872,8 @@ export interface EnvironmentLook {
|
|
|
840
872
|
color: SceneColorGrade;
|
|
841
873
|
}
|
|
842
874
|
/**
|
|
843
|
-
* The world the 3D stage sits in:
|
|
844
|
-
*
|
|
845
|
-
*
|
|
846
|
-
* The two asset ids are a single slot the editors write through
|
|
847
|
-
* {@link environmentWithAsset}: at most one is ever set.
|
|
875
|
+
* The world the 3D stage sits in: independent environment map and 3D set,
|
|
876
|
+
* scene-global fog, and post-processing.
|
|
848
877
|
*/
|
|
849
878
|
export interface SceneEnvironment {
|
|
850
879
|
/** Equirectangular `.hdr` or image driving the environment lighting, or null. */
|
|
@@ -856,14 +885,21 @@ export interface SceneEnvironment {
|
|
|
856
885
|
* has no IBL term of its own and the app adds one.
|
|
857
886
|
*/
|
|
858
887
|
iblAvatarAmount: number;
|
|
888
|
+
/** Show the selected map, falling back to the model's sky, independently of the lighting source. */
|
|
859
889
|
showSkybox: boolean;
|
|
890
|
+
/** Visible skybox blur, 0..1; defaults to 0. Omitted by older hosts. */
|
|
891
|
+
skyboxBlur?: number;
|
|
892
|
+
/** Visible skybox brightness, 0..2; defaults to 1. Omitted by older hosts. */
|
|
893
|
+
skyboxIntensity?: number;
|
|
894
|
+
/** Panorama and lighting yaw in radians; defaults to 0 and may wrap beyond one turn. Omitted by older hosts. */
|
|
895
|
+
iblRotation?: number;
|
|
860
896
|
/** A `prop` asset (glb/gltf) rendered as the set the scene sits in, or null. */
|
|
861
897
|
modelAssetId: string | null;
|
|
862
898
|
/** Where that set sits, in the same units as an object's `place3d`. */
|
|
863
899
|
modelPlace: Place3D;
|
|
864
900
|
/**
|
|
865
|
-
*
|
|
866
|
-
*
|
|
901
|
+
* Generate lighting from the set, using the selected map or the set's sky as input.
|
|
902
|
+
* False uses the map directly; the skybox remains independent of this choice.
|
|
867
903
|
*/
|
|
868
904
|
bakeFromModel: boolean;
|
|
869
905
|
/** Whether lights baked into the set render at all. */
|
|
@@ -881,6 +917,11 @@ export interface SceneEnvironment {
|
|
|
881
917
|
volumetricLighting?: SceneVolumetricLighting;
|
|
882
918
|
/** Optimize unshadowed point lights on supported renderers; omitted by older hosts. */
|
|
883
919
|
clusteredLighting?: boolean;
|
|
920
|
+
/**
|
|
921
|
+
* Simulate 3D objects as rigid bodies falling onto the stage floor; omitted by older hosts.
|
|
922
|
+
* The simulated pose is never saved — switching it off restores each object's placement.
|
|
923
|
+
*/
|
|
924
|
+
physics?: boolean;
|
|
884
925
|
effects: SceneEffects;
|
|
885
926
|
/**
|
|
886
927
|
* Built-in effects added as layers, in registry order — one keeps its row and tuning while
|
|
@@ -940,7 +981,7 @@ export interface ScenePatch {
|
|
|
940
981
|
* App-level features a client gates on (never version-sniff): `hello` and
|
|
941
982
|
* `app.info` report them — the per-app mirror of {@link InstanceRuntime.capabilities}.
|
|
942
983
|
*/
|
|
943
|
-
export declare const APP_CAPABILITIES: readonly ["storage", "speech", "automations", "controllers", "model-editing", "asset-inspection", "layer-effects", "scene-transitions", "area-lights", "spot-lights", "shadow-filters"];
|
|
984
|
+
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"];
|
|
944
985
|
export type AppCapability = (typeof APP_CAPABILITIES)[number];
|
|
945
986
|
export declare function isAppCapability(v: unknown): v is AppCapability;
|
|
946
987
|
/** What a loaded model instance can do; absent capabilities answer `unsupported-for-format`. */
|
package/dist/wire/types.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@laplace.live/persona-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"description": "TypeScript SDK and wire schema for the LAPLACE Persona plugin API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"node": ">=24"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"zod": "^4.6.
|
|
37
|
+
"zod": "^4.6.4"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"build": "rimraf dist && tsc -p tsconfig.build.json",
|