@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.
- package/CHANGELOG.md +20 -0
- package/dist/needle-engine.js +9983 -9692
- package/dist/needle-engine.umd.cjs +306 -223
- package/lib/engine/api.d.ts +1 -0
- package/lib/engine/api.js +1 -0
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/codegen/license.d.ts +1 -0
- package/lib/engine/codegen/license.js +2 -0
- package/lib/engine/codegen/license.js.map +1 -0
- package/lib/engine/engine.js +0 -2
- package/lib/engine/engine.js.map +1 -1
- package/lib/engine/engine_camera.d.ts +4 -0
- package/lib/engine/engine_camera.js +13 -0
- package/lib/engine/engine_camera.js.map +1 -0
- package/lib/engine/engine_element.d.ts +1 -0
- package/lib/engine/engine_element.js +18 -2
- package/lib/engine/engine_element.js.map +1 -1
- package/lib/engine/engine_element_loading.js +28 -4
- package/lib/engine/engine_element_loading.js.map +1 -1
- package/lib/engine/engine_input.d.ts +2 -0
- package/lib/engine/engine_input.js +14 -0
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_license.d.ts +1 -0
- package/lib/engine/engine_license.js +199 -0
- package/lib/engine/engine_license.js.map +1 -0
- package/lib/engine/engine_physics.d.ts +3 -0
- package/lib/engine/engine_physics.js +13 -2
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_setup.js +1 -1
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/engine_types.d.ts +4 -0
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine/extensions/extension_utils.js +1 -1
- package/lib/engine/extensions/extension_utils.js.map +1 -1
- package/lib/engine/js-extensions/Camera.d.ts +1 -0
- package/lib/engine/js-extensions/Camera.js +37 -0
- package/lib/engine/js-extensions/Camera.js.map +1 -0
- package/lib/engine/js-extensions/Layers.js +1 -0
- package/lib/engine/js-extensions/Layers.js.map +1 -1
- package/lib/engine/js-extensions/index.d.ts +2 -0
- package/lib/engine/js-extensions/index.js +3 -0
- package/lib/engine/js-extensions/index.js.map +1 -0
- package/lib/engine-components/CameraUtils.d.ts +1 -3
- package/lib/engine-components/CameraUtils.js +34 -17
- package/lib/engine-components/CameraUtils.js.map +1 -1
- package/lib/engine-components/Light.d.ts +4 -1
- package/lib/engine-components/Light.js +17 -2
- package/lib/engine-components/Light.js.map +1 -1
- package/lib/engine-components/OrbitControls.d.ts +4 -1
- package/lib/engine-components/OrbitControls.js +13 -2
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/ScreenCapture.d.ts +2 -2
- package/lib/engine-components/ScreenCapture.js +3 -1
- package/lib/engine-components/ScreenCapture.js.map +1 -1
- package/lib/engine-components/VideoPlayer.d.ts +2 -1
- package/lib/engine-components/VideoPlayer.js +9 -6
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/timeline/TimelineTracks.js +7 -1
- package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
- package/lib/engine-components/ui/BaseUIComponent.d.ts +3 -0
- package/lib/engine-components/ui/BaseUIComponent.js +20 -10
- package/lib/engine-components/ui/BaseUIComponent.js.map +1 -1
- package/lib/engine-components/ui/Button.js +7 -3
- package/lib/engine-components/ui/Button.js.map +1 -1
- package/lib/engine-components/ui/EventSystem.js +21 -42
- package/lib/engine-components/ui/EventSystem.js.map +1 -1
- package/lib/engine-components/ui/Graphic.d.ts +1 -0
- package/lib/engine-components/ui/Graphic.js +7 -0
- package/lib/engine-components/ui/Graphic.js.map +1 -1
- package/lib/engine-components/ui/Interfaces.d.ts +2 -1
- package/lib/engine-components/ui/RaycastUtils.js +2 -0
- package/lib/engine-components/ui/RaycastUtils.js.map +1 -1
- package/lib/engine-components/ui/Text.js +10 -1
- package/lib/engine-components/ui/Text.js.map +1 -1
- package/lib/needle-engine.d.ts +2 -0
- package/lib/needle-engine.js +2 -2
- package/lib/needle-engine.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/engine/api.ts +2 -1
- package/src/engine/assets/logo.svg +1 -0
- package/src/engine/codegen/license.js +1 -0
- package/src/engine/engine.ts +0 -3
- package/src/engine/engine_camera.ts +18 -0
- package/src/engine/engine_element.ts +18 -2
- package/src/engine/engine_element_loading.ts +33 -8
- package/src/engine/engine_input.ts +17 -5
- package/src/engine/engine_license.ts +216 -0
- package/src/engine/engine_physics.ts +16 -2
- package/src/engine/engine_setup.ts +2 -1
- package/src/engine/engine_types.ts +9 -4
- package/src/engine/extensions/extension_utils.ts +1 -1
- package/src/engine/js-extensions/Camera.ts +35 -0
- package/src/engine/js-extensions/Layers.ts +2 -1
- package/src/engine/js-extensions/index.ts +2 -0
- package/src/engine-components/CameraUtils.ts +42 -20
- package/src/engine-components/Light.ts +16 -3
- package/src/engine-components/OrbitControls.ts +18 -6
- package/src/engine-components/ScreenCapture.ts +3 -2
- package/src/engine-components/VideoPlayer.ts +10 -6
- package/src/engine-components/timeline/TimelineTracks.ts +9 -3
- package/src/engine-components/ui/BaseUIComponent.ts +21 -11
- package/src/engine-components/ui/Button.ts +7 -3
- package/src/engine-components/ui/EventSystem.ts +20 -42
- package/src/engine-components/ui/Graphic.ts +7 -0
- package/src/engine-components/ui/Interfaces.ts +3 -1
- package/src/engine-components/ui/RaycastUtils.ts +2 -1
- package/src/engine-components/ui/Text.ts +11 -2
- 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 {
|
|
5
|
-
import { ICamera
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
|
102
|
-
|
|
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
|
|
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
|
|
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.
|
|
359
|
-
this.
|
|
360
|
-
target["material"] = this.
|
|
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.
|
|
368
|
+
(this._videoMaterial as any).map = this._videoTexture;
|
|
365
369
|
}
|
|
366
370
|
else {
|
|
367
371
|
switch (this.targetMaterialProperty) {
|
|
368
372
|
default:
|
|
369
|
-
(this.
|
|
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 &&
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
266
|
-
|
|
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
|
-
|
|
402
|
-
|
|
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 (
|
|
502
|
-
lu.frame =
|
|
503
|
-
|
|
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:
|
|
519
|
+
this.lastUpdateFrame = [{ context, frame: currentFrame, nextUpdate: currentFrame }];
|
|
513
520
|
threeMeshUI.update();
|
|
514
521
|
}
|
|
515
522
|
|
|
516
|
-
static updateState(intersect: THREE.Object3D,
|
|
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:
|
|
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 =
|
|
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);
|
package/src/needle-engine.ts
CHANGED
|
@@ -3,8 +3,8 @@ makeErrorsVisibleForDevelopment();
|
|
|
3
3
|
|
|
4
4
|
import "./engine/engine_element";
|
|
5
5
|
import "./engine/engine_setup";
|
|
6
|
-
|
|
7
|
-
|
|
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";
|