Needle Engine

Changes between version 3.32.11-alpha and 3.31.2
Files changed (229) hide show
  1. src/engine-schemes/vrUserStateBuffer.fbs +0 -0
  2. plugins/next/next.js +13 -4
  3. src/engine-schemes/README.md +0 -2
  4. src/engine-components/export/usdz/extensions/behavior/Actions.ts +2 -3
  5. src/engine-components/AlignmentConstraint.ts +2 -3
  6. src/engine-components/Animation.ts +3 -4
  7. src/engine-components/export/usdz/extensions/Animation.ts +4 -5
  8. src/engine-components/AnimationCurve.ts +2 -18
  9. src/engine-components/AnimationUtils.ts +3 -4
  10. src/engine-components/export/usdz/utils/animationutils.ts +4 -5
  11. src/engine-components/Animator.ts +5 -6
  12. src/engine-components/AnimatorController.ts +9 -10
  13. src/engine-components/postprocessing/Effects/Antialiasing.ts +0 -1
  14. src/engine-components/api.ts +8 -6
  15. src/engine/api.ts +22 -21
  16. src/engine-components/export/usdz/extensions/behavior/AudioExtension.ts +2 -3
  17. src/engine-components/AudioListener.ts +1 -2
  18. src/engine-components/AudioSource.ts +8 -13
  19. src/engine-components/avatar/Avatar_Brain_LookAt.ts +4 -5
  20. src/engine-components/avatar/Avatar_MouthShapes.ts +3 -4
  21. src/engine-components/webxr/Avatar.ts +0 -221
  22. src/engine-components/avatar/AvatarBlink_Simple.ts +2 -3
  23. src/engine-components/avatar/AvatarEyeLook_Rotation.ts +4 -5
  24. src/engine-components/AvatarLoader.ts +5 -6
  25. src/engine-components/AxesHelper.ts +2 -3
  26. src/engine-components/ui/BaseUIComponent.ts +25 -27
  27. src/engine-components/BasicIKConstraint.ts +2 -3
  28. src/engine-components/export/usdz/extensions/behavior/Behaviour.ts +1 -1
  29. src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts +13 -12
  30. src/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.ts +2 -2
  31. src/engine-components/postprocessing/Effects/Bloom.ts +0 -1
  32. src/engine-components/BoxHelperComponent.ts +3 -4
  33. src/engine-components/ui/Button.ts +10 -10
  34. src/engine-components/Camera.ts +13 -12
  35. src/engine-components/CameraUtils.ts +7 -8
  36. src/engine-components/ui/Canvas.ts +20 -38
  37. src/engine-components/ui/CanvasGroup.ts +3 -3
  38. src/engine-components/CharacterController.ts +4 -5
  39. src/engine-components/postprocessing/Effects/ChromaticAberration.ts +0 -1
  40. src/engine-components/Collider.ts +5 -6
  41. src/engine-components/postprocessing/Effects/ColorAdjustments.ts +1 -2
  42. src/engine-components/Component.ts +19 -112
  43. src/engine-components/codegen/components.ts +15 -10
  44. src/engine-components/ContactShadows.ts +3 -3
  45. src/engine/debug/debug_console.ts +4 -8
  46. src/engine/debug/debug_overlay.ts +7 -8
  47. src/engine/debug/debug.ts +2 -2
  48. src/engine-components/DeleteBox.ts +0 -1
  49. src/engine-components/postprocessing/Effects/DepthOfField.ts +12 -6
  50. src/engine-components/DeviceFlag.ts +1 -1
  51. src/engine-components/DragControls.ts +182 -939
  52. src/engine-components/DropListener.ts +4 -5
  53. src/engine-components/Duplicatable.ts +91 -73
  54. src/engine/engine_addressables.ts +6 -7
  55. src/engine/engine_assetdatabase.ts +1 -2
  56. src/engine/engine_camera.ts +1 -2
  57. src/engine/engine_components.ts +7 -8
  58. src/engine/engine_context.ts +68 -110
  59. src/engine/engine_create_objects.ts +1 -13
  60. src/engine/engine_element_loading.ts +11 -24
  61. src/engine/engine_element_overlay.ts +0 -17
  62. src/engine/engine_element.ts +10 -35
  63. src/engine/engine_gameobject.ts +9 -9
  64. src/engine/engine_gizmos.ts +20 -61
  65. src/engine/engine_gltf_builtin_components.ts +9 -11
  66. src/engine/engine_gltf.ts +3 -4
  67. src/engine/engine_hot_reload.ts +2 -2
  68. src/engine/engine_input.ts +185 -474
  69. src/engine/engine_license.ts +6 -9
  70. src/engine/engine_lifecycle_api.ts +4 -28
  71. src/engine/engine_lifecycle_functions_internal.ts +2 -2
  72. src/engine/engine_lightdata.ts +3 -4
  73. src/engine/engine_loaders.ts +3 -3
  74. src/engine/engine_mainloop_utils.ts +7 -34
  75. src/engine/engine_networking_auto.ts +1 -1
  76. src/engine/engine_networking_files_default_components.ts +1 -2
  77. src/engine/engine_networking_files.ts +7 -8
  78. src/engine/engine_networking_instantiate.ts +12 -17
  79. src/engine/engine_networking_peer.ts +1 -2
  80. src/engine/engine_networking_streams.ts +7 -8
  81. src/engine/engine_networking.ts +8 -12
  82. src/engine/engine_physics_rapier.ts +44 -56
  83. src/engine/engine_physics.ts +18 -23
  84. src/engine/engine_playerview.ts +1 -2
  85. src/engine/engine_scenelighting.ts +4 -5
  86. src/engine/engine_scenetools.ts +8 -9
  87. src/engine/engine_serialization_builtin_serializer.ts +6 -7
  88. src/engine/engine_serialization_core.ts +7 -8
  89. src/engine/engine_serialization.ts +5 -4
  90. src/engine/engine_shaders.ts +3 -4
  91. src/engine/engine_texture.ts +1 -2
  92. src/engine/engine_three_utils.ts +4 -18
  93. src/engine/engine_time.ts +1 -2
  94. src/engine/engine_types.ts +4 -25
  95. src/engine/engine_typestore.ts +4 -0
  96. src/engine/engine_util_decorator.ts +2 -3
  97. src/engine/engine_utils_screenshot.ts +1 -2
  98. src/engine/engine_utils.ts +6 -71
  99. src/engine/engine_xr.ts +0 -2
  100. src/engine/engine.ts +3 -3
  101. src/engine-components/ui/EventSystem.ts +178 -237
  102. src/engine-components/EventTrigger.ts +2 -2
  103. src/engine/extensions/EXT_texture_exr.ts +2 -3
  104. src/engine/extensions/extension_utils.ts +1 -2
  105. src/engine-components/export/usdz/Extension.ts +1 -2
  106. src/engine/extensions/extensions.ts +11 -12
  107. src/engine-components/js-extensions/ExtensionUtils.ts +0 -1
  108. src/engine-components/FlyControls.ts +1 -2
  109. src/engine-components/Fog.ts +1 -2
  110. src/engine-components/Gizmos.ts +4 -5
  111. src/engine-components/export/gltf/GltfExport.ts +6 -6
  112. src/engine-components/ui/Graphic.ts +7 -8
  113. src/engine-components/GridHelper.ts +3 -4
  114. src/engine-components/GroundProjection.ts +5 -11
  115. src/engine-components/ui/Image.ts +1 -2
  116. src/engine-components/export/usdz/index.ts +3 -3
  117. src/engine-components/postprocessing/index.ts +2 -2
  118. src/engine-components/timeline/index.ts +2 -2
  119. src/engine-components/webxr/index.ts +3 -2
  120. src/engine/extensions/index.ts +2 -2
  121. src/engine/xr/index.ts +0 -5
  122. src/engine-components/ui/InputField.ts +4 -4
  123. src/engine-components/Interactable.ts +14 -6
  124. src/engine/xr/internal.ts +0 -35
  125. src/engine-components/Joints.ts +0 -1
  126. src/engine-components/ui/Layout.ts +3 -3
  127. src/engine-components/Light.ts +13 -10
  128. src/engine-components/LODGroup.ts +4 -5
  129. src/engine-components/debug/LogStats.ts +1 -1
  130. src/engine-components/utils/LookAt.ts +4 -4
  131. src/engine-components/LookAtConstraint.ts +2 -3
  132. src/engine/extensions/NEEDLE_animator_controller_model.ts +2 -3
  133. src/engine/extensions/NEEDLE_components.ts +6 -7
  134. src/engine/extensions/NEEDLE_gameobject_data.ts +3 -3
  135. src/engine/extensions/NEEDLE_lighting_settings.ts +6 -7
  136. src/engine/extensions/NEEDLE_lightmaps.ts +7 -8
  137. src/engine/extensions/NEEDLE_persistent_assets.ts +2 -3
  138. src/engine/extensions/NEEDLE_progressive.ts +3 -5
  139. src/engine/extensions/NEEDLE_render_objects.ts +18 -18
  140. src/engine/extensions/NEEDLE_techniques_webgl.ts +5 -8
  141. src/needle-engine.ts +3 -0
  142. src/engine/xr/NeedleXRController.ts +0 -639
  143. src/engine/xr/NeedleXRSession.ts +0 -1247
  144. src/engine/xr/NeedleXRSync.ts +0 -221
  145. src/engine-components/NestedGltf.ts +4 -4
  146. src/engine-components/Networking.ts +1 -1
  147. src/engine-components/js-extensions/Object3D.ts +12 -11
  148. src/engine-components/OffsetConstraint.ts +3 -4
  149. src/engine-components/utils/OpenURL.ts +40 -8
  150. src/engine-components/OrbitControls.ts +15 -15
  151. src/engine-components/ui/Outline.ts +2 -3
  152. src/engine-components/ParticleSystem.ts +33 -33
  153. src/engine-components/ParticleSystemModules.ts +17 -66
  154. src/engine-components/ParticleSystemSubEmitter.ts +3 -4
  155. src/engine-components/postprocessing/Effects/Pixelation.ts +3 -4
  156. src/engine-components/timeline/PlayableDirector.ts +9 -10
  157. src/engine-components/PlayerColor.ts +14 -19
  158. src/engine-components-experimental/networking/PlayerSync.ts +26 -113
  159. src/engine-components/ui/PointerEvents.ts +30 -118
  160. src/engine-components/postprocessing/PostProcessingEffect.ts +4 -5
  161. src/engine-components/postprocessing/PostProcessingHandler.ts +4 -5
  162. src/engine-components-experimental/Presentation.ts +1 -1
  163. src/engine-components/ui/Raycaster.ts +8 -27
  164. src/engine-components/ui/RaycastUtils.ts +1 -2
  165. src/engine-components/ui/RectTransform.ts +5 -6
  166. src/engine-components/ReflectionProbe.ts +2 -3
  167. src/engine/codegen/register_types.ts +28 -17
  168. src/engine-components/Renderer.ts +38 -33
  169. src/engine-components/RendererLightmap.ts +2 -3
  170. src/engine-components/js-extensions/RGBAColor.ts +1 -2
  171. src/engine-components/RigidBody.ts +6 -7
  172. src/engine-components/SceneSwitcher.ts +12 -13
  173. src/engine/xr/SceneTransition.ts +0 -77
  174. src/engine-schemes/schemes.ts +1 -2
  175. src/engine-components/ScreenCapture.ts +8 -9
  176. src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.ts +0 -1
  177. src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.ts +2 -3
  178. src/engine-components/ShadowCatcher.ts +3 -4
  179. src/engine-components/timeline/SignalAsset.ts +2 -2
  180. src/engine-components/Skybox.ts +9 -10
  181. src/engine-components/SmoothFollow.ts +4 -5
  182. src/engine-components/ui/SpatialHtml.ts +0 -1
  183. src/engine-components/SpatialTrigger.ts +3 -4
  184. src/engine-components/SpectatorCamera.ts +33 -23
  185. src/engine-components/SpriteRenderer.ts +3 -4
  186. src/engine-components/SyncedCamera.ts +13 -13
  187. src/engine-components/SyncedRoom.ts +2 -2
  188. src/engine-components/SyncedTransform.ts +7 -25
  189. src/engine-components/webxr/TeleportTarget.ts +0 -9
  190. src/engine/xr/TempXRContext.ts +0 -183
  191. src/engine/tests/test_utils.ts +1 -1
  192. src/engine-components/TestRunner.ts +5 -6
  193. src/engine-components/ui/Text.ts +8 -9
  194. src/engine-components/export/usdz/ThreeUSDZExporter.ts +32 -33
  195. src/engine-components/postprocessing/Effects/TiltShiftEffect.ts +3 -4
  196. src/engine-components/timeline/TimelineTracks.ts +22 -60
  197. src/engine-components/postprocessing/Effects/Tonemapping.ts +0 -1
  198. src/engine-components/TransformGizmo.ts +5 -6
  199. src/engine-components/webxr/types.ts +0 -4
  200. src/engine/extensions/usage_tracker.ts +1 -2
  201. src/engine-components/export/usdz/USDZExporter.ts +92 -21
  202. src/engine-components/export/usdz/extensions/USDZText.ts +5 -6
  203. src/engine-components/export/usdz/extensions/USDZUI.ts +6 -7
  204. src/engine-components/ui/Utils.ts +2 -4
  205. src/engine/xr/utils.ts +0 -40
  206. src/engine-components/js-extensions/Vector.ts +1 -2
  207. src/engine-components/VideoPlayer.ts +6 -7
  208. src/engine-components/postprocessing/Effects/Vignette.ts +2 -3
  209. src/engine-components/Voip.ts +5 -6
  210. src/engine-components/postprocessing/Volume.ts +9 -7
  211. src/engine-components/postprocessing/VolumeParameter.ts +7 -0
  212. src/engine-schemes/vr-user-state-buffer.ts +30 -37
  213. src/engine-components/webxr/WebARCameraBackground.ts +53 -46
  214. src/engine-components/webxr/WebARSessionRoot.ts +29 -400
  215. src/engine-components/webxr/WebXR.ts +673 -207
  216. src/engine-components/webxr/WebXRAvatar.ts +300 -10
  217. src/engine-components/webxr/WebXRButtons.ts +0 -291
  218. src/engine-components/webxr/WebXRImageTracking.ts +77 -69
  219. src/engine-components/webxr/WebXRPlaneTracking.ts +49 -56
  220. src/engine-components/webxr/WebXRRig.ts +8 -45
  221. src/engine-components/webxr/controllers/XRControllerFollow.ts +0 -67
  222. src/engine-components/webxr/controllers/XRControllerModel.ts +0 -253
  223. src/engine-components/webxr/controllers/XRControllerMovement.ts +0 -328
  224. src/engine-components/webxr/XRFlag.ts +0 -143
  225. src/engine/xr/XRRig.ts +0 -9
  226. src/engine-components/webxr/WebXRController.ts +1168 -0
  227. src/engine-components/webxr/WebXRGrabRendering.ts +151 -0
  228. src/engine-components/webxr/WebXRSync.ts +463 -0
  229. src/engine-components/XRFlag.ts +139 -0
src/engine-schemes/vrUserStateBuffer.fbs CHANGED
File without changes
plugins/next/next.js CHANGED
@@ -16,15 +16,18 @@
16
16
  * @returns {import('next').NextConfig}
17
17
  */
18
18
  export const needleNext = (nextConfig, userSettings) => {
19
- if (!nextConfig) nextConfig = {
20
- reactStrictMode: true,
21
- };
19
+ console.log("Apply 🌵 needle next config");
22
20
 
21
+ if (!nextConfig)
22
+ nextConfig = {
23
+ reactStrictMode: true,
24
+ };
25
+
23
26
  // add transpile packages
24
27
  if (!nextConfig.transpilePackages) {
25
28
  nextConfig.transpilePackages = [];
26
29
  }
27
- nextConfig.transpilePackages.push("three", "peerjs", "@needle-tools/engine", "three-mesh-ui");
30
+ nextConfig.transpilePackages.push("three", "peerjs", "three-mesh-ui");
28
31
 
29
32
  // add webpack config
30
33
  if (!nextConfig.webpack) nextConfig.webpack = nextWebPack;
@@ -37,6 +40,12 @@
37
40
  }
38
41
  /** @param {import ('next').NextConfig config } */
