@shopware-ag/dive 1.16.25 → 1.16.26-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/build/dive.cjs +1652 -203
  2. package/build/dive.cjs.map +1 -1
  3. package/build/dive.d.cts +50 -8
  4. package/build/dive.d.ts +50 -8
  5. package/build/dive.js +1619 -159
  6. package/build/dive.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/ar/AR.ts +164 -0
  9. package/src/ar/arquicklook/ARQuickLook.ts +42 -0
  10. package/src/ar/webxr/WebXR.ts +176 -0
  11. package/src/ar/webxr/controller/WebXRController.ts +334 -0
  12. package/src/ar/webxr/crosshair/WebXRCrosshair.ts +35 -0
  13. package/src/ar/webxr/origin/WebXROrigin.ts +191 -0
  14. package/src/ar/webxr/overlay/Overlay.ts +50 -0
  15. package/src/ar/webxr/raycaster/WebXRRaycaster.ts +131 -0
  16. package/src/ar/webxr/raycaster/ar/WebXRRaycasterAR.ts +102 -0
  17. package/src/ar/webxr/raycaster/three/WebXRRaycasterTHREE.ts +49 -0
  18. package/src/ar/webxr/touchscreencontrols/WebXRTouchscreenControls.ts +356 -0
  19. package/src/axiscamera/AxisCamera.ts +4 -4
  20. package/src/axiscamera/__test__/AxisCamera.test.ts +4 -0
  21. package/src/com/Communication.ts +17 -0
  22. package/src/com/__test__/Communication.test.ts +1 -1
  23. package/src/com/actions/index.ts +2 -0
  24. package/src/dive.ts +51 -9
  25. package/src/events/EventExecutor.ts +35 -0
  26. package/src/helper/findSceneRecursive/findSceneRecursive.ts +2 -2
  27. package/src/info/Info.ts +37 -1
  28. package/src/info/__test__/Info.test.ts +45 -5
  29. package/src/mediacreator/MediaCreator.ts +4 -4
  30. package/src/mediacreator/__test__/MediaCreator.test.ts +7 -2
  31. package/src/renderer/Renderer.ts +21 -11
  32. package/src/renderer/__test__/Renderer.test.ts +19 -1
  33. package/src/scene/Scene.ts +35 -12
  34. package/src/scene/__test__/Scene.test.ts +39 -5
  35. package/src/scene/root/Root.ts +1 -0
  36. package/src/scene/xrroot/XRRoot.ts +56 -0
  37. package/src/scene/xrroot/xrlightroot/XRLightRoot.ts +80 -0
  38. package/src/toolbox/BaseTool.ts +9 -3
  39. package/src/toolbox/Toolbox.ts +1 -1
  40. package/src/toolbox/__test__/Toolbox.test.ts +1 -1
  41. package/src/toolbox/select/SelectTool.ts +1 -1
  42. package/src/toolbox/select/__test__/SelectTool.test.ts +1 -1
  43. package/src/toolbox/transform/TransformTool.ts +4 -4
  44. package/src/toolbox/transform/__test__/TransformTool.test.ts +2 -4
package/build/dive.js CHANGED
@@ -94,7 +94,11 @@ var init_findInterface = __esm({
94
94
  });
95
95
 
96
96
  // src/toolbox/BaseTool.ts
97
- import { Raycaster, Vector2, Vector3 } from "three";
97
+ import {
98
+ Raycaster,
99
+ Vector2,
100
+ Vector3
101
+ } from "three";
98
102
  var DIVEBaseTool;
