Needle Engine

Changes between version 3.41.0-alpha.3 and 3.41.0-alpha.4
Files changed (16) hide show
  1. src/engine-components/Animation.ts +1 -1
  2. src/engine-components/AnimationUtils.ts +2 -2
  3. src/engine-components/Animator.ts +1 -1
  4. src/engine/api.ts +3 -3
  5. src/engine-components/ContactShadows.ts +1 -1
  6. src/engine/engine_animation.ts +3 -3
  7. src/engine/engine_lifecycle_api.ts +1 -1
  8. src/engine/engine_scenetools.ts +5 -7
  9. src/engine/engine_serialization_builtin_serializer.ts +1 -1
  10. src/engine/engine_test_utils.ts +4 -3
  11. src/engine/engine_utils_format.ts +6 -2
  12. src/engine/engine_utils_screenshot.ts +34 -2
  13. src/engine/export/gltf/index.ts +4 -3
  14. src/engine-components/timeline/PlayableDirector.ts +1 -1
  15. src/engine-components/RendererLightmap.ts +4 -1
  16. src/engine/export/gltf/Writers.ts +2 -1
src/engine-components/Animation.ts CHANGED
@@ -2,10 +2,10 @@
2
2
 
3
3
  import { Mathf } from "../engine/engine_math.js";
4
4
  import { serializable } from "../engine/engine_serialization_decorator.js";
5
+ import { IAnimationComponent } from "../engine/engine_types.js";
5
6
  import { getParam } from "../engine/engine_utils.js";
6
7
  import { MixerEvent } from "./Animator.js";
7
8
  import { Behaviour } from "./Component.js";
8
- import { IAnimationComponent } from "../needle-engine.js";
9
9
 
10
10
  const debug = getParam("debuganimation");
11
11
 
src/engine-components/AnimationUtils.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import { Object3D, PropertyBinding } from "three";
2
2
  import type { GLTF } from "three/examples/jsm/loaders/GLTFLoader.js";
3
3
 
4
+ import { AnimationUtils } from "../engine/engine_animation.js";
5
+ import { addComponent, addNewComponent } from "../engine/engine_components.js";
4
6
  import { ContextEvent, ContextRegistry } from "../engine/engine_context_registry.js";
5
7
  import { Animation } from "./Animation.js";
6
8
  import { Animator } from "./Animator.js";
7
9
  import { GameObject } from "./Component.js";
8
10
  import { PlayableDirector } from "./timeline/PlayableDirector.js";
9
- import { AnimationUtils } from "../engine/engine_animation.js";
10
- import { addComponent, addNewComponent } from "../engine/engine_components.js";
11
11
 
12
12
 
13
13
  const $objectAnimationKey = Symbol("objectIsAnimatedData");
src/engine-components/Animator.ts CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  import { Mathf } from "../engine/engine_math.js";
4
4
  import { serializable } from "../engine/engine_serialization_decorator.js";
5
+ import { IAnimationComponent } from "../engine/engine_types.js";
5
6
  import { getParam } from "../engine/engine_utils.js";
6
7
  import type { AnimatorControllerModel } from "../engine/extensions/NEEDLE_animator_controller_model.js";
7
8
  import { getObjectAnimated } from "./AnimationUtils.js";
8
9
  import { AnimatorController } from "./AnimatorController.js";
9
10
  import { Behaviour } from "./Component.js";
10
- import { IAnimationComponent } from "../needle-engine.js";
11
11
 
12
12
  const debug = getParam("debuganimator");
13
13
 
src/engine/api.ts CHANGED
@@ -15,7 +15,6 @@
15
15
  export * from "./engine_element.js";
16
16
  export * from "./engine_element_attributes.js";
17
17
  export * from "./engine_element_loading.js";
18
- export * from "./export/index.js";
19
18
  export * from "./engine_gameobject.js";
20
19
  export { Gizmos } from "./engine_gizmos.js"
21
20
  export * from "./engine_gltf.js";
@@ -42,18 +41,19 @@
42
41
  export * from "./engine_scenetools.js";
43
42
  export * from "./engine_serialization.js";
44
43
  export { type ISerializable } from "./engine_serialization_core.js";
44
+ export * from "./engine_test_utils.js";
45
45
  export * from "./engine_texture.js";
46
- export * from "./engine_test_utils.js";
47
46
  export * from "./engine_three_utils.js";
48
47
  export * from "./engine_time.js";
49
48
  export * from "./engine_time_utils.js";
50
- export * from "./engine_utils_format.js";
51
49
  export * from "./engine_types.js";
52
50
  export { registerType, TypeStore } from "./engine_typestore.js";
53
51
  export { prefix, validate } from "./engine_util_decorator.js";
54
52
  export * from "./engine_utils.js";
53
+ export * from "./engine_utils_format.js";
55
54
  export * from "./engine_utils_screenshot.js";
56
55
  export * from "./engine_web_api.js";
56
+ export * from "./export/index.js";
57
57
  export * from "./extensions/index.js";
58
58
  export * from "./js-extensions/index.js";
59
59
  export * from "./webcomponents/api.js"
src/engine-components/ContactShadows.ts CHANGED
@@ -6,12 +6,12 @@
6
6
  import { addComponent } from "../engine/engine_components.js";
7
7
  import { Context } from "../engine/engine_context.js";
8
8
  import { Gizmos } from "../engine/engine_gizmos.js";
9
+ import { onStart } from "../engine/engine_lifecycle_api.js";
9
10
  import { serializable } from "../engine/engine_serialization_decorator.js";
10
11
  import { getBoundingBox } from "../engine/engine_three_utils.js";
11
12
  import { getParam } from "../engine/engine_utils.js"
12
13
  import { setCustomVisibility } from "../engine/js-extensions/Layers.js";
13
14
  import { Behaviour, GameObject } from "./Component.js";
14
- import { onStart } from "../engine/engine_lifecycle_api.js";
15
15
 
16
16
  const debug = getParam("debugcontactshadows");
17
17
 
src/engine/engine_animation.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { AnimationAction, AnimationClip, AnimationMixer, Object3D, PropertyBinding } from "three";
2
- import type { Context } from "./engine_context";
3
- import { GLTF, IAnimationComponent, IComponent } from "./engine_types";
4
- import { foreachComponentEnumerator } from "./engine_gameobject";
5
2
 
3
+ import type { Context } from "./engine_context.js";
4
+ import { GLTF, IAnimationComponent } from "./engine_types.js";
5
+
6
6
  /**
7
7
  * Registry for animation related data. Use {@link registerAnimationMixer} to register an animation mixer instance.
8
8
  * Can be accessed from {@link Context.animations} and is used internally e.g. when exporting GLTF files.
src/engine/engine_lifecycle_api.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { FrameEvent } from "./engine_context.js";
2
2
  import { ContextEvent } from "./engine_context_registry.js";
3
- import { type LifecycleMethod, registerFrameEventCallback, unregisterFrameEventCallback, LifecycleMethodOptions } from "./engine_lifecycle_functions_internal.js";
3
+ import { type LifecycleMethod, LifecycleMethodOptions,registerFrameEventCallback, unregisterFrameEventCallback } from "./engine_lifecycle_functions_internal.js";
4
4
 
5
5
 
6
6
  /**
src/engine/engine_scenetools.ts CHANGED
@@ -12,12 +12,12 @@
12
12
  import { registerPrewarmObject } from "./engine_mainloop_utils.js";
13
13
  import { SerializationContext } from "./engine_serialization_core.js";
14
14
  import { Context } from "./engine_setup.js"
15
+ import { postprocessFBXMaterials } from "./engine_three_utils.js";
15
16
  import { type UIDProvider } from "./engine_types.js";
16
17
  import * as utils from "./engine_utils.js";
18
+ import { FileType, tryDetermineFileTypeFromURL } from "./engine_utils_format.js"
17
19
  import { invokeAfterImportPluginHooks, registerComponentExtension, registerExtensions } from "./extensions/extensions.js";
18
20
  import { NEEDLE_components } from "./extensions/NEEDLE_components.js";
19
- import { FileType, tryDetermineFileTypeFromURL } from "./engine_utils_format.js"
20
- import { postprocessFBXMaterials } from "./engine_three_utils.js";
21
21
 
22
22
  /** @internal */
23
23
  export class NeedleGltfLoader implements INeedleGltfLoader {
@@ -125,12 +125,10 @@
125
125
  case "obj":
126
126
  return new OBJLoader();
127
127
  case "usd":
128
+ case "usda":
129
+ case "usdz":
128
130
  console.warn("USD files are not supported.")
129
131
  return null;
130
- break;
131
- case "usdz":
132
- console.warn("USDZ files are not supported.")
133
- return null;
134
132
  // return new USDZLoader();
135
133
  default:
136
134
  console.warn("Unknown file type:", type);
@@ -330,7 +328,7 @@
330
328
 
331
329
  if ((result as Object3D)?.isObject3D) {
332
330
  const obj = result as Object3D;
333
-
331
+
334
332
  if (loader instanceof FBXLoader) {
335
333
  obj.traverse((child) => {
336
334
  const mesh = child as Mesh;
src/engine/engine_serialization_builtin_serializer.ts CHANGED
@@ -9,8 +9,8 @@
9
9
  import { debugExtension } from "./engine_default_parameters.js";
10
10
  import { SerializationContext, TypeSerializer } from "./engine_serialization_core.js";
11
11
  import { RenderTexture } from "./engine_texture.js";
12
+ import { IComponent } from "./engine_types.js";
12
13
  import { resolveUrl } from "./engine_utils.js";
13
- import { IComponent } from "./engine_types.js";
14
14
 
15
15
  // export class SourcePath {
16
16
  // src?:string
src/engine/engine_test_utils.ts CHANGED
@@ -1,7 +1,8 @@
1
- import { PerspectiveCamera, Scene, Vector3, Object3D, EquirectangularReflectionMapping, DataTextureLoader } from "three";
1
+ import { DataTextureLoader,EquirectangularReflectionMapping, Object3D, PerspectiveCamera, Scene, Vector3 } from "three";
2
+ import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
3
+
2
4
  import { AssetReference } from "./engine_addressables.js";
3
5
  import { getBoundingBox } from "./engine_three_utils.js";
4
- import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
5
6
 
6
7
  declare type ComparisonSceneOptions = {
7
8
  /**
@@ -59,7 +60,7 @@
59
60
  scene.add(camera);
60
61
 
61
62
  // Load an environment map
62
- let environmentUrl = opts.environment || "https://dl.polyhaven.org/file/ph-assets/HDRIs/exr/1k/studio_small_09_1k.exr";
63
+ const environmentUrl = opts.environment || "https://dl.polyhaven.org/file/ph-assets/HDRIs/exr/1k/studio_small_09_1k.exr";
63
64
  if (environmentUrl) {
64
65
  let loader: DataTextureLoader | null = null;
65
66
  if (environmentUrl.endsWith(".hdr")) {
src/engine/engine_utils_format.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { getParam } from "./engine_utils";
1
+ import { getParam } from "./engine_utils.js";
2
2
 
3
3
  const debug = getParam("debugfileformat");
4
4
 
5
5
  /**
6
6
  * The supported file types that can be determined by the engine. Used in {@link tryDetermineFileTypeFromURL} and {@link tryDetermineFileTypeFromBinary}
7
7
  */
8
- export declare type FileType = "gltf" | "glb" | "fbx" | "obj" | "usdz" | "usd" | "unknown";
8
+ export declare type FileType = "gltf" | "glb" | "fbx" | "obj" | "usdz" | "usd" | "usda" | "unknown";
9
9
 
10
10
  /**
11
11
  * Tries to determine the file type of a file from its URL
@@ -62,6 +62,10 @@
62
62
  if (bytes[0] == 80 && bytes[1] == 88 && bytes[2] == 82 && bytes[3] == 45 && bytes[4] == 85 && bytes[5] == 83 && bytes[6] == 68 && bytes[7] == 67) {
63
63
  return "usd";
64
64
  }
65
+ // USDA: check if the file starts with #usda
66
+ else if(bytes[0] == 35 && bytes[1] == 117 && bytes[2] == 115 && bytes[3] == 100 && bytes[4] == 97) {
67
+ return "usda";
68
+ }
65
69
  // FBX
66
70
  if (bytes[0] == 75 && bytes[1] == 97 && bytes[2] == 121 && bytes[3] == 100 && bytes[4] == 97 && bytes[5] == 114 && bytes[6] == 97 && bytes[7] == 32) {
67
71
  return "fbx";
src/engine/engine_utils_screenshot.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { Camera, Color, PerspectiveCamera } from "three";
2
2
 
3
+ import { Renderer } from "../engine-components/Renderer.js";
4
+ import { getComponentsInChildren } from "./engine_components.js";
3
5
  import { ContextRegistry } from "./engine_context_registry.js";
4
6
  import { Context } from "./engine_setup.js";
5
7
 
@@ -33,7 +35,7 @@
33
35
  /**
34
36
  * The context to take the screenshot from. If not provided, the current context will be used.
35
37
  */
36
- context?: Pick<Context, "renderer" | "mainCamera" | "renderNow" | "updateAspect" | "updateSize">,
38
+ context?: Pick<Context, "scene" | "renderer" | "mainCamera" | "renderNow" | "updateAspect" | "updateSize">,
37
39
  /**
38
40
  * The width of the screenshot - if not provided, the width of the current renderer will be used.
39
41
  */
@@ -53,7 +55,20 @@
53
55
  /**
54
56
  * If true, the background will be transparent.
55
57
  */
56
- transparent?: boolean
58
+ transparent?: boolean,
59
+
60
+ /**
61
+ * If set the screenshot will be downloaded using the provided filename.
62
+ * NOTE: if you need more control you can manually download the returned image using {@link saveImage}
63
+ * @default undefined
64
+ */
65
+ download_filename?: string,
66
+
67
+ /**
68
+ * If true onBeforeRender and onAfterRender will be invoked on all renderers in the scene.
69
+ * @default true
70
+ */
71
+ render_events?: boolean,
57
72
  };
58
73
 
59
74
  /**
@@ -127,10 +142,27 @@
127
142
  if (camera instanceof PerspectiveCamera)
128
143
  context.updateAspect(camera, width, height);
129
144
 
145
+
146
+ // Calling onBeforeRender to update objects with reflection probes. https://linear.app/needle/issue/NE-5112
147
+ const callRenderEvents = opts.render_events !== false;
148
+ const renderers = new Array<Renderer>();
149
+ if (callRenderEvents) {
150
+ getComponentsInChildren(context.scene, Renderer, renderers);
151
+ renderers.forEach(r => r?.onBeforeRender());
152
+ }
153
+
130
154
  // render now
131
155
  context.renderNow();
132
156
 
157
+ if (callRenderEvents)
158
+ renderers.forEach(r => r.onAfterRender());
159
+
133
160
  const dataUrl = canvas.toDataURL(mimeType);
161
+
162
+ if (opts.download_filename) {
163
+ saveImage(dataUrl, opts.download_filename);
164
+ }
165
+
134
166
  return dataUrl;
135
167
  }
136
168
  finally {
src/engine/export/gltf/index.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import { AnimationClip, Object3D } from "three";
2
+ import { GLTFExporter, GLTFExporterOptions } from "three/examples/jsm/exporters/GLTFExporter";
3
+
4
+ import GLTFMeshGPUInstancingExtension from "../../../include/three/EXT_mesh_gpu_instancing_exporter.js";
5
+ import { AnimationUtils } from "../../engine_animation.js";
2
6
  import type { Context } from "../../engine_setup.js";
3
- import { GLTFExporter, GLTFExporterOptions } from "three/examples/jsm/exporters/GLTFExporter";
4
- import GLTFMeshGPUInstancingExtension from "../../../include/three/EXT_mesh_gpu_instancing_exporter";
5
7
  import { registerExportExtensions } from "../../extensions/index.js";
6
- import { AnimationUtils } from "../../engine_animation.js";
7
8
  import { __isExporting } from "../state.js";
8
9
  import { GizmoWriter as GLTFGizmoWriter, RenderTextureWriter as GLTFRenderTextureWriter } from "./Writers.js";
9
10
 
src/engine-components/timeline/PlayableDirector.ts CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { FrameEvent } from '../../engine/engine_context.js';
4
4
  import { isLocalNetwork } from '../../engine/engine_networking_utils.js';
5
+ import { serializable } from '../../engine/engine_serialization.js';
5
6
  import type { GuidsMap } from '../../engine/engine_types.js';
6
7
  import { deepClone, delay, getParam } from '../../engine/engine_utils.js';
7
8
  import { Animator } from '../Animator.js';
@@ -11,7 +12,6 @@
11
12
  import { SignalReceiver } from './SignalAsset.js';
12
13
  import * as Models from "./TimelineModels.js";
13
14
  import * as Tracks from "./TimelineTracks.js";
14
- import { serializable } from '../../engine/engine_serialization.js';
15
15
 
16
16
  const debug = getParam("debugtimeline");
17
17
 
src/engine-components/RendererLightmap.ts CHANGED
@@ -73,7 +73,10 @@
73
73
  }
74
74
 
75
75
  if (this.gameObject.type === "Group") {
76
- console.warn("Lightmap on multimaterial object is not supported yet... please open a feature request on https://github.com/needle-tools/needle-engine-support if your project requires it");
76
+ if (this.gameObject["Needle:Multimaterial-LightmapWarning"] === undefined) {
77
+ this.gameObject["Needle:Multimaterial-LightmapWarning"] = true;
78
+ console.warn("Lightmap on multimaterial object is not supported yet... please open a feature request on https://github.com/needle-tools/needle-engine-support if your project requires it");
79
+ }
77
80
  return;
78
81
  }
79
82
 
src/engine/export/gltf/Writers.ts CHANGED
@@ -1,9 +1,10 @@
1
1
 
2
2
  import { Object3D, Texture } from 'three';
3
3
  import { GLTFExporterPlugin, GLTFWriter } from 'three/examples/jsm/exporters/GLTFExporter.js';
4
+
5
+ import { RGBAColor } from '../../../engine-components/js-extensions/index.js';
4
6
  import { Gizmos } from '../../engine_gizmos.js';
5
7
  import { createFlatTexture } from '../../engine_shaders.js';
6
- import { RGBAColor } from '../../../engine-components/js-extensions/index.js';
7
8
 
8
9
  declare type BeforeWriteArgs = { keep: boolean };