39
42
  function nextWebPack(config, { buildId, dev, isServer, defaultLoaders, webpack }) {
43
+
44
+ // workaround: fix type finding in production builds
45
+ console.log("Apply next webpack config concatentateModules=false, pathinfo=verbose");
46
+ config.optimization.concatenateModules = false;
47
+ config.output.pathinfo = 'verbose';
48
+
40
49
  const meta = getMeta();
41
50
  let useRapier = true;
42
51
  if (userSettings.useRapier === false) useRapier = false;
src/engine-schemes/README.md DELETED
@@ -1,2 +0,0 @@
1
- Using flatbuffer compiler 2.0
2
- https://github.com/google/flatbuffers/releases/tag/v2.0.0
src/engine-components/export/usdz/extensions/behavior/Actions.ts CHANGED
@@ -1,7 +1,6 @@
1
- import { BufferGeometry,Material, Matrix4, Object3D } from "three";
2
-
3
- import { USDDocument,USDObject } from "../../ThreeUSDZExporter.js";
1
+ import { Object3D, Matrix4, Material, BufferGeometry } from "three";
4
2
  import { ActionBuilder, ActionModel } from "./BehavioursBuilder.js";
3
+ import { USDObject, USDDocument } from "../../ThreeUSDZExporter.js";
5
4
 
6
5
  export abstract class DocumentAction {
7
6
 
src/engine-components/AlignmentConstraint.ts CHANGED
@@ -1,8 +1,7 @@
1
+ import { Behaviour, GameObject } from "./Component.js";
2
+ import * as utils from "./../engine/engine_three_utils.js";
1
3
  import { Vector3 } from "three";
2
-
3
4
  import { serializable } from "../engine/engine_serialization_decorator.js";
4
- import * as utils from "./../engine/engine_three_utils.js";
5
- import { Behaviour, GameObject } from "./Component.js";
6
5
 
7
6
  export class AlignmentConstraint extends Behaviour {
8
7
 
src/engine-components/Animation.ts CHANGED
@@ -1,11 +1,10 @@
1
+ import { Behaviour } from "./Component.js";
1
2
  import { AnimationAction, AnimationClip, AnimationMixer, LoopOnce, LoopRepeat } from "three";
2
-
3
+ import { MixerEvent } from "./Animator.js";
4
+ import { serializable } from "../engine/engine_serialization_decorator.js";
3
5
  import { Mathf } from "../engine/engine_math.js";
4
- import { serializable } from "../engine/engine_serialization_decorator.js";
5
6
  import type { Vec2 } from "../engine/engine_types.js";
6
7
  import { getParam } from "../engine/engine_utils.js";
7
- import { MixerEvent } from "./Animator.js";
8
- import { Behaviour } from "./Component.js";
9
8
 
10
9
  const debug = getParam("debuganimation");
11
10
 
src/engine-components/export/usdz/extensions/Animation.ts CHANGED
@@ -1,10 +1,9 @@
1
- import { AnimationClip, Bone,Interpolant, KeyframeTrack, Matrix4, Object3D, PropertyBinding, Quaternion, Vector3 } from "three";
2
-
1
+ import { GameObject } from "../../../Component.js";
3
2
  import { getParam } from "../../../../engine/engine_utils.js";
3
+ import { USDObject, buildMatrix, findStructuralNodesInBoneHierarchy, usdNumberFormatting as fn, getPathToSkeleton } from "../ThreeUSDZExporter.js";
4
+ import type { IUSDExporterExtension } from "../Extension.js";
5
+ import { Object3D, Matrix4, Vector3, Quaternion, Interpolant, AnimationClip, KeyframeTrack, PropertyBinding, Bone } from "three";
4
6
  import { Animator } from "../../../Animator.js";
5
- import { GameObject } from "../../../Component.js";
6
- import type { IUSDExporterExtension } from "../Extension.js";
7
- import { buildMatrix, findStructuralNodesInBoneHierarchy, getPathToSkeleton,usdNumberFormatting as fn, USDObject } from "../ThreeUSDZExporter.js";
8
7
 
9
8
  const debug = getParam("debugusdzanimation");
10
9
  const debugSerialization = getParam("debugusdzanimationserialization");
src/engine-components/AnimationCurve.ts CHANGED
@@ -23,22 +23,6 @@
23
23
  @serializable(Keyframe)
24
24
  keys!: Array<Keyframe>;
25
25
 
26
- clone() {
27
- const curve = new AnimationCurve();
28
- curve.keys = this.keys?.map(k => {
29
- const key = new Keyframe();
30
- key.time = k.time;
31
- key.value = k.value;
32
- key.inTangent = k.inTangent;
33
- key.inWeight = k.inWeight;
34
- key.outTangent = k.outTangent;
35
- key.outWeight = k.outWeight;
36
- key.weightedMode = k.weightedMode;
37
- return key;
38
- }) || [];
39
- return curve;
40
- }
41
-
42
26
  get duration(): number {
43
27
  if (!this.keys || this.keys.length == 0) return 0;
44
28
  return this.keys[this.keys.length - 1].time;
@@ -54,9 +38,9 @@
54
38
  for (let i = 0; i < this.keys.length; i++) {
55
39
  const kf = this.keys[i];
56
40
  if (kf.time <= time) {
57
- const hasNextKeyframe = i + 1 < this.keys.length;
41
+ const hasNextKeyframe = i+1 < this.keys.length;
58
42
  if (hasNextKeyframe) {
59
- const nextKf = this.keys[i + 1];
43
+ const nextKf = this.keys[i+1];
60
44
  // if the next
61
45
  if (nextKf.time < time) continue;
62
46
  // tangents are set to Infinity if interpolation is set to constant - in that case we should always return the floored value
src/engine-components/AnimationUtils.ts CHANGED
@@ -1,12 +1,11 @@
1
- import { Object3D } from "three";
2
1
  import type { GLTF } from "three/examples/jsm/loaders/GLTFLoader.js";
3
-
2
+ import { ContextEvent, ContextRegistry } from "../engine/engine_context_registry.js";
4
3
  import { addNewComponent } from "../engine/engine_components.js";
5
- import { ContextEvent, ContextRegistry } from "../engine/engine_context_registry.js";
4
+ import { Animator } from "./Animator.js";
6
5
  import { Animation } from "./Animation.js";
7
- import { Animator } from "./Animator.js";
8
6
  import { GameObject } from "./Component.js";
9
7
  import { PlayableDirector } from "./timeline/PlayableDirector.js";
8
+ import { Object3D } from "three";
10
9
 
11
10
 
12
11
  const $objectAnimationKey = Symbol("objectIsAnimatedData");
src/engine-components/export/usdz/utils/animationutils.ts CHANGED
@@ -1,10 +1,9 @@
1
- import { AnimationClip,Object3D } from "three";
2
-
3
- import { getParam } from "../../../../engine/engine_utils.js";
1
+ import { Animator } from "../../../Animator.js";
4
2
  import { Animation } from "../../../Animation.js";
5
- import { Animator } from "../../../Animator.js";
3
+ import { Object3D, AnimationClip } from "three";
4
+ import { AnimationExtension } from "../extensions/Animation.js";
6
5
  import { Behaviour, GameObject } from "../../../Component.js";
7
- import { AnimationExtension } from "../extensions/Animation.js";
6
+ import { getParam } from "../../../../engine/engine_utils.js";
8
7
  import { PlayAnimationOnClick } from "../extensions/behavior/BehaviourComponents.js";
9
8
 
10
9
  const debug = getParam("debugusdz");
src/engine-components/Animator.ts CHANGED
@@ -1,12 +1,11 @@
1
- import type { AnimationAction, AnimationActionLoopStyles, AnimationMixer } from "three";
2
-
3
- import { Mathf } from "../engine/engine_math.js";
4
- import { serializable } from "../engine/engine_serialization_decorator.js";
1
+ import { Behaviour } from "./Component.js";
2
+ import type { AnimationActionLoopStyles, AnimationAction, AnimationMixer } from "three";
5
3
  import { getParam } from "../engine/engine_utils.js";
6
4
  import type { AnimatorControllerModel } from "../engine/extensions/NEEDLE_animator_controller_model.js";
5
+ import { AnimatorController } from "./AnimatorController.js";
6
+ import { serializable } from "../engine/engine_serialization_decorator.js";
7
+ import { Mathf } from "../engine/engine_math.js";
7
8
  import { getObjectAnimated } from "./AnimationUtils.js";
8
- import { AnimatorController } from "./AnimatorController.js";
9
- import { Behaviour } from "./Component.js";
10
9
 
11
10
  const debug = getParam("debuganimator");
12
11
 
src/engine-components/AnimatorController.ts CHANGED
@@ -1,16 +1,15 @@
1
+ import { Animator } from "./Animator.js";
2
+ import type { AnimatorControllerModel, Condition, State, Transition } from "../engine/extensions/NEEDLE_animator_controller_model.js";
3
+ import { AnimatorConditionMode, AnimatorControllerParameterType, AnimatorStateInfo, createMotion, StateMachineBehaviour } from "../engine/extensions/NEEDLE_animator_controller_model.js";
1
4
  import { AnimationAction, AnimationClip, AnimationMixer, AxesHelper, Euler, KeyframeTrack, LoopOnce, Object3D, Quaternion, Vector3 } from "three";
2
-
5
+ import { deepClone, getParam } from "../engine/engine_utils.js";
6
+ import { Context } from "../engine/engine_setup.js";
7
+ import { TypeStore } from "../engine/engine_typestore.js";
8
+ import { SerializationContext, TypeSerializer, assign } from "../engine/engine_serialization_core.js";
9
+ import { Mathf } from "../engine/engine_math.js";
10
+ import { isAnimationAction } from "../engine/engine_three_utils.js";
3
11
  import { isDevEnvironment } from "../engine/debug/index.js";
4
- import { Mathf } from "../engine/engine_math.js";
5
12
  import { InstantiateIdProvider } from "../engine/engine_networking_instantiate.js";
6
- import { assign,SerializationContext, TypeSerializer } from "../engine/engine_serialization_core.js";
7
- import { Context } from "../engine/engine_setup.js";
8
- import { isAnimationAction } from "../engine/engine_three_utils.js";
9
- import { TypeStore } from "../engine/engine_typestore.js";
10
- import { deepClone, getParam } from "../engine/engine_utils.js";
11
- import type { AnimatorControllerModel, Condition, State, Transition } from "../engine/extensions/NEEDLE_animator_controller_model.js";
12
- import { AnimatorConditionMode, AnimatorControllerParameterType, AnimatorStateInfo, createMotion, StateMachineBehaviour } from "../engine/extensions/NEEDLE_animator_controller_model.js";
13
- import { Animator } from "./Animator.js";
14
13
 
15
14
  const debug = getParam("debuganimatorcontroller");
16
15
  const debugRootMotion = getParam("debugrootmotion");
src/engine-components/postprocessing/Effects/Antialiasing.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { EdgeDetectionMode, SMAAEffect, SMAAPreset } from "postprocessing";
2
-
3
2
  import { serializable } from "../../../engine/engine_serialization.js";
4
3
  import { type EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect.js";
5
4
  import { VolumeParameter } from "../VolumeParameter.js";
src/engine-components/api.ts CHANGED
@@ -1,18 +1,20 @@
1
+ export { Behaviour, Component, GameObject } from "./Component.js"
1
2
  export * from "./codegen/components.js";
2
- export { Behaviour, Component, GameObject } from "./Component.js"
3
3
 
4
4
  // We dont want to export everything in the extensions
5
- export { ClearFlags } from "./Camera.js"
5
+ export * from "./js-extensions/RGBAColor.js";
6
+ export * from "./js-extensions/Object3D.js";
7
+ export * from "./XRFlag.js"
8
+
6
9
  export * from "./export/index.js"
7
- export * from "./js-extensions/Object3D.js";
8
- export * from "./js-extensions/RGBAColor.js";
9
10
  export * from "./postprocessing/index.js"
10
- export { type ISceneEventListener } from "./SceneSwitcher.js";
11
11
  export * from "./timeline/index.js"
12
12
  export * from "./ui/index.js"
13
13
  export * from "./webxr/index.js"
14
- export * from "./webxr/XRFlag.js"
15
14
 
15
+ export { ClearFlags } from "./Camera.js"
16
+ export { type ISceneEventListener } from "./SceneSwitcher.js";
17
+
16
18
  import "./CameraUtils.js"
17
19
  import "./AnimationUtils.js"
18
20
 
src/engine/api.ts CHANGED
@@ -1,42 +1,42 @@
1
1
 
2
- export * from "./debug/index.js";
2
+ export * from "./extensions/index.js";
3
3
  export * from "./engine_addressables.js";
4
4
  export * from "./engine_application.js";
5
5
  export * from "./engine_assetdatabase.js";
6
+ export * from "./engine_create_objects.js";
7
+ export * from "./engine_components_internal.js";
6
8
  export * from "./engine_components.js";
7
9
  export * from "./engine_components_internal.js";
8
- export * from "./engine_components_internal.js";
9
- export * from "./engine_constants.js";
10
+ export * from "./engine_context_registry.js";
10
11
  export * from "./engine_context.js";
11
- export * from "./engine_context_registry.js";
12
12
  export * from "./engine_coroutine.js"
13
- export * from "./engine_create_objects.js";
13
+ export * from "./engine_constants.js";
14
+ export * from "./debug/index.js";
14
15
  export * from "./engine_element.js";
16
+ export * from "./engine_element_loading.js";
15
17
  export * from "./engine_element_attributes.js";
16
- export * from "./engine_element_loading.js";
17
- export * from "./engine_gameobject.js";
18
18
  export { Gizmos } from "./engine_gizmos.js"
19
19
  export * from "./engine_gltf.js";
20
20
  export * from "./engine_hot_reload.js";
21
- export * from "./engine_input.js";
22
- export { InstancingUtil } from "./engine_instancing.js";
23
- export { hasIndieLicense,hasProLicense } from "./engine_license.js";
24
- export * from "./engine_lifecycle_api.js";
25
- export * from "./engine_math.js";
21
+ export * from "./engine_gameobject.js";
26
22
  export * from "./engine_networking.js";
23
+ export * from "./engine_networking_types.js";
27
24
  export { syncField } from "./engine_networking_auto.js";
28
25
  export * from "./engine_networking_files.js";
29
26
  export * from "./engine_networking_instantiate.js";
30
- export * from "./engine_networking_peer.js";
31
27
  export * from "./engine_networking_streams.js";
32
- export * from "./engine_networking_types.js";
33
28
  export * from "./engine_networking_utils.js";
29
+ export * from "./engine_networking_peer.js";
34
30
  export * from "./engine_patcher.js";
31
+ export * from "./engine_playerview.js";
35
32
  export * from "./engine_physics.js";
36
33
  export * from "./engine_physics.types.js";
37
34
  export * from "./engine_physics_rapier.js";
38
- export * from "./engine_playerview.js";
39
35
  export * from "./engine_scenelighting.js";
36
+ export * from "./engine_input.js";
37
+ export * from "./engine_lifecycle_api.js";
38
+ export * from "./engine_math.js";
39
+ export * from "./js-extensions/index.js";
40
40
  export * from "./engine_scenetools.js";
41
41
  export * from "./engine_serialization.js";
42
42
  export { type ISerializable } from "./engine_serialization_core.js";
@@ -44,11 +44,12 @@
44
44
  export * from "./engine_three_utils.js";
45
45
  export * from "./engine_time.js";
46
46
  export * from "./engine_types.js";
47
- export { registerType,TypeStore } from "./engine_typestore.js";
48
- export { prefix,validate } from "./engine_util_decorator.js";
49
- export * from "./engine_utils.js";
50
47
  export * from "./engine_utils_screenshot.js";
51
48
  export * from "./engine_web_api.js";
52
- export * from "./engine_xr.js";
53
- export * from "./extensions/index.js";
54
- export * from "./js-extensions/index.js";
49
+ export * from "./engine_utils.js";
50
+
51
+ export { TypeStore, registerType } from "./engine_typestore.js";
52
+
53
+ export { InstancingUtil } from "./engine_instancing.js";
54
+ export { validate, prefix } from "./engine_util_decorator.js";
55
+ export { hasProLicense, hasIndieLicense } from "./engine_license.js";
src/engine-components/export/usdz/extensions/behavior/AudioExtension.ts CHANGED
@@ -1,9 +1,8 @@
1
- import { Object3D } from "three";
2
-
3
- import { AudioSource } from "../../../../AudioSource.js";
4
1
  import { GameObject } from "../../../../Component.js";
5
2
  import type { IUSDExporterExtension } from "../../Extension.js";
6
3
  import { USDObject, USDWriter, USDZExporterContext } from "../../ThreeUSDZExporter.js";
4
+ import { Object3D } from "three";
5
+ import { AudioSource } from "../../../../AudioSource.js";
7
6
 
8
7
  export class AudioExtension implements IUSDExporterExtension {
9
8
 
src/engine-components/AudioListener.ts CHANGED
@@ -1,8 +1,7 @@
1
+ import { Behaviour, GameObject } from "./Component.js";
1
2
  import { AudioListener as ThreeAudioListener } from "three";
2
-
3
3
  import { AudioSource } from "./AudioSource.js";
4
4
  import { Camera } from "./Camera.js";
5
- import { Behaviour, GameObject } from "./Component.js";
6
5
 
7
6
 
8
7
  export class AudioListener extends Behaviour {
src/engine-components/AudioSource.ts CHANGED
@@ -1,12 +1,11 @@
1
+ import { Behaviour, GameObject } from "./Component.js";
2
+ import { PositionalAudioHelper } from 'three/examples/jsm/helpers/PositionalAudioHelper.js';
3
+ import { AudioListener } from "./AudioListener.js";
4
+ import * as utils from "../engine/engine_utils.js";
5
+ import { serializable } from "../engine/engine_serialization_decorator.js";
6
+ import { ApplicationEvents } from "../engine/engine_application.js";
1
7
  import { Audio, AudioContext, AudioLoader, PositionalAudio } from "three";
2
- import { PositionalAudioHelper } from 'three/examples/jsm/helpers/PositionalAudioHelper.js';
3
-
4
8
  import { isDevEnvironment } from "../engine/debug/index.js";
5
- import { ApplicationEvents } from "../engine/engine_application.js";
6
- import { serializable } from "../engine/engine_serialization_decorator.js";
7
- import * as utils from "../engine/engine_utils.js";
8
- import { AudioListener } from "./AudioListener.js";
9
- import { Behaviour, GameObject } from "./Component.js";
10
9
 
11
10
 
12
11
  const debug = utils.getParam("debugaudio");
@@ -141,7 +140,7 @@
141
140
  if (!listener && this.context.mainCamera) listener = GameObject.addNewComponent(this.context.mainCamera, AudioListener);
142
141
  if (listener?.listener) {
143
142
  this.sound = new PositionalAudio(listener.listener);
144
- this.gameObject?.add(this.sound);
143
+ this.gameObject.add(this.sound);
145
144
  }
146
145
  else if (debug) console.warn("No audio listener found in scene - can not play audio");
147
146
  }
@@ -158,9 +157,6 @@
158
157
  }
159
158
 
160
159
  onEnable(): void {
161
- if (this.sound)
162
- this.gameObject.add(this.sound);
163
-
164
160
  if (!AudioSource.userInteractionRegistered) {
165
161
  AudioSource.registerWaitForAllowAudio(() => {
166
162
  if (this.enabled && !this.destroyed && this.shouldPlay)
@@ -332,7 +328,6 @@
332
328
  if (this.sound && !this.sound.isPlaying) {
333
329
  const muted = this.context.application.muted;
334
330
  if (muted) this.sound.setVolume(0);
335
- this.gameObject?.add(this.sound);
336
331
 
337
332
  if (this.clip instanceof MediaStream) {
338
333
 
@@ -416,7 +411,7 @@
416
411
  this._hasEnded = true;
417
412
  if (debug)
418
413
  console.log("Audio clip ended", this.clip);
419
- this.dispatchEvent(new CustomEvent("ended", { detail: this }));
414
+ this.sound.dispatchEvent({ type: 'ended', target: this });
420
415
  }
421
416
 
422
417
  // this.gameObject.position.x = Math.sin(time.time) * 2;
src/engine-components/avatar/Avatar_Brain_LookAt.ts CHANGED
@@ -1,12 +1,11 @@
1
1
  import * as THREE from "three";
2
-
3
- import { OwnershipModel } from "../../engine/engine_networking.js";
4
- import type { IModel } from "../../engine/engine_networking_types.js";
5
- import { Context } from "../../engine/engine_setup.js";
6
- import * as utils from "../../engine/engine_three_utils.js";
7
2
  import { TypeStore } from "../../engine/engine_typestore.js";
8
3
  import { Behaviour, GameObject } from "../Component.js";
9
4
  import { AvatarMarker } from "../webxr/WebXRAvatar.js";
5
+ import * as utils from "../../engine/engine_three_utils.js";
6
+ import { OwnershipModel } from "../../engine/engine_networking.js";
7
+ import { Context } from "../../engine/engine_setup.js";
8
+ import type { IModel } from "../../engine/engine_networking_types.js";
10
9
 
11
10
  export class Avatar_POI {
12
11
 
src/engine-components/avatar/Avatar_MouthShapes.ts CHANGED
@@ -1,10 +1,9 @@
1
- import { Object3D } from "three";
2
-
3
- import { serializable } from "../../engine/engine_serialization_decorator.js";
4
- import * as utils from "../../engine/engine_utils.js";
5
1
  import { Behaviour, GameObject } from "../Component.js";
6
2
  import { Voip } from "../Voip.js";
7
3
  import { AvatarMarker } from "../webxr/WebXRAvatar.js";
4
+ import * as utils from "../../engine/engine_utils.js";
5
+ import { Object3D } from "three";
6
+ import { serializable } from "../../engine/engine_serialization_decorator.js";
8
7
 
9
8
  const debug = utils.getParam("debugmouth");
10
9
 
src/engine-components/webxr/Avatar.ts DELETED
@@ -1,221 +0,0 @@
1
- import { Object3D, Quaternion, Vector3 } from "three";
2
-
3
- import { AssetReference } from "../../engine/engine_addressables.js";
4
- import { ObjectUtils, PrimitiveType } from "../../engine/engine_create_objects.js";
5
- import { serializable } from "../../engine/engine_serialization_decorator.js";
6
- import { IGameObject } from "../../engine/engine_types.js";
7
- import { getParam,PromiseAllWithErrors } from "../../engine/engine_utils.js";
8
- import { NeedleXREventArgs, NeedleXRSession, NeedleXRUtils } from "../../engine/xr/index.js";
9
- import { PlayerState } from "../../engine-components-experimental/networking/PlayerSync.js";
10
- import { Behaviour, GameObject } from "../Component.js";
11
- import { SyncedTransform } from "../SyncedTransform.js";
12
- import { AvatarMarker } from "./WebXRAvatar.js";
13
- import { XRFlag } from "./XRFlag.js";
14
-
15
- const debug = getParam("debugwebxr");
16
-
17
- const flipForwardQuaternion = new Quaternion().setFromAxisAngle(new Vector3(0, 1, 0), Math.PI);
18
-
19
- export class Avatar extends Behaviour {
20
-
21
- @serializable(AssetReference)
22
- head?: AssetReference;
23
-
24
- @serializable(AssetReference)
25
- leftHand?: AssetReference;
26
-
27
- @serializable(AssetReference)
28
- rightHand?: AssetReference;
29
-
30
- private _syncTransforms?: SyncedTransform[];
31
-
32
- async onEnterXR(_args: NeedleXREventArgs) {
33
- if (!this.activeAndEnabled) return;
34
- if (debug) console.warn("AVATAR ENTER XR", this.guid, this.sourceId, this, this.activeAndEnabled)
35
- if (this._syncTransforms)
36
- this._syncTransforms.length = 0;
37
- await this.prepareAvatar();
38
-
39
- const playerstate = PlayerState.getFor(this);
40
- if (playerstate?.owner) {
41
- const marker = this.gameObject.addNewComponent(AvatarMarker)!;
42
- marker.avatar = this.gameObject;
43
- marker.connectionId = playerstate.owner;
44
- }
45
- else if(this.context.connection.isConnected) console.error("No player state found for avatar", this);
46
- }
47
-
48
- onLeaveXR(_args: NeedleXREventArgs): void {
49
- const marker = this.gameObject.getComponent(AvatarMarker);
50
- if (marker) {
51
- marker.destroy();
52
- }
53
- }
54
-
55
- onUpdateXR(args: NeedleXREventArgs): void {
56
- if (!this.activeAndEnabled) return;
57
-
58
- const isLocalPlayer = PlayerState.isLocalPlayer(this);
59
- if (!isLocalPlayer) return;
60
-
61
- const xr = args.xr;
62
- // make sure the avatar is inside the active rig
63
- if (xr.rig && xr.rig.gameObject !== this.gameObject.parent) {
64
- this.gameObject.position.set(0, 0, 0);
65
- this.gameObject.rotation.set(0, 0, 0);
66
- this.gameObject.scale.set(1, 1, 1);
67
- xr.rig.gameObject.add(this.gameObject);
68
- }
69
- // this.gameObject.position.copy(xr.rig!.gameObject.position);
70
- // this.gameObject.quaternion.copy(xr.rig!.gameObject.quaternion);
71
- // this.gameObject.scale.set(1, 1, 1);
72
-
73
-
74
- if (this._syncTransforms && isLocalPlayer) {
75
- for (const sync of this._syncTransforms) {
76
- sync.fastMode = true;
77
- if (!sync.isOwned())
78
- sync.requestOwnership();
79
- }
80
- }
81
-
82
-
83
- // synchronize head
84
- if (this.head && this.context.mainCamera) {
85
- const headObj = this.head.asset as IGameObject;
86
- headObj.position.copy(this.context.mainCamera.position);
87
- headObj.quaternion.copy(this.context.mainCamera.quaternion);
88
- headObj.quaternion.x *= -1;
89
-
90
- // HACK: XRFlag limitation workaround to make sure first person user head is never rendered
91
- if (this.context.time.frameCount % 10 === 0) {
92
- const xrflags = GameObject.getComponentsInChildren(this.head.asset, XRFlag);
93
- for (const flag of xrflags) {
94
- flag.enabled = false;
95
- flag.gameObject.visible = false;
96
- }
97
- }
98
- }
99
-
100
- // synchronize hands
101
- const leftCtrl = args.xr.leftController;
102
- const leftObj = this.leftHand?.asset as Object3D;
103
- if (leftCtrl && leftObj) {
104
- leftObj.position.copy(leftCtrl.gripPosition);
105
- leftObj.quaternion.copy(leftCtrl.gripQuaternion);
106
- leftObj.quaternion.multiply(flipForwardQuaternion);
107
- leftObj.visible = leftCtrl.isTracking;
108
- }
109
-
110
- const right = args.xr.rightController;
111
- if (right && this.rightHand?.asset) {
112
- const rightObj = this.rightHand.asset as Object3D;
113
- rightObj.position.copy(right.gripPosition);
114
- rightObj.quaternion.copy(right.gripQuaternion);
115
- rightObj.quaternion.multiply(flipForwardQuaternion);
116
- rightObj.visible = right.isTracking;
117
- }
118
- }
119
-
120
- onBeforeRender(): void {
121
- if (this.context.time.frame % 10 === 0)
122
- this.updateRemoteAvatarVisibility();
123
- }
124
-
125
-
126
- private updateRemoteAvatarVisibility() {
127
- if (this.context.connection.isConnected) {
128
- const state = PlayerState.getFor(this);
129
- if (state && state.isLocalPlayer == false) {
130
-
131
- const sync = NeedleXRSession.getXRSync(this.context);
132
- if (sync) {
133
- if (sync.hasState(state.owner)) {
134
- this.tryFindAvatarObjectsIfMissing();
135
-
136
- const leftObj = this.leftHand?.asset as Object3D;
137
- if (leftObj) {
138
- leftObj.visible = sync?.isTracking(state.owner, "left") ?? false;
139
- }
140
- const rightObj = this.rightHand?.asset as Object3D;
141
- if (rightObj) {
142
- rightObj.visible = sync?.isTracking(state.owner, "right") ?? false;
143
- }
144
- }
145
- }
146
-
147
- // HACK: XRFlag limitation workaround to make sure first person user head of OTHER users is ALWAYS rendered
148
- if (this.head?.asset) {
149
- const xrflags = GameObject.getComponentsInChildren(this.head.asset, XRFlag);
150
- for (const flag of xrflags) {
151
- flag.enabled = false;
152
- flag.gameObject.visible = true;
153
- }
154
- }
155
- }
156
- }
157
- }
158
-
159
-
160
-
161
- private tryFindAvatarObjectsIfMissing() {
162
- // if no avatar objects are set, try to find them
163
- if (!this.head || !this.leftHand || !this.rightHand) {
164
- const res = { head: this.head, leftHand: this.leftHand, rightHand: this.rightHand };
165
- NeedleXRUtils.tryFindAvatarObjects(this.gameObject, this.sourceId || "", res);
166
- if (res.head) this.head = res.head;
167
- if (res.leftHand) this.leftHand = res.leftHand;
168
- if (res.rightHand) this.rightHand = res.rightHand;
169
- }
170
- }
171
-
172
- private async prepareAvatar() {
173
- // if no avatar objects are set, try to find them
174
- this.tryFindAvatarObjectsIfMissing();
175
-
176
- if (!this.head) {
177
- const head = new Object3D();
178
- head.name = "Head";
179
- const cube = ObjectUtils.createPrimitive(PrimitiveType.Cube);
180
- head.add(cube);
181
- this.gameObject.add(head);
182
- this.head = new AssetReference("", this.sourceId, head);
183
- if (debug) console.log("Create head", head);
184
- }
185
-
186
- if (!this.rightHand) {
187
- const rightHand = new Object3D();
188
- rightHand.name = "Right Hand";
189
- this.gameObject.add(rightHand);
190
- this.rightHand = new AssetReference("", this.sourceId, rightHand);
191
- if (debug) console.log("Create right hand", rightHand);
192
- }
193
-
194
- if (!this.leftHand) {
195
- const leftHand = new Object3D();
196
- leftHand.name = "Left Hand";
197
- this.gameObject.add(leftHand);
198
- this.leftHand = new AssetReference("", this.sourceId, leftHand);
199
- if (debug) console.log("Create left hand", leftHand);
200
- }
201
-
202
- await this.loadAvatarObjects(this.head, this.leftHand, this.rightHand);
203
-
204
- if (PlayerState.isLocalPlayer(this.gameObject)) {
205
- this._syncTransforms = GameObject.getComponentsInChildren(this.gameObject, SyncedTransform);
206
- }
207
- }
208
-
209
-
210
- private async loadAvatarObjects(head: AssetReference, left: AssetReference, right: AssetReference) {
211
- const pHead = head.loadAssetAsync();
212
- const pHandLeft = left.loadAssetAsync();
213
- const pHandRight = right.loadAssetAsync();
214
- const promises = new Array<Promise<any>>();
215
- if (pHead) promises.push(pHead);
216
- if (pHandLeft) promises.push(pHandLeft);
217
- if (pHandRight) promises.push(pHandRight);
218
- const res = await PromiseAllWithErrors(promises);
219
- if (debug) console.log("Avatar loaded results:", res);
220
- }
221
- }
src/engine-components/avatar/AvatarBlink_Simple.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import { Object3D } from "three";
2
-
2
+ import { Behaviour, GameObject } from "../Component.js";
3
+ import { XRFlag, XRState } from "../XRFlag.js";
3
4
  import { serializable } from "../../engine/engine_serialization_decorator.js";
4
- import { Behaviour, GameObject } from "../Component.js";
5
- import { XRFlag, XRState } from "../webxr/XRFlag.js";
6
5
 
7
6
 
8
7
  export class AvatarBlink_Simple extends Behaviour {
src/engine-components/avatar/AvatarEyeLook_Rotation.ts CHANGED
@@ -1,11 +1,10 @@
1
+ import { Behaviour, GameObject } from "../Component.js";
2
+ import * as utils from "../../engine/engine_three_utils.js"
1
3
  import * as THREE from "three";
4
+ import { Avatar_Brain_LookAt } from "./Avatar_Brain_LookAt.js";
5
+ import { serializable } from "../../engine/engine_serialization_decorator.js";
2
6
  import { Object3D } from "three";
3
7
 
4
- import { serializable } from "../../engine/engine_serialization_decorator.js";
5
- import * as utils from "../../engine/engine_three_utils.js"
6
- import { Behaviour, GameObject } from "../Component.js";
7
- import { Avatar_Brain_LookAt } from "./Avatar_Brain_LookAt.js";
8
-
9
8
  export class AvatarEyeLook_Rotation extends Behaviour {
10
9
 
11
10
  @serializable(Object3D)
src/engine-components/AvatarLoader.ts CHANGED
@@ -1,13 +1,12 @@
1
- import { Box3, Object3D, Vector3 } from "three";
2
1
  import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
3
-
4
- import { InstantiateOptions } from "../engine/engine_gameobject.js";
5
- import { getLoader } from "../engine/engine_gltf.js";
2
+ import * as utils from "../engine/engine_utils.js"
6
3
  import * as loaders from "../engine/engine_loaders.js"
7
4
  import { Context } from "../engine/engine_setup.js";
8
- import * as utils from "../engine/engine_utils.js"
5
+ import { GameObject } from "./Component.js";
9
6
  import { download_file } from "../engine/engine_web_api.js";
10
- import { GameObject } from "./Component.js";
7
+ import { getLoader } from "../engine/engine_gltf.js";
8
+ import { InstantiateOptions } from "../engine/engine_gameobject.js";
9
+ import { Box3, Object3D, Vector3 } from "three";
11
10
 
12
11
  const debug = utils.getParam("debugavatar");
13
12
 
src/engine-components/AxesHelper.ts CHANGED
@@ -1,8 +1,7 @@
1
- import { AxesHelper as _AxesHelper } from "three";
2
-
1
+ import { Behaviour } from "./Component.js";
3
2
  import * as params from "../engine/engine_default_parameters.js";
4
3
  import { serializable } from "../engine/engine_serialization_decorator.js";
5
- import { Behaviour } from "./Component.js";
4
+ import { AxesHelper as _AxesHelper } from "three";
6
5
 
7
6
  export class AxesHelper extends Behaviour {
8
7
  @serializable()
src/engine-components/ui/BaseUIComponent.ts CHANGED
@@ -1,12 +1,11 @@
1
1
  // import { Canvas } from './Canvas.js';
2
- import { AxesHelper, Object3D } from 'three';
3
2
  import * as ThreeMeshUI from 'three-mesh-ui';
4
-
5
- import { showGizmos } from '../../engine/engine_default_parameters.js';
6
- import { getParam } from '../../engine/engine_utils.js';
7
3
  import { Behaviour, GameObject } from "../Component.js";
8
4
  import { EventSystem } from "./EventSystem.js";
5
+ import { showGizmos } from '../../engine/engine_default_parameters.js';
6
+ import { AxesHelper, Object3D } from 'three';
9
7
  import type { ICanvas } from './Interfaces.js';
8
+ import { getParam } from '../../engine/engine_utils.js';
10
9
  export const includesDir = "./include";
11
10
 
12
11
  const debug = getParam("debugshadowcomponents");
@@ -25,38 +24,22 @@
25
24
 
26
25
  export const $shadowDomOwner = Symbol("shadowDomOwner");
27
26
 
28
- /** Derive from this class if you want to implement your own UI components
29
- * It provides utility methods and simplifies managing the underlying three-mesh-ui hierarchy
30
- */
31
27
  export class BaseUIComponent extends Behaviour {
32
28
 
33
- /** Is this object on the root of the UI hierarchy ? */
34
29
  isRoot() { return this.Root?.gameObject === this.gameObject; }
35
30
 
36
- /** Access the parent canvas component */
37
31
  get canvas() {
38
32
  const cv = this.Root as any as ICanvas;
39
33
  if (cv?.isCanvas) return cv;
40
34
  return null;
41
35
  }
42
- /** @deprecated use `canvas` */
43
- protected get Canvas() {
44
- return this.canvas;
45
- }
46
36
 
47
- /** Mark the UI dirty which will trigger an THREE-Mesh-UI update */
48
37
  markDirty() {
49
38
  EventSystem.markUIDirty(this.context);
50
39
  }
51
40
 
52
- /** the underlying three-mesh-ui */
53
- get shadowComponent() { return this._shadowComponent }
54
- private set shadowComponent(val: Object3D | null) {
55
- this._shadowComponent = val;
56
- }
41
+ shadowComponent: ThreeMeshUI.Block | null = null;
57
42
 
58
- private _shadowComponent: Object3D | null = null;
59
-
60
43
  private _controlsChildLayout = true;
61
44
  get controlsChildLayout(): boolean { return this._controlsChildLayout; }
62
45
  set controlsChildLayout(val: boolean) {
@@ -75,6 +58,11 @@
75
58
  return this._root;
76
59
  }
77
60
 
61
+ // TODO: rename to canvas
62
+ protected get Canvas() {
63
+ return this.canvas;
64
+ }
65
+
78
66
  // private _intermediate?: Object3D;
79
67
  protected _parentComponent?: BaseUIComponent | null = undefined;
80
68
 
@@ -89,10 +77,7 @@
89
77
  super.onEnable();
90
78
  }
91
79
 
92
- /** Add a three-mesh-ui object to the UI hierarchy
93
- * @param container the three-mesh-ui object to add
94
- * @param parent the parent component to add the object to
95
- */
80
+ //@ts-ignore
96
81
  protected addShadowComponent(container: any, parent?: BaseUIComponent) {
97
82
 
98
83
  this.removeShadowComponent();
@@ -149,7 +134,21 @@
149
134
  if(debug) console.log(this.shadowComponent)
150
135
  }
151
136
 
152
- protected setShadowComponentOwner(current: ThreeMeshUI.MeshUIBaseElement | Object3D | null | undefined) {
137
+
138
+ set(_state: object) {
139
+ // if (!this.shadowComponent) return;
140
+ // this.traverseOwnedShadowComponents(this.shadowComponent, this, o => {
141
+ // for (const ch of o.children) {
142
+ // console.log(this, ch);
143
+ // if (ch.isUI && typeof ch.set === "function") {
144
+ // // ch.set(state);
145
+ // // ch.update(true, true, true);
146
+ // }
147
+ // }
148
+ // })
149
+ }
150
+
151
+ protected setShadowComponentOwner(current: Object3D | null | undefined) {
153
152
  if (!current) return;
154
153
  // TODO: only traverse our own hierarchy, we can stop if we find another owner
155
154
  if (current[$shadowDomOwner] === undefined || current[$shadowDomOwner] === this) {
@@ -172,7 +171,6 @@
172
171
  }
173
172
  }
174
173
 
175
- /** Remove the underlying UI object from the hierarchy */
176
174
  protected removeShadowComponent() {
177
175
  if (this.shadowComponent) {
178
176
  this.shadowComponent.removeFromParent();
src/engine-components/BasicIKConstraint.ts CHANGED
@@ -1,8 +1,7 @@
1
+ import { Behaviour, GameObject } from "./Component.js";
2
+ import * as utils from "./../engine/engine_three_utils.js";
1
3
  import { Vector3 } from "three";
2
4
 
3
- import * as utils from "./../engine/engine_three_utils.js";
4
- import { Behaviour, GameObject } from "./Component.js";
5
-
6
5
  export class BasicIKConstraint extends Behaviour {
7
6
 
8
7
  private from!: GameObject;
src/engine-components/export/usdz/extensions/behavior/Behaviour.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { getParam } from "../../../../../engine/engine_utils.js";
2
1
  import { GameObject } from "../../../../Component.js";
3
2
  import type { IUSDExporterExtension } from "../../Extension.js";
4
3
  import { USDObject, USDWriter, USDZExporterContext } from "../../ThreeUSDZExporter.js";
5
4
  import { BehaviorModel } from "./BehavioursBuilder.js";
5
+ import { getParam } from "../../../../../engine/engine_utils.js";
6
6
 
7
7
  const debug = getParam("debugusdz");
8
8
 
src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts CHANGED
@@ -1,20 +1,21 @@
1
- import { Group,Material, Mesh, Object3D, Quaternion, Vector3 } from "three";
2
-
3
- import { isDevEnvironment, showBalloonWarning } from "../../../../../engine/debug/index.js";
4
- import { serializable } from "../../../../../engine/engine_serialization_decorator.js";
5
- import { getWorldPosition, getWorldQuaternion, getWorldScale, setWorldPosition, setWorldQuaternion, setWorldScale } from "../../../../../engine/engine_three_utils.js";
6
- import type { State } from "../../../../../engine/extensions/NEEDLE_animator_controller_model.js";
7
- import { NEEDLE_progressive } from "../../../../../engine/extensions/NEEDLE_progressive.js";
1
+ import { Behaviour, GameObject } from "../../../../Component.js";
8
2
  import { Animator } from "../../../../Animator.js";
9
- import { AudioSource } from "../../../../AudioSource.js";
10
- import { Behaviour, GameObject } from "../../../../Component.js";
11
3
  import { Renderer } from "../../../../Renderer.js";
4
+ import { serializable } from "../../../../../engine/engine_serialization_decorator.js";
12
5
  import type { IPointerClickHandler, PointerEventData } from "../../../../ui/PointerEvents.js";
13
- import { ObjectRaycaster,Raycaster } from "../../../../ui/Raycaster.js";
6
+ import { AnimationExtension, RegisteredAnimationInfo, type UsdzAnimation } from "../Animation.js";
7
+ import { getWorldPosition, getWorldQuaternion, getWorldScale, setWorldPosition, setWorldQuaternion, setWorldScale } from "../../../../../engine/engine_three_utils.js";
8
+
9
+ import { Object3D, Material, Vector3, Quaternion, Mesh, Group } from "three";
14
10
  import { USDDocument, USDObject, USDZExporterContext } from "../../ThreeUSDZExporter.js";
15
- import { AnimationExtension, RegisteredAnimationInfo, type UsdzAnimation } from "../Animation.js";
11
+
16
12
  import type { BehaviorExtension, UsdzBehaviour } from "./Behaviour.js";
17
- import { ActionBuilder, ActionModel, AuralMode, BehaviorModel, GroupActionModel, type IBehaviorElement, MotionType, MultiplePerformOperation,PlayAction, Space, TriggerBuilder } from "./BehavioursBuilder.js";
13
+ import { ActionBuilder, ActionModel, AuralMode, BehaviorModel, type IBehaviorElement, MotionType, PlayAction, Space, TriggerBuilder, GroupActionModel, MultiplePerformOperation } from "./BehavioursBuilder.js";
14
+ import { AudioSource } from "../../../../AudioSource.js";
15
+ import { NEEDLE_progressive } from "../../../../../engine/extensions/NEEDLE_progressive.js";
16
+ import { isDevEnvironment, showBalloonWarning } from "../../../../../engine/debug/index.js";
17
+ import { Raycaster, ObjectRaycaster } from "../../../../ui/Raycaster.js";
18
+ import type { State } from "../../../../../engine/extensions/NEEDLE_animator_controller_model.js";
18
19
 
19
20
  function ensureRaycaster(obj: GameObject) {
20
21
  if (!obj) return;
src/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Object3D } from "three";
2
+ import { USDDocument, USDObject, USDWriter, makeNameSafeForUSD } from "../../ThreeUSDZExporter.js";
2
3
 
4
+ import { BehaviorExtension } from "./Behaviour.js";
3
5
  import { getParam } from "../../../../../engine/engine_utils.js";
4
- import { makeNameSafeForUSD,USDDocument, USDObject, USDWriter } from "../../ThreeUSDZExporter.js";
5
- import { BehaviorExtension } from "./Behaviour.js";
6
6
 
7
7
  const debug = getParam("debugusdz");
8
8
 
src/engine-components/postprocessing/Effects/Bloom.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { BlendFunction, BloomEffect, SelectiveBloomEffect } from "postprocessing";
2
-
3
2
  import { serializable } from "../../../engine/engine_serialization.js";
4
3
  import { PostProcessingEffect } from "../PostProcessingEffect.js";
5
4
  import { VolumeParameter } from "../VolumeParameter.js";
src/engine-components/BoxHelperComponent.ts CHANGED
@@ -1,9 +1,8 @@
1
- import { Box3, Color, type ColorRepresentation, LineSegments, Object3D, Vector3 } from "three";
2
-
1
+ import { Behaviour } from "./Component.js";
2
+ import { getParam } from "../engine/engine_utils.js";
3
3
  import { CreateWireCube, Gizmos } from "../engine/engine_gizmos.js";
4
4
  import { getWorldPosition, getWorldScale } from "../engine/engine_three_utils.js";
5
- import { getParam } from "../engine/engine_utils.js";
6
- import { Behaviour } from "./Component.js";
5
+ import { Box3, Color, type ColorRepresentation, LineSegments, Object3D, Vector3 } from "three";
7
6
 
8
7
  const gizmos = getParam("gizmos");
9
8
  const debug = getParam("debugboxhelper");
src/engine-components/ui/Button.ts CHANGED
@@ -1,15 +1,15 @@
1
- import { showBalloonMessage } from "../../engine/debug/index.js";
2
- import { Gizmos } from "../../engine/engine_gizmos.js";
3
- import { PointerType } from "../../engine/engine_input.js";
4
- import { serializable } from "../../engine/engine_serialization_decorator.js";
5
- import { getParam } from "../../engine/engine_utils.js";
6
- import { Animator } from "../Animator.js";
7
1
  import { Behaviour, GameObject } from "../Component.js";
8
2
  import { EventList } from "../EventList.js";
3
+ import type { IPointerClickHandler, IPointerEnterHandler, IPointerEventHandler, IPointerExitHandler, PointerEventData } from "./PointerEvents.js";
4
+ import { Image } from "./Image.js";
9
5
  import { RGBAColor } from "../js-extensions/RGBAColor.js";
10
- import { Image } from "./Image.js";
11
- import type { IPointerClickHandler, IPointerEnterHandler, IPointerEventHandler, IPointerExitHandler, PointerEventData } from "./PointerEvents.js";
6
+ import { serializable } from "../../engine/engine_serialization_decorator.js";
7
+ import { Animator } from "../Animator.js";
8
+ import { getParam } from "../../engine/engine_utils.js";
9
+ import { showBalloonMessage } from "../../engine/debug/index.js";
12
10
  import { GraphicRaycaster, ObjectRaycaster, Raycaster } from "./Raycaster.js";
11
+ import { PointerType } from "../../engine/engine_input.js";
12
+ import { Gizmos } from "../../engine/engine_gizmos.js";
13
13
 
14
14
  const debug = getParam("debugbutton");
15
15
 
@@ -120,10 +120,10 @@
120
120
  }
121
121
 
122
122
  onPointerClick(args: PointerEventData) {
123
- if (!this.interactable) return;
123
+ if (!this.interactable || args.pointerId !== 0) return;
124
124
 
125
- if (args.button !== 0 && args.event.pointerType === PointerType.Mouse) return;
126
125
  // Button clicks should only run with left mouse button while using mouse
126
+ if(args.pointerId !== 0 && this.context.input.getIsMouse(args.pointerId)) return;
127
127
  if (debug) {
128
128
  console.warn("Button Click", this.onClick);
129
129
  showBalloonMessage("CLICKED button " + this.name + " at " + this.context.time.frameCount);
src/engine-components/Camera.ts CHANGED
@@ -1,17 +1,17 @@
1
- import { EquirectangularReflectionMapping, OrthographicCamera, PerspectiveCamera, Ray, SRGBColorSpace, Vector3 } from "three";
2
- import { Texture } from "three";
3
-
1
+ import { Behaviour, GameObject } from "./Component.js";
2
+ import { getParam } from "../engine/engine_utils.js";
3
+ import { serializable } from "../engine/engine_serialization_decorator.js";
4
+ import { RGBAColor } from "./js-extensions/RGBAColor.js";
5
+ import { Context, XRSessionMode } from "../engine/engine_setup.js";
6
+ import type { ICamera } from "../engine/engine_types.js"
4
7
  import { isDevEnvironment, showBalloonMessage, showBalloonWarning } from "../engine/debug/index.js";
8
+ import { getWorldPosition } from "../engine/engine_three_utils.js";
5
9
  import { Gizmos } from "../engine/engine_gizmos.js";
6
- import { serializable } from "../engine/engine_serialization_decorator.js";
7
- import { Context } from "../engine/engine_setup.js";
10
+
11
+ import { EquirectangularReflectionMapping, OrthographicCamera, PerspectiveCamera, Ray, SRGBColorSpace, Vector3 } from "three";
12
+ import { OrbitControls } from "./OrbitControls.js";
8
13
  import { RenderTexture } from "../engine/engine_texture.js";
9
- import { getWorldPosition } from "../engine/engine_three_utils.js";
10
- import type { ICamera } from "../engine/engine_types.js"
11
- import { getParam } from "../engine/engine_utils.js";
12
- import { Behaviour, GameObject } from "./Component.js";
13
- import { RGBAColor } from "./js-extensions/RGBAColor.js";
14
- import { OrbitControls } from "./OrbitControls.js";
14
+ import { Texture } from "three";
15
15
 
16
16
  export enum ClearFlags {
17
17
  Skybox = 1,
@@ -350,6 +350,7 @@
350
350
  if (this._backgroundBlurriness !== undefined)
351
351
  this.context.scene.backgroundBlurriness = this._backgroundBlurriness;
352
352
  if (this._backgroundIntensity !== undefined)
353
+ //@ts-ignore
353
354
  this.context.scene.backgroundIntensity = this._backgroundIntensity;
354
355
 
355
356
  break;
@@ -391,7 +392,7 @@
391
392
  if (debug)
392
393
  showBalloonMessage("Environment blend mode: " + environmentBlendMode + " on " + navigator.userAgent);
393
394
  let transparent = environmentBlendMode === 'additive' || environmentBlendMode === 'alpha-blend';
394
- if (context.isInAR) {
395
+ if (context.xrSessionMode === XRSessionMode.ImmersiveAR) {
395
396
  if (environmentBlendMode === "opaque") {
396
397
  // workaround for Quest 2 returning opaque when it should be alpha-blend
397
398
  // check user agent if this is the Quest browser and return true if so
src/engine-components/CameraUtils.ts CHANGED
@@ -1,15 +1,14 @@
1
+ import { OrbitControls } from "./OrbitControls.js";
2
+ import { addNewComponent, getOrAddComponent } from "../engine/engine_components.js";
1
3
  import { Object3D } from "three";
2
-
4
+ import type { ICamera, IContext } from "../engine/engine_types.js";
5
+ import { RGBAColor } from "./js-extensions/RGBAColor.js";
6
+ import { ContextEvent, ContextRegistry } from "../engine/engine_context_registry.js";
3
7
  import { getCameraController } from "../engine/engine_camera.js";
4
- import { addNewComponent, getOrAddComponent } from "../engine/engine_components.js";
5
- import { Context } from "../engine/engine_context.js";
6
- import { ContextEvent, ContextRegistry } from "../engine/engine_context_registry.js";
8
+ import { Camera, ClearFlags } from "./Camera.js";
7
9
  import { NeedleEngineHTMLElement } from "../engine/engine_element.js";
8
- import type { ICamera, IContext } from "../engine/engine_types.js";
9
10
  import { getParam } from "../engine/engine_utils.js";
10
- import { Camera, ClearFlags } from "./Camera.js";
11
- import { RGBAColor } from "./js-extensions/RGBAColor.js";
12
- import { OrbitControls } from "./OrbitControls.js";
11
+ import { Context } from "../engine/engine_context.js";
13
12
 
14
13
  const debug = getParam("debugmissingcamera");
15
14
 
src/engine-components/ui/Canvas.ts CHANGED
@@ -1,19 +1,17 @@
1
- import { Matrix4, Object3D } from "three";
2
- import * as ThreeMeshUI from 'three-mesh-ui'
3
-
4
- import { Mathf } from "../../engine/engine_math.js";
1
+ import { updateRenderSettings as updateRenderSettingsRecursive } from "./Utils.js";
5
2
  import { serializable } from "../../engine/engine_serialization_decorator.js";
6
3
  import { FrameEvent } from "../../engine/engine_setup.js";
7
- import { getParam } from "../../engine/engine_utils.js";
8
- import { NeedleXREventArgs } from "../../engine/xr/index.js";
4
+ import { BaseUIComponent, UIRootComponent } from "./BaseUIComponent.js";
5
+ import { GameObject } from "../Component.js";
6
+ import { Matrix4, Object3D } from "three";
7
+ import { RectTransform } from "./RectTransform.js";
8
+ import type { ICanvas, ICanvasEventReceiver, ILayoutGroup, IRectTransform } from "./Interfaces.js";
9
9
  import { Camera } from "../Camera.js";
10
- import { GameObject } from "../Component.js";
11
- import { BaseUIComponent, UIRootComponent } from "./BaseUIComponent.js";
12
10
  import { EventSystem } from "./EventSystem.js";
13
- import type { ICanvas, ICanvasEventReceiver, ILayoutGroup, IRectTransform } from "./Interfaces.js";
11
+ import * as ThreeMeshUI from 'three-mesh-ui'
12
+ import { getParam } from "../../engine/engine_utils.js";
14
13
  import { LayoutGroup } from "./Layout.js";
15
- import { RectTransform } from "./RectTransform.js";
16
- import { updateRenderSettings as updateRenderSettingsRecursive } from "./Utils.js";
14
+ import { Mathf } from "../../engine/engine_math.js";
17
15
 
18
16
  export enum RenderMode {
19
17
  ScreenSpaceOverlay = 0,
@@ -202,30 +200,19 @@
202
200
  }
203
201
  }
204
202
 
205
- onEnterXR(args: NeedleXREventArgs): void {
206
- if (this.screenspace) {
207
- if (args.xr.isVR || args.xr.isPassThrough) {
208
- this.gameObject.visible = false;
209
- }
210
- }
211
- }
212
- onLeaveXR(args: NeedleXREventArgs): void {
213
- if (this.screenspace) {
214
- if (args.xr.isVR || args.xr.isPassThrough) {
215
- this.gameObject.visible = true;
216
- }
217
- }
218
- }
219
-
220
203
  onBeforeRenderRoutine = () => {
221
- this.previousParent = this.gameObject.parent;
222
- if ((this.context.xr?.isVR || this.context.xr?.isPassThrough) && this.screenspace) {
223
- // see https://linear.app/needle/issue/NE-4114
224
- this.gameObject.visible = false;
225
- this.gameObject.removeFromParent();
204
+ if (this.context.isInVR) {
205
+ this.onUpdateRenderMode();
206
+ this.handleLayoutUpdates();
207
+ // TODO TMUI @swingingtom - For VR this is so we don't have text clipping
208
+ this.shadowComponent?.updateMatrixWorld(true);
209
+ this.shadowComponent?.updateWorldMatrix(true, true);
210
+ this.invokeBeforeRenderEvents();
211
+ EventSystem.ensureUpdateMeshUI(ThreeMeshUI, this.context, true);
226
212
  return;
227
213
  }
228
214
 
215
+ this.previousParent = this.gameObject.parent;
229
216
  // console.log(this.previousParent?.name + "/" + this.gameObject.name);
230
217
 
231
218
  if (this.renderOnTop || this.screenspace) {
@@ -244,12 +231,7 @@
244
231
  }
245
232
 
246
233
  onAfterRenderRoutine = () => {
247
- if ((this.context.xr?.isVR || this.context.xr?.isPassThrough) && this.screenspace) {
248
- this.previousParent?.add(this.gameObject);
249
- // this is currently causing an error during XR (https://linear.app/needle/issue/NE-4114)
250
- // this.gameObject.visible = true;
251
- return;
252
- }
234
+ if(this.context.isInVR) return;
253
235
  if ((this.screenspace || this.renderOnTop) && this.previousParent && this.context.mainCamera) {
254
236
  if (this.screenspace) {
255
237
  const camObj = this.context.mainCamera;
@@ -294,7 +276,7 @@
294
276
  for (const ch of this._rectTransforms) {
295
277
  if (matrixWorldChanged) ch.markDirty();
296
278
  let layout = this._layoutGroups.get(ch.gameObject);
297
- if (ch.isDirty && !layout) {
279
+ if(ch.isDirty && !layout){
298
280
  layout = ch.gameObject.getComponentInParent(LayoutGroup) as LayoutGroup;
299
281
  }
300
282
  if (ch.isDirty || layout?.isDirty) {
src/engine-components/ui/CanvasGroup.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { serializable } from "../../engine/engine_serialization_decorator.js";
1
+ import { Graphic } from "./Graphic.js";
2
2
  import { FrameEvent } from "../../engine/engine_setup.js";
3
3
  import { Behaviour, GameObject } from "../Component.js";
4
+ import { type ICanvasGroup, type IHasAlphaFactor } from "./Interfaces.js";
5
+ import { serializable } from "../../engine/engine_serialization_decorator.js";
4
6
  import { BaseUIComponent } from "./BaseUIComponent.js";
5
- import { Graphic } from "./Graphic.js";
6
- import { type ICanvasGroup, type IHasAlphaFactor } from "./Interfaces.js";
7
7
 
8
8
 
9
9
  export class CanvasGroup extends Behaviour implements ICanvasGroup {
src/engine-components/CharacterController.ts CHANGED
@@ -1,15 +1,14 @@
1
1
  import { Quaternion, Ray, Vector2, Vector3 } from "three";
2
-
3
2
  import { Mathf } from "../engine/engine_math.js";
4
- import { RaycastOptions } from "../engine/engine_physics.js";
5
3
  import { serializable } from "../engine/engine_serialization.js";
6
- import { getWorldPosition } from "../engine/engine_three_utils.js";
7
4
  import { Collision } from "../engine/engine_types.js";
8
- import { getParam } from "../engine/engine_utils.js";
9
- import { Animator } from "./Animator.js"
10
5
  import { CapsuleCollider } from "./Collider.js";
11
6
  import { Behaviour, GameObject } from "./Component.js";
12
7
  import { Rigidbody } from "./RigidBody.js";
8
+ import { Animator } from "./Animator.js"
9
+ import { RaycastOptions } from "../engine/engine_physics.js";
10
+ import { getWorldPosition } from "../engine/engine_three_utils.js";
11
+ import { getParam } from "../engine/engine_utils.js";
13
12
 
14
13
  const debug = getParam("debugcharactercontroller");
15
14
 
src/engine-components/postprocessing/Effects/ChromaticAberration.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { ChromaticAberrationEffect } from "postprocessing";
2
2
  import { Vector2 } from "three";
3
-
4
3
  import { serializable } from "../../../engine/engine_serialization.js";
5
4
  import { type EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect.js";
6
5
  import { VolumeParameter } from "../VolumeParameter.js";
src/engine-components/Collider.ts CHANGED
@@ -1,14 +1,13 @@
1
+ import { Behaviour } from "./Component.js";
2
+ import { Rigidbody } from "./RigidBody.js";
3
+ import { serializable } from "../engine/engine_serialization_decorator.js";
1
4
  import { Group, Mesh, Vector3 } from "three"
2
-
3
- import type { PhysicsMaterial } from "../engine/engine_physics.types.js";
4
- import { serializable } from "../engine/engine_serialization_decorator.js";
5
- import { getWorldScale } from "../engine/engine_three_utils.js";
6
5
  // import { IColliderProvider, registerColliderProvider } from "../engine/engine_physics.js";
7
6
  import type { IBoxCollider, ICollider, ISphereCollider } from "../engine/engine_types.js";
7
+ import { getWorldScale } from "../engine/engine_three_utils.js";
8
+ import type { PhysicsMaterial } from "../engine/engine_physics.types.js";
8
9
  import { validate } from "../engine/engine_util_decorator.js";
9
10
  import { unwatchWrite, watchWrite } from "../engine/engine_utils.js";
10
- import { Behaviour } from "./Component.js";
11
- import { Rigidbody } from "./RigidBody.js";
12
11
 
13
12
 
14
13
  export class Collider extends Behaviour implements ICollider {
src/engine-components/postprocessing/Effects/ColorAdjustments.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  import { BrightnessContrastEffect, HueSaturationEffect } from "postprocessing";
2
- import { LinearToneMapping, NoToneMapping } from "three";
3
-
4
2
  import { serializable } from "../../../engine/engine_serialization.js";
5
3
  import { type EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect.js";
6
4
  import { VolumeParameter } from "../VolumeParameter.js";
7
5
  import { registerCustomEffectType } from "../VolumeProfile.js";
6
+ import { LinearToneMapping, NoToneMapping } from "three";
8
7
 
9
8
 
10
9
  export class ColorAdjustments extends PostProcessingEffect {
src/engine-components/Component.ts CHANGED
@@ -1,17 +1,15 @@
1
- import { Euler, Object3D, Quaternion, Scene, Vector3 } from "three";
2
-
3
- import { isDevEnvironment } from "../engine/debug/index.js";
4
- import { addNewComponent, destroyComponentInstance, findObjectOfType, findObjectsOfType, getComponent, getComponentInChildren, getComponentInParent, getComponents, getComponentsInChildren, getComponentsInParent, getOrAddComponent, moveComponentInstance, removeComponent } from "../engine/engine_components.js";
1
+ import { Mathf } from "../engine/engine_math.js";
2
+ import * as threeutils from "../engine/engine_three_utils.js";
5
3
  import { activeInHierarchyFieldName } from "../engine/engine_constants.js";
6
- import { destroy, findByGuid, foreachComponent, HideFlags, IInstantiateOptions, instantiate, isActiveInHierarchy, isActiveSelf, isDestroyed, isUsingInstancing, markAsInstancedRendered, setActive } from "../engine/engine_gameobject.js";
4
+ import { Context, FrameEvent } from "../engine/engine_setup.js";
7
5
  import * as main from "../engine/engine_mainloop_utils.js";
8
6
  import { syncDestroy, syncInstantiate } from "../engine/engine_networking_instantiate.js";
9
- import { Context, FrameEvent } from "../engine/engine_setup.js";
10
- import * as threeutils from "../engine/engine_three_utils.js";
11
- import type { Collision, Constructor, ConstructorConcrete, GuidsMap, ICollider, IComponent, IGameObject, SourceIdentifier } from "../engine/engine_types.js";
12
- import { INeedleXRSessionEventReceiver, NeedleXRControllerEventArgs, NeedleXREventArgs } from "../engine/engine_xr.js";
13
- import { IPointerEventHandler, PointerEventData } from "./ui/PointerEvents.js";
7
+ import type { ConstructorConcrete, SourceIdentifier, IComponent, IGameObject, Constructor, GuidsMap, Collision, ICollider } from "../engine/engine_types.js";
8
+ import { addNewComponent, destroyComponentInstance, findObjectOfType, findObjectsOfType, getComponent, getComponentInChildren, getComponentInParent, getComponents, getComponentsInChildren, getComponentsInParent, getOrAddComponent, moveComponentInstance, removeComponent } from "../engine/engine_components.js";
9
+ import { findByGuid, destroy, InstantiateOptions, instantiate, HideFlags, foreachComponent, markAsInstancedRendered, isActiveInHierarchy, isActiveSelf, isUsingInstancing, setActive, isDestroyed, IInstantiateOptions } from "../engine/engine_gameobject.js";
14
10
 
11
+ import { Euler, Object3D, Quaternion, Scene, Vector3 } from "three";
12
+ import { showBalloonWarning, isDevEnvironment } from "../engine/debug/index.js";
15
13
 
16
14
  // export interface ISerializationCallbackReceiver {
17
15
  // onBeforeSerialize?(): object | void;
@@ -125,7 +123,7 @@
125
123
  main.addScriptToArrays(comp, context!);
126
124
  if (comp.__internalDidAwakeAndStart) return;
127
125
  if (context!.new_script_start.includes(comp) === false) {
128
- context!.new_script_start.push(comp as Component);
126
+ context!.new_script_start.push(comp as Behaviour);
129
127
  }
130
128
  }, true);
131
129
  }
@@ -256,7 +254,7 @@
256
254
  return getComponentsInParent(go, typeName, arr);
257
255
  }
258
256
 
259
- public static getAllComponents(go: IGameObject | Object3D): Component[] {
257
+ public static getAllComponents(go: IGameObject | Object3D): Behaviour[] {
260
258
  const componentsList = go.userData?.components;
261
259
  const newList = [...componentsList];
262
260
  return newList;
@@ -296,7 +294,7 @@
296
294
  abstract set worldQuaternion(val: Quaternion);
297
295
  abstract get worldQuaternion(): Quaternion;
298
296
  abstract set worldRotation(val: Vector3);
299
- abstract get worldRotation(): Vector3;
297
+ abstract get worldRotation(): Vector3;
300
298
  abstract set worldScale(val: Vector3);
301
299
  abstract get worldScale(): Vector3;
302
300
 
@@ -307,28 +305,17 @@
307
305
 
308
306
 
309
307
 
310
- /** Needle Engine component base class. Derive from this component to implement your own using the provided lifecycle methods. Components can be added to threejs objects using `GameObject.addComponent`.
311
- *
312
- * The most common lifecycle methods are `awake`, `start`, `onEanble`, `onDisable` `update` and `onDestroy`.
313
- * XR specific callbacks include `onEnterXR`, `onLeaveXR`, `onUpdateXR`, `onControllerAdded` and `onControllerRemoved`.
314
- * To receive pointer events implement `onPointerDown`, `onPointerUp`, `onPointerEnter`, `onPointerExit` and `onPointerMove`.
315
- */
316
- export abstract class Component implements IComponent, EventTarget,
317
- Partial<INeedleXRSessionEventReceiver>,
318
- Partial<IPointerEventHandler>
319
- {
308
+ export class Component implements IComponent, EventTarget {
320
309
 
321
310
  get isComponent(): boolean { return true; }
322
311
 
323
312
  private __context: Context | undefined;
324
- /** Use the context to get access to many Needle Engine features and use physics, timing, access the camera or scene */
325
313
  get context(): Context {
326
314
  return this.__context ?? Context.Current;
327
315
  }
328
316
  set context(context: Context) {
329
317
  this.__context = context;
330
318
  }
331
- /** shorthand for `this.context.scene` */
332
319
  get scene(): Scene { return this.context.scene; }
333
320
 
334
321
  get layer(): number {
@@ -368,7 +355,7 @@
368
355
  return this.gameObject?.userData.hideFlags;
369
356
  }
370
357
 
371
- /** @returns true if the object is enabled and active in the hierarchy */
358
+
372
359
  get activeAndEnabled(): boolean {
373
360
  if (this.destroyed) return false;
374
361
  if (this.__isEnabled === false) return false;
@@ -398,27 +385,19 @@
398
385
  this.gameObject[activeInHierarchyFieldName] = val;
399
386
  }
400
387
 
401
- /** the object this component is attached to. Note that this is a threejs Object3D with some additional features */
402
388
  gameObject!: GameObject;
403
- /** the unique identifier for this component */
404
389
  guid: string = "invalid";
405
- /** holds the source identifier this object was created with/from (e.g. if it was part of a glTF file the sourceId holds the url to the glTF) */
406
390
  sourceId?: SourceIdentifier;
407
391
  // transform: Object3D = nullObject;
408
392
 
409
393
  /** called on a component with a map of old to new guids (e.g. when instantiate generated new guids and e.g. timeline track bindings needs to remape them) */
410
394
  resolveGuids?(guidsMap: GuidsMap): void;
411
395
 
412
- /** called once when the component becomes active for the first time (once per component)
413
- * This is the first callback to be called */
396
+ /** called once when the component becomes active for the first time */
414
397
  awake() { }
415
- /** called every time when the component gets enabled (this is invoked after awake and before start)
416
- * or when it becomes active in the hierarchy (e.g. if a parent object or this.gameObject gets set to visible)
417
- */
398
+ /** called every time when the component gets enabled (this is invoked after awake and before start) */
418
399
  onEnable() { }
419
- /** called every time the component gets disabled or if a parent object (or this.gameObject) gets set to invisible */
420
400
  onDisable() { }
421
- /** Called when the component gets destroyed */
422
401
  onDestroy() {
423
402
  this.__destroyed = true;
424
403
  }
@@ -430,17 +409,11 @@
430
409
  /** Called for all scripts when the context gets paused or unpaused */
431
410
  onPausedChanged?(isPaused: boolean, wasPaused: boolean): void;
432
411
 
433
- /** called at the beginning of a frame (once per component) */
434
412
  start?(): void;
435
- /** first callback in a frame (called every frame when implemented) */
436
413
  earlyUpdate?(): void;
437
- /** regular callback in a frame (called every frame when implemented) */
438
414
  update?(): void;
439
- /** late callback in a frame (called every frame when implemented) */
440
415
  lateUpdate?(): void;
441
- /** called before the scene gets rendered in the main update loop */
442
416
  onBeforeRender?(frame: XRFrame | null): void;
443
- /** called after the scene was rendered */
444
417
  onAfterRender?(): void;
445
418
 
446
419
  onCollisionEnter?(col: Collision);
@@ -451,79 +424,18 @@
451
424
  onTriggerStay?(col: ICollider);
452
425
  onTriggerExit?(col: ICollider);
453
426
 
454
-
455
- /** Optional callback, you can implement this to only get callbacks for VR or AR sessions if necessary.
456
- * @returns true if the mode is supported (if false the mode is not supported by this ciomponent and it will not receive XR callbacks for this mode)
457
- */
458
- supportsXR?(mode: XRSessionMode): boolean;
459
- /** Called before the XR session is requested. Use this callback if you want to modify the session init features */
460
- onBeforeXR?(mode: XRSessionMode, args: XRSessionInit): void;
461
- /** Callback when this component joins a xr session (or becomes active in a running XR session) */
462
- onEnterXR?(args: NeedleXREventArgs): void;
463
- /** Callback when a xr session updates (while it is still active in XR session) */
464
- onUpdateXR?(args: NeedleXREventArgs): void;
465
- /** Callback when this component exists a xr session (or when it becomes inactive in a running XR session) */
466
- onLeaveXR?(args: NeedleXREventArgs): void;
467
- /** Callback when a controller is connected/added while in a XR session
468
- * OR when the component joins a running XR session that has already connected controllers
469
- * OR when the component becomes active during a running XR session that has already connected controllers */
470
- onXRControllerAdded?(args: NeedleXRControllerEventArgs): void;
471
- /** callback when a controller is removed while in a XR session
472
- * OR when the component becomes inactive during a running XR session
473
- */
474
- onXRControllerRemoved?(args: NeedleXRControllerEventArgs): void;
475
-
476
-
477
- /* IPointerEventReceiver */
478
- /* @inheritdoc */
479
- onPointerEnter?(args: PointerEventData);
480
- onPointerMove?(args: PointerEventData);
481
- onPointerExit?(args: PointerEventData);
482
- onPointerDown?(args: PointerEventData);
483
- onPointerUp?(args: PointerEventData);
484
- onPointerClick?(args: PointerEventData);
485
-
486
-
487
- /** starts a coroutine (javascript generator function)
488
- * `yield` will wait for the next frame:
489
- * - Use `yield WaitForSeconds(1)` to wait for 1 second.
490
- * - Use `yield WaitForFrames(10)` to wait for 10 frames.
491
- * - Use `yield new Promise(...)` to wait for a promise to resolve.
492
- * @param routine generator function to start
493
- * @param evt event to register the coroutine for (default: FrameEvent.Update). Note that all coroutine FrameEvent callbacks are invoked after the matching regular component callbacks. For example `FrameEvent.Update` will be called after regular component `update()` methods)
494
- * @returns the generator function (use it to stop the coroutine with `stopCoroutine`)
495
- * @example
496
- * ```ts
497
- * onEnable() { this.startCoroutine(this.myCoroutine()); }
498
- * private *myCoroutine() {
499
- * while(this.activeAndEnabled) {
500
- * console.log("Hello World", this.context.time.frame);
501
- * // wait for 5 frames
502
- * for(let i = 0; i < 5; i++) yield;
503
- * }
504
- * }
505
- * ```
506
- */
507
427
  startCoroutine(routine: Generator, evt: FrameEvent = FrameEvent.Update): Generator {
508
428
  return this.context.registerCoroutineUpdate(this, routine, evt);
509
429
  }
510
- /**
511
- * Stop a coroutine that was previously started with `startCoroutine`
512
- * @param routine the routine to be stopped
513
- * @param evt the frame event to unregister the routine from (default: FrameEvent.Update)
514
- */
430
+
515
431
  stopCoroutine(routine: Generator, evt: FrameEvent = FrameEvent.Update): void {
516
432
  this.context.unregisterCoroutineUpdate(routine, evt);
517
433
  }
518
434
 
519
- /** @returns true if this component was destroyed (`this.destroy()`) or the whole object this component was part of */
520
435
  public get destroyed(): boolean {
521
436
  return this.__destroyed;
522
437
  }
523
438
 
524
- /**
525
- * Destroys this component (and removes it from the object)
526
- */
527
439
  public destroy() {
528
440
  if (this.__destroyed) return;
529
441
  this.__internalDestroy();
@@ -552,11 +464,7 @@
552
464
 
553
465
  /** @internal */
554
466
  constructor() {
555
- this.__didAwake = false;
556
- this.__didStart = false;
557
- this.__didEnable = false;
558
- this.__isEnabled = undefined;
559
- this.__destroyed = false;
467
+ this.__internalNewInstanceCreated();
560
468
  }
561
469
 
562
470
 
@@ -758,6 +666,5 @@
758
666
  }
759
667
  }
760
668
 
761
- // For legacy reasons we need to export this as well
762
- // (and we don't use extend to inherit the component docs)
763
- export { Component as Behaviour };
669
+ export class Behaviour extends Component {
670
+ }
src/engine-components/codegen/components.ts CHANGED
@@ -1,4 +1,3 @@
1
- /* eslint-disable */
2
1
  // Export types
3
2
  export class __Ignore {}
4
3
  export { ActionBuilder } from "../export/usdz/extensions/behavior/BehavioursBuilder.js";
@@ -12,11 +11,11 @@
12
11
  export { Animator } from "../Animator.js";
13
12
  export { AnimatorController } from "../AnimatorController.js";
14
13
  export { Antialiasing } from "../postprocessing/Effects/Antialiasing.js";
14
+ export { AttachedObject } from "../webxr/WebXRController.js";
15
15
  export { AudioExtension } from "../export/usdz/extensions/behavior/AudioExtension.js";
16
16
  export { AudioListener } from "../AudioListener.js";
17
17
  export { AudioSource } from "../AudioSource.js";
18
18
  export { AudioTrackHandler } from "../timeline/TimelineTracks.js";
19
- export { Avatar } from "../webxr/Avatar.js";
20
19
  export { Avatar_Brain_LookAt } from "../avatar/Avatar_Brain_LookAt.js";
21
20
  export { Avatar_MouthShapes } from "../avatar/Avatar_MouthShapes.js";
22
21
  export { Avatar_MustacheShake } from "../avatar/Avatar_MustacheShake.js";
@@ -31,6 +30,7 @@
31
30
  export { BasicIKConstraint } from "../BasicIKConstraint.js";
32
31
  export { BehaviorExtension } from "../export/usdz/extensions/behavior/Behaviour.js";
33
32
  export { BehaviorModel } from "../export/usdz/extensions/behavior/BehavioursBuilder.js";
33
+ export { Behaviour } from "../Component.js";
34
34
  export { Bloom } from "../postprocessing/Effects/Bloom.js";
35
35
  export { BoxCollider } from "../Collider.js";
36
36
  export { BoxGizmo } from "../Gizmos.js";
@@ -51,6 +51,7 @@
51
51
  export { ColorAdjustments } from "../postprocessing/Effects/ColorAdjustments.js";
52
52
  export { ColorBySpeedModule } from "../ParticleSystemModules.js";
53
53
  export { ColorOverLifetimeModule } from "../ParticleSystemModules.js";
54
+ export { Component } from "../Component.js";
54
55
  export { ContactShadows } from "../ContactShadows.js";
55
56
  export { ControlTrackHandler } from "../timeline/TimelineTracks.js";
56
57
  export { CustomBranding } from "../export/usdz/USDZExporter.js";
@@ -87,6 +88,7 @@
87
88
  export { Image } from "../ui/Image.js";
88
89
  export { InheritVelocityModule } from "../ParticleSystemModules.js";
89
90
  export { InputField } from "../ui/InputField.js";
91
+ export { Interactable } from "../Interactable.js";
90
92
  export { Light } from "../Light.js";
91
93
  export { LimitVelocityOverLifetimeModule } from "../ParticleSystemModules.js";
92
94
  export { LODGroup } from "../LODGroup.js";
@@ -100,7 +102,6 @@
100
102
  export { MeshRenderer } from "../Renderer.js";
101
103
  export { MinMaxCurve } from "../ParticleSystemModules.js";
102
104
  export { MinMaxGradient } from "../ParticleSystemModules.js";
103
- export { NeedleWebXRHtmlElement } from "../webxr/WebXRButtons.js";
104
105
  export { NestedGltf } from "../NestedGltf.js";
105
106
  export { Networking } from "../Networking.js";
106
107
  export { NoiseModule } from "../ParticleSystemModules.js";
@@ -124,6 +125,7 @@
124
125
  export { PreliminaryAction } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
125
126
  export { PreliminaryTrigger } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
126
127
  export { RawImage } from "../ui/Image.js";
128
+ export { Raycaster } from "../ui/Raycaster.js";
127
129
  export { Rect } from "../ui/RectTransform.js";
128
130
  export { RectTransform } from "../ui/RectTransform.js";
129
131
  export { ReflectionProbe } from "../ReflectionProbe.js";
@@ -151,7 +153,6 @@
151
153
  export { SizeOverLifetimeModule } from "../ParticleSystemModules.js";
152
154
  export { SkinnedMeshRenderer } from "../Renderer.js";
153
155
  export { SmoothFollow } from "../SmoothFollow.js";
154
- export { SpatialGrabRaycaster } from "../ui/Raycaster.js";
155
156
  export { SpatialHtml } from "../ui/SpatialHtml.js";
156
157
  export { SpatialTrigger } from "../SpatialTrigger.js";
157
158
  export { SpatialTriggerReceiver } from "../SpatialTrigger.js";
@@ -166,7 +167,7 @@
166
167
  export { SyncedRoom } from "../SyncedRoom.js";
167
168
  export { SyncedTransform } from "../SyncedTransform.js";
168
169
  export { TapGestureTrigger } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
169
- export { TeleportTarget } from "../webxr/TeleportTarget.js";
170
+ export { TeleportTarget } from "../webxr/WebXRController.js";
170
171
  export { TestRunner } from "../TestRunner.js";
171
172
  export { TestSimulateUserData } from "../TestRunner.js";
172
173
  export { Text } from "../ui/Text.js";
@@ -196,16 +197,20 @@
196
197
  export { Volume } from "../postprocessing/Volume.js";
197
198
  export { VolumeParameter } from "../postprocessing/VolumeParameter.js";
198
199
  export { VolumeProfile } from "../postprocessing/VolumeProfile.js";
200
+ export { VRUserState } from "../webxr/WebXRSync.js";
201
+ export { WebAR } from "../webxr/WebXR.js";
199
202
  export { WebARCameraBackground } from "../webxr/WebARCameraBackground.js";
200
203
  export { WebARSessionRoot } from "../webxr/WebARSessionRoot.js";
201
204
  export { WebXR } from "../webxr/WebXR.js";
205
+ export { WebXRAvatar } from "../webxr/WebXRAvatar.js";
206
+ export { WebXRController } from "../webxr/WebXRController.js";
202
207
  export { WebXRImageTracking } from "../webxr/WebXRImageTracking.js";
203
208
  export { WebXRImageTrackingModel } from "../webxr/WebXRImageTracking.js";
204
209
  export { WebXRPlaneTracking } from "../webxr/WebXRPlaneTracking.js";
210
+ export { WebXRSync } from "../webxr/WebXRSync.js";
205
211
  export { WebXRTrackedImage } from "../webxr/WebXRImageTracking.js";
206
- export { XRControllerFollow } from "../webxr/controllers/XRControllerFollow.js";
207
- export { XRControllerModel } from "../webxr/controllers/XRControllerModel.js";
208
- export { XRControllerMovement } from "../webxr/controllers/XRControllerMovement.js";
209
- export { XRFlag } from "../webxr/XRFlag.js";
212
+ export { XRFlag } from "../XRFlag.js";
213
+ export { XRGrabModel } from "../webxr/WebXRGrabRendering.js";
214
+ export { XRGrabRendering } from "../webxr/WebXRGrabRendering.js";
210
215
  export { XRRig } from "../webxr/WebXRRig.js";
211
- export { XRState } from "../webxr/XRFlag.js";
216
+ export { XRState } from "../XRFlag.js";
src/engine-components/ContactShadows.ts CHANGED
@@ -1,11 +1,11 @@
1
+ import { Behaviour } from "./Component.js";
2
+ import { serializable } from "../engine/engine_serialization_decorator.js";
3
+
1
4
  import { CustomBlending, DoubleSide, Group, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MinEquation, OrthographicCamera, PlaneGeometry, ShaderMaterial, WebGLRenderTarget } from "three";
2
5
  import { HorizontalBlurShader } from 'three/examples/jsm/shaders/HorizontalBlurShader.js';
3
6
  import { VerticalBlurShader } from 'three/examples/jsm/shaders/VerticalBlurShader.js';
4
-
5
- import { serializable } from "../engine/engine_serialization_decorator.js";
6
7
  import { getParam } from "../engine/engine_utils.js"
7
8
  import { setCustomVisibility } from "../engine/js-extensions/Layers.js";
8
- import { Behaviour } from "./Component.js";
9
9
 
10
10
  const debug = getParam("debugcontactshadows");
11
11
 
src/engine/debug/debug_console.ts CHANGED
@@ -1,7 +1,6 @@
1
+ import { getErrorCount } from "./debug_overlay.js";
2
+ import { getParam, isMobileDevice } from "../engine_utils.js";
1
3
  import { isLocalNetwork } from "../engine_networking_utils.js";
2
- import { getParam, isMobileDevice, isQuest } from "../engine_utils.js";
3
- import { isDevEnvironment } from "./debug.js";
4
- import { getErrorCount, makeErrorsVisibleForDevelopment } from "./debug_overlay.js";
5
4
 
6
5
  let consoleInstance: any = null;
7
6
  let consoleHtmlElement: HTMLElement | null = null;
@@ -23,11 +22,8 @@
23
22
  currentUrl.searchParams.set("console", "1");
24
23
  console.log("🌵 Tip: You can add the \"?console\" query parameter to the url to show the debug console (on mobile it will automatically open in the bottom right corner when your get errors during development)", "\nOpen this page console: " + currentUrl.toString());
25
24
  }
26
- const isMobile = isMobileDevice() || (isQuest() && isDevEnvironment());
25
+ const isMobile = isMobileDevice();
27
26
  if (isMobile) {
28
- // we need to invoke this here - otherwise we will miss errors that happen after the console is loaded
29
- // and calling the method from the root needle-engine.ts import is evaluated later (if we import the method from the toplevel file and then invoke it)
30
- makeErrorsVisibleForDevelopment();
31
27
  beginWatchingLogs();
32
28
  createConsole(true);
33
29
  if (isMobile) {
@@ -195,7 +191,7 @@
195
191
  }
196
192
  `;
197
193
  consoleHtmlElement?.prepend(styles);
198
- if (startHidden === true && getErrorCount() <= 0)
194
+ if (startHidden === true)
199
195
  hideDebugConsole();
200
196
  console.log("🌵 Debug console has loaded");
201
197
  }
src/engine/debug/debug_overlay.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import { getParam } from "../engine_utils.js";
2
+ import { isLocalNetwork } from "../engine_networking_utils.js";
1
3
  import { ContextRegistry } from "../engine_context_registry.js";
2
- import { isLocalNetwork } from "../engine_networking_utils.js";
3
- import { getParam } from "../engine_utils.js";
4
4
 
5
5
  const debug = getParam("debugdebug");
6
6
  let hide = false;
@@ -15,7 +15,7 @@
15
15
  }
16
16
 
17
17
  export function getErrorCount() {
18
- return _errorCount;
18
+ return errorCount;
19
19
  }
20
20
 
21
21
  const originalConsoleError = console.error;
@@ -37,10 +37,9 @@
37
37
  if (hide) return;
38
38
  const isLocal = isLocalNetwork();
39
39
  if (debug) console.log("Is this a local network?", isLocal);
40
- if (isLocal)
41
- {
40
+ if (isLocal) {
42
41
  if (debug)
43
- console.warn("Patch console", window.location.hostname);
42
+ console.log(window.location.hostname);
44
43
  console.error = patchedConsoleError;
45
44
  window.addEventListener("error", (event) => {
46
45
  if (hide) return;
@@ -67,10 +66,10 @@
67
66
  }
68
67
 
69
68
 
70
- let _errorCount = 0;
69
+ let errorCount = 0;
71
70
 
72
71
  function onReceivedError() {
73
- _errorCount += 1;
72
+ errorCount += 1;
74
73
  }
75
74
 
76
75
  function onParseError(args: Array<any>) {
src/engine/debug/debug.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import { addLog, LogType, setAllowOverlayMessages } from "./debug_overlay.js";
2
+ import { showDebugConsole } from "./debug_console.js";
1
3
  import { isLocalNetwork } from "../engine_networking_utils.js";
2
- import { showDebugConsole } from "./debug_console.js";
3
- import { addLog, LogType, setAllowOverlayMessages } from "./debug_overlay.js";
4
4
 
5
5
  export { showDebugConsole }
6
6
  export { LogType, setAllowOverlayMessages };
src/engine-components/DeleteBox.ts CHANGED
@@ -1,6 +1,5 @@
1
1
 
2
2
  import * as THREE from "three";
3
-
4
3
  import { syncDestroy } from "../engine/engine_networking_instantiate.js";
5
4
  import { getParam } from "../engine/engine_utils.js";
6
5
  import { BoxHelperComponent } from "./BoxHelperComponent.js";
src/engine-components/postprocessing/Effects/DepthOfField.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import { DepthOfFieldEffect } from "postprocessing";
2
-
2
+ import { serializable } from "../../../engine/engine_serialization.js";
3
3
  import { Mathf } from "../../../engine/engine_math.js";
4
- import { serializable } from "../../../engine/engine_serialization.js";
5
- import { isMobileDevice } from "../../../engine/engine_utils.js";
4
+ import { getParam, isMobileDevice } from "../../../engine/engine_utils.js";
6
5
  import { PostProcessingEffect } from "../PostProcessingEffect.js";
7
6
  import { VolumeParameter } from "../VolumeParameter.js";
8
7
  import { registerCustomEffectType } from "../VolumeProfile.js";
@@ -13,6 +12,8 @@
13
12
  Bokeh = 2,
14
13
  }
15
14
 
15
+ const debug = getParam("debugpost");
16
+
16
17
  export class DepthOfField extends PostProcessingEffect {
17
18
 
18
19
  get typeName() {
@@ -41,6 +42,8 @@
41
42
  bokehScale?: VolumeParameter;
42
43
 
43
44
  init() {
45
+ if (debug) console.log("DOF: INIT");
46
+
44
47
  this.focalLength.valueProcessor = v => {
45
48
  const t = v / 300;
46
49
  const max = 2;// this.context.mainCameraComponent?.farClipPlane ?? 10;
@@ -55,7 +58,10 @@
55
58
  }
56
59
 
57
60
  onCreateEffect() {
58
- if (this.mode === DepthOfFieldMode.Off) return undefined;
61
+ if (this.mode === DepthOfFieldMode.Off) {
62
+ if (debug) console.warn("DepthOfField: Mode is set to Off");
63
+ return undefined;
64
+ }
59
65
 
60
66
  const factor = 1 / window.devicePixelRatio;
61
67
 
@@ -78,9 +84,9 @@
78
84
  });
79
85
 
80
86
  this.focusDistance.onValueChanged = v => {
81
- dof.circleOfConfusionMaterial.worldFocusDistance = v;
87
+ dof.cocMaterial.worldFocusDistance = v;
82
88
  }
83
- this.focalLength.onValueChanged = v => dof.circleOfConfusionMaterial.worldFocusRange = v;
89
+ this.focalLength.onValueChanged = v => dof.cocMaterial.worldFocusRange = v;
84
90
  this.aperture.onValueChanged = v => dof.bokehScale = v;
85
91
 
86
92
  if (this.resolutionScale) this.resolutionScale.onValueChanged = v => dof.resolution.scale = v;
src/engine-components/DeviceFlag.ts CHANGED
@@ -1,6 +1,6 @@
1
1
 
2
+ import { isMobileDevice } from "../engine/engine_utils.js";
2
3
  import { serializable } from "../engine/engine_serialization_decorator.js";
3
- import { isMobileDevice } from "../engine/engine_utils.js";
4
4
  import { Behaviour, GameObject } from "./Component.js";
5
5
 
6
6
 
src/engine-components/DragControls.ts CHANGED
@@ -1,126 +1,104 @@
1
- import { AxesHelper, Box3, BufferGeometry, Camera, Color, Event, Line, LineBasicMaterial, Matrix3, Matrix4, Mesh, MeshBasicMaterial, Object3D, Plane, PlaneHelper, Quaternion, Ray, Raycaster, SphereGeometry, Vector3 } from "three";
2
-
3
- import { Gizmos } from "../engine/engine_gizmos.js";
4
- import { InstancingUtil } from "../engine/engine_instancing.js";
5
- import { Mathf } from "../engine/engine_math.js";
1
+ import { GameObject } from "./Component.js";
2
+ import { SyncedTransform } from "./SyncedTransform.js";
3
+ import type { IPointerDownHandler, IPointerEnterHandler, IPointerEventHandler, IPointerExitHandler, IPointerUpHandler, PointerEventData } from "./ui/PointerEvents.js";
4
+ import { Context } from "../engine/engine_setup.js";
5
+ import { Interactable, UsageMarker } from "./Interactable.js";
6
+ import { Rigidbody } from "./RigidBody.js";
7
+ import { WebXR } from "./webxr/WebXR.js";
8
+ import { Avatar_POI } from "./avatar/Avatar_Brain_LookAt.js";
6
9
  import { RaycastOptions } from "../engine/engine_physics.js";
7
- import { serializable } from "../engine/engine_serialization_decorator.js";
8
- import { Context } from "../engine/engine_setup.js";
9
10
  import { getWorldPosition, setWorldPosition } from "../engine/engine_three_utils.js";
10
- import { IGameObject } from "../engine/engine_types.js";
11
- import { getParam } from "../engine/engine_utils.js";
12
- import { NeedleXRSession } from "../engine/engine_xr.js";
13
- import { Avatar_POI } from "./avatar/Avatar_Brain_LookAt.js";
14
- import { Behaviour, GameObject } from "./Component.js";
15
- import { UsageMarker } from "./Interactable.js";
11
+ import type { KeyCode } from "../engine/engine_input.js";
12
+ import { nameofFactory } from "../engine/engine_utils.js";
13
+ import { InstancingUtil } from "../engine/engine_instancing.js";
16
14
  import { OrbitControls } from "./OrbitControls.js";
17
- import { Rigidbody } from "./RigidBody.js";
18
- import { SyncedTransform } from "./SyncedTransform.js";
19
- import type { IPointerEventHandler, PointerEventData } from "./ui/PointerEvents.js";
15
+ import { BufferGeometry, Camera, Color, Line, LineBasicMaterial, Matrix4, Mesh, MeshBasicMaterial, Object3D, Plane, Ray, Raycaster, SphereGeometry, Vector2, Vector3 } from "three";
20
16
  import { ObjectRaycaster } from "./ui/Raycaster.js";
17
+ import { serializable } from "../engine/engine_serialization_decorator.js";
21
18
 
22
- const debug = getParam("debugdrag");
19
+ const debug = false;
23
20
 
24
- export enum DragMode {
25
- /** Object stays at the same horizontal plane as it started. Commonly used for objects on the floor */
26
- XZPlane = 0,
27
- /** Object is dragged as if it was attached to the pointer. In 2D, that means it's dragged along the camera screen plane. In XR, it's dragged by the controller/hand. */
28
- Attached = 1,
29
- /** Object is dragged along the initial raycast hit normal. */
30
- HitNormal = 2,
31
- /** Combination of XZ and Screen based on the viewing angle. Low angles result in Screen dragging and higher angles in XZ dragging. */
32
- DynamicViewAngle = 3,
33
- /** The drag plane is adjusted dynamically while dragging. */
34
- SnapToSurfaces = 4,
21
+ export enum DragEvents {
22
+ SelectStart = "selectstart",
23
+ SelectEnd = "selectend",
35
24
  }
36
25
 
37
- export class DragControls extends Behaviour implements IPointerEventHandler {
26
+ interface SelectArgs {
27
+ selected: Object3D;
28
+ attached: Object3D | GameObject | null;
29
+ }
38
30
 
39
- // dragPlane (floor, object, view)
40
- // snap to surface (snap orientation?)
41
- // two-handed drag (scale, rotate, move)
42
- // keep upright (no tilt)
43
31
 
44
- /** How and where the object is dragged along. */
45
- @serializable()
46
- public dragMode: DragMode = DragMode.DynamicViewAngle;
32
+ export interface IDragEventListener {
33
+ onDragStart?();
34
+ onDragEnd?();
35
+ }
47
36
 
48
- /** Snap dragged objects to a XYZ grid – 0 means: no snapping. */
49
- @serializable()
50
- public snapGridResolution: number = 0.0;
51
-
52
- /** Keep the original rotation of the dragged object. */
53
- @serializable()
54
- public keepRotation: boolean = true;
55
-
56
- /** How and where the object is dragged along while dragging in XR. */
57
- @serializable()
58
- public xrDragMode: DragMode = DragMode.Attached;
37
+ export class DragControls extends Interactable implements IPointerEventHandler {
59
38
 
60
- /** Keep the original rotation of the dragged object while dragging in XR. */
61
- @serializable()
62
- public xrKeepRotation: boolean = false;
39
+ private static _active: number = 0;
40
+ public static get HasAnySelected(): boolean { return this._active > 0; }
63
41
 
64
- /** Accelerate dragging objects closer / further away when in XR */
42
+ /** Show's drag gizmos when enabled */
65
43
  @serializable()
66
- public xrDistanceDragFactor: number = 1;
44
+ public showGizmo: boolean = true;
67
45
 
68
- /** When enabled, draws a line from the dragged object downwards to the next raycast hit. */
46
+ /** When enabled DragControls will drag vertically when the object is viewed from a low angle */
69
47
  @serializable()
70
- public showGizmo: boolean = false;
48
+ public useViewAngle: boolean = true;
71
49
 
72
- // future:
73
- // constraints?
50
+ public transformSelf: boolean = true;
51
+ // public transformGroup: boolean = true;
52
+ // public targets: Object3D[] | null = null;
74
53
 
75
- public static get HasAnySelected(): boolean { return this._active > 0; }
76
- private static _active: number = 0;
77
-
78
- /** The object to be dragged – we pass this to handlers when they are created */
79
- private targetObject: GameObject | null = null;
54
+ // private controls: Control | null = null;
80
55
  private orbit: OrbitControls | null = null;
81
- private _dragHelper: LegacyDragVisualsHelper | null = null;
82
- private static lastHovered: Object3D;
83
- private _draggingRigidbodies: Rigidbody[] = [];
84
- private _potentialDragStartEvt: PointerEventData | null = null;
85
- private _dragHandlers: Map<Object3D, IDragHandler> = new Map();
86
- private _totalMovement: Vector3 = new Vector3();
87
- /** A marker is attached to components that are currently interacted with, to e.g. prevent them from being deleted. */
88
- private _marker: UsageMarker | null = null;
89
- private _isDragging: boolean = false;
90
- private _didDrag: boolean = false;
91
56
 
92
- setTargetObject(obj: Object3D | null) {
93
- this.targetObject = obj as GameObject;
94
- for (const handler of this._dragHandlers.values()) {
95
- handler.setTargetObject(obj);
96
- }
57
+ private selectStartEventListener: ((controls: DragControls, args: SelectArgs) => void)[] = [];
58
+ private selectEndEventListener: Array<Function> = [];
59
+ private _dragHelper: DragHelper | null = null;
60
+
61
+ constructor() {
62
+ super();
63
+ this.selectStartEventListener = [];
64
+ this.selectEndEventListener = [];
65
+ this._dragDelta = new Vector2();
97
66
  }
98
67
 
99
- awake() {
100
- // initialize all data that may be cloned incorrectly otherwise
101
- this._potentialDragStartEvt = null;
102
- this._dragHandlers = new Map();
103
- this._totalMovement = new Vector3();
104
- this._marker = null;
105
- this._isDragging = false;
106
- this._didDrag = false;
107
- this._dragHelper = null;
108
- this._draggingRigidbodies = [];
68
+
69
+ // TODO: Update DragEventListener code
70
+ addDragEventListener(type: DragEvents, cb: (ctrls: DragControls, args: SelectArgs) => void | Function) {
71
+ switch (type) {
72
+ case DragEvents.SelectStart:
73
+ this.selectStartEventListener.push(cb);
74
+ break;
75
+ case DragEvents.SelectEnd:
76
+ this.selectEndEventListener.push(cb);
77
+ break;
78
+ }
109
79
  }
110
80
 
81
+
82
+
111
83
  start() {
112
84
  this.orbit = GameObject.findObjectOfType(OrbitControls, this.context);
113
- if (!this.gameObject.getComponentInParent(ObjectRaycaster))
85
+ if (!this.gameObject.getComponentInParent(ObjectRaycaster)) {
114
86
  this.gameObject.addNewComponent(ObjectRaycaster);
87
+ }
115
88
  }
116
89
 
90
+ private static lastHovered: Object3D;
91
+ private _draggingRigidbodies: Rigidbody[] = [];
92
+
117
93
  private allowEdit(_obj: Object3D | null = null) {
118
94
  return this.context.connection.allowEditing;
119
95
  }
120
96
 
121
97
  onPointerEnter(evt: PointerEventData) {
122
98
  if (!this.allowEdit(this.gameObject)) return;
123
- if (evt.mode !== "screen") return;
99
+ if (WebXR.IsInWebXR) return;
100
+ // const interactable = GameObject.getComponentInParent(evt.object, Interactable);
101
+ // if (!interactable) return;
124
102
  const dc = GameObject.getComponentInParent(evt.object, DragControls);
125
103
  if (!dc || dc !== this) return;
126
104
  DragControls.lastHovered = evt.object;
@@ -129,121 +107,83 @@
129
107
 
130
108
  onPointerExit(evt: PointerEventData) {
131
109
  if (!this.allowEdit(this.gameObject)) return;
132
- if (evt.mode !== "screen") return;
110
+ if (WebXR.IsInWebXR) return;
133
111
  if (DragControls.lastHovered !== evt.object) return;
112
+ // const interactable = GameObject.getComponentInParent(evt.object, Interactable);
113
+ // if (!interactable) return;
134
114
  this.context.domElement.style.cursor = 'auto';
135
115
  }
136
116
 
117
+ private _waitingForDragStart: PointerEventData | null = null;
118
+
137
119
  onPointerDown(args: PointerEventData) {
138
120
  if (!this.allowEdit(this.gameObject)) return;
139
- if (args.used) return;
140
- DragControls.lastHovered = args.object;
141
-
142
- if (args.button === 0) {
143
- if (this._dragHandlers.size === 0) {
144
- this._didDrag = false;
145
- this._totalMovement.set(0, 0, 0);
146
- this._potentialDragStartEvt = args;
147
- }
148
-
149
- DragControls._active += 1;
150
-
151
- const newDragHandler = new DragPointerHandler(this, this.targetObject || this.gameObject);
152
- this._dragHandlers.set(args.event.space, newDragHandler);
153
-
154
- // We need to turn off OrbitControls immediately, otherwise they still get data for a short moment
155
- // and they don't properly handle being disabled while already processing data (smoothing happens when enabling again)
156
- if (this.orbit) this.orbit.enabled = false;
157
-
158
- newDragHandler.onDragStart(args);
159
-
160
- if (this._dragHandlers.size === 2) {
161
- const iterator = this._dragHandlers.values();
162
- const a = iterator.next().value;
163
- const b = iterator.next().value;
164
- const mtHandler = new MultiTouchDragHandler(this, this.targetObject || this.gameObject, a, b);
165
- this._dragHandlers.set(this.gameObject, mtHandler);
166
-
167
- mtHandler.onDragStart(args);
168
- }
169
-
170
- args.use();
171
- }
121
+ if (WebXR.IsInWebXR) return;
122
+ DragControls._active += 1;
123
+ this._dragDelta.set(0, 0);
124
+ this._didDrag = false;
125
+ // Clone to not modify the original event (and this event is used in the actual onDragStart method)
126
+ this._waitingForDragStart = args.clone();
127
+ args.stopPropagation();
128
+ // disabling pointer controls here already, otherwise we get a few frames of movement event in orbit controls and this will rotate the camera sligthly AFTER drag controls dragging ends.
129
+ if (this.orbit) this.orbit.enabled = false;
172
130
  }
173
131
 
174
132
  onPointerMove(args: PointerEventData) {
175
- if (this._isDragging || this._potentialDragStartEvt !== null) args.use();
133
+ if(this._isDragging || this._waitingForDragStart !== null) args.use();
176
134
  }
177
135
 
178
136
  onPointerUp(args: PointerEventData) {
179
-
180
- if(debug) Gizmos.DrawLabel(args.point ?? this.gameObject.worldPosition, "POINTERUP:" + args.pointerId + ", " + args.button, .03, 3);
181
-
137
+ this._waitingForDragStart = null;
182
138
  if (!this.allowEdit(this.gameObject)) return;
183
- if (args.button !== 0) return;
184
- this._potentialDragStartEvt = null;
139
+ if (DragControls._active > 0)
140
+ DragControls._active -= 1;
141
+ if (WebXR.IsInWebXR) return;
142
+ this.onDragEnd(args);
143
+ args.stopPropagation();
144
+ if (this.orbit) this.orbit.enabled = true;
145
+ }
185
146
 
186
- const handler = this._dragHandlers.get(args.event.space);
187
- const mtHandler = this._dragHandlers.get(this.gameObject) as MultiTouchDragHandler;
188
- if (mtHandler && (mtHandler.handlerA === handler || mtHandler.handlerB === handler)) {
189
- // any of the two handlers has been released, so we can remove the multi-touch handler
190
- this._dragHandlers.delete(this.gameObject);
191
- mtHandler.onDragEnd(args);
192
- }
193
147
 
194
- if (handler) {
195
- if (DragControls._active > 0)
196
- DragControls._active -= 1;
197
-
198
- if (handler.onDragEnd) handler.onDragEnd(args);
199
- this._dragHandlers.delete(args.event.space);
200
-
201
- if (this._dragHandlers.size === 0) {
202
- this.onLastDragEnd(args);
203
- }
204
- args.use();
205
- }
206
-
207
- if (DragControls._active === 0) {
208
- if (this.orbit) this.orbit.enabled = true;
209
- }
210
- }
211
-
212
148
  update(): void {
149
+ if (WebXR.IsInWebXR) return;
213
150
 
214
- for (const handler of this._dragHandlers.values()) {
215
- if (handler.collectMovementInfo) handler.collectMovementInfo();
216
- // TODO this doesn't make sense, we should instead just use the max here
217
- // or even better, each handler can decide on their own how to handle this
218
- if (handler.getTotalMovement) this._totalMovement.add(handler.getTotalMovement());
219
- }
220
-
221
151
  // drag start only after having dragged for some pixels
222
- if (this._potentialDragStartEvt) {
152
+ if (this._waitingForDragStart) {
223
153
  if (!this._didDrag) {
224
- // this is so we can e.g. process clicks without having a drag change the position, e.g. a click to call a method.
225
- // TODO probably needs to be treated differently for spatial (3D motion) and screen (2D pixel motion) drags
226
- if (this._totalMovement.length() > 0.0003)
154
+ // this is so we can e.g. process clicks without having a drag change the position
155
+ // e.g. a click to rotate the object
156
+ const delta = this.context.input.getPointerPositionDelta(0);
157
+ if (delta)
158
+ this._dragDelta.add(delta);
159
+ if (this._dragDelta.length() > 2)
227
160
  this._didDrag = true;
228
161
  else return;
229
162
  }
230
- const args = this._potentialDragStartEvt;
231
- this._potentialDragStartEvt = null;
232
- this.onFirstDragStart(args);
163
+ const args = this._waitingForDragStart;
164
+ this._waitingForDragStart = null;
165
+ this.onDragStart(args);
233
166
  }
234
167
 
235
- for (const handler of this._dragHandlers.values())
236
- if (handler.onDragUpdate) handler.onDragUpdate(this._dragHandlers.size);
237
-
238
- if (this._dragHelper && this._dragHelper.hasSelected)
239
- this.onAnyDragUpdate();
168
+ if (this._dragHelper && this._dragHelper.hasSelected) {
169
+ this.onUpdateDrag();
170
+ }
171
+
172
+ if (this._dragHelper?.hasSelected === false || (this._activePointerId !== undefined && this.context.input.getPointerPressed(this._activePointerId) === false)) {
173
+ this.onDragEnd(null);
174
+ }
240
175
  }
241
176
 
242
- /** Called when the first pointer starts dragging on this object. Not called for subsequent pointers on the same object. */
243
- private onFirstDragStart(evt: PointerEventData) {
177
+ private _isDragging: boolean = false;
178
+ private _marker: UsageMarker | null = null;
179
+ private _dragDelta!: Vector2;
180
+ private _didDrag: boolean = false;
181
+ private _activePointerId?: number;
182
+
183
+ private onDragStart(evt: PointerEventData) {
244
184
  if (!this._dragHelper) {
245
185
  if (this.context.mainCamera)
246
- this._dragHelper = new LegacyDragVisualsHelper(this.context.mainCamera);
186
+ this._dragHelper = new DragHelper(this.context.mainCamera);
247
187
  else
248
188
  return;
249
189
  }
@@ -252,17 +192,46 @@
252
192
  const dc = GameObject.getComponentInParent(evt.object, DragControls);
253
193
  if (!dc || dc !== this) return;
254
194
 
255
- const object = this.targetObject || this.gameObject;
256
195
 
257
- if (!object) return;
196
+ let object: Object3D = evt.object;
258
197
 
198
+ if (this.transformSelf) {
199
+ object = this.gameObject;
200
+ }
201
+
202
+ // raise event
203
+ const args: { selected: Object3D, attached: Object3D | null } = { selected: object, attached: object };
204
+ for (const listener of this.selectStartEventListener) {
205
+ listener(this, args);
206
+ }
207
+
208
+ this._activePointerId = evt.pointerId;
209
+
210
+ if (!args.attached) return;
211
+ if (args.attached !== object) {
212
+ // // if duplicatable changes the object being dragged
213
+ // // should it also change the active drag controls (e.g. if it has a own one)
214
+ // const drag = GameObject.getComponentInParent(args.attached, DragControls);
215
+ // if (drag && drag !== this) {
216
+ // // incredibly ugly code to pass the drag controls event to another drag controls instance
217
+ // // This is necessary since we dont call the onPointerUp events anymore for all objects
218
+ // // that have previously received the onPointerDown event.
219
+ // // NOTE: added the EventSystem.raisedPointerDownEvents array again because of this uglyness here. The code was originally removed in 757fc5e5bafd02aa13d6cd35dd5e8729c841465a and now we're adding it in 8ce886d8344d1abd5ebb89ae3e1fb8d6d47293da
220
+ // this.onDragEnd(null);
221
+ // drag.onPointerDown(evt);
222
+ // evt.object = args.attached;
223
+ // drag.onDragStart(evt);
224
+ // return;
225
+ // }
226
+ }
227
+ object = args.attached;
259
228
  this._isDragging = true;
260
229
  this._dragHelper.setSelected(object, this.context);
261
230
  if (this.orbit) this.orbit.enabled = false;
262
231
 
263
232
  const sync = GameObject.getComponentInChildren(object, SyncedTransform);
264
- if (debug) console.log("DRAG START", sync, object);
265
-
233
+ if (debug)
234
+ console.log("DRAG START", sync, object);
266
235
  if (sync) {
267
236
  sync.fastMode = true;
268
237
  sync?.requestOwnership();
@@ -270,31 +239,30 @@
270
239
 
271
240
  this._marker = GameObject.addNewComponent(object, UsageMarker);
272
241
 
242
+ // console.log(object, this._marker);
243
+
273
244
  this._draggingRigidbodies.length = 0;
274
245
  const rbs = GameObject.getComponentsInChildren(object, Rigidbody);
275
246
  if (rbs)
276
247
  this._draggingRigidbodies.push(...rbs);
248
+
249
+ const l = nameofFactory<IDragEventListener>();
250
+ GameObject.invokeOnChildren(this._dragHelper.selected, l("onDragStart"));
277
251
  }
278
252
 
279
- /** Called each frame as long as any pointer is dragging this object. */
280
- private onAnyDragUpdate() {
253
+ private onUpdateDrag() {
281
254
  if (!this._dragHelper) return;
282
255
  this._dragHelper.showGizmo = this.showGizmo;
256
+ this._dragHelper.useViewAngle = this.useViewAngle;
283
257
 
284
258
  this._dragHelper.onUpdate(this.context);
285
259
  for (const rb of this._draggingRigidbodies) {
286
260
  rb.wakeUp();
287
261
  rb.resetVelocities();
288
- rb.resetForcesAndTorques();
289
262
  }
290
-
291
- const object = this.targetObject || this.gameObject;
292
-
293
- InstancingUtil.markDirty(object);
294
263
  }
295
264
 
296
- /** Called when the last pointer has been removed from this object. */
297
- private onLastDragEnd(evt: PointerEventData | null) {
265
+ private onDragEnd(evt: PointerEventData | null) {
298
266
  if (!this || !this._isDragging) return;
299
267
  this._isDragging = false;
300
268
  if (!this._dragHelper) return;
@@ -303,7 +271,8 @@
303
271
  }
304
272
  this._draggingRigidbodies.length = 0;
305
273
  const selected = this._dragHelper.selected;
306
- if (debug) console.log("DRAG END", selected, selected?.visible)
274
+ if (debug)
275
+ console.log("DRAG END", selected, selected?.visible)
307
276
  this._dragHelper.setSelected(null, this.context);
308
277
  if (this.orbit) this.orbit.enabled = true;
309
278
  if (evt?.object) {
@@ -313,751 +282,23 @@
313
282
  // sync?.requestOwnership();
314
283
  }
315
284
  }
316
- if (this._marker)
285
+ if (this._marker) {
317
286
  this._marker.destroy();
318
- }
319
- }
320
-
321
- /** Handles two touch points affecting one object. Allows movement, scale and rotation of objects. */
322
- class MultiTouchDragHandler implements IDragHandler {
323
-
324
- handlerA: DragPointerHandler;
325
- handlerB: DragPointerHandler;
326
-
327
- private context: Context;
328
- private settings: DragControls;
329
- private gameObject: GameObject;
330
- private _handlerAAttachmentPoint: Vector3 = new Vector3();
331
- private _handlerBAttachmentPoint: Vector3 = new Vector3();
332
-
333
- private _followObject: GameObject;
334
- private _manipulatorObject: GameObject;
335
- private _deviceMode!: XRTargetRayMode;
336
- private _followObjectStartWorldQuaternion: Quaternion = new Quaternion();
337
-
338
- constructor(dragControls: DragControls, gameObject: GameObject, pointerA: DragPointerHandler, pointerB: DragPointerHandler) {
339
- this.context = dragControls.context;
340
- this.settings = dragControls;
341
- this.gameObject = gameObject;
342
- this.handlerA = pointerA;
343
- this.handlerB = pointerB;
344
-
345
- this._followObject = new Object3D() as GameObject;
346
- this._manipulatorObject = new Object3D() as GameObject;
347
-
348
- this.context.scene.add(this._manipulatorObject);
349
-
350
- const rig = NeedleXRSession.active?.rig?.gameObject;
351
-
352
- if (!this.handlerA || !this.handlerB || !this.handlerA.hitPointInLocalSpace || !this.handlerB.hitPointInLocalSpace) {
353
- console.error("Invalid: MultiTouchDragHandler needs two valid DragPointerHandlers with hitPointInLocalSpace set.");
354
- return;
355
287
  }
356
-
357
- this._tempVec1.copy(this.handlerA.hitPointInLocalSpace);
358
- this._tempVec2.copy(this.handlerB.hitPointInLocalSpace);
359
- this.gameObject.localToWorld(this._tempVec1);
360
- this.gameObject.localToWorld(this._tempVec2);
361
- if (rig) {
362
- rig.worldToLocal(this._tempVec1);
363
- rig.worldToLocal(this._tempVec2);
288
+ // raise event
289
+ for (const listener of this.selectEndEventListener) {
290
+ listener(this);
364
291
  }
365
- this._initialDistance = this._tempVec1.distanceTo(this._tempVec2);
366
-
367
- if (this._initialDistance < 0.02) {
368
- if (debug) {
369