@laplace.live/persona-sdk 1.3.0 → 1.5.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/client/client.d.ts +1 -0
- package/dist/client/client.js +3 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/values/controller.d.ts +11 -11
- package/dist/values/controller.js +24 -44
- package/dist/values/curve.d.ts +4 -4
- package/dist/values/effect-schema.d.ts +4 -0
- package/dist/values/effect-schema.js +76 -30
- package/dist/values/guards.d.ts +12 -0
- package/dist/values/guards.js +16 -0
- package/dist/values/hands.d.ts +22 -22
- package/dist/values/hands.js +30 -58
- package/dist/values/hotkeys.d.ts +14 -0
- package/dist/values/hotkeys.js +13 -1
- package/dist/values/labels.d.ts +10 -5
- package/dist/values/labels.js +20 -9
- package/dist/values/lipsync.d.ts +2 -2
- package/dist/values/lipsync.js +2 -15
- package/dist/values/locale.d.ts +9 -4
- package/dist/values/locale.js +4 -3
- package/dist/values/scene-transition.d.ts +14 -0
- package/dist/values/scene-transition.js +36 -0
- package/dist/wire/errors.js +3 -2
- package/dist/wire/events.d.ts +4 -4
- package/dist/wire/events.js +3 -2
- package/dist/wire/methods.d.ts +13 -13
- package/dist/wire/protocol.d.ts +3 -1
- package/dist/wire/protocol.js +3 -1
- package/dist/wire/schemas.d.ts +18 -2
- package/dist/wire/schemas.js +17 -7
- package/dist/wire/types.d.ts +123 -22
- package/dist/wire/types.js +60 -66
- package/package.json +1 -1
package/dist/client/client.d.ts
CHANGED
|
@@ -47,6 +47,7 @@ export interface PersonaClientOptions {
|
|
|
47
47
|
reconnect?: boolean;
|
|
48
48
|
reconnectDelayMs?: number;
|
|
49
49
|
reconnectDelayMaxMs?: number;
|
|
50
|
+
/** Override every request timeout; defaults to 10 seconds, or 120 seconds for scene activation. */
|
|
50
51
|
requestTimeoutMs?: number;
|
|
51
52
|
/** Bound each awaited {@link PersonaClient.connect} — on expiry it rejects while the attempt keeps going. */
|
|
52
53
|
connectTimeoutMs?: number;
|
package/dist/client/client.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { parseServerMessage } from "../wire/envelope.js";
|
|
2
2
|
import { PersonaApiError } from "../wire/errors.js";
|
|
3
|
-
import { CLOSE_FORCE_DISCONNECTED, CLOSE_KEY_REVOKED, INJECT_HEARTBEAT_MS, injectTargetKey, PROTOCOL_VERSION, } from "../wire/protocol.js";
|
|
3
|
+
import { CLOSE_FORCE_DISCONNECTED, CLOSE_KEY_REVOKED, INJECT_HEARTBEAT_MS, injectTargetKey, PROTOCOL_VERSION, SCENE_ACTIVATION_TIMEOUT_MS, } from "../wire/protocol.js";
|
|
4
4
|
import { personaWsUrl } from "./address.js";
|
|
5
5
|
const DEFAULTS = {
|
|
6
6
|
url: personaWsUrl(),
|
|
@@ -107,7 +107,8 @@ export class PersonaClient {
|
|
|
107
107
|
const timer = setTimeout(() => {
|
|
108
108
|
this.pending.delete(id);
|
|
109
109
|
reject(new Error(`request timed out: ${method}`));
|
|
110
|
-
}, this.opts.requestTimeoutMs ??
|
|
110
|
+
}, this.opts.requestTimeoutMs ??
|
|
111
|
+
(method === 'scene.activate' ? SCENE_ACTIVATION_TIMEOUT_MS : DEFAULTS.requestTimeoutMs));
|
|
111
112
|
this.pending.set(id, { resolve: resolve, reject, timer });
|
|
112
113
|
ws.send(JSON.stringify({ kind: 'request', id, method, ...(params === undefined ? {} : { params }) }));
|
|
113
114
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export * from './values/limits.ts';
|
|
|
15
15
|
export * from './values/lipsync.ts';
|
|
16
16
|
export * from './values/locale.ts';
|
|
17
17
|
export * from './values/model-info.ts';
|
|
18
|
+
export * from './values/scene-transition.ts';
|
|
18
19
|
export * from './values/stage-info.ts';
|
|
19
20
|
export * from './values/terms.ts';
|
|
20
21
|
export * from './values/vrm-bindings.ts';
|
package/dist/index.js
CHANGED
|
@@ -17,6 +17,7 @@ export * from "./values/limits.js";
|
|
|
17
17
|
export * from "./values/lipsync.js";
|
|
18
18
|
export * from "./values/locale.js";
|
|
19
19
|
export * from "./values/model-info.js";
|
|
20
|
+
export * from "./values/scene-transition.js";
|
|
20
21
|
export * from "./values/stage-info.js";
|
|
21
22
|
export * from "./values/terms.js";
|
|
22
23
|
export * from "./values/vrm-bindings.js";
|
|
@@ -2,17 +2,6 @@
|
|
|
2
2
|
export type ControllerSlot = number;
|
|
3
3
|
/** Whether a value can identify a persistent controller profile. */
|
|
4
4
|
export declare function isControllerSlot(value: unknown): value is ControllerSlot;
|
|
5
|
-
/** Standard gamepad controls, using VTS's parameter names for the first controller. */
|
|
6
|
-
export declare const BASE_CONTROLLER_INPUT_NAMES: readonly ["ControllerStickLeftX", "ControllerStickLeftY", "ControllerStickRightX", "ControllerStickRightY", "ControllerStickPressLeft", "ControllerStickPressRight", "ControllerDPadX", "ControllerDPadY", "ControllerCross", "ControllerCircle", "ControllerSquare", "ControllerTriangle", "ControllerShoulderLeft", "ControllerShoulderRight", "ControllerTriggerLeft", "ControllerTriggerRight", "ControllerOptionLeft", "ControllerOptionRight", "ControllerHome"];
|
|
7
|
-
export type BaseControllerInputName = (typeof BASE_CONTROLLER_INPUT_NAMES)[number];
|
|
8
|
-
type NumberedControllerName<T extends string> = T extends `Controller${infer Control}` ? `Controller${number}${Control}` : never;
|
|
9
|
-
export type ControllerInputName = BaseControllerInputName | NumberedControllerName<BaseControllerInputName>;
|
|
10
|
-
/** Address a parameter on one controller; slot 1 retains its original VTS name. */
|
|
11
|
-
export declare function controllerInputName(base: BaseControllerInputName, slot: ControllerSlot): ControllerInputName;
|
|
12
|
-
/** Remove a controller parameter's slot prefix for shared labels and ranges. */
|
|
13
|
-
export declare function baseControllerInputName(full: ControllerInputName): BaseControllerInputName;
|
|
14
|
-
/** Whether an input names a supported controller parameter. */
|
|
15
|
-
export declare function isControllerInputName(v: string): v is ControllerInputName;
|
|
16
5
|
/** Stick and D-pad axes are signed, with positive Y pointing up; other controls are 0..1. */
|
|
17
6
|
export declare const BASE_CONTROLLER_INPUT_RANGES: {
|
|
18
7
|
readonly ControllerStickLeftX: readonly [-1, 1];
|
|
@@ -35,6 +24,17 @@ export declare const BASE_CONTROLLER_INPUT_RANGES: {
|
|
|
35
24
|
readonly ControllerOptionRight: readonly [0, 1];
|
|
36
25
|
readonly ControllerHome: readonly [0, 1];
|
|
37
26
|
};
|
|
27
|
+
/** Standard gamepad controls, using VTS's parameter names for the first controller. */
|
|
28
|
+
export declare const BASE_CONTROLLER_INPUT_NAMES: readonly BaseControllerInputName[];
|
|
29
|
+
export type BaseControllerInputName = keyof typeof BASE_CONTROLLER_INPUT_RANGES;
|
|
30
|
+
type NumberedControllerName<T extends string> = T extends `Controller${infer Control}` ? `Controller${number}${Control}` : never;
|
|
31
|
+
export type ControllerInputName = BaseControllerInputName | NumberedControllerName<BaseControllerInputName>;
|
|
32
|
+
/** Address a parameter on one controller; slot 1 retains its original VTS name. */
|
|
33
|
+
export declare function controllerInputName(base: BaseControllerInputName, slot: ControllerSlot): ControllerInputName;
|
|
34
|
+
/** Remove a controller parameter's slot prefix for shared labels and ranges. */
|
|
35
|
+
export declare function baseControllerInputName(full: ControllerInputName): BaseControllerInputName;
|
|
36
|
+
/** Whether an input names a supported controller parameter. */
|
|
37
|
+
export declare function isControllerInputName(v: string): v is ControllerInputName;
|
|
38
38
|
/** Natural parameter range, shared by every controller profile. */
|
|
39
39
|
export declare function controllerInputRange(name: ControllerInputName): readonly [number, number];
|
|
40
40
|
/** VTS shortcut names differ from parameter names, especially shoulders, clicks and D-pad. */
|
|
@@ -1,31 +1,33 @@
|
|
|
1
|
-
import { finiteOr, isRecord, nonEmptyString } from "./guards.js";
|
|
1
|
+
import { finiteOr, isRecord, keysOf, nonEmptyString } from "./guards.js";
|
|
2
2
|
import { clamp } from "./limits.js";
|
|
3
3
|
/** Whether a value can identify a persistent controller profile. */
|
|
4
4
|
export function isControllerSlot(value) {
|
|
5
5
|
return typeof value === 'number' && Number.isSafeInteger(value) && value > 0;
|
|
6
6
|
}
|
|
7
|
+
/** Stick and D-pad axes are signed, with positive Y pointing up; other controls are 0..1. */
|
|
8
|
+
export const BASE_CONTROLLER_INPUT_RANGES = {
|
|
9
|
+
ControllerStickLeftX: [-1, 1],
|
|
10
|
+
ControllerStickLeftY: [-1, 1],
|
|
11
|
+
ControllerStickRightX: [-1, 1],
|
|
12
|
+
ControllerStickRightY: [-1, 1],
|
|
13
|
+
ControllerStickPressLeft: [0, 1],
|
|
14
|
+
ControllerStickPressRight: [0, 1],
|
|
15
|
+
ControllerDPadX: [-1, 1],
|
|
16
|
+
ControllerDPadY: [-1, 1],
|
|
17
|
+
ControllerCross: [0, 1],
|
|
18
|
+
ControllerCircle: [0, 1],
|
|
19
|
+
ControllerSquare: [0, 1],
|
|
20
|
+
ControllerTriangle: [0, 1],
|
|
21
|
+
ControllerShoulderLeft: [0, 1],
|
|
22
|
+
ControllerShoulderRight: [0, 1],
|
|
23
|
+
ControllerTriggerLeft: [0, 1],
|
|
24
|
+
ControllerTriggerRight: [0, 1],
|
|
25
|
+
ControllerOptionLeft: [0, 1],
|
|
26
|
+
ControllerOptionRight: [0, 1],
|
|
27
|
+
ControllerHome: [0, 1],
|
|
28
|
+
};
|
|
7
29
|
/** Standard gamepad controls, using VTS's parameter names for the first controller. */
|
|
8
|
-
export const BASE_CONTROLLER_INPUT_NAMES =
|
|
9
|
-
'ControllerStickLeftX',
|
|
10
|
-
'ControllerStickLeftY',
|
|
11
|
-
'ControllerStickRightX',
|
|
12
|
-
'ControllerStickRightY',
|
|
13
|
-
'ControllerStickPressLeft',
|
|
14
|
-
'ControllerStickPressRight',
|
|
15
|
-
'ControllerDPadX',
|
|
16
|
-
'ControllerDPadY',
|
|
17
|
-
'ControllerCross',
|
|
18
|
-
'ControllerCircle',
|
|
19
|
-
'ControllerSquare',
|
|
20
|
-
'ControllerTriangle',
|
|
21
|
-
'ControllerShoulderLeft',
|
|
22
|
-
'ControllerShoulderRight',
|
|
23
|
-
'ControllerTriggerLeft',
|
|
24
|
-
'ControllerTriggerRight',
|
|
25
|
-
'ControllerOptionLeft',
|
|
26
|
-
'ControllerOptionRight',
|
|
27
|
-
'ControllerHome',
|
|
28
|
-
];
|
|
30
|
+
export const BASE_CONTROLLER_INPUT_NAMES = keysOf(BASE_CONTROLLER_INPUT_RANGES);
|
|
29
31
|
/** Slot 1 keeps the bare VTS name; every other slot inserts its number after `Controller`. */
|
|
30
32
|
function slotPrefixed(base, slot) {
|
|
31
33
|
if (!isControllerSlot(slot))
|
|
@@ -56,28 +58,6 @@ export function isControllerInputName(v) {
|
|
|
56
58
|
const parts = controllerParts(v);
|
|
57
59
|
return parts !== null && CONTROLLER_INPUT_SET.has(parts.base);
|
|
58
60
|
}
|
|
59
|
-
/** Stick and D-pad axes are signed, with positive Y pointing up; other controls are 0..1. */
|
|
60
|
-
export const BASE_CONTROLLER_INPUT_RANGES = {
|
|
61
|
-
ControllerStickLeftX: [-1, 1],
|
|
62
|
-
ControllerStickLeftY: [-1, 1],
|
|
63
|
-
ControllerStickRightX: [-1, 1],
|
|
64
|
-
ControllerStickRightY: [-1, 1],
|
|
65
|
-
ControllerStickPressLeft: [0, 1],
|
|
66
|
-
ControllerStickPressRight: [0, 1],
|
|
67
|
-
ControllerDPadX: [-1, 1],
|
|
68
|
-
ControllerDPadY: [-1, 1],
|
|
69
|
-
ControllerCross: [0, 1],
|
|
70
|
-
ControllerCircle: [0, 1],
|
|
71
|
-
ControllerSquare: [0, 1],
|
|
72
|
-
ControllerTriangle: [0, 1],
|
|
73
|
-
ControllerShoulderLeft: [0, 1],
|
|
74
|
-
ControllerShoulderRight: [0, 1],
|
|
75
|
-
ControllerTriggerLeft: [0, 1],
|
|
76
|
-
ControllerTriggerRight: [0, 1],
|
|
77
|
-
ControllerOptionLeft: [0, 1],
|
|
78
|
-
ControllerOptionRight: [0, 1],
|
|
79
|
-
ControllerHome: [0, 1],
|
|
80
|
-
};
|
|
81
61
|
/** Natural parameter range, shared by every controller profile. */
|
|
82
62
|
export function controllerInputRange(name) {
|
|
83
63
|
return BASE_CONTROLLER_INPUT_RANGES[baseControllerInputName(name)];
|
package/dist/values/curve.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* `outRange` is what puts it in Cubism units.
|
|
9
9
|
*/
|
|
10
10
|
/** Governs the segment *leaving* a keyframe; the last keyframe's is never read. */
|
|
11
|
-
export type Interpolation =
|
|
11
|
+
export type Interpolation = (typeof INTERPOLATIONS)[number];
|
|
12
12
|
export interface Point {
|
|
13
13
|
x: number;
|
|
14
14
|
y: number;
|
|
@@ -137,7 +137,7 @@ export declare function insertAnchor(keyframes: Keyframe[], at: Point): {
|
|
|
137
137
|
index: number;
|
|
138
138
|
};
|
|
139
139
|
/** Every {@link Interpolation}, in the order an editor lists them. */
|
|
140
|
-
export declare const INTERPOLATIONS: readonly
|
|
140
|
+
export declare const INTERPOLATIONS: readonly ["linear", "step", "invertStep", "bezier"];
|
|
141
141
|
/**
|
|
142
142
|
* A curve from an untrusted document — a config file or an IPC caller — or null when it
|
|
143
143
|
* cannot be made into one. Anchors are clamped into the unit square and sorted by x, which is
|
|
@@ -154,8 +154,8 @@ export declare function sanitizeCurve(v: unknown): Curve | null;
|
|
|
154
154
|
*/
|
|
155
155
|
export declare function identityCurve(): Curve;
|
|
156
156
|
/** A ready-made response shape that replaces the whole curve; `linear` is the identity. */
|
|
157
|
-
export type CurvePresetId =
|
|
158
|
-
export declare const CURVE_PRESET_IDS: readonly
|
|
157
|
+
export type CurvePresetId = (typeof CURVE_PRESET_IDS)[number];
|
|
158
|
+
export declare const CURVE_PRESET_IDS: readonly ["linear", "step", "invertStep", "bezier", "easeIn", "easeOut", "sCurve", "threshold", "steps"];
|
|
159
159
|
/**
|
|
160
160
|
* Fresh whole-curve shapes: endpoint holds, a Bezier ease-in-out, and shapes from VBridger's presets.
|
|
161
161
|
* The remaining shapes are transcribed from its Unity curves
|
|
@@ -6,6 +6,8 @@ export declare const EFFECT_SCOPES: {
|
|
|
6
6
|
readonly colorWheels: readonly ["scene", "layer"];
|
|
7
7
|
readonly colorShift: readonly ["scene", "layer"];
|
|
8
8
|
readonly selectColors: readonly ["scene", "layer"];
|
|
9
|
+
readonly gradient: readonly ["scene", "layer"];
|
|
10
|
+
readonly flare: readonly ["scene"];
|
|
9
11
|
readonly blur: readonly ["scene", "layer"];
|
|
10
12
|
readonly bloom: readonly ["scene", "layer"];
|
|
11
13
|
readonly diffusion: readonly ["scene", "layer"];
|
|
@@ -66,6 +68,8 @@ export declare const EFFECT_SPECS: Record<EffectKey, Readonly<Record<string, Eff
|
|
|
66
68
|
export declare const EFFECT_COLOR_SPECS: Partial<Record<EffectKey, Readonly<Record<string, EffectColorSpec>>>>;
|
|
67
69
|
/** Boolean defaults, validated alongside numeric and color parameters. */
|
|
68
70
|
export declare const EFFECT_BOOLEAN_SPECS: Partial<Record<EffectKey, Readonly<Record<string, EffectBooleanSpec>>>>;
|
|
71
|
+
/** Blend-mode order shared by effect editors and shader uniforms. */
|
|
72
|
+
export declare const EFFECT_BLEND_MODES: readonly ["normal", "darken", "multiply", "colorBurn", "linearBurn", "add", "lighten", "screen", "colorDodge", "overlay", "softLight", "hardLight", "vividLight", "linearLight", "pinLight", "hardMix", "difference", "exclusion", "subtract", "divide", "hue", "saturation", "color", "luminosity"];
|
|
69
73
|
/** Enum defaults and allowed values. */
|
|
70
74
|
export declare const EFFECT_ENUM_SPECS: Partial<Record<EffectKey, Readonly<Record<string, EffectEnumSpec>>>>;
|
|
71
75
|
/** Select the layer effects from any value set containing them. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Scope and parameter metadata are plain data; labels and rendering stay with their consumers.
|
|
2
|
-
import { finiteOr, isRecord } from "./guards.js";
|
|
2
|
+
import { finiteOr, isOneOf, isRecord } from "./guards.js";
|
|
3
3
|
import { clamp, hexColorOr } from "./limits.js";
|
|
4
4
|
/** Supported owners of each toggle effect; scene and layer membership are independent. */
|
|
5
5
|
export const EFFECT_SCOPES = {
|
|
@@ -8,6 +8,8 @@ export const EFFECT_SCOPES = {
|
|
|
8
8
|
colorWheels: ['scene', 'layer'],
|
|
9
9
|
colorShift: ['scene', 'layer'],
|
|
10
10
|
selectColors: ['scene', 'layer'],
|
|
11
|
+
gradient: ['scene', 'layer'],
|
|
12
|
+
flare: ['scene'],
|
|
11
13
|
blur: ['scene', 'layer'],
|
|
12
14
|
bloom: ['scene', 'layer'],
|
|
13
15
|
diffusion: ['scene', 'layer'],
|
|
@@ -26,7 +28,7 @@ export const EFFECT_SCOPES = {
|
|
|
26
28
|
};
|
|
27
29
|
export const EFFECT_KEYS = Object.keys(EFFECT_SCOPES);
|
|
28
30
|
function keysForScope(scope) {
|
|
29
|
-
return EFFECT_KEYS.filter((key) => EFFECT_SCOPES[key]
|
|
31
|
+
return EFFECT_KEYS.filter((key) => isOneOf(scope, EFFECT_SCOPES[key]));
|
|
30
32
|
}
|
|
31
33
|
/** Older hosts advertise effect availability through the values present in their payload. */
|
|
32
34
|
export function availableEffectKeys(scope, effects) {
|
|
@@ -122,6 +124,25 @@ export const EFFECT_SPECS = {
|
|
|
122
124
|
saturation: { default: -1, min: -1, max: 1, step: 0.01 },
|
|
123
125
|
blend: { default: 1, min: 0, max: 1, step: 0.01 },
|
|
124
126
|
},
|
|
127
|
+
gradient: {
|
|
128
|
+
radius: { default: 1, min: 0, max: 3, step: 0.01 },
|
|
129
|
+
smoothness: { default: 1, min: 0, max: 5, step: 0.01 },
|
|
130
|
+
centerX: { default: 0, min: -1, max: 1, step: 0.01 },
|
|
131
|
+
centerY: { default: 0, min: -1, max: 1, step: 0.01 },
|
|
132
|
+
angle: { default: 0, min: -180, max: 180, step: 1, unit: '°' },
|
|
133
|
+
scaleX: { default: 1, min: 0, max: 2, step: 0.01 },
|
|
134
|
+
scaleY: { default: 0.5, min: 0, max: 2, step: 0.01 },
|
|
135
|
+
opacity: { default: 1, min: 0, max: 1, step: 0.01 },
|
|
136
|
+
},
|
|
137
|
+
flare: {
|
|
138
|
+
intensity: { default: 0, min: 0, max: 1, step: 0.01 },
|
|
139
|
+
size: { default: 0, min: 0, max: 2, step: 0.01 },
|
|
140
|
+
angle: { default: 0, min: -180, max: 180, step: 1, unit: '°' },
|
|
141
|
+
glowOpacity: { default: 1, min: 0, max: 1, step: 0.01 },
|
|
142
|
+
raysScale: { default: 0, min: 0, max: 1, step: 0.01 },
|
|
143
|
+
raysIntensity: { default: 0, min: 0, max: 1, step: 0.01 },
|
|
144
|
+
raysOpacity: { default: 1, min: 0, max: 1, step: 0.01 },
|
|
145
|
+
},
|
|
125
146
|
blur: {
|
|
126
147
|
radius: { default: 8, min: 0, max: 64, step: 0.5, unit: 'px' },
|
|
127
148
|
},
|
|
@@ -240,6 +261,14 @@ export const EFFECT_SPECS = {
|
|
|
240
261
|
* string param appear.
|
|
241
262
|
*/
|
|
242
263
|
export const EFFECT_COLOR_SPECS = {
|
|
264
|
+
gradient: {
|
|
265
|
+
color: { default: '#ffffff' },
|
|
266
|
+
backgroundColor: { default: '#000000' },
|
|
267
|
+
},
|
|
268
|
+
flare: {
|
|
269
|
+
color: { default: '#ffffff' },
|
|
270
|
+
raysColor: { default: '#ffffff' },
|
|
271
|
+
},
|
|
243
272
|
colorWheels: {
|
|
244
273
|
liftColor: { default: '#ffffff' },
|
|
245
274
|
gammaColor: { default: '#ffffff' },
|
|
@@ -280,6 +309,11 @@ export const EFFECT_COLOR_SPECS = {
|
|
|
280
309
|
};
|
|
281
310
|
/** Boolean defaults, validated alongside numeric and color parameters. */
|
|
282
311
|
export const EFFECT_BOOLEAN_SPECS = {
|
|
312
|
+
flare: { rays: { default: false } },
|
|
313
|
+
gradient: {
|
|
314
|
+
invert: { default: false },
|
|
315
|
+
transparentBackground: { default: false },
|
|
316
|
+
},
|
|
283
317
|
blur: { highQuality: { default: false } },
|
|
284
318
|
bloom: {
|
|
285
319
|
selectColors: { default: false },
|
|
@@ -306,40 +340,50 @@ export const EFFECT_BOOLEAN_SPECS = {
|
|
|
306
340
|
color10Enabled: { default: false },
|
|
307
341
|
},
|
|
308
342
|
};
|
|
343
|
+
/** Blend-mode order shared by effect editors and shader uniforms. */
|
|
344
|
+
export const EFFECT_BLEND_MODES = [
|
|
345
|
+
'normal',
|
|
346
|
+
'darken',
|
|
347
|
+
'multiply',
|
|
348
|
+
'colorBurn',
|
|
349
|
+
'linearBurn',
|
|
350
|
+
'add',
|
|
351
|
+
'lighten',
|
|
352
|
+
'screen',
|
|
353
|
+
'colorDodge',
|
|
354
|
+
'overlay',
|
|
355
|
+
'softLight',
|
|
356
|
+
'hardLight',
|
|
357
|
+
'vividLight',
|
|
358
|
+
'linearLight',
|
|
359
|
+
'pinLight',
|
|
360
|
+
'hardMix',
|
|
361
|
+
'difference',
|
|
362
|
+
'exclusion',
|
|
363
|
+
'subtract',
|
|
364
|
+
'divide',
|
|
365
|
+
'hue',
|
|
366
|
+
'saturation',
|
|
367
|
+
'color',
|
|
368
|
+
'luminosity',
|
|
369
|
+
];
|
|
309
370
|
/** Enum defaults and allowed values. */
|
|
310
371
|
export const EFFECT_ENUM_SPECS = {
|
|
372
|
+
flare: {
|
|
373
|
+
mode: { default: 'add', values: ['add', 'screen', 'colorDodge'] },
|
|
374
|
+
raysMode: { default: 'sun', values: ['sun', 'shine', 'god'] },
|
|
375
|
+
},
|
|
376
|
+
gradient: {
|
|
377
|
+
type: { default: 'circle', values: ['solid', 'linear', 'circle', 'ellipse'] },
|
|
378
|
+
blendMode: { default: 'normal', values: EFFECT_BLEND_MODES },
|
|
379
|
+
},
|
|
311
380
|
blur: { mode: { default: 'gaussian', values: ['gaussian', 'bokeh'] } },
|
|
312
381
|
bloom: { mode: { default: 'normal', values: ['normal', 'streak', 'star'] } },
|
|
313
382
|
rim: {
|
|
314
383
|
mode: { default: 'single', values: ['single', 'double', 'sharpenSingle', 'sharpenDouble'] },
|
|
315
384
|
blendMode: {
|
|
316
385
|
default: 'overlay',
|
|
317
|
-
values:
|
|
318
|
-
'normal',
|
|
319
|
-
'darken',
|
|
320
|
-
'multiply',
|
|
321
|
-
'colorBurn',
|
|
322
|
-
'linearBurn',
|
|
323
|
-
'add',
|
|
324
|
-
'lighten',
|
|
325
|
-
'screen',
|
|
326
|
-
'colorDodge',
|
|
327
|
-
'overlay',
|
|
328
|
-
'softLight',
|
|
329
|
-
'hardLight',
|
|
330
|
-
'vividLight',
|
|
331
|
-
'linearLight',
|
|
332
|
-
'pinLight',
|
|
333
|
-
'hardMix',
|
|
334
|
-
'difference',
|
|
335
|
-
'exclusion',
|
|
336
|
-
'subtract',
|
|
337
|
-
'divide',
|
|
338
|
-
'hue',
|
|
339
|
-
'saturation',
|
|
340
|
-
'color',
|
|
341
|
-
'luminosity',
|
|
342
|
-
],
|
|
386
|
+
values: EFFECT_BLEND_MODES,
|
|
343
387
|
},
|
|
344
388
|
},
|
|
345
389
|
outline: { quality: { default: 'medium', values: ['low', 'medium', 'high'] } },
|
|
@@ -396,7 +440,9 @@ export const ALL_EFFECT_STACK_ORDER = [
|
|
|
396
440
|
'colorWheels',
|
|
397
441
|
'colorShift',
|
|
398
442
|
'selectColors',
|
|
443
|
+
'gradient',
|
|
399
444
|
'blur',
|
|
445
|
+
'flare',
|
|
400
446
|
'pixelate',
|
|
401
447
|
'glitch',
|
|
402
448
|
'droplets',
|
|
@@ -404,9 +450,9 @@ export const ALL_EFFECT_STACK_ORDER = [
|
|
|
404
450
|
'vignette',
|
|
405
451
|
];
|
|
406
452
|
/** Scene composition order, retained under its existing SDK name. */
|
|
407
|
-
export const EFFECT_STACK_ORDER = ALL_EFFECT_STACK_ORDER.filter((key) =>
|
|
453
|
+
export const EFFECT_STACK_ORDER = ALL_EFFECT_STACK_ORDER.filter((key) => isOneOf(key, SCENE_EFFECT_KEYS));
|
|
408
454
|
/** Layer composition order before the result joins the scene. */
|
|
409
|
-
export const LAYER_EFFECT_STACK_ORDER = ALL_EFFECT_STACK_ORDER.filter((key) =>
|
|
455
|
+
export const LAYER_EFFECT_STACK_ORDER = ALL_EFFECT_STACK_ORDER.filter((key) => isOneOf(key, LAYER_EFFECT_KEYS));
|
|
410
456
|
/** Heal only the requested effect keys, using the same parameter kinds as defaults and editors. */
|
|
411
457
|
export function healEffectValues(raw, keys) {
|
|
412
458
|
const src = isRecord(raw) ? raw : {};
|
package/dist/values/guards.d.ts
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
/** Plain-object check: object, non-null, and not an array. */
|
|
2
2
|
export declare function isRecord(v: unknown): v is Record<string, unknown>;
|
|
3
|
+
/**
|
|
4
|
+
* Membership test that narrows. `list.includes(v)` cannot take an `unknown`, and widening the
|
|
5
|
+
* list to `readonly string[]` to get there throws the narrowing away — so every caller ended up
|
|
6
|
+
* asserting the result back. Comparing element-wise keeps `T` in hand.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isOneOf<T extends string>(v: unknown, list: readonly T[]): v is T;
|
|
9
|
+
/**
|
|
10
|
+
* `Object.keys` typed to the record's own keys. TS widens to `string[]` because a value can
|
|
11
|
+
* carry keys its type never listed — true of an open object, not of the closed literal tables
|
|
12
|
+
* this is for, so callers own that the record is exactly its type.
|
|
13
|
+
*/
|
|
14
|
+
export declare function keysOf<T extends object>(o: T): (keyof T & string)[];
|
|
3
15
|
/** Finite-number type guard (rejects NaN and ±Infinity). */
|
|
4
16
|
export declare function isFiniteNumber(v: unknown): v is number;
|
|
5
17
|
/** The value when it is a finite number, else `fallback`. */
|
package/dist/values/guards.js
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
export function isRecord(v) {
|
|
4
4
|
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Membership test that narrows. `list.includes(v)` cannot take an `unknown`, and widening the
|
|
8
|
+
* list to `readonly string[]` to get there throws the narrowing away — so every caller ended up
|
|
9
|
+
* asserting the result back. Comparing element-wise keeps `T` in hand.
|
|
10
|
+
*/
|
|
11
|
+
export function isOneOf(v, list) {
|
|
12
|
+
return list.some(item => item === v);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* `Object.keys` typed to the record's own keys. TS widens to `string[]` because a value can
|
|
16
|
+
* carry keys its type never listed — true of an open object, not of the closed literal tables
|
|
17
|
+
* this is for, so callers own that the record is exactly its type.
|
|
18
|
+
*/
|
|
19
|
+
export function keysOf(o) {
|
|
20
|
+
return Object.keys(o);
|
|
21
|
+
}
|
|
6
22
|
/** Finite-number type guard (rejects NaN and ±Infinity). */
|
|
7
23
|
export function isFiniteNumber(v) {
|
|
8
24
|
return typeof v === 'number' && Number.isFinite(v);
|
package/dist/values/hands.d.ts
CHANGED
|
@@ -1,25 +1,3 @@
|
|
|
1
|
-
/** VTube Studio hand inputs, extended with nizima LIVE's wrist Y rotation. */
|
|
2
|
-
export declare const HAND_INPUT_NAMES: readonly ["HandLeftFound", "HandLeftPositionX", "HandLeftPositionY", "HandLeftPositionZ", "HandLeftAngleX", "HandLeftAngleY", "HandLeftAngleZ", "HandLeftOpen", "HandLeftFinger_1_Thumb", "HandLeftFinger_2_Index", "HandLeftFinger_3_Middle", "HandLeftFinger_4_Ring", "HandLeftFinger_5_Pinky", "HandRightFound", "HandRightPositionX", "HandRightPositionY", "HandRightPositionZ", "HandRightAngleX", "HandRightAngleY", "HandRightAngleZ", "HandRightOpen", "HandRightFinger_1_Thumb", "HandRightFinger_2_Index", "HandRightFinger_3_Middle", "HandRightFinger_4_Ring", "HandRightFinger_5_Pinky", "BothHandsFound", "HandDistance"];
|
|
3
|
-
export type HandInputName = (typeof HAND_INPUT_NAMES)[number];
|
|
4
|
-
export type HandInputs = Partial<Record<HandInputName, number>>;
|
|
5
|
-
/** Whether an input uses the canonical hand vocabulary. */
|
|
6
|
-
export declare function isHandInputName(input: string): input is HandInputName;
|
|
7
|
-
/** Names nizima uses for VTS's numbered fingers and both-hands detection. */
|
|
8
|
-
export declare const NIZIMA_HAND_ALIASES: {
|
|
9
|
-
readonly HandLeftFingerThumb: "HandLeftFinger_1_Thumb";
|
|
10
|
-
readonly HandLeftFingerIndex: "HandLeftFinger_2_Index";
|
|
11
|
-
readonly HandLeftFingerMiddle: "HandLeftFinger_3_Middle";
|
|
12
|
-
readonly HandLeftFingerRing: "HandLeftFinger_4_Ring";
|
|
13
|
-
readonly HandLeftFingerPinky: "HandLeftFinger_5_Pinky";
|
|
14
|
-
readonly HandRightFingerThumb: "HandRightFinger_1_Thumb";
|
|
15
|
-
readonly HandRightFingerIndex: "HandRightFinger_2_Index";
|
|
16
|
-
readonly HandRightFingerMiddle: "HandRightFinger_3_Middle";
|
|
17
|
-
readonly HandRightFingerRing: "HandRightFinger_4_Ring";
|
|
18
|
-
readonly HandRightFingerPinky: "HandRightFinger_5_Pinky";
|
|
19
|
-
readonly HandBothFound: "BothHandsFound";
|
|
20
|
-
};
|
|
21
|
-
/** Canonicalize a hand name; aliases share canonical units on the plugin API. */
|
|
22
|
-
export declare function canonicalHandInputName(input: string): HandInputName | null;
|
|
23
1
|
/** Angles are degrees; positions and distance use VTS's ten-unit scale. */
|
|
24
2
|
export declare const HAND_INPUT_RANGES: {
|
|
25
3
|
readonly HandLeftFound: readonly [0, 1];
|
|
@@ -51,3 +29,25 @@ export declare const HAND_INPUT_RANGES: {
|
|
|
51
29
|
readonly BothHandsFound: readonly [0, 1];
|
|
52
30
|
readonly HandDistance: readonly [0, 10];
|
|
53
31
|
};
|
|
32
|
+
/** VTube Studio hand inputs, extended with nizima LIVE's wrist Y rotation. */
|
|
33
|
+
export declare const HAND_INPUT_NAMES: readonly HandInputName[];
|
|
34
|
+
export type HandInputName = keyof typeof HAND_INPUT_RANGES;
|
|
35
|
+
export type HandInputs = Partial<Record<HandInputName, number>>;
|
|
36
|
+
/** Whether an input uses the canonical hand vocabulary. */
|
|
37
|
+
export declare function isHandInputName(input: string): input is HandInputName;
|
|
38
|
+
/** Names nizima uses for VTS's numbered fingers and both-hands detection. */
|
|
39
|
+
export declare const NIZIMA_HAND_ALIASES: {
|
|
40
|
+
readonly HandLeftFingerThumb: "HandLeftFinger_1_Thumb";
|
|
41
|
+
readonly HandLeftFingerIndex: "HandLeftFinger_2_Index";
|
|
42
|
+
readonly HandLeftFingerMiddle: "HandLeftFinger_3_Middle";
|
|
43
|
+
readonly HandLeftFingerRing: "HandLeftFinger_4_Ring";
|
|
44
|
+
readonly HandLeftFingerPinky: "HandLeftFinger_5_Pinky";
|
|
45
|
+
readonly HandRightFingerThumb: "HandRightFinger_1_Thumb";
|
|
46
|
+
readonly HandRightFingerIndex: "HandRightFinger_2_Index";
|
|
47
|
+
readonly HandRightFingerMiddle: "HandRightFinger_3_Middle";
|
|
48
|
+
readonly HandRightFingerRing: "HandRightFinger_4_Ring";
|
|
49
|
+
readonly HandRightFingerPinky: "HandRightFinger_5_Pinky";
|
|
50
|
+
readonly HandBothFound: "BothHandsFound";
|
|
51
|
+
};
|
|
52
|
+
/** Canonicalize a hand name; aliases share canonical units on the plugin API. */
|
|
53
|
+
export declare function canonicalHandInputName(input: string): HandInputName | null;
|
package/dist/values/hands.js
CHANGED
|
@@ -1,61 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export const HAND_INPUT_NAMES = [
|
|
3
|
-
'HandLeftFound',
|
|
4
|
-
'HandLeftPositionX',
|
|
5
|
-
'HandLeftPositionY',
|
|
6
|
-
'HandLeftPositionZ',
|
|
7
|
-
'HandLeftAngleX',
|
|
8
|
-
'HandLeftAngleY',
|
|
9
|
-
'HandLeftAngleZ',
|
|
10
|
-
'HandLeftOpen',
|
|
11
|
-
'HandLeftFinger_1_Thumb',
|
|
12
|
-
'HandLeftFinger_2_Index',
|
|
13
|
-
'HandLeftFinger_3_Middle',
|
|
14
|
-
'HandLeftFinger_4_Ring',
|
|
15
|
-
'HandLeftFinger_5_Pinky',
|
|
16
|
-
'HandRightFound',
|
|
17
|
-
'HandRightPositionX',
|
|
18
|
-
'HandRightPositionY',
|
|
19
|
-
'HandRightPositionZ',
|
|
20
|
-
'HandRightAngleX',
|
|
21
|
-
'HandRightAngleY',
|
|
22
|
-
'HandRightAngleZ',
|
|
23
|
-
'HandRightOpen',
|
|
24
|
-
'HandRightFinger_1_Thumb',
|
|
25
|
-
'HandRightFinger_2_Index',
|
|
26
|
-
'HandRightFinger_3_Middle',
|
|
27
|
-
'HandRightFinger_4_Ring',
|
|
28
|
-
'HandRightFinger_5_Pinky',
|
|
29
|
-
'BothHandsFound',
|
|
30
|
-
'HandDistance',
|
|
31
|
-
];
|
|
32
|
-
const HAND_INPUT_SET = new Set(HAND_INPUT_NAMES);
|
|
33
|
-
/** Whether an input uses the canonical hand vocabulary. */
|
|
34
|
-
export function isHandInputName(input) {
|
|
35
|
-
return HAND_INPUT_SET.has(input);
|
|
36
|
-
}
|
|
37
|
-
/** Names nizima uses for VTS's numbered fingers and both-hands detection. */
|
|
38
|
-
export const NIZIMA_HAND_ALIASES = {
|
|
39
|
-
HandLeftFingerThumb: 'HandLeftFinger_1_Thumb',
|
|
40
|
-
HandLeftFingerIndex: 'HandLeftFinger_2_Index',
|
|
41
|
-
HandLeftFingerMiddle: 'HandLeftFinger_3_Middle',
|
|
42
|
-
HandLeftFingerRing: 'HandLeftFinger_4_Ring',
|
|
43
|
-
HandLeftFingerPinky: 'HandLeftFinger_5_Pinky',
|
|
44
|
-
HandRightFingerThumb: 'HandRightFinger_1_Thumb',
|
|
45
|
-
HandRightFingerIndex: 'HandRightFinger_2_Index',
|
|
46
|
-
HandRightFingerMiddle: 'HandRightFinger_3_Middle',
|
|
47
|
-
HandRightFingerRing: 'HandRightFinger_4_Ring',
|
|
48
|
-
HandRightFingerPinky: 'HandRightFinger_5_Pinky',
|
|
49
|
-
HandBothFound: 'BothHandsFound',
|
|
50
|
-
};
|
|
51
|
-
/** Canonicalize a hand name; aliases share canonical units on the plugin API. */
|
|
52
|
-
export function canonicalHandInputName(input) {
|
|
53
|
-
if (isHandInputName(input))
|
|
54
|
-
return input;
|
|
55
|
-
return Object.hasOwn(NIZIMA_HAND_ALIASES, input)
|
|
56
|
-
? NIZIMA_HAND_ALIASES[input]
|
|
57
|
-
: null;
|
|
58
|
-
}
|
|
1
|
+
import { keysOf } from "./guards.js";
|
|
59
2
|
/** Angles are degrees; positions and distance use VTS's ten-unit scale. */
|
|
60
3
|
export const HAND_INPUT_RANGES = {
|
|
61
4
|
HandLeftFound: [0, 1],
|
|
@@ -87,3 +30,32 @@ export const HAND_INPUT_RANGES = {
|
|
|
87
30
|
BothHandsFound: [0, 1],
|
|
88
31
|
HandDistance: [0, 10],
|
|
89
32
|
};
|
|
33
|
+
/** VTube Studio hand inputs, extended with nizima LIVE's wrist Y rotation. */
|
|
34
|
+
export const HAND_INPUT_NAMES = keysOf(HAND_INPUT_RANGES);
|
|
35
|
+
const HAND_INPUT_SET = new Set(HAND_INPUT_NAMES);
|
|
36
|
+
/** Whether an input uses the canonical hand vocabulary. */
|
|
37
|
+
export function isHandInputName(input) {
|
|
38
|
+
return HAND_INPUT_SET.has(input);
|
|
39
|
+
}
|
|
40
|
+
/** Names nizima uses for VTS's numbered fingers and both-hands detection. */
|
|
41
|
+
export const NIZIMA_HAND_ALIASES = {
|
|
42
|
+
HandLeftFingerThumb: 'HandLeftFinger_1_Thumb',
|
|
43
|
+
HandLeftFingerIndex: 'HandLeftFinger_2_Index',
|
|
44
|
+
HandLeftFingerMiddle: 'HandLeftFinger_3_Middle',
|
|
45
|
+
HandLeftFingerRing: 'HandLeftFinger_4_Ring',
|
|
46
|
+
HandLeftFingerPinky: 'HandLeftFinger_5_Pinky',
|
|
47
|
+
HandRightFingerThumb: 'HandRightFinger_1_Thumb',
|
|
48
|
+
HandRightFingerIndex: 'HandRightFinger_2_Index',
|
|
49
|
+
HandRightFingerMiddle: 'HandRightFinger_3_Middle',
|
|
50
|
+
HandRightFingerRing: 'HandRightFinger_4_Ring',
|
|
51
|
+
HandRightFingerPinky: 'HandRightFinger_5_Pinky',
|
|
52
|
+
HandBothFound: 'BothHandsFound',
|
|
53
|
+
};
|
|
54
|
+
/** Canonicalize a hand name; aliases share canonical units on the plugin API. */
|
|
55
|
+
export function canonicalHandInputName(input) {
|
|
56
|
+
if (isHandInputName(input))
|
|
57
|
+
return input;
|
|
58
|
+
return Object.hasOwn(NIZIMA_HAND_ALIASES, input)
|
|
59
|
+
? NIZIMA_HAND_ALIASES[input]
|
|
60
|
+
: null;
|
|
61
|
+
}
|
package/dist/values/hotkeys.d.ts
CHANGED
|
@@ -9,6 +9,20 @@ export declare function hasCommandModifier(accelerator: string | null): boolean;
|
|
|
9
9
|
export declare function canRunInBackground(accelerator: string | null): boolean;
|
|
10
10
|
/** True when a model hotkey is meant to fire while Persona sits in the background — what main registers on, and what the globe shows. */
|
|
11
11
|
export declare function hotkeyRunsInBackground(h: Hotkey): boolean;
|
|
12
|
+
/** Automations are enabled unless explicitly paused. */
|
|
13
|
+
export declare function automationEnabled(s: {
|
|
14
|
+
enabled?: boolean;
|
|
15
|
+
}): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* True when an automation claims its combo — what main registers with the OS and what the
|
|
18
|
+
* renderer binds controllers to. The two must agree or a combo fires nothing, or nothing owns it.
|
|
19
|
+
*/
|
|
20
|
+
export declare function automationBindable<T extends {
|
|
21
|
+
enabled?: boolean;
|
|
22
|
+
accelerator: string | null;
|
|
23
|
+
}>(s: T): s is T & {
|
|
24
|
+
accelerator: string;
|
|
25
|
+
};
|
|
12
26
|
/** Accelerators bound by more than one entry — the warning every shortcut list raises. */
|
|
13
27
|
export declare function duplicateAccelerators(bindings: readonly {
|
|
14
28
|
accelerator: string | null;
|
package/dist/values/hotkeys.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Hotkey rules every consumer must agree on: main decides OS registration by them, and a
|
|
2
2
|
// client reading `Hotkey.global` off the wire needs the same rule to know the flag can apply.
|
|
3
3
|
import { isControllerTriggerName } from "./controller.js";
|
|
4
|
+
import { isOneOf } from "./guards.js";
|
|
4
5
|
// Shift is deliberately absent: Shift+letter is how text is typed, and a global
|
|
5
6
|
// registration consumes the combo system-wide (VTS can allow it because it observes).
|
|
6
7
|
const COMMAND_MODIFIERS = ['Control', 'Alt', 'Super'];
|
|
@@ -8,7 +9,7 @@ const COMMAND_MODIFIERS = ['Control', 'Alt', 'Super'];
|
|
|
8
9
|
export function hasCommandModifier(accelerator) {
|
|
9
10
|
if (accelerator === null)
|
|
10
11
|
return false;
|
|
11
|
-
return accelerator.split('+').some(t =>
|
|
12
|
+
return accelerator.split('+').some(t => isOneOf(t, COMMAND_MODIFIERS));
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
14
15
|
* True when `global` can apply: a command-modifier combo registers with the OS, and a controller
|
|
@@ -24,6 +25,17 @@ export function canRunInBackground(accelerator) {
|
|
|
24
25
|
export function hotkeyRunsInBackground(h) {
|
|
25
26
|
return h.global && h.active && h.action !== null && canRunInBackground(h.accelerator);
|
|
26
27
|
}
|
|
28
|
+
/** Automations are enabled unless explicitly paused. */
|
|
29
|
+
export function automationEnabled(s) {
|
|
30
|
+
return s.enabled !== false;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* True when an automation claims its combo — what main registers with the OS and what the
|
|
34
|
+
* renderer binds controllers to. The two must agree or a combo fires nothing, or nothing owns it.
|
|
35
|
+
*/
|
|
36
|
+
export function automationBindable(s) {
|
|
37
|
+
return automationEnabled(s) && s.accelerator !== null;
|
|
38
|
+
}
|
|
27
39
|
/** Accelerators bound by more than one entry — the warning every shortcut list raises. */
|
|
28
40
|
export function duplicateAccelerators(bindings) {
|
|
29
41
|
const seen = new Set();
|