@webspatial/core-sdk 0.1.11 → 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 +14 -0
- package/dist/iife/index.d.ts +4 -1
- package/dist/iife/index.global.js +9 -2
- package/dist/iife/index.global.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +844 -824
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/Spatial.ts +1 -1
- package/src/core/SpatialHelper.ts +4 -0
- package/src/core/SpatialWindowContainer.ts +6 -0
- package/src/core/component/SpatialWindowComponent.ts +11 -3
- package/src/types/global.d.ts +12 -0
- package/tsconfig.json +1 -1
- package/tsup.config.ts +16 -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;
|
|
@@ -472,1014 +480,1026 @@ var SpatialComponent = class extends SpatialObject {
|
|
|
472
480
|
}
|
|
473
481
|
};
|
|
474
482
|
|
|
475
|
-
// src/core/
|
|
476
|
-
var
|
|
477
|
-
/**
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
*/
|
|
481
|
-
async loadURL(url) {
|
|
482
|
-
await WebSpatial.updateResource(this._resource, { url });
|
|
483
|
-
}
|
|
484
|
-
async setFromWindow(window2) {
|
|
485
|
-
if (window2._webSpatialID) {
|
|
486
|
-
await WebSpatial.updateResource(this._resource, {
|
|
487
|
-
windowID: window2._webSpatialID
|
|
488
|
-
});
|
|
489
|
-
} else {
|
|
490
|
-
await console.warn(
|
|
491
|
-
"failed to call setFromWindow, window provided is not valid"
|
|
492
|
-
);
|
|
493
|
-
}
|
|
483
|
+
// src/core/SpatialWindowContainer.ts
|
|
484
|
+
var SpatialWindowContainer = class {
|
|
485
|
+
/** @hidden */
|
|
486
|
+
constructor(_wg) {
|
|
487
|
+
this._wg = _wg;
|
|
494
488
|
}
|
|
495
489
|
/**
|
|
496
|
-
*
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
* @param width width in pixels
|
|
500
|
-
* @param height height in pixels
|
|
490
|
+
* @hidden
|
|
491
|
+
* Sets sets the open configuration for opening new window containers
|
|
492
|
+
* @param options style options
|
|
501
493
|
*/
|
|
502
|
-
async
|
|
503
|
-
await WebSpatial.
|
|
504
|
-
|
|
494
|
+
async _setOpenSettings(options) {
|
|
495
|
+
await WebSpatial.updateWindowContainer(this._wg, {
|
|
496
|
+
nextOpenSettings: options
|
|
505
497
|
});
|
|
506
498
|
}
|
|
507
499
|
/**
|
|
508
|
-
*
|
|
509
|
-
* @
|
|
500
|
+
* Retrieves the root entity of the windowContainer
|
|
501
|
+
* @returns the root entity of the windowContainer if one exists
|
|
510
502
|
*/
|
|
511
|
-
async
|
|
512
|
-
await WebSpatial.
|
|
513
|
-
|
|
503
|
+
async getRootEntity() {
|
|
504
|
+
let reqResp = await WebSpatial.updateWindowContainer(this._wg, {
|
|
505
|
+
getRootEntityID: ""
|
|
514
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
|
+
}
|
|
515
514
|
}
|
|
516
|
-
|
|
517
|
-
*
|
|
518
|
-
* @param
|
|
515
|
+
/*
|
|
516
|
+
* Sets the root entity that this windowContainer will display (this does not effect resource ownership)
|
|
517
|
+
* @param entity to display
|
|
519
518
|
*/
|
|
520
|
-
async
|
|
521
|
-
await
|
|
522
|
-
|
|
519
|
+
async setRootEntity(entity) {
|
|
520
|
+
await entity._setParentWindowContainer(this);
|
|
521
|
+
}
|
|
522
|
+
async close() {
|
|
523
|
+
await WebSpatial.updateWindowContainer(this._wg, {
|
|
524
|
+
close: true
|
|
523
525
|
});
|
|
524
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 {
|
|
525
535
|
/**
|
|
526
|
-
*
|
|
527
|
-
* @param options style options
|
|
536
|
+
* Base color of the material containing rgba between 0 and 1
|
|
528
537
|
*/
|
|
529
|
-
|
|
530
|
-
const { material, cornerRadius } = styleParam;
|
|
531
|
-
const options = {};
|
|
532
|
-
if (material?.type) {
|
|
533
|
-
options.backgroundMaterial = material.type;
|
|
534
|
-
}
|
|
535
|
-
if (cornerRadius !== void 0) {
|
|
536
|
-
if (typeof cornerRadius === "number") {
|
|
537
|
-
options.cornerRadius = {
|
|
538
|
-
topLeading: cornerRadius,
|
|
539
|
-
bottomLeading: cornerRadius,
|
|
540
|
-
topTrailing: cornerRadius,
|
|
541
|
-
bottomTrailing: cornerRadius
|
|
542
|
-
};
|
|
543
|
-
} else {
|
|
544
|
-
options.cornerRadius = { ...cornerRadius };
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
if (document && document.readyState == "loading") {
|
|
548
|
-
var encoded = encodeURIComponent(JSON.stringify(options));
|
|
549
|
-
var x = document.createElement("link");
|
|
550
|
-
x.rel = "stylesheet";
|
|
551
|
-
x.href = "forceStyle://mystyle.css?style=" + encoded;
|
|
552
|
-
document.head.appendChild(x);
|
|
553
|
-
}
|
|
554
|
-
await WebSpatial.updateResource(this._resource, { style: options });
|
|
555
|
-
}
|
|
538
|
+
baseColor = { r: 0, g: 0.7, b: 0.7, a: 1 };
|
|
556
539
|
/**
|
|
557
|
-
*
|
|
558
|
-
* Should only be used internally
|
|
559
|
-
* See https://developer.apple.com/documentation/uikit/1624475-uiedgeinsetsmake?language=objc
|
|
560
|
-
* @param insets margin to modify scroll distances by
|
|
540
|
+
* PBR metalic value between 0 and 1
|
|
561
541
|
*/
|
|
562
|
-
|
|
563
|
-
await WebSpatial.updateResource(this._resource, {
|
|
564
|
-
setScrollEdgeInsets: insets
|
|
565
|
-
});
|
|
566
|
-
}
|
|
542
|
+
metallic = { value: 0.5 };
|
|
567
543
|
/**
|
|
568
|
-
*
|
|
569
|
-
* @param enabled value to set
|
|
544
|
+
* PBR roughness value between 0 and 1
|
|
570
545
|
*/
|
|
571
|
-
|
|
572
|
-
|
|
546
|
+
roughness = { value: 0.5 };
|
|
547
|
+
_modelComponentAttachedTo = {};
|
|
548
|
+
_addToComponent(c) {
|
|
549
|
+
this._modelComponentAttachedTo[c._resource.id] = c;
|
|
573
550
|
}
|
|
574
551
|
/**
|
|
575
|
-
*
|
|
576
|
-
* @param scrollWithParent value to set
|
|
552
|
+
* Syncs state of color, metallic, roupghness to the renderer
|
|
577
553
|
*/
|
|
578
|
-
async
|
|
554
|
+
async update() {
|
|
579
555
|
await WebSpatial.updateResource(this._resource, {
|
|
580
|
-
|
|
556
|
+
baseColor: this.baseColor,
|
|
557
|
+
metallic: this.metallic,
|
|
558
|
+
roughness: this.roughness
|
|
581
559
|
});
|
|
560
|
+
for (var key in this._modelComponentAttachedTo) {
|
|
561
|
+
await this._modelComponentAttachedTo[key]._syncMaterials();
|
|
562
|
+
}
|
|
582
563
|
}
|
|
583
564
|
};
|
|
584
565
|
|
|
585
|
-
// src/core/
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
WebSpatial.registerEventReceiver(_resource.id, (data) => {
|
|
591
|
-
this.onRecvEvent(data);
|
|
592
|
-
});
|
|
593
|
-
}
|
|
594
|
-
async onDestroy() {
|
|
595
|
-
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();
|
|
596
571
|
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
var SpatialInputComponent = class extends EventSpatialComponent {
|
|
601
|
-
onRecvEvent(data) {
|
|
602
|
-
this.onTranslate(data);
|
|
572
|
+
var parentWindow = null;
|
|
573
|
+
if (options?.windowComponent !== null) {
|
|
574
|
+
parentWindow = options?.windowComponent ? options?.windowComponent._resource : WebSpatial.getCurrentWebPanel();
|
|
603
575
|
}
|
|
576
|
+
return [parentWindowContainer, parentWindow];
|
|
577
|
+
}
|
|
578
|
+
var SpatialSession = class _SpatialSession {
|
|
579
|
+
/** @hidden */
|
|
580
|
+
_engineUpdateListeners = Array();
|
|
581
|
+
/** @hidden */
|
|
582
|
+
_frameLoopStarted = false;
|
|
604
583
|
/**
|
|
605
|
-
*
|
|
606
|
-
* @param
|
|
584
|
+
* Add event listener callback to be called each frame
|
|
585
|
+
* @param callback callback to be called each update
|
|
607
586
|
*/
|
|
608
|
-
|
|
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
|
+
}
|
|
609
599
|
}
|
|
610
|
-
};
|
|
611
|
-
|
|
612
|
-
// src/core/component/SpatialModelComponent.ts
|
|
613
|
-
var SpatialModelComponent = class extends SpatialComponent {
|
|
614
|
-
cachedMaterials = new Array();
|
|
615
600
|
/**
|
|
616
|
-
*
|
|
617
|
-
* @
|
|
601
|
+
* Creates a Entity
|
|
602
|
+
* @returns Entity
|
|
618
603
|
*/
|
|
619
|
-
async
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
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);
|
|
623
612
|
}
|
|
624
613
|
/**
|
|
625
|
-
*
|
|
626
|
-
*
|
|
614
|
+
* Creates a WindowComponent
|
|
615
|
+
* [TODO] should creation of components be moved to entity? and these made private?
|
|
616
|
+
* @returns WindowComponent
|
|
627
617
|
*/
|
|
628
|
-
async
|
|
629
|
-
|
|
630
|
-
await WebSpatial.
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
}
|
|
637
|
-
/** @hidden */
|
|
638
|
-
async _syncMaterials() {
|
|
639
|
-
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);
|
|
640
626
|
}
|
|
641
|
-
};
|
|
642
|
-
|
|
643
|
-
// src/core/component/SpatialViewComponent.ts
|
|
644
|
-
var SpatialViewComponent = class extends SpatialComponent {
|
|
645
627
|
/**
|
|
646
|
-
*
|
|
628
|
+
* Creates a ViewComponent used to display 3D content within the entity
|
|
629
|
+
* @returns SpatialViewComponent
|
|
647
630
|
*/
|
|
648
|
-
async
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
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);
|
|
652
639
|
}
|
|
653
640
|
/**
|
|
654
|
-
*
|
|
655
|
-
*
|
|
656
|
-
*/
|
|
657
|
-
async
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
};
|
|
663
|
-
|
|
664
|
-
// src/core/component/SpatialModel3DComponent.ts
|
|
665
|
-
var SpatialModel3DComponent = class extends EventSpatialComponent {
|
|
666
|
-
onRecvEvent(data) {
|
|
667
|
-
const { eventType, value, error } = data;
|
|
668
|
-
switch (eventType) {
|
|
669
|
-
case "phase":
|
|
670
|
-
if (value === "success") {
|
|
671
|
-
this.onSuccess?.();
|
|
672
|
-
} else {
|
|
673
|
-
this.onFailure?.(error);
|
|
674
|
-
}
|
|
675
|
-
break;
|
|
676
|
-
case "dragstart":
|
|
677
|
-
this._onDragStart?.(value);
|
|
678
|
-
break;
|
|
679
|
-
case "dragend":
|
|
680
|
-
this._onDragEnd?.(value);
|
|
681
|
-
break;
|
|
682
|
-
case "drag":
|
|
683
|
-
this._onDrag?.(value);
|
|
684
|
-
break;
|
|
685
|
-
case "tap":
|
|
686
|
-
this._onTap?.();
|
|
687
|
-
break;
|
|
688
|
-
case "doubletap":
|
|
689
|
-
this._onDoubleTap?.();
|
|
690
|
-
break;
|
|
691
|
-
case "longpress":
|
|
692
|
-
this._onLongPress?.();
|
|
693
|
-
break;
|
|
694
|
-
default:
|
|
695
|
-
break;
|
|
641
|
+
* Creates a ModelComponent used to display geometry + material of a 3D model
|
|
642
|
+
* @returns ModelComponent
|
|
643
|
+
*/
|
|
644
|
+
async createModelComponent(options) {
|
|
645
|
+
var [parentWindowContainer, parentWindow] = _parseParentResources(options);
|
|
646
|
+
var opts = void 0;
|
|
647
|
+
if (options) {
|
|
648
|
+
opts = { modelURL: options.url };
|
|
696
649
|
}
|
|
650
|
+
let entity = await WebSpatial.createResource(
|
|
651
|
+
"ModelComponent",
|
|
652
|
+
parentWindowContainer,
|
|
653
|
+
parentWindow,
|
|
654
|
+
opts
|
|
655
|
+
);
|
|
656
|
+
return new SpatialModelComponent(entity);
|
|
697
657
|
}
|
|
698
658
|
/**
|
|
699
|
-
*
|
|
659
|
+
* Creates a Model3DComponent
|
|
660
|
+
* @returns Model3DComponent
|
|
700
661
|
*/
|
|
701
|
-
async
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
await WebSpatial.
|
|
708
|
-
|
|
709
|
-
|
|
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);
|
|
710
675
|
}
|
|
711
676
|
/**
|
|
712
|
-
*
|
|
713
|
-
*
|
|
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
|
|
714
680
|
*/
|
|
715
|
-
async
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
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);
|
|
719
689
|
}
|
|
720
690
|
/**
|
|
721
|
-
*
|
|
722
|
-
* @
|
|
691
|
+
* Creates a MeshResource containing geometry data
|
|
692
|
+
* @returns MeshResource
|
|
723
693
|
*/
|
|
724
|
-
async
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
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);
|
|
728
703
|
}
|
|
729
704
|
/**
|
|
730
|
-
*
|
|
731
|
-
*
|
|
732
|
-
*
|
|
733
|
-
* @param aspectRatio number
|
|
705
|
+
* Creates a PhysicallyBasedMaterial containing PBR material data
|
|
706
|
+
* @returns PhysicallyBasedMaterial
|
|
734
707
|
*/
|
|
735
|
-
async
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
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);
|
|
739
717
|
}
|
|
740
718
|
/**
|
|
741
|
-
*
|
|
742
|
-
* @
|
|
743
|
-
*/
|
|
744
|
-
async
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
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
|
+
);
|
|
748
732
|
}
|
|
749
733
|
/**
|
|
750
|
-
*
|
|
751
|
-
* @
|
|
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
|
|
752
739
|
*/
|
|
753
|
-
async
|
|
754
|
-
await WebSpatial.
|
|
755
|
-
resizable
|
|
756
|
-
});
|
|
740
|
+
async _createScene(style = "Plain", cfg) {
|
|
741
|
+
return await WebSpatial.createScene(style, cfg);
|
|
757
742
|
}
|
|
758
743
|
/**
|
|
759
|
-
*
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
/**
|
|
763
|
-
* Callback fired when model load failure
|
|
764
|
-
* @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
|
|
765
747
|
*/
|
|
766
|
-
|
|
748
|
+
getCurrentWindowComponent() {
|
|
749
|
+
return new SpatialWindowComponent(WebSpatial.getCurrentWebPanel());
|
|
750
|
+
}
|
|
767
751
|
/**
|
|
768
|
-
*
|
|
769
|
-
* @
|
|
752
|
+
* Retrieves the parent window for this page or null if this is the root page
|
|
753
|
+
* @returns the window component or null
|
|
770
754
|
*/
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
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);
|
|
777
763
|
});
|
|
764
|
+
} else {
|
|
765
|
+
var res = new WebSpatialResource();
|
|
766
|
+
res.id = parentResp.data.parentID;
|
|
767
|
+
return new SpatialWindowComponent(res);
|
|
778
768
|
}
|
|
779
769
|
}
|
|
780
770
|
/**
|
|
781
|
-
*
|
|
782
|
-
* @param
|
|
771
|
+
* Logs a message to the native apps console
|
|
772
|
+
* @param msg mesage to log
|
|
783
773
|
*/
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
})
|
|
791
|
-
|
|
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
|
+
);
|
|
792
782
|
}
|
|
793
783
|
/**
|
|
794
|
-
*
|
|
795
|
-
*
|
|
784
|
+
* @hidden
|
|
785
|
+
* Debugging only, used to ping the native renderer
|
|
796
786
|
*/
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
if (this._onDragEnd !== callback) {
|
|
800
|
-
this._onDragEnd = callback;
|
|
801
|
-
WebSpatial.updateResource(this._resource, {
|
|
802
|
-
enableDragEvent: this.enableDragEvent
|
|
803
|
-
});
|
|
804
|
-
}
|
|
787
|
+
async _ping(msg) {
|
|
788
|
+
return await WebSpatial.ping(msg);
|
|
805
789
|
}
|
|
806
|
-
|
|
807
|
-
|
|
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();
|
|
808
797
|
}
|
|
809
798
|
/**
|
|
810
|
-
*
|
|
799
|
+
* @hidden
|
|
811
800
|
*/
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
if (this._onTap !== callback) {
|
|
815
|
-
this._onTap = callback;
|
|
816
|
-
WebSpatial.updateResource(this._resource, {
|
|
817
|
-
enableTapEvent: void 0 !== callback
|
|
818
|
-
});
|
|
819
|
-
}
|
|
801
|
+
async _inspect(spatialObjectId = WebSpatial.getCurrentWebPanel().id) {
|
|
802
|
+
return WebSpatial.inspect(spatialObjectId);
|
|
820
803
|
}
|
|
821
|
-
/** Callback fired when model was double tapped */
|
|
822
|
-
_onDoubleTap;
|
|
823
|
-
set onDoubleTap(callback) {
|
|
824
|
-
if (this._onDoubleTap !== callback) {
|
|
825
|
-
this._onDoubleTap = callback;
|
|
826
|
-
WebSpatial.updateResource(this._resource, {
|
|
827
|
-
enableDoubleTapEvent: void 0 !== callback
|
|
828
|
-
});
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
/** Callback fired when model was long pressed */
|
|
832
|
-
_onLongPress;
|
|
833
|
-
set onLongPress(callback) {
|
|
834
|
-
if (this._onLongPress !== callback) {
|
|
835
|
-
this._onLongPress = callback;
|
|
836
|
-
WebSpatial.updateResource(this._resource, {
|
|
837
|
-
enableLongPressEvent: void 0 !== callback
|
|
838
|
-
});
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
};
|
|
842
|
-
|
|
843
|
-
// src/core/resource/SpatialMeshResource.ts
|
|
844
|
-
var SpatialMeshResource = class extends SpatialObject {
|
|
845
|
-
};
|
|
846
|
-
|
|
847
|
-
// src/core/resource/SpatialPhysicallyBasedMaterialResource.ts
|
|
848
|
-
var SpatialPhysicallyBasedMaterialResource = class extends SpatialObject {
|
|
849
|
-
/**
|
|
850
|
-
* Base color of the material containing rgba between 0 and 1
|
|
851
|
-
*/
|
|
852
|
-
baseColor = { r: 0, g: 0.7, b: 0.7, a: 1 };
|
|
853
804
|
/**
|
|
854
|
-
*
|
|
805
|
+
* @hidden
|
|
855
806
|
*/
|
|
856
|
-
|
|
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;
|
|
857
819
|
/**
|
|
858
|
-
*
|
|
820
|
+
* Retreives the window container corresponding to the Immersive space
|
|
821
|
+
* @returns the immersive window container
|
|
859
822
|
*/
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
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
|
+
}
|
|
864
832
|
}
|
|
833
|
+
// Retreives the window container that is the parent to this spatial web page
|
|
834
|
+
static _currentWindowContainer = null;
|
|
865
835
|
/**
|
|
866
|
-
*
|
|
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
|
|
867
839
|
*/
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
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;
|
|
876
848
|
}
|
|
877
849
|
}
|
|
878
|
-
};
|
|
879
|
-
|
|
880
|
-
// src/core/SpatialWindowContainer.ts
|
|
881
|
-
var SpatialWindowContainer = class {
|
|
882
|
-
/** @hidden */
|
|
883
|
-
constructor(_wg) {
|
|
884
|
-
this._wg = _wg;
|
|
885
|
-
}
|
|
886
850
|
/**
|
|
887
|
-
*
|
|
888
|
-
*
|
|
889
|
-
* @
|
|
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
|
|
890
854
|
*/
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
855
|
+
transaction(fn) {
|
|
856
|
+
WebSpatial.startTransaction();
|
|
857
|
+
fn();
|
|
858
|
+
return WebSpatial.sendTransaction();
|
|
895
859
|
}
|
|
896
860
|
/**
|
|
897
|
-
*
|
|
898
|
-
* @returns
|
|
861
|
+
* Creates a window context object that is compatable with SpatialWindowComponent's setFromWindow API
|
|
862
|
+
* @returns window context
|
|
899
863
|
*/
|
|
900
|
-
async
|
|
901
|
-
let
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
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();
|
|
906
882
|
} else {
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
883
|
+
while (openedWindow.window._webSpatialID == void 0) {
|
|
884
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
885
|
+
}
|
|
910
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;
|
|
911
891
|
}
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
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);
|
|
918
914
|
}
|
|
919
915
|
};
|
|
920
916
|
|
|
921
|
-
// src/core/
|
|
922
|
-
|
|
923
|
-
var parentWindowContainer = null;
|
|
924
|
-
if (options?.windowContainer !== null) {
|
|
925
|
-
parentWindowContainer = options?.windowContainer ? options?.windowContainer._wg : WebSpatial.getCurrentWindowContainer();
|
|
926
|
-
}
|
|
927
|
-
var parentWindow = null;
|
|
928
|
-
if (options?.windowComponent !== null) {
|
|
929
|
-
parentWindow = options?.windowComponent ? options?.windowComponent._resource : WebSpatial.getCurrentWebPanel();
|
|
930
|
-
}
|
|
931
|
-
return [parentWindowContainer, parentWindow];
|
|
932
|
-
}
|
|
933
|
-
var SpatialSession = class _SpatialSession {
|
|
934
|
-
/** @hidden */
|
|
935
|
-
_engineUpdateListeners = Array();
|
|
936
|
-
/** @hidden */
|
|
937
|
-
_frameLoopStarted = false;
|
|
917
|
+
// src/core/Spatial.ts
|
|
918
|
+
var Spatial = class {
|
|
938
919
|
/**
|
|
939
|
-
*
|
|
940
|
-
* @
|
|
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
|
|
941
923
|
*/
|
|
942
|
-
|
|
943
|
-
this.
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
await Promise.all(
|
|
948
|
-
this._engineUpdateListeners.map((cb) => {
|
|
949
|
-
return cb(time);
|
|
950
|
-
})
|
|
951
|
-
);
|
|
952
|
-
});
|
|
924
|
+
requestSession() {
|
|
925
|
+
if (this.isSupported() && this.getNativeVersion() === this.getClientVersion()) {
|
|
926
|
+
return new SpatialSession();
|
|
927
|
+
} else {
|
|
928
|
+
return null;
|
|
953
929
|
}
|
|
954
930
|
}
|
|
955
931
|
/**
|
|
956
|
-
*
|
|
957
|
-
* @returns Entity
|
|
932
|
+
* @returns true if web spatial is supported by this webpage
|
|
958
933
|
*/
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
let entity = await WebSpatial.createResource(
|
|
962
|
-
"Entity",
|
|
963
|
-
parentWindowContainer,
|
|
964
|
-
parentWindow
|
|
965
|
-
);
|
|
966
|
-
return new SpatialEntity(entity);
|
|
934
|
+
isSupported() {
|
|
935
|
+
return this.getNativeVersion() === this.getClientVersion();
|
|
967
936
|
}
|
|
968
937
|
/**
|
|
969
|
-
*
|
|
970
|
-
*
|
|
971
|
-
* @returns WindowComponent
|
|
938
|
+
* Gets the native version, format is "x.x.x"
|
|
939
|
+
* @returns native version string
|
|
972
940
|
*/
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
parentWindow
|
|
979
|
-
);
|
|
980
|
-
return new SpatialWindowComponent(entity);
|
|
941
|
+
getNativeVersion() {
|
|
942
|
+
if (window.__WebSpatialData && window.__WebSpatialData.getNativeVersion) {
|
|
943
|
+
return window.__WebSpatialData.getNativeVersion();
|
|
944
|
+
}
|
|
945
|
+
return window.WebSpatailNativeVersion;
|
|
981
946
|
}
|
|
982
947
|
/**
|
|
983
|
-
*
|
|
984
|
-
* @returns
|
|
948
|
+
* Gets the client version, format is "x.x.x"
|
|
949
|
+
* @returns client version string
|
|
985
950
|
*/
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
951
|
+
getClientVersion() {
|
|
952
|
+
return "0.0.1";
|
|
953
|
+
}
|
|
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
|
+
}
|
|
974
|
+
}
|
|
975
|
+
return null;
|
|
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 {
|
|
995
1135
|
/**
|
|
996
|
-
*
|
|
997
|
-
* @
|
|
1136
|
+
* Loads a url page in the window
|
|
1137
|
+
* @param url url to load
|
|
998
1138
|
*/
|
|
999
|
-
async
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
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
|
+
);
|
|
1004
1151
|
}
|
|
1005
|
-
let entity = await WebSpatial.createResource(
|
|
1006
|
-
"ModelComponent",
|
|
1007
|
-
parentWindowContainer,
|
|
1008
|
-
parentWindow,
|
|
1009
|
-
opts
|
|
1010
|
-
);
|
|
1011
|
-
return new SpatialModelComponent(entity);
|
|
1012
1152
|
}
|
|
1013
1153
|
/**
|
|
1014
|
-
*
|
|
1015
|
-
*
|
|
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
|
|
1016
1159
|
*/
|
|
1017
|
-
async
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
opts = { modelURL: options.url };
|
|
1022
|
-
}
|
|
1023
|
-
let entity = await WebSpatial.createResource(
|
|
1024
|
-
"Model3DComponent",
|
|
1025
|
-
parentWindowContainer,
|
|
1026
|
-
parentWindow,
|
|
1027
|
-
opts
|
|
1028
|
-
);
|
|
1029
|
-
return new SpatialModel3DComponent(entity);
|
|
1160
|
+
async setResolution(width, height) {
|
|
1161
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1162
|
+
resolution: { x: width, y: height }
|
|
1163
|
+
});
|
|
1030
1164
|
}
|
|
1031
1165
|
/**
|
|
1032
|
-
*
|
|
1033
|
-
*
|
|
1034
|
-
* @returns InputComponent
|
|
1166
|
+
* [Experimental] Sets the anchor which the entity this is attached to will rotate around
|
|
1167
|
+
* @param rotationAnchor
|
|
1035
1168
|
*/
|
|
1036
|
-
async
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
parentWindowContainer,
|
|
1041
|
-
parentWindow
|
|
1042
|
-
);
|
|
1043
|
-
return new SpatialInputComponent(entity);
|
|
1169
|
+
async setRotationAnchor(rotationAnchor) {
|
|
1170
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1171
|
+
rotationAnchor
|
|
1172
|
+
});
|
|
1044
1173
|
}
|
|
1045
1174
|
/**
|
|
1046
|
-
*
|
|
1047
|
-
* @
|
|
1175
|
+
* [Experimental] Sets the opacity of the window after apply material
|
|
1176
|
+
* @param opacity
|
|
1048
1177
|
*/
|
|
1049
|
-
async
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
parentWindowContainer,
|
|
1054
|
-
parentWindow,
|
|
1055
|
-
options
|
|
1056
|
-
);
|
|
1057
|
-
return new SpatialMeshResource(entity);
|
|
1178
|
+
async setOpacity(opacity) {
|
|
1179
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1180
|
+
opacity
|
|
1181
|
+
});
|
|
1058
1182
|
}
|
|
1059
1183
|
/**
|
|
1060
|
-
*
|
|
1061
|
-
* @
|
|
1184
|
+
* Sets the style that should be applied to the window
|
|
1185
|
+
* @param options style options
|
|
1062
1186
|
*/
|
|
1063
|
-
async
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
options
|
|
1070
|
-
|
|
1071
|
-
|
|
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
|
+
}
|
|
1072
1217
|
}
|
|
1073
1218
|
/**
|
|
1074
|
-
*
|
|
1075
|
-
*
|
|
1076
|
-
*
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
parentWindowContainer,
|
|
1084
|
-
parentWindow
|
|
1085
|
-
)
|
|
1086
|
-
);
|
|
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
|
|
1223
|
+
*/
|
|
1224
|
+
async setScrollEdgeInsets(insets) {
|
|
1225
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1226
|
+
setScrollEdgeInsets: insets
|
|
1227
|
+
});
|
|
1087
1228
|
}
|
|
1088
1229
|
/**
|
|
1089
|
-
*
|
|
1090
|
-
* @
|
|
1091
|
-
* @param {WindowStyle} [style='Plain'] - The style of the Scene container to be created with. Defaults to 'Plain'.
|
|
1092
|
-
* @param {Object} [cfg={}] - Configuration object for the Scene.
|
|
1093
|
-
* @returns Boolean
|
|
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
|
|
1094
1232
|
*/
|
|
1095
|
-
async
|
|
1096
|
-
|
|
1233
|
+
async setScrollEnabled(enabled) {
|
|
1234
|
+
await WebSpatial.updateResource(this._resource, { scrollEnabled: enabled });
|
|
1097
1235
|
}
|
|
1098
1236
|
/**
|
|
1099
|
-
*
|
|
1100
|
-
* @
|
|
1101
|
-
* [TODO] discuss implications of this not being async
|
|
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
|
|
1102
1239
|
*/
|
|
1103
|
-
|
|
1104
|
-
|
|
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);
|
|
1105
1265
|
}
|
|
1106
1266
|
/**
|
|
1107
|
-
*
|
|
1108
|
-
* @
|
|
1267
|
+
* Callback fired when a translate event occurs
|
|
1268
|
+
* @param data translate event data
|
|
1109
1269
|
*/
|
|
1110
|
-
|
|
1111
|
-
let parentResp = await WebSpatial.updateResource(
|
|
1112
|
-
WebSpatial.getCurrentWebPanel(),
|
|
1113
|
-
{ getParentID: "" }
|
|
1114
|
-
);
|
|
1115
|
-
if (parentResp.data.parentID === "") {
|
|
1116
|
-
return new Promise((res2, rej) => {
|
|
1117
|
-
res2(null);
|
|
1118
|
-
});
|
|
1119
|
-
} else {
|
|
1120
|
-
var res = new WebSpatialResource();
|
|
1121
|
-
res.id = parentResp.data.parentID;
|
|
1122
|
-
return new SpatialWindowComponent(res);
|
|
1123
|
-
}
|
|
1270
|
+
onTranslate(data) {
|
|
1124
1271
|
}
|
|
1272
|
+
};
|
|
1273
|
+
|
|
1274
|
+
// src/core/component/SpatialModelComponent.ts
|
|
1275
|
+
var SpatialModelComponent = class extends SpatialComponent {
|
|
1276
|
+
cachedMaterials = new Array();
|
|
1125
1277
|
/**
|
|
1126
|
-
*
|
|
1127
|
-
* @param
|
|
1278
|
+
* Sets the mesh to be displayed by the component
|
|
1279
|
+
* @param mesh mesh to set
|
|
1128
1280
|
*/
|
|
1129
|
-
async
|
|
1130
|
-
await WebSpatial.
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
return JSON.stringify(x);
|
|
1134
|
-
})
|
|
1135
|
-
})
|
|
1136
|
-
);
|
|
1281
|
+
async setMesh(mesh) {
|
|
1282
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1283
|
+
meshResource: mesh._resource.id
|
|
1284
|
+
});
|
|
1137
1285
|
}
|
|
1138
1286
|
/**
|
|
1139
|
-
*
|
|
1140
|
-
*
|
|
1287
|
+
* Sets the materials that should be applied to the mesh
|
|
1288
|
+
* @param materials array of materials to set
|
|
1141
1289
|
*/
|
|
1142
|
-
async
|
|
1143
|
-
|
|
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
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
/** @hidden */
|
|
1300
|
+
async _syncMaterials() {
|
|
1301
|
+
await this.setMaterials(this.cachedMaterials);
|
|
1144
1302
|
}
|
|
1303
|
+
};
|
|
1304
|
+
|
|
1305
|
+
// src/core/component/SpatialViewComponent.ts
|
|
1306
|
+
var SpatialViewComponent = class extends SpatialComponent {
|
|
1145
1307
|
/**
|
|
1146
|
-
*
|
|
1147
|
-
* Debugging to get internal state from native code
|
|
1148
|
-
* @returns data as a js object
|
|
1308
|
+
* Sets the resolution of the spatial view in dom pixels
|
|
1149
1309
|
*/
|
|
1150
|
-
async
|
|
1151
|
-
|
|
1310
|
+
async setResolution(width, height) {
|
|
1311
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1312
|
+
resolution: { x: width, y: height }
|
|
1313
|
+
});
|
|
1152
1314
|
}
|
|
1153
1315
|
/**
|
|
1154
|
-
*
|
|
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
|
|
1155
1318
|
*/
|
|
1156
|
-
async
|
|
1157
|
-
|
|
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
|
+
}
|
|
1158
1359
|
}
|
|
1159
1360
|
/**
|
|
1160
|
-
*
|
|
1361
|
+
* Sets the resolution of the spatial view in dom pixels
|
|
1161
1362
|
*/
|
|
1162
|
-
async
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
async openImmersiveSpace() {
|
|
1167
|
-
return await WebSpatial.openImmersiveSpace();
|
|
1363
|
+
async setResolution(width, height) {
|
|
1364
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1365
|
+
resolution: { x: width, y: height }
|
|
1366
|
+
});
|
|
1168
1367
|
}
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1368
|
+
async setRotationAnchor(rotationAnchor) {
|
|
1369
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1370
|
+
rotationAnchor
|
|
1371
|
+
});
|
|
1172
1372
|
}
|
|
1173
|
-
static _immersiveWindowContainer = null;
|
|
1174
1373
|
/**
|
|
1175
|
-
*
|
|
1176
|
-
* @
|
|
1374
|
+
* Sets the opacity of the model
|
|
1375
|
+
* @param opacity
|
|
1177
1376
|
*/
|
|
1178
|
-
async
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
}
|
|
1182
|
-
_SpatialSession._immersiveWindowContainer = new SpatialWindowContainer(
|
|
1183
|
-
WebSpatial.getImmersiveWindowContainer()
|
|
1184
|
-
);
|
|
1185
|
-
return _SpatialSession._immersiveWindowContainer;
|
|
1186
|
-
}
|
|
1377
|
+
async setOpacity(opacity) {
|
|
1378
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1379
|
+
opacity
|
|
1380
|
+
});
|
|
1187
1381
|
}
|
|
1188
|
-
// Retreives the window container that is the parent to this spatial web page
|
|
1189
|
-
static _currentWindowContainer = null;
|
|
1190
1382
|
/**
|
|
1191
|
-
*
|
|
1192
|
-
*
|
|
1193
|
-
* @returns the current window container for the window
|
|
1383
|
+
* Sets how the model fill the rect
|
|
1384
|
+
* @param contentMode
|
|
1194
1385
|
*/
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
}
|
|
1199
|
-
_SpatialSession._currentWindowContainer = new SpatialWindowContainer(
|
|
1200
|
-
WebSpatial.getCurrentWindowContainer()
|
|
1201
|
-
);
|
|
1202
|
-
return _SpatialSession._currentWindowContainer;
|
|
1203
|
-
}
|
|
1386
|
+
async setContentMode(contentMode) {
|
|
1387
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1388
|
+
contentMode
|
|
1389
|
+
});
|
|
1204
1390
|
}
|
|
1205
1391
|
/**
|
|
1206
|
-
*
|
|
1207
|
-
*
|
|
1208
|
-
*
|
|
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
|
|
1209
1396
|
*/
|
|
1210
|
-
|
|
1211
|
-
WebSpatial.
|
|
1212
|
-
|
|
1213
|
-
|
|
1397
|
+
async setAspectRatio(aspectRatio) {
|
|
1398
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1399
|
+
aspectRatio
|
|
1400
|
+
});
|
|
1214
1401
|
}
|
|
1215
1402
|
/**
|
|
1216
|
-
*
|
|
1217
|
-
* @
|
|
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
|
|
1218
1405
|
*/
|
|
1219
|
-
async
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
while (openedWindow.window.testAPI == null) {
|
|
1224
|
-
if (counter > 15) {
|
|
1225
|
-
openedWindow?.close();
|
|
1226
|
-
openedWindow = window.open("about:blank");
|
|
1227
|
-
counter = 0;
|
|
1228
|
-
this.log("unexpected error when trying to open new window, retrying.");
|
|
1229
|
-
}
|
|
1230
|
-
var locName = "about:blank?x" + counter;
|
|
1231
|
-
openedWindow.location.href = locName;
|
|
1232
|
-
counter++;
|
|
1233
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
1234
|
-
}
|
|
1235
|
-
;
|
|
1236
|
-
openedWindow._webSpatialID = openedWindow.window.testAPI.getWindowID();
|
|
1237
|
-
} else {
|
|
1238
|
-
while (openedWindow.window._webSpatialID == void 0) {
|
|
1239
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
openedWindow.document.head.innerHTML = `<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1243
|
-
<base href="${document.baseURI}">
|
|
1244
|
-
`;
|
|
1245
|
-
return openedWindow;
|
|
1246
|
-
}
|
|
1247
|
-
// Get Entity by id. Currently for debugging only.
|
|
1248
|
-
/** @hidden */
|
|
1249
|
-
async _getEntity(id) {
|
|
1250
|
-
const entityInfo = await WebSpatial.inspect(id);
|
|
1251
|
-
const [_, x, y, z] = entityInfo.position.match(/(\d+\.?\d*)/g);
|
|
1252
|
-
const [__, sx, sy, sz] = entityInfo.scale.match(/(\d+\.?\d*)/g);
|
|
1253
|
-
var res = new WebSpatialResource();
|
|
1254
|
-
res.id = id;
|
|
1255
|
-
res.windowContainerId = WebSpatial.getCurrentWindowContainer().id;
|
|
1256
|
-
const entity = new SpatialEntity(res);
|
|
1257
|
-
entity.transform.position.x = parseFloat(x);
|
|
1258
|
-
entity.transform.position.y = parseFloat(y);
|
|
1259
|
-
entity.transform.position.z = parseFloat(z);
|
|
1260
|
-
entity.transform.scale.x = parseFloat(sx);
|
|
1261
|
-
entity.transform.scale.y = parseFloat(sy);
|
|
1262
|
-
entity.transform.scale.z = parseFloat(sz);
|
|
1263
|
-
return entity;
|
|
1264
|
-
}
|
|
1265
|
-
// set loading view.
|
|
1266
|
-
/** @hidden */
|
|
1267
|
-
async setLoading(method, style) {
|
|
1268
|
-
return WebSpatial.setLoading(method, style);
|
|
1406
|
+
async setScrollWithParent(scrollWithParent) {
|
|
1407
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1408
|
+
scrollWithParent
|
|
1409
|
+
});
|
|
1269
1410
|
}
|
|
1270
|
-
};
|
|
1271
|
-
|
|
1272
|
-
// src/core/Spatial.ts
|
|
1273
|
-
var Spatial = class {
|
|
1274
1411
|
/**
|
|
1275
|
-
*
|
|
1276
|
-
* @
|
|
1277
|
-
* [TODO] discuss implications of this not being async
|
|
1412
|
+
* Sets whether the model appear in original size or fit the rect
|
|
1413
|
+
* @param resizable
|
|
1278
1414
|
*/
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
}
|
|
1283
|
-
return null;
|
|
1284
|
-
}
|
|
1415
|
+
async setResizable(resizable) {
|
|
1416
|
+
await WebSpatial.updateResource(this._resource, {
|
|
1417
|
+
resizable
|
|
1418
|
+
});
|
|
1285
1419
|
}
|
|
1286
1420
|
/**
|
|
1287
|
-
*
|
|
1421
|
+
* Callback fired when model load success
|
|
1288
1422
|
*/
|
|
1289
|
-
|
|
1290
|
-
|
|
1423
|
+
onSuccess;
|
|
1424
|
+
/**
|
|
1425
|
+
* Callback fired when model load failure
|
|
1426
|
+
* @param errorReason
|
|
1427
|
+
*/
|
|
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
|
+
}
|
|
1291
1441
|
}
|
|
1292
1442
|
/**
|
|
1293
|
-
*
|
|
1294
|
-
* @
|
|
1443
|
+
* Callback fired when model was dragged
|
|
1444
|
+
* @param dragEvent
|
|
1295
1445
|
*/
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
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
|
+
});
|
|
1299
1453
|
}
|
|
1300
|
-
return window.WebSpatailNativeVersion;
|
|
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,
|