@found-in-space/skykit 0.2.0-alpha.1 → 0.2.0-dev.20260527.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/README.md +143 -6
- package/examples/custom-object-layer/custom-object-layer.js +1 -24
- package/examples/xr-free-roam/index.html +62 -4
- package/examples/xr-free-roam/xr-free-roam.css +249 -18
- package/examples/xr-free-roam/xr-free-roam.js +644 -217
- package/package.json +31 -5
- package/src/__tests__/skykit-anchored-images.test.js +32 -4
- package/src/__tests__/skykit-browser.test.js +217 -0
- package/src/__tests__/skykit-data.test.js +131 -0
- package/src/__tests__/skykit-parallax.test.js +4 -4
- package/src/__tests__/skykit-touch-os.test.js +71 -0
- package/src/__tests__/skykit-xr.test.js +123 -2
- package/src/__tests__/skykit.test.js +138 -1
- package/src/anchored-images.js +14 -15
- package/src/browser-addons.d.ts +16 -0
- package/src/browser-addons.js +155 -0
- package/src/browser-constellations.d.ts +13 -0
- package/src/browser-constellations.js +387 -0
- package/src/browser-journey.d.ts +8 -0
- package/src/browser-journey.js +240 -0
- package/src/browser.d.ts +98 -0
- package/src/browser.js +215 -13
- package/src/data.d.ts +133 -0
- package/src/data.js +447 -0
- package/src/embed.d.ts +5 -0
- package/src/embed.js +52 -2
- package/src/hr-diagram.js +23 -5
- package/src/index.d.ts +32 -7
- package/src/plugins.js +87 -43
- package/src/story.d.ts +57 -0
- package/src/story.js +396 -0
- package/src/three-shim.d.ts +32 -0
- package/src/touch-os.d.ts +70 -0
- package/src/touch-os.js +275 -0
- package/src/utils.js +96 -6
- package/src/viewer-entry.d.ts +10 -0
- package/src/viewer-entry.js +4 -0
- package/src/viewer.js +110 -12
- package/src/xr/plugins.js +224 -13
- package/src/xr/session.js +60 -14
- package/src/xr.d.ts +22 -0
- package/src/xr.js +1 -0
package/src/index.d.ts
CHANGED
|
@@ -67,6 +67,18 @@ export interface QuaternionLike {
|
|
|
67
67
|
w: number;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
export interface SkykitLookAtInput {
|
|
71
|
+
targetPc?: Vector3Like | [number, number, number];
|
|
72
|
+
raDeg?: number;
|
|
73
|
+
raHours?: number;
|
|
74
|
+
decDeg?: number;
|
|
75
|
+
distancePc?: number;
|
|
76
|
+
star?: string | StarObjectRef | StarPickMeta | unknown;
|
|
77
|
+
orientationIcrs?: QuaternionLike;
|
|
78
|
+
positionAngleDeg?: number;
|
|
79
|
+
[key: string]: unknown;
|
|
80
|
+
}
|
|
81
|
+
|
|
70
82
|
export interface SkykitObserverMotion {
|
|
71
83
|
velocityPcPerSec: Vector3Like;
|
|
72
84
|
speedPcPerSec: number;
|
|
@@ -76,8 +88,8 @@ export interface SkykitViewState {
|
|
|
76
88
|
revision: number;
|
|
77
89
|
observerPc: Vector3Like;
|
|
78
90
|
renderObserverPosition: Vector3Like;
|
|
91
|
+
lookAt?: SkykitLookAtInput | null;
|
|
79
92
|
targetPc?: Vector3Like | null;
|
|
80
|
-
directionIcrs?: Vector3Like | null;
|
|
81
93
|
orientationIcrs?: QuaternionLike | null;
|
|
82
94
|
limitingMagnitude: number;
|
|
83
95
|
verticalFovDeg?: number;
|
|
@@ -370,6 +382,8 @@ export interface SkykitViewerOptions {
|
|
|
370
382
|
parts?: Iterable<SkykitThreePart>;
|
|
371
383
|
plugins?: Iterable<SkykitPluginInput>;
|
|
372
384
|
view?: Partial<SkykitViewState>;
|
|
385
|
+
resolveLookAtStar?: (star: unknown, lookAt: SkykitLookAtInput) => SkykitLookAtInput | Vector3Like | [number, number, number] | Promise<SkykitLookAtInput | Vector3Like | [number, number, number] | null> | null;
|
|
386
|
+
resolveLookAtBookmark?: (bookmarkId: string, lookAt: unknown) => SkykitLookAtInput | Vector3Like | [number, number, number] | Promise<SkykitLookAtInput | Vector3Like | [number, number, number] | null> | null;
|
|
373
387
|
autoMountRenderer?: boolean;
|
|
374
388
|
}
|
|
375
389
|
|
|
@@ -412,6 +426,7 @@ export interface SkykitViewer {
|
|
|
412
426
|
readonly observerRig: SkykitObserverRig;
|
|
413
427
|
readonly actions: SkykitActionRegistry;
|
|
414
428
|
addPart(part: SkykitThreePart): SkykitPluginTeardown;
|
|
429
|
+
addPlugin(plugin: SkykitPluginInput): Promise<SkykitPluginTeardown>;
|
|
415
430
|
getViewState(): SkykitViewState;
|
|
416
431
|
requestViewState(patch: Partial<SkykitViewState>, reason?: string): void;
|
|
417
432
|
update(deltaSeconds?: number, frameOptions?: SkykitFrameOptions): void;
|
|
@@ -501,11 +516,11 @@ export interface AnchoredImageCatalog {
|
|
|
501
516
|
resolveTargetPc(key: string, options?: AnchoredImageTargetOptions): Vector3Like | null;
|
|
502
517
|
resolveLookAt(key: string, options?: AnchoredImageLookAtOptions): AnchoredImageLookAtResult | null;
|
|
503
518
|
resolveNearest(
|
|
504
|
-
|
|
519
|
+
lookDirection: Vector3Like | [number, number, number],
|
|
505
520
|
options?: AnchoredImageResolveNearestOptions
|
|
506
521
|
): AnchoredImageMatch | null;
|
|
507
522
|
resolveWithinAngle(
|
|
508
|
-
|
|
523
|
+
lookDirection: Vector3Like | [number, number, number],
|
|
509
524
|
options: AnchoredImageResolveWithinAngleOptions
|
|
510
525
|
): AnchoredImageMatch[];
|
|
511
526
|
}
|
|
@@ -553,6 +568,8 @@ export interface AnchoredImageSkyPluginOptions {
|
|
|
553
568
|
catalog: AnchoredImageCatalog;
|
|
554
569
|
controller: AnchoredImageController;
|
|
555
570
|
loading?: AnchoredImageSkyLoading;
|
|
571
|
+
anchorMode?: SkykitLayerAnchorMode;
|
|
572
|
+
scaleBandId?: string;
|
|
556
573
|
fixedAtInfinity?: boolean;
|
|
557
574
|
radius?: number;
|
|
558
575
|
opacity?: number;
|
|
@@ -674,7 +691,7 @@ export interface SkykitStarSourceRestartRetentionPolicy {
|
|
|
674
691
|
}
|
|
675
692
|
|
|
676
693
|
export interface SkykitHrDiagramTouchOsOptions {
|
|
677
|
-
surfaces?: EmbeddedSurfaceService;
|
|
694
|
+
surfaces?: EmbeddedSurfaceService | (() => EmbeddedSurfaceService | null | undefined);
|
|
678
695
|
sourceId?: string;
|
|
679
696
|
componentId?: string;
|
|
680
697
|
width?: number;
|
|
@@ -938,6 +955,16 @@ export interface SkykitJourneyPluginOptions {
|
|
|
938
955
|
) => void;
|
|
939
956
|
}
|
|
940
957
|
|
|
958
|
+
export interface SkykitJourneyPlugin extends SkykitPlugin {
|
|
959
|
+
goTo(payload: unknown): Promise<JourneySceneSpec | null>;
|
|
960
|
+
next(): Promise<JourneySceneSpec | null>;
|
|
961
|
+
previous(): Promise<JourneySceneSpec | null>;
|
|
962
|
+
seek(payload: unknown): number;
|
|
963
|
+
play(payload?: unknown): number;
|
|
964
|
+
pause(): number;
|
|
965
|
+
getSnapshot(): unknown;
|
|
966
|
+
}
|
|
967
|
+
|
|
941
968
|
export interface SkykitSpatialPreloadStrategyOptions {
|
|
942
969
|
combine?: boolean;
|
|
943
970
|
baseStrategy?: StarCellStrategy;
|
|
@@ -1170,9 +1197,7 @@ export declare function createKeyboardNavigationPlugin(options?: SkykitKeyboardN
|
|
|
1170
1197
|
export declare function createSkykitNavigationPlugin(options?: SkykitNavigationPluginOptions): SkykitPlugin & {
|
|
1171
1198
|
getSnapshot(): unknown;
|
|
1172
1199
|
};
|
|
1173
|
-
export declare function createSkykitJourneyPlugin(options?: SkykitJourneyPluginOptions):
|
|
1174
|
-
getSnapshot(): unknown;
|
|
1175
|
-
};
|
|
1200
|
+
export declare function createSkykitJourneyPlugin(options?: SkykitJourneyPluginOptions): SkykitJourneyPlugin;
|
|
1176
1201
|
export declare function createSkykitStarPreloadRequestsFromSpatialHints(
|
|
1177
1202
|
hints: Iterable<SpatialPreloadHint>,
|
|
1178
1203
|
options?: SkykitSpatialPreloadStrategyOptions
|
package/src/plugins.js
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
createOrbitTransferRoute,
|
|
20
20
|
createSpatialPoseTransition,
|
|
21
21
|
createSpatialNavigationAutomation,
|
|
22
|
+
resolveSpatialLookAt,
|
|
22
23
|
resolveSpatialTarget,
|
|
23
24
|
} from '@found-in-space/spatial';
|
|
24
25
|
|
|
@@ -219,8 +220,12 @@ export function createSkykitNavigationPlugin(options = {}) {
|
|
|
219
220
|
id,
|
|
220
221
|
setup(context) {
|
|
221
222
|
const threeContext = /** @type {import('./index.d.ts').SkykitThreePluginContext} */ (context);
|
|
222
|
-
threeContext.addPart(part);
|
|
223
|
-
|
|
223
|
+
const removePart = threeContext.addPart(part);
|
|
224
|
+
const unregisterActions = registerNavigationActions(threeContext);
|
|
225
|
+
return () => {
|
|
226
|
+
unregisterActions();
|
|
227
|
+
removePart();
|
|
228
|
+
};
|
|
224
229
|
},
|
|
225
230
|
getSnapshot: () => part.getSnapshot?.() ?? null,
|
|
226
231
|
};
|
|
@@ -366,10 +371,24 @@ export function createSkykitNavigationPlugin(options = {}) {
|
|
|
366
371
|
const position = positionInput === undefined
|
|
367
372
|
? current.observerPc
|
|
368
373
|
: await resolveTarget(positionInput, context) ?? current.observerPc;
|
|
374
|
+
const lookAtInput = targetSource.lookAt;
|
|
375
|
+
const resolvedLook = lookAtInput !== undefined
|
|
376
|
+
? await resolveSpatialLookAt(lookAtInput, {
|
|
377
|
+
observerPc: position,
|
|
378
|
+
resolveBookmark: typeof options.resolveBookmark === 'function'
|
|
379
|
+
? (bookmarkId, original) => options.resolveBookmark?.(
|
|
380
|
+
bookmarkId,
|
|
381
|
+
/** @type {import('@found-in-space/spatial').SpatialTargetInput} */ (original),
|
|
382
|
+
context,
|
|
383
|
+
) ?? null
|
|
384
|
+
: undefined,
|
|
385
|
+
})
|
|
386
|
+
: null;
|
|
369
387
|
const orientationInput = targetSource.orientationIcrs
|
|
370
388
|
?? (targetSource.orientation && isQuaternionLike(targetSource.orientation) ? targetSource.orientation : undefined)
|
|
371
389
|
?? source.orientationIcrs;
|
|
372
|
-
const orientation =
|
|
390
|
+
const orientation = resolvedLook?.orientationIcrs
|
|
391
|
+
?? normalizeQuaternion(orientationInput, current.orientationIcrs ?? IDENTITY_QUATERNION);
|
|
373
392
|
return createSpatialPoseTransition({
|
|
374
393
|
from: {
|
|
375
394
|
position: current.observerPc,
|
|
@@ -391,7 +410,7 @@ export function createSkykitNavigationPlugin(options = {}) {
|
|
|
391
410
|
|
|
392
411
|
/**
|
|
393
412
|
* @param {import('./index.d.ts').SkykitJourneyPluginOptions} [options]
|
|
394
|
-
* @returns {
|
|
413
|
+
* @returns {import('./index.d.ts').SkykitJourneyPlugin}
|
|
395
414
|
*/
|
|
396
415
|
export function createSkykitJourneyPlugin(options = {}) {
|
|
397
416
|
const id = options.id ?? 'journey';
|
|
@@ -458,56 +477,81 @@ export function createSkykitJourneyPlugin(options = {}) {
|
|
|
458
477
|
id,
|
|
459
478
|
setup(context) {
|
|
460
479
|
const threeContext = /** @type {import('./index.d.ts').SkykitThreePluginContext} */ (context);
|
|
461
|
-
threeContext.addPart(part);
|
|
462
|
-
|
|
480
|
+
const removePart = threeContext.addPart(part);
|
|
481
|
+
const unregisterActions = registerJourneyActions(threeContext);
|
|
482
|
+
return () => {
|
|
483
|
+
unregisterActions();
|
|
484
|
+
removePart();
|
|
485
|
+
};
|
|
463
486
|
},
|
|
487
|
+
goTo,
|
|
488
|
+
next,
|
|
489
|
+
previous,
|
|
490
|
+
seek,
|
|
491
|
+
play,
|
|
492
|
+
pause,
|
|
464
493
|
getSnapshot,
|
|
465
494
|
};
|
|
466
495
|
|
|
496
|
+
/** @param {unknown} payload */
|
|
497
|
+
async function goTo(payload) {
|
|
498
|
+
await pendingSceneApplication;
|
|
499
|
+
const sceneId = resolveSceneId(payload);
|
|
500
|
+
const spec = sceneId && controller ? controller.goTo(sceneId, { source: SKYKIT_ACTIONS.journey.goToChapter }) : null;
|
|
501
|
+
await pendingSceneApplication;
|
|
502
|
+
return spec;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
async function next() {
|
|
506
|
+
await pendingSceneApplication;
|
|
507
|
+
const spec = controller?.next({ source: SKYKIT_ACTIONS.journey.next }) ?? null;
|
|
508
|
+
await pendingSceneApplication;
|
|
509
|
+
return spec;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
async function previous() {
|
|
513
|
+
await pendingSceneApplication;
|
|
514
|
+
const spec = controller?.previous({ source: SKYKIT_ACTIONS.journey.previous }) ?? null;
|
|
515
|
+
await pendingSceneApplication;
|
|
516
|
+
return spec;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/** @param {unknown} payload */
|
|
520
|
+
function seek(payload) {
|
|
521
|
+
currentTimeSecs = clampTime(resolveTimeSecs(payload), evaluator?.durationSecs ?? Number.POSITIVE_INFINITY);
|
|
522
|
+
if (evaluator && pluginContext) applyTimedFrame(evaluator.evaluate(currentTimeSecs), { viewer: pluginContext.viewer, view: pluginContext.getViewState() });
|
|
523
|
+
if (pluginContext) emitTimedPreloadHints(pluginContext, 'seek');
|
|
524
|
+
return currentTimeSecs;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/** @param {unknown} [payload] */
|
|
528
|
+
function play(payload) {
|
|
529
|
+
if (payload && typeof payload === 'object' && 'timeSecs' in payload) {
|
|
530
|
+
currentTimeSecs = clampTime(resolveTimeSecs(payload), evaluator?.durationSecs ?? Number.POSITIVE_INFINITY);
|
|
531
|
+
}
|
|
532
|
+
playing = true;
|
|
533
|
+
if (pluginContext) emitTimedPreloadHints(pluginContext, 'play');
|
|
534
|
+
return currentTimeSecs;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
function pause() {
|
|
538
|
+
playing = false;
|
|
539
|
+
return currentTimeSecs;
|
|
540
|
+
}
|
|
541
|
+
|
|
467
542
|
/** @param {import('./index.d.ts').SkykitThreePluginContext} context */
|
|
468
543
|
function registerJourneyActions(context) {
|
|
469
544
|
const unregisters = [
|
|
470
|
-
context.actions.registerAction(SKYKIT_ACTIONS.journey.goToChapter,
|
|
471
|
-
|
|
472
|
-
const sceneId = resolveSceneId(payload);
|
|
473
|
-
const spec = sceneId && controller ? controller.goTo(sceneId, { source: SKYKIT_ACTIONS.journey.goToChapter }) : null;
|
|
474
|
-
await pendingSceneApplication;
|
|
475
|
-
return spec;
|
|
476
|
-
}, { label: 'Go to journey chapter' }),
|
|
477
|
-
context.actions.registerAction(SKYKIT_ACTIONS.journey.next, async () => {
|
|
478
|
-
await pendingSceneApplication;
|
|
479
|
-
const spec = controller?.next({ source: SKYKIT_ACTIONS.journey.next }) ?? null;
|
|
480
|
-
await pendingSceneApplication;
|
|
481
|
-
return spec;
|
|
482
|
-
}, {
|
|
545
|
+
context.actions.registerAction(SKYKIT_ACTIONS.journey.goToChapter, ({ payload }) => goTo(payload), { label: 'Go to journey chapter' }),
|
|
546
|
+
context.actions.registerAction(SKYKIT_ACTIONS.journey.next, () => next(), {
|
|
483
547
|
label: 'Next journey chapter',
|
|
484
548
|
}),
|
|
485
|
-
context.actions.registerAction(SKYKIT_ACTIONS.journey.previous,
|
|
486
|
-
await pendingSceneApplication;
|
|
487
|
-
const spec = controller?.previous({ source: SKYKIT_ACTIONS.journey.previous }) ?? null;
|
|
488
|
-
await pendingSceneApplication;
|
|
489
|
-
return spec;
|
|
490
|
-
}, {
|
|
549
|
+
context.actions.registerAction(SKYKIT_ACTIONS.journey.previous, () => previous(), {
|
|
491
550
|
label: 'Previous journey chapter',
|
|
492
551
|
}),
|
|
493
|
-
context.actions.registerAction(SKYKIT_ACTIONS.journey.seek, ({ payload }) => {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
emitTimedPreloadHints(context, 'seek');
|
|
497
|
-
return currentTimeSecs;
|
|
498
|
-
}, { label: 'Seek journey time' }),
|
|
499
|
-
context.actions.registerAction(SKYKIT_ACTIONS.journey.play, ({ payload }) => {
|
|
500
|
-
if (payload && typeof payload === 'object' && 'timeSecs' in payload) {
|
|
501
|
-
currentTimeSecs = clampTime(resolveTimeSecs(payload), evaluator?.durationSecs ?? Number.POSITIVE_INFINITY);
|
|
502
|
-
}
|
|
503
|
-
playing = true;
|
|
504
|
-
emitTimedPreloadHints(context, 'play');
|
|
505
|
-
return currentTimeSecs;
|
|
506
|
-
}, { label: 'Play journey' }),
|
|
507
|
-
context.actions.registerAction(SKYKIT_ACTIONS.journey.pause, () => {
|
|
508
|
-
playing = false;
|
|
509
|
-
return currentTimeSecs;
|
|
510
|
-
}, { label: 'Pause journey' }),
|
|
552
|
+
context.actions.registerAction(SKYKIT_ACTIONS.journey.seek, ({ payload }) => seek(payload), { label: 'Seek journey time' }),
|
|
553
|
+
context.actions.registerAction(SKYKIT_ACTIONS.journey.play, ({ payload }) => play(payload), { label: 'Play journey' }),
|
|
554
|
+
context.actions.registerAction(SKYKIT_ACTIONS.journey.pause, () => pause(), { label: 'Pause journey' }),
|
|
511
555
|
];
|
|
512
556
|
return () => {
|
|
513
557
|
for (const unregister of unregisters.reverse()) unregister();
|
package/src/story.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { SkykitBrowser, SkykitBrowserHost, SkykitBrowserOptions } from './browser.js';
|
|
2
|
+
import type { SkykitViewState, SkykitViewer, Vector3Like } from './index.js';
|
|
3
|
+
|
|
4
|
+
export type SkykitStoryHost = SkykitBrowserHost;
|
|
5
|
+
|
|
6
|
+
export interface SkykitStoryChapterInput {
|
|
7
|
+
id?: string;
|
|
8
|
+
title?: string;
|
|
9
|
+
body?: string;
|
|
10
|
+
bodyHtml?: string | null;
|
|
11
|
+
targetPc?: Vector3Like | null;
|
|
12
|
+
observerPc?: Vector3Like | null;
|
|
13
|
+
view?: Partial<SkykitViewState> | null;
|
|
14
|
+
annotations?: unknown[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface SkykitStoryChapter {
|
|
18
|
+
id: string;
|
|
19
|
+
title: string;
|
|
20
|
+
body: string;
|
|
21
|
+
bodyHtml: string | null;
|
|
22
|
+
targetPc: Vector3Like | null;
|
|
23
|
+
observerPc: Vector3Like | null;
|
|
24
|
+
view: Partial<SkykitViewState> | null;
|
|
25
|
+
annotations: unknown[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface SkykitStoryOptions extends SkykitBrowserOptions {
|
|
29
|
+
host?: SkykitStoryHost;
|
|
30
|
+
src?: string;
|
|
31
|
+
chapters?: Iterable<SkykitStoryChapterInput>;
|
|
32
|
+
initialChapter?: string | number;
|
|
33
|
+
controls?: boolean;
|
|
34
|
+
previousLabel?: string;
|
|
35
|
+
nextLabel?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface SkykitStory {
|
|
39
|
+
browser: SkykitBrowser;
|
|
40
|
+
viewer: SkykitViewer;
|
|
41
|
+
chapters: SkykitStoryChapter[];
|
|
42
|
+
readonly currentIndex: number;
|
|
43
|
+
readonly currentChapter: SkykitStoryChapter | null;
|
|
44
|
+
next(): SkykitStoryChapter | null;
|
|
45
|
+
previous(): SkykitStoryChapter | null;
|
|
46
|
+
goTo(indexOrId: number | string): SkykitStoryChapter | null;
|
|
47
|
+
dispose(): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export declare function createSkykitStory(
|
|
51
|
+
host: SkykitStoryHost,
|
|
52
|
+
options?: SkykitStoryOptions
|
|
53
|
+
): Promise<SkykitStory>;
|
|
54
|
+
|
|
55
|
+
export declare function createSkykitStory(
|
|
56
|
+
options?: SkykitStoryOptions
|
|
57
|
+
): Promise<SkykitStory>;
|