@needle-tools/engine 2.63.3-pre.1 → 2.64.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 (67) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/needle-engine.js +7725 -7641
  3. package/dist/needle-engine.umd.cjs +215 -214
  4. package/lib/engine/engine_constants.d.ts +1 -1
  5. package/lib/engine/engine_constants.js +1 -1
  6. package/lib/engine/engine_constants.js.map +1 -1
  7. package/lib/engine/engine_gameobject.js +2 -2
  8. package/lib/engine/engine_gameobject.js.map +1 -1
  9. package/lib/engine/engine_instancing.d.ts +1 -0
  10. package/lib/engine/engine_instancing.js +3 -2
  11. package/lib/engine/engine_instancing.js.map +1 -1
  12. package/lib/engine/engine_license.js +14 -13
  13. package/lib/engine/engine_license.js.map +1 -1
  14. package/lib/engine/engine_mainloop_utils.js +27 -52
  15. package/lib/engine/engine_mainloop_utils.js.map +1 -1
  16. package/lib/engine/engine_physics.d.ts +1 -0
  17. package/lib/engine/engine_physics.js +30 -0
  18. package/lib/engine/engine_physics.js.map +1 -1
  19. package/lib/engine/engine_setup.d.ts +1 -1
  20. package/lib/engine/engine_setup.js.map +1 -1
  21. package/lib/engine/engine_time.d.ts +1 -0
  22. package/lib/engine/engine_time.js +5 -1
  23. package/lib/engine/engine_time.js.map +1 -1
  24. package/lib/engine/engine_types.d.ts +12 -0
  25. package/lib/engine/engine_types.js.map +1 -1
  26. package/lib/engine-components/Animation.js +6 -6
  27. package/lib/engine-components/Animation.js.map +1 -1
  28. package/lib/engine-components/AnimatorController.js +2 -0
  29. package/lib/engine-components/AnimatorController.js.map +1 -1
  30. package/lib/engine-components/AudioSource.js +1 -1
  31. package/lib/engine-components/AudioSource.js.map +1 -1
  32. package/lib/engine-components/Component.d.ts +1 -0
  33. package/lib/engine-components/Component.js.map +1 -1
  34. package/lib/engine-components/ParticleSystem.js +13 -1
  35. package/lib/engine-components/ParticleSystem.js.map +1 -1
  36. package/lib/engine-components/Renderer.d.ts +5 -1
  37. package/lib/engine-components/Renderer.js +78 -29
  38. package/lib/engine-components/Renderer.js.map +1 -1
  39. package/lib/engine-components/js-extensions/Object3D.js +7 -0
  40. package/lib/engine-components/js-extensions/Object3D.js.map +1 -1
  41. package/lib/engine-components/timeline/PlayableDirector.d.ts +5 -0
  42. package/lib/engine-components/timeline/PlayableDirector.js +36 -23
  43. package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
  44. package/lib/engine-components/timeline/TimelineTracks.d.ts +9 -0
  45. package/lib/engine-components/timeline/TimelineTracks.js +112 -19
  46. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  47. package/lib/tsconfig.tsbuildinfo +1 -1
  48. package/package.json +1 -1
  49. package/src/engine/engine_constants.ts +1 -1
  50. package/src/engine/engine_gameobject.ts +2 -2
  51. package/src/engine/engine_instancing.ts +3 -3
  52. package/src/engine/engine_license.ts +14 -13
  53. package/src/engine/engine_mainloop_utils.ts +32 -58
  54. package/src/engine/engine_physics.ts +23 -0
  55. package/src/engine/engine_setup.ts +1 -1
  56. package/src/engine/engine_time.ts +9 -4
  57. package/src/engine/engine_types.ts +36 -22
  58. package/src/engine-components/Animation.ts +6 -5
  59. package/src/engine-components/AnimatorController.ts +1 -0
  60. package/src/engine-components/AudioSource.ts +1 -1
  61. package/src/engine-components/Component.ts +3 -0
  62. package/src/engine-components/ParticleSystem.ts +15 -2
  63. package/src/engine-components/Renderer.ts +92 -33
  64. package/src/engine-components/js-extensions/Object3D.ts +7 -1
  65. package/src/engine-components/timeline/PlayableDirector.ts +35 -24
  66. package/src/engine-components/timeline/TimelineTracks.ts +124 -20
  67. package/src/engine/codegen/license.js +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/engine",