99
103
  var init_BaseTool = __esm({
100
104
  "src/toolbox/BaseTool.ts"() {
@@ -314,7 +318,7 @@ var init_BaseTool = __esm({
314
318
  });
315
319
 
316
320
  // src/toolbox/transform/TransformTool.ts
317
- import { TransformControls } from "three/examples/jsm/Addons";
321
+ import { TransformControls } from "three/examples/jsm/controls/TransformControls";
318
322
  var DIVETransformTool;
319
323
  var init_TransformTool = __esm({
320
324
  "src/toolbox/transform/TransformTool.ts"() {
@@ -360,7 +364,7 @@ var init_TransformTool = __esm({
360
364
  if (!this._gizmo.object.onMoveEnd) return;
361
365
  this._gizmo.object.onMoveEnd();
362
366
  });
363
- scene.add(this._gizmo);
367
+ this._scene.add(this._gizmo);
364
368
  }
365
369
  Activate() {
366
370
  }
@@ -625,6 +629,1405 @@ var init_IO = __esm({
625
629
  }
626
630
  });
627
631
 
632
+ // src/info/Info.ts
633
+ var WebXRUnsupportedReason, DIVEInfo;
634
+ var init_Info = __esm({
635
+ "src/info/Info.ts"() {
636
+ "use strict";
637
+ WebXRUnsupportedReason = /* @__PURE__ */ ((WebXRUnsupportedReason2) => {
638
+ WebXRUnsupportedReason2[WebXRUnsupportedReason2["UNKNWON_ERROR"] = 0] = "UNKNWON_ERROR";
639
+ WebXRUnsupportedReason2[WebXRUnsupportedReason2["NO_HTTPS"] = 1] = "NO_HTTPS";
640
+ WebXRUnsupportedReason2[WebXRUnsupportedReason2["IMMERSIVE_AR_NOT_SUPPORTED_BY_DEVICE"] = 2] = "IMMERSIVE_AR_NOT_SUPPORTED_BY_DEVICE";
641
+ WebXRUnsupportedReason2[WebXRUnsupportedReason2["AR_SESSION_NOT_ALLOWED"] = 3] = "AR_SESSION_NOT_ALLOWED";
642
+ return WebXRUnsupportedReason2;
643
+ })(WebXRUnsupportedReason || {});
644
+ DIVEInfo = class {
645
+ /**
646
+ *
647
+ * @returns The system the user is using. Possible values are "Android", "iOS", "Windows", "MacOS", "Linux" or "Unknown".
648
+ */
649
+ static GetSystem() {
650
+ const platform = navigator.platform;
651
+ if (/Android/.test(navigator.userAgent)) {
652
+ return "Android";
653
+ } else if (/iPhone|iPad|iPod/.test(navigator.userAgent)) {
654
+ return "iOS";
655
+ } else if (platform.startsWith("Win")) {
656
+ return "Windows";
657
+ } else if (platform.startsWith("Mac")) {
658
+ return "MacOS";
659
+ } else if (platform.startsWith("Linux")) {
660
+ return "Linux";
661
+ } else {
662
+ return "Unknown";
663
+ }
664
+ }
665
+ /**
666
+ * @returns A promise that resolves to a boolean indicating whether the user's device supports WebXR.
667
+ */
668
+ static GetSupportsWebXR() {
669
+ return __async(this, null, function* () {
670
+ if (this._supportsWebXR !== null) {
671
+ return this._supportsWebXR;
672
+ }
673
+ if (!navigator.xr) {
674
+ this._supportsWebXR = false;
675
+ if (window.isSecureContext === false) {
676
+ this._webXRUnsupportedReason = 1 /* NO_HTTPS */;
677
+ } else {
678
+ this._webXRUnsupportedReason = 0 /* UNKNWON_ERROR */;
679
+ }
680
+ return this._supportsWebXR;
681
+ }
682
+ try {
683
+ const supported = yield navigator.xr.isSessionSupported("immersive-ar");
684
+ if (!supported) {
685
+ this._webXRUnsupportedReason = 2 /* IMMERSIVE_AR_NOT_SUPPORTED_BY_DEVICE */;
686
+ }
687
+ this._supportsWebXR = supported;
688
+ } catch (error) {
689
+ this._supportsWebXR = false;
690
+ this._webXRUnsupportedReason = 3 /* AR_SESSION_NOT_ALLOWED */;
691
+ }
692
+ return this._supportsWebXR;
693
+ });
694
+ }
695
+ /**
696
+ * @returns The reason why WebXR is not supported on the user's device. Returns null if WebXR is supported nor not has been checked yet.
697
+ */
698
+ static GetWebXRUnsupportedReason() {
699
+ if (this._supportsWebXR === null) {
700
+ console.log("WebXR support has not been checked yet.");
701
+ return null;
702
+ }
703
+ return this._webXRUnsupportedReason;
704
+ }
705
+ /**
706
+ * @returns A boolean indicating whether the user's device supports AR Quick Look.
707
+ */
708
+ static GetSupportsARQuickLook() {
709
+ const a = document.createElement("a");
710
+ if (a.relList.supports("ar")) {
711
+ return true;
712
+ }
713
+ const userAgent = navigator.userAgent;
714
+ const isIOS = /iPad|iPhone|iPod/.test(userAgent) && !window.MSStream;
715
+ if (!isIOS) {
716
+ return false;
717
+ }
718
+ const match = userAgent.match(/OS (\d+)_/);
719
+ if (!match || match.length < 2) {
720
+ return false;
721
+ }
722
+ const iOSVersion = parseInt(match[1], 10);
723
+ const minQuickLookVersion = 12;
724
+ if (iOSVersion < minQuickLookVersion) {
725
+ return false;
726
+ }
727
+ const isSupportedBrowser = /^((?!chrome|android).)*safari|CriOS|FxiOS/i.test(userAgent);
728
+ if (isSupportedBrowser) {
729
+ return true;
730
+ }
731
+ return false;
732
+ }
733
+ /**
734
+ * @returns A boolean indicating whether the user's device is a mobile device.
735
+ */
736
+ static get isMobile() {
737
+ return this.GetSystem() === "Android" || this.GetSystem() === "iOS";
738
+ }
739
+ /**
740
+ * @returns A boolean indicating whether the user's device is a desktop device.
741
+ */
742
+ static get isDesktop() {
743
+ return !this.isMobile;
744
+ }
745
+ /**
746
+ * @returns A promise that resolves to a boolean indicating whether the user's device is capable of AR.
747
+ */
748
+ static GetIsARCapable() {
749
+ return __async(this, null, function* () {
750
+ if (this.GetSupportsARQuickLook()) {
751
+ return true;
752
+ }
753
+ return yield this.GetSupportsWebXR();
754
+ });
755
+ }
756
+ };
757
+ DIVEInfo._supportsWebXR = null;
758
+ DIVEInfo._webXRUnsupportedReason = null;
759
+ }
760
+ });
761
+
762
+ // src/ar/arquicklook/ARQuickLook.ts
763
+ import { Object3D as Object3D2 } from "three";
764
+ import { USDZExporter } from "three/examples/jsm/exporters/USDZExporter";
765
+ var DIVEARQuickLook;
766
+ var init_ARQuickLook = __esm({
767
+ "src/ar/arquicklook/ARQuickLook.ts"() {
768
+ "use strict";
769
+ DIVEARQuickLook = class {
770
+ static Launch(scene) {
771
+ const quickLookScene = new Object3D2();
772
+ quickLookScene.add(...this.extractModels(scene));
773
+ return this.launchARFromNode(quickLookScene);
774
+ }
775
+ static extractModels(scene) {
776
+ return scene.Root.children;
777
+ }
778
+ static launchARFromNode(node) {
779
+ return this._usdzExporter.parse(node, { quickLookCompatible: true }).then((usdz) => {
780
+ const blob = new Blob([usdz], { type: "model/vnd.usdz+zip" });
781
+ const url = URL.createObjectURL(blob);
782
+ const a = document.createElement("a");
783
+ a.innerHTML = "<picture></picture>";
784
+ a.rel = "ar";
785
+ a.href = url;
786
+ a.download = "scene.usdz";
787
+ a.click();
788
+ });
789
+ }
790
+ };
791
+ DIVEARQuickLook._usdzExporter = new USDZExporter();
792
+ }
793
+ });
794
+
795
+ // src/ar/webxr/overlay/Overlay.ts
796
+ var Overlay;
797
+ var init_Overlay = __esm({
798
+ "src/ar/webxr/overlay/Overlay.ts"() {
799
+ "use strict";
800
+ Overlay = class {
801
+ get Element() {
802
+ return this._element;
803
+ }
804
+ get CloseButton() {
805
+ return this._closeButton;
806
+ }
807
+ constructor() {
808
+ this._element = document.createElement("div");
809
+ this._closeButton = this.createCloseButton();
810
+ this._element.appendChild(this._closeButton);
811
+ document.body.appendChild(this._element);
812
+ }
813
+ createCloseButton() {
814
+ const path = document.createElementNS(
815
+ "http://www.w3.org/2000/svg",
816
+ "path"
817
+ );
818
+ path.setAttribute("d", "M 12,12 L 28,28 M 28,12 12,28");
819
+ path.setAttribute("stroke", "#fff");
820
+ path.setAttribute("stroke-width", "2");
821
+ const svg = document.createElementNS(
822
+ "http://www.w3.org/2000/svg",
823
+ "svg"
824
+ );
825
+ svg.setAttribute("width", "38");
826
+ svg.setAttribute("height", "38");
827
+ svg.style.position = "absolute";
828
+ svg.style.right = "20px";
829
+ svg.style.top = "20px";
830
+ svg.appendChild(path);
831
+ return svg;
832
+ }
833
+ };
834
+ }
835
+ });
836
+
837
+ // src/ar/webxr/crosshair/WebXRCrosshair.ts
838
+ import { Mesh, MeshBasicMaterial, Object3D as Object3D3, RingGeometry } from "three";
839
+ var DIVEWebXRCrosshair;
840
+ var init_WebXRCrosshair = __esm({
841
+ "src/ar/webxr/crosshair/WebXRCrosshair.ts"() {
842
+ "use strict";
843
+ DIVEWebXRCrosshair = class extends Object3D3 {
844
+ set mesh(mesh) {
845
+ this.clear();
846
+ if (mesh) {
847
+ this.add(mesh);
848
+ }
849
+ }
850
+ constructor(mesh) {
851
+ super();
852
+ if (mesh) {
853
+ this.mesh = mesh;
854
+ } else {
855
+ this.UseDefaultMesh();
856
+ }
857
+ this.matrixAutoUpdate = false;
858
+ return this;
859
+ }
860
+ UseDefaultMesh() {
861
+ const geometry = new RingGeometry(0.08, 0.1, 32).rotateX(-Math.PI / 2);
862
+ const material = new MeshBasicMaterial();
863
+ this.mesh = new Mesh(geometry, material);
864
+ }
865
+ UpdateFromPose(pose) {
866
+ this.matrix.fromArray(pose.transform.matrix);
867
+ }
868
+ };
869
+ }
870
+ });
871
+
872
+ // src/ar/webxr/raycaster/ar/WebXRRaycasterAR.ts
873
+ import { Matrix4, Vector3 as Vector32 } from "three";
874
+ var DIVEWebXRRaycasterAR;
875
+ var init_WebXRRaycasterAR = __esm({
876
+ "src/ar/webxr/raycaster/ar/WebXRRaycasterAR.ts"() {
877
+ "use strict";
878
+ DIVEWebXRRaycasterAR = class {
879
+ constructor(session, renderer) {
880
+ this._referenceSpaceBuffer = null;
881
+ this._requesting = false;
882
+ this._initialized = false;
883
+ this._session = session;
884
+ this._renderer = renderer;
885
+ this._hitMatrixBuffer = new Matrix4();
886
+ }
887
+ Dispose() {
888
+ var _a;
889
+ (_a = this._transientHitTestSource) == null ? void 0 : _a.cancel();
890
+ this._transientHitTestSource = void 0;
891
+ this._initialized = false;
892
+ }
893
+ Init() {
894
+ return __async(this, null, function* () {
895
+ if (!this._session) {
896
+ console.error(
897
+ "DIVEWebXRRaycaster: No session set in Init()! Aborting initialization..."
898
+ );
899
+ return Promise.reject();
900
+ }
901
+ if (this._requesting) {
902
+ console.error(
903
+ "DIVEWebXRRaycaster: Currently initializing! Aborting initialization..."
904
+ );
905
+ return Promise.reject();
906
+ }
907
+ if (this._initialized) {
908
+ console.error(
909
+ "DIVEWebXRRaycaster: Already initialized! Aborting initialization..."
910
+ );
911
+ return Promise.reject();
912
+ }
913
+ this._requesting = true;
914
+ this._transientHitTestSource = yield this._session.requestHitTestSourceForTransientInput({
915
+ profile: "generic-touchscreen"
916
+ });
917
+ this._referenceSpaceBuffer = this._renderer.xr.getReferenceSpace();
918
+ this._requesting = false;
919
+ if (!this._transientHitTestSource) {
920
+ return Promise.reject();
921
+ }
922
+ this._initialized = true;
923
+ console.log("DIVEWebXRRaycasterAR: Initialized");
924
+ return Promise.resolve(this);
925
+ });
926
+ }
927
+ GetIntersections(frame) {
928
+ if (!this._transientHitTestSource) return [];
929
+ const touches = frame.getHitTestResultsForTransientInput(
930
+ this._transientHitTestSource
931
+ );
932
+ if (touches.length === 0) return [];
933
+ const hits = touches.map((touch) => {
934
+ if (!this._referenceSpaceBuffer) return void 0;
935
+ if (!touch.results[0]) return void 0;
936
+ if (!touch.results[0].getPose) return void 0;
937
+ const pose = touch.results[0].getPose(this._referenceSpaceBuffer);
938
+ if (!pose) return void 0;
939
+ this._hitMatrixBuffer.fromArray(pose.transform.matrix);
940
+ const position = new Vector32().setFromMatrixPosition(
941
+ this._hitMatrixBuffer
942
+ );
943
+ return {
944
+ point: position,
945
+ matrix: this._hitMatrixBuffer,
946
+ object: void 0
947
+ };
948
+ });
949
+ return hits.filter((hit) => hit !== void 0);
950
+ }
951
+ };
952
+ }
953
+ });
954
+
955
+ // src/ar/webxr/raycaster/three/WebXRRaycasterTHREE.ts
956
+ import {
957
+ Raycaster as Raycaster2
958
+ } from "three";
959
+ var DIVEWebXRRaycasterTHREE;
960
+ var init_WebXRRaycasterTHREE = __esm({
961
+ "src/ar/webxr/raycaster/three/WebXRRaycasterTHREE.ts"() {
962
+ "use strict";
963
+ DIVEWebXRRaycasterTHREE = class {
964
+ constructor(renderer, scene) {
965
+ // internal raycaster
966
+ this._raycaster = new Raycaster2();
967
+ this._renderer = renderer;
968
+ this._scene = scene;
969
+ this._controller = this._renderer.xr.getController(0);
970
+ }
971
+ Init() {
972
+ return __async(this, null, function* () {
973
+ console.log("DIVEWebXRRaycasterTHREE: Initialized");
974
+ return Promise.resolve(this);
975
+ });
976
+ }
977
+ GetIntersections() {
978
+ this._controller.updateMatrixWorld();
979
+ this._raycaster.setFromXRController(this._controller);
980
+ const intersections = this._raycaster.intersectObjects(
981
+ this._scene.XRRoot.XRModelRoot.children
982
+ );
983
+ if (intersections.length === 0) return [];
984
+ return intersections.map((intersection) => {
985
+ return {
986
+ point: intersection.point,
987
+ matrix: intersection.object.matrixWorld,
988
+ object: intersection.object
989
+ };
990
+ });
991
+ }
992
+ };
993
+ }
994
+ });
995
+
996
+ // src/events/EventExecutor.ts
997
+ var DIVEEventExecutor;
998
+ var init_EventExecutor = __esm({
999
+ "src/events/EventExecutor.ts"() {
1000
+ "use strict";
1001
+ DIVEEventExecutor = class {
1002
+ constructor() {
1003
+ this._listeners = /* @__PURE__ */ new Map();
1004
+ }
1005
+ Subscribe(type, listener) {
1006
+ if (!this._listeners.get(type)) this._listeners.set(type, []);
1007
+ this._listeners.get(type).push(listener);
1008
+ return () => {
1009
+ const listenerArray = this._listeners.get(type);
1010
+ if (!listenerArray) return false;
1011
+ const existingIndex = listenerArray.findIndex(
1012
+ (entry) => entry === listener
1013
+ );
1014
+ if (existingIndex === -1) return false;
1015
+ listenerArray.splice(existingIndex, 1);
1016
+ return true;
1017
+ };
1018
+ }
1019
+ dispatch(type, payload) {
1020
+ const listenerArray = this._listeners.get(type);
1021
+ if (!listenerArray) return;
1022
+ listenerArray.forEach((listener) => listener(payload));
1023
+ }
1024
+ };
1025
+ }
1026
+ });
1027
+
1028
+ // src/ar/webxr/raycaster/WebXRRaycaster.ts
1029
+ var DIVEWebXRRaycaster;
1030
+ var init_WebXRRaycaster = __esm({
1031
+ "src/ar/webxr/raycaster/WebXRRaycaster.ts"() {
1032
+ "use strict";
1033
+ init_WebXRRaycasterAR();
1034
+ init_WebXRRaycasterTHREE();
1035
+ init_EventExecutor();
1036
+ DIVEWebXRRaycaster = class extends DIVEEventExecutor {
1037
+ constructor(session, renderer, scene) {
1038
+ super();
1039
+ this._initialized = false;
1040
+ this._arHitResultBuffer = [];
1041
+ this._sceneHitResultBuffer = [];
1042
+ // buffers
1043
+ this._hasHit = false;
1044
+ this._session = session;
1045
+ this._threeRaycaster = new DIVEWebXRRaycasterTHREE(renderer, scene);
1046
+ this._arRaycaster = new DIVEWebXRRaycasterAR(session, renderer);
1047
+ }
1048
+ Dispose() {
1049
+ this._initialized = false;
1050
+ }
1051
+ Init() {
1052
+ return __async(this, null, function* () {
1053
+ if (!this._session) {
1054
+ console.error(
1055
+ "DIVEWebXRRaycaster: No session set in Init()! Aborting initialization..."
1056
+ );
1057
+ return Promise.reject();
1058
+ }
1059
+ if (this._initialized) {
1060
+ console.error(
1061
+ "DIVEWebXRRaycaster: Already initialized! Aborting initialization..."
1062
+ );
1063
+ return Promise.reject();
1064
+ }
1065
+ yield this._threeRaycaster.Init();
1066
+ yield this._arRaycaster.Init();
1067
+ console.log("DIVEWebXRRaycaster: Initialized");
1068
+ this._initialized = true;
1069
+ return Promise.resolve(this);
1070
+ });
1071
+ }
1072
+ GetARIntersections(frame) {
1073
+ this._arHitResultBuffer = this._arRaycaster.GetIntersections(frame);
1074
+ if (this._arHitResultBuffer.length > 0) {
1075
+ this.onARHitFound(this._arHitResultBuffer[0]);
1076
+ } else {
1077
+ this.onARHitLost();
1078
+ }
1079
+ return this._arHitResultBuffer;
1080
+ }
1081
+ GetSceneIntersections() {
1082
+ this._sceneHitResultBuffer = this._threeRaycaster.GetIntersections();
1083
+ if (this._sceneHitResultBuffer.length > 0) {
1084
+ this.onSceneHitFound(this._sceneHitResultBuffer[0]);
1085
+ } else {
1086
+ this.onSceneHitLost();
1087
+ }
1088
+ return this._sceneHitResultBuffer;
1089
+ }
1090
+ onARHitFound(hit) {
1091
+ this._hasHit = true;
1092
+ this.dispatch("AR_HIT_FOUND", { hit });
1093
+ }
1094
+ onARHitLost() {
1095
+ if (!this._hasHit) return;
1096
+ this._hasHit = false;
1097
+ this.dispatch("AR_HIT_LOST");
1098
+ }
1099
+ onSceneHitFound(hit) {
1100
+ this._hasHit = true;
1101
+ this.dispatch("SCENE_HIT_FOUND", { hit });
1102
+ }
1103
+ onSceneHitLost() {
1104
+ if (!this._hasHit) return;
1105
+ this._hasHit = false;
1106
+ this.dispatch("SCENE_HIT_LOST");
1107
+ }
1108
+ };
1109
+ }
1110
+ });
1111
+
1112
+ // src/ar/webxr/origin/WebXROrigin.ts
1113
+ import { Matrix4 as Matrix42, Quaternion, Vector3 as Vector33 } from "three";
1114
+ var DIVEWebXROrigin;
1115
+ var init_WebXROrigin = __esm({
1116
+ "src/ar/webxr/origin/WebXROrigin.ts"() {
1117
+ "use strict";
1118
+ DIVEWebXROrigin = class {
1119
+ constructor(session, renderer, entityTypes) {
1120
+ this._raycastHitCounter = 0;
1121
+ this._originSetResolve = () => {
1122
+ };
1123
+ this._renderer = renderer;
1124
+ this._session = session;
1125
+ this._originSet = new Promise((resolve) => {
1126
+ this._originSetResolve = resolve;
1127
+ });
1128
+ this._requesting = false;
1129
+ this._initialized = false;
1130
+ this._referenceSpaceBuffer = null;
1131
+ this._hitTestSource = null;
1132
+ this._entityTypes = entityTypes || ["plane"];
1133
+ this._hitTestResultBuffer = [];
1134
+ this._matrix = new Matrix42();
1135
+ this._position = new Vector33();
1136
+ this._quaternion = new Quaternion();
1137
+ this._scale = new Vector33();
1138
+ this._originSet.then(() => {
1139
+ this._matrix.decompose(
1140
+ this._position,
1141
+ this._quaternion,
1142
+ this._scale
1143
+ );
1144
+ });
1145
+ }
1146
+ get originSet() {
1147
+ return this._originSet;
1148
+ }
1149
+ get matrix() {
1150
+ return this._matrix;
1151
+ }
1152
+ set matrix(value) {
1153
+ this._matrix = value;
1154
+ this._matrix.decompose(this._position, this._quaternion, this._scale);
1155
+ }
1156
+ get position() {
1157
+ return this._position;
1158
+ }
1159
+ get quaternion() {
1160
+ return this._quaternion;
1161
+ }
1162
+ get scale() {
1163
+ return this._scale;
1164
+ }
1165
+ Init() {
1166
+ return __async(this, null, function* () {
1167
+ if (this._initialized) {
1168
+ return Promise.resolve(this);
1169
+ }
1170
+ if (!this._session) {
1171
+ console.error(
1172
+ "DIVEWebXROrigin: No session set in Init()! Aborting initialization..."
1173
+ );
1174
+ return Promise.reject();
1175
+ }
1176
+ if (this._requesting) {
1177
+ console.error(
1178
+ "DIVEWebXROrigin: Currently initializing! Aborting initialization..."
1179
+ );
1180
+ return Promise.reject();
1181
+ }
1182
+ this._requesting = true;
1183
+ const referenceSpace = yield this._session.requestReferenceSpace("viewer");
1184
+ this._hitTestSource = (yield this._session.requestHitTestSource({
1185
+ space: referenceSpace,
1186
+ entityTypes: this._entityTypes
1187
+ })) || null;
1188
+ this._requesting = false;
1189
+ if (!this._hitTestSource) {
1190
+ return Promise.reject();
1191
+ }
1192
+ this._initialized = true;
1193
+ return Promise.resolve(this);
1194
+ });
1195
+ }
1196
+ Dispose() {
1197
+ var _a;
1198
+ this._initialized = false;
1199
+ this._requesting = false;
1200
+ (_a = this._hitTestSource) == null ? void 0 : _a.cancel();
1201
+ this._hitTestSource = null;
1202
+ this._hitTestResultBuffer = [];
1203
+ this._matrix = new Matrix42();
1204
+ this._position = new Vector33();
1205
+ this._quaternion = new Quaternion();
1206
+ this._scale = new Vector33();
1207
+ }
1208
+ Update(frame) {
1209
+ if (!this._initialized) return;
1210
+ if (!this._hitTestSource) {
1211
+ throw new Error(
1212
+ "DIVEWebXRRaycaster: Critical Error: HitTestSource not available but WebXROrigin is initialized!"
1213
+ );
1214
+ }
1215
+ this._hitTestResultBuffer = frame.getHitTestResults(
1216
+ this._hitTestSource
1217
+ );
1218
+ if (this._hitTestResultBuffer.length > 0) {
1219
+ this._referenceSpaceBuffer = this._renderer.xr.getReferenceSpace();
1220
+ if (!this._referenceSpaceBuffer) {
1221
+ this.onHitLost();
1222
+ return;
1223
+ }
1224
+ const pose = this._hitTestResultBuffer[0].getPose(
1225
+ this._referenceSpaceBuffer
1226
+ );
1227
+ if (!pose) {
1228
+ this.onHitLost();
1229
+ return;
1230
+ }
1231
+ this.onHitFound(pose);
1232
+ } else {
1233
+ this.onHitLost();
1234
+ }
1235
+ }
1236
+ onHitFound(pose) {
1237
+ this._raycastHitCounter++;
1238
+ this.matrix.fromArray(pose.transform.matrix);
1239
+ if (this._raycastHitCounter > 50) {
1240
+ this._originSetResolve();
1241
+ }
1242
+ }
1243
+ onHitLost() {
1244
+ this._raycastHitCounter = 0;
1245
+ }
1246
+ };
1247
+ }
1248
+ });
1249
+
1250
+ // src/ar/webxr/touchscreencontrols/WebXRTouchscreenControls.ts
1251
+ import { Vector2 as Vector22 } from "three";
1252
+ var DIVEWebXRTouchscreenControls;
1253
+ var init_WebXRTouchscreenControls = __esm({
1254
+ "src/ar/webxr/touchscreencontrols/WebXRTouchscreenControls.ts"() {
1255
+ "use strict";
1256
+ init_EventExecutor();
1257
+ DIVEWebXRTouchscreenControls = class extends DIVEEventExecutor {
1258
+ constructor(session) {
1259
+ super();
1260
+ // touch members
1261
+ this._touchCount = 0;
1262
+ this._touches = [];
1263
+ // rotate members
1264
+ this._handleRotateStarted = false;
1265
+ this._handleRotateMoved = false;
1266
+ this._handleRotateEnded = false;
1267
+ this._startAngle = 0;
1268
+ this._lastAngle = 0;
1269
+ this._angleDelta = 0;
1270
+ // scale members
1271
+ this._handlePinchStarted = false;
1272
+ this._handlePinchMoved = false;
1273
+ this._handlePinchEnded = false;
1274
+ this._scaleDistanceStart = 0;
1275
+ this._currentDistance = 1;
1276
+ this._deltaDistance = 0;
1277
+ this._session = session;
1278
+ this._touches = [
1279
+ {
1280
+ start: new Vector22(),
1281
+ current: new Vector22(),
1282
+ delta: new Vector22()
1283
+ },
1284
+ {
1285
+ start: new Vector22(),
1286
+ current: new Vector22(),
1287
+ delta: new Vector22()
1288
+ }
1289
+ ];
1290
+ this._handleRotateStarted = false;
1291
+ window.addEventListener(
1292
+ "touchstart",
1293
+ (e) => this.onTouchStart(e)
1294
+ );
1295
+ window.addEventListener(
1296
+ "touchmove",
1297
+ (e) => this.onTouchMove(e)
1298
+ );
1299
+ window.addEventListener(
1300
+ "touchend",
1301
+ (e) => this.onTouchEnd(e)
1302
+ );
1303
+ this._session.addEventListener(
1304
+ "selectstart",
1305
+ () => this.onSessionSelectStart()
1306
+ );
1307
+ this._session.addEventListener(
1308
+ "selectend",
1309
+ () => this.onSessionSelectEnd()
1310
+ );
1311
+ }
1312
+ Dispose() {
1313
+ window.removeEventListener(
1314
+ "touchstart",
1315
+ (e) => this.onTouchStart(e)
1316
+ );
1317
+ window.removeEventListener(
1318
+ "touchmove",
1319
+ (e) => this.onTouchMove(e)
1320
+ );
1321
+ window.removeEventListener(
1322
+ "touchend",
1323
+ (e) => this.onTouchEnd(e)
1324
+ );
1325
+ this._session.removeEventListener(
1326
+ "selectstart",
1327
+ () => this.onSessionSelectStart()
1328
+ );
1329
+ this._session.removeEventListener(
1330
+ "selectend",
1331
+ () => this.onSessionSelectEnd()
1332
+ );
1333
+ }
1334
+ onTouchStart(event) {
1335
+ this._touchCount = event.touches.length;
1336
+ this._touches[0].start.set(
1337
+ event.touches[0].clientX,
1338
+ event.touches[0].clientY
1339
+ );
1340
+ this._touches[0].current.set(
1341
+ event.touches[0].clientX,
1342
+ event.touches[0].clientY
1343
+ );
1344
+ this._touches[0].delta.set(0, 0);
1345
+ if (this._touchCount > 1) {
1346
+ this._touches[1].start.set(
1347
+ event.touches[1].clientX,
1348
+ event.touches[1].clientY
1349
+ );
1350
+ this._touches[1].current.set(
1351
+ event.touches[1].clientX,
1352
+ event.touches[1].clientY
1353
+ );
1354
+ this._touches[1].delta.set(0, 0);
1355
+ }
1356
+ if (this._touchCount === 2) {
1357
+ this.handleRotateStart();
1358
+ this.handlePinchStart();
1359
+ }
1360
+ if (this._handleRotateStarted) {
1361
+ this.dispatch("ROTATE_START", {
1362
+ current: 0
1363
+ });
1364
+ this._handleRotateStarted = false;
1365
+ }
1366
+ if (this._handlePinchStarted) {
1367
+ this.dispatch("PINCH_START", {
1368
+ current: 0
1369
+ });
1370
+ this._handlePinchStarted = false;
1371
+ }
1372
+ }
1373
+ onTouchMove(event) {
1374
+ this._touchCount = event.touches.length;
1375
+ this._touches[0].start.set(
1376
+ event.touches[0].clientX,
1377
+ event.touches[0].clientY
1378
+ );
1379
+ this._touches[0].current.set(
1380
+ event.touches[0].clientX,
1381
+ event.touches[0].clientY
1382
+ );
1383
+ this._touches[0].delta.copy(
1384
+ this._touches[0].current.clone().sub(this._touches[0].start)
1385
+ );
1386
+ if (this._touchCount > 1) {
1387
+ this._touches[1].start.set(
1388
+ event.touches[1].clientX,
1389
+ event.touches[1].clientY
1390
+ );
1391
+ this._touches[1].current.set(
1392
+ event.touches[1].clientX,
1393
+ event.touches[1].clientY
1394
+ );
1395
+ this._touches[1].delta.copy(
1396
+ this._touches[1].current.clone().sub(this._touches[1].start)
1397
+ );
1398
+ }
1399
+ if (this._touchCount === 2) {
1400
+ this.handleRotateMoved();
1401
+ this.handlePinchMoved();
1402
+ }
1403
+ if (this._touchCount === 1) {
1404
+ this.dispatch("TOUCH_MOVE", {
1405
+ touches: [
1406
+ {
1407
+ current: this._touches[0].current.clone(),
1408
+ delta: this._touches[0].delta.clone()
1409
+ },
1410
+ {
1411
+ current: this._touches[1].current.clone(),
1412
+ delta: this._touches[1].delta.clone()
1413
+ }
1414
+ ],
1415
+ touchCount: this._touchCount
1416
+ });
1417
+ }
1418
+ if (this._touchCount === 2) {
1419
+ if (this._handleRotateMoved) {
1420
+ this.dispatch("ROTATE_MOVE", {
1421
+ current: this._lastAngle,
1422
+ delta: this._angleDelta
1423
+ });
1424
+ this._handleRotateMoved = false;
1425
+ }
1426
+ if (this._handlePinchMoved) {
1427
+ this.dispatch("PINCH_MOVE", {
1428
+ current: this._currentDistance,
1429
+ delta: this._deltaDistance
1430
+ });
1431
+ this._handlePinchMoved = false;
1432
+ }
1433
+ }
1434
+ }
1435
+ onTouchEnd(event) {
1436
+ this._touchCount = event.touches.length;
1437
+ if (this._touchCount === 0) {
1438
+ this._touches[0].start.set(0, 0);
1439
+ this._touches[0].current.set(0, 0);
1440
+ this._touches[0].delta.set(0, 0);
1441
+ }
1442
+ if (this._touchCount === 1) {
1443
+ this.handleRotateEnded();
1444
+ this.handlePinchEnded();
1445
+ this._touches[1].start.set(0, 0);
1446
+ this._touches[1].current.set(0, 0);
1447
+ this._touches[1].delta.set(0, 0);
1448
+ }
1449
+ if (this._handleRotateEnded) {
1450
+ this.dispatch("ROTATE_END", {
1451
+ current: this._lastAngle
1452
+ });
1453
+ this._handleRotateEnded = false;
1454
+ }
1455
+ if (this._handlePinchEnded) {
1456
+ this.dispatch("PINCH_END", {
1457
+ current: this._currentDistance
1458
+ });
1459
+ this._handlePinchEnded = false;
1460
+ }
1461
+ }
1462
+ onSessionSelectStart() {
1463
+ this.dispatch("TOUCH_START", {
1464
+ touches: [
1465
+ {
1466
+ current: this._touches[0].current.clone()
1467
+ },
1468
+ {
1469
+ current: this._touches[1].current.clone()
1470
+ }
1471
+ ],
1472
+ touchCount: this._touchCount
1473
+ });
1474
+ }
1475
+ onSessionSelectEnd() {
1476
+ this.dispatch("TOUCH_END", {
1477
+ touches: [
1478
+ {
1479
+ current: this._touches[0].current.clone()
1480
+ },
1481
+ {
1482
+ current: this._touches[1].current.clone()
1483
+ }
1484
+ ],
1485
+ touchCount: this._touchCount
1486
+ });
1487
+ }
1488
+ // rotation handler
1489
+ handleRotateStart() {
1490
+ this._handleRotateStarted = true;
1491
+ this._startAngle = this._touches[1].start.clone().sub(this._touches[0].current).angle();
1492
+ }
1493
+ handleRotateMoved() {
1494
+ this._handleRotateMoved = true;
1495
+ const currentAngle = this._touches[1].current.clone().sub(this._touches[0].current).angle();
1496
+ this._angleDelta = currentAngle - this._startAngle;
1497
+ this._lastAngle = this._angleDelta * -1;
1498
+ }
1499
+ handleRotateEnded() {
1500
+ this._handleRotateEnded = true;
1501
+ }
1502
+ // pinch handler
1503
+ handlePinchStart() {
1504
+ this._handlePinchStarted = true;
1505
+ this._scaleDistanceStart = this._touches[1].start.distanceTo(
1506
+ this._touches[0].current
1507
+ );
1508
+ }
1509
+ handlePinchMoved() {
1510
+ this._handlePinchMoved = true;
1511
+ const beforeDistance = this._currentDistance;
1512
+ const distance = this._touches[1].current.distanceTo(
1513
+ this._touches[0].current
1514
+ );
1515
+ this._currentDistance = distance / this._scaleDistanceStart;
1516
+ this._deltaDistance = this._currentDistance - beforeDistance;
1517
+ }
1518
+ handlePinchEnded() {
1519
+ this._handlePinchEnded = true;
1520
+ }
1521
+ };
1522
+ }
1523
+ });
1524
+
1525
+ // src/ar/webxr/controller/WebXRController.ts
1526
+ import {
1527
+ Mesh as Mesh2,
1528
+ Object3D as Object3D4,
1529
+ Quaternion as Quaternion2,
1530
+ Vector3 as Vector34
1531
+ } from "three";
1532
+ var DIVEWebXRController;
1533
+ var init_WebXRController = __esm({
1534
+ "src/ar/webxr/controller/WebXRController.ts"() {
1535
+ "use strict";
1536
+ init_WebXRCrosshair();
1537
+ init_WebXRRaycaster();
1538
+ init_WebXROrigin();
1539
+ init_WebXRTouchscreenControls();
1540
+ init_findInterface();
1541
+ DIVEWebXRController = class extends Object3D4 {
1542
+ constructor(session, renderer, scene) {
1543
+ super();
1544
+ this._frameBuffer = null;
1545
+ this._handNodeInitialPosition = new Vector34();
1546
+ this._placed = false;
1547
+ // grabbing
1548
+ this._grabbedObject = null;
1549
+ this._arHitPosition = new Vector34();
1550
+ this._arHitQuaternion = new Quaternion2();
1551
+ this._arHitScale = new Vector34(1, 1, 1);
1552
+ // grabbing position
1553
+ this._initialObjectPosition = null;
1554
+ this._initialRaycastHit = null;
1555
+ this._deltaRaycastHit = new Vector34();
1556
+ // grabbing rotation
1557
+ this._touchQuaterion = new Quaternion2();
1558
+ // grabbing scale
1559
+ this._touchScale = 1;
1560
+ this._scaleThreshold = 0.1;
1561
+ this._startTouchQuaternion = new Quaternion2();
1562
+ this._startTouchScale = 1;
1563
+ this._renderer = renderer;
1564
+ this._scene = scene;
1565
+ this._session = session;
1566
+ this._xrRaycaster = new DIVEWebXRRaycaster(session, renderer, scene);
1567
+ this._origin = new DIVEWebXROrigin(this._session, this._renderer, [
1568
+ "plane"
1569
+ ]);
1570
+ this._crosshair = new DIVEWebXRCrosshair();
1571
+ this._crosshair.visible = false;
1572
+ this._xrCamera = this._renderer.xr.getCamera();
1573
+ this._scene.XRRoot.XRHandNode.position.set(0, -0.05, -0.25);
1574
+ this._handNodeInitialPosition = this._scene.XRRoot.XRHandNode.position.clone();
1575
+ this._touchscreenControls = new DIVEWebXRTouchscreenControls(
1576
+ this._session
1577
+ );
1578
+ this._touchscreenControls.Subscribe(
1579
+ "TOUCH_START",
1580
+ () => this.onTouchStart()
1581
+ );
1582
+ this._touchscreenControls.Subscribe(
1583
+ "TOUCH_MOVE",
1584
+ () => this.onTouchMove()
1585
+ );
1586
+ this._touchscreenControls.Subscribe(
1587
+ "TOUCH_END",
1588
+ (p) => this.onTouchEnd(p)
1589
+ );
1590
+ this._touchscreenControls.Subscribe(
1591
+ "ROTATE_START",
1592
+ () => this.onRotateStart()
1593
+ );
1594
+ this._touchscreenControls.Subscribe(
1595
+ "ROTATE_MOVE",
1596
+ (p) => this.onRotateMove(p)
1597
+ );
1598
+ this._touchscreenControls.Subscribe(
1599
+ "PINCH_START",
1600
+ () => this.onPinchStart()
1601
+ );
1602
+ this._touchscreenControls.Subscribe(
1603
+ "PINCH_MOVE",
1604
+ (p) => this.onPinchMove(p)
1605
+ );
1606
+ }
1607
+ Init() {
1608
+ return __async(this, null, function* () {
1609
+ this.prepareScene();
1610
+ yield this.initOrigin();
1611
+ yield this.initRaycaster();
1612
+ return Promise.resolve(this);
1613
+ });
1614
+ }
1615
+ Dispose() {
1616
+ this.restoreScene();
1617
+ this._origin.Dispose();
1618
+ this._xrRaycaster.Dispose();
1619
+ this._placed = false;
1620
+ }
1621
+ Update(frame) {
1622
+ this._frameBuffer = frame;
1623
+ if (!this._placed) {
1624
+ this._xrCamera.updateMatrixWorld();
1625
+ this._scene.XRRoot.XRHandNode.position.copy(
1626
+ this._handNodeInitialPosition.clone().applyMatrix4(this._xrCamera.matrixWorld)
1627
+ );
1628
+ this._scene.XRRoot.XRHandNode.quaternion.setFromRotationMatrix(
1629
+ this._xrCamera.matrixWorld
1630
+ );
1631
+ if (this._origin) {
1632
+ this._origin.Update(frame);
1633
+ }
1634
+ }
1635
+ }
1636
+ // placement
1637
+ initOrigin() {
1638
+ return __async(this, null, function* () {
1639
+ this._origin = yield this._origin.Init();
1640
+ this._origin.originSet.then(() => {
1641
+ this.placeObjects(this._origin.matrix);
1642
+ });
1643
+ });
1644
+ }
1645
+ placeObjects(matrix) {
1646
+ this._scene.XRRoot.XRModelRoot.matrix.copy(matrix);
1647
+ [...this._scene.XRRoot.XRHandNode.children].forEach((child) => {
1648
+ this._scene.XRRoot.XRModelRoot.add(child);
1649
+ });
1650
+ this._placed = true;
1651
+ }
1652
+ // grabbing
1653
+ updateObject() {
1654
+ if (!this._grabbedObject) return;
1655
+ this._grabbedObject.position.copy(this._arHitPosition);
1656
+ this._grabbedObject.quaternion.copy(
1657
+ this._arHitQuaternion.clone().multiply(this._touchQuaterion)
1658
+ );
1659
+ this._grabbedObject.scale.copy(
1660
+ new Vector34(
1661
+ this._touchScale,
1662
+ this._touchScale,
1663
+ this._touchScale
1664
+ ).multiply(this._arHitScale)
1665
+ );
1666
+ }
1667
+ onTouchStart() {
1668
+ const sceneHits = this._xrRaycaster.GetSceneIntersections();
1669
+ console.log("sceneHits", sceneHits);
1670
+ if (sceneHits.length === 0) return;
1671
+ if (!sceneHits[0].object) return;
1672
+ const moveable = findInterface(
1673
+ sceneHits[0].object,
1674
+ "isMovable"
1675
+ );
1676
+ if (!moveable) return;
1677
+ this._grabbedObject = moveable;
1678
+ }
1679
+ onTouchMove() {
1680
+ if (!this._frameBuffer) return;
1681
+ if (!this._grabbedObject) return;
1682
+ const intersections = this._xrRaycaster.GetARIntersections(
1683
+ this._frameBuffer
1684
+ );
1685
+ if (intersections.length === 0) {
1686
+ this._crosshair.visible = false;
1687
+ return;
1688
+ }
1689
+ const hit = intersections[0];
1690
+ this._crosshair.visible = true;
1691
+ this._crosshair.matrix.copy(hit.matrix);
1692
+ if (!this._grabbedObject) return;
1693
+ if (!this._initialObjectPosition || !this._initialRaycastHit) {
1694
+ this._initialObjectPosition = this._grabbedObject.position.clone();
1695
+ this._initialRaycastHit = hit.point.clone();
1696
+ }
1697
+ hit.matrix.decompose(
1698
+ this._arHitPosition,
1699
+ this._arHitQuaternion,
1700
+ this._arHitScale
1701
+ );
1702
+ this._deltaRaycastHit.copy(
1703
+ hit.point.clone().sub(this._initialRaycastHit)
1704
+ );
1705
+ this._arHitPosition.copy(
1706
+ this._initialObjectPosition.clone().add(this._deltaRaycastHit)
1707
+ );
1708
+ console.log("arHitPosition", this._arHitPosition);
1709
+ this.updateObject();
1710
+ }
1711
+ onTouchEnd(payload) {
1712
+ if (payload.touchCount === 0) {
1713
+ this._crosshair.visible = false;
1714
+ this._initialObjectPosition = null;
1715
+ this._initialRaycastHit = null;
1716
+ this._grabbedObject = null;
1717
+ }
1718
+ }
1719
+ onRotateStart() {
1720
+ this._startTouchQuaternion = this._touchQuaterion.clone();
1721
+ }
1722
+ onRotateMove(payload) {
1723
+ this._touchQuaterion.setFromAxisAngle(
1724
+ new Vector34(0, -1, 0),
1725
+ payload.delta * 3
1726
+ );
1727
+ this._touchQuaterion.multiply(this._startTouchQuaternion);
1728
+ this.updateObject();
1729
+ }
1730
+ onPinchStart() {
1731
+ this._startTouchScale = this._touchScale;
1732
+ }
1733
+ onPinchMove(payload) {
1734
+ this._touchScale = this._startTouchScale * payload.current;
1735
+ this.updateObject();
1736
+ }
1737
+ // prepare & cleanup scene
1738
+ prepareScene() {
1739
+ this._scene.XRRoot.XRModelRoot.matrixAutoUpdate = false;
1740
+ this._scene.add(this._crosshair);
1741
+ const children = [];
1742
+ this._scene.Root.children.forEach((child) => {
1743
+ const clone = child.clone();
1744
+ clone.layers.enableAll();
1745
+ clone.traverse((obj) => {
1746
+ obj.layers.enableAll();
1747
+ if (obj instanceof Mesh2) {
1748
+ obj.scale.set(0.1, 0.1, 0.1);
1749
+ }
1750
+ });
1751
+ clone.position.set(0, 0, 0);
1752
+ children.push(clone);
1753
+ });
1754
+ this._scene.XRRoot.XRHandNode.add(...children);
1755
+ }
1756
+ restoreScene() {
1757
+ this._scene.remove(this._crosshair);
1758
+ this._scene.XRRoot.XRHandNode.clear();
1759
+ this._scene.XRRoot.XRModelRoot.clear();
1760
+ this._scene.XRRoot.XRModelRoot.matrixAutoUpdate = true;
1761
+ }
1762
+ // raycast
1763
+ initRaycaster() {
1764
+ return __async(this, null, function* () {
1765
+ yield this._xrRaycaster.Init();
1766
+ if (!this._xrRaycaster) {
1767
+ console.error(
1768
+ "Raycaster not initialized successfully. Aborting WebXR..."
1769
+ );
1770
+ this.Dispose();
1771
+ return Promise.reject();
1772
+ }
1773
+ });
1774
+ }
1775
+ };
1776
+ }
1777
+ });
1778
+
1779
+ // src/ar/webxr/WebXR.ts
1780
+ var _DIVEWebXR, DIVEWebXR;
1781
+ var init_WebXR = __esm({
1782
+ "src/ar/webxr/WebXR.ts"() {
1783
+ "use strict";
1784
+ init_Overlay();
1785
+ init_WebXRController();
1786
+ _DIVEWebXR = class _DIVEWebXR {
1787
+ static Launch(renderer, scene, controller) {
1788
+ return __async(this, null, function* () {
1789
+ this._renderer = renderer;
1790
+ this._scene = scene;
1791
+ this._controller = controller;
1792
+ this._cameraPosition = this._controller.object.position.clone();
1793
+ this._cameraTarget = this._controller.target.clone();
1794
+ if (!navigator.xr) {
1795
+ console.error("WebXR not supported");
1796
+ return Promise.reject();
1797
+ }
1798
+ this._renderer.xr.enabled = true;
1799
+ this._scene.InitXR(renderer);
1800
+ if (!_DIVEWebXR._overlay) {
1801
+ const overlay = new Overlay();
1802
+ _DIVEWebXR._overlay = overlay;
1803
+ }
1804
+ _DIVEWebXR._options.domOverlay = { root: _DIVEWebXR._overlay.Element };
1805
+ const session = yield navigator.xr.requestSession(
1806
+ "immersive-ar",
1807
+ this._options
1808
+ );
1809
+ session.addEventListener("end", () => {
1810
+ this._onSessionEnded();
1811
+ });
1812
+ renderer.xr.setReferenceSpaceType(this._referenceSpaceType);
1813
+ yield renderer.xr.setSession(session);
1814
+ _DIVEWebXR._overlay.Element.style.display = "";
1815
+ this._session = session;
1816
+ _DIVEWebXR._overlay.CloseButton.addEventListener(
1817
+ "click",
1818
+ () => this.End()
1819
+ );
1820
+ yield this._onSessionStarted();
1821
+ return Promise.resolve();
1822
+ });
1823
+ }
1824
+ static Update(_time, frame) {
1825
+ if (!this._session) return;
1826
+ if (this._xrController) {
1827
+ this._xrController.Update(frame);
1828
+ }
1829
+ }
1830
+ static End() {
1831
+ if (!this._session) return;
1832
+ this._session.end();
1833
+ }
1834
+ static _onSessionStarted() {
1835
+ return __async(this, null, function* () {
1836
+ if (!this._session) return;
1837
+ this._renderCallbackId = this._renderer.AddPreRenderCallback(
1838
+ (time, frame) => {
1839
+ this.Update(time, frame);
1840
+ }
1841
+ );
1842
+ this._xrController = new DIVEWebXRController(
1843
+ this._session,
1844
+ this._renderer,
1845
+ this._scene
1846
+ );
1847
+ yield this._xrController.Init().catch(() => {
1848
+ this.End();
1849
+ });
1850
+ return Promise.resolve();
1851
+ });
1852
+ }
1853
+ static _onSessionEnded() {
1854
+ if (!this._session) return;
1855
+ if (this._xrController) {
1856
+ this._xrController.Dispose();
1857
+ }
1858
+ if (this._renderCallbackId) {
1859
+ this._renderer.RemovePreRenderCallback(this._renderCallbackId);
1860
+ this._renderCallbackId = null;
1861
+ }
1862
+ this._renderer.xr.enabled = false;
1863
+ const canvasWrapper = this._renderer.domElement.parentElement;
1864
+ if (canvasWrapper) {
1865
+ const { clientWidth, clientHeight } = canvasWrapper;
1866
+ this._renderer.OnResize(clientWidth, clientHeight);
1867
+ this._controller.object.OnResize(clientWidth, clientHeight);
1868
+ }
1869
+ this._controller.object.position.copy(this._cameraPosition);
1870
+ this._controller.target.copy(this._cameraTarget);
1871
+ this._cameraPosition.set(0, 0, 0);
1872
+ this._cameraTarget.set(0, 0, 0);
1873
+ this._scene.DisposeXR();
1874
+ this._session.removeEventListener("end", this._onSessionEnded);
1875
+ _DIVEWebXR._overlay.Element.style.display = "none";
1876
+ this._session = null;
1877
+ }
1878
+ };
1879
+ // render loop members
1880
+ _DIVEWebXR._renderCallbackId = null;
1881
+ // setup members
1882
+ _DIVEWebXR._session = null;
1883
+ _DIVEWebXR._referenceSpaceType = "local";
1884
+ _DIVEWebXR._overlay = null;
1885
+ _DIVEWebXR._options = {
1886
+ requiredFeatures: [
1887
+ "local",
1888
+ "hit-test"
1889
+ ],
1890
+ optionalFeatures: [
1891
+ "light-estimation",
1892
+ "local-floor",
1893
+ "dom-overlay",
1894
+ "depth-sensing"
1895
+ ],
1896
+ depthSensing: {
1897
+ usagePreference: ["gpu-optimized"],
1898
+ dataFormatPreference: []
1899
+ },
1900
+ domOverlay: { root: {} }
1901
+ };
1902
+ _DIVEWebXR._xrController = null;
1903
+ DIVEWebXR = _DIVEWebXR;
1904
+ }
1905
+ });
1906
+
1907
+ // src/ar/AR.ts
1908
+ var AR_exports = {};
1909
+ __export(AR_exports, {
1910
+ DIVEAR: () => DIVEAR
1911
+ });
1912
+ var DIVEAR;
1913
+ var init_AR = __esm({
1914
+ "src/ar/AR.ts"() {
1915
+ "use strict";
1916
+ init_Info();
1917
+ init_ARQuickLook();
1918
+ init_WebXR();
1919
+ DIVEAR = class {
1920
+ constructor(renderer, scene, controller) {
1921
+ this.arPlacement = "floor";
1922
+ this.arScale = "auto";
1923
+ this._renderer = renderer;
1924
+ this._scene = scene;
1925
+ this._controller = controller;
1926
+ }
1927
+ Launch() {
1928
+ return __async(this, null, function* () {
1929
+ const system = DIVEInfo.GetSystem();
1930
+ if (system === "iOS") {
1931
+ const support = DIVEInfo.GetSupportsARQuickLook();
1932
+ if (!support) {
1933
+ console.log("ARQuickLook not supported");
1934
+ return Promise.reject();
1935
+ }
1936
+ console.log("Launching AR on iOS");
1937
+ yield DIVEARQuickLook.Launch(this._scene);
1938
+ return Promise.resolve();
1939
+ }
1940
+ if (system === "Android") {
1941
+ this.openSceneViewer();
1942
+ return;
1943
+ const support = yield DIVEInfo.GetSupportsWebXR();
1944
+ if (!support) {
1945
+ console.log(
1946
+ "WebXR not supported. Reason: " + WebXRUnsupportedReason[DIVEInfo.GetWebXRUnsupportedReason()]
1947
+ );
1948
+ return Promise.reject();
1949
+ }
1950
+ console.log("Launching AR on Android");
1951
+ yield DIVEWebXR.Launch(
1952
+ this._renderer,
1953
+ this._scene,
1954
+ this._controller
1955
+ );
1956
+ return Promise.resolve();
1957
+ }
1958
+ console.log(
1959
+ "AR not supported. Not a mobile system. (System is " + system + ")"
1960
+ );
1961
+ });
1962
+ }
1963
+ openSceneViewer() {
1964
+ const src = this.createSceneViewerSrc();
1965
+ const anchor = document.createElement("a");
1966
+ const noArViewerSigil = "#model-viewer-no-ar-fallback";
1967
+ const location = self.location.toString();
1968
+ const locationUrl = new URL(location);
1969
+ const modelUrl = new URL(src, location);
1970
+ if (modelUrl.hash) modelUrl.hash = "";
1971
+ const params = new URLSearchParams(modelUrl.search);
1972
+ locationUrl.hash = noArViewerSigil;
1973
+ params.set("mode", "ar_preferred");
1974
+ if (!params.has("disable_occlusion")) {
1975
+ params.set("disable_occlusion", "true");
1976
+ }
1977
+ if (this.arScale === "fixed") {
1978
+ params.set("resizable", "false");
1979
+ }
1980
+ if (this.arPlacement === "wall") {
1981
+ params.set("enable_vertical_placement", "true");
1982
+ }
1983
+ if (params.has("sound")) {
1984
+ const soundUrl = new URL(params.get("sound"), location);
1985
+ params.set("sound", soundUrl.toString());
1986
+ }
1987
+ if (params.has("link")) {
1988
+ const linkUrl = new URL(params.get("link"), location);
1989
+ params.set("link", linkUrl.toString());
1990
+ }
1991
+ console.log("modelUrl.toString()", modelUrl.toString());
1992
+ console.log(
1993
+ "encodeURIComponent(modelUrl.toString())",
1994
+ encodeURIComponent(modelUrl.toString())
1995
+ );
1996
+ const intent = `intent://arvr.google.com/scene-viewer/1.2?${params.toString() + "&file=" + modelUrl.toString()}#Intent;scheme=https;package=com.google.android.googlequicksearchbox;action=android.intent.action.VIEW;S.browser_fallback_url=${encodeURIComponent(
1997
+ locationUrl.toString()
1998
+ )};end;`;
1999
+ console.log({ intent });
2000
+ const undoHashChange = () => {
2001
+ if (self.location.hash === noArViewerSigil) {
2002
+ self.history.back();
2003
+ console.warn(
2004
+ "Error while trying to present in AR with Scene Viewer"
2005
+ );
2006
+ console.warn("Falling back to next ar-mode");
2007
+ }
2008
+ };
2009
+ self.addEventListener("hashchange", undoHashChange, { once: true });
2010
+ anchor.setAttribute("href", intent);
2011
+ console.log("Attempting to present in AR with Scene Viewer...");
2012
+ anchor.click();
2013
+ }
2014
+ createSceneViewerSrc() {
2015
+ let uri = null;
2016
+ this._scene.traverse((object) => {
2017
+ if (uri) return;
2018
+ if (object.userData.uri) {
2019
+ uri = object.userData.uri;
2020
+ }
2021
+ });
2022
+ if (!uri) {
2023
+ throw new Error("No model found in scene");
2024
+ }
2025
+ return uri;
2026
+ }
2027
+ };
2028
+ }
2029
+ });
2030
+
628
2031
  // src/renderer/Renderer.ts
629
2032
  import {
630
2033
  MathUtils,
@@ -669,8 +2072,8 @@ var DIVERenderer = class extends WebGLRenderer {
669
2072
  }
670
2073
  // Starts the renderer with the given scene and camera.
671
2074
  StartRenderer(scene, cam) {
672
- this.setAnimationLoop(() => {
673
- this.internal_render(scene, cam);
2075
+ this.setAnimationLoop((time, frame) => {
2076
+ this.internal_render(scene, cam, time, frame);
674
2077
  });
675
2078
  this.running = true;
676
2079
  }
@@ -744,14 +2147,14 @@ var DIVERenderer = class extends WebGLRenderer {
744
2147
  * @param scene Scene to render.
745
2148
  * @param cam Camera to render with.
746
2149
  */
747
- internal_render(scene, cam) {
2150
+ internal_render(scene, cam, time, frame) {
748
2151
  if ((this.paused || !this.running) && !this.force) return;
749
2152
  this.preRenderCallbacks.forEach((callback) => {
750
- callback();
2153
+ callback(time, frame);
751
2154
  });
752
2155
  this.render(scene, cam);
753
2156
  this.postRenderCallbacks.forEach((callback) => {
754
- callback();
2157
+ callback(time, frame);
755
2158
  });
756
2159
  this.force = false;
757
2160
  }
@@ -761,7 +2164,7 @@ var DIVERenderer = class extends WebGLRenderer {
761
2164
  import { Color as Color7, Scene as Scene2 } from "three";
762
2165
 
763
2166
  // src/scene/root/Root.ts
764
- import { Box3 as Box32, Color as Color5, Object3D as Object3D6 } from "three";
2167
+ import { Box3 as Box32, Color as Color5, Object3D as Object3D8 } from "three";
765
2168
 
766
2169
  // src/light/AmbientLight.ts
767
2170
  init_VisibilityLayerMask();
@@ -791,10 +2194,10 @@ var DIVEAmbientLight = class extends Object3D {
791
2194
  import {
792
2195
  PointLight,
793
2196
  SphereGeometry,
794
- MeshBasicMaterial,
795
- Mesh,
2197
+ MeshBasicMaterial as MeshBasicMaterial2,
2198
+ Mesh as Mesh3,
796
2199
  FrontSide,
797
- Object3D as Object3D3
2200
+ Object3D as Object3D5
798
2201
  } from "three";
799
2202
 
800
2203
  // src/com/Communication.ts
@@ -813,6 +2216,7 @@ var _DIVECommunication = class _DIVECommunication {
813
2216
  this.toolbox = toolbox;
814
2217
  this._mediaGenerator = null;
815
2218
  this._io = null;
2219
+ this._ar = null;
816
2220
  _DIVECommunication.__instances.push(this);
817
2221
  }
818
2222
  static get(id) {
@@ -847,6 +2251,13 @@ var _DIVECommunication = class _DIVECommunication {
847
2251
  }
848
2252
  return this._io;
849
2253
  }
2254
+ get ar() {
2255
+ if (!this._ar) {
2256
+ const DIVEAR2 = (init_AR(), __toCommonJS(AR_exports)).DIVEAR;
2257
+ this._ar = new DIVEAR2(this.renderer, this.scene, this.controller);
2258
+ }
2259
+ return this._ar;
2260
+ }
850
2261
  DestroyInstance() {
851
2262
  const existingIndex = _DIVECommunication.__instances.findIndex(
852
2263
  (entry) => entry.id === this.id
@@ -1014,6 +2425,11 @@ var _DIVECommunication = class _DIVECommunication {
1014
2425
  );
1015
2426
  break;
1016
2427
  }
2428
+ case "LAUNCH_AR": {
2429
+ this.ar.Launch();
2430
+ returnValue = true;
2431
+ break;
2432
+ }
1017
2433
  default: {
1018
2434
  console.warn(
1019
2435
  `DIVECommunication.PerformAction: has been executed with unknown Action type ${action}`
@@ -1297,7 +2713,7 @@ var DIVECommunication = _DIVECommunication;
1297
2713
 
1298
2714
  // src/light/PointLight.ts
1299
2715
  init_VisibilityLayerMask();
1300
- var DIVEPointLight = class extends Object3D3 {
2716
+ var DIVEPointLight = class extends Object3D5 {
1301
2717
  constructor() {
1302
2718
  super();
1303
2719
  this.isDIVELight = true;
@@ -1318,13 +2734,13 @@ var DIVEPointLight = class extends Object3D3 {
1318
2734
  geoSize * 320,
1319
2735
  geoSize * 320
1320
2736
  );
1321
- const material = new MeshBasicMaterial({
2737
+ const material = new MeshBasicMaterial2({
1322
2738
  color: this.light.color,
1323
2739
  transparent: true,
1324
2740
  opacity: 0.8,
1325
2741
  side: FrontSide
1326
2742
  });
1327
- this.mesh = new Mesh(geometry, material);
2743
+ this.mesh = new Mesh3(geometry, material);
1328
2744
  this.mesh.layers.mask = UI_LAYER_MASK;
1329
2745
  this.add(this.mesh);
1330
2746
  }
@@ -1364,8 +2780,8 @@ var DIVEPointLight = class extends Object3D3 {
1364
2780
 
1365
2781
  // src/light/SceneLight.ts
1366
2782
  init_VisibilityLayerMask();
1367
- import { DirectionalLight, HemisphereLight, Object3D as Object3D4 } from "three";
1368
- var DIVESceneLight = class extends Object3D4 {
2783
+ import { DirectionalLight, HemisphereLight, Object3D as Object3D6 } from "three";
2784
+ var DIVESceneLight = class extends Object3D6 {
1369
2785
  constructor() {
1370
2786
  super();
1371
2787
  this.isDIVELight = true;
@@ -1406,7 +2822,7 @@ var DIVESceneLight = class extends Object3D4 {
1406
2822
 
1407
2823
  // src/model/Model.ts
1408
2824
  init_VisibilityLayerMask();
1409
- import { MeshStandardMaterial, Raycaster as Raycaster2, Vector3 as Vector33 } from "three";
2825
+ import { MeshStandardMaterial, Raycaster as Raycaster3, Vector3 as Vector36 } from "three";
1410
2826
 
1411
2827
  // src/helper/findSceneRecursive/findSceneRecursive.ts
1412
2828
  var findSceneRecursive = (object) => {
@@ -1418,8 +2834,8 @@ var findSceneRecursive = (object) => {
1418
2834
 
1419
2835
  // src/node/Node.ts
1420
2836
  init_VisibilityLayerMask();
1421
- import { Box3, Object3D as Object3D5, Vector3 as Vector32 } from "three";
1422
- var DIVENode = class extends Object3D5 {
2837
+ import { Box3, Object3D as Object3D7, Vector3 as Vector35 } from "three";
2838
+ var DIVENode = class extends Object3D7 {
1423
2839
  constructor() {
1424
2840
  super();
1425
2841
  this.isDIVENode = true;
@@ -1427,7 +2843,7 @@ var DIVENode = class extends Object3D5 {
1427
2843
  this.isMovable = true;
1428
2844
  this.gizmo = null;
1429
2845
  this.layers.mask = PRODUCT_LAYER_MASK;
1430
- this._positionWorldBuffer = new Vector32();
2846
+ this._positionWorldBuffer = new Vector35();
1431
2847
  this._boundingBox = new Box3();
1432
2848
  }
1433
2849
  SetPosition(position) {
@@ -1435,7 +2851,7 @@ var DIVENode = class extends Object3D5 {
1435
2851
  this.position.set(position.x, position.y, position.z);
1436
2852
  return;
1437
2853
  }
1438
- const newPosition = new Vector32(position.x, position.y, position.z);
2854
+ const newPosition = new Vector35(position.x, position.y, position.z);
1439
2855
  this.position.copy(this.parent.worldToLocal(newPosition));
1440
2856
  if ("isDIVEGroup" in this.parent) {
1441
2857
  this.parent.UpdateLineTo(this);
@@ -1585,10 +3001,10 @@ var DIVEModel = class extends DIVENode {
1585
3001
  }
1586
3002
  const bottomY = this._boundingBox.min.y * this.scale.y;
1587
3003
  const bbBottomCenter = this.localToWorld(
1588
- this._boundingBox.getCenter(new Vector33()).multiply(this.scale)
3004
+ this._boundingBox.getCenter(new Vector36()).multiply(this.scale)
1589
3005
  );
1590
3006
  bbBottomCenter.y = bottomY + this.position.y;
1591
- const raycaster = new Raycaster2(bbBottomCenter, new Vector33(0, -1, 0));
3007
+ const raycaster = new Raycaster3(bbBottomCenter, new Vector36(0, -1, 0));
1592
3008
  raycaster.layers.mask = PRODUCT_LAYER_MASK;
1593
3009
  const intersections = raycaster.intersectObjects(
1594
3010
  findSceneRecursive(this).Root.children,
@@ -1600,7 +3016,7 @@ var DIVEModel = class extends DIVENode {
1600
3016
  const meshBB = mesh.geometry.boundingBox;
1601
3017
  const worldPos = mesh.localToWorld(meshBB.max.clone());
1602
3018
  const oldPos = this.position.clone();
1603
- const newPos = this.position.clone().setY(worldPos.y).sub(new Vector33(0, bottomY, 0));
3019
+ const newPos = this.position.clone().setY(worldPos.y).sub(new Vector36(0, bottomY, 0));
1604
3020
  this.position.copy(newPos);
1605
3021
  if (this.position.y === oldPos.y) return;
1606
3022
  this.onMove();
@@ -1651,17 +3067,17 @@ import {
1651
3067
  Color as Color4,
1652
3068
  ConeGeometry,
1653
3069
  CylinderGeometry,
1654
- Mesh as Mesh3,
3070
+ Mesh as Mesh5,
1655
3071
  MeshStandardMaterial as MeshStandardMaterial2,
1656
- Raycaster as Raycaster3,
3072
+ Raycaster as Raycaster4,
1657
3073
  SphereGeometry as SphereGeometry2,
1658
- Vector3 as Vector34
3074
+ Vector3 as Vector37
1659
3075
  } from "three";
1660
3076
  var DIVEPrimitive = class extends DIVENode {
1661
3077
  constructor() {
1662
3078
  super();
1663
3079
  this.isDIVEPrimitive = true;
1664
- this._mesh = new Mesh3();
3080
+ this._mesh = new Mesh5();
1665
3081
  this._mesh.layers.mask = PRODUCT_LAYER_MASK;
1666
3082
  this._mesh.castShadow = true;
1667
3083
  this._mesh.receiveShadow = true;
@@ -1734,10 +3150,10 @@ var DIVEPrimitive = class extends DIVENode {
1734
3150
  }
1735
3151
  const bottomY = this._boundingBox.min.y * this.scale.y;
1736
3152
  const bbBottomCenter = this.localToWorld(
1737
- this._boundingBox.getCenter(new Vector34()).multiply(this.scale)
3153
+ this._boundingBox.getCenter(new Vector37()).multiply(this.scale)
1738
3154
  );
1739
3155
  bbBottomCenter.y = bottomY + this.position.y;
1740
- const raycaster = new Raycaster3(bbBottomCenter, new Vector34(0, -1, 0));
3156
+ const raycaster = new Raycaster4(bbBottomCenter, new Vector37(0, -1, 0));
1741
3157
  raycaster.layers.mask = PRODUCT_LAYER_MASK;
1742
3158
  const intersections = raycaster.intersectObjects(
1743
3159
  findSceneRecursive(this).Root.children,
@@ -1749,7 +3165,7 @@ var DIVEPrimitive = class extends DIVENode {
1749
3165
  const meshBB = mesh.geometry.boundingBox;
1750
3166
  const worldPos = mesh.localToWorld(meshBB.max.clone());
1751
3167
  const oldPos = this.position.clone();
1752
- const newPos = this.position.clone().setY(worldPos.y).sub(new Vector34(0, bottomY, 0));
3168
+ const newPos = this.position.clone().setY(worldPos.y).sub(new Vector37(0, bottomY, 0));
1753
3169
  this.position.copy(newPos);
1754
3170
  if (this.position.y === oldPos.y) return;
1755
3171
  this.onMove();
@@ -1890,7 +3306,7 @@ import {
1890
3306
  BufferGeometry as BufferGeometry2,
1891
3307
  Line,
1892
3308
  LineDashedMaterial,
1893
- Vector3 as Vector35
3309
+ Vector3 as Vector38
1894
3310
  } from "three";
1895
3311
  var DIVEGroup = class extends DIVENode {
1896
3312
  // lines to children
@@ -1968,7 +3384,7 @@ var DIVEGroup = class extends DIVENode {
1968
3384
  */
1969
3385
  updateLineTo(line, object) {
1970
3386
  line.geometry.setFromPoints([
1971
- new Vector35(0, 0, 0),
3387
+ new Vector38(0, 0, 0),
1972
3388
  object.position.clone()
1973
3389
  ]);
1974
3390
  line.computeLineDistances();
@@ -2023,7 +3439,7 @@ var DIVEGroup = class extends DIVENode {
2023
3439
  };
2024
3440
 
2025
3441
  // src/scene/root/Root.ts
2026
- var DIVERoot = class extends Object3D6 {
3442
+ var DIVERoot = class extends Object3D8 {
2027
3443
  constructor() {
2028
3444
  super();
2029
3445
  this.isDIVERoot = true;
@@ -2208,6 +3624,7 @@ var DIVERoot = class extends Object3D6 {
2208
3624
  const created = new DIVEModel();
2209
3625
  sceneObject = created;
2210
3626
  sceneObject.userData.id = model.id;
3627
+ sceneObject.userData.uri = model.uri;
2211
3628
  this.add(sceneObject);
2212
3629
  }
2213
3630
  if (model.uri !== void 0) {
@@ -2366,8 +3783,8 @@ var GRID_SIDE_LINE_COLOR = "#dddddd";
2366
3783
 
2367
3784
  // src/grid/Grid.ts
2368
3785
  init_VisibilityLayerMask();
2369
- import { GridHelper, Object3D as Object3D7 } from "three";
2370
- var DIVEGrid = class extends Object3D7 {
3786
+ import { GridHelper, Object3D as Object3D9 } from "three";
3787
+ var DIVEGrid = class extends Object3D9 {
2371
3788
  constructor() {
2372
3789
  super();
2373
3790
  this.name = "Grid";
@@ -2390,11 +3807,11 @@ var DIVEGrid = class extends Object3D7 {
2390
3807
  init_VisibilityLayerMask();
2391
3808
  import {
2392
3809
  Color as Color6,
2393
- Mesh as Mesh4,
3810
+ Mesh as Mesh6,
2394
3811
  MeshStandardMaterial as MeshStandardMaterial3,
2395
3812
  PlaneGeometry
2396
3813
  } from "three";
2397
- var DIVEFloor = class extends Mesh4 {
3814
+ var DIVEFloor = class extends Mesh6 {
2398
3815
  constructor() {
2399
3816
  super(
2400
3817
  new PlaneGeometry(1e4, 1e4),
@@ -2416,26 +3833,141 @@ var DIVEFloor = class extends Mesh4 {
2416
3833
  }
2417
3834
  };
2418
3835
 
3836
+ // src/scene/xrroot/XRRoot.ts
3837
+ import { Mesh as Mesh7, Object3D as Object3D11, PlaneGeometry as PlaneGeometry2, ShadowMaterial } from "three";
3838
+
3839
+ // src/scene/xrroot/xrlightroot/XRLightRoot.ts
3840
+ init_VisibilityLayerMask();
3841
+ import { XREstimatedLight } from "three/examples/jsm/webxr/XREstimatedLight";
3842
+ import { Object3D as Object3D10 } from "three";
3843
+ var DIVEXRLightRoot = class extends Object3D10 {
3844
+ constructor(scene) {
3845
+ super();
3846
+ this.name = "XRLightRoot";
3847
+ this._scene = scene;
3848
+ this._xrLight = null;
3849
+ this._lightRoot = new DIVERoot();
3850
+ this._lightRoot.UpdateSceneObject({
3851
+ id: "XRSceneLight",
3852
+ entityType: "light",
3853
+ name: "XRSceneLight",
3854
+ type: "scene",
3855
+ color: 16777215,
3856
+ intensity: 1,
3857
+ enabled: true,
3858
+ visible: true
3859
+ });
3860
+ this.add(this._lightRoot);
3861
+ }
3862
+ InitLightEstimation(renderer) {
3863
+ if (!this._xrLight) {
3864
+ this._xrLight = new XREstimatedLight(renderer, true);
3865
+ this._xrLight.layers.mask = PRODUCT_LAYER_MASK;
3866
+ this.add(this._xrLight);
3867
+ }
3868
+ this._xrLight.addEventListener("estimationstart", () => {
3869
+ this.onEstimationStart();
3870
+ });
3871
+ this._xrLight.addEventListener("estimationend", () => {
3872
+ this.onEstimationEnd();
3873
+ });
3874
+ }
3875
+ DisposeLightEstimation() {
3876
+ if (!this._xrLight) return;
3877
+ this._xrLight.removeEventListener("estimationstart", () => {
3878
+ this.onEstimationStart();
3879
+ });
3880
+ this._xrLight.removeEventListener("estimationend", () => {
3881
+ this.onEstimationEnd();
3882
+ });
3883
+ }
3884
+ onEstimationStart() {
3885
+ this._lightRoot.visible = false;
3886
+ if (!this._xrLight) return;
3887
+ if (this._xrLight.environment) {
3888
+ this._scene.environment = this._xrLight.environment;
3889
+ }
3890
+ }
3891
+ onEstimationEnd() {
3892
+ this._lightRoot.visible = true;
3893
+ this._scene.environment = null;
3894
+ if (!this._xrLight) return;
3895
+ }
3896
+ };
3897
+
3898
+ // src/scene/xrroot/XRRoot.ts
3899
+ var DIVEXRRoot = class extends Object3D11 {
3900
+ get XRModelRoot() {
3901
+ return this._xrModelRoot;
3902
+ }
3903
+ get XRLightRoot() {
3904
+ return this._xrLightRoot;
3905
+ }
3906
+ get XRHandNode() {
3907
+ return this._xrHandNode;
3908
+ }
3909
+ constructor(scene) {
3910
+ super();
3911
+ this.name = "XRRoot";
3912
+ this._xrModelRoot = new DIVERoot();
3913
+ this._xrModelRoot.name = "XRModelRoot";
3914
+ this.add(this._xrModelRoot);
3915
+ this._xrShadowPlane = new Mesh7(
3916
+ new PlaneGeometry2(100, 100),
3917
+ new ShadowMaterial({ opacity: 1, transparent: true })
3918
+ );
3919
+ this._xrModelRoot.add(this._xrShadowPlane);
3920
+ this._xrLightRoot = new DIVEXRLightRoot(scene);
3921
+ this._xrLightRoot.name = "XRLightRoot";
3922
+ this.add(this._xrLightRoot);
3923
+ this._xrHandNode = new Object3D11();
3924
+ this._xrHandNode.name = "XRHandNode";
3925
+ this.add(this._xrHandNode);
3926
+ }
3927
+ InitLightEstimation(renderer) {
3928
+ this._xrLightRoot.InitLightEstimation(renderer);
3929
+ }
3930
+ DisposeLightEstimation() {
3931
+ this._xrLightRoot.DisposeLightEstimation();
3932
+ }
3933
+ };
3934
+
2419
3935
  // src/scene/Scene.ts
2420
3936
  var DIVEScene = class extends Scene2 {
2421
3937
  get Root() {
2422
- return this.root;
3938
+ return this._root;
3939
+ }
3940
+ get XRRoot() {
3941
+ return this._xrRoot;
2423
3942
  }
2424
3943
  get Floor() {
2425
- return this.floor;
3944
+ return this._floor;
2426
3945
  }
2427
3946
  get Grid() {
2428
- return this.grid;
3947
+ return this._grid;
2429
3948
  }
2430
3949
  constructor() {
2431
3950
  super();
2432
3951
  this.background = new Color7(16777215);
2433
- this.root = new DIVERoot();
2434
- this.add(this.root);
2435
- this.floor = new DIVEFloor();
2436
- this.add(this.floor);
2437
- this.grid = new DIVEGrid();
2438
- this.add(this.grid);
3952
+ this._root = new DIVERoot();
3953
+ this.add(this._root);
3954
+ this._floor = new DIVEFloor();
3955
+ this.add(this._floor);
3956
+ this._grid = new DIVEGrid();
3957
+ this.add(this._grid);
3958
+ this._xrRoot = new DIVEXRRoot(this);
3959
+ this._xrRoot.visible = false;
3960
+ this.add(this._xrRoot);
3961
+ }
3962
+ InitXR(renderer) {
3963
+ this._root.visible = false;
3964
+ this._xrRoot.visible = true;
3965
+ this._xrRoot.InitLightEstimation(renderer);
3966
+ }
3967
+ DisposeXR() {
3968
+ this._root.visible = true;
3969
+ this._xrRoot.visible = false;
3970
+ this._xrRoot.DisposeLightEstimation();
2439
3971
  }
2440
3972
  SetBackground(color) {
2441
3973
  this.background = new Color7(color);
@@ -2465,7 +3997,7 @@ init_PerspectiveCamera();
2465
3997
 
2466
3998
  // src/controls/OrbitControls.ts
2467
3999
  import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
2468
- import { MathUtils as MathUtils2, Vector3 as Vector36 } from "three";
4000
+ import { MathUtils as MathUtils2, Vector3 as Vector39 } from "three";
2469
4001
  import { Easing } from "@tweenjs/tween.js";
2470
4002
  var DIVEOrbitControlsDefaultSettings = {
2471
4003
  enableDamping: true,
@@ -2507,8 +4039,8 @@ var _DIVEOrbitControls = class _DIVEOrbitControls extends OrbitControls {
2507
4039
  this.dispose();
2508
4040
  }
2509
4041
  ComputeEncompassingView(bb) {
2510
- const center = bb.getCenter(new Vector36());
2511
- const size = bb.getSize(new Vector36());
4042
+ const center = bb.getCenter(new Vector39());
4043
+ const size = bb.getSize(new Vector39());
2512
4044
  const distance = Math.max(size.x, size.y, size.z) * 1.25;
2513
4045
  const direction = this.object.position.clone().normalize();
2514
4046
  return {
@@ -2718,7 +4250,7 @@ init_VisibilityLayerMask();
2718
4250
  import {
2719
4251
  AxesHelper,
2720
4252
  Color as Color8,
2721
- Matrix4,
4253
+ Matrix4 as Matrix44,
2722
4254
  OrthographicCamera,
2723
4255
  Vector4
2724
4256
  } from "three";
@@ -2782,7 +4314,7 @@ var DIVEAxisCamera = class extends OrthographicCamera {
2782
4314
  }
2783
4315
  SetFromCameraMatrix(matrix) {
2784
4316
  this.axesHelper.rotation.setFromRotationMatrix(
2785
- new Matrix4().extractRotation(matrix).invert()
4317
+ new Matrix44().extractRotation(matrix).invert()
2786
4318
  );
2787
4319
  }
2788
4320
  };
@@ -2854,109 +4386,13 @@ var getObjectDelta = (a, b) => {
2854
4386
  };
2855
4387
 
2856
4388
  // src/dive.ts
4389
+ init_Info();
2857
4390
  import { generateUUID as generateUUID2 } from "three/src/math/MathUtils";
2858
4391
 
2859
- // src/info/Info.ts
2860
- var DIVEInfo = class {
2861
- /**
2862
- *
2863
- * @returns The system the user is using. Possible values are "Android", "iOS", "Windows", "MacOS", "Linux" or "Unknown".
2864
- */
2865
- static GetSystem() {
2866
- const platform = navigator.platform;
2867
- if (/Android/.test(navigator.userAgent)) {
2868
- return "Android";
2869
- } else if (/iPhone|iPad|iPod/.test(navigator.userAgent)) {
2870
- return "iOS";
2871
- } else if (platform.startsWith("Win")) {
2872
- return "Windows";
2873
- } else if (platform.startsWith("Mac")) {
2874
- return "MacOS";
2875
- } else if (platform.startsWith("Linux")) {
2876
- return "Linux";
2877
- } else {
2878
- return "Unknown";
2879
- }
2880
- }
2881
- /**
2882
- * @returns A promise that resolves to a boolean indicating whether the user's device supports WebXR.
2883
- */
2884
- static GetSupportsWebXR() {
2885
- return __async(this, null, function* () {
2886
- if (this._supportsWebXR !== null) {
2887
- return this._supportsWebXR;
2888
- }
2889
- if (!navigator.xr) {
2890
- this._supportsWebXR = false;
2891
- return this._supportsWebXR;
2892
- }
2893
- try {
2894
- const supported = yield navigator.xr.isSessionSupported("immersive-ar");
2895
- this._supportsWebXR = supported;
2896
- } catch (error) {
2897
- this._supportsWebXR = false;
2898
- }
2899
- return this._supportsWebXR;
2900
- });
2901
- }
2902
- /**
2903
- * @returns A boolean indicating whether the user's device supports AR Quick Look.
2904
- */
2905
- static GetSupportsARQuickLook() {
2906
- const a = document.createElement("a");
2907
- if (a.relList.supports("ar")) {
2908
- return true;
2909
- }
2910
- const userAgent = navigator.userAgent;
2911
- const isIOS = /iPad|iPhone|iPod/.test(userAgent) && !window.MSStream;
2912
- if (!isIOS) {
2913
- return false;
2914
- }
2915
- const match = userAgent.match(/OS (\d+)_/);
2916
- if (!match || match.length < 2) {
2917
- return false;
2918
- }
2919
- const iOSVersion = parseInt(match[1], 10);
2920
- const minQuickLookVersion = 12;
2921
- if (iOSVersion < minQuickLookVersion) {
2922
- return false;
2923
- }
2924
- const isSupportedBrowser = /^((?!chrome|android).)*safari|CriOS|FxiOS/i.test(userAgent);
2925
- if (isSupportedBrowser) {
2926
- return true;
2927
- }
2928
- return false;
2929
- }
2930
- /**
2931
- * @returns A boolean indicating whether the user's device is a mobile device.
2932
- */
2933
- static get isMobile() {
2934
- return this.GetSystem() === "Android" || this.GetSystem() === "iOS";
2935
- }
2936
- /**
2937
- * @returns A boolean indicating whether the user's device is a desktop device.
2938
- */
2939
- static get isDesktop() {
2940
- return !this.isMobile;
2941
- }
2942
- /**
2943
- * @returns A promise that resolves to a boolean indicating whether the user's device is capable of AR.
2944
- */
2945
- static GetIsARCapable() {
2946
- return __async(this, null, function* () {
2947
- if (this.GetSupportsARQuickLook()) {
2948
- return true;
2949
- }
2950
- return yield this.GetSupportsWebXR();
2951
- });
2952
- }
2953
- };
2954
- DIVEInfo._supportsWebXR = null;
2955
-
2956
4392
  // package.json
2957
4393
  var package_default = {
2958
4394
  name: "@shopware-ag/dive",
2959
- version: "1.16.25",
4395
+ version: "1.16.26-beta.0",
2960
4396
  description: "Shopware Spatial Framework",
2961
4397
  type: "module",
2962
4398
  main: "./build/dive.cjs",
@@ -3108,8 +4544,8 @@ var DIVEDefaultSettings = {
3108
4544
  };
3109
4545
  var DIVE = class _DIVE {
3110
4546
  // static members
3111
- static QuickView(uri) {
3112
- const dive = new _DIVE();
4547
+ static QuickView(uri, settings) {
4548
+ const dive = new _DIVE(settings);
3113
4549
  dive.Communication.PerformAction("SET_CAMERA_TRANSFORM", {
3114
4550
  position: { x: 0, y: 2, z: 2 },
3115
4551
  target: { x: 0, y: 0.5, z: 0 }
@@ -3128,9 +4564,6 @@ var DIVE = class _DIVE {
3128
4564
  const modelid = generateUUID2();
3129
4565
  dive.Communication.Subscribe("MODEL_LOADED", (data) => {
3130
4566
  if (data.id !== modelid) return;
3131
- dive.Communication.PerformAction("PLACE_ON_FLOOR", {
3132
- id: modelid
3133
- });
3134
4567
  const transform = dive.Communication.PerformAction(
3135
4568
  "COMPUTE_ENCOMPASSING_VIEW",
3136
4569
  {}
@@ -3253,9 +4686,36 @@ var DIVE = class _DIVE {
3253
4686
  console.log(this.scene);
3254
4687
  }
3255
4688
  };
3256
- console.log(
3257
- `DIVE ${package_default.version} initialized ${false ? "in development mode" : ""}`
3258
- );
4689
+ console.log(`
4690
+ @@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@
4691
+ @@@@+-:::::::---------------------==------------------------------=#@@@@
4692
+ @@%=::::.......::---------------------------------------------------------+@@
4693
+ @@+:::...........::-----------------------------------------------------------#@@
4694
+ @@=:::.........::::::--------------${" DIVE " + package_default.version.padStart(7, " ") + " "}---------------------------------%@
4695
+ @%:::.......:::::::-------------------${false ? " DEV MODE " : "--------------"}------------------------------------#@
4696
+ @*:::.....:::::-----------------------------------------------------------------------*@
4697
+ @%::::::.::::---------------------------------------------------------------------------@@
4698
+ @@-:::::::::-----------------------------------------------------------------------------=@
4699
+ @%::::::::--------------------------------------------------------------------------------%@
4700
+ @+::::::::--------------------------------=@@@@@%-----------------------------------------%@
4701
+ @=:::::::--------------------------------*@@ @@+---------------------------------------#@
4702
+ @+:::::::-------------------------------*@ @*--------------------------------------%@
4703
+ @#::::::::-----------------------------=@@ @@=-------------------------------------%@
4704
+ @@-::::::::----------------------------@@ @@------------------------------------=@
4705
+ @%:::::::::--------------------------*@ @*-----------------------------------@@
4706
+ @*:::::::::-------------------------@@ @@----------------------------------%@
4707
+ @#::::::::::----------------------%@ @%--------------------------------%@
4708
+ @#:::::::::::-------------------=@@ @@=------------------------------%@
4709
+ @@-::::::::::::----------------%@ @%----------------------------=@@
4710
+ @@#::::::::::::::------------*@ @*--------------------------#@@
4711
+ @@+::::::::::::::::--------@@ @@------------------------+@@
4712
+ @@*:::::::::::::::::----@@ @@---------------------+@@
4713
+ @@@-:::::::::::::::--#@ @#-----------------=%@@
4714
+ @@%-::::::::::::-%@ @%-------------=%@@
4715
+ @@@@+:::::::#@@ @@*-------*@@@@
4716
+ @@@@@@@ @@@@@@
4717
+
4718
+ `);
3259
4719
  }
3260
4720
  Dispose() {
3261
4721
  var _a;