@webspatial/core-sdk 0.1.10 → 0.1.13
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/CHANGELOG.md +20 -0
- package/dist/iife/index.d.ts +730 -0
- package/dist/iife/index.global.js +11 -0
- package/dist/iife/index.global.js.map +1 -0
- package/dist/index.d.ts +20 -2
- package/dist/index.js +845 -825
- package/dist/index.js.map +1 -1
- package/package.json +9 -2
- package/src/core/Spatial.ts +6 -6
- package/src/core/SpatialHelper.ts +4 -0
- package/src/core/SpatialWindowContainer.ts +6 -0
- package/src/core/component/SpatialWindowComponent.ts +11 -3
- package/src/core/private/WebSpatial.ts +36 -9
- package/src/types/global.d.ts +12 -0
- package/tsconfig.json +1 -1
- package/tsup.config.ts +29 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
(function(){
|
|
3
|
+
if(typeof window === 'undefined') return;
|
|
4
|
+
if(!window.__webspatialsdk__) window.__webspatialsdk__ = {}
|
|
5
|
+
window.__webspatialsdk__['core-sdk-version'] = "0.1.13"
|
|
6
|
+
})()
|
|
7
|
+
|
|
8
|
+
|
|
1
9
|
// src/core/private/remote-command/RemoteCommand.ts
|
|
2
10
|
var RemoteCommand = class _RemoteCommand {
|
|
3
11
|
static requestCounter = 0;
|
|
@@ -35,7 +43,6 @@ var WebSpatial = class _WebSpatial {
|
|
|
35
43
|
delete this.eventReceivers[resourceId];
|
|
36
44
|
}
|
|
37
45
|
static init() {
|
|
38
|
-
;
|
|
39
46
|
window.__SpatialWebEvent = (e) => {
|
|
40
47
|
if (e.resourceId) {
|
|
41
48
|
var callback = _WebSpatial.eventReceivers[e.resourceId];
|
|
@@ -84,12 +91,10 @@ var WebSpatial = class _WebSpatial {
|
|
|
84
91
|
}
|
|
85
92
|
var msg = JSON.stringify(cmd);
|
|
86
93
|
if (_WebSpatial.getBackend() == "AVP") {
|
|
87
|
-
;
|
|
88
94
|
window.webkit.messageHandlers.bridge.postMessage(msg);
|
|
89
95
|
return;
|
|
90
96
|
} else {
|
|
91
|
-
;
|
|
92
|
-
window.bridge.nativeMessage(msg);
|
|
97
|
+
window.__WebSpatialData.androidNativeMessage(msg);
|
|
93
98
|
return;
|
|
94
99
|
}
|
|
95
100
|
}
|
|
@@ -475,1011 +480,1026 @@ var SpatialComponent = class extends SpatialObject {
|
|
|
475
480
|
}
|
|
476
481
|
};
|
|
477
482
|
|
|
478
|
-
// src/core/
|
|
479
|
-
var
|
|
480
|
-
/**
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
*/
|
|
484
|
-
async loadURL(url) {
|
|
485
|
-
await WebSpatial.updateResource(this._resource, { url });
|
|
486
|
-
}
|
|
487
|
-
async setFromWindow(window2) {
|
|
488
|
-
if (window2._webSpatialID) {
|
|
489
|
-
await WebSpatial.updateResource(this._resource, {
|
|
490
|
-
windowID: window2._webSpatialID
|
|
491
|
-
});
|
|
492
|
-
} else {
|
|
493
|
-
await console.warn(
|
|
494
|
-
"failed to call setFromWindow, window provided is not valid"
|
|
495
|
-
);
|
|
496
|
-
}
|
|
483
|
+
// src/core/SpatialWindowContainer.ts
|
|
484
|
+
var SpatialWindowContainer = class {
|
|
485
|
+
/** @hidden */
|
|
486
|
+
constructor(_wg) {
|
|
487
|
+
this._wg = _wg;
|
|
497
488
|
}
|
|
498
489
|
/**
|
|
499
|
-
*
|
|
500
|
-
*
|
|
501
|
-
*
|
|
502
|
-
* @param width width in pixels
|
|
503
|
-
* @param height height in pixels
|
|
490
|
+
* @hidden
|
|
491
|
+
* Sets sets the open configuration for opening new window containers
|
|
492
|
+
* @param options style options
|
|
504
493
|
*/
|
|
505
|
-
async
|
|
506
|
-
await WebSpatial.
|
|
507
|
-
|
|
494
|
+
async _setOpenSettings(options) {
|
|
495
|
+
await WebSpatial.updateWindowContainer(this._wg, {
|
|
496
|
+
nextOpenSettings: options
|
|
508
497
|
});
|
|
509
498
|
}
|
|
510
499
|
/**
|
|
511
|
-
*
|
|
512
|
-
* @
|
|
500
|
+
* Retrieves the root entity of the windowContainer
|
|
501
|
+
* @returns the root entity of the windowContainer if one exists
|
|
513
502
|
*/
|
|
514
|
-
async
|
|
515
|
-
await WebSpatial.
|
|
516
|
-
|
|
503
|
+
async getRootEntity() {
|
|
504
|
+
let reqResp = await WebSpatial.updateWindowContainer(this._wg, {
|
|
505
|
+
getRootEntityID: ""
|
|
517
506
|
});
|
|
507
|
+
if (reqResp.data.rootEntId === "") {
|
|
508
|
+
return null;
|
|
509
|
+
} else {
|
|
510
|
+
var res = new WebSpatialResource();
|
|
511
|
+
res.id = reqResp.data.rootEntId;
|
|
512
|
+
return new SpatialEntity(res);
|
|
513
|
+
}
|
|
518
514
|
}
|
|
519
|
-
|
|
520
|
-
*
|
|
521
|
-
* @param
|
|
515
|
+
/*
|
|
516
|
+
* Sets the root entity that this windowContainer will display (this does not effect resource ownership)
|
|
517
|
+
* @param entity to display
|
|
522
518
|
*/
|
|
523
|
-
async
|
|
524
|
-
await
|
|
525
|
-
|
|
519
|
+
async setRootEntity(entity) {
|
|
520
|
+
await entity._setParentWindowContainer(this);
|
|
521
|
+
}
|
|
522
|
+
async close() {
|
|
523
|
+
await WebSpatial.updateWindowContainer(this._wg, {
|
|
524
|
+
close: true
|
|
526
525
|
});
|
|
527
526
|
}
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
// src/core/resource/SpatialMeshResource.ts
|
|
530
|
+
var SpatialMeshResource = class extends SpatialObject {
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
// src/core/resource/SpatialPhysicallyBasedMaterialResource.ts
|
|
534
|
+
var SpatialPhysicallyBasedMaterialResource = class extends SpatialObject {
|
|
528
535
|
/**
|
|
529
|
-
*
|
|
530
|
-
* @param options style options
|
|
536
|
+
* Base color of the material containing rgba between 0 and 1
|
|
531
537
|
*/
|
|
532
|
-
|
|
533
|
-
const { material, cornerRadius } = styleParam;
|
|
534
|
-
const options = {};
|
|
535
|
-
if (material?.type) {
|
|
536
|
-
options.backgroundMaterial = material.type;
|
|
537
|
-
}
|
|
538
|
-
if (cornerRadius !== void 0) {
|
|
539
|
-
if (typeof cornerRadius === "number") {
|
|
540
|
-
options.cornerRadius = {
|
|
541
|
-
topLeading: cornerRadius,
|
|
542
|
-
bottomLeading: cornerRadius,
|
|
543
|
-
topTrailing: cornerRadius,
|
|
544
|
-
bottomTrailing: cornerRadius
|
|
545
|
-
};
|
|
546
|
-
} else {
|
|
547
|
-
options.cornerRadius = { ...cornerRadius };
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
if (document && document.readyState == "loading") {
|
|
551
|
-
var encoded = encodeURIComponent(JSON.stringify(options));
|
|
552
|
-
var x = document.createElement("link");
|
|
553
|
-
x.rel = "stylesheet";
|
|
554
|
-
x.href = "forceStyle://mystyle.css?style=" + encoded;
|
|
555
|
-
document.head.appendChild(x);
|
|
556
|
-
}
|
|
557
|
-
await WebSpatial.updateResource(this._resource, { style: options });
|
|
558
|
-
}
|
|
538
|
+
baseColor = { r: 0, g: 0.7, b: 0.7, a: 1 };
|
|
559
539
|
/**
|
|
560
|
-
*
|
|
561
|
-
* Should only be used internally
|
|
562
|
-
* See https://developer.apple.com/documentation/uikit/1624475-uiedgeinsetsmake?language=objc
|
|
563
|
-
* @param insets margin to modify scroll distances by
|
|
540
|
+
* PBR metalic value between 0 and 1
|
|
564
541
|
*/
|
|
565
|
-
|
|
566
|
-
await WebSpatial.updateResource(this._resource, {
|
|
567
|
-
setScrollEdgeInsets: insets
|
|
568
|
-
});
|
|
569
|
-
}
|
|
542
|
+
metallic = { value: 0.5 };
|
|
570
543
|
/**
|
|
571
|
-
*
|
|
572
|
-
* @param enabled value to set
|
|
544
|
+
* PBR roughness value between 0 and 1
|
|
573
545
|
*/
|
|
574
|
-
|
|
575
|
-
|
|
546
|
+
roughness = { value: 0.5 };
|
|
547
|
+
_modelComponentAttachedTo = {};
|
|
548
|
+
_addToComponent(c) {
|
|
549
|
+
this._modelComponentAttachedTo[c._resource.id] = c;
|
|
576
550
|
}
|
|
577
551
|
/**
|
|
578
|
-
*
|
|
579
|
-
* @param scrollWithParent value to set
|
|
552
|
+
* Syncs state of color, metallic, roupghness to the renderer
|
|
580
553
|
*/
|
|
581
|
-
async
|
|
554
|
+
async update() {
|
|
582
555
|
await WebSpatial.updateResource(this._resource, {
|
|
583
|
-
|
|
556
|
+
baseColor: this.baseColor,
|
|
557
|
+
metallic: this.metallic,
|
|
558
|
+
roughness: this.roughness
|
|
584
559
|
});
|
|
560
|
+
for (var key in this._modelComponentAttachedTo) {
|
|
561
|
+
await this._modelComponentAttachedTo[key]._syncMaterials();
|
|
562
|
+
}
|
|
585
563
|
}
|
|
586
564
|
};
|
|
587
565
|
|
|
588
|
-
// src/core/
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
WebSpatial.registerEventReceiver(_resource.id, (data) => {
|
|
594
|
-
this.onRecvEvent(data);
|
|
595
|
-
});
|
|
596
|
-
}
|
|
597
|
-
async onDestroy() {
|
|
598
|
-
WebSpatial.unregisterEventReceiver(this._resource.id);
|
|
566
|
+
// src/core/SpatialSession.ts
|
|
567
|
+
function _parseParentResources(options) {
|
|
568
|
+
var parentWindowContainer = null;
|
|
569
|
+
if (options?.windowContainer !== null) {
|
|
570
|
+
parentWindowContainer = options?.windowContainer ? options?.windowContainer._wg : WebSpatial.getCurrentWindowContainer();
|
|
599
571
|
}
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
var SpatialInputComponent = class extends EventSpatialComponent {
|
|
604
|
-
onRecvEvent(data) {
|
|
605
|
-
this.onTranslate(data);
|
|
572
|
+
var parentWindow = null;
|
|
573
|
+
if (options?.windowComponent !== null) {
|
|
574
|
+
parentWindow = options?.windowComponent ? options?.windowComponent._resource : WebSpatial.getCurrentWebPanel();
|
|
606
575
|
}
|
|
576
|
+
return [parentWindowContainer, parentWindow];
|
|
577
|
+
}
|
|
578
|
+
var SpatialSession = class _SpatialSession {
|
|
579
|
+
/** @hidden */
|
|
580
|
+
_engineUpdateListeners = Array();
|
|
581
|
+
/** @hidden */
|
|
582
|
+
_frameLoopStarted = false;
|
|
607
583
|
/**
|
|
608
|
-
*
|
|
609
|
-
* @param
|
|
584
|
+
* Add event listener callback to be called each frame
|
|
585
|
+
* @param callback callback to be called each update
|
|
610
586
|
*/
|
|
611
|
-
|
|
587
|
+
addOnEngineUpdateEventListener(callback) {
|
|
588
|
+
this._engineUpdateListeners.push(callback);
|
|
589
|
+
if (!this._frameLoopStarted) {
|
|
590
|
+
this._frameLoopStarted = true;
|
|
591
|
+
WebSpatial.onFrame(async (time) => {
|
|
592
|
+
await Promise.all(
|
|
593
|
+
this._engineUpdateListeners.map((cb) => {
|
|
594
|
+
return cb(time);
|
|
595
|
+
})
|
|
596
|
+
);
|
|
597
|
+
});
|
|
598
|
+
}
|
|
612
599
|
}
|
|
613
|
-
};
|
|
614
|
-
|
|
615
|
-
// src/core/component/SpatialModelComponent.ts
|
|
616
|
-
var SpatialModelComponent = class extends SpatialComponent {
|
|
617
|
-
cachedMaterials = new Array();
|
|
618
600
|
/**
|
|
619
|
-
*
|
|
620
|
-
* @
|
|
601
|
+
* Creates a Entity
|
|
602
|
+
* @returns Entity
|
|
621
603
|
*/
|
|
622
|
-
async
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
604
|
+
async createEntity(options) {
|
|
605
|
+
var [parentWindowContainer, parentWindow] = _parseParentResources(options);
|
|
606
|
+
let entity = await WebSpatial.createResource(
|
|
607
|
+
"Entity",
|
|
608
|
+
parentWindowContainer,
|
|
609
|
+
parentWindow
|
|
610
|
+
);
|
|
611
|
+
return new SpatialEntity(entity);
|
|
626
612
|
}
|
|
627
613
|
/**
|
|
628
|
-
*
|
|
629
|
-
*
|
|
614
|
+
* Creates a WindowComponent
|
|
615
|
+
* [TODO] should creation of components be moved to entity? and these made private?
|
|
616
|
+
* @returns WindowComponent
|
|
630
617
|
*/
|
|
631
|
-
async
|
|
632
|
-
|
|
633
|
-
await WebSpatial.
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
}
|
|
640
|
-
/** @hidden */
|
|
641
|
-
async _syncMaterials() {
|
|
642
|
-
await this.setMaterials(this.cachedMaterials);
|
|
618
|
+
async createWindowComponent(options) {
|
|
619
|
+
var [parentWindowContainer, parentWindow] = _parseParentResources(options);
|
|
620
|
+
let entity = await WebSpatial.createResource(
|
|
621
|
+
"SpatialWebView",
|
|
622
|
+
parentWindowContainer,
|
|
623
|
+
parentWindow
|
|
624
|
+
);
|
|
625
|
+
return new SpatialWindowComponent(entity);
|
|
643
626
|
}
|
|
644
|
-
};
|
|
645
|
-
|
|
646
|
-
// src/core/component/SpatialViewComponent.ts
|
|
647
|
-
var SpatialViewComponent = class extends SpatialComponent {
|
|
648
627
|
/**
|
|
649
|
-
*
|
|
628
|
+
* Creates a ViewComponent used to display 3D content within the entity
|
|
629
|
+
* @returns SpatialViewComponent
|
|
650
630
|
*/
|
|
651
|
-
async
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
631
|
+
async createViewComponent(options) {
|
|
632
|
+
var [parentWindowContainer, parentWindow] = _parseParentResources(options);
|
|
633
|
+
let entity = await WebSpatial.createResource(
|
|
634
|
+
"SpatialView",
|
|
635
|
+
parentWindowContainer,
|
|
636
|
+
parentWindow
|
|
637
|
+
);
|
|
638
|
+
return new SpatialViewComponent(entity);
|
|
655
639
|
}
|
|
656
640
|
/**
|
|
657
|
-
*
|
|
658
|
-
*
|
|
641
|
+
* Creates a ModelComponent used to display geometry + material of a 3D model
|
|
642
|
+
* @returns ModelComponent
|
|
659
643
|
*/
|
|
660
|
-
async
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
};
|
|
666
|
-
|
|
667
|
-
// src/core/component/SpatialModel3DComponent.ts
|
|
668
|
-
var SpatialModel3DComponent = class extends EventSpatialComponent {
|
|
669
|
-
onRecvEvent(data) {
|
|
670
|
-
const { eventType, value, error } = data;
|
|
671
|
-
switch (eventType) {
|
|
672
|
-
case "phase":
|
|
673
|
-
if (value === "success") {
|
|
674
|
-
this.onSuccess?.();
|
|
675
|
-
} else {
|
|
676
|
-
this.onFailure?.(error);
|
|
677
|
-
}
|
|
678
|
-
break;
|
|
679
|
-
case "dragstart":
|
|
680
|
-
this._onDragStart?.(value);
|
|
681
|
-
break;
|
|
682
|
-
case "dragend":
|
|
683
|
-
this._onDragEnd?.(value);
|
|
684
|
-
break;
|
|
685
|
-
case "drag":
|
|
686
|
-
this._onDrag?.(value);
|
|
687
|
-
break;
|
|
688
|
-
case "tap":
|
|
689
|
-
this._onTap?.();
|
|
690
|
-
break;
|
|
691
|
-
case "doubletap":
|
|
692
|
-
this._onDoubleTap?.();
|
|
693
|
-
break;
|
|
694
|
-
case "longpress":
|
|
695
|
-
this._onLongPress?.();
|
|
696
|
-
break;
|
|
697
|
-
default:
|
|
698
|
-
break;
|
|
644
|
+
async createModelComponent(options) {
|
|
645
|
+
var [parentWindowContainer, parentWindow] = _parseParentResources(options);
|
|
646
|
+
var opts = void 0;
|
|
647
|
+
if (options) {
|
|
648
|
+
opts = { modelURL: options.url };
|
|
699
649
|
}
|
|
650
|
+
let entity = await WebSpatial.createResource(
|
|
651
|
+
"ModelComponent",
|
|
652
|
+
parentWindowContainer,
|
|
653
|
+
parentWindow,
|
|
654
|
+
opts
|
|
655
|
+
);
|
|
656
|
+
return new SpatialModelComponent(entity);
|
|
700
657
|
}
|
|
701
658
|
/**
|
|
702
|
-
*
|
|
659
|
+
* Creates a Model3DComponent
|
|
660
|
+
* @returns Model3DComponent
|
|
703
661
|
*/
|
|
704
|
-
async
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
await WebSpatial.
|
|
711
|
-
|
|
712
|
-
|
|
662
|
+
async createModel3DComponent(options) {
|
|
663
|
+
var [parentWindowContainer, parentWindow] = _parseParentResources(options);
|
|
664
|
+
var opts = void 0;
|
|
665
|
+
if (options) {
|
|
666
|
+
opts = { modelURL: options.url };
|
|
667
|
+
}
|
|
668
|
+
let entity = await WebSpatial.createResource(
|
|
669
|
+
"Model3DComponent",
|
|
670
|
+
parentWindowContainer,
|
|
671
|
+
parentWindow,
|
|
672
|
+
opts
|
|
673
|
+
);
|
|
674
|
+
return new SpatialModel3DComponent(entity);
|
|
713
675
|
}
|
|
714
676
|
/**
|
|
715
|
-
*
|
|
716
|
-
*
|
|
677
|
+
* Creates a InputComponent
|
|
678
|
+
* [Experimental] Creates a InputComponent used to handle click and drag events of the entity containing a model
|
|
679
|
+
* @returns InputComponent
|
|
717
680
|
*/
|
|
718
|
-
async
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
681
|
+
async createInputComponent(options) {
|
|
682
|
+
var [parentWindowContainer, parentWindow] = _parseParentResources(options);
|
|
683
|
+
let entity = await WebSpatial.createResource(
|
|
684
|
+
"InputComponent",
|
|
685
|
+
parentWindowContainer,
|
|
686
|
+
parentWindow
|
|
687
|
+
);
|
|
688
|
+
return new SpatialInputComponent(entity);
|
|
722
689
|
}
|
|
723
690
|
/**
|
|
724
|
-
*
|
|
725
|
-
* @
|
|
691
|
+
* Creates a MeshResource containing geometry data
|
|
692
|
+
* @returns MeshResource
|
|
726
693
|
*/
|
|
727
|
-
async
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
694
|
+
async createMeshResource(options) {
|
|
695
|
+
var [parentWindowContainer, parentWindow] = _parseParentResources(options);
|
|
696
|
+
let entity = await WebSpatial.createResource(
|
|
697
|
+
"MeshResource",
|
|
698
|
+
parentWindowContainer,
|
|
699
|
+
parentWindow,
|
|
700
|
+
options
|
|
701
|
+
);
|
|
702
|
+
return new SpatialMeshResource(entity);
|
|
731
703
|
}
|
|
732
704
|
/**
|
|
733
|
-
*
|
|
734
|
-
*
|
|
735
|
-
*
|
|
736
|
-
* @param aspectRatio number
|
|
705
|
+
* Creates a PhysicallyBasedMaterial containing PBR material data
|
|
706
|
+
* @returns PhysicallyBasedMaterial
|
|
737
707
|
*/
|
|
738
|
-
async
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
708
|
+
async createPhysicallyBasedMaterialResource(options) {
|
|
709
|
+
var [parentWindowContainer, parentWindow] = _parseParentResources(options);
|
|
710
|
+
let entity = await WebSpatial.createResource(
|
|
711
|
+
"PhysicallyBasedMaterial",
|
|
712
|
+
parentWindowContainer,
|
|
713
|
+
parentWindow,
|
|
714
|
+
options
|
|
715
|
+
);
|
|
716
|
+
return new SpatialPhysicallyBasedMaterialResource(entity);
|
|
742
717
|
}
|
|
743
718
|
/**
|
|
744
|
-
*
|
|
745
|
-
* @
|
|
746
|
-
*/
|
|
747
|
-
async
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
719
|
+
* Creates a WindowContainer
|
|
720
|
+
* @returns SpatialWindowContainer
|
|
721
|
+
* */
|
|
722
|
+
async createWindowContainer(options) {
|
|
723
|
+
var style = options?.style ? options?.style : "Plain";
|
|
724
|
+
var [parentWindowContainer, parentWindow] = _parseParentResources(options);
|
|
725
|
+
return new SpatialWindowContainer(
|
|
726
|
+
await WebSpatial.createWindowContainer(
|
|
727
|
+
style,
|
|
728
|
+
parentWindowContainer,
|
|
729
|
+
parentWindow
|
|
730
|
+
)
|
|
731
|
+
);
|
|
751
732
|
}
|
|
752
733
|
/**
|
|
753
|
-
*
|
|
754
|
-
* @
|
|
734
|
+
* Creates a Scene to display content within an anchored area managed by the OS
|
|
735
|
+
* @hidden
|
|
736
|
+
* @param {WindowStyle} [style='Plain'] - The style of the Scene container to be created with. Defaults to 'Plain'.
|
|
737
|
+
* @param {Object} [cfg={}] - Configuration object for the Scene.
|
|
738
|
+
* @returns Boolean
|
|
755
739
|
*/
|
|
756
|
-
async
|
|
757
|
-
await WebSpatial.
|
|
758
|
-
resizable
|
|
759
|
-
});
|
|
740
|
+
async _createScene(style = "Plain", cfg) {
|
|
741
|
+
return await WebSpatial.createScene(style, cfg);
|
|
760
742
|
}
|
|
761
743
|
/**
|
|
762
|
-
*
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
/**
|
|
766
|
-
* Callback fired when model load failure
|
|
767
|
-
* @param errorReason
|
|
744
|
+
* Retrieves the window for this page
|
|
745
|
+
* @returns the window component corresponding to the js running on this page
|
|
746
|
+
* [TODO] discuss implications of this not being async
|
|
768
747
|
*/
|
|
769
|
-
|
|
748
|
+
getCurrentWindowComponent() {
|
|
749
|
+
return new SpatialWindowComponent(WebSpatial.getCurrentWebPanel());
|
|
750
|
+
}
|
|
770
751
|
/**
|
|
771
|
-
*
|
|
772
|
-
* @
|
|
752
|
+
* Retrieves the parent window for this page or null if this is the root page
|
|
753
|
+
* @returns the window component or null
|
|
773
754
|
*/
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
755
|
+
async getParentWindowComponent() {
|
|
756
|
+
let parentResp = await WebSpatial.updateResource(
|
|
757
|
+
WebSpatial.getCurrentWebPanel(),
|
|
758
|
+
{ getParentID: "" }
|
|
759
|
+
);
|
|
760
|
+
if (parentResp.data.parentID === "") {
|
|
761
|
+
return new Promise((res2, rej) => {
|
|
762
|
+
res2(null);
|
|
780
763
|
});
|
|
764
|
+
} else {
|
|
765
|
+
var res = new WebSpatialResource();
|
|
766
|
+
res.id = parentResp.data.parentID;
|
|
767
|
+
return new SpatialWindowComponent(res);
|
|
781
768
|
}
|
|
782
769
|
}
|
|
783
770
|
/**
|
|
784
|
-
*
|
|
785
|
-
* @param
|
|
771
|
+
* Logs a message to the native apps console
|
|
772
|
+
* @param msg mesage to log
|
|
786
773
|
*/
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
})
|
|
794
|
-
|
|
774
|
+
async log(...msg) {
|
|
775
|
+
await WebSpatial.sendCommand(
|
|
776
|
+
new RemoteCommand("log", {
|
|
777
|
+
logString: msg.map((x) => {
|
|
778
|
+
return JSON.stringify(x);
|
|
779
|
+
})
|
|
780
|
+
})
|
|
781
|
+
);
|
|
795
782
|
}
|
|
796
783
|
/**
|
|
797
|
-
*
|
|
798
|
-
*
|
|
784
|
+
* @hidden
|
|
785
|
+
* Debugging only, used to ping the native renderer
|
|
799
786
|
*/
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
if (this._onDragEnd !== callback) {
|
|
803
|
-
this._onDragEnd = callback;
|
|
804
|
-
WebSpatial.updateResource(this._resource, {
|
|
805
|
-
enableDragEvent: this.enableDragEvent
|
|
806
|
-
});
|
|
807
|
-
}
|
|
787
|
+
async _ping(msg) {
|
|
788
|
+
return await WebSpatial.ping(msg);
|
|
808
789
|
}
|
|
809
|
-
|
|
810
|
-
|
|
790
|
+
/**
|
|
791
|
+
* @hidden
|
|
792
|
+
* Debugging to get internal state from native code
|
|
793
|
+
* @returns data as a js object
|
|
794
|
+
*/
|
|
795
|
+
async _getStats() {
|
|
796
|
+
return await WebSpatial.getStats();
|
|
811
797
|
}
|
|
812
798
|
/**
|
|
813
|
-
*
|
|
799
|
+
* @hidden
|
|
814
800
|
*/
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
if (this._onTap !== callback) {
|
|
818
|
-
this._onTap = callback;
|
|
819
|
-
WebSpatial.updateResource(this._resource, {
|
|
820
|
-
enableTapEvent: void 0 !== callback
|
|
821
|
-
});
|
|
822
|
-
}
|
|
801
|
+
async _inspect(spatialObjectId = WebSpatial.getCurrentWebPanel().id) {
|
|
802
|
+
return WebSpatial.inspect(spatialObjectId);
|
|
823
803
|
}
|
|
824
|
-
/** Callback fired when model was double tapped */
|
|
825
|
-
_onDoubleTap;
|
|
826
|
-
set onDoubleTap(callback) {
|
|
827
|
-
if (this._onDoubleTap !== callback) {
|
|
828
|
-
this._onDoubleTap = callback;
|
|
829
|
-
WebSpatial.updateResource(this._resource, {
|
|
830
|
-
enableDoubleTapEvent: void 0 !== callback
|
|
831
|
-
});
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
/** Callback fired when model was long pressed */
|
|
835
|
-
_onLongPress;
|
|
836
|
-
set onLongPress(callback) {
|
|
837
|
-
if (this._onLongPress !== callback) {
|
|
838
|
-
this._onLongPress = callback;
|
|
839
|
-
WebSpatial.updateResource(this._resource, {
|
|
840
|
-
enableLongPressEvent: void 0 !== callback
|
|
841
|
-
});
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
};
|
|
845
|
-
|
|
846
|
-
// src/core/resource/SpatialMeshResource.ts
|
|
847
|
-
var SpatialMeshResource = class extends SpatialObject {
|
|
848
|
-
};
|
|
849
|
-
|
|
850
|
-
// src/core/resource/SpatialPhysicallyBasedMaterialResource.ts
|
|
851
|
-
var SpatialPhysicallyBasedMaterialResource = class extends SpatialObject {
|
|
852
|
-
/**
|
|
853
|
-
* Base color of the material containing rgba between 0 and 1
|
|
854
|
-
*/
|
|
855
|
-
baseColor = { r: 0, g: 0.7, b: 0.7, a: 1 };
|
|
856
804
|
/**
|
|
857
|
-
*
|
|
805
|
+
* @hidden
|
|
858
806
|
*/
|
|
859
|
-
|
|
807
|
+
async _inspectRootWindowContainer() {
|
|
808
|
+
return WebSpatial.inspectRootWindowContainer();
|
|
809
|
+
}
|
|
810
|
+
/** Opens the immersive space */
|
|
811
|
+
async openImmersiveSpace() {
|
|
812
|
+
return await WebSpatial.openImmersiveSpace();
|
|
813
|
+
}
|
|
814
|
+
/** Closes the immersive space */
|
|
815
|
+
async dismissImmersiveSpace() {
|
|
816
|
+
return await WebSpatial.dismissImmersiveSpace();
|
|
817
|
+
}
|
|
818
|
+
static _immersiveWindowContainer = null;
|
|
860
819
|
/**
|
|
861
|
-
*
|
|
820
|
+
* Retreives the window container corresponding to the Immersive space
|
|
821
|
+
* @returns the immersive window container
|
|
862
822
|
*/
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
823
|
+
async getImmersiveWindowContainer() {
|
|
824
|
+
if (_SpatialSession._immersiveWindowContainer) {
|
|
825
|
+
return _SpatialSession._immersiveWindowContainer;
|
|
826
|
+
} else {
|
|
827
|
+
_SpatialSession._immersiveWindowContainer = new SpatialWindowContainer(
|
|
828
|
+
WebSpatial.getImmersiveWindowContainer()
|
|
829
|
+
);
|
|
830
|
+
return _SpatialSession._immersiveWindowContainer;
|
|
831
|
+
}
|
|
867
832
|
}
|
|
833
|
+
// Retreives the window container that is the parent to this spatial web page
|
|
834
|
+
static _currentWindowContainer = null;
|
|
868
835
|
/**
|
|
869
|
-
*
|
|
836
|
+
* Gets the current window container for the window
|
|
837
|
+
* [TODO] discuss what happens if it doesnt yet have a window container
|
|
838
|
+
* @returns the current window container for the window
|
|
870
839
|
*/
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
840
|
+
getCurrentWindowContainer() {
|
|
841
|
+
if (_SpatialSession._currentWindowContainer) {
|
|
842
|
+
return _SpatialSession._currentWindowContainer;
|
|
843
|
+
} else {
|
|
844
|
+
_SpatialSession._currentWindowContainer = new SpatialWindowContainer(
|
|
845
|
+
WebSpatial.getCurrentWindowContainer()
|
|
846
|
+
);
|
|
847
|
+
return _SpatialSession._currentWindowContainer;
|
|
879
848
|
}
|
|
880
849
|
}
|
|
881
|
-
};
|
|
882
|
-
|
|
883
|
-
// src/core/SpatialWindowContainer.ts
|
|
884
|
-
var SpatialWindowContainer = class {
|
|
885
|
-
/** @hidden */
|
|
886
|
-
constructor(_wg) {
|
|
887
|
-
this._wg = _wg;
|
|
888
|
-
}
|
|
889
850
|
/**
|
|
890
|
-
*
|
|
891
|
-
*
|
|
892
|
-
* @
|
|
851
|
+
* Start a transaction that queues up commands to submit them all at once to reduce ipc overhead
|
|
852
|
+
* @param fn function to be run, within this function, promises will not resolve
|
|
853
|
+
* @returns promise for the entire transaction completion
|
|
893
854
|
*/
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
855
|
+
transaction(fn) {
|
|
856
|
+
WebSpatial.startTransaction();
|
|
857
|
+
fn();
|
|
858
|
+
return WebSpatial.sendTransaction();
|
|
898
859
|
}
|
|
899
860
|
/**
|
|
900
|
-
*
|
|
901
|
-
* @returns
|
|
861
|
+
* Creates a window context object that is compatable with SpatialWindowComponent's setFromWindow API
|
|
862
|
+
* @returns window context
|
|
902
863
|
*/
|
|
903
|
-
async
|
|
904
|
-
let
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
864
|
+
async createWindowContext() {
|
|
865
|
+
let openedWindow = window.open("webspatial://createWindowContext");
|
|
866
|
+
if (WebSpatial.getBackend() != "AVP") {
|
|
867
|
+
var counter = 0;
|
|
868
|
+
while (openedWindow.window.testAPI == null) {
|
|
869
|
+
if (counter > 15) {
|
|
870
|
+
openedWindow?.close();
|
|
871
|
+
openedWindow = window.open("about:blank");
|
|
872
|
+
counter = 0;
|
|
873
|
+
this.log("unexpected error when trying to open new window, retrying.");
|
|
874
|
+
}
|
|
875
|
+
var locName = "about:blank?x" + counter;
|
|
876
|
+
openedWindow.location.href = locName;
|
|
877
|
+
counter++;
|
|
878
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
879
|
+
}
|
|
880
|
+
;
|
|
881
|
+
openedWindow._webSpatialID = openedWindow.window.testAPI.getWindowID();
|
|
909
882
|
} else {
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
883
|
+
while (openedWindow.window._webSpatialID == void 0) {
|
|
884
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
885
|
+
}
|
|
913
886
|
}
|
|
887
|
+
openedWindow.document.head.innerHTML = `<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
888
|
+
<base href="${document.baseURI}">
|
|
889
|
+
`;
|
|
890
|
+
return openedWindow;
|
|
914
891
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
892
|
+
// Get Entity by id. Currently for debugging only.
|
|
893
|
+
/** @hidden */
|
|
894
|
+
async _getEntity(id) {
|
|
895
|
+
const entityInfo = await WebSpatial.inspect(id);
|
|
896
|
+
const [_, x, y, z] = entityInfo.position.match(/(\d+\.?\d*)/g);
|
|
897
|
+
const [__, sx, sy, sz] = entityInfo.scale.match(/(\d+\.?\d*)/g);
|
|
898
|
+
var res = new WebSpatialResource();
|
|
899
|
+
res.id = id;
|
|
900
|
+
res.windowContainerId = WebSpatial.getCurrentWindowContainer().id;
|
|
901
|
+
const entity = new SpatialEntity(res);
|
|
902
|
+
entity.transform.position.x = parseFloat(x);
|
|
903
|
+
entity.transform.position.y = parseFloat(y);
|
|
904
|
+
entity.transform.position.z = parseFloat(z);
|
|
905
|
+
entity.transform.scale.x = parseFloat(sx);
|
|
906
|
+
entity.transform.scale.y = parseFloat(sy);
|
|
907
|
+
entity.transform.scale.z = parseFloat(sz);
|
|
908
|
+
return entity;
|
|
909
|
+
}
|
|
910
|
+
// set loading view.
|
|
911
|
+
/** @hidden */
|
|
912
|
+
async setLoading(method, style) {
|
|
913
|
+
return WebSpatial.setLoading(method, style);
|
|
921
914
|
}
|
|
922
915
|
};
|
|
923
916
|
|
|
924
|
-
// src/core/
|
|
925
|
-
|
|
926
|
-
var parentWindowContainer = null;
|
|
927
|
-
if (options?.windowContainer !== null) {
|
|
928
|
-
parentWindowContainer = options?.windowContainer ? options?.windowContainer._wg : WebSpatial.getCurrentWindowContainer();
|
|
929
|
-
}
|
|
930
|
-
var parentWindow = null;
|
|
931
|
-
if (options?.windowComponent !== null) {
|
|
932
|
-
parentWindow = options?.windowComponent ? options?.windowComponent._resource : WebSpatial.getCurrentWebPanel();
|
|
933
|
-
}
|
|
934
|
-
return [parentWindowContainer, parentWindow];
|
|
935
|
-
}
|
|
936
|
-
var SpatialSession = class _SpatialSession {
|
|
937
|
-
/** @hidden */
|
|
938
|
-
_engineUpdateListeners = Array();
|
|
939
|
-
/** @hidden */
|
|
940
|
-
_frameLoopStarted = false;
|
|
917
|
+
// src/core/Spatial.ts
|
|
918
|
+
var Spatial = class {
|
|
941
919
|
/**
|
|
942
|
-
*
|
|
943
|
-
* @
|
|
920
|
+
* Requests a session object from the browser
|
|
921
|
+
* @returns The session or null if not availible in the current browser
|
|
922
|
+
* [TODO] discuss implications of this not being async
|
|
944
923
|
*/
|
|
945
|
-
|
|
946
|
-
this.
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
await Promise.all(
|
|
951
|
-
this._engineUpdateListeners.map((cb) => {
|
|
952
|
-
return cb(time);
|
|
953
|
-
})
|
|
954
|
-
);
|
|
955
|
-
});
|
|
924
|
+
requestSession() {
|
|
925
|
+
if (this.isSupported() && this.getNativeVersion() === this.getClientVersion()) {
|
|
926
|
+
return new SpatialSession();
|
|
927
|
+
} else {
|
|
928
|
+
return null;
|
|
956
929
|
}
|
|
957
930
|
}
|
|
958
931
|
/**
|
|
959
|
-
*
|
|
960
|
-
* @returns Entity
|
|
932
|
+
* @returns true if web spatial is supported by this webpage
|
|
961
933
|
*/
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
let entity = await WebSpatial.createResource(
|
|
965
|
-
"Entity",
|
|
966
|
-
parentWindowContainer,
|
|
967
|
-
parentWindow
|
|
968
|
-
);
|
|
969
|
-
return new SpatialEntity(entity);
|
|
934
|
+
isSupported() {
|
|
935
|
+
return this.getNativeVersion() === this.getClientVersion();
|
|
970
936
|
}
|
|
971
937
|
/**
|
|
972
|
-
*
|
|
973
|
-
*
|
|
974
|
-
* @returns WindowComponent
|
|
938
|
+
* Gets the native version, format is "x.x.x"
|
|
939
|
+
* @returns native version string
|
|
975
940
|
*/
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
parentWindow
|
|
982
|
-
);
|
|
983
|
-
return new SpatialWindowComponent(entity);
|
|
941
|
+
getNativeVersion() {
|
|
942
|
+
if (window.__WebSpatialData && window.__WebSpatialData.getNativeVersion) {
|
|
943
|
+
return window.__WebSpatialData.getNativeVersion();
|
|
944
|
+
}
|
|
945
|
+
return window.WebSpatailNativeVersion;
|
|
984
946
|
}
|
|
985
947
|
/**
|
|
986
|
-
*
|
|
987
|
-
* @returns
|
|
948
|
+
* Gets the client version, format is "x.x.x"
|
|
949
|
+
* @returns client version string
|
|
988
950
|
*/
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
let entity = await WebSpatial.createResource(
|
|
992
|
-
"SpatialView",
|
|
993
|
-
parentWindowContainer,
|
|
994
|
-
parentWindow
|
|
995
|
-
);
|
|
996
|
-
return new SpatialViewComponent(entity);
|
|
951
|
+
getClientVersion() {
|
|
952
|
+
return "0.0.1";
|
|
997
953
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
954
|
+
};
|
|
955
|
+
|
|
956
|
+
// src/core/SpatialHelper.ts
|
|
957
|
+
var SpatialHelper = class _SpatialHelper {
|
|
958
|
+
constructor(session) {
|
|
959
|
+
this.session = session;
|
|
960
|
+
}
|
|
961
|
+
static _instance = null;
|
|
962
|
+
static get instance() {
|
|
963
|
+
if (this._instance) {
|
|
964
|
+
return this._instance;
|
|
965
|
+
} else {
|
|
966
|
+
let spatial = new Spatial();
|
|
967
|
+
if (spatial.isSupported()) {
|
|
968
|
+
let session = spatial.requestSession();
|
|
969
|
+
if (session) {
|
|
970
|
+
this._instance = new _SpatialHelper(session);
|
|
971
|
+
return this._instance;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
1007
974
|
}
|
|
1008
|
-
|
|
1009
|
-
"ModelComponent",
|
|
1010
|
-
parentWindowContainer,
|
|
1011
|
-
parentWindow,
|
|
1012
|
-
opts
|
|
1013
|
-
);
|
|
1014
|
-
return new SpatialModelComponent(entity);
|
|
975
|
+
return null;
|
|
1015
976
|
}
|
|
977
|
+
shape = {
|
|
978
|
+
createShapeEntity: async (shape = "box") => {
|
|
979
|
+
var box = await this.session.createMeshResource({ shape });
|
|
980
|
+
var mat = await this.session.createPhysicallyBasedMaterialResource();
|
|
981
|
+
await mat.update();
|
|
982
|
+
var customModel = await this.session.createModelComponent();
|
|
983
|
+
customModel.setMaterials([mat]);
|
|
984
|
+
customModel.setMesh(box);
|
|
985
|
+
var boxEntity = await this.session.createEntity();
|
|
986
|
+
await boxEntity.setComponent(customModel);
|
|
987
|
+
boxEntity.transform.position.z = 0;
|
|
988
|
+
boxEntity.transform.scale = new Vec3(0.5, 0.5, 0.5);
|
|
989
|
+
await boxEntity.updateTransform();
|
|
990
|
+
return boxEntity;
|
|
991
|
+
},
|
|
992
|
+
createModelEntity: async (url) => {
|
|
993
|
+
var customModel = await this.session.createModelComponent({ url });
|
|
994
|
+
var boxEntity = await this.session.createEntity();
|
|
995
|
+
await boxEntity.setComponent(customModel);
|
|
996
|
+
await boxEntity.updateTransform();
|
|
997
|
+
return boxEntity;
|
|
998
|
+
},
|
|
999
|
+
wrapInBoundingBoxEntity: async (entityToWrap) => {
|
|
1000
|
+
var bb = await entityToWrap.getBoundingBox();
|
|
1001
|
+
var targetSize = 1;
|
|
1002
|
+
var scale = targetSize / Math.max(bb.extents.x, bb.extents.y, bb.extents.z);
|
|
1003
|
+
entityToWrap.transform.scale.x = scale;
|
|
1004
|
+
entityToWrap.transform.scale.y = scale;
|
|
1005
|
+
entityToWrap.transform.scale.z = scale;
|
|
1006
|
+
entityToWrap.transform.position.x = -bb.center.x * scale;
|
|
1007
|
+
entityToWrap.transform.position.y = -bb.center.y * scale;
|
|
1008
|
+
entityToWrap.transform.position.z = -bb.center.z * scale;
|
|
1009
|
+
await entityToWrap.updateTransform();
|
|
1010
|
+
var boudningEntity = await _SpatialHelper.instance?.session.createEntity();
|
|
1011
|
+
await entityToWrap.setParent(boudningEntity);
|
|
1012
|
+
return boudningEntity;
|
|
1013
|
+
}
|
|
1014
|
+
};
|
|
1015
|
+
navigation = {
|
|
1016
|
+
openPanel: async (url, options) => {
|
|
1017
|
+
if (options?.resolution) {
|
|
1018
|
+
await this.session.getCurrentWindowContainer()._setOpenSettings({ resolution: options.resolution });
|
|
1019
|
+
}
|
|
1020
|
+
var wg = await this.session.createWindowContainer({
|
|
1021
|
+
style: "Plain",
|
|
1022
|
+
windowComponent: null,
|
|
1023
|
+
windowContainer: null
|
|
1024
|
+
});
|
|
1025
|
+
var ent = await this.session.createEntity({
|
|
1026
|
+
windowComponent: null,
|
|
1027
|
+
windowContainer: wg
|
|
1028
|
+
});
|
|
1029
|
+
var i = await this.session.createWindowComponent({
|
|
1030
|
+
windowComponent: null,
|
|
1031
|
+
windowContainer: wg
|
|
1032
|
+
});
|
|
1033
|
+
await i.loadURL(url);
|
|
1034
|
+
await ent.setCoordinateSpace("Root");
|
|
1035
|
+
await ent.setComponent(i);
|
|
1036
|
+
await wg.setRootEntity(ent);
|
|
1037
|
+
await this.session.getCurrentWindowContainer()._setOpenSettings({ resolution: { width: 900, height: 700 } });
|
|
1038
|
+
return {
|
|
1039
|
+
windowContainer: wg
|
|
1040
|
+
};
|
|
1041
|
+
},
|
|
1042
|
+
openVolume: async (url, options) => {
|
|
1043
|
+
var wg = await this.session.createWindowContainer({
|
|
1044
|
+
style: "Volumetric",
|
|
1045
|
+
windowComponent: null,
|
|
1046
|
+
windowContainer: null
|
|
1047
|
+
});
|
|
1048
|
+
var rootEnt = await this.session.createEntity({
|
|
1049
|
+
windowComponent: null,
|
|
1050
|
+
windowContainer: wg
|
|
1051
|
+
});
|
|
1052
|
+
await rootEnt.setComponent(
|
|
1053
|
+
await this.session.createViewComponent({
|
|
1054
|
+
windowComponent: null,
|
|
1055
|
+
windowContainer: wg
|
|
1056
|
+
})
|
|
1057
|
+
);
|
|
1058
|
+
await rootEnt.setCoordinateSpace("Root");
|
|
1059
|
+
await wg.setRootEntity(rootEnt);
|
|
1060
|
+
var ent = await this.session.createEntity({
|
|
1061
|
+
windowComponent: null,
|
|
1062
|
+
windowContainer: wg
|
|
1063
|
+
});
|
|
1064
|
+
var i = await this.session.createWindowComponent({
|
|
1065
|
+
windowComponent: null,
|
|
1066
|
+
windowContainer: wg
|
|
1067
|
+
});
|
|
1068
|
+
await i.loadURL(url);
|
|
1069
|
+
if (options?.resolution) {
|
|
1070
|
+
await i.setResolution(
|
|
1071
|
+
options.resolution.width,
|
|
1072
|
+
options.resolution.height
|
|
1073
|
+
);
|
|
1074
|
+
} else {
|
|
1075
|
+
await i.setResolution(1e3, 1e3);
|
|
1076
|
+
}
|
|
1077
|
+
ent.transform.position.z = -0.49;
|
|
1078
|
+
await ent.updateTransform();
|
|
1079
|
+
await ent.setCoordinateSpace("App");
|
|
1080
|
+
await ent.setComponent(i);
|
|
1081
|
+
await ent.setParent(rootEnt);
|
|
1082
|
+
}
|
|
1083
|
+
};
|
|
1084
|
+
dom = {
|
|
1085
|
+
attachSpatialView: async (divOnPage) => {
|
|
1086
|
+
var viewEnt = await this.session.createEntity();
|
|
1087
|
+
await viewEnt.setCoordinateSpace("Dom");
|
|
1088
|
+
await viewEnt.setComponent(await this.session.createViewComponent());
|
|
1089
|
+
var wc = await this.session.getCurrentWindowComponent();
|
|
1090
|
+
var ent = await wc.getEntity();
|
|
1091
|
+
await viewEnt.setParent(ent);
|
|
1092
|
+
var update = () => {
|
|
1093
|
+
var rect = divOnPage.getBoundingClientRect();
|
|
1094
|
+
viewEnt.transform.position.x = rect.x + rect.width / 2;
|
|
1095
|
+
viewEnt.transform.position.y = rect.y + rect.height / 2 + window.scrollY;
|
|
1096
|
+
viewEnt.updateTransform();
|
|
1097
|
+
viewEnt.getComponent(SpatialViewComponent).setResolution(rect.width, rect.height);
|
|
1098
|
+
};
|
|
1099
|
+
var mo = new MutationObserver(update);
|
|
1100
|
+
mo.observe(divOnPage, { attributes: true });
|
|
1101
|
+
var ro = new ResizeObserver(update);
|
|
1102
|
+
ro.observe(divOnPage);
|
|
1103
|
+
const addRemoveObserver = new MutationObserver((mutations) => {
|
|
1104
|
+
mutations.forEach((mutation) => {
|
|
1105
|
+
mutation.removedNodes.forEach((node) => {
|
|
1106
|
+
if (node instanceof HTMLElement) {
|
|
1107
|
+
update();
|
|
1108
|
+
}
|
|
1109
|
+
});
|
|
1110
|
+
mutation.addedNodes.forEach((node) => {
|
|
1111
|
+
if (node instanceof HTMLElement) {
|
|
1112
|
+
update();
|
|
1113
|
+
}
|
|
1114
|
+
});
|
|
1115
|
+
});
|
|
1116
|
+
});
|
|
1117
|
+
addRemoveObserver.observe(document.body, {
|
|
1118
|
+
childList: true,
|
|
1119
|
+
subtree: true
|
|
1120
|
+
});
|
|
1121
|
+
update();
|
|
1122
|
+
return {
|
|
1123
|
+
entity: viewEnt
|
|
1124
|
+
};
|
|
1125
|
+
}
|
|
1126
|
+
};
|
|
1127
|
+
setBackgroundStyle = async (style, backgroundColor = "#00000000") => {
|
|
1128
|
+
document.documentElement.style.backgroundColor = backgroundColor;
|
|
1129
|
+
await this.session.getCurrentWindowComponent().setStyle(style);
|
|
1130
|
+
};
|
|
1131
|
+
};
|
|
1132
|
+
|
|
1133
|
+
// src/core/component/SpatialWindowComponent.ts
|
|
1134
|
+
var SpatialWindowComponent = class extends SpatialComponent {
|
|
1016
1135
|
/**
|
|
1017
|
-
*
|
|
1018
|
-
* @
|
|
1136
|
+
* Loads a url page in the window
|
|
1137
|
+
* @param url url to load
|
|
1019
1138
|
*/
|
|
1020
|
-
async
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1139
|
+
async loadURL(url) {
|
|
1140
|
+
await WebSpatial.updateResource(this._resource, { url });
|
|
1141
|
+
}
|
|
1142
|
+
async setFromWindow(window2) {
|
|
1143
|
+
if (window2._webSpatialID) {
|
|
1144
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1145
|
+
windowID: window2._webSpatialID
|
|
1146
|
+
});
|
|
1147
|
+
} else {
|
|
1148
|
+
await console.warn(
|
|
1149
|
+
"failed to call setFromWindow, window provided is not valid"
|
|
1150
|
+
);
|
|
1025
1151
|
}
|
|
1026
|
-
let entity = await WebSpatial.createResource(
|
|
1027
|
-
"Model3DComponent",
|
|
1028
|
-
parentWindowContainer,
|
|
1029
|
-
parentWindow,
|
|
1030
|
-
opts
|
|
1031
|
-
);
|
|
1032
|
-
return new SpatialModel3DComponent(entity);
|
|
1033
1152
|
}
|
|
1034
1153
|
/**
|
|
1035
|
-
*
|
|
1036
|
-
*
|
|
1037
|
-
*
|
|
1154
|
+
* Sets the resolution of the window, the resulting dimensions when rendered will be equal to 1/1360 units
|
|
1155
|
+
* eg. if the resolution is set to 1360x1360 it will be a 1x1 plane
|
|
1156
|
+
* See 1360 in spatialViewUI.swift for how this ratio works
|
|
1157
|
+
* @param width width in pixels
|
|
1158
|
+
* @param height height in pixels
|
|
1038
1159
|
*/
|
|
1039
|
-
async
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
parentWindowContainer,
|
|
1044
|
-
parentWindow
|
|
1045
|
-
);
|
|
1046
|
-
return new SpatialInputComponent(entity);
|
|
1160
|
+
async setResolution(width, height) {
|
|
1161
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1162
|
+
resolution: { x: width, y: height }
|
|
1163
|
+
});
|
|
1047
1164
|
}
|
|
1048
1165
|
/**
|
|
1049
|
-
*
|
|
1050
|
-
* @
|
|
1166
|
+
* [Experimental] Sets the anchor which the entity this is attached to will rotate around
|
|
1167
|
+
* @param rotationAnchor
|
|
1051
1168
|
*/
|
|
1052
|
-
async
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
parentWindowContainer,
|
|
1057
|
-
parentWindow,
|
|
1058
|
-
options
|
|
1059
|
-
);
|
|
1060
|
-
return new SpatialMeshResource(entity);
|
|
1169
|
+
async setRotationAnchor(rotationAnchor) {
|
|
1170
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1171
|
+
rotationAnchor
|
|
1172
|
+
});
|
|
1061
1173
|
}
|
|
1062
1174
|
/**
|
|
1063
|
-
*
|
|
1064
|
-
* @
|
|
1175
|
+
* [Experimental] Sets the opacity of the window after apply material
|
|
1176
|
+
* @param opacity
|
|
1065
1177
|
*/
|
|
1066
|
-
async
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
parentWindowContainer,
|
|
1071
|
-
parentWindow,
|
|
1072
|
-
options
|
|
1073
|
-
);
|
|
1074
|
-
return new SpatialPhysicallyBasedMaterialResource(entity);
|
|
1178
|
+
async setOpacity(opacity) {
|
|
1179
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1180
|
+
opacity
|
|
1181
|
+
});
|
|
1075
1182
|
}
|
|
1076
1183
|
/**
|
|
1077
|
-
*
|
|
1078
|
-
* @
|
|
1079
|
-
|
|
1080
|
-
async
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1184
|
+
* Sets the style that should be applied to the window
|
|
1185
|
+
* @param options style options
|
|
1186
|
+
*/
|
|
1187
|
+
async setStyle(styleParam) {
|
|
1188
|
+
const currentWindowComponent = SpatialHelper.instance?.session.getCurrentWindowComponent();
|
|
1189
|
+
const isSettingSelfStyle = currentWindowComponent?._resource.id == this._resource.id;
|
|
1190
|
+
const { material, cornerRadius } = styleParam;
|
|
1191
|
+
const options = {};
|
|
1192
|
+
if (material?.type) {
|
|
1193
|
+
options.backgroundMaterial = material.type;
|
|
1194
|
+
}
|
|
1195
|
+
if (cornerRadius !== void 0) {
|
|
1196
|
+
if (typeof cornerRadius === "number") {
|
|
1197
|
+
options.cornerRadius = {
|
|
1198
|
+
topLeading: cornerRadius,
|
|
1199
|
+
bottomLeading: cornerRadius,
|
|
1200
|
+
topTrailing: cornerRadius,
|
|
1201
|
+
bottomTrailing: cornerRadius
|
|
1202
|
+
};
|
|
1203
|
+
} else {
|
|
1204
|
+
options.cornerRadius = { ...cornerRadius };
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
if (isSettingSelfStyle && document && document.readyState == "loading") {
|
|
1208
|
+
var encoded = encodeURIComponent(JSON.stringify(options));
|
|
1209
|
+
var x = document.createElement("link");
|
|
1210
|
+
x.rel = "stylesheet";
|
|
1211
|
+
x.href = "forceStyle://mystyle.css?style=" + encoded;
|
|
1212
|
+
document.head.appendChild(x);
|
|
1213
|
+
x.remove();
|
|
1214
|
+
} else {
|
|
1215
|
+
await WebSpatial.updateResource(this._resource, { style: options });
|
|
1216
|
+
}
|
|
1090
1217
|
}
|
|
1091
1218
|
/**
|
|
1092
|
-
*
|
|
1093
|
-
*
|
|
1094
|
-
*
|
|
1095
|
-
* @param
|
|
1096
|
-
* @returns Boolean
|
|
1219
|
+
* Modifies the amount the spatial window can be scrolled
|
|
1220
|
+
* Should only be used internally
|
|
1221
|
+
* See https://developer.apple.com/documentation/uikit/1624475-uiedgeinsetsmake?language=objc
|
|
1222
|
+
* @param insets margin to modify scroll distances by
|
|
1097
1223
|
*/
|
|
1098
|
-
async
|
|
1099
|
-
|
|
1224
|
+
async setScrollEdgeInsets(insets) {
|
|
1225
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1226
|
+
setScrollEdgeInsets: insets
|
|
1227
|
+
});
|
|
1100
1228
|
}
|
|
1101
1229
|
/**
|
|
1102
|
-
*
|
|
1103
|
-
* @
|
|
1104
|
-
* [TODO] discuss implications of this not being async
|
|
1230
|
+
* Enable/Disable scrolling in the window (defaults to enabled), if disabled, scrolling will be applied to the root page
|
|
1231
|
+
* @param enabled value to set
|
|
1105
1232
|
*/
|
|
1106
|
-
|
|
1107
|
-
|
|
1233
|
+
async setScrollEnabled(enabled) {
|
|
1234
|
+
await WebSpatial.updateResource(this._resource, { scrollEnabled: enabled });
|
|
1235
|
+
}
|
|
1236
|
+
/**
|
|
1237
|
+
* Defaults to false. If set to true, scrolling the parent page will also scroll this window with it like other dom elements
|
|
1238
|
+
* @param scrollWithParent value to set
|
|
1239
|
+
*/
|
|
1240
|
+
async setScrollWithParent(scrollWithParent) {
|
|
1241
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1242
|
+
scrollWithParent
|
|
1243
|
+
});
|
|
1244
|
+
}
|
|
1245
|
+
};
|
|
1246
|
+
|
|
1247
|
+
// src/core/component/EventSpatialComponent.ts
|
|
1248
|
+
var EventSpatialComponent = class extends SpatialComponent {
|
|
1249
|
+
// Class implementation goes here
|
|
1250
|
+
constructor(_resource) {
|
|
1251
|
+
super(_resource);
|
|
1252
|
+
WebSpatial.registerEventReceiver(_resource.id, (data) => {
|
|
1253
|
+
this.onRecvEvent(data);
|
|
1254
|
+
});
|
|
1255
|
+
}
|
|
1256
|
+
async onDestroy() {
|
|
1257
|
+
WebSpatial.unregisterEventReceiver(this._resource.id);
|
|
1258
|
+
}
|
|
1259
|
+
};
|
|
1260
|
+
|
|
1261
|
+
// src/core/component/SpatialInputComponent.ts
|
|
1262
|
+
var SpatialInputComponent = class extends EventSpatialComponent {
|
|
1263
|
+
onRecvEvent(data) {
|
|
1264
|
+
this.onTranslate(data);
|
|
1108
1265
|
}
|
|
1109
1266
|
/**
|
|
1110
|
-
*
|
|
1111
|
-
* @
|
|
1267
|
+
* Callback fired when a translate event occurs
|
|
1268
|
+
* @param data translate event data
|
|
1112
1269
|
*/
|
|
1113
|
-
|
|
1114
|
-
let parentResp = await WebSpatial.updateResource(
|
|
1115
|
-
WebSpatial.getCurrentWebPanel(),
|
|
1116
|
-
{ getParentID: "" }
|
|
1117
|
-
);
|
|
1118
|
-
if (parentResp.data.parentID === "") {
|
|
1119
|
-
return new Promise((res2, rej) => {
|
|
1120
|
-
res2(null);
|
|
1121
|
-
});
|
|
1122
|
-
} else {
|
|
1123
|
-
var res = new WebSpatialResource();
|
|
1124
|
-
res.id = parentResp.data.parentID;
|
|
1125
|
-
return new SpatialWindowComponent(res);
|
|
1126
|
-
}
|
|
1270
|
+
onTranslate(data) {
|
|
1127
1271
|
}
|
|
1272
|
+
};
|
|
1273
|
+
|
|
1274
|
+
// src/core/component/SpatialModelComponent.ts
|
|
1275
|
+
var SpatialModelComponent = class extends SpatialComponent {
|
|
1276
|
+
cachedMaterials = new Array();
|
|
1128
1277
|
/**
|
|
1129
|
-
*
|
|
1130
|
-
* @param
|
|
1278
|
+
* Sets the mesh to be displayed by the component
|
|
1279
|
+
* @param mesh mesh to set
|
|
1131
1280
|
*/
|
|
1132
|
-
async
|
|
1133
|
-
await WebSpatial.
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
return JSON.stringify(x);
|
|
1137
|
-
})
|
|
1138
|
-
})
|
|
1139
|
-
);
|
|
1281
|
+
async setMesh(mesh) {
|
|
1282
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1283
|
+
meshResource: mesh._resource.id
|
|
1284
|
+
});
|
|
1140
1285
|
}
|
|
1141
1286
|
/**
|
|
1142
|
-
*
|
|
1143
|
-
*
|
|
1287
|
+
* Sets the materials that should be applied to the mesh
|
|
1288
|
+
* @param materials array of materials to set
|
|
1144
1289
|
*/
|
|
1145
|
-
async
|
|
1146
|
-
|
|
1290
|
+
async setMaterials(materials) {
|
|
1291
|
+
this.cachedMaterials = materials;
|
|
1292
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1293
|
+
materials: materials.map((m) => {
|
|
1294
|
+
m._addToComponent(this);
|
|
1295
|
+
return m._resource.id;
|
|
1296
|
+
})
|
|
1297
|
+
});
|
|
1147
1298
|
}
|
|
1299
|
+
/** @hidden */
|
|
1300
|
+
async _syncMaterials() {
|
|
1301
|
+
await this.setMaterials(this.cachedMaterials);
|
|
1302
|
+
}
|
|
1303
|
+
};
|
|
1304
|
+
|
|
1305
|
+
// src/core/component/SpatialViewComponent.ts
|
|
1306
|
+
var SpatialViewComponent = class extends SpatialComponent {
|
|
1148
1307
|
/**
|
|
1149
|
-
*
|
|
1150
|
-
* Debugging to get internal state from native code
|
|
1151
|
-
* @returns data as a js object
|
|
1308
|
+
* Sets the resolution of the spatial view in dom pixels
|
|
1152
1309
|
*/
|
|
1153
|
-
async
|
|
1154
|
-
|
|
1310
|
+
async setResolution(width, height) {
|
|
1311
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1312
|
+
resolution: { x: width, y: height }
|
|
1313
|
+
});
|
|
1155
1314
|
}
|
|
1156
1315
|
/**
|
|
1157
|
-
*
|
|
1316
|
+
* Sets if content of the spatialView should be within a portal
|
|
1317
|
+
* If true, volume will be behind the page, if false, it will be in front of the page
|
|
1158
1318
|
*/
|
|
1159
|
-
async
|
|
1160
|
-
|
|
1319
|
+
async setIsPortal(isPortal) {
|
|
1320
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1321
|
+
isPortal
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
};
|
|
1325
|
+
|
|
1326
|
+
// src/core/component/SpatialModel3DComponent.ts
|
|
1327
|
+
var SpatialModel3DComponent = class extends EventSpatialComponent {
|
|
1328
|
+
onRecvEvent(data) {
|
|
1329
|
+
const { eventType, value, error } = data;
|
|
1330
|
+
switch (eventType) {
|
|
1331
|
+
case "phase":
|
|
1332
|
+
if (value === "success") {
|
|
1333
|
+
this.onSuccess?.();
|
|
1334
|
+
} else {
|
|
1335
|
+
this.onFailure?.(error);
|
|
1336
|
+
}
|
|
1337
|
+
break;
|
|
1338
|
+
case "dragstart":
|
|
1339
|
+
this._onDragStart?.(value);
|
|
1340
|
+
break;
|
|
1341
|
+
case "dragend":
|
|
1342
|
+
this._onDragEnd?.(value);
|
|
1343
|
+
break;
|
|
1344
|
+
case "drag":
|
|
1345
|
+
this._onDrag?.(value);
|
|
1346
|
+
break;
|
|
1347
|
+
case "tap":
|
|
1348
|
+
this._onTap?.();
|
|
1349
|
+
break;
|
|
1350
|
+
case "doubletap":
|
|
1351
|
+
this._onDoubleTap?.();
|
|
1352
|
+
break;
|
|
1353
|
+
case "longpress":
|
|
1354
|
+
this._onLongPress?.();
|
|
1355
|
+
break;
|
|
1356
|
+
default:
|
|
1357
|
+
break;
|
|
1358
|
+
}
|
|
1161
1359
|
}
|
|
1162
1360
|
/**
|
|
1163
|
-
*
|
|
1361
|
+
* Sets the resolution of the spatial view in dom pixels
|
|
1164
1362
|
*/
|
|
1165
|
-
async
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
async openImmersiveSpace() {
|
|
1170
|
-
return await WebSpatial.openImmersiveSpace();
|
|
1363
|
+
async setResolution(width, height) {
|
|
1364
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1365
|
+
resolution: { x: width, y: height }
|
|
1366
|
+
});
|
|
1171
1367
|
}
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1368
|
+
async setRotationAnchor(rotationAnchor) {
|
|
1369
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1370
|
+
rotationAnchor
|
|
1371
|
+
});
|
|
1175
1372
|
}
|
|
1176
|
-
static _immersiveWindowContainer = null;
|
|
1177
1373
|
/**
|
|
1178
|
-
*
|
|
1179
|
-
* @
|
|
1374
|
+
* Sets the opacity of the model
|
|
1375
|
+
* @param opacity
|
|
1180
1376
|
*/
|
|
1181
|
-
async
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
}
|
|
1185
|
-
_SpatialSession._immersiveWindowContainer = new SpatialWindowContainer(
|
|
1186
|
-
WebSpatial.getImmersiveWindowContainer()
|
|
1187
|
-
);
|
|
1188
|
-
return _SpatialSession._immersiveWindowContainer;
|
|
1189
|
-
}
|
|
1377
|
+
async setOpacity(opacity) {
|
|
1378
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1379
|
+
opacity
|
|
1380
|
+
});
|
|
1190
1381
|
}
|
|
1191
|
-
// Retreives the window container that is the parent to this spatial web page
|
|
1192
|
-
static _currentWindowContainer = null;
|
|
1193
1382
|
/**
|
|
1194
|
-
*
|
|
1195
|
-
*
|
|
1196
|
-
* @returns the current window container for the window
|
|
1383
|
+
* Sets how the model fill the rect
|
|
1384
|
+
* @param contentMode
|
|
1197
1385
|
*/
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
}
|
|
1202
|
-
_SpatialSession._currentWindowContainer = new SpatialWindowContainer(
|
|
1203
|
-
WebSpatial.getCurrentWindowContainer()
|
|
1204
|
-
);
|
|
1205
|
-
return _SpatialSession._currentWindowContainer;
|
|
1206
|
-
}
|
|
1386
|
+
async setContentMode(contentMode) {
|
|
1387
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1388
|
+
contentMode
|
|
1389
|
+
});
|
|
1207
1390
|
}
|
|
1208
1391
|
/**
|
|
1209
|
-
*
|
|
1210
|
-
*
|
|
1211
|
-
*
|
|
1392
|
+
* Constrains this model dimensions to the specified aspect ratio.
|
|
1393
|
+
* with a value of 0, the model will use the original aspect ratio.
|
|
1394
|
+
*
|
|
1395
|
+
* @param aspectRatio number
|
|
1212
1396
|
*/
|
|
1213
|
-
|
|
1214
|
-
WebSpatial.
|
|
1215
|
-
|
|
1216
|
-
|
|
1397
|
+
async setAspectRatio(aspectRatio) {
|
|
1398
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1399
|
+
aspectRatio
|
|
1400
|
+
});
|
|
1217
1401
|
}
|
|
1218
1402
|
/**
|
|
1219
|
-
*
|
|
1220
|
-
* @
|
|
1403
|
+
* Defaults to false. If set to true, scrolling the parent page will also scroll this window with it like other dom elements
|
|
1404
|
+
* @param scrollWithParent value to set
|
|
1221
1405
|
*/
|
|
1222
|
-
async
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
while (openedWindow.window.testAPI == null) {
|
|
1227
|
-
if (counter > 15) {
|
|
1228
|
-
openedWindow?.close();
|
|
1229
|
-
openedWindow = window.open("about:blank");
|
|
1230
|
-
counter = 0;
|
|
1231
|
-
this.log("unexpected error when trying to open new window, retrying.");
|
|
1232
|
-
}
|
|
1233
|
-
var locName = "about:blank?x" + counter;
|
|
1234
|
-
openedWindow.location.href = locName;
|
|
1235
|
-
counter++;
|
|
1236
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
1237
|
-
}
|
|
1238
|
-
;
|
|
1239
|
-
openedWindow._webSpatialID = openedWindow.window.testAPI.getWindowID();
|
|
1240
|
-
} else {
|
|
1241
|
-
while (openedWindow.window._webSpatialID == void 0) {
|
|
1242
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
openedWindow.document.head.innerHTML = `<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1246
|
-
<base href="${document.baseURI}">
|
|
1247
|
-
`;
|
|
1248
|
-
return openedWindow;
|
|
1249
|
-
}
|
|
1250
|
-
// Get Entity by id. Currently for debugging only.
|
|
1251
|
-
/** @hidden */
|
|
1252
|
-
async _getEntity(id) {
|
|
1253
|
-
const entityInfo = await WebSpatial.inspect(id);
|
|
1254
|
-
const [_, x, y, z] = entityInfo.position.match(/(\d+\.?\d*)/g);
|
|
1255
|
-
const [__, sx, sy, sz] = entityInfo.scale.match(/(\d+\.?\d*)/g);
|
|
1256
|
-
var res = new WebSpatialResource();
|
|
1257
|
-
res.id = id;
|
|
1258
|
-
res.windowContainerId = WebSpatial.getCurrentWindowContainer().id;
|
|
1259
|
-
const entity = new SpatialEntity(res);
|
|
1260
|
-
entity.transform.position.x = parseFloat(x);
|
|
1261
|
-
entity.transform.position.y = parseFloat(y);
|
|
1262
|
-
entity.transform.position.z = parseFloat(z);
|
|
1263
|
-
entity.transform.scale.x = parseFloat(sx);
|
|
1264
|
-
entity.transform.scale.y = parseFloat(sy);
|
|
1265
|
-
entity.transform.scale.z = parseFloat(sz);
|
|
1266
|
-
return entity;
|
|
1406
|
+
async setScrollWithParent(scrollWithParent) {
|
|
1407
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1408
|
+
scrollWithParent
|
|
1409
|
+
});
|
|
1267
1410
|
}
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1411
|
+
/**
|
|
1412
|
+
* Sets whether the model appear in original size or fit the rect
|
|
1413
|
+
* @param resizable
|
|
1414
|
+
*/
|
|
1415
|
+
async setResizable(resizable) {
|
|
1416
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1417
|
+
resizable
|
|
1418
|
+
});
|
|
1272
1419
|
}
|
|
1273
|
-
};
|
|
1274
|
-
|
|
1275
|
-
// src/core/Spatial.ts
|
|
1276
|
-
var Spatial = class {
|
|
1277
1420
|
/**
|
|
1278
|
-
*
|
|
1279
|
-
* @returns The session or null if not availible in the current browser
|
|
1280
|
-
* [TODO] discuss implications of this not being async
|
|
1421
|
+
* Callback fired when model load success
|
|
1281
1422
|
*/
|
|
1282
|
-
|
|
1283
|
-
if (this.isSupported() && this.getNativeVersion() === this.getClientVersion()) {
|
|
1284
|
-
return new SpatialSession();
|
|
1285
|
-
} else {
|
|
1286
|
-
return null;
|
|
1287
|
-
}
|
|
1288
|
-
}
|
|
1423
|
+
onSuccess;
|
|
1289
1424
|
/**
|
|
1290
|
-
*
|
|
1425
|
+
* Callback fired when model load failure
|
|
1426
|
+
* @param errorReason
|
|
1291
1427
|
*/
|
|
1292
|
-
|
|
1293
|
-
|
|
1428
|
+
onFailure;
|
|
1429
|
+
/**
|
|
1430
|
+
* Callback fired when model was dragged at the beginning
|
|
1431
|
+
* @param dragEvent
|
|
1432
|
+
*/
|
|
1433
|
+
_onDragStart;
|
|
1434
|
+
set onDragStart(callback) {
|
|
1435
|
+
if (this._onDragStart !== callback) {
|
|
1436
|
+
this._onDragStart = callback;
|
|
1437
|
+
WebSpatial.updateResource(this._resource, {
|
|
1438
|
+
enableDragEvent: this.enableDragEvent
|
|
1439
|
+
});
|
|
1440
|
+
}
|
|
1294
1441
|
}
|
|
1295
1442
|
/**
|
|
1296
|
-
*
|
|
1297
|
-
* @
|
|
1443
|
+
* Callback fired when model was dragged
|
|
1444
|
+
* @param dragEvent
|
|
1298
1445
|
*/
|
|
1299
|
-
|
|
1300
|
-
|
|
1446
|
+
_onDrag;
|
|
1447
|
+
set onDrag(callback) {
|
|
1448
|
+
if (this._onDrag !== callback) {
|
|
1449
|
+
this._onDrag = callback;
|
|
1450
|
+
WebSpatial.updateResource(this._resource, {
|
|
1451
|
+
enableDragEvent: this.enableDragEvent
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1301
1454
|
}
|
|
1302
1455
|
/**
|
|
1303
|
-
*
|
|
1304
|
-
* @
|
|
1456
|
+
* Callback fired when model was dragged at the ending
|
|
1457
|
+
* @param dragEvent
|
|
1305
1458
|
*/
|
|
1306
|
-
|
|
1307
|
-
|
|
1459
|
+
_onDragEnd;
|
|
1460
|
+
set onDragEnd(callback) {
|
|
1461
|
+
if (this._onDragEnd !== callback) {
|
|
1462
|
+
this._onDragEnd = callback;
|
|
1463
|
+
WebSpatial.updateResource(this._resource, {
|
|
1464
|
+
enableDragEvent: this.enableDragEvent
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1308
1467
|
}
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
// src/core/SpatialHelper.ts
|
|
1312
|
-
var SpatialHelper = class _SpatialHelper {
|
|
1313
|
-
constructor(session) {
|
|
1314
|
-
this.session = session;
|
|
1468
|
+
get enableDragEvent() {
|
|
1469
|
+
return void 0 !== this._onDrag || void 0 !== this._onDragStart || void 0 !== this._onDragEnd;
|
|
1315
1470
|
}
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
return this._instance;
|
|
1327
|
-
}
|
|
1328
|
-
}
|
|
1471
|
+
/**
|
|
1472
|
+
* Callback fired when model was tapped
|
|
1473
|
+
*/
|
|
1474
|
+
_onTap;
|
|
1475
|
+
set onTap(callback) {
|
|
1476
|
+
if (this._onTap !== callback) {
|
|
1477
|
+
this._onTap = callback;
|
|
1478
|
+
WebSpatial.updateResource(this._resource, {
|
|
1479
|
+
enableTapEvent: void 0 !== callback
|
|
1480
|
+
});
|
|
1329
1481
|
}
|
|
1330
|
-
return null;
|
|
1331
1482
|
}
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
customModel.setMesh(box);
|
|
1340
|
-
var boxEntity = await this.session.createEntity();
|
|
1341
|
-
await boxEntity.setComponent(customModel);
|
|
1342
|
-
boxEntity.transform.position.z = 0;
|
|
1343
|
-
boxEntity.transform.scale = new Vec3(0.5, 0.5, 0.5);
|
|
1344
|
-
await boxEntity.updateTransform();
|
|
1345
|
-
return boxEntity;
|
|
1346
|
-
},
|
|
1347
|
-
createModelEntity: async (url) => {
|
|
1348
|
-
var customModel = await this.session.createModelComponent({ url });
|
|
1349
|
-
var boxEntity = await this.session.createEntity();
|
|
1350
|
-
await boxEntity.setComponent(customModel);
|
|
1351
|
-
await boxEntity.updateTransform();
|
|
1352
|
-
return boxEntity;
|
|
1353
|
-
},
|
|
1354
|
-
wrapInBoundingBoxEntity: async (entityToWrap) => {
|
|
1355
|
-
var bb = await entityToWrap.getBoundingBox();
|
|
1356
|
-
var targetSize = 1;
|
|
1357
|
-
var scale = targetSize / Math.max(bb.extents.x, bb.extents.y, bb.extents.z);
|
|
1358
|
-
entityToWrap.transform.scale.x = scale;
|
|
1359
|
-
entityToWrap.transform.scale.y = scale;
|
|
1360
|
-
entityToWrap.transform.scale.z = scale;
|
|
1361
|
-
entityToWrap.transform.position.x = -bb.center.x * scale;
|
|
1362
|
-
entityToWrap.transform.position.y = -bb.center.y * scale;
|
|
1363
|
-
entityToWrap.transform.position.z = -bb.center.z * scale;
|
|
1364
|
-
await entityToWrap.updateTransform();
|
|
1365
|
-
var boudningEntity = await _SpatialHelper.instance?.session.createEntity();
|
|
1366
|
-
await entityToWrap.setParent(boudningEntity);
|
|
1367
|
-
return boudningEntity;
|
|
1368
|
-
}
|
|
1369
|
-
};
|
|
1370
|
-
navigation = {
|
|
1371
|
-
openPanel: async (url, options) => {
|
|
1372
|
-
if (options?.resolution) {
|
|
1373
|
-
await this.session.getCurrentWindowContainer()._setOpenSettings({ resolution: options.resolution });
|
|
1374
|
-
}
|
|
1375
|
-
var wg = await this.session.createWindowContainer({
|
|
1376
|
-
style: "Plain",
|
|
1377
|
-
windowComponent: null,
|
|
1378
|
-
windowContainer: null
|
|
1379
|
-
});
|
|
1380
|
-
var ent = await this.session.createEntity({
|
|
1381
|
-
windowComponent: null,
|
|
1382
|
-
windowContainer: wg
|
|
1383
|
-
});
|
|
1384
|
-
var i = await this.session.createWindowComponent({
|
|
1385
|
-
windowComponent: null,
|
|
1386
|
-
windowContainer: wg
|
|
1387
|
-
});
|
|
1388
|
-
await i.loadURL(url);
|
|
1389
|
-
await ent.setCoordinateSpace("Root");
|
|
1390
|
-
await ent.setComponent(i);
|
|
1391
|
-
await wg.setRootEntity(ent);
|
|
1392
|
-
await this.session.getCurrentWindowContainer()._setOpenSettings({ resolution: { width: 900, height: 700 } });
|
|
1393
|
-
},
|
|
1394
|
-
openVolume: async (url, options) => {
|
|
1395
|
-
var wg = await this.session.createWindowContainer({
|
|
1396
|
-
style: "Volumetric",
|
|
1397
|
-
windowComponent: null,
|
|
1398
|
-
windowContainer: null
|
|
1399
|
-
});
|
|
1400
|
-
var rootEnt = await this.session.createEntity({
|
|
1401
|
-
windowComponent: null,
|
|
1402
|
-
windowContainer: wg
|
|
1403
|
-
});
|
|
1404
|
-
await rootEnt.setComponent(
|
|
1405
|
-
await this.session.createViewComponent({
|
|
1406
|
-
windowComponent: null,
|
|
1407
|
-
windowContainer: wg
|
|
1408
|
-
})
|
|
1409
|
-
);
|
|
1410
|
-
await rootEnt.setCoordinateSpace("Root");
|
|
1411
|
-
await wg.setRootEntity(rootEnt);
|
|
1412
|
-
var ent = await this.session.createEntity({
|
|
1413
|
-
windowComponent: null,
|
|
1414
|
-
windowContainer: wg
|
|
1415
|
-
});
|
|
1416
|
-
var i = await this.session.createWindowComponent({
|
|
1417
|
-
windowComponent: null,
|
|
1418
|
-
windowContainer: wg
|
|
1483
|
+
/** Callback fired when model was double tapped */
|
|
1484
|
+
_onDoubleTap;
|
|
1485
|
+
set onDoubleTap(callback) {
|
|
1486
|
+
if (this._onDoubleTap !== callback) {
|
|
1487
|
+
this._onDoubleTap = callback;
|
|
1488
|
+
WebSpatial.updateResource(this._resource, {
|
|
1489
|
+
enableDoubleTapEvent: void 0 !== callback
|
|
1419
1490
|
});
|
|
1420
|
-
await i.loadURL(url);
|
|
1421
|
-
if (options?.resolution) {
|
|
1422
|
-
await i.setResolution(
|
|
1423
|
-
options.resolution.width,
|
|
1424
|
-
options.resolution.height
|
|
1425
|
-
);
|
|
1426
|
-
} else {
|
|
1427
|
-
await i.setResolution(1e3, 1e3);
|
|
1428
|
-
}
|
|
1429
|
-
ent.transform.position.z = -0.49;
|
|
1430
|
-
await ent.updateTransform();
|
|
1431
|
-
await ent.setCoordinateSpace("App");
|
|
1432
|
-
await ent.setComponent(i);
|
|
1433
|
-
await ent.setParent(rootEnt);
|
|
1434
1491
|
}
|
|
1435
|
-
}
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
await viewEnt.setParent(ent);
|
|
1444
|
-
var update = () => {
|
|
1445
|
-
var rect = divOnPage.getBoundingClientRect();
|
|
1446
|
-
viewEnt.transform.position.x = rect.x + rect.width / 2;
|
|
1447
|
-
viewEnt.transform.position.y = rect.y + rect.height / 2 + window.scrollY;
|
|
1448
|
-
viewEnt.updateTransform();
|
|
1449
|
-
viewEnt.getComponent(SpatialViewComponent).setResolution(rect.width, rect.height);
|
|
1450
|
-
};
|
|
1451
|
-
var mo = new MutationObserver(update);
|
|
1452
|
-
mo.observe(divOnPage, { attributes: true });
|
|
1453
|
-
var ro = new ResizeObserver(update);
|
|
1454
|
-
ro.observe(divOnPage);
|
|
1455
|
-
const addRemoveObserver = new MutationObserver((mutations) => {
|
|
1456
|
-
mutations.forEach((mutation) => {
|
|
1457
|
-
mutation.removedNodes.forEach((node) => {
|
|
1458
|
-
if (node instanceof HTMLElement) {
|
|
1459
|
-
update();
|
|
1460
|
-
}
|
|
1461
|
-
});
|
|
1462
|
-
mutation.addedNodes.forEach((node) => {
|
|
1463
|
-
if (node instanceof HTMLElement) {
|
|
1464
|
-
update();
|
|
1465
|
-
}
|
|
1466
|
-
});
|
|
1467
|
-
});
|
|
1468
|
-
});
|
|
1469
|
-
addRemoveObserver.observe(document.body, {
|
|
1470
|
-
childList: true,
|
|
1471
|
-
subtree: true
|
|
1492
|
+
}
|
|
1493
|
+
/** Callback fired when model was long pressed */
|
|
1494
|
+
_onLongPress;
|
|
1495
|
+
set onLongPress(callback) {
|
|
1496
|
+
if (this._onLongPress !== callback) {
|
|
1497
|
+
this._onLongPress = callback;
|
|
1498
|
+
WebSpatial.updateResource(this._resource, {
|
|
1499
|
+
enableLongPressEvent: void 0 !== callback
|
|
1472
1500
|
});
|
|
1473
|
-
update();
|
|
1474
|
-
return {
|
|
1475
|
-
entity: viewEnt
|
|
1476
|
-
};
|
|
1477
1501
|
}
|
|
1478
|
-
}
|
|
1479
|
-
setBackgroundStyle = async (style, backgroundColor = "#00000000") => {
|
|
1480
|
-
document.documentElement.style.backgroundColor = backgroundColor;
|
|
1481
|
-
await this.session.getCurrentWindowComponent().setStyle(style);
|
|
1482
|
-
};
|
|
1502
|
+
}
|
|
1483
1503
|
};
|
|
1484
1504
|
export {
|
|
1485
1505
|
Spatial,
|