@needle-tools/engine 2.62.1-pre → 2.63.0-pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/needle-engine.js +9983 -9692
  3. package/dist/needle-engine.umd.cjs +306 -223
  4. package/lib/engine/api.d.ts +1 -0
  5. package/lib/engine/api.js +1 -0
  6. package/lib/engine/api.js.map +1 -1
  7. package/lib/engine/codegen/license.d.ts +1 -0
  8. package/lib/engine/codegen/license.js +2 -0
  9. package/lib/engine/codegen/license.js.map +1 -0
  10. package/lib/engine/engine.js +0 -2
  11. package/lib/engine/engine.js.map +1 -1
  12. package/lib/engine/engine_camera.d.ts +4 -0
  13. package/lib/engine/engine_camera.js +13 -0
  14. package/lib/engine/engine_camera.js.map +1 -0
  15. package/lib/engine/engine_element.d.ts +1 -0
  16. package/lib/engine/engine_element.js +18 -2
  17. package/lib/engine/engine_element.js.map +1 -1
  18. package/lib/engine/engine_element_loading.js +28 -4
  19. package/lib/engine/engine_element_loading.js.map +1 -1
  20. package/lib/engine/engine_input.d.ts +2 -0
  21. package/lib/engine/engine_input.js +14 -0
  22. package/lib/engine/engine_input.js.map +1 -1
  23. package/lib/engine/engine_license.d.ts +1 -0
  24. package/lib/engine/engine_license.js +199 -0
  25. package/lib/engine/engine_license.js.map +1 -0
  26. package/lib/engine/engine_physics.d.ts +3 -0
  27. package/lib/engine/engine_physics.js +13 -2
  28. package/lib/engine/engine_physics.js.map +1 -1
  29. package/lib/engine/engine_setup.js +1 -1
  30. package/lib/engine/engine_setup.js.map +1 -1
  31. package/lib/engine/engine_types.d.ts +4 -0
  32. package/lib/engine/engine_types.js.map +1 -1
  33. package/lib/engine/extensions/extension_utils.js +1 -1
  34. package/lib/engine/extensions/extension_utils.js.map +1 -1
  35. package/lib/engine/js-extensions/Camera.d.ts +1 -0
  36. package/lib/engine/js-extensions/Camera.js +37 -0
  37. package/lib/engine/js-extensions/Camera.js.map +1 -0
  38. package/lib/engine/js-extensions/Layers.js +1 -0
  39. package/lib/engine/js-extensions/Layers.js.map +1 -1
  40. package/lib/engine/js-extensions/index.d.ts +2 -0
  41. package/lib/engine/js-extensions/index.js +3 -0
  42. package/lib/engine/js-extensions/index.js.map +1 -0
  43. package/lib/engine-components/CameraUtils.d.ts +1 -3
  44. package/lib/engine-components/CameraUtils.js +34 -17
  45. package/lib/engine-components/CameraUtils.js.map +1 -1
  46. package/lib/engine-components/Light.d.ts +4 -1
  47. package/lib/engine-components/Light.js +17 -2
  48. package/lib/engine-components/Light.js.map +1 -1
  49. package/lib/engine-components/OrbitControls.d.ts +4 -1
  50. package/lib/engine-components/OrbitControls.js +13 -2
  51. package/lib/engine-components/OrbitControls.js.map +1 -1
  52. package/lib/engine-components/ScreenCapture.d.ts +2 -2
  53. package/lib/engine-components/ScreenCapture.js +3 -1
  54. package/lib/engine-components/ScreenCapture.js.map +1 -1
  55. package/lib/engine-components/VideoPlayer.d.ts +2 -1
  56. package/lib/engine-components/VideoPlayer.js +9 -6
  57. package/lib/engine-components/VideoPlayer.js.map +1 -1
  58. package/lib/engine-components/timeline/TimelineTracks.js +7 -1
  59. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  60. package/lib/engine-components/ui/BaseUIComponent.d.ts +3 -0
  61. package/lib/engine-components/ui/BaseUIComponent.js +20 -10
  62. package/lib/engine-components/ui/BaseUIComponent.js.map +1 -1
  63. package/lib/engine-components/ui/Button.js +7 -3
  64. package/lib/engine-components/ui/Button.js.map +1 -1
  65. package/lib/engine-components/ui/EventSystem.js +21 -42
  66. package/lib/engine-components/ui/EventSystem.js.map +1 -1
  67. package/lib/engine-components/ui/Graphic.d.ts +1 -0
  68. package/lib/engine-components/ui/Graphic.js +7 -0
  69. package/lib/engine-components/ui/Graphic.js.map +1 -1
  70. package/lib/engine-components/ui/Interfaces.d.ts +2 -1
  71. package/lib/engine-components/ui/RaycastUtils.js +2 -0
  72. package/lib/engine-components/ui/RaycastUtils.js.map +1 -1
  73. package/lib/engine-components/ui/Text.js +10 -1
  74. package/lib/engine-components/ui/Text.js.map +1 -1
  75. package/lib/needle-engine.d.ts +2 -0
  76. package/lib/needle-engine.js +2 -2
  77. package/lib/needle-engine.js.map +1 -1
  78. package/lib/tsconfig.tsbuildinfo +1 -1
  79. package/package.json +2 -2
  80. package/src/engine/api.ts +2 -1
  81. package/src/engine/assets/logo.svg +1 -0
  82. package/src/engine/codegen/license.js +1 -0
  83. package/src/engine/engine.ts +0 -3
  84. package/src/engine/engine_camera.ts +18 -0
  85. package/src/engine/engine_element.ts +18 -2
  86. package/src/engine/engine_element_loading.ts +33 -8
  87. package/src/engine/engine_input.ts +17 -5
  88. package/src/engine/engine_license.ts +216 -0
  89. package/src/engine/engine_physics.ts +16 -2
  90. package/src/engine/engine_setup.ts +2 -1
  91. package/src/engine/engine_types.ts +9 -4
  92. package/src/engine/extensions/extension_utils.ts +1 -1
  93. package/src/engine/js-extensions/Camera.ts +35 -0
  94. package/src/engine/js-extensions/Layers.ts +2 -1
  95. package/src/engine/js-extensions/index.ts +2 -0
  96. package/src/engine-components/CameraUtils.ts +42 -20
  97. package/src/engine-components/Light.ts +16 -3
  98. package/src/engine-components/OrbitControls.ts +18 -6
  99. package/src/engine-components/ScreenCapture.ts +3 -2
  100. package/src/engine-components/VideoPlayer.ts +10 -6
  101. package/src/engine-components/timeline/TimelineTracks.ts +9 -3
  102. package/src/engine-components/ui/BaseUIComponent.ts +21 -11
  103. package/src/engine-components/ui/Button.ts +7 -3
  104. package/src/engine-components/ui/EventSystem.ts +20 -42
  105. package/src/engine-components/ui/Graphic.ts +7 -0
  106. package/src/engine-components/ui/Interfaces.ts +3 -1
  107. package/src/engine-components/ui/RaycastUtils.ts +2 -1
  108. package/src/engine-components/ui/Text.ts +11 -2
  109. package/src/needle-engine.ts +6 -2
@@ -1,32 +1,54 @@
1
1
  import { OrbitControls } from "./OrbitControls";
2
- import { Camera } from "./Camera";
3
2
  import { addNewComponent } from "../engine/engine_components";
4
- import { Color, Object3D, Scene, Vector3 } from "three";
5
- import { ICamera, SourceIdentifier } from "../engine/engine_types";
6
- import { lookAtInverse } from "../engine/engine_three_utils";
3
+ import { Object3D } from "three";
4
+ import { ICamera } from "../engine/engine_types";
7
5
  import { RGBAColor } from "./js-extensions/RGBAColor";
8
6
  import { ContextEvent, ContextRegistry } from "../engine/engine_context_registry";
9
-
7
+ import { getCameraController } from "../engine/engine_camera";
8
+ import { Camera } from "./Camera";
9
+ import { EngineElement } from "../engine/engine_element";
10
10
 
11
11
  ContextRegistry.registerCallback(ContextEvent.MissingCamera, (evt) => {
12
- createCameraWithOrbitControl(evt.context.scene, "unknown");
13
- });
12
+ const scene = evt.context.scene;
13
+ const srcId = "unknown";
14
14
 
15
+ const cameraObject = new Object3D();
16
+ scene.add(cameraObject);
15
17
 
16
- export function createCameraWithOrbitControl(scene: Scene, source: SourceIdentifier): ICamera {
17
- const srcId = source;
18
- const go = new Object3D();
19
- scene.add(go);
20
18
  const camInstance = new Camera();
21
- const cam = addNewComponent(go, camInstance, true) as ICamera
19
+ const cam = addNewComponent(cameraObject, camInstance, true) as ICamera
22
20
  cam.sourceId = srcId;
23
21
  cam.clearFlags = 2;
24
22
  cam.backgroundColor = new RGBAColor(0.5, 0.5, 0.5, 1);
25
- const orbit = addNewComponent(go, new OrbitControls(), false) as OrbitControls;
26
- orbit.sourceId = srcId;
27
- go.position.x = -2;
28
- go.position.y = 2;
29
- go.position.z = 2;
30
- lookAtInverse(go, new Vector3(0, 0, 0));
31
- return cam as Camera;
32
- }
23
+
24
+ cameraObject.position.x = -2;
25
+ cameraObject.position.y = 2;
26
+ cameraObject.position.z = 2;
27
+ return cam;
28
+ });
29
+
30
+ ContextRegistry.registerCallback(ContextEvent.ContextCreated, (evt) => {
31
+ if (!evt.context.mainCamera) return;
32
+
33
+ // check if the <needle-engine controls> is not set to false
34
+ const engineElement = evt.context.domElement as EngineElement
35
+
36
+ if (engineElement?.cameraControls === true) {
37
+
38
+ // Check if something else already acts as a camera controller
39
+ const existing = getCameraController(evt.context.mainCamera);
40
+ if (existing?.isCameraController === true) {
41
+ return;
42
+ }
43
+
44
+ const cam = evt.context.mainCameraComponent;
45
+ const cameraObject = cam?.gameObject;
46
+ if (cameraObject) {
47
+ const orbit = addNewComponent(cameraObject, new OrbitControls(), false) as OrbitControls;
48
+ orbit.sourceId = "unknown";
49
+ }
50
+ else {
51
+ console.warn("Missing camera object, can not add orbit controls")
52
+ }
53
+ }
54
+ })
@@ -95,7 +95,17 @@ export class Light extends Behaviour implements ILight {
95
95
  public innerSpotAngle: number = 1;
96
96
 
97
97
  @serializable(Color)
98
- public color: THREE.Color = new THREE.Color(0xffffff);
98
+ set color(val: Color) {
99
+ this._color = val;
100
+ if (this.light !== undefined) {
101
+ this.light.color = val;
102
+ }
103
+ }
104
+ get color(): Color {
105
+ if (this.light) return this.light.color;
106
+ return this._color;
107
+ }
108
+ public _color: THREE.Color = new THREE.Color(0xffffff);
99
109
 
100
110
  @serializable()
101
111
  set shadowNearPlane(val: number) {
@@ -242,13 +252,14 @@ export class Light extends Behaviour implements ILight {
242
252
 
243
253
  awake() {
244
254
  this.color = new THREE.Color(this.color ?? 0xffffff);
245
- if(debug) console.log(this.name, this);
255
+ if (debug) console.log(this.name, this);
246
256
  }
247
257
 
248
258
  onEnable(): void {
249
259
  this.createLight();
250
260
  if (this.isBaked) return;
251
261
  else if (this.light) {
262
+ this.light.visible = true;
252
263
  if (this.selfIsLight) {
253
264
  // nothing to do
254
265
  }
@@ -257,12 +268,14 @@ export class Light extends Behaviour implements ILight {
257
268
  }
258
269
  if (this.type === LightType.Directional)
259
270
  this.startCoroutine(this.updateMainLightRoutine(), FrameEvent.LateUpdate);
260
-
261
271
  this._webXRStartedListener = WebXR.addEventListener(WebXREvent.XRStarted, this.onWebXRStarted.bind(this));
262
272
  this._webXREndedListener = WebXR.addEventListener(WebXREvent.XRStopped, this.onWebXREnded.bind(this));
263
273
  }
264
274
 
265
275
  onDisable() {
276
+ if (this.light) {
277
+ this.light.visible = false;
278
+ }
266
279
  WebXR.removeEventListener(WebXREvent.XRStarted, this._webXRStartedListener);
267
280
  WebXR.removeEventListener(WebXREvent.XRStopped, this._webXREndedListener);
268
281
  }
@@ -6,17 +6,23 @@ import { RaycastOptions } from "../engine/engine_physics";
6
6
  import { serializable } from "../engine/engine_serialization_decorator";
7
7
  import { getParam, isMobileDevice } from "../engine/engine_utils";
8
8
 
9
- import { Box3, Object3D, PerspectiveCamera, Vector2, Vector3 } from "three";
9
+ import { Camera as ThreeCamera, Box3, Object3D, PerspectiveCamera, Vector2, Vector3 } from "three";
10
10
  import { OrbitControls as ThreeOrbitControls } from "three/examples/jsm/controls/OrbitControls";
11
11
  import { EventSystem, EventSystemEvents } from "./ui/EventSystem";
12
- import { transformWithEsbuild } from "vite";
12
+ import { ICameraController } from "../engine/engine_types";
13
+ import { setCameraController } from "../engine/engine_camera";
13
14
 
14
15
  const freeCam = getParam("freecam");
15
16
 
16
17
  const disabledKeys = { LEFT: "", UP: "", RIGHT: "", BOTTOM: "" };
17
18
  let defaultKeys: any = undefined;
18
19
 
19
- export class OrbitControls extends Behaviour {
20
+ export class OrbitControls extends Behaviour implements ICameraController {
21
+
22
+ get isCameraController(): boolean {
23
+ return true;
24
+ }
25
+
20
26
  public get controls() {
21
27
  return this._controls;
22
28
  }
@@ -64,6 +70,7 @@ export class OrbitControls extends Behaviour {
64
70
 
65
71
  private _eventSystem?: EventSystem;
66
72
  private _afterHandleInputFn?: any;
73
+ private _camera : Camera | null = null;
67
74
 
68
75
  targetElement: HTMLElement | null = null;
69
76
 
@@ -98,8 +105,10 @@ export class OrbitControls extends Behaviour {
98
105
 
99
106
  onEnable() {
100
107
  this._enableTime = this.context.time.time;
101
- const camGo = GameObject.getComponent(this.gameObject, Camera);
102
- const cam = camGo?.cam;
108
+ const cameraComponent = GameObject.getComponent(this.gameObject, Camera);
109
+ this._camera = cameraComponent;
110
+ const cam = cameraComponent?.cam;
111
+ if (cam) setCameraController(cam, this, true);
103
112
  if (!this._controls) {
104
113
  console.assert(cam !== null && cam !== undefined, "Missing camera", this);
105
114
  if (cam)
@@ -153,6 +162,9 @@ export class OrbitControls extends Behaviour {
153
162
  }
154
163
 
155
164
  onDisable() {
165
+ if (this._camera?.cam) {
166
+ setCameraController(this._camera.cam, this, false);
167
+ }
156
168
  if (this._controls) {
157
169
  this._controls.enabled = false;
158
170
  this._controls.autoRotate = false;
@@ -160,7 +172,7 @@ export class OrbitControls extends Behaviour {
160
172
  }
161
173
  }
162
174
 
163
- private _shouldDisable : boolean = false;
175
+ private _shouldDisable: boolean = false;
164
176
  private afterHandleInput() {
165
177
  if (this._controls && this._eventSystem) {
166
178
  this._shouldDisable = this._eventSystem.hasActiveUI;
@@ -5,7 +5,7 @@ import { Context } from "../engine/engine_setup";
5
5
  import { RoomEvents } from "../engine/engine_networking";
6
6
  import { UserJoinedOrLeftRoomModel } from "../engine/engine_networking";
7
7
  import { serializable } from "../engine/engine_serialization";
8
- import { IPointerClickHandler } from "./ui/PointerEvents";
8
+ import { IPointerClickHandler, PointerEventData } from "./ui/PointerEvents";
9
9
  import { EventDispatcher } from "three";
10
10
  import { AudioSource } from "./AudioSource";
11
11
  import { getParam } from "../engine/engine_utils";
@@ -39,7 +39,8 @@ declare type ScreenCaptureOptions = {
39
39
 
40
40
  export class ScreenCapture extends Behaviour implements IPointerClickHandler {
41
41
 
42
- onPointerClick() {
42
+ onPointerClick(evt : PointerEventData) {
43
+ if(evt && evt.pointerId !== 0) return;
43
44
  if(this.context.connection.isInRoom === false) return;
44
45
  if (this.isReceiving) {
45
46
  if (this.videoPlayer)
@@ -122,6 +122,10 @@ export class VideoPlayer extends Behaviour {
122
122
  }
123
123
  }
124
124
 
125
+ get videoMaterial() {
126
+ return this._videoMaterial;
127
+ }
128
+
125
129
  get videoTexture() {
126
130
  return this._videoTexture;
127
131
  }
@@ -140,7 +144,7 @@ export class VideoPlayer extends Behaviour {
140
144
 
141
145
  private _videoElement: HTMLVideoElement | null = null;
142
146
  private _videoTexture: THREE.VideoTexture | null = null;
143
- private videoMaterial: Material | null = null;
147
+ private _videoMaterial: Material | null = null;
144
148
 
145
149
  private _isPlaying: boolean = false;
146
150
  private wasPlaying: boolean = false;
@@ -355,18 +359,18 @@ export class VideoPlayer extends Behaviour {
355
359
  if (mat) {
356
360
  this._targetObjects.push(target);
357
361
 
358
- if (mat !== this.videoMaterial) {
359
- this.videoMaterial = mat.clone();
360
- target["material"] = this.videoMaterial;
362
+ if (mat !== this._videoMaterial) {
363
+ this._videoMaterial = mat.clone();
364
+ target["material"] = this._videoMaterial;
361
365
  }
362
366
 
363
367
  if (!this.targetMaterialProperty) {
364
- (this.videoMaterial as any).map = this._videoTexture;
368
+ (this._videoMaterial as any).map = this._videoTexture;
365
369
  }
366
370
  else {
367
371
  switch (this.targetMaterialProperty) {
368
372
  default:
369
- (this.videoMaterial as any).map = this._videoTexture;
373
+ (this._videoMaterial as any).map = this._videoTexture;
370
374
  break;
371
375
  // doesnt render:
372
376
  // case "emissiveTexture":
@@ -276,7 +276,7 @@ export class AnimationTrackHandler extends TrackHandler {
276
276
  const isInTimeRange = time >= model.start && time <= model.end;
277
277
  const postExtrapolation: Models.ClipExtrapolation = model.postExtrapolationMode;
278
278
  let isActive = isInTimeRange;
279
- if (!isActive && !didPostExtrapolate && model.end < time && model.postExtrapolationMode !== Models.ClipExtrapolation.None) {
279
+ if (!isActive && !didPostExtrapolate && model.end < time && postExtrapolation !== Models.ClipExtrapolation.None) {
280
280
  const nextClip = i < this.clips.length - 1 ? this.models[i + 1] : null;
281
281
  // use post extrapolate if its the last clip of the next clip has not yet started
282
282
  if (!nextClip || nextClip.start > time) {
@@ -284,6 +284,12 @@ export class AnimationTrackHandler extends TrackHandler {
284
284
  didPostExtrapolate = true;
285
285
  }
286
286
  }
287
+ const preExtrapolation: Models.ClipExtrapolation = model.preExtrapolationMode;
288
+ if (i == 0 && !isActive && !didPostExtrapolate && model.start > time && preExtrapolation !== Models.ClipExtrapolation.None) {
289
+ isActive = true;
290
+ if (preExtrapolation !== Models.ClipExtrapolation.Hold)
291
+ time += model.start;
292
+ }
287
293
  if (isActive) {
288
294
  // const clip = this.clips[i];
289
295
  let weight = 1;
@@ -316,9 +322,9 @@ export class AnimationTrackHandler extends TrackHandler {
316
322
  }
317
323
  }
318
324
 
319
- if(model.reversed === true) action.time = action.getClip().duration - t;
325
+ if (model.reversed === true) action.time = action.getClip().duration - t;
320
326
  else action.time = t;
321
-
327
+
322
328
  action.timeScale = 0;
323
329
  const effectiveWeight = weight * this.director.weight;
324
330
  action.weight = effectiveWeight;
@@ -53,6 +53,13 @@ export class BaseUIComponent extends Behaviour {
53
53
  // private _intermediate?: Object3D;
54
54
  protected _parentComponent?: BaseUIComponent | null = undefined;
55
55
 
56
+ __internalNewInstanceCreated() {
57
+ super.__internalNewInstanceCreated();
58
+ this.shadowComponent = null;
59
+ this._root = undefined;
60
+ this._parentComponent = undefined;
61
+ }
62
+
56
63
  onEnable() {
57
64
  super.onEnable();
58
65
  }
@@ -79,17 +86,7 @@ export class BaseUIComponent extends Behaviour {
79
86
  // this.gameObject.layers.set(2)
80
87
 
81
88
 
82
- // TODO: only traverse our own hierarchy, we can stop if we find another owner
83
- container.traverse(c => {
84
- if (c[$shadowDomOwner] === undefined) {
85
- c[$shadowDomOwner] = this;
86
- }
87
-
88
- // // this makes text not render anymore when enabled again
89
- // if (raycastTarget === false) {
90
- // c.layers.set(2);
91
- // }
92
- });
89
+ this.setShadowComponentOwner(container);
93
90
 
94
91
  let needsUpdate = false;
95
92
 
@@ -136,6 +133,19 @@ export class BaseUIComponent extends Behaviour {
136
133
  // })
137
134
  }
138
135
 
136
+ protected setShadowComponentOwner(current: Object3D | null | undefined) {
137
+ if (!current) return;
138
+ // TODO: only traverse our own hierarchy, we can stop if we find another owner
139
+ if (current[$shadowDomOwner] === undefined || current[$shadowDomOwner] === this) {
140
+ current[$shadowDomOwner] = this;
141
+ if (current.children) {
142
+ for (const ch of current.children) {
143
+ this.setShadowComponentOwner(ch);
144
+ }
145
+ }
146
+ }
147
+ }
148
+
139
149
  private traverseOwnedShadowComponents(current: Object3D, owner: any, callback: (obj: any) => void) {
140
150
  if (!current) return;
141
151
  if (current[$shadowDomOwner] === owner) {
@@ -6,6 +6,7 @@ import { RGBAColor } from "../js-extensions/RGBAColor";
6
6
  import { serializable } from "../../engine/engine_serialization_decorator";
7
7
  import { Animator } from "../Animator";
8
8
  import { getParam } from "../../engine/engine_utils";
9
+ import { showBalloonMessage } from "../../engine/debug";
9
10
 
10
11
  const debug = getParam("debugbutton");
11
12
 
@@ -102,7 +103,7 @@ export class Button extends Behaviour implements IPointerEventHandler {
102
103
 
103
104
  onPointerUp(_) {
104
105
  if (debug)
105
- console.log("Button Down", this.animationTriggers?.highlightedTrigger, this.animator);
106
+ console.warn("Button Up", this.animationTriggers?.highlightedTrigger, this.animator, this._isHovered);
106
107
  if (this.transition == Transition.Animation && this.animationTriggers && this.animator) {
107
108
  this.animator.SetTrigger(this._isHovered ? this.animationTriggers.highlightedTrigger : this.animationTriggers.normalTrigger);
108
109
  }
@@ -112,8 +113,10 @@ export class Button extends Behaviour implements IPointerEventHandler {
112
113
  }
113
114
 
114
115
  onPointerClick(_args: PointerEventData) {
115
- if (debug)
116
- console.trace("Button Click", this.onClick);
116
+ if (debug) {
117
+ console.warn("Button Click", this.onClick);
118
+ showBalloonMessage("CLICKED button " + this.name + " at " + this.context.time.frameCount);
119
+ }
117
120
  this.onClick?.invoke();
118
121
  }
119
122
 
@@ -153,6 +156,7 @@ export class Button extends Behaviour implements IPointerEventHandler {
153
156
  super.awake();
154
157
  if (debug)
155
158
  console.log(this);
159
+ this._isInit = false;
156
160
  this.init();
157
161
  }
158
162
 
@@ -13,6 +13,7 @@ import { ICanvasGroup, IGraphic } from "./Interfaces";
13
13
  import { getParam } from "../../engine/engine_utils";
14
14
  import { UIRaycastUtils } from "./RaycastUtils";
15
15
  import { $shadowDomOwner } from "./BaseUIComponent";
16
+ import { showBalloonMessage, showBalloonWarning } from "../../engine/debug";
16
17
 
17
18
  const debug = getParam("debugeventsystem");
18
19
 
@@ -248,6 +249,8 @@ export class EventSystem extends Behaviour {
248
249
  args: args,
249
250
  hasActiveUI: this.currentActiveMeshUIComponents.length > 0,
250
251
  }
252
+ if(debug && args.isClicked)
253
+ showBalloonMessage("EventSystem: " + args.pointerId + " - " + this.context.time.frame + " - Up:" + args.isUp + ", Down:" + args.isDown)
251
254
  this.dispatchEvent(new CustomEvent(EventSystemEvents.BeforeHandleInput, { detail: evt }))
252
255
  this.handleIntersections(hits, args);
253
256
  this.dispatchEvent(new CustomEvent(EventSystemEvents.AfterHandleInput, { detail: evt }))
@@ -261,11 +264,11 @@ export class EventSystem extends Behaviour {
261
264
  else return;
262
265
 
263
266
  if (this.lastPointerEvent.isUp) {
264
- for (const obj of this.raisedPointerDownEvents) {
265
- if (obj.onPointerUp) {
266
- obj.onPointerUp(this.lastPointerEvent);
267
- }
268
- }
267
+ // for (const obj of this.raisedPointerDownEvents) {
268
+ // if (obj.onPointerUp) {
269
+ // obj.onPointerUp(this.lastPointerEvent);
270
+ // }
271
+ // }
269
272
  this.raisedPointerDownEvents.length = 0;
270
273
  this.raisedPointerDownObjects.length = 0;
271
274
  }
@@ -398,8 +401,8 @@ export class EventSystem extends Behaviour {
398
401
  }
399
402
  }
400
403
 
401
- // if (clicked)
402
- // console.log(this.context.time.frame, object);
404
+ if (clicked && debug)
405
+ console.log(this.context.time.frame, object);
403
406
  this.objectsHoveredThisFrame.push(object);
404
407
 
405
408
  if (canvasGroup === null || canvasGroup.interactable) {
@@ -488,7 +491,7 @@ export class EventSystem extends Behaviour {
488
491
  class MeshUIHelper {
489
492
 
490
493
  private static lastSelected: THREE.Object3D | null = null;
491
- private static lastUpdateFrame: { context: Context, frame: number }[] = [];
494
+ private static lastUpdateFrame: { context: Context, frame: number, nextUpdate: number }[] = [];
492
495
  private static needsUpdate: boolean = false;
493
496
 
494
497
  static markDirty() {
@@ -496,11 +499,15 @@ class MeshUIHelper {
496
499
  }
497
500
 
498
501
  static update(threeMeshUI: any, context: Context) {
502
+ const currentFrame = context.time.frameCount;
499
503
  for (const lu of this.lastUpdateFrame) {
500
504
  if (lu.context === context) {
501
- if (context.time.frameCount === lu.frame) return;
502
- lu.frame = context.time.frameCount;
503
- if (this.needsUpdate || context.time.frameCount < 1) {
505
+ if (currentFrame === lu.frame) return;
506
+ lu.frame = currentFrame;
507
+ let shouldUpdate = this.needsUpdate || currentFrame < 1;
508
+ if(lu.nextUpdate === context.time.frameCount) shouldUpdate = true;
509
+ if(this.needsUpdate) lu.nextUpdate = currentFrame + 3;
510
+ if (shouldUpdate) {
504
511
  if (debug)
505
512
  console.log("Update threemeshui");
506
513
  this.needsUpdate = false;
@@ -509,11 +516,11 @@ class MeshUIHelper {
509
516
  return;
510
517
  }
511
518
  }
512
- this.lastUpdateFrame = [{ context, frame: context.time.frameCount }];
519
+ this.lastUpdateFrame = [{ context, frame: currentFrame, nextUpdate: currentFrame }];
513
520
  threeMeshUI.update();
514
521
  }
515
522
 
516
- static updateState(intersect: THREE.Object3D, selectState: boolean): ThreeMeshUI.Block | null {
523
+ static updateState(intersect: THREE.Object3D, _selectState: boolean): ThreeMeshUI.Block | null {
517
524
  let foundBlock: ThreeMeshUI.Block | null = null;
518
525
 
519
526
  if (intersect) {
@@ -522,30 +529,10 @@ class MeshUIHelper {
522
529
  if (foundBlock && foundBlock !== this.lastSelected) {
523
530
  const interactable = foundBlock["interactable"];
524
531
  if (interactable === false) return null;
525
- if (selectState) {
526
- this.lastSelected = foundBlock;
527
- //@ts-ignore
528
- if (foundBlock.states["pressed"])
529
- //@ts-ignore
530
- foundBlock.setState("pressed");
531
-
532
- } else {
533
- //@ts-ignore
534
- if (foundBlock.states["hovered"])
535
- //@ts-ignore
536
- foundBlock.setState("hovered");
537
- };
538
532
  this.needsUpdate = true;
539
533
  }
540
534
  }
541
535
 
542
- // Update non-targeted buttons state
543
- // MeshUIBaseComponent.objectsWithState.forEach((obj) => {
544
- // if ((!intersect || obj !== foundBlock) && obj.isUI) {
545
- // obj.setState('idle');
546
- // };
547
- // });
548
-
549
536
  return foundBlock;
550
537
  }
551
538
 
@@ -558,15 +545,6 @@ class MeshUIHelper {
558
545
 
559
546
  static resetState(obj: any) {
560
547
  if (!obj) return;
561
- const interactable = obj["interactable"];
562
- if (interactable === false) {
563
- if (obj.states["disabled"])
564
- obj.setState("disabled");
565
- }
566
- else if (obj === this.lastSelected && obj.states["selected"]) {
567
- obj.setState("selected");
568
- }
569
- else obj.setState('normal');
570
548
  this.needsUpdate = true;
571
549
  }
572
550
 
@@ -51,6 +51,13 @@ export class Graphic extends BaseUIComponent implements IGraphic {
51
51
  return this._rect!;
52
52
  }
53
53
 
54
+ __internalNewInstanceCreated(): void {
55
+ super.__internalNewInstanceCreated();
56
+ this._rect = null;
57
+ this.uiObject = null;
58
+ if(this._color) this._color = this._color.clone();
59
+ }
60
+
54
61
  setState(state: string) {
55
62
  this.makePanel();
56
63
  if (this.uiObject) {
@@ -1,10 +1,12 @@
1
+ import { IComponent } from "../../engine/engine_types";
2
+
1
3
  export interface ICanvasGroup {
2
4
  get isCanvasGroup() : boolean;
3
5
  blocksRaycasts: boolean;
4
6
  interactable: boolean;
5
7
  }
6
8
 
7
- export interface IGraphic {
9
+ export interface IGraphic extends IComponent {
8
10
  get isGraphic() : boolean;
9
11
  raycastTarget: boolean;
10
12
  }
@@ -33,7 +33,7 @@ export class UIRaycastUtils {
33
33
  if (canvasGroup.interactable === false) return false;
34
34
  }
35
35
  // handle Graphic Raycast target
36
- const graphic = foreachComponent(obj, c => {
36
+ const graphic : IGraphic | undefined = foreachComponent(obj, c => {
37
37
  if ((c as unknown as IGraphic).isGraphic === true) return c;
38
38
  return undefined;
39
39
  }, false);
@@ -43,6 +43,7 @@ export class UIRaycastUtils {
43
43
  out.graphic = graphic as IGraphic;
44
44
  }
45
45
  if (graphic?.raycastTarget === false) return false;
46
+ if (graphic?.layer === 2) return false;
46
47
 
47
48
  return true;
48
49
  }
@@ -160,7 +160,7 @@ export class Text extends Graphic {
160
160
  private _text: string = "";
161
161
  private _fontSize: number = 12;
162
162
  private _textMeshUi: Array<ThreeMeshUI.Text> | null = null;
163
- private _textContainer: any = null;
163
+ private _textContainer: ThreeMeshUI.Block | null = null;
164
164
 
165
165
  private getTextOpts(): object {
166
166
  let fontSize = this.fontSize;
@@ -185,7 +185,16 @@ export class Text extends Graphic {
185
185
  this._didHandleTextRenderOnTop = false;
186
186
  if (this.uiObject) {
187
187
  // @ts-ignore
188
- this.uiObject.onAfterUpdate = this.updateWidth.bind(this);
188
+ this.uiObject.onAfterUpdate = () => {
189
+ this.updateWidth();
190
+ // We need to update the shadow owner when the text updates
191
+ // because once the font has loaded we get new children (a new mesh)
192
+ // which is the text, it needs to be linked back to this component
193
+ // to be properly handled by the EventSystem
194
+ // since the EventSystem looks for shadow component owners to handle events
195
+ this.setShadowComponentOwner(this.uiObject);
196
+ this.markDirty();
197
+ };
189
198
  }
190
199
 
191
200
  setTimeout(()=> this.markDirty(), 10);
@@ -3,8 +3,8 @@ makeErrorsVisibleForDevelopment();
3
3
 
4
4
  import "./engine/engine_element";
5
5
  import "./engine/engine_setup";
6
- // import "./engine/engine_mainloop";
7
- // import "./engine-components/DomOverlay";
6
+
7
+ import "./engine-components/CameraUtils"
8
8
 
9
9
 
10
10
  export { GameObject, Behaviour } from "./engine-components/Component";
@@ -50,3 +50,7 @@ if(!globalThis["THREE"]) {
50
50
  globalThis["THREE"] = THREE;
51
51
  }
52
52
  else console.warn("Threejs is already imported");
53
+
54
+
55
+
56
+ import "./engine/engine_license";