@playcanvas/splat-transform 3.3.1 → 3.3.2

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/cli.mjs CHANGED
@@ -71623,11 +71623,11 @@ class CompressedChunk {
71623
71623
  /**
71624
71624
  * The splat-transform version (semver MAJOR.MINOR.PATCH).
71625
71625
  */
71626
- const version = '3.3.1';
71626
+ const version = '3.3.2';
71627
71627
  /**
71628
71628
  * The splat-transform revision (short Git hash of HEAD at build time).
71629
71629
  */
71630
- const revision = '8d49f07';
71630
+ const revision = '4248313';
71631
71631
 
71632
71632
  const generatedByString = `Generated by splat-transform ${version}`;
71633
71633
  const chunkProps = [
package/dist/index.cjs CHANGED
@@ -25683,11 +25683,11 @@ class CompressedChunk {
25683
25683
  /**
25684
25684
  * The splat-transform version (semver MAJOR.MINOR.PATCH).
25685
25685
  */
25686
- const version = '3.3.1';
25686
+ const version = '3.3.2';
25687
25687
  /**
25688
25688
  * The splat-transform revision (short Git hash of HEAD at build time).
25689
25689
  */
25690
- const revision = '8d49f07';
25690
+ const revision = '4248313';
25691
25691
 
25692
25692
  const generatedByString = `Generated by splat-transform ${version}`;
25693
25693
  const chunkProps = [
package/dist/index.mjs CHANGED
@@ -25680,11 +25680,11 @@ class CompressedChunk {
25680
25680
  /**
25681
25681
  * The splat-transform version (semver MAJOR.MINOR.PATCH).
25682
25682
  */
25683
- const version = '3.3.1';
25683
+ const version = '3.3.2';
25684
25684
  /**
25685
25685
  * The splat-transform revision (short Git hash of HEAD at build time).
25686
25686
  */
25687
- const revision = '8d49f07';
25687
+ const revision = '4248313';
25688
25688
 
25689
25689
  const generatedByString = `Generated by splat-transform ${version}`;
25690
25690
  const chunkProps = [
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The viewer's settings api — types, shared defaults, validation and authoring ranges —
3
+ * re-exported from the vendored viewer. Producers building on this package author their
4
+ * experience settings against the exact viewer version embedded in html exports, without
5
+ * needing a viewer dependency of their own.
6
+ */
7
+ export * from '@playcanvas/supersplat-viewer/settings';
@@ -0,0 +1,212 @@
1
+ /** A camera animation track. Only the first track in a settings file is played. */
2
+ type AnimTrack = {
3
+ name: string;
4
+ duration: number;
5
+ frameRate: number;
6
+ loopMode: 'none' | 'repeat' | 'pingpong';
7
+ interpolation: 'step' | 'spline';
8
+ smoothness: number;
9
+ keyframes: {
10
+ times: number[];
11
+ values: {
12
+ position: number[];
13
+ target: number[];
14
+ fov: number[];
15
+ };
16
+ };
17
+ };
18
+ /** A camera position, look-at target and vertical field of view in degrees. */
19
+ type CameraPose = {
20
+ position: [number, number, number];
21
+ target: [number, number, number];
22
+ fov: number;
23
+ };
24
+ /** A camera. Only the first camera in a settings file is used. */
25
+ type Camera = {
26
+ initial: CameraPose;
27
+ };
28
+ /** A point of interest in the scene, with the camera framing used to view it. */
29
+ type Annotation = {
30
+ position: [number, number, number];
31
+ title: string;
32
+ text: string;
33
+ extras?: unknown;
34
+ camera: Camera;
35
+ };
36
+ /** Post-processing applied to the rendered image. Each effect is independently toggled. */
37
+ type PostEffectSettings = {
38
+ sharpness: {
39
+ enabled: boolean;
40
+ amount: number;
41
+ };
42
+ bloom: {
43
+ enabled: boolean;
44
+ intensity: number;
45
+ blurLevel: number;
46
+ };
47
+ grading: {
48
+ enabled: boolean;
49
+ brightness: number;
50
+ contrast: number;
51
+ saturation: number;
52
+ tint: [number, number, number];
53
+ };
54
+ vignette: {
55
+ enabled: boolean;
56
+ intensity: number;
57
+ inner: number;
58
+ outer: number;
59
+ curvature: number;
60
+ };
61
+ fringing: {
62
+ enabled: boolean;
63
+ intensity: number;
64
+ };
65
+ };
66
+ /**
67
+ * A published experience: what is in the scene and how it is presented.
68
+ *
69
+ * This is the wire format of `settings.json`. Read it with {@link importSettings}, which
70
+ * migrates older versions forward.
71
+ */
72
+ type ExperienceSettings = {
73
+ version: 2;
74
+ tonemapping: 'none' | 'linear' | 'filmic' | 'hejl' | 'aces' | 'aces2' | 'neutral';
75
+ highPrecisionRendering: boolean;
76
+ soundUrl?: string;
77
+ background: {
78
+ color: [number, number, number];
79
+ skyboxUrl?: string;
80
+ };
81
+ postEffectSettings: PostEffectSettings;
82
+ animTracks: AnimTrack[];
83
+ cameras: Camera[];
84
+ annotations: Annotation[];
85
+ startMode: 'default' | 'animTrack' | 'annotation';
86
+ };
87
+
88
+ /** An inclusive numeric bound. `step` is UI granularity, not a constraint. */
89
+ type NumericRange = {
90
+ readonly min: number;
91
+ readonly max: number;
92
+ readonly step: number;
93
+ };
94
+ /**
95
+ * Bounds for each post-processing parameter, taken from the PlayCanvas engine's documented
96
+ * ranges (`CameraFrame`, and `RenderPassBloom` for `blurLevel`).
97
+ */
98
+ type PostEffectRanges = {
99
+ readonly sharpness: {
100
+ readonly amount: NumericRange;
101
+ };
102
+ readonly bloom: {
103
+ readonly intensity: NumericRange;
104
+ readonly blurLevel: NumericRange;
105
+ };
106
+ readonly grading: {
107
+ readonly brightness: NumericRange;
108
+ readonly contrast: NumericRange;
109
+ readonly saturation: NumericRange;
110
+ };
111
+ readonly vignette: {
112
+ readonly intensity: NumericRange;
113
+ readonly inner: NumericRange;
114
+ readonly outer: NumericRange;
115
+ readonly curvature: NumericRange;
116
+ };
117
+ readonly fringing: {
118
+ readonly intensity: NumericRange;
119
+ };
120
+ };
121
+ /** Bounds for a camera's vertical field of view, in degrees. */
122
+ declare const CAMERA_FOV_RANGE: NumericRange;
123
+ /** Bounds for each post-processing parameter. */
124
+ declare const POST_EFFECT_RANGES: PostEffectRanges;
125
+ /** An inclusive bound with no UI step. */
126
+ type Bounds = {
127
+ readonly min: number;
128
+ readonly max: number;
129
+ };
130
+ /** Bounds and size limits for camera animation tracks. */
131
+ type AnimTrackLimits = {
132
+ readonly duration: Bounds;
133
+ readonly frameRate: Bounds;
134
+ readonly smoothness: Bounds;
135
+ readonly maxKeyframes: number;
136
+ readonly nameMax: number;
137
+ readonly maxTracks: number;
138
+ };
139
+ /** Size limits for annotations. */
140
+ type AnnotationLimits = {
141
+ readonly maxCount: number;
142
+ readonly titleMax: number;
143
+ readonly textMax: number;
144
+ };
145
+ /** Bounds and size limits for camera animation tracks. Intentionally tight for now. */
146
+ declare const ANIM_TRACK_LIMITS: AnimTrackLimits;
147
+ /** Size limits for annotations. Intentionally tight for now. */
148
+ declare const ANNOTATION_LIMITS: AnnotationLimits;
149
+ /**
150
+ * Test a field of view against {@link CAMERA_FOV_RANGE}.
151
+ *
152
+ * @param fov - Vertical field of view in degrees.
153
+ * @returns Whether the value is within the authoring bounds.
154
+ */
155
+ declare const isCameraFovInRange: (fov: number) => boolean;
156
+
157
+ /** Default page and scene background, as normalized 0..1 rgb components. */
158
+ declare const DEFAULT_BACKGROUND_COLOR: readonly [number, number, number];
159
+ /** Default tonemapping curve. */
160
+ declare const DEFAULT_TONEMAPPING: ExperienceSettings['tonemapping'];
161
+ /** Default vertical field of view, in degrees. */
162
+ declare const DEFAULT_CAMERA_FOV: number;
163
+ /**
164
+ * How the default camera is placed: `environment` frames a captured space from inside it,
165
+ * `object` frames a subject from outside.
166
+ */
167
+ type CameraFit = 'environment' | 'object';
168
+ /**
169
+ * Default post-processing settings, with every effect disabled.
170
+ *
171
+ * @returns A fresh object; callers may mutate it freely.
172
+ */
173
+ declare const defaultPostEffectSettings: () => PostEffectSettings;
174
+ /**
175
+ * Default experience settings, shared by every tool that writes a settings file.
176
+ *
177
+ * @param fit - How to place the default camera. Defaults to `environment`.
178
+ * @returns A fresh object; callers may mutate it freely.
179
+ */
180
+ declare const defaultSettings: (fit?: CameraFit) => ExperienceSettings;
181
+
182
+ /**
183
+ * Migrate settings of any supported version to the latest schema.
184
+ *
185
+ * Assumes valid input — call {@link validateSettings} first if the source is untrusted. Does
186
+ * not mutate the object passed in.
187
+ *
188
+ * @param settings - Parsed contents of a settings file.
189
+ * @returns The settings at the latest version.
190
+ * @throws If the version is not supported.
191
+ */
192
+ declare const importSettings: (settings: unknown) => ExperienceSettings;
193
+ /** Options for {@link validateSettings}. */
194
+ type ValidateOptions = {
195
+ /**
196
+ * Also check the exported authoring bounds. Off by default: those bounds are stricter
197
+ * than what the viewer will render, and some settings in the wild fail them. Producers
198
+ * writing new settings should turn this on.
199
+ */
200
+ limits?: boolean;
201
+ };
202
+ /**
203
+ * Validate unknown data against any supported settings schema version.
204
+ *
205
+ * @param settings - Data to validate.
206
+ * @param options - See {@link ValidateOptions}.
207
+ * @throws If the data is not valid settings, with a message naming the offending field.
208
+ */
209
+ declare const validateSettings: (settings: unknown, options?: ValidateOptions) => void;
210
+
211
+ export { ANIM_TRACK_LIMITS, ANNOTATION_LIMITS, CAMERA_FOV_RANGE, DEFAULT_BACKGROUND_COLOR, DEFAULT_CAMERA_FOV, DEFAULT_TONEMAPPING, POST_EFFECT_RANGES, defaultPostEffectSettings, defaultSettings, importSettings, isCameraFovInRange, validateSettings };
212
+ export type { AnimTrack, AnimTrackLimits, Annotation, AnnotationLimits, Bounds, Camera, CameraFit, CameraPose, ExperienceSettings, NumericRange, PostEffectRanges, PostEffectSettings, ValidateOptions };
@@ -0,0 +1,601 @@
1
+ // The single source of default experience settings, so every tool that writes a settings file
2
+ // agrees. Several independent copies of these values had drifted apart; these are the ones
3
+ // matching the settings already published in the wild, which means some producers change:
4
+ // `tonemapping` is 'linear' rather than 'none', `background.color` is black rather than 0.4
5
+ // grey, `bloom.intensity` is 0.1 rather than 1 (1 falls outside the authoring range in
6
+ // ranges.ts) and `grading.brightness` is 1 rather than 0.
7
+ // Frozen: `defaultSettings()` copies this, so a consumer mutating it would otherwise change
8
+ // every later call's result.
9
+ /** Default page and scene background, as normalized 0..1 rgb components. */
10
+ const DEFAULT_BACKGROUND_COLOR = Object.freeze([0, 0, 0]);
11
+ /** Default tonemapping curve. */
12
+ const DEFAULT_TONEMAPPING = 'linear';
13
+ /** Default vertical field of view, in degrees. */
14
+ // Annotated so the published declaration widens to `number`; without it the emitted type is
15
+ // the literal `75`, which bakes the value into the api.
16
+ // eslint-disable-next-line @typescript-eslint/no-inferrable-types
17
+ const DEFAULT_CAMERA_FOV = 85;
18
+ const defaultCameraPose = (fit = 'environment') => {
19
+ return fit === 'environment'
20
+ ? { position: [0, 2, 0], target: [2, 2, 0], fov: DEFAULT_CAMERA_FOV }
21
+ : { position: [2, 2, -2], target: [0, 0, 0], fov: DEFAULT_CAMERA_FOV };
22
+ };
23
+ /**
24
+ * Default post-processing settings, with every effect disabled.
25
+ *
26
+ * @returns A fresh object; callers may mutate it freely.
27
+ */
28
+ const defaultPostEffectSettings = () => ({
29
+ sharpness: {
30
+ enabled: false,
31
+ amount: 0
32
+ },
33
+ bloom: {
34
+ enabled: false,
35
+ intensity: 0.1,
36
+ blurLevel: 2
37
+ },
38
+ grading: {
39
+ enabled: false,
40
+ brightness: 1,
41
+ contrast: 1,
42
+ saturation: 1,
43
+ tint: [1, 1, 1]
44
+ },
45
+ vignette: {
46
+ enabled: false,
47
+ intensity: 0.5,
48
+ inner: 0.3,
49
+ outer: 0.75,
50
+ curvature: 1
51
+ },
52
+ fringing: {
53
+ enabled: false,
54
+ intensity: 0.5
55
+ }
56
+ });
57
+ /**
58
+ * Default experience settings, shared by every tool that writes a settings file.
59
+ *
60
+ * @param fit - How to place the default camera. Defaults to `environment`.
61
+ * @returns A fresh object; callers may mutate it freely.
62
+ */
63
+ const defaultSettings = (fit = 'environment') => ({
64
+ version: 2,
65
+ tonemapping: DEFAULT_TONEMAPPING,
66
+ highPrecisionRendering: false,
67
+ background: {
68
+ color: [...DEFAULT_BACKGROUND_COLOR]
69
+ },
70
+ postEffectSettings: defaultPostEffectSettings(),
71
+ animTracks: [],
72
+ cameras: [{ initial: defaultCameraPose(fit) }],
73
+ annotations: [],
74
+ startMode: 'default'
75
+ });
76
+
77
+ const assertObject = (value, path) => {
78
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
79
+ throw new Error(`${path} must be an object`);
80
+ }
81
+ return value;
82
+ };
83
+ const assertNumber = (value, path) => {
84
+ if (typeof value !== 'number' || !isFinite(value)) {
85
+ throw new Error(`${path} must be a finite number`);
86
+ }
87
+ return value;
88
+ };
89
+ const assertString = (value, path) => {
90
+ if (typeof value !== 'string') {
91
+ throw new Error(`${path} must be a string`);
92
+ }
93
+ return value;
94
+ };
95
+ const assertBoolean = (value, path) => {
96
+ if (typeof value !== 'boolean') {
97
+ throw new Error(`${path} must be a boolean`);
98
+ }
99
+ return value;
100
+ };
101
+ const assertEnum = (value, allowed, path) => {
102
+ if (typeof value !== 'string' || !allowed.includes(value)) {
103
+ throw new Error(`${path} must be one of: ${allowed.join(', ')}`);
104
+ }
105
+ return value;
106
+ };
107
+ const assertArray = (value, path) => {
108
+ if (!Array.isArray(value)) {
109
+ throw new Error(`${path} must be an array`);
110
+ }
111
+ return value;
112
+ };
113
+ const assertNumberArray = (value, path) => {
114
+ const arr = assertArray(value, path);
115
+ for (let i = 0; i < arr.length; i++) {
116
+ assertNumber(arr[i], `${path}[${i}]`);
117
+ }
118
+ return arr;
119
+ };
120
+ const assertTuple3 = (value, path) => {
121
+ const arr = assertNumberArray(value, path);
122
+ if (arr.length !== 3) {
123
+ throw new Error(`${path} must have exactly 3 elements`);
124
+ }
125
+ return arr;
126
+ };
127
+
128
+ const validateAnimTrack$1 = (data, path) => {
129
+ const obj = assertObject(data, path);
130
+ assertString(obj.name, `${path}.name`);
131
+ assertNumber(obj.duration, `${path}.duration`);
132
+ if (obj.frameRate !== undefined)
133
+ assertNumber(obj.frameRate, `${path}.frameRate`);
134
+ assertEnum(obj.target, ['camera'], `${path}.target`);
135
+ assertEnum(obj.loopMode, ['none', 'repeat', 'pingpong'], `${path}.loopMode`);
136
+ assertEnum(obj.interpolation, ['step', 'spline'], `${path}.interpolation`);
137
+ if (obj.smoothness !== undefined)
138
+ assertNumber(obj.smoothness, `${path}.smoothness`);
139
+ const kf = assertObject(obj.keyframes, `${path}.keyframes`);
140
+ assertNumberArray(kf.times, `${path}.keyframes.times`);
141
+ const vals = assertObject(kf.values, `${path}.keyframes.values`);
142
+ assertNumberArray(vals.position, `${path}.keyframes.values.position`);
143
+ assertNumberArray(vals.target, `${path}.keyframes.values.target`);
144
+ return data;
145
+ };
146
+ const validateV1 = (data) => {
147
+ const obj = assertObject(data, 'settings');
148
+ const camera = assertObject(obj.camera, 'settings.camera');
149
+ if (camera.fov !== undefined)
150
+ assertNumber(camera.fov, 'settings.camera.fov');
151
+ // Exactly 3 elements: migration casts these straight into v2 tuples, so any other arity
152
+ // would validate here yet produce output that fails v2 validation.
153
+ if (camera.position !== undefined)
154
+ assertTuple3(camera.position, 'settings.camera.position');
155
+ if (camera.target !== undefined)
156
+ assertTuple3(camera.target, 'settings.camera.target');
157
+ if (camera.startAnim !== undefined)
158
+ assertEnum(camera.startAnim, ['none', 'orbit', 'animTrack'], 'settings.camera.startAnim');
159
+ if (camera.animTrack != null)
160
+ assertString(camera.animTrack, 'settings.camera.animTrack');
161
+ const bg = assertObject(obj.background, 'settings.background');
162
+ if (bg.color !== undefined)
163
+ assertTuple3(bg.color, 'settings.background.color');
164
+ if (obj.animTracks !== undefined) {
165
+ const tracks = assertArray(obj.animTracks, 'settings.animTracks');
166
+ tracks.forEach((t, i) => validateAnimTrack$1(t, `settings.animTracks[${i}]`));
167
+ }
168
+ return data;
169
+ };
170
+
171
+ const TONEMAPPING = ['none', 'linear', 'filmic', 'hejl', 'aces', 'aces2', 'neutral'];
172
+ const LOOP_MODES = ['none', 'repeat', 'pingpong'];
173
+ const INTERPOLATIONS = ['step', 'spline'];
174
+ const START_MODES = ['default', 'animTrack', 'annotation'];
175
+ const validateAnimTrack = (data, path) => {
176
+ const obj = assertObject(data, path);
177
+ assertString(obj.name, `${path}.name`);
178
+ assertNumber(obj.duration, `${path}.duration`);
179
+ assertNumber(obj.frameRate, `${path}.frameRate`);
180
+ assertEnum(obj.loopMode, LOOP_MODES, `${path}.loopMode`);
181
+ assertEnum(obj.interpolation, INTERPOLATIONS, `${path}.interpolation`);
182
+ assertNumber(obj.smoothness, `${path}.smoothness`);
183
+ const kf = assertObject(obj.keyframes, `${path}.keyframes`);
184
+ assertNumberArray(kf.times, `${path}.keyframes.times`);
185
+ const vals = assertObject(kf.values, `${path}.keyframes.values`);
186
+ assertNumberArray(vals.position, `${path}.keyframes.values.position`);
187
+ assertNumberArray(vals.target, `${path}.keyframes.values.target`);
188
+ assertNumberArray(vals.fov, `${path}.keyframes.values.fov`);
189
+ return data;
190
+ };
191
+ const validateCamera = (data, path) => {
192
+ const obj = assertObject(data, path);
193
+ const initial = assertObject(obj.initial, `${path}.initial`);
194
+ assertTuple3(initial.position, `${path}.initial.position`);
195
+ assertTuple3(initial.target, `${path}.initial.target`);
196
+ assertNumber(initial.fov, `${path}.initial.fov`);
197
+ return data;
198
+ };
199
+ const validateAnnotation = (data, path) => {
200
+ const obj = assertObject(data, path);
201
+ assertTuple3(obj.position, `${path}.position`);
202
+ assertString(obj.title, `${path}.title`);
203
+ assertString(obj.text, `${path}.text`);
204
+ validateCamera(obj.camera, `${path}.camera`);
205
+ return data;
206
+ };
207
+ const validatePostEffects = (data, path) => {
208
+ const obj = assertObject(data, path);
209
+ const sh = assertObject(obj.sharpness, `${path}.sharpness`);
210
+ assertBoolean(sh.enabled, `${path}.sharpness.enabled`);
211
+ assertNumber(sh.amount, `${path}.sharpness.amount`);
212
+ const bl = assertObject(obj.bloom, `${path}.bloom`);
213
+ assertBoolean(bl.enabled, `${path}.bloom.enabled`);
214
+ assertNumber(bl.intensity, `${path}.bloom.intensity`);
215
+ assertNumber(bl.blurLevel, `${path}.bloom.blurLevel`);
216
+ const gr = assertObject(obj.grading, `${path}.grading`);
217
+ assertBoolean(gr.enabled, `${path}.grading.enabled`);
218
+ assertNumber(gr.brightness, `${path}.grading.brightness`);
219
+ assertNumber(gr.contrast, `${path}.grading.contrast`);
220
+ assertNumber(gr.saturation, `${path}.grading.saturation`);
221
+ assertTuple3(gr.tint, `${path}.grading.tint`);
222
+ const vi = assertObject(obj.vignette, `${path}.vignette`);
223
+ assertBoolean(vi.enabled, `${path}.vignette.enabled`);
224
+ assertNumber(vi.intensity, `${path}.vignette.intensity`);
225
+ assertNumber(vi.inner, `${path}.vignette.inner`);
226
+ assertNumber(vi.outer, `${path}.vignette.outer`);
227
+ assertNumber(vi.curvature, `${path}.vignette.curvature`);
228
+ const fr = assertObject(obj.fringing, `${path}.fringing`);
229
+ assertBoolean(fr.enabled, `${path}.fringing.enabled`);
230
+ assertNumber(fr.intensity, `${path}.fringing.intensity`);
231
+ return data;
232
+ };
233
+ const validateV2 = (data) => {
234
+ const obj = assertObject(data, 'settings');
235
+ if (obj.version !== 2) {
236
+ throw new Error('settings.version must be 2');
237
+ }
238
+ assertEnum(obj.tonemapping, TONEMAPPING, 'settings.tonemapping');
239
+ assertBoolean(obj.highPrecisionRendering, 'settings.highPrecisionRendering');
240
+ if (obj.soundUrl !== undefined)
241
+ assertString(obj.soundUrl, 'settings.soundUrl');
242
+ const bg = assertObject(obj.background, 'settings.background');
243
+ assertTuple3(bg.color, 'settings.background.color');
244
+ if (bg.skyboxUrl !== undefined)
245
+ assertString(bg.skyboxUrl, 'settings.background.skyboxUrl');
246
+ validatePostEffects(obj.postEffectSettings, 'settings.postEffectSettings');
247
+ const tracks = assertArray(obj.animTracks, 'settings.animTracks');
248
+ tracks.forEach((t, i) => validateAnimTrack(t, `settings.animTracks[${i}]`));
249
+ const cameras = assertArray(obj.cameras, 'settings.cameras');
250
+ cameras.forEach((c, i) => validateCamera(c, `settings.cameras[${i}]`));
251
+ const annotations = assertArray(obj.annotations, 'settings.annotations');
252
+ annotations.forEach((a, i) => validateAnnotation(a, `settings.annotations[${i}]`));
253
+ assertEnum(obj.startMode, START_MODES, 'settings.startMode');
254
+ return data;
255
+ };
256
+
257
+ // Authoring bounds for experience settings, shared by the settings validators and by editor
258
+ // UIs that need slider ranges. Pure data with no imports, so a consumer can take these
259
+ // without pulling in the schema.
260
+ //
261
+ // These are *authoring* limits, not read limits: the viewer renders values outside them
262
+ // perfectly well, and settings in the wild contain some (see validate-limits.ts).
263
+ // `step` is UI granularity, not a constraint.
264
+ // These are published constants that the validators themselves read, so a consumer mutating
265
+ // one would silently change validation for everyone in the realm. Freeze rather than rely on
266
+ // `as const`, which is erased at runtime.
267
+ const deepFreeze = (value) => {
268
+ if (value !== null && typeof value === 'object') {
269
+ Object.values(value).forEach(deepFreeze);
270
+ Object.freeze(value);
271
+ }
272
+ return value;
273
+ };
274
+ /** Bounds for a camera's vertical field of view, in degrees. */
275
+ const CAMERA_FOV_RANGE = deepFreeze({
276
+ min: 10,
277
+ max: 120,
278
+ step: 1
279
+ });
280
+ /** Bounds for each post-processing parameter. */
281
+ const POST_EFFECT_RANGES = deepFreeze({
282
+ sharpness: {
283
+ amount: { min: 0, max: 1, step: 0.01 }
284
+ },
285
+ bloom: {
286
+ intensity: { min: 0, max: 0.1, step: 0.01 },
287
+ blurLevel: { min: 1, max: 16, step: 1 }
288
+ },
289
+ grading: {
290
+ brightness: { min: 0, max: 3, step: 0.01 },
291
+ contrast: { min: 0.5, max: 1.5, step: 0.01 },
292
+ saturation: { min: 0, max: 2, step: 0.01 }
293
+ },
294
+ vignette: {
295
+ intensity: { min: 0, max: 1, step: 0.01 },
296
+ inner: { min: 0, max: 3, step: 0.01 },
297
+ outer: { min: 0, max: 3, step: 0.01 },
298
+ curvature: { min: 0.01, max: 10, step: 0.01 }
299
+ },
300
+ fringing: {
301
+ intensity: { min: 0, max: 100, step: 1 }
302
+ }
303
+ });
304
+ // Annotated rather than `as const`: the annotation keeps them readonly while widening the
305
+ // values, so the published types do not bake in numbers we may want to relax later.
306
+ /** Bounds and size limits for camera animation tracks. Intentionally tight for now. */
307
+ const ANIM_TRACK_LIMITS = deepFreeze({
308
+ duration: { min: 0.1, max: 600 },
309
+ frameRate: { min: 1, max: 120 },
310
+ smoothness: { min: 0, max: 1 },
311
+ maxKeyframes: 1000,
312
+ nameMax: 120,
313
+ maxTracks: 10
314
+ });
315
+ /** Size limits for annotations. Intentionally tight for now. */
316
+ const ANNOTATION_LIMITS = deepFreeze({
317
+ maxCount: 25,
318
+ titleMax: 60,
319
+ textMax: 280
320
+ });
321
+ /**
322
+ * Test a field of view against {@link CAMERA_FOV_RANGE}.
323
+ *
324
+ * @param fov - Vertical field of view in degrees.
325
+ * @returns Whether the value is within the authoring bounds.
326
+ */
327
+ const isCameraFovInRange = (fov) => {
328
+ return fov >= CAMERA_FOV_RANGE.min && fov <= CAMERA_FOV_RANGE.max;
329
+ };
330
+
331
+ // Authoring-limit checks, deliberately separate from the shape validation in v2.ts.
332
+ //
333
+ // Shape validation answers "can the viewer read this" and must keep accepting every settings
334
+ // file ever written. These limits answer "is this sane input from an editor" and are stricter
335
+ // — strictly enough that some existing data fails them. `bloom.intensity` is the known case:
336
+ // the range caps it at 0.1, while several older default objects wrote 1. So this runs only on
337
+ // request, via `validateSettings(x, { limits: true })`, and never on the viewer's read path.
338
+ const range = (value, bounds, path) => {
339
+ if (value < bounds.min || value > bounds.max) {
340
+ throw new Error(`${path} must be between ${bounds.min} and ${bounds.max}, got ${value}`);
341
+ }
342
+ };
343
+ const maxLength = (value, max, path) => {
344
+ if (value.length > max) {
345
+ throw new Error(`${path} must be at most ${max} characters, got ${value.length}`);
346
+ }
347
+ };
348
+ const maxCount = (value, max, path) => {
349
+ if (value.length > max) {
350
+ throw new Error(`${path} must have at most ${max} entries, got ${value.length}`);
351
+ }
352
+ };
353
+ const validateLimitsV2 = (settings) => {
354
+ const fx = settings.postEffectSettings;
355
+ range(fx.sharpness.amount, POST_EFFECT_RANGES.sharpness.amount, 'settings.postEffectSettings.sharpness.amount');
356
+ range(fx.bloom.intensity, POST_EFFECT_RANGES.bloom.intensity, 'settings.postEffectSettings.bloom.intensity');
357
+ range(fx.bloom.blurLevel, POST_EFFECT_RANGES.bloom.blurLevel, 'settings.postEffectSettings.bloom.blurLevel');
358
+ range(fx.grading.brightness, POST_EFFECT_RANGES.grading.brightness, 'settings.postEffectSettings.grading.brightness');
359
+ range(fx.grading.contrast, POST_EFFECT_RANGES.grading.contrast, 'settings.postEffectSettings.grading.contrast');
360
+ range(fx.grading.saturation, POST_EFFECT_RANGES.grading.saturation, 'settings.postEffectSettings.grading.saturation');
361
+ range(fx.vignette.intensity, POST_EFFECT_RANGES.vignette.intensity, 'settings.postEffectSettings.vignette.intensity');
362
+ range(fx.vignette.inner, POST_EFFECT_RANGES.vignette.inner, 'settings.postEffectSettings.vignette.inner');
363
+ range(fx.vignette.outer, POST_EFFECT_RANGES.vignette.outer, 'settings.postEffectSettings.vignette.outer');
364
+ range(fx.vignette.curvature, POST_EFFECT_RANGES.vignette.curvature, 'settings.postEffectSettings.vignette.curvature');
365
+ range(fx.fringing.intensity, POST_EFFECT_RANGES.fringing.intensity, 'settings.postEffectSettings.fringing.intensity');
366
+ // no count limit on cameras — the viewer only reads cameras[0], but the format allows more
367
+ settings.cameras.forEach((camera, i) => {
368
+ range(camera.initial.fov, CAMERA_FOV_RANGE, `settings.cameras[${i}].initial.fov`);
369
+ });
370
+ maxCount(settings.animTracks, ANIM_TRACK_LIMITS.maxTracks, 'settings.animTracks');
371
+ settings.animTracks.forEach((track, i) => {
372
+ const path = `settings.animTracks[${i}]`;
373
+ maxLength(track.name, ANIM_TRACK_LIMITS.nameMax, `${path}.name`);
374
+ range(track.duration, ANIM_TRACK_LIMITS.duration, `${path}.duration`);
375
+ range(track.frameRate, ANIM_TRACK_LIMITS.frameRate, `${path}.frameRate`);
376
+ if (!Number.isInteger(track.frameRate)) {
377
+ throw new Error(`${path}.frameRate must be an integer, got ${track.frameRate}`);
378
+ }
379
+ range(track.smoothness, ANIM_TRACK_LIMITS.smoothness, `${path}.smoothness`);
380
+ // Keyframe times are frame numbers: non-negative integers, strictly ascending, since
381
+ // the spline is built from them in order.
382
+ const { times, values } = track.keyframes;
383
+ maxCount(times, ANIM_TRACK_LIMITS.maxKeyframes, `${path}.keyframes.times`);
384
+ // At least one: `CubicSpline.calcKnots` derives its dimension as
385
+ // `points.length / times.length`, so an empty track computes 0/0 and allocates
386
+ // `new Array(NaN)`, which throws. A track the viewer cannot load is not valid input.
387
+ if (times.length === 0) {
388
+ throw new Error(`${path}.keyframes.times must have at least one keyframe`);
389
+ }
390
+ times.forEach((time, k) => {
391
+ const at = `${path}.keyframes.times[${k}]`;
392
+ if (time < 0) {
393
+ throw new Error(`${at} must be non-negative, got ${time}`);
394
+ }
395
+ if (!Number.isInteger(time)) {
396
+ throw new Error(`${at} must be an integer, got ${time}`);
397
+ }
398
+ if (k > 0 && time <= times[k - 1]) {
399
+ throw new Error(`${at} must be greater than the previous frame, got ${time}`);
400
+ }
401
+ });
402
+ // The track is flattened into one spline, so a mis-sized array silently stops the
403
+ // animation rather than failing loudly at runtime.
404
+ const vectorValues = times.length * 3;
405
+ if (values.position.length !== vectorValues) {
406
+ throw new Error(`${path}.keyframes.values.position must have 3 values per keyframe (${vectorValues}), got ${values.position.length}`);
407
+ }
408
+ if (values.target.length !== vectorValues) {
409
+ throw new Error(`${path}.keyframes.values.target must have 3 values per keyframe (${vectorValues}), got ${values.target.length}`);
410
+ }
411
+ if (values.fov.length !== times.length) {
412
+ throw new Error(`${path}.keyframes.values.fov must have 1 value per keyframe (${times.length}), got ${values.fov.length}`);
413
+ }
414
+ // No CAMERA_FOV_RANGE check on keyframes.values.fov: the validator this reaches parity
415
+ // with does not bound those either, and they are splined rather than set directly.
416
+ });
417
+ maxCount(settings.annotations, ANNOTATION_LIMITS.maxCount, 'settings.annotations');
418
+ settings.annotations.forEach((annotation, i) => {
419
+ const path = `settings.annotations[${i}]`;
420
+ maxLength(annotation.title, ANNOTATION_LIMITS.titleMax, `${path}.title`);
421
+ maxLength(annotation.text, ANNOTATION_LIMITS.textMax, `${path}.text`);
422
+ range(annotation.camera.initial.fov, CAMERA_FOV_RANGE, `${path}.camera.initial.fov`);
423
+ });
424
+ };
425
+ // The v1 -> v2 migration substitutes defaults for falsy values — `frameRate: 0` becomes 30,
426
+ // `camera.fov: 0` becomes the default fov — so a post-migration check cannot see them and an
427
+ // explicitly invalid zero would pass. Check those fields as the caller supplied them.
428
+ //
429
+ // Only the coerced fields are checked here; everything else survives migration unchanged and
430
+ // is covered by validateLimitsV2.
431
+ const validateLimitsV1 = (settings) => {
432
+ if (settings.camera.fov !== undefined) {
433
+ range(settings.camera.fov, CAMERA_FOV_RANGE, 'settings.camera.fov');
434
+ }
435
+ settings.animTracks?.forEach((track, i) => {
436
+ if (track.frameRate === undefined) {
437
+ return;
438
+ }
439
+ const path = `settings.animTracks[${i}].frameRate`;
440
+ range(track.frameRate, ANIM_TRACK_LIMITS.frameRate, path);
441
+ if (!Number.isInteger(track.frameRate)) {
442
+ throw new Error(`${path} must be an integer, got ${track.frameRate}`);
443
+ }
444
+ });
445
+ };
446
+
447
+ const migrateV1 = (input) => {
448
+ // Copy first: callers own the object they pass in, and an API consumer holding a
449
+ // reference should not see it rewritten underneath them.
450
+ const settings = structuredClone(input);
451
+ if (settings.animTracks) {
452
+ settings.animTracks?.forEach((track) => {
453
+ // some early settings did not have frameRate set on anim tracks
454
+ if (!track.frameRate) {
455
+ const defaultFrameRate = 30;
456
+ track.frameRate = defaultFrameRate;
457
+ const times = track.keyframes.times;
458
+ for (let i = 0; i < times.length; i++) {
459
+ times[i] *= defaultFrameRate;
460
+ }
461
+ }
462
+ // smoothness property added in v1.4.0
463
+ // eslint-disable-next-line no-prototype-builtins -- preserve property lookup semantics
464
+ if (!track.hasOwnProperty('smoothness')) {
465
+ track.smoothness = 0;
466
+ }
467
+ });
468
+ }
469
+ else {
470
+ // some scenes were published without animTracks
471
+ settings.animTracks = [];
472
+ }
473
+ return settings;
474
+ };
475
+ const migrateAnimTrackV2 = (animTrackV1, fov) => {
476
+ return {
477
+ name: animTrackV1.name,
478
+ duration: animTrackV1.duration,
479
+ frameRate: animTrackV1.frameRate,
480
+ loopMode: animTrackV1.loopMode,
481
+ interpolation: animTrackV1.interpolation,
482
+ smoothness: animTrackV1.smoothness,
483
+ keyframes: {
484
+ times: animTrackV1.keyframes.times,
485
+ values: {
486
+ position: animTrackV1.keyframes.values.position,
487
+ target: animTrackV1.keyframes.values.target,
488
+ fov: new Array(animTrackV1.keyframes.times.length).fill(fov)
489
+ }
490
+ }
491
+ };
492
+ };
493
+ const migrateV2 = (v1) => {
494
+ return {
495
+ version: 2,
496
+ // Not the shared default ('linear'): tonemapping applies unconditionally, so changing
497
+ // it here would alter how existing v1 content renders.
498
+ tonemapping: 'none',
499
+ highPrecisionRendering: false,
500
+ background: {
501
+ color: v1.background.color || [0, 0, 0]
502
+ },
503
+ // Shared defaults rather than a private copy, so a migrated document lands inside the
504
+ // authoring bounds and `validateSettings(v1, { limits: true })` reports the caller's
505
+ // data instead of values invented here. Every effect is `enabled: false`, so which
506
+ // numbers they carry is inert.
507
+ postEffectSettings: defaultPostEffectSettings(),
508
+ animTracks: v1.animTracks.map((animTrackV1) => {
509
+ return migrateAnimTrackV2(animTrackV1, v1.camera.fov || DEFAULT_CAMERA_FOV);
510
+ }),
511
+ cameras: v1.camera.position && v1.camera.target
512
+ ? [
513
+ {
514
+ initial: {
515
+ position: v1.camera.position,
516
+ target: v1.camera.target,
517
+ fov: v1.camera.fov || DEFAULT_CAMERA_FOV
518
+ }
519
+ }
520
+ ]
521
+ : [],
522
+ annotations: [],
523
+ startMode: v1.camera.startAnim === 'animTrack' ? 'animTrack' : 'default'
524
+ };
525
+ };
526
+ /**
527
+ * Migrate settings of any supported version to the latest schema.
528
+ *
529
+ * Assumes valid input — call {@link validateSettings} first if the source is untrusted. Does
530
+ * not mutate the object passed in.
531
+ *
532
+ * @param settings - Parsed contents of a settings file.
533
+ * @returns The settings at the latest version.
534
+ * @throws If the version is not supported.
535
+ */
536
+ const importSettings = (settings) => {
537
+ let result;
538
+ const version = settings.version;
539
+ if (version === undefined) {
540
+ // v1 -> v2
541
+ result = migrateV2(migrateV1(settings));
542
+ }
543
+ else if (version === 2) {
544
+ // already v2
545
+ result = settings;
546
+ }
547
+ else {
548
+ throw new Error(`Unsupported experience settings version: ${version}`);
549
+ }
550
+ return result;
551
+ };
552
+ /**
553
+ * Validate unknown data against any supported settings schema version.
554
+ *
555
+ * @param settings - Data to validate.
556
+ * @param options - See {@link ValidateOptions}.
557
+ * @throws If the data is not valid settings, with a message naming the offending field.
558
+ */
559
+ const validateSettings = (settings, options = {}) => {
560
+ const obj = assertObject(settings, 'settings');
561
+ const version = obj.version;
562
+ if (version === undefined) {
563
+ validateV1(settings);
564
+ if (options.limits) {
565
+ // Fields the migration would coerce, as the caller wrote them.
566
+ validateLimitsV1(settings);
567
+ // Everything else has to be checked against the migrated result, so a value the
568
+ // migration derived can fail — v1 keyframe times in seconds are rescaled to
569
+ // frames, for instance, and may land on a fraction. Say so, rather than reporting
570
+ // a path and number the caller never wrote.
571
+ let migrated;
572
+ try {
573
+ migrated = migrateV2(migrateV1(settings));
574
+ }
575
+ catch (err) {
576
+ throw new Error(`settings could not be migrated for validation: ${err.message}`);
577
+ }
578
+ try {
579
+ validateLimitsV2(migrated);
580
+ }
581
+ catch (err) {
582
+ throw new Error(`${err.message} (checked after migrating from v1)`);
583
+ }
584
+ }
585
+ }
586
+ else if (version === 2) {
587
+ validateV2(settings);
588
+ if (options.limits) {
589
+ validateLimitsV2(settings);
590
+ }
591
+ }
592
+ else if (typeof version !== 'number') {
593
+ throw new Error(`settings.version must be a number, got ${typeof version}`);
594
+ }
595
+ else {
596
+ throw new Error(`Unsupported experience settings version: ${version}`);
597
+ }
598
+ };
599
+
600
+ export { ANIM_TRACK_LIMITS, ANNOTATION_LIMITS, CAMERA_FOV_RANGE, DEFAULT_BACKGROUND_COLOR, DEFAULT_CAMERA_FOV, DEFAULT_TONEMAPPING, POST_EFFECT_RANGES, defaultPostEffectSettings, defaultSettings, importSettings, isCameraFovInRange, validateSettings };
601
+ //# sourceMappingURL=viewer-settings.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewer-settings.mjs","sources":["../node_modules/@playcanvas/supersplat-viewer/dist/settings.js"],"sourcesContent":["// The single source of default experience settings, so every tool that writes a settings file\n// agrees. Several independent copies of these values had drifted apart; these are the ones\n// matching the settings already published in the wild, which means some producers change:\n// `tonemapping` is 'linear' rather than 'none', `background.color` is black rather than 0.4\n// grey, `bloom.intensity` is 0.1 rather than 1 (1 falls outside the authoring range in\n// ranges.ts) and `grading.brightness` is 1 rather than 0.\n// Frozen: `defaultSettings()` copies this, so a consumer mutating it would otherwise change\n// every later call's result.\n/** Default page and scene background, as normalized 0..1 rgb components. */\nconst DEFAULT_BACKGROUND_COLOR = Object.freeze([0, 0, 0]);\n/** Default tonemapping curve. */\nconst DEFAULT_TONEMAPPING = 'linear';\n/** Default vertical field of view, in degrees. */\n// Annotated so the published declaration widens to `number`; without it the emitted type is\n// the literal `75`, which bakes the value into the api.\n// eslint-disable-next-line @typescript-eslint/no-inferrable-types\nconst DEFAULT_CAMERA_FOV = 85;\nconst defaultCameraPose = (fit = 'environment') => {\n return fit === 'environment'\n ? { position: [0, 2, 0], target: [2, 2, 0], fov: DEFAULT_CAMERA_FOV }\n : { position: [2, 2, -2], target: [0, 0, 0], fov: DEFAULT_CAMERA_FOV };\n};\n/**\n * Default post-processing settings, with every effect disabled.\n *\n * @returns A fresh object; callers may mutate it freely.\n */\nconst defaultPostEffectSettings = () => ({\n sharpness: {\n enabled: false,\n amount: 0\n },\n bloom: {\n enabled: false,\n intensity: 0.1,\n blurLevel: 2\n },\n grading: {\n enabled: false,\n brightness: 1,\n contrast: 1,\n saturation: 1,\n tint: [1, 1, 1]\n },\n vignette: {\n enabled: false,\n intensity: 0.5,\n inner: 0.3,\n outer: 0.75,\n curvature: 1\n },\n fringing: {\n enabled: false,\n intensity: 0.5\n }\n});\n/**\n * Default experience settings, shared by every tool that writes a settings file.\n *\n * @param fit - How to place the default camera. Defaults to `environment`.\n * @returns A fresh object; callers may mutate it freely.\n */\nconst defaultSettings = (fit = 'environment') => ({\n version: 2,\n tonemapping: DEFAULT_TONEMAPPING,\n highPrecisionRendering: false,\n background: {\n color: [...DEFAULT_BACKGROUND_COLOR]\n },\n postEffectSettings: defaultPostEffectSettings(),\n animTracks: [],\n cameras: [{ initial: defaultCameraPose(fit) }],\n annotations: [],\n startMode: 'default'\n});\n\nconst assertObject = (value, path) => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new Error(`${path} must be an object`);\n }\n return value;\n};\nconst assertNumber = (value, path) => {\n if (typeof value !== 'number' || !isFinite(value)) {\n throw new Error(`${path} must be a finite number`);\n }\n return value;\n};\nconst assertString = (value, path) => {\n if (typeof value !== 'string') {\n throw new Error(`${path} must be a string`);\n }\n return value;\n};\nconst assertBoolean = (value, path) => {\n if (typeof value !== 'boolean') {\n throw new Error(`${path} must be a boolean`);\n }\n return value;\n};\nconst assertEnum = (value, allowed, path) => {\n if (typeof value !== 'string' || !allowed.includes(value)) {\n throw new Error(`${path} must be one of: ${allowed.join(', ')}`);\n }\n return value;\n};\nconst assertArray = (value, path) => {\n if (!Array.isArray(value)) {\n throw new Error(`${path} must be an array`);\n }\n return value;\n};\nconst assertNumberArray = (value, path) => {\n const arr = assertArray(value, path);\n for (let i = 0; i < arr.length; i++) {\n assertNumber(arr[i], `${path}[${i}]`);\n }\n return arr;\n};\nconst assertTuple3 = (value, path) => {\n const arr = assertNumberArray(value, path);\n if (arr.length !== 3) {\n throw new Error(`${path} must have exactly 3 elements`);\n }\n return arr;\n};\n\nconst validateAnimTrack$1 = (data, path) => {\n const obj = assertObject(data, path);\n assertString(obj.name, `${path}.name`);\n assertNumber(obj.duration, `${path}.duration`);\n if (obj.frameRate !== undefined)\n assertNumber(obj.frameRate, `${path}.frameRate`);\n assertEnum(obj.target, ['camera'], `${path}.target`);\n assertEnum(obj.loopMode, ['none', 'repeat', 'pingpong'], `${path}.loopMode`);\n assertEnum(obj.interpolation, ['step', 'spline'], `${path}.interpolation`);\n if (obj.smoothness !== undefined)\n assertNumber(obj.smoothness, `${path}.smoothness`);\n const kf = assertObject(obj.keyframes, `${path}.keyframes`);\n assertNumberArray(kf.times, `${path}.keyframes.times`);\n const vals = assertObject(kf.values, `${path}.keyframes.values`);\n assertNumberArray(vals.position, `${path}.keyframes.values.position`);\n assertNumberArray(vals.target, `${path}.keyframes.values.target`);\n return data;\n};\nconst validateV1 = (data) => {\n const obj = assertObject(data, 'settings');\n const camera = assertObject(obj.camera, 'settings.camera');\n if (camera.fov !== undefined)\n assertNumber(camera.fov, 'settings.camera.fov');\n // Exactly 3 elements: migration casts these straight into v2 tuples, so any other arity\n // would validate here yet produce output that fails v2 validation.\n if (camera.position !== undefined)\n assertTuple3(camera.position, 'settings.camera.position');\n if (camera.target !== undefined)\n assertTuple3(camera.target, 'settings.camera.target');\n if (camera.startAnim !== undefined)\n assertEnum(camera.startAnim, ['none', 'orbit', 'animTrack'], 'settings.camera.startAnim');\n if (camera.animTrack != null)\n assertString(camera.animTrack, 'settings.camera.animTrack');\n const bg = assertObject(obj.background, 'settings.background');\n if (bg.color !== undefined)\n assertTuple3(bg.color, 'settings.background.color');\n if (obj.animTracks !== undefined) {\n const tracks = assertArray(obj.animTracks, 'settings.animTracks');\n tracks.forEach((t, i) => validateAnimTrack$1(t, `settings.animTracks[${i}]`));\n }\n return data;\n};\n\nconst TONEMAPPING = ['none', 'linear', 'filmic', 'hejl', 'aces', 'aces2', 'neutral'];\nconst LOOP_MODES = ['none', 'repeat', 'pingpong'];\nconst INTERPOLATIONS = ['step', 'spline'];\nconst START_MODES = ['default', 'animTrack', 'annotation'];\nconst validateAnimTrack = (data, path) => {\n const obj = assertObject(data, path);\n assertString(obj.name, `${path}.name`);\n assertNumber(obj.duration, `${path}.duration`);\n assertNumber(obj.frameRate, `${path}.frameRate`);\n assertEnum(obj.loopMode, LOOP_MODES, `${path}.loopMode`);\n assertEnum(obj.interpolation, INTERPOLATIONS, `${path}.interpolation`);\n assertNumber(obj.smoothness, `${path}.smoothness`);\n const kf = assertObject(obj.keyframes, `${path}.keyframes`);\n assertNumberArray(kf.times, `${path}.keyframes.times`);\n const vals = assertObject(kf.values, `${path}.keyframes.values`);\n assertNumberArray(vals.position, `${path}.keyframes.values.position`);\n assertNumberArray(vals.target, `${path}.keyframes.values.target`);\n assertNumberArray(vals.fov, `${path}.keyframes.values.fov`);\n return data;\n};\nconst validateCamera = (data, path) => {\n const obj = assertObject(data, path);\n const initial = assertObject(obj.initial, `${path}.initial`);\n assertTuple3(initial.position, `${path}.initial.position`);\n assertTuple3(initial.target, `${path}.initial.target`);\n assertNumber(initial.fov, `${path}.initial.fov`);\n return data;\n};\nconst validateAnnotation = (data, path) => {\n const obj = assertObject(data, path);\n assertTuple3(obj.position, `${path}.position`);\n assertString(obj.title, `${path}.title`);\n assertString(obj.text, `${path}.text`);\n validateCamera(obj.camera, `${path}.camera`);\n return data;\n};\nconst validatePostEffects = (data, path) => {\n const obj = assertObject(data, path);\n const sh = assertObject(obj.sharpness, `${path}.sharpness`);\n assertBoolean(sh.enabled, `${path}.sharpness.enabled`);\n assertNumber(sh.amount, `${path}.sharpness.amount`);\n const bl = assertObject(obj.bloom, `${path}.bloom`);\n assertBoolean(bl.enabled, `${path}.bloom.enabled`);\n assertNumber(bl.intensity, `${path}.bloom.intensity`);\n assertNumber(bl.blurLevel, `${path}.bloom.blurLevel`);\n const gr = assertObject(obj.grading, `${path}.grading`);\n assertBoolean(gr.enabled, `${path}.grading.enabled`);\n assertNumber(gr.brightness, `${path}.grading.brightness`);\n assertNumber(gr.contrast, `${path}.grading.contrast`);\n assertNumber(gr.saturation, `${path}.grading.saturation`);\n assertTuple3(gr.tint, `${path}.grading.tint`);\n const vi = assertObject(obj.vignette, `${path}.vignette`);\n assertBoolean(vi.enabled, `${path}.vignette.enabled`);\n assertNumber(vi.intensity, `${path}.vignette.intensity`);\n assertNumber(vi.inner, `${path}.vignette.inner`);\n assertNumber(vi.outer, `${path}.vignette.outer`);\n assertNumber(vi.curvature, `${path}.vignette.curvature`);\n const fr = assertObject(obj.fringing, `${path}.fringing`);\n assertBoolean(fr.enabled, `${path}.fringing.enabled`);\n assertNumber(fr.intensity, `${path}.fringing.intensity`);\n return data;\n};\nconst validateV2 = (data) => {\n const obj = assertObject(data, 'settings');\n if (obj.version !== 2) {\n throw new Error('settings.version must be 2');\n }\n assertEnum(obj.tonemapping, TONEMAPPING, 'settings.tonemapping');\n assertBoolean(obj.highPrecisionRendering, 'settings.highPrecisionRendering');\n if (obj.soundUrl !== undefined)\n assertString(obj.soundUrl, 'settings.soundUrl');\n const bg = assertObject(obj.background, 'settings.background');\n assertTuple3(bg.color, 'settings.background.color');\n if (bg.skyboxUrl !== undefined)\n assertString(bg.skyboxUrl, 'settings.background.skyboxUrl');\n validatePostEffects(obj.postEffectSettings, 'settings.postEffectSettings');\n const tracks = assertArray(obj.animTracks, 'settings.animTracks');\n tracks.forEach((t, i) => validateAnimTrack(t, `settings.animTracks[${i}]`));\n const cameras = assertArray(obj.cameras, 'settings.cameras');\n cameras.forEach((c, i) => validateCamera(c, `settings.cameras[${i}]`));\n const annotations = assertArray(obj.annotations, 'settings.annotations');\n annotations.forEach((a, i) => validateAnnotation(a, `settings.annotations[${i}]`));\n assertEnum(obj.startMode, START_MODES, 'settings.startMode');\n return data;\n};\n\n// Authoring bounds for experience settings, shared by the settings validators and by editor\n// UIs that need slider ranges. Pure data with no imports, so a consumer can take these\n// without pulling in the schema.\n//\n// These are *authoring* limits, not read limits: the viewer renders values outside them\n// perfectly well, and settings in the wild contain some (see validate-limits.ts).\n// `step` is UI granularity, not a constraint.\n// These are published constants that the validators themselves read, so a consumer mutating\n// one would silently change validation for everyone in the realm. Freeze rather than rely on\n// `as const`, which is erased at runtime.\nconst deepFreeze = (value) => {\n if (value !== null && typeof value === 'object') {\n Object.values(value).forEach(deepFreeze);\n Object.freeze(value);\n }\n return value;\n};\n/** Bounds for a camera's vertical field of view, in degrees. */\nconst CAMERA_FOV_RANGE = deepFreeze({\n min: 10,\n max: 120,\n step: 1\n});\n/** Bounds for each post-processing parameter. */\nconst POST_EFFECT_RANGES = deepFreeze({\n sharpness: {\n amount: { min: 0, max: 1, step: 0.01 }\n },\n bloom: {\n intensity: { min: 0, max: 0.1, step: 0.01 },\n blurLevel: { min: 1, max: 16, step: 1 }\n },\n grading: {\n brightness: { min: 0, max: 3, step: 0.01 },\n contrast: { min: 0.5, max: 1.5, step: 0.01 },\n saturation: { min: 0, max: 2, step: 0.01 }\n },\n vignette: {\n intensity: { min: 0, max: 1, step: 0.01 },\n inner: { min: 0, max: 3, step: 0.01 },\n outer: { min: 0, max: 3, step: 0.01 },\n curvature: { min: 0.01, max: 10, step: 0.01 }\n },\n fringing: {\n intensity: { min: 0, max: 100, step: 1 }\n }\n});\n// Annotated rather than `as const`: the annotation keeps them readonly while widening the\n// values, so the published types do not bake in numbers we may want to relax later.\n/** Bounds and size limits for camera animation tracks. Intentionally tight for now. */\nconst ANIM_TRACK_LIMITS = deepFreeze({\n duration: { min: 0.1, max: 600 },\n frameRate: { min: 1, max: 120 },\n smoothness: { min: 0, max: 1 },\n maxKeyframes: 1000,\n nameMax: 120,\n maxTracks: 10\n});\n/** Size limits for annotations. Intentionally tight for now. */\nconst ANNOTATION_LIMITS = deepFreeze({\n maxCount: 25,\n titleMax: 60,\n textMax: 280\n});\n/**\n * Test a field of view against {@link CAMERA_FOV_RANGE}.\n *\n * @param fov - Vertical field of view in degrees.\n * @returns Whether the value is within the authoring bounds.\n */\nconst isCameraFovInRange = (fov) => {\n return fov >= CAMERA_FOV_RANGE.min && fov <= CAMERA_FOV_RANGE.max;\n};\n\n// Authoring-limit checks, deliberately separate from the shape validation in v2.ts.\n//\n// Shape validation answers \"can the viewer read this\" and must keep accepting every settings\n// file ever written. These limits answer \"is this sane input from an editor\" and are stricter\n// — strictly enough that some existing data fails them. `bloom.intensity` is the known case:\n// the range caps it at 0.1, while several older default objects wrote 1. So this runs only on\n// request, via `validateSettings(x, { limits: true })`, and never on the viewer's read path.\nconst range = (value, bounds, path) => {\n if (value < bounds.min || value > bounds.max) {\n throw new Error(`${path} must be between ${bounds.min} and ${bounds.max}, got ${value}`);\n }\n};\nconst maxLength = (value, max, path) => {\n if (value.length > max) {\n throw new Error(`${path} must be at most ${max} characters, got ${value.length}`);\n }\n};\nconst maxCount = (value, max, path) => {\n if (value.length > max) {\n throw new Error(`${path} must have at most ${max} entries, got ${value.length}`);\n }\n};\nconst validateLimitsV2 = (settings) => {\n const fx = settings.postEffectSettings;\n range(fx.sharpness.amount, POST_EFFECT_RANGES.sharpness.amount, 'settings.postEffectSettings.sharpness.amount');\n range(fx.bloom.intensity, POST_EFFECT_RANGES.bloom.intensity, 'settings.postEffectSettings.bloom.intensity');\n range(fx.bloom.blurLevel, POST_EFFECT_RANGES.bloom.blurLevel, 'settings.postEffectSettings.bloom.blurLevel');\n range(fx.grading.brightness, POST_EFFECT_RANGES.grading.brightness, 'settings.postEffectSettings.grading.brightness');\n range(fx.grading.contrast, POST_EFFECT_RANGES.grading.contrast, 'settings.postEffectSettings.grading.contrast');\n range(fx.grading.saturation, POST_EFFECT_RANGES.grading.saturation, 'settings.postEffectSettings.grading.saturation');\n range(fx.vignette.intensity, POST_EFFECT_RANGES.vignette.intensity, 'settings.postEffectSettings.vignette.intensity');\n range(fx.vignette.inner, POST_EFFECT_RANGES.vignette.inner, 'settings.postEffectSettings.vignette.inner');\n range(fx.vignette.outer, POST_EFFECT_RANGES.vignette.outer, 'settings.postEffectSettings.vignette.outer');\n range(fx.vignette.curvature, POST_EFFECT_RANGES.vignette.curvature, 'settings.postEffectSettings.vignette.curvature');\n range(fx.fringing.intensity, POST_EFFECT_RANGES.fringing.intensity, 'settings.postEffectSettings.fringing.intensity');\n // no count limit on cameras — the viewer only reads cameras[0], but the format allows more\n settings.cameras.forEach((camera, i) => {\n range(camera.initial.fov, CAMERA_FOV_RANGE, `settings.cameras[${i}].initial.fov`);\n });\n maxCount(settings.animTracks, ANIM_TRACK_LIMITS.maxTracks, 'settings.animTracks');\n settings.animTracks.forEach((track, i) => {\n const path = `settings.animTracks[${i}]`;\n maxLength(track.name, ANIM_TRACK_LIMITS.nameMax, `${path}.name`);\n range(track.duration, ANIM_TRACK_LIMITS.duration, `${path}.duration`);\n range(track.frameRate, ANIM_TRACK_LIMITS.frameRate, `${path}.frameRate`);\n if (!Number.isInteger(track.frameRate)) {\n throw new Error(`${path}.frameRate must be an integer, got ${track.frameRate}`);\n }\n range(track.smoothness, ANIM_TRACK_LIMITS.smoothness, `${path}.smoothness`);\n // Keyframe times are frame numbers: non-negative integers, strictly ascending, since\n // the spline is built from them in order.\n const { times, values } = track.keyframes;\n maxCount(times, ANIM_TRACK_LIMITS.maxKeyframes, `${path}.keyframes.times`);\n // At least one: `CubicSpline.calcKnots` derives its dimension as\n // `points.length / times.length`, so an empty track computes 0/0 and allocates\n // `new Array(NaN)`, which throws. A track the viewer cannot load is not valid input.\n if (times.length === 0) {\n throw new Error(`${path}.keyframes.times must have at least one keyframe`);\n }\n times.forEach((time, k) => {\n const at = `${path}.keyframes.times[${k}]`;\n if (time < 0) {\n throw new Error(`${at} must be non-negative, got ${time}`);\n }\n if (!Number.isInteger(time)) {\n throw new Error(`${at} must be an integer, got ${time}`);\n }\n if (k > 0 && time <= times[k - 1]) {\n throw new Error(`${at} must be greater than the previous frame, got ${time}`);\n }\n });\n // The track is flattened into one spline, so a mis-sized array silently stops the\n // animation rather than failing loudly at runtime.\n const vectorValues = times.length * 3;\n if (values.position.length !== vectorValues) {\n throw new Error(`${path}.keyframes.values.position must have 3 values per keyframe (${vectorValues}), got ${values.position.length}`);\n }\n if (values.target.length !== vectorValues) {\n throw new Error(`${path}.keyframes.values.target must have 3 values per keyframe (${vectorValues}), got ${values.target.length}`);\n }\n if (values.fov.length !== times.length) {\n throw new Error(`${path}.keyframes.values.fov must have 1 value per keyframe (${times.length}), got ${values.fov.length}`);\n }\n // No CAMERA_FOV_RANGE check on keyframes.values.fov: the validator this reaches parity\n // with does not bound those either, and they are splined rather than set directly.\n });\n maxCount(settings.annotations, ANNOTATION_LIMITS.maxCount, 'settings.annotations');\n settings.annotations.forEach((annotation, i) => {\n const path = `settings.annotations[${i}]`;\n maxLength(annotation.title, ANNOTATION_LIMITS.titleMax, `${path}.title`);\n maxLength(annotation.text, ANNOTATION_LIMITS.textMax, `${path}.text`);\n range(annotation.camera.initial.fov, CAMERA_FOV_RANGE, `${path}.camera.initial.fov`);\n });\n};\n// The v1 -> v2 migration substitutes defaults for falsy values — `frameRate: 0` becomes 30,\n// `camera.fov: 0` becomes the default fov — so a post-migration check cannot see them and an\n// explicitly invalid zero would pass. Check those fields as the caller supplied them.\n//\n// Only the coerced fields are checked here; everything else survives migration unchanged and\n// is covered by validateLimitsV2.\nconst validateLimitsV1 = (settings) => {\n if (settings.camera.fov !== undefined) {\n range(settings.camera.fov, CAMERA_FOV_RANGE, 'settings.camera.fov');\n }\n settings.animTracks?.forEach((track, i) => {\n if (track.frameRate === undefined) {\n return;\n }\n const path = `settings.animTracks[${i}].frameRate`;\n range(track.frameRate, ANIM_TRACK_LIMITS.frameRate, path);\n if (!Number.isInteger(track.frameRate)) {\n throw new Error(`${path} must be an integer, got ${track.frameRate}`);\n }\n });\n};\n\nconst migrateV1 = (input) => {\n // Copy first: callers own the object they pass in, and an API consumer holding a\n // reference should not see it rewritten underneath them.\n const settings = structuredClone(input);\n if (settings.animTracks) {\n settings.animTracks?.forEach((track) => {\n // some early settings did not have frameRate set on anim tracks\n if (!track.frameRate) {\n const defaultFrameRate = 30;\n track.frameRate = defaultFrameRate;\n const times = track.keyframes.times;\n for (let i = 0; i < times.length; i++) {\n times[i] *= defaultFrameRate;\n }\n }\n // smoothness property added in v1.4.0\n // eslint-disable-next-line no-prototype-builtins -- preserve property lookup semantics\n if (!track.hasOwnProperty('smoothness')) {\n track.smoothness = 0;\n }\n });\n }\n else {\n // some scenes were published without animTracks\n settings.animTracks = [];\n }\n return settings;\n};\nconst migrateAnimTrackV2 = (animTrackV1, fov) => {\n return {\n name: animTrackV1.name,\n duration: animTrackV1.duration,\n frameRate: animTrackV1.frameRate,\n loopMode: animTrackV1.loopMode,\n interpolation: animTrackV1.interpolation,\n smoothness: animTrackV1.smoothness,\n keyframes: {\n times: animTrackV1.keyframes.times,\n values: {\n position: animTrackV1.keyframes.values.position,\n target: animTrackV1.keyframes.values.target,\n fov: new Array(animTrackV1.keyframes.times.length).fill(fov)\n }\n }\n };\n};\nconst migrateV2 = (v1) => {\n return {\n version: 2,\n // Not the shared default ('linear'): tonemapping applies unconditionally, so changing\n // it here would alter how existing v1 content renders.\n tonemapping: 'none',\n highPrecisionRendering: false,\n background: {\n color: v1.background.color || [0, 0, 0]\n },\n // Shared defaults rather than a private copy, so a migrated document lands inside the\n // authoring bounds and `validateSettings(v1, { limits: true })` reports the caller's\n // data instead of values invented here. Every effect is `enabled: false`, so which\n // numbers they carry is inert.\n postEffectSettings: defaultPostEffectSettings(),\n animTracks: v1.animTracks.map((animTrackV1) => {\n return migrateAnimTrackV2(animTrackV1, v1.camera.fov || DEFAULT_CAMERA_FOV);\n }),\n cameras: v1.camera.position && v1.camera.target\n ? [\n {\n initial: {\n position: v1.camera.position,\n target: v1.camera.target,\n fov: v1.camera.fov || DEFAULT_CAMERA_FOV\n }\n }\n ]\n : [],\n annotations: [],\n startMode: v1.camera.startAnim === 'animTrack' ? 'animTrack' : 'default'\n };\n};\n/**\n * Migrate settings of any supported version to the latest schema.\n *\n * Assumes valid input — call {@link validateSettings} first if the source is untrusted. Does\n * not mutate the object passed in.\n *\n * @param settings - Parsed contents of a settings file.\n * @returns The settings at the latest version.\n * @throws If the version is not supported.\n */\nconst importSettings = (settings) => {\n let result;\n const version = settings.version;\n if (version === undefined) {\n // v1 -> v2\n result = migrateV2(migrateV1(settings));\n }\n else if (version === 2) {\n // already v2\n result = settings;\n }\n else {\n throw new Error(`Unsupported experience settings version: ${version}`);\n }\n return result;\n};\n/**\n * Validate unknown data against any supported settings schema version.\n *\n * @param settings - Data to validate.\n * @param options - See {@link ValidateOptions}.\n * @throws If the data is not valid settings, with a message naming the offending field.\n */\nconst validateSettings = (settings, options = {}) => {\n const obj = assertObject(settings, 'settings');\n const version = obj.version;\n if (version === undefined) {\n validateV1(settings);\n if (options.limits) {\n // Fields the migration would coerce, as the caller wrote them.\n validateLimitsV1(settings);\n // Everything else has to be checked against the migrated result, so a value the\n // migration derived can fail — v1 keyframe times in seconds are rescaled to\n // frames, for instance, and may land on a fraction. Say so, rather than reporting\n // a path and number the caller never wrote.\n let migrated;\n try {\n migrated = migrateV2(migrateV1(settings));\n }\n catch (err) {\n throw new Error(`settings could not be migrated for validation: ${err.message}`);\n }\n try {\n validateLimitsV2(migrated);\n }\n catch (err) {\n throw new Error(`${err.message} (checked after migrating from v1)`);\n }\n }\n }\n else if (version === 2) {\n validateV2(settings);\n if (options.limits) {\n validateLimitsV2(settings);\n }\n }\n else if (typeof version !== 'number') {\n throw new Error(`settings.version must be a number, got ${typeof version}`);\n }\n else {\n throw new Error(`Unsupported experience settings version: ${version}`);\n }\n};\n\nexport { ANIM_TRACK_LIMITS, ANNOTATION_LIMITS, CAMERA_FOV_RANGE, DEFAULT_BACKGROUND_COLOR, DEFAULT_CAMERA_FOV, DEFAULT_TONEMAPPING, POST_EFFECT_RANGES, defaultPostEffectSettings, defaultSettings, importSettings, isCameraFovInRange, validateSettings };\n//# sourceMappingURL=settings.js.map\n"],"names":[],"mappings":"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","x_google_ignoreList":[0]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcanvas/splat-transform",
3
- "version": "3.3.1",
3
+ "version": "3.3.2",
4
4
  "author": "PlayCanvas<support@playcanvas.com>",
5
5
  "homepage": "https://playcanvas.com",
6
6
  "description": "Library and CLI tool for 3D Gaussian splat format conversion and transformation",
@@ -28,6 +28,10 @@
28
28
  }
29
29
  },
30
30
  "./worker": "./dist/worker.mjs",
31
+ "./viewer-settings": {
32
+ "types": "./dist/viewer-settings.d.ts",
33
+ "import": "./dist/viewer-settings.mjs"
34
+ },
31
35
  "./lib/*": "./lib/*"
32
36
  },
33
37
  "bin": {