3
- "version": "2.63.3-pre.1",
3
+ "version": "2.64.0-pre",
4
4
  "description": "Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development, and can be deployed anywhere. It is flexible, extensible, and collaboration and XR come naturally.",
5
5
  "main": "dist/needle-engine.umd.cjs",
6
6
  "module": "dist/needle-engine.js",
@@ -1,3 +1,3 @@
1
1
 
2
- export const activeInHierarchyFieldName = "__isActiveInHierarchy";
2
+ export const activeInHierarchyFieldName = Symbol("isActiveInHierarchy");
3
3
  export const builtinComponentKeyName = "builtin_components";
@@ -6,7 +6,7 @@ import { logHierarchy, setWorldPosition, setWorldQuaternion } from "./engine_thr
6
6
  import { GuidsMap, IComponent as Component, IComponent, IGameObject as GameObject, UIDProvider } from "./engine_types";
7
7
  import { getParam, tryFindObject } from "./engine_utils";
8
8
  import { apply } from "../engine-components/js-extensions/Object3D";
9
- import { InstancingUtil } from "./engine_instancing";
9
+ import { $isUsingInstancing, InstancingUtil } from "./engine_instancing";
10
10
  import { activeInHierarchyFieldName } from "./engine_constants";
11
11
  import { assign } from "./engine_serialization_core";
12
12
 
@@ -75,7 +75,7 @@ export function isActiveInHierarchy(go: Object3D): boolean {
75
75
  }
76
76
 
77
77
  export function markAsInstancedRendered(go: THREE.Object3D, instanced: boolean) {
78
- go["__isUsingInstancing"] = instanced;
78
+ go[$isUsingInstancing] = instanced;
79
79
  }
80
80
 
81
81
  export function isUsingInstancing(instance: THREE.Object3D): boolean { return InstancingUtil.isUsingInstancing(instance); }
@@ -1,17 +1,17 @@
1
1
  export const NEED_UPDATE_INSTANCE_KEY = Symbol("NEEDLE_NEED_UPDATE_INSTANCE");
2
2
 
3
-
3
+ export const $isUsingInstancing = Symbol("isUsingInstancing");
4
4
 
5
5
  export class InstancingUtil {
6
6
 
7
- static isUsingInstancing(instance: THREE.Object3D): boolean { return instance["__isUsingInstancing"] === true; }
7
+ static isUsingInstancing(instance: THREE.Object3D): boolean { return instance[$isUsingInstancing] === true; }
8
8
 
9
9
  // TODO: change this so it does not set matrix world directly but some flag that is only used by instancing
10
10
  static markDirty(go: THREE.Object3D | null, recursive: boolean = true) {
11
11
  if (!go) return;
12
12
  // potential optimization:
13
13
  // if(go.matrixWorldNeedsUpdate) return;
14
- // console.trace(go, GameObject.isUsingInstancing(go));
14
+ // console.warn("UPDATE", go);
15
15
  if (this.isUsingInstancing(go)) {
16
16
  go[NEED_UPDATE_INSTANCE_KEY] = true;
17
17
  go.matrixWorldNeedsUpdate = true;
@@ -42,7 +42,7 @@ async function showLicenseInfo(ctx: IContext) {
42
42
 
43
43
 
44
44
  const _licenseText = "🌵 <span class=\"text\">Made with <a href=\"https://needle.tools\" target=\"_blank\">Needle</a></span>";
45
- const licenseElementClass = "needle-license-element";
45
+ const licenseElementIdentifier = "needle-license-element";
46
46
  const licenseDuration = 30000;
47
47
  const licenseDelay = 600;
48
48
 
@@ -78,6 +78,7 @@ function insertNonCommercialUseHint(ctx: IContext) {
78
78
  setTimeout(() => {
79
79
  clearInterval(interval);
80
80
  licenseElement?.remove();
81
+ style?.remove();
81
82
  }, removeDelay);
82
83
 
83
84
  }
@@ -97,8 +98,7 @@ async function logNonCommercialUse(_logo?: string) {
97
98
 
98
99
  function createLicenseElement() {
99
100
  const licenseElement = document.createElement("div");
100
- licenseElement.classList.add(licenseElementClass);
101
- licenseElement.setAttribute("data-needle_engine_license_element", "");
101
+ licenseElement.setAttribute(licenseElementIdentifier, "");
102
102
  licenseElement.style.position = "fixed";
103
103
  licenseElement.style.bottom = "12px";
104
104
  licenseElement.style.right = "15px";
@@ -112,10 +112,8 @@ function createLicenseElement() {
112
112
  // TODO: would be better to put this into a web element and use shadow dom
113
113
  function createLicenseStyle() {
114
114
  const licenseStyle = document.createElement("style");
115
- const selector = "." + licenseElementClass;
115
+ const selector = `div[${licenseElementIdentifier}]`;
116
116
  licenseStyle.innerHTML = `
117
- @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;500&display=swap');
118
-
119
117
  ${selector} {
120
118
  font-family: 'Roboto', sans-serif !important;
121
119
  font-weight: 300;
@@ -145,23 +143,26 @@ function createLicenseStyle() {
145
143
  opacity: .9;
146
144
  }
147
145
  2% {
148
- transform: translate(0, 3px);
146
+ transform: translate(0, 2.5px);
149
147
  }
150
- 6% {
148
+ 3% {
151
149
  transform: translate(0, 0px);
152
150
  pointer-events: all;
153
151
  opacity: 1;
154
152
  }
155
- 50% {
153
+ 4% {
156
154
  transform: scale(1)
157
155
  }
158
- 51% {
159
- transform: scale(1.2)
156
+ 4.5% {
157
+ transform: scale(1.3)
158
+ }
159
+ 6% {
160
+ transform: scale(1.32)
160
161
  }
161
- 53% {
162
+ 7% {
162
163
  transform: scale(1)
163
164
  }
164
- 90% {
165
+ 98% {
165
166
  opacity: 1;
166
167
  pointer-events: all;
167
168
  transform: scale(1)
@@ -7,6 +7,7 @@ import { isActiveSelf } from './engine_gameobject';
7
7
  import { ContextRegistry } from "./engine_context_registry";
8
8
 
9
9
  const debug = getParam("debugnewscripts");
10
+ const debugHierarchy = getParam("debughierarchy");
10
11
 
11
12
  // if some other script adds new scripts in onEnable or awake
12
13
  // the original array should be cleared before processing it
@@ -214,8 +215,6 @@ function removeFromArray(script: any, array: any[]) {
214
215
  if (index >= 0) array.splice(index, 1);
215
216
  }
216
217
 
217
- const previousActiveMap: { [key: string]: boolean } = {};
218
- const previousActiveInHierarchyMap: { [key: string]: boolean } = {};
219
218
 
220
219
  export function updateIsActive(obj?: Object3D) {
221
220
  if (!obj) obj = ContextRegistry.Current.scene;
@@ -226,67 +225,43 @@ export function updateIsActive(obj?: Object3D) {
226
225
  updateIsActiveInHierarchyRecursiveRuntime(obj, isActiveSelf(obj), true);
227
226
  }
228
227
 
229
- // const $wasSetVisibleBefore = Symbol("wasSetVisibleBefore");
230
228
 
231
229
  function updateIsActiveInHierarchyRecursiveRuntime(go: THREE.Object3D, activeInHierarchy: boolean, allowEventCall: boolean) {
232
- let activeStateChanged: boolean = false;
233
-
234
- const active = isActiveSelf(go);
235
-
236
- // this is a test if we dont control active state from visibility and set
237
- // active to true by default (even if the object is invisible) in engine_gameobjects:isActiveSelf
238
- // then we need to check if the object is set to visible for the first time
239
- // const visible = go.visible;
240
- // if (!active && visible) {
241
- // if (!go[$wasSetVisibleBefore]) {
242
- // go[$wasSetVisibleBefore] = true;
243
- // setActive(go, true);
244
- // }
245
- // }
246
-
247
- // if (activeInHierarchy) {
248
- // const prevActive = previousActiveMap[go.uuid];
249
- // if (prevActive !== undefined) {
250
- // if (prevActive !== active) {
251
- // activeStateChanged = true;
252
- // if (allowEventCall) {
253
- // perComponent(go, comp => {
254
- // if (active) {
255
- // utils.safeInvoke(comp.__internalAwake.bind(comp));
256
- // comp.onEnable();
257
- // }
258
- // else comp.onDisable();
259
- // });
260
- // }
261
- // }
262
- // }
263
- // }
264
- previousActiveMap[go.uuid] = active;
265
230
 
231
+ if (activeInHierarchy) {
232
+ activeInHierarchy = isActiveSelf(go);
233
+ // IF we update activeInHierarchy within a disabled hierarchy we need to check the parent
234
+ if (activeInHierarchy && go.parent) {
235
+ activeInHierarchy = go.parent[constants.activeInHierarchyFieldName]
236
+ }
237
+ }
266
238
 
267
- if (activeInHierarchy) activeInHierarchy = isActiveSelf(go);
239
+ const prevActive = go[constants.activeInHierarchyFieldName];
240
+ const changed = prevActive !== activeInHierarchy;
268
241
  go[constants.activeInHierarchyFieldName] = activeInHierarchy;
269
242
 
270
243
  // only raise events here if we didnt call enable etc already
271
- if (!activeStateChanged) {
272
- const prevActiveInHierarchy = previousActiveInHierarchyMap[go.uuid];
273
- if (prevActiveInHierarchy !== undefined) {
274
- if (prevActiveInHierarchy !== activeInHierarchy) {
275
- // console.log("CHANGE", go.name, activeInHierarchy);
276
- if (allowEventCall) {
277
- perComponent(go, comp => {
278
- if (activeInHierarchy) {
279
- utils.safeInvoke(comp.__internalAwake.bind(comp));
280
- comp.enabled = true;
281
- // comp.onEnable();
282
- }
283
- else comp.enabled = false;
284
- });
244
+ if (changed) {
245
+ if (debugHierarchy)
246
+ console.warn("ACTIVE CHANGE", go.name, activeInHierarchy, "changed?" + changed, go.userData.components, go.children, go);
247
+ if (allowEventCall) {
248
+ perComponent(go, comp => {
249
+ if (activeInHierarchy) {
250
+ if (comp.enabled) {
251
+ utils.safeInvoke(comp.__internalAwake.bind(comp));
252
+ comp["__didEnable"] = true;
253
+ comp.onEnable();
254
+ }
285
255
  }
286
- }
256
+ else {
257
+ if (comp["__didAwake"]) {
258
+ comp["__didEnable"] = false;
259
+ comp.onDisable();
260
+ }
261
+ }
262
+ });
287
263
  }
288
264
  }
289
- previousActiveInHierarchyMap[go.uuid] = activeInHierarchy;
290
265
 
291
266
  if (go.children) {
292
267
  for (const ch of go.children) {
@@ -312,7 +287,6 @@ export function updateActiveInHierarchyWithoutEventCall(go: THREE.Object3D) {
312
287
  console.error("GO is null");
313
288
  return;
314
289
  }
315
- previousActiveInHierarchyMap[go.uuid] = activeInHierarchy;
316
290
  go[constants.activeInHierarchyFieldName] = activeInHierarchy && foundScene;
317
291
  }
318
292
 
@@ -341,7 +315,7 @@ export function registerPrewarmObject(obj: Object3D, context: IContext) {
341
315
  obj[$waitingForPrewarm] = true;
342
316
  const list = prewarmList.get(context);
343
317
  list!.push(obj);
344
- if(debugPrewarm) console.debug("register prewarm", obj.name);
318
+ if (debugPrewarm) console.debug("register prewarm", obj.name);
345
319
  }
346
320
 
347
321
  let prewarmTarget: WebGLCubeRenderTarget | null = null;
@@ -355,7 +329,7 @@ export function runPrewarm(context: IContext) {
355
329
 
356
330
  const cam = context.mainCamera;
357
331
  if (cam) {
358
- if(debugPrewarm) console.log("prewarm", list.length, "objects", [...list]);
332
+ if (debugPrewarm) console.log("prewarm", list.length, "objects", [...list]);
359
333
  const renderer = context.renderer;
360
334
  const scene = context.scene;
361
335
  renderer.compile(scene, cam!)
@@ -364,10 +338,10 @@ export function runPrewarm(context: IContext) {
364
338
  prewarmCamera.update(renderer, scene);
365
339
  for (const obj of list) {
366
340
  obj[$prewarmedFlag] = true;
367
- obj[$waitingForPrewarm] = false;
341
+ obj[$waitingForPrewarm] = false;
368
342
  }
369
343
  list.length = 0;
370
- if(debugPrewarm) console.log("prewarm done");
344
+ if (debugPrewarm) console.log("prewarm done");
371
345
  }
372
346
  }
373
347
 
@@ -26,6 +26,7 @@ const debugPhysics = getParam("debugphysics");
26
26
  const debugColliderPlacement = getParam("debugphysicscolliders");
27
27
  const debugCollisions = getParam("debugcollisions");
28
28
  const showColliders = getParam("showcolliders");
29
+ const noPhysics = getParam("nophysics");
29
30
 
30
31
 
31
32
  declare type PhysicsBody = {
@@ -286,6 +287,8 @@ export class Physics {
286
287
 
287
288
  // physics simulation
288
289
 
290
+ enabled: boolean = true;
291
+
289
292
  private _tempPosition: Vector3 = new Vector3();
290
293
  private _tempQuaternion: Quaternion = new Quaternion();
291
294
  private _tempScale: Vector3 = new Vector3();
@@ -325,6 +328,7 @@ export class Physics {
325
328
  Physics._didLoadPhysicsEngine = true;
326
329
  }
327
330
  this.world = new World(this._gravity);
331
+ if (noPhysics) this.enabled = false;
328
332
  }
329
333
 
330
334
  private _gravity = { x: 0.0, y: -9.81, z: 0.0 };
@@ -347,6 +351,10 @@ export class Physics {
347
351
  }
348
352
 
349
353
  addBoxCollider(collider: ICollider, center: Vector3, size: Vector3) {
354
+ if (!this.enabled) {
355
+ if(debugPhysics) console.warn("Physics is disabled");
356
+ return;
357
+ }
350
358
  const obj = collider.gameObject;
351
359
  const scale = getWorldScale(obj, this._tempPosition).multiply(size);
352
360
  scale.multiplyScalar(0.5);
@@ -355,6 +363,10 @@ export class Physics {
355
363
  }
356
364
 
357
365
  addSphereCollider(collider: ICollider, center: Vector3, radius: number) {
366
+ if (!this.enabled) {
367
+ if(debugPhysics) console.warn("Physics is disabled");
368
+ return;
369
+ }
358
370
  const obj = collider.gameObject;
359
371
  const scale = getWorldScale(obj, this._tempPosition).multiplyScalar(radius);
360
372
  const desc = ColliderDesc.ball(scale.x);
@@ -362,6 +374,10 @@ export class Physics {
362
374
  }
363
375
 
364
376
  addCapsuleCollider(collider: ICollider, center: Vector3, height: number, radius: number) {
377
+ if (!this.enabled) {
378
+ if(debugPhysics) console.warn("Physics is disabled");
379
+ return;
380
+ }
365
381
  const obj = collider.gameObject;
366
382
  const scale = getWorldScale(obj, this._tempPosition);
367
383
  if (debugPhysics) console.log("capsule scale", scale, height, radius);
@@ -370,6 +386,10 @@ export class Physics {
370
386
  }
371
387
 
372
388
  addMeshCollider(collider: ICollider, mesh: Mesh, convex: boolean, scale: Vector3) {
389
+ if (!this.enabled) {
390
+ if(debugPhysics) console.warn("Physics is disabled");
391
+ return;
392
+ }
373
393
  const geo = mesh.geometry;
374
394
  if (!geo) {
375
395
  if (debugPhysics) console.warn("Missing mesh geometry", mesh.name);
@@ -575,6 +595,7 @@ export class Physics {
575
595
  }
576
596
 
577
597
  updateBody(comp: ICollider | IRigidbody, translation: boolean, rotation: boolean) {
598
+ if (!this.enabled) return;
578
599
  if (comp.destroyed || !comp.gameObject) return;
579
600
  if (!translation && !rotation) return;
580
601
 
@@ -637,6 +658,7 @@ export class Physics {
637
658
 
638
659
  public step(dt?: number) {
639
660
  if (!this.world) return;
661
+ if (!this.enabled) return;
640
662
  this._isUpdatingPhysicsWorld = true;
641
663
  if (!this.eventQueue) {
642
664
  this.eventQueue = new EventQueue(false);
@@ -670,6 +692,7 @@ export class Physics {
670
692
 
671
693
  public postStep() {
672
694
  if (!this.world) return;
695
+ if (!this.enabled) return;
673
696
  this._isUpdatingPhysicsWorld = true;
674
697
  this.syncObjects();
675
698
  this._isUpdatingPhysicsWorld = false;
@@ -233,7 +233,7 @@ export class Context implements IContext {
233
233
 
234
234
  private _stats: Stats.default | null = stats ? Stats.default() : null;
235
235
 
236
- constructor(args: ContextArgs | undefined) {
236
+ constructor(args?: ContextArgs) {
237
237
  this.name = args?.name || "";
238
238
  this.alias = args?.alias;
239
239
  this.domElement = args?.domElement || document.body;
@@ -3,7 +3,7 @@ import { getParam } from './engine_utils';
3
3
 
4
4
  const timescaleUrl = getParam("timescale");
5
5
  let timeScale = 1;
6
- if(typeof timescaleUrl === "number") timeScale = timescaleUrl;
6
+ if (typeof timescaleUrl === "number") timeScale = timescaleUrl;
7
7
 
8
8
  export class Time {
9
9
 
@@ -28,12 +28,17 @@ export class Time {
28
28
  private _fpsSamples: number[] = [];
29
29
  private _fpsSampleIndex: number = 0;
30
30
 
31
+ constructor() {
32
+ if (typeof timeScale === "number")
33
+ this.timeScale = timeScale;
34
+ }
35
+
31
36
  update() {
32
37
  this.deltaTime = this.clock.getDelta();
33
38
  // clamp delta time because if tab is not active clock.getDelta can get pretty big
34
39
  this.deltaTime = Math.min(.1, this.deltaTime);
35
- this.deltaTime *= timeScale * this.timeScale;
36
- if(this.deltaTime <= 0) this.deltaTime = 0.000000000001;
40
+ this.deltaTime *= this.timeScale;
41
+ if (this.deltaTime <= 0) this.deltaTime = 0.000000000001;
37
42
  this.frame += 1;
38
43
  this.time += this.deltaTime;
39
44
 
@@ -42,6 +47,6 @@ export class Time {
42
47
  let sum = 0;
43
48
  for (let i = 0; i < this._fpsSamples.length; i++)
44
49
  sum += this._fpsSamples[i];
45
- this._smoothedFps = 1/(sum / this._fpsSamples.length);
50
+ this._smoothedFps = 1 / (sum / this._fpsSamples.length);
46
51
  }
47
52
  }
@@ -21,9 +21,9 @@ export interface UIDProvider {
21
21
 
22
22
 
23
23
  export declare type CoroutineData = {
24
- comp: IComponent,
25
- main: Generator,
26
- chained?: Array<Generator>
24
+ comp: IComponent,
25
+ main: Generator,
26
+ chained?: Array<Generator>
27
27
  }
28
28
 
29
29
 
@@ -37,25 +37,25 @@ export interface IContext {
37
37
  domElement: HTMLElement;
38
38
 
39
39
  scripts: IComponent[];
40
- scripts_pausedChanged: IComponent[];
41
- // scripts with update event
42
- scripts_earlyUpdate: IComponent[];
43
- scripts_update: IComponent[];
44
- scripts_lateUpdate: IComponent[];
45
- scripts_onBeforeRender: IComponent[];
46
- scripts_onAfterRender: IComponent[];
47
- scripts_WithCorroutines: IComponent[];
48
- coroutines: { [FrameEvent: number]: Array<CoroutineData> };
49
-
50
- post_setup_callbacks: Function[];
51
- pre_update_callbacks: Function[];
52
- pre_render_callbacks: Function[];
53
- post_render_callbacks: Function[];
54
-
55
- new_scripts: IComponent[];
56
- new_script_start: IComponent[];
57
- new_scripts_pre_setup_callbacks: Function[];
58
- new_scripts_post_setup_callbacks: Function[];
40
+ scripts_pausedChanged: IComponent[];
41
+ // scripts with update event
42
+ scripts_earlyUpdate: IComponent[];
43
+ scripts_update: IComponent[];
44
+ scripts_lateUpdate: IComponent[];
45
+ scripts_onBeforeRender: IComponent[];
46
+ scripts_onAfterRender: IComponent[];
47
+ scripts_WithCorroutines: IComponent[];
48
+ coroutines: { [FrameEvent: number]: Array<CoroutineData> };
49
+
50
+ post_setup_callbacks: Function[];
51
+ pre_update_callbacks: Function[];
52
+ pre_render_callbacks: Function[];
53
+ post_render_callbacks: Function[];
54
+
55
+ new_scripts: IComponent[];
56
+ new_script_start: IComponent[];
57
+ new_scripts_pre_setup_callbacks: Function[];
58
+ new_scripts_post_setup_callbacks: Function[];
59
59
 
60
60
  stopAllCoroutinesFrom(script: IComponent);
61
61
  }
@@ -71,6 +71,13 @@ export declare interface IGameObject extends Object3D {
71
71
  guid: string | undefined;
72
72
 
73
73
  activeSelf: boolean;
74
+
75
+ /** NOTE: this is just a wrapper for devs coming from Unity. Please use this.gameObject instead. In Needle Engine this.gameObject is the same as this.gameObject.transform. See the tutorial link below for more information
76
+ * @augments Object3D
77
+ * @tutorial https://fwd.needle.tools/needle-engine/docs/transform
78
+ * */
79
+ get transform(): Object3D;
80
+
74
81
  addNewComponent<T>(type: Constructor<T>): T | null;
75
82
  removeComponent(comp: IComponent): IComponent;
76
83
  getOrAddComponent<T>(typeName: Constructor<T> | null): T;
@@ -100,12 +107,19 @@ export interface IComponent {
100
107
 
101
108
  get activeAndEnabled(): boolean;
102
109
 
110
+ /** @internal */
103
111
  __internalNewInstanceCreated();
112
+ /** @internal */
104
113
  __internalAwake();
114
+ /** @internal */
105
115
  __internalStart();
116
+ /** @internal */
106
117
  __internalEnable();
118
+ /** @internal */
107
119
  __internalDisable();
120
+ /** @internal */
108
121
  __internalDestroy();
122
+ /** @internal */
109
123
  resolveGuids?(guidsMap: GuidsMap): void;
110
124
 
111
125
  /** experimental, called when the script is registered for the first time, this is called even if the component is not enabled. */
@@ -125,11 +125,12 @@ export class Animation extends Behaviour {
125
125
  update() {
126
126
  if (!this.mixer) return;
127
127
  this.mixer.update(this.context.time.deltaTime);
128
- for (const handle of this._handles) {
129
- handle._update();
130
- }
131
- if (this._handles?.length > 0)
132
- InstancingUtil.markDirty(this.gameObject);
128
+ // this is now handled via matrix auto update
129
+ // for (const handle of this._handles) {
130
+ // handle._update();
131
+ // }
132
+ // if (this._handles?.length > 0)
133
+ // InstancingUtil.markDirty(this.gameObject);
133
134
  }
134
135
 
135
136
  getAction(name: string): THREE.AnimationAction | undefined | null {
@@ -146,6 +146,7 @@ export class AnimatorController {
146
146
  if (!this.animator) return;
147
147
  this.evaluateTransitions();
148
148
  this.updateActiveStates();
149
+ if(!this._activeState) return;
149
150
  const dt = this.animator.context.time.deltaTime;
150
151
  if (this.animator.applyRootMotion) {
151
152
  this.rootMotionHandler?.onBeforeUpdate();
@@ -75,7 +75,7 @@ export class AudioSource extends Behaviour {
75
75
  }
76
76
  this.callbacks.length = 0;
77
77
  };
78
- let fn = callback.bind(this);
78
+ const fn = callback.bind(this);
79
79
  document.addEventListener('pointerdown', fn);
80
80
  document.addEventListener('click', fn);
81
81
  document.addEventListener('dragstart', fn);
@@ -23,6 +23,9 @@ abstract class GameObject extends THREE.Object3D implements THREE.Object3D, IGam
23
23
 
24
24
  guid: string | undefined;
25
25
 
26
+ // The actual implementation / prototype of threejs is modified in js-extensions/Object3D
27
+ abstract get transform(): THREE.Object3D;
28
+
26
29
  public static isDestroyed(go: THREE.Object3D): boolean {
27
30
  return isDestroyed(go);
28
31
  }
@@ -70,7 +70,7 @@ export class ParticleSystemRenderer extends Behaviour {
70
70
 
71
71
  getMaterial(trailEnabled: boolean = false) {
72
72
  const material = (trailEnabled === true && this.trailMaterial) ? this.trailMaterial : this.particleMaterial;
73
-
73
+
74
74
  // progressive load on start
75
75
  // TODO: figure out how to do this before particle system rendering so we only load textures for visible materials
76
76
  if (material && !suppressProgressiveLoading && material["_didRequestTextureLOD"] === undefined) {
@@ -836,7 +836,20 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
836
836
  onBeforeRender() {
837
837
  this.onUpdate();
838
838
  const dt = this.deltaTime;
839
- this._batchSystem?.update(dt);
839
+
840
+ if (this._batchSystem) {
841
+ // Updating layers on batches
842
+ // TODO: figure out a better way to do this
843
+ // Issue: https://github.com/Alchemist0823/three.quarks/issues/49
844
+ if (this.context.time.frameCount % 60 === 0) {
845
+ for (let i = 0; i < this._batchSystem.batches.length; i++) {
846
+ const batch = this._batchSystem.batches[i];
847
+ batch.layers.disableAll();
848
+ batch.layers.set(2);
849
+ }
850
+ }
851
+ this._batchSystem.update(dt);
852
+ }
840
853
  this._time += dt;
841
854
  if (this._time > this.duration) this._time = 0;
842
855
  }