@needle-tools/engine 4.12.0-next.dd87659 → 4.12.0-next.f0b1535
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 +1 -1
- package/components.needle.json +1 -1
- package/dist/generateMeshBVH.worker-iyfPIK6R.js +21 -0
- package/dist/{gltf-progressive-DZrY8VT6.min.js → gltf-progressive-BmSygnAC.min.js} +2 -2
- package/dist/{gltf-progressive-DgYz5BYa.js → gltf-progressive-DnLBuGK5.js} +24 -24
- package/dist/{gltf-progressive-DWcmTMCh.umd.cjs → gltf-progressive-Rs-ojtXy.umd.cjs} +1 -1
- package/dist/{loader.worker-Dip-PthR.js → loader.worker-DWzfDpAl.js} +4 -4
- package/dist/{needle-engine.bundle-CiqX7AtA.js → needle-engine.bundle-CrbGpIHn.js} +8564 -8382
- package/dist/{needle-engine.bundle-CiL59iU3.min.js → needle-engine.bundle-DAiK_I7w.min.js} +150 -151
- package/dist/needle-engine.bundle-DdJ-HkwM.umd.cjs +1646 -0
- package/dist/needle-engine.d.ts +142 -43
- package/dist/needle-engine.js +4 -4
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/{postprocessing-DYDtB188.min.js → postprocessing-B5ksn9-G.min.js} +54 -54
- package/dist/{postprocessing-CMgoN5t5.umd.cjs → postprocessing-DZtb9Nnn.umd.cjs} +81 -81
- package/dist/{postprocessing-BTW9pD_s.js → postprocessing-__7s9wON.js} +450 -441
- package/dist/{three-DfMvBzXi.js → three-BCCkyCA5.js} +1 -7
- package/dist/{three-qj71I7J3.umd.cjs → three-Bf2NBxAw.umd.cjs} +2 -2
- package/dist/{three-B7CT31Bt.min.js → three-W7zWTcfP.min.js} +1 -1
- package/dist/{three-examples-CsW4_6LI.umd.cjs → three-examples-Dho7cuu4.umd.cjs} +4 -4
- package/dist/{three-examples-D1P7eEhn.min.js → three-examples-MsJjauyk.min.js} +10 -10
- package/dist/{three-examples-D1SK93ek.js → three-examples-y2GeYlze.js} +2 -20
- package/dist/{three-mesh-ui-C_uSB5dD.js → three-mesh-ui-3nSSizT4.js} +1 -1
- package/dist/{three-mesh-ui-LQ44s0AL.min.js → three-mesh-ui-CIez6qJQ.min.js} +1 -1
- package/dist/{three-mesh-ui-DpATDXwU.umd.cjs → three-mesh-ui-zsOOA5Pq.umd.cjs} +1 -1
- package/dist/{vendor-D0zoswDa.js → vendor-DMZcbVO1.js} +3707 -3527
- package/dist/vendor-sURMCFSI.min.js +1116 -0
- package/dist/{vendor-UCpFAwt1.umd.cjs → vendor-tyBvnMF-.umd.cjs} +39 -39
- package/lib/engine/codegen/register_types.js +0 -2
- package/lib/engine/codegen/register_types.js.map +1 -1
- package/lib/engine/debug/debug_console.js +403 -1
- package/lib/engine/debug/debug_console.js.map +1 -1
- package/lib/engine/engine_components.js +3 -3
- package/lib/engine/engine_components.js.map +1 -1
- package/lib/engine/engine_input.d.ts +5 -0
- package/lib/engine/engine_input.js +6 -0
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_license.js +3 -9
- package/lib/engine/engine_license.js.map +1 -1
- package/lib/engine/engine_networking.js +5 -5
- package/lib/engine/engine_networking.js.map +1 -1
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_physics_rapier.js +1 -1
- package/lib/engine/engine_physics_rapier.js.map +1 -1
- package/lib/engine/engine_utils.d.ts +4 -1
- package/lib/engine/engine_utils.js +28 -4
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/extensions/extensions.d.ts +29 -7
- package/lib/engine/extensions/extensions.js.map +1 -1
- package/lib/engine/webcomponents/WebXRButtons.js +13 -5
- package/lib/engine/webcomponents/WebXRButtons.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.js +4 -5
- package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.ar-overlay.js +4 -0
- package/lib/engine/webcomponents/needle-engine.ar-overlay.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.js +1 -1
- package/lib/engine/webcomponents/needle-engine.js.map +1 -1
- package/lib/engine/xr/NeedleXRSession.d.ts +1 -1
- package/lib/engine/xr/NeedleXRSession.js +67 -24
- package/lib/engine/xr/NeedleXRSession.js.map +1 -1
- package/lib/engine/xr/TempXRContext.js +12 -2
- package/lib/engine/xr/TempXRContext.js.map +1 -1
- package/lib/engine/xr/usdz.js +6 -2
- package/lib/engine/xr/usdz.js.map +1 -1
- package/lib/engine-components/AlignmentConstraint.d.ts +1 -2
- package/lib/engine-components/AlignmentConstraint.js +1 -2
- package/lib/engine-components/AlignmentConstraint.js.map +1 -1
- package/lib/engine-components/Animation.d.ts +2 -0
- package/lib/engine-components/Animation.js +2 -0
- package/lib/engine-components/Animation.js.map +1 -1
- package/lib/engine-components/Animator.d.ts +1 -0
- package/lib/engine-components/Animator.js +1 -0
- package/lib/engine-components/Animator.js.map +1 -1
- package/lib/engine-components/AudioListener.d.ts +1 -1
- package/lib/engine-components/AudioListener.js +1 -1
- package/lib/engine-components/AudioSource.d.ts +1 -1
- package/lib/engine-components/AudioSource.js +1 -1
- package/lib/engine-components/BasicIKConstraint.d.ts +8 -0
- package/lib/engine-components/BasicIKConstraint.js +8 -0
- package/lib/engine-components/BasicIKConstraint.js.map +1 -1
- package/lib/engine-components/BoxHelperComponent.d.ts +1 -0
- package/lib/engine-components/BoxHelperComponent.js +1 -0
- package/lib/engine-components/BoxHelperComponent.js.map +1 -1
- package/lib/engine-components/Camera.d.ts +2 -2
- package/lib/engine-components/Camera.js +2 -2
- package/lib/engine-components/CharacterController.d.ts +6 -2
- package/lib/engine-components/CharacterController.js +6 -2
- package/lib/engine-components/CharacterController.js.map +1 -1
- package/lib/engine-components/Collider.d.ts +2 -2
- package/lib/engine-components/Collider.js +1 -1
- package/lib/engine-components/Collider.js.map +1 -1
- package/lib/engine-components/Component.d.ts +2 -1
- package/lib/engine-components/Component.js +3 -2
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/ContactShadows.d.ts +1 -1
- package/lib/engine-components/ContactShadows.js +1 -1
- package/lib/engine-components/DragControls.js +3 -0
- package/lib/engine-components/DragControls.js.map +1 -1
- package/lib/engine-components/Gizmos.d.ts +2 -0
- package/lib/engine-components/Gizmos.js +2 -0
- package/lib/engine-components/Gizmos.js.map +1 -1
- package/lib/engine-components/Joints.d.ts +20 -0
- package/lib/engine-components/Joints.js +20 -0
- package/lib/engine-components/Joints.js.map +1 -1
- package/lib/engine-components/LODGroup.d.ts +1 -1
- package/lib/engine-components/LODGroup.js +1 -1
- package/lib/engine-components/LookAtConstraint.d.ts +1 -1
- package/lib/engine-components/LookAtConstraint.js +1 -1
- package/lib/engine-components/Networking.d.ts +1 -1
- package/lib/engine-components/Networking.js +1 -1
- package/lib/engine-components/OrbitControls.d.ts +1 -1
- package/lib/engine-components/OrbitControls.js +1 -1
- package/lib/engine-components/Renderer.d.ts +6 -0
- package/lib/engine-components/Renderer.js +6 -0
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/RendererInstancing.js +5 -3
- package/lib/engine-components/RendererInstancing.js.map +1 -1
- package/lib/engine-components/SceneSwitcher.js +18 -14
- package/lib/engine-components/SceneSwitcher.js.map +1 -1
- package/lib/engine-components/ShadowCatcher.d.ts +1 -1
- package/lib/engine-components/ShadowCatcher.js +1 -1
- package/lib/engine-components/SpectatorCamera.d.ts +1 -1
- package/lib/engine-components/SpectatorCamera.js +16 -8
- package/lib/engine-components/SpectatorCamera.js.map +1 -1
- package/lib/engine-components/SpriteRenderer.d.ts +2 -1
- package/lib/engine-components/SpriteRenderer.js +2 -1
- package/lib/engine-components/SpriteRenderer.js.map +1 -1
- package/lib/engine-components/Voip.d.ts +1 -1
- package/lib/engine-components/Voip.js +1 -1
- package/lib/engine-components/api.d.ts +1 -0
- package/lib/engine-components/api.js +1 -0
- package/lib/engine-components/api.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +0 -1
- package/lib/engine-components/codegen/components.js +0 -1
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/export/gltf/GltfExport.d.ts +5 -0
- package/lib/engine-components/export/gltf/GltfExport.js +5 -0
- package/lib/engine-components/export/gltf/GltfExport.js.map +1 -1
- package/lib/engine-components/export/usdz/USDZExporter.d.ts +1 -0
- package/lib/engine-components/export/usdz/USDZExporter.js +1 -0
- package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
- package/lib/engine-components/particlesystem/ParticleSystem.d.ts +1 -1
- package/lib/engine-components/particlesystem/ParticleSystem.js +1 -1
- package/lib/engine-components/timeline/SignalAsset.d.ts +1 -1
- package/lib/engine-components/timeline/SignalAsset.js +1 -1
- package/lib/engine-components/ui/Button.d.ts +1 -1
- package/lib/engine-components/ui/Button.js +1 -1
- package/lib/engine-components/ui/Canvas.d.ts +1 -1
- package/lib/engine-components/ui/Canvas.js +1 -1
- package/lib/engine-components/ui/CanvasGroup.d.ts +1 -1
- package/lib/engine-components/ui/CanvasGroup.js +1 -1
- package/lib/engine-components/ui/EventSystem.d.ts +1 -1
- package/lib/engine-components/ui/EventSystem.js +1 -1
- package/lib/engine-components/ui/Image.d.ts +1 -1
- package/lib/engine-components/ui/Image.js +1 -1
- package/lib/engine-components/ui/InputField.d.ts +1 -1
- package/lib/engine-components/ui/InputField.js +1 -1
- package/lib/engine-components/ui/Outline.d.ts +1 -1
- package/lib/engine-components/ui/Outline.js +1 -1
- package/lib/engine-components/ui/Raycaster.d.ts +3 -2
- package/lib/engine-components/ui/Raycaster.js +3 -2
- package/lib/engine-components/ui/Raycaster.js.map +1 -1
- package/lib/engine-components/ui/RectTransform.d.ts +6 -0
- package/lib/engine-components/ui/RectTransform.js +6 -0
- package/lib/engine-components/ui/RectTransform.js.map +1 -1
- package/lib/engine-components/ui/SpatialHtml.d.ts +7 -0
- package/lib/engine-components/ui/SpatialHtml.js +7 -0
- package/lib/engine-components/ui/SpatialHtml.js.map +1 -1
- package/lib/engine-components/ui/Text.d.ts +2 -0
- package/lib/engine-components/ui/Text.js +2 -0
- package/lib/engine-components/ui/Text.js.map +1 -1
- package/lib/engine-components/utils/LookAt.d.ts +2 -1
- package/lib/engine-components/utils/LookAt.js +2 -1
- package/lib/engine-components/utils/LookAt.js.map +1 -1
- package/lib/engine-components/web/CursorFollow.d.ts +1 -1
- package/lib/engine-components/web/CursorFollow.js +1 -1
- package/lib/engine-components/web/HoverAnimation.d.ts +1 -1
- package/lib/engine-components/web/HoverAnimation.js +1 -1
- package/lib/engine-components/web/ViewBox.d.ts +1 -1
- package/lib/engine-components/web/ViewBox.js +1 -1
- package/lib/engine-components/webxr/Avatar.js +2 -0
- package/lib/engine-components/webxr/Avatar.js.map +1 -1
- package/lib/engine-components/webxr/WebXR.js +18 -12
- package/lib/engine-components/webxr/WebXR.js.map +1 -1
- package/package.json +5 -5
- package/plugins/vite/poster-client.js +8 -1
- package/src/engine/codegen/register_types.ts +0 -2
- package/src/engine/debug/debug_console.ts +449 -1
- package/src/engine/engine_components.ts +4 -4
- package/src/engine/engine_input.ts +7 -0
- package/src/engine/engine_license.ts +3 -8
- package/src/engine/engine_networking.ts +5 -5
- package/src/engine/engine_physics.ts +3 -3
- package/src/engine/engine_physics_rapier.ts +1 -1
- package/src/engine/engine_utils.ts +23 -4
- package/src/engine/extensions/extensions.ts +30 -6
- package/src/engine/webcomponents/WebXRButtons.ts +15 -5
- package/src/engine/webcomponents/needle menu/needle-menu.ts +4 -5
- package/src/engine/webcomponents/needle-engine.ar-overlay.ts +6 -0
- package/src/engine/webcomponents/needle-engine.ts +2 -2
- package/src/engine/xr/NeedleXRSession.ts +78 -27
- package/src/engine/xr/TempXRContext.ts +12 -2
- package/src/engine/xr/usdz.ts +6 -1
- package/src/engine-components/AlignmentConstraint.ts +1 -2
- package/src/engine-components/Animation.ts +2 -0
- package/src/engine-components/Animator.ts +1 -0
- package/src/engine-components/AudioListener.ts +1 -1
- package/src/engine-components/AudioSource.ts +1 -1
- package/src/engine-components/BasicIKConstraint.ts +8 -0
- package/src/engine-components/BoxHelperComponent.ts +1 -0
- package/src/engine-components/Camera.ts +2 -2
- package/src/engine-components/CharacterController.ts +6 -2
- package/src/engine-components/Collider.ts +2 -2
- package/src/engine-components/Component.ts +5 -4
- package/src/engine-components/ContactShadows.ts +1 -1
- package/src/engine-components/DragControls.ts +4 -0
- package/src/engine-components/Gizmos.ts +2 -0
- package/src/engine-components/Joints.ts +20 -0
- package/src/engine-components/LODGroup.ts +1 -1
- package/src/engine-components/LookAtConstraint.ts +1 -1
- package/src/engine-components/Networking.ts +1 -1
- package/src/engine-components/OrbitControls.ts +1 -1
- package/src/engine-components/Renderer.ts +6 -0
- package/src/engine-components/RendererInstancing.ts +6 -3
- package/src/engine-components/SceneSwitcher.ts +17 -17
- package/src/engine-components/ShadowCatcher.ts +1 -1
- package/src/engine-components/SpectatorCamera.ts +22 -11
- package/src/engine-components/SpriteRenderer.ts +2 -1
- package/src/engine-components/Voip.ts +1 -1
- package/src/engine-components/api.ts +2 -1
- package/src/engine-components/codegen/components.ts +0 -1
- package/src/engine-components/export/gltf/GltfExport.ts +5 -0
- package/src/engine-components/export/usdz/USDZExporter.ts +1 -0
- package/src/engine-components/particlesystem/ParticleSystem.ts +1 -1
- package/src/engine-components/timeline/SignalAsset.ts +1 -1
- package/src/engine-components/ui/Button.ts +1 -1
- package/src/engine-components/ui/Canvas.ts +1 -1
- package/src/engine-components/ui/CanvasGroup.ts +1 -1
- package/src/engine-components/ui/EventSystem.ts +1 -1
- package/src/engine-components/ui/Image.ts +1 -1
- package/src/engine-components/ui/InputField.ts +1 -1
- package/src/engine-components/ui/Outline.ts +1 -1
- package/src/engine-components/ui/Raycaster.ts +3 -2
- package/src/engine-components/ui/RectTransform.ts +6 -0
- package/src/engine-components/ui/SpatialHtml.ts +7 -0
- package/src/engine-components/ui/Text.ts +2 -0
- package/src/engine-components/utils/LookAt.ts +2 -1
- package/src/engine-components/web/CursorFollow.ts +1 -1
- package/src/engine-components/web/HoverAnimation.ts +1 -1
- package/src/engine-components/web/ViewBox.ts +1 -1
- package/src/engine-components/webxr/Avatar.ts +4 -0
- package/src/engine-components/webxr/WebXR.ts +19 -11
- package/dist/generateMeshBVH.worker-mO20N_b8.js +0 -21
- package/dist/needle-engine.bundle-DzYZGJbS.umd.cjs +0 -1647
- package/dist/vendor-BKGa4GE0.min.js +0 -1116
|
@@ -606,7 +606,8 @@ export namespace DeviceUtilities {
|
|
|
606
606
|
/** @returns `true` if we're currently on an iPad */
|
|
607
607
|
export function isiPad() {
|
|
608
608
|
if (__isiPad !== undefined) return __isiPad;
|
|
609
|
-
|
|
609
|
+
const userAgent = navigator.userAgent.toLowerCase();
|
|
610
|
+
return __isiPad = /iPad/.test(navigator.userAgent) || userAgent.includes("macintosh") && "ontouchend" in document;
|
|
610
611
|
}
|
|
611
612
|
|
|
612
613
|
let __isAndroidDevice: boolean | undefined;
|
|
@@ -623,17 +624,25 @@ export namespace DeviceUtilities {
|
|
|
623
624
|
return __isMozillaXR = /WebXRViewer\//i.test(navigator.userAgent);
|
|
624
625
|
}
|
|
625
626
|
|
|
627
|
+
let __isNeedleAppClip: boolean | undefined;
|
|
628
|
+
/** @returns `true` if we're currently in the Needle App Clip */
|
|
629
|
+
export function isNeedleAppClip() {
|
|
630
|
+
if (__isNeedleAppClip !== undefined) return __isNeedleAppClip;
|
|
631
|
+
return __isNeedleAppClip = /NeedleAppClip\//i.test(navigator.userAgent);
|
|
632
|
+
}
|
|
633
|
+
|
|
626
634
|
let __isMacOS: boolean | undefined;
|
|
627
635
|
// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgentData
|
|
628
636
|
/** @returns `true` for MacOS devices */
|
|
629
637
|
export function isMacOS() {
|
|
630
638
|
if (__isMacOS !== undefined) return __isMacOS;
|
|
639
|
+
if (isiOS() || isiPad()) return __isMacOS = false;
|
|
640
|
+
const userAgent = navigator.userAgent.toLowerCase();
|
|
631
641
|
if (navigator.userAgentData) {
|
|
632
642
|
// Use modern UA Client Hints API if available
|
|
633
643
|
return __isMacOS = navigator.userAgentData.platform === 'macOS';
|
|
634
644
|
} else {
|
|
635
645
|
// Fallback to user agent string parsing
|
|
636
|
-
const userAgent = navigator.userAgent.toLowerCase();
|
|
637
646
|
return __isMacOS = userAgent.includes('mac os x') || userAgent.includes('macintosh');
|
|
638
647
|
}
|
|
639
648
|
}
|
|
@@ -642,13 +651,13 @@ export namespace DeviceUtilities {
|
|
|
642
651
|
/** @returns `true` for VisionOS devices */
|
|
643
652
|
export function isVisionOS() {
|
|
644
653
|
if (__isVisionOS !== undefined) return __isVisionOS;
|
|
645
|
-
return __isVisionOS = (
|
|
654
|
+
return __isVisionOS = (isiPad() && "xr" in navigator && supportsQuickLookAR());
|
|
646
655
|
}
|
|
647
656
|
|
|
648
657
|
let __isiOS: boolean | undefined;
|
|
649
658
|
const iosDevices = ['iPad Simulator', 'iPhone Simulator', 'iPod Simulator', 'iPad', 'iPhone', 'iPod'];
|
|
650
659
|
|
|
651
|
-
/** @returns `true` for
|
|
660
|
+
/** @returns `true` for mobile Apple devices like iPad, iPhone, iPod, Vision Pro, ... */
|
|
652
661
|
export function isiOS() {
|
|
653
662
|
if (__isiOS !== undefined) return __isiOS;
|
|
654
663
|
// eslint-disable-next-line deprecation/deprecation
|
|
@@ -725,6 +734,16 @@ export namespace DeviceUtilities {
|
|
|
725
734
|
else __chromeVersion = null;
|
|
726
735
|
return __chromeVersion;
|
|
727
736
|
}
|
|
737
|
+
|
|
738
|
+
let __safariVersion: string | null | undefined;
|
|
739
|
+
export function getSafariVersion() {
|
|
740
|
+
if (__safariVersion !== undefined) return __safariVersion;
|
|
741
|
+
const match = navigator.userAgent.match(/Version\/(\d+\.\d+)/);
|
|
742
|
+
if (match && isSafari()) {
|
|
743
|
+
__safariVersion = match[1];
|
|
744
|
+
} else __safariVersion = null;
|
|
745
|
+
return __safariVersion;
|
|
746
|
+
}
|
|
728
747
|
}
|
|
729
748
|
|
|
730
749
|
/**
|
|
@@ -30,20 +30,44 @@ const KHR_ANIMATIONPOINTER_IMPORT = import("@needle-tools/three-animation-pointe
|
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Callback type for glTF import plugins. See {@link INeedleGLTFExtensionPlugin.onImport}
|
|
35
|
+
*/
|
|
36
|
+
export type OnImportCallback = (loader: GLTFLoader, url: string, context: Context) => void;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Callback type for glTF export plugins. See {@link INeedleGLTFExtensionPlugin.onExport}
|
|
40
|
+
*/
|
|
41
|
+
export type OnExportCallback = (exporter: GLTFExporter, context: Context) => void;
|
|
35
42
|
|
|
36
43
|
/**
|
|
37
|
-
* Interface for registering custom glTF extensions to the Needle Engine GLTFLoaders.
|
|
44
|
+
* Interface for registering custom glTF extensions to the Needle Engine GLTFLoaders.
|
|
45
|
+
* Register your plugin using the {@link addCustomExtensionPlugin} method
|
|
38
46
|
*/
|
|
39
47
|
export interface INeedleGLTFExtensionPlugin {
|
|
40
48
|
/** The Name of your plugin */
|
|
41
49
|
name: string;
|
|
42
|
-
/** Called before starting to load a glTF file. This callback can be used to add custom extensions to the GLTFLoader
|
|
50
|
+
/** Called before starting to load a glTF file. This callback can be used to add custom extensions to the [GLTFLoader](https://threejs.org/docs/#GLTFLoader.register)
|
|
51
|
+
*
|
|
52
|
+
* @example Add a custom extension to the GLTFloader
|
|
53
|
+
* ```ts
|
|
54
|
+
* onImport: (loader, url, context) => {
|
|
55
|
+
* loader.register((parser) => new MyCustomExtension(parser));
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
43
59
|
onImport?: OnImportCallback;
|
|
44
|
-
/** Called after
|
|
60
|
+
/** Called after a glTF file has been loaded */
|
|
45
61
|
onLoaded?: (url: string, gltf: GLTF, context: Context) => void;
|
|
46
|
-
/** Called before starting to export a glTF file. This callback can be used to add custom extensions to the GLTFExporter
|
|
62
|
+
/** Called before starting to export a glTF file. This callback can be used to add custom extensions to the [GLTFExporter](https://threejs.org/docs/#examples/en/exporters/GLTFExporter.register)
|
|
63
|
+
*
|
|
64
|
+
* @example Add a custom extension to the GLTFExporter
|
|
65
|
+
* ```ts
|
|
66
|
+
* onExport: (exporter, context) => {
|
|
67
|
+
* exporter.register((writer) => new MyCustomExportExtension(writer));
|
|
68
|
+
* }
|
|
69
|
+
*
|
|
70
|
+
*/
|
|
47
71
|
onExport?: OnExportCallback;
|
|
48
72
|
}
|
|
49
73
|
|
|
@@ -57,13 +57,16 @@ export class WebXRButtonFactory {
|
|
|
57
57
|
this._quicklookButton = button;
|
|
58
58
|
button.dataset["needle"] = "quicklook-button";
|
|
59
59
|
const supportsQuickLook = DeviceUtilities.supportsQuickLookAR();
|
|
60
|
+
let buttonText = "View in AR";
|
|
60
61
|
// we can immediately enter this scene, because the platform supports rel="ar" links
|
|
61
|
-
if (
|
|
62
|
-
|
|
62
|
+
if (DeviceUtilities.isVisionOS()) {
|
|
63
|
+
buttonText = "View in AR";
|
|
63
64
|
}
|
|
64
|
-
else {
|
|
65
|
-
|
|
65
|
+
else if (supportsQuickLook || DeviceUtilities.isiOS()) {
|
|
66
|
+
buttonText = "Open in Quicklook";
|
|
66
67
|
}
|
|
68
|
+
|
|
69
|
+
button.innerText = buttonText;
|
|
67
70
|
button.prepend(getIconElement("view_in_ar"));
|
|
68
71
|
|
|
69
72
|
let createdExporter = false;
|
|
@@ -209,13 +212,20 @@ export class WebXRButtonFactory {
|
|
|
209
212
|
}
|
|
210
213
|
|
|
211
214
|
private updateSessionSupported(button: HTMLButtonElement, mode: XRSessionMode) {
|
|
215
|
+
if (mode === "immersive-ar" && DeviceUtilities.isiOS() && !DeviceUtilities.isVisionOS()) {
|
|
216
|
+
// on iOS, we can forward to the AppClip experience from the same button,
|
|
217
|
+
// so we always show the button. No AppClip support on VisionOS for now, so
|
|
218
|
+
// button state depends on WebXR support there.
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
212
222
|
if (!("xr" in navigator)) {
|
|
213
223
|
button.style.display = "none";
|
|
214
224
|
return;
|
|
215
225
|
}
|
|
216
226
|
NeedleXRSession.isSessionSupported(mode).then(supported => {
|
|
217
227
|
button.style.display = !supported ? "none" : "";
|
|
218
|
-
if (isDevEnvironment() && !supported) console.log("[WebXR] \"" + mode + "\" is not supported on this device
|
|
228
|
+
if (isDevEnvironment() && !supported) console.log("[WebXR] \"" + mode + "\" is not supported on this device. Make sure your server runs using HTTPS and you have a device connected that supports " + mode);
|
|
219
229
|
});
|
|
220
230
|
}
|
|
221
231
|
|
|
@@ -601,16 +601,15 @@ export class NeedleMenuElement extends HTMLElement {
|
|
|
601
601
|
bottom: calc(100% + 5px);
|
|
602
602
|
z-index: 100;
|
|
603
603
|
width: auto;
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
604
|
+
max-width: 90vw;
|
|
605
|
+
left: 50%;
|
|
606
|
+
transform: translateX(-50%);
|
|
607
|
+
padding: .2rem 1em;
|
|
607
608
|
|
|
608
609
|
}
|
|
609
610
|
.compact.logo-hidden .foldout {
|
|
610
611
|
/** for when there's no logo we want to center the foldout **/
|
|
611
612
|
min-width: 24ch;
|
|
612
|
-
margin-left: 50%;
|
|
613
|
-
transform: translateX(calc(-50% - .2rem));
|
|
614
613
|
}
|
|
615
614
|
|
|
616
615
|
.compact.top .foldout {
|
|
@@ -118,6 +118,12 @@ export class AROverlayHandler {
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
private ensureQuitARButton(element: HTMLElement) {
|
|
121
|
+
|
|
122
|
+
// No quit button in app clips, we provide one via the native UI
|
|
123
|
+
if (DeviceUtilities.isNeedleAppClip()) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
121
127
|
const quitARSlot = document.createElement("slot");
|
|
122
128
|
quitARSlot.setAttribute("name", "quit-ar");
|
|
123
129
|
this.appendElement(quitARSlot, element);
|
|
@@ -356,7 +356,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
356
356
|
case "loadfinished":
|
|
357
357
|
if (typeof newValue === "string" && newValue.length > 0) {
|
|
358
358
|
if (debug) console.log(name + " attribute changed", newValue);
|
|
359
|
-
this.registerEventFromAttribute(
|
|
359
|
+
this.registerEventFromAttribute(name, newValue);
|
|
360
360
|
}
|
|
361
361
|
break;
|
|
362
362
|
case "dracoDecoderPath":
|
|
@@ -708,7 +708,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
708
708
|
if (attributeValue)
|
|
709
709
|
this.registerEventFromAttribute("loadstart", attributeValue);
|
|
710
710
|
}
|
|
711
|
-
private registerEventFromAttribute(eventName: 'loadfinished' | 'loadstart', code: string) {
|
|
711
|
+
private registerEventFromAttribute(eventName: 'loadfinished' | 'loadstart' | 'progress', code: string) {
|
|
712
712
|
const prev = this._previouslyRegisteredMap.get(eventName);
|
|
713
713
|
if (prev) {
|
|
714
714
|
this._previouslyRegisteredMap.delete(eventName);
|
|
@@ -82,6 +82,34 @@ function getDOMOverlayElement(domElement: HTMLElement) {
|
|
|
82
82
|
handleSessionGranted();
|
|
83
83
|
async function handleSessionGranted() {
|
|
84
84
|
|
|
85
|
+
// await delay(400);
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
let defaultMode: XRSessionMode = "immersive-vr";
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
// In app clips we default to AR
|
|
92
|
+
if (DeviceUtilities.isNeedleAppClip()) {
|
|
93
|
+
defaultMode = "immersive-ar";
|
|
94
|
+
}
|
|
95
|
+
// Check if VR is even supported, otherwise try AR
|
|
96
|
+
else if (!(await navigator.xr?.isSessionSupported("immersive-vr"))) {
|
|
97
|
+
defaultMode = "immersive-ar";
|
|
98
|
+
}
|
|
99
|
+
// Check if AR is supported, otherwise we can't do anything
|
|
100
|
+
if (!(await navigator.xr?.isSessionSupported("immersive-ar")) && defaultMode === "immersive-ar") {
|
|
101
|
+
console.warn("[NeedleXRSession:granted] Neither VR nor AR supported, aborting session start.");
|
|
102
|
+
// showBalloonMessage("NeidleXRSession: Neither VR nor AR supported, aborting session start.");
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
} catch (e) {
|
|
106
|
+
console.error("[NeedleXRSession:granted] Error while checking XR support:", e);
|
|
107
|
+
// showBalloonWarning("NeedleXRSession: Error while checking XR support: " + (e as Error).message);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// showBalloonMessage("sessiongranted: " + defaultMode);
|
|
112
|
+
|
|
85
113
|
// TODO: asap session granted doesnt handle the pre-room yet
|
|
86
114
|
if (getParam("debugasap")) {
|
|
87
115
|
let asapSession = globalThis["needle:XRSession"] as XRSession | undefined | Promise<XRSession>;
|
|
@@ -94,11 +122,11 @@ async function handleSessionGranted() {
|
|
|
94
122
|
enableSpatialConsole(true);
|
|
95
123
|
const session = await asapSession;
|
|
96
124
|
if (session) {
|
|
97
|
-
const sessionInit = NeedleXRSession.getDefaultSessionInit(
|
|
98
|
-
NeedleXRSession.setSession(
|
|
125
|
+
const sessionInit = NeedleXRSession.getDefaultSessionInit(defaultMode);
|
|
126
|
+
NeedleXRSession.setSession(defaultMode, session, sessionInit, cb.context);
|
|
99
127
|
}
|
|
100
128
|
else {
|
|
101
|
-
console.error("NeedleXRSession: ASAP session was rejected");
|
|
129
|
+
console.error("[NeedleXRSession:granted] ASAP session was rejected");
|
|
102
130
|
}
|
|
103
131
|
asapSession = undefined;
|
|
104
132
|
});
|
|
@@ -106,6 +134,9 @@ async function handleSessionGranted() {
|
|
|
106
134
|
}
|
|
107
135
|
}
|
|
108
136
|
|
|
137
|
+
// console.log("Attaching sessiongranted handler...", { haveXR: 'xr' in navigator });
|
|
138
|
+
// setTimeout(() => console.log("Session Granted handler attached.", { haveXR: 'xr' in navigator }), 1000);
|
|
139
|
+
|
|
109
140
|
if ('xr' in navigator) {
|
|
110
141
|
// WebXRViewer (based on Firefox) has a bug where addEventListener
|
|
111
142
|
// throws a silent exception and aborts execution entirely.
|
|
@@ -115,10 +146,7 @@ async function handleSessionGranted() {
|
|
|
115
146
|
}
|
|
116
147
|
|
|
117
148
|
navigator.xr?.addEventListener('sessiongranted', async () => {
|
|
118
|
-
enableSpatialConsole(true);
|
|
119
|
-
|
|
120
|
-
console.log("Received Session Granted...")
|
|
121
|
-
await delay(100);
|
|
149
|
+
// enableSpatialConsole(true);
|
|
122
150
|
|
|
123
151
|
const lastSessionMode = sessionStorage.getItem("needle_xr_session_mode") as XRSessionMode;
|
|
124
152
|
const lastSessionInit = sessionStorage.getItem("needle_xr_session_init") ?? null;
|
|
@@ -126,7 +154,8 @@ async function handleSessionGranted() {
|
|
|
126
154
|
|
|
127
155
|
let info: SessionInfo | null = null;
|
|
128
156
|
if (contextIsLoading()) {
|
|
129
|
-
await TemporaryXRContext.start(lastSessionMode ||
|
|
157
|
+
await TemporaryXRContext.start(lastSessionMode || defaultMode, init || NeedleXRSession.getDefaultSessionInit(defaultMode))
|
|
158
|
+
.catch(e => console.warn("[NeedleXRSession:granted] TemporaryXRContext start failed:", e));
|
|
130
159
|
await waitForContextLoadingFinished();
|
|
131
160
|
info = await TemporaryXRContext.handoff();
|
|
132
161
|
}
|
|
@@ -134,17 +163,19 @@ async function handleSessionGranted() {
|
|
|
134
163
|
NeedleXRSession.setSession(info.mode, info.session, info.init, Context.Current);
|
|
135
164
|
}
|
|
136
165
|
else if (lastSessionMode && lastSessionInit) {
|
|
137
|
-
console.log("
|
|
166
|
+
console.log("[NeedleXRSession:granted] Restore last session")
|
|
138
167
|
const init = JSON.parse(lastSessionInit);
|
|
139
168
|
NeedleXRSession.start(lastSessionMode as XRSessionMode, init).catch(e => console.warn(e));
|
|
140
169
|
}
|
|
141
170
|
else {
|
|
142
171
|
// if no session was found we start VR by default
|
|
143
|
-
NeedleXRSession.start(
|
|
172
|
+
NeedleXRSession.start(defaultMode).catch(e => console.warn("[NeedleXRSession:granted] failed:", e));
|
|
144
173
|
}
|
|
145
174
|
// make sure we only subscribe to the event once
|
|
146
175
|
}, { once: true });
|
|
147
|
-
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
// showBalloonWarning("NeedleXRSession: WebXR not available in this browser.");
|
|
148
179
|
}
|
|
149
180
|
}
|
|
150
181
|
function saveSessionInfo(mode: XRSessionMode, init: XRSessionInit) {
|
|
@@ -419,28 +450,48 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
419
450
|
* @param init The XRSessionInit to use (optional), docs: https://developer.mozilla.org/en-US/docs/Web/API/XRSessionInit
|
|
420
451
|
* @param context The Needle Engine context to use
|
|
421
452
|
*/
|
|
422
|
-
static async start(mode: XRSessionMode | "ar", init?: XRSessionInit, context?: Context): Promise<NeedleXRSession | null> {
|
|
453
|
+
static async start(mode: XRSessionMode | "ar" | "quicklook", init?: XRSessionInit, context?: Context): Promise<NeedleXRSession | null> {
|
|
423
454
|
|
|
424
|
-
// handle iOS platform where "immersive-ar" is
|
|
455
|
+
// handle iOS platform where "immersive-ar" is special:
|
|
456
|
+
// - we either launch QuickLook
|
|
457
|
+
// - or forward to the Needle App Clip experience for WebXR AR
|
|
425
458
|
// TODO: should we add a separate mode (e.g. "AR")? https://linear.app/needle/issue/NE-5303
|
|
426
459
|
if (DeviceUtilities.isiOS()) {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
460
|
+
|
|
461
|
+
const arSupported = await this.isARSupported().catch(() => false);
|
|
462
|
+
|
|
463
|
+
// On VisionOS, we use QuickLook for AR experiences; no AppClip support for now.
|
|
464
|
+
if (DeviceUtilities.isVisionOS() && !arSupported && (mode === "ar" || mode === "immersive-ar")) {
|
|
465
|
+
mode = "quicklook";
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
if (mode === "quicklook") {
|
|
469
|
+
InternalUSDZRegistry.exportAndOpen();
|
|
470
|
+
return null;
|
|
436
471
|
}
|
|
472
|
+
|
|
473
|
+
if (!arSupported && (mode === "immersive-ar" || mode === "ar")) {
|
|
474
|
+
// Forward to the AppClip experience
|
|
475
|
+
// const url = `https://appclip.apple.com/id?p=tools.needle.launch-app.Clip&url=${encodeURIComponent(location.href)}`
|
|
476
|
+
const url =`https://appclip.needle.tools/ar?url=${encodeURIComponent(location.href)}`;
|
|
477
|
+
console.debug("iOS device detected - opening Needle App Clip for AR experience", url, { mode, init });
|
|
478
|
+
// navigate to app clip url but keep the current url in history, open in same tab
|
|
479
|
+
window.location.href = url;
|
|
480
|
+
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (mode === "quicklook") {
|
|
486
|
+
console.warn("QuickLook mode is only supported on iOS devices");
|
|
487
|
+
return null;
|
|
437
488
|
}
|
|
438
|
-
|
|
489
|
+
|
|
490
|
+
// Since we now know we are not on iOS, ar mode becomes "immersive-ar"
|
|
491
|
+
if (mode == "ar") {
|
|
439
492
|
mode = "immersive-ar";
|
|
440
493
|
}
|
|
441
494
|
|
|
442
|
-
|
|
443
|
-
|
|
444
495
|
if (isDevEnvironment() && getParam("debugxrpreroom")) {
|
|
445
496
|
console.warn("Debug: Starting temporary XR session");
|
|
446
497
|
await TemporaryXRContext.start(mode, init || NeedleXRSession.getDefaultSessionInit(mode));
|
|
@@ -539,8 +590,8 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
539
590
|
this._currentSessionRequestMode = mode;
|
|
540
591
|
/**@type {XRSystem} */
|
|
541
592
|
const newSession = await (this._currentSessionRequest)?.catch(e => {
|
|
542
|
-
console.error(e, "Code: " + e
|
|
543
|
-
if (e
|
|
593
|
+
console.error(e, "Code: " + e?.code);
|
|
594
|
+
if (e?.code === 9) showBalloonWarning("Couldn't start XR session. Make sure you allow the required permissions.")
|
|
544
595
|
console.log("If the specified XR configuration is not supported (e.g. entering AR doesnt work) - make sure you access the website on a secure connection (HTTPS) and your device has the required permissions (e.g. camera access)");
|
|
545
596
|
const notSecure = location.protocol === 'http:';
|
|
546
597
|
if (notSecure) showBalloonWarning("XR requires a secure connection (HTTPS)");
|
|
@@ -32,7 +32,13 @@ export class TemporaryXRContext {
|
|
|
32
32
|
return null;
|
|
33
33
|
}
|
|
34
34
|
this._requestInFlight = true;
|
|
35
|
-
const session = await navigator.xr.requestSession(mode, init)
|
|
35
|
+
const session = await navigator.xr.requestSession(mode, init).catch(err => {
|
|
36
|
+
console.error("Failed to start temporary XR session:", err);
|
|
37
|
+
});
|
|
38
|
+
if (!session) {
|
|
39
|
+
this._requestInFlight = false;
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
36
42
|
session.addEventListener("end", () => {
|
|
37
43
|
this._active = null;
|
|
38
44
|
});
|
|
@@ -82,10 +88,14 @@ export class TemporaryXRContext {
|
|
|
82
88
|
this._session = session;
|
|
83
89
|
this._session.addEventListener("end", this.onEnd);
|
|
84
90
|
|
|
85
|
-
this._renderer = new WebGLRenderer({ alpha: true });
|
|
91
|
+
this._renderer = new WebGLRenderer({ alpha: true, antialias: true });
|
|
92
|
+
this._renderer.outputColorSpace = 'srgb';
|
|
86
93
|
this._renderer.setAnimationLoop(this.onFrame);
|
|
87
94
|
this._renderer.xr.setSession(session);
|
|
88
95
|
this._renderer.xr.enabled = true;
|
|
96
|
+
// Set pixel ratio and size
|
|
97
|
+
this._renderer.setPixelRatio(Math.min(2, window.devicePixelRatio));
|
|
98
|
+
this._renderer.setSize(window.innerWidth, window.innerHeight);
|
|
89
99
|
this._camera = new PerspectiveCamera();
|
|
90
100
|
this._scene = new Scene();
|
|
91
101
|
this._scene.fog = new Fog(0x444444, 10, 250);
|
package/src/engine/xr/usdz.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isDevEnvironment } from "../debug/index.js";
|
|
1
2
|
|
|
2
3
|
declare type USDZExporter = {
|
|
3
4
|
exportAndOpen(): Promise<any>,
|
|
@@ -11,7 +12,11 @@ export namespace InternalUSDZRegistry {
|
|
|
11
12
|
const usdzExporter: USDZExporter[] = [];
|
|
12
13
|
|
|
13
14
|
export function exportAndOpen(): boolean {
|
|
14
|
-
if (!usdzExporter?.length)
|
|
15
|
+
if (!usdzExporter?.length) {
|
|
16
|
+
if (isDevEnvironment()) {
|
|
17
|
+
console.warn("No USDZ exporters found – cannot export USDZ for QuickLook.");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
15
20
|
for (const exp of usdzExporter) {
|
|
16
21
|
exp.exportAndOpen();
|
|
17
22
|
}
|
|
@@ -9,9 +9,8 @@ import { Behaviour, GameObject } from "./Component.js";
|
|
|
9
9
|
* You can use this to create dynamic beams or connectors between objects.
|
|
10
10
|
*
|
|
11
11
|
* @summary Aligns and scales the object between two target GameObjects
|
|
12
|
-
* @category
|
|
12
|
+
* @category Constraints
|
|
13
13
|
* @group Components
|
|
14
|
-
|
|
15
14
|
**/
|
|
16
15
|
export class AlignmentConstraint extends Behaviour {
|
|
17
16
|
|
|
@@ -43,6 +43,7 @@ export declare class PlayOptions {
|
|
|
43
43
|
* It works with an {@link AnimatorController} to handle state transitions and animation blending.
|
|
44
44
|
* A new AnimatorController can be created from code via `AnimatorController.createFromClips`.
|
|
45
45
|
*
|
|
46
|
+
* @summary Plays and manages animations on a GameObject based on an AnimatorController
|
|
46
47
|
* @category Animation and Sequencing
|
|
47
48
|
* @group Components
|
|
48
49
|
*/
|
|
@@ -9,7 +9,7 @@ import { Behaviour, GameObject } from "./Component.js";
|
|
|
9
9
|
* This component creates and manages a Three.js {@link three#AudioListener}, automatically connecting it
|
|
10
10
|
* to the main camera or a Camera in the parent hierarchy.
|
|
11
11
|
*
|
|
12
|
-
* @summary
|
|
12
|
+
* @summary Receives audio in the scene and outputs it to speakers
|
|
13
13
|
* @category Multimedia
|
|
14
14
|
* @group Components
|
|
15
15
|
*/
|
|
@@ -52,7 +52,7 @@ export enum AudioRolloffMode {
|
|
|
52
52
|
* is muted, the volume is set to 0. When unmuted, the volume
|
|
53
53
|
* returns to its previous value.
|
|
54
54
|
*
|
|
55
|
-
* @summary
|
|
55
|
+
* @summary Plays audio clips from files or media streams
|
|
56
56
|
* @category Multimedia
|
|
57
57
|
* @group Components
|
|
58
58
|
*/
|
|
@@ -3,6 +3,14 @@ import { Vector3 } from "three";
|
|
|
3
3
|
import * as utils from "./../engine/engine_three_utils.js";
|
|
4
4
|
import { Behaviour, GameObject } from "./Component.js";
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* BasicIKConstraint positions the GameObject between two target GameObjects (`from` and `to`) with an optional `hint` GameObject to guide the bending direction.
|
|
8
|
+
* This is useful for simple inverse kinematics setups, such as positioning a joint in a limb.
|
|
9
|
+
*
|
|
10
|
+
* @summary Simple Inverse Kinematics Constraint
|
|
11
|
+
* @category Animation
|
|
12
|
+
* @group Components
|
|
13
|
+
*/
|
|
6
14
|
export class BasicIKConstraint extends Behaviour {
|
|
7
15
|
|
|
8
16
|
private from!: GameObject;
|
|
@@ -14,6 +14,7 @@ const debug = getParam("debugboxhelper");
|
|
|
14
14
|
* Debug mode can be enabled with the URL parameter `?debugboxhelper`, which will visualize intersection tests.
|
|
15
15
|
* Helper visualization can be enabled with the URL parameter `?gizmos`.
|
|
16
16
|
*
|
|
17
|
+
* @summary Bounding box helper with intersection tests
|
|
17
18
|
* @category Helpers
|
|
18
19
|
* @group Components
|
|
19
20
|
*/
|
|
@@ -36,8 +36,8 @@ const debugscreenpointtoray = getParam("debugscreenpointtoray");
|
|
|
36
36
|
* Supports both perspective and orthographic cameras with various rendering options.
|
|
37
37
|
* Internally, this component uses {@link PerspectiveCamera} and {@link OrthographicCamera} three.js objects.
|
|
38
38
|
*
|
|
39
|
-
* @summary
|
|
40
|
-
* @category Camera
|
|
39
|
+
* @summary Rendering scenes from a specific viewpoint
|
|
40
|
+
* @category Camera and Controls
|
|
41
41
|
* @group Components
|
|
42
42
|
*/
|
|
43
43
|
export class Camera extends Behaviour implements ICamera {
|
|
@@ -110,8 +110,12 @@ export class CharacterController extends Behaviour {
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
/**
|
|
113
|
-
*
|
|
114
|
-
*
|
|
113
|
+
* CharacterControllerInput handles user input to control a CharacterController.
|
|
114
|
+
* It supports movement, looking around, jumping, and double jumping.
|
|
115
|
+
* You can customize movement speed, rotation speed, and jump forces.
|
|
116
|
+
* It also integrates with an Animator component for character animations.
|
|
117
|
+
* @summary User Input for Character Controller
|
|
118
|
+
* @category Character
|
|
115
119
|
* @group Components
|
|
116
120
|
*/
|
|
117
121
|
export class CharacterControllerInput extends Behaviour {
|
|
@@ -22,11 +22,11 @@ import { Rigidbody } from "./RigidBody.js";
|
|
|
22
22
|
* - Example: https://samples.needle.tools/physics-playground
|
|
23
23
|
* - Example: https://samples.needle.tools/physics-&-animation
|
|
24
24
|
*
|
|
25
|
-
*
|
|
25
|
+
* @summary Physics collider
|
|
26
26
|
* @category Physics
|
|
27
27
|
* @group Components
|
|
28
28
|
*/
|
|
29
|
-
export class Collider extends Behaviour implements ICollider {
|
|
29
|
+
export abstract class Collider extends Behaviour implements ICollider {
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* Identifies this component as a collider.
|
|
@@ -476,10 +476,11 @@ export abstract class GameObject extends Object3D implements Object3D, IGameObje
|
|
|
476
476
|
* Gets a component of the specified type in the gameObject's children hierarchy
|
|
477
477
|
* @param go GameObject to search in
|
|
478
478
|
* @param typeName Constructor of the component type
|
|
479
|
+
* @param includeInactive Whether to include inactive objects in the search
|
|
479
480
|
* @returns The first matching component if found, otherwise null
|
|
480
481
|
*/
|
|
481
|
-
public static getComponentInChildren<T extends IComponent>(go: IGameObject | Object3D, typeName: Constructor<T
|
|
482
|
-
return getComponentInChildren(go, typeName);
|
|
482
|
+
public static getComponentInChildren<T extends IComponent>(go: IGameObject | Object3D, typeName: Constructor<T>, includeInactive: boolean = false): T | null {
|
|
483
|
+
return getComponentInChildren(go, typeName, includeInactive);
|
|
483
484
|
}
|
|
484
485
|
|
|
485
486
|
/**
|
|
@@ -588,7 +589,7 @@ export abstract class Component implements IComponent, EventTarget,
|
|
|
588
589
|
*/
|
|
589
590
|
get [$componentName]() { return TypeStore.getKey(this.constructor as any) || undefined; }
|
|
590
591
|
|
|
591
|
-
|
|
592
|
+
|
|
592
593
|
private __context: Context | undefined;
|
|
593
594
|
|
|
594
595
|
/**
|
|
@@ -1106,7 +1107,7 @@ export abstract class Component implements IComponent, EventTarget,
|
|
|
1106
1107
|
this.dispatchEvent(new CustomEvent("destroyed", { detail: this }));
|
|
1107
1108
|
}
|
|
1108
1109
|
destroyComponentInstance(this as any);
|
|
1109
|
-
if(isHotReloadEnabled()) unregisterHotReloadType(this);
|
|
1110
|
+
if (isHotReloadEnabled()) unregisterHotReloadType(this);
|
|
1110
1111
|
}
|
|
1111
1112
|
|
|
1112
1113
|
/**
|
|
@@ -53,7 +53,7 @@ type FitParameters = {
|
|
|
53
53
|
*
|
|
54
54
|
* ContactShadows can also be enabled on the `<needle-engine>` web component directly by adding the `contactshadows` attribute. The value of the attribute will be used as opacity and darkness of the shadows: `<needle-engine contactshadows="0.7">`.
|
|
55
55
|
*
|
|
56
|
-
*
|
|
56
|
+
* @summary Display contact shadows on the ground
|
|
57
57
|
* @category Rendering
|
|
58
58
|
* @group Components
|
|
59
59
|
*/
|
|
@@ -485,6 +485,8 @@ interface IDragHandler {
|
|
|
485
485
|
onDragUpdate?(numberOfPointers: number): void;
|
|
486
486
|
}
|
|
487
487
|
|
|
488
|
+
|
|
489
|
+
// #region MultiTouchDragHandler
|
|
488
490
|
/**
|
|
489
491
|
* Handles two touch points affecting one object.
|
|
490
492
|
* Enables multi-touch interactions that allow movement, scaling, and rotation of objects.
|
|
@@ -734,6 +736,7 @@ class MultiTouchDragHandler implements IDragHandler {
|
|
|
734
736
|
}
|
|
735
737
|
|
|
736
738
|
|
|
739
|
+
// #region DragPointerHandler
|
|
737
740
|
/**
|
|
738
741
|
* Handles a single pointer on an object.
|
|
739
742
|
* DragPointerHandlers manage determining if a drag operation has started, tracking pointer movement,
|
|
@@ -1335,6 +1338,7 @@ class DragPointerHandler implements IDragHandler {
|
|
|
1335
1338
|
}
|
|
1336
1339
|
}
|
|
1337
1340
|
|
|
1341
|
+
// #region LegacyDragVisualsHelper
|
|
1338
1342
|
/**
|
|
1339
1343
|
* Provides visual helper elements for DragControls.
|
|
1340
1344
|
* Shows where objects will be placed and their relation to surfaces below them.
|
|
@@ -8,6 +8,8 @@ import { Behaviour } from "./Component.js";
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* BoxGizmo is a component that displays a box around the object in the scene. It can optionally expand to the object's bounds.
|
|
11
|
+
*
|
|
12
|
+
* @summary Display a box around the object
|
|
11
13
|
* @category Helpers
|
|
12
14
|
* @group Components
|
|
13
15
|
*/
|