Needle Engine

Changes between version 4.1.0-beta and 3.51.4
Files changed (130) hide show
  1. plugins/next/alias.cjs +2 -0
  2. plugins/common/config.cjs +1 -1
  3. plugins/next/license.cjs +3 -17
  4. plugins/vite/alias.js +10 -28
  5. plugins/vite/asap.js +17 -196
  6. plugins/vite/build-pipeline.js +69 -256
  7. plugins/common/buildinfo.js +3 -4
  8. plugins/vite/buildinfo.js +14 -20
  9. plugins/common/config.js +2 -2
  10. plugins/vite/config.js +6 -7
  11. plugins/vite/copyfiles.js +67 -68
  12. plugins/vite/defines.js +3 -20
  13. plugins/vite/dependencies.js +16 -196
  14. plugins/vite/drop.js +0 -5
  15. plugins/common/files.js +0 -32
  16. plugins/vite/index.js +5 -10
  17. plugins/common/license.js +0 -191
  18. plugins/vite/license.js +11 -14
  19. plugins/next/next.js +0 -2
  20. plugins/vite/peer.js +3 -1
  21. plugins/vite/reload.js +1 -2
  22. src/engine/assets/static.js +0 -5
  23. plugins/common/timers.js +0 -8
  24. plugins/common/version.js +2 -19
  25. src/engine-components/Animation.ts +4 -4
  26. src/engine-components/postprocessing/Effects/Antialiasing.ts +6 -6
  27. src/engine-components/api.ts +1 -2
  28. src/engine/api.ts +1 -2
  29. src/engine-components/AvatarLoader.ts +3 -2
  30. src/engine-components/postprocessing/Effects/BloomEffect.ts +5 -6
  31. src/engine-components/ui/Button.ts +1 -1
  32. src/engine-components/postprocessing/Effects/ChromaticAberration.ts +2 -2
  33. src/engine-components/Collider.ts +2 -6
  34. src/engine-components/postprocessing/Effects/ColorAdjustments.ts +3 -3
  35. src/engine-components/Component.ts +2 -2
  36. src/engine-components/codegen/components.ts +140 -140
  37. src/engine/debug/debug_spatial_console.ts +0 -1
  38. src/engine-components/postprocessing/Effects/DepthOfField.ts +2 -3
  39. src/engine-components/DragControls.ts +7 -7
  40. src/engine-components/DropListener.ts +63 -282
  41. src/engine-components/postprocessing/Effects/EffectWrapper.ts +1 -1
  42. src/engine/engine_addressables.ts +2 -2
  43. src/engine/engine_animation.ts +2 -2
  44. src/engine/engine_components_internal.ts +7 -5
  45. src/engine/engine_components.ts +3 -3
  46. src/engine/engine_constants.ts +6 -11
  47. src/engine/engine_context_registry.ts +2 -2
  48. src/engine/engine_context.ts +13 -35
  49. src/engine/engine_element_attributes.ts +1 -1
  50. src/engine/engine_element.ts +16 -44
  51. src/engine/engine_gameobject.ts +2 -2
  52. src/engine/engine_gizmos.ts +0 -1
  53. src/engine/engine_gltf_builtin_components.ts +5 -14
  54. src/engine/engine_gltf.ts +5 -3
  55. src/engine/engine_input.ts +0 -7
  56. src/engine/engine_license.ts +3 -5
  57. src/engine/engine_loaders.ts +13 -14
  58. src/engine/engine_lods.ts +0 -5
  59. src/engine/engine_modules.ts +0 -84
  60. src/engine/engine_networking_auto.ts +26 -26
  61. src/engine/engine_networking_blob.ts +0 -254
  62. src/engine/engine_networking_files_default_components.ts +3 -5
  63. src/engine/engine_networking_files.ts +151 -160
  64. src/engine/engine_networking_instantiate.ts +8 -19
  65. src/engine/engine_networking_streams.ts +1 -1
  66. src/engine/engine_networking.ts +26 -91
  67. src/engine/engine_physics_rapier.ts +72 -112
  68. src/engine/engine_physics.ts +31 -45
  69. src/engine/engine_scenetools.ts +30 -35
  70. src/engine/engine_serialization_builtin_serializer.ts +3 -3
  71. src/engine/engine_serialization_core.ts +2 -16
  72. src/engine/engine_texture.ts +3 -6
  73. src/engine/engine_tonemapping.ts +5 -10
  74. src/engine/engine_types.ts +13 -23
  75. src/engine/engine_utils_format.ts +19 -30
  76. src/engine/engine_utils_screenshot.ts +41 -416
  77. src/engine/engine_utils_screenshot.xr.ts +0 -104
  78. src/engine-components/EventList.ts +6 -9
  79. src/engine-components/EventTrigger.ts +1 -1
  80. src/engine-components/export/gltf/GltfExport.ts +7 -17
  81. plugins/types/index.d.ts +3 -3
  82. src/engine/analytics/index.ts +0 -11
  83. src/engine/assets/index.ts +4 -2
  84. src/engine-components/ui/InputField.ts +2 -2
  85. src/engine/analytics/lcp.ts +0 -35
  86. plugins/types/license.d.ts +4 -18
  87. src/engine/extensions/NEEDLE_components.ts +3 -11
  88. src/asap/needle-asap.ts +32 -26
  89. src/needle-engine.ts +15 -26
  90. src/engine/webcomponents/needle menu/needle-menu-spatial.ts +0 -1
  91. src/engine/webcomponents/needle menu/needle-menu.ts +2 -2
  92. plugins/types/needleConfig.d.ts +1 -4
  93. src/engine/xr/NeedleXRController.ts +5 -2
  94. src/engine/xr/NeedleXRSession.ts +8 -15
  95. src/engine-components/NestedGltf.ts +2 -7
  96. src/engine/js-extensions/Object3D.ts +0 -4
  97. src/engine-components/OrbitControls.ts +9 -18
  98. src/engine-components/particlesystem/ParticleSystem.ts +17 -42
  99. src/engine-components/particlesystem/ParticleSystemModules.ts +12 -25
  100. src/engine-components/particlesystem/ParticleSystemSubEmitter.ts +6 -6
  101. src/engine-components/postprocessing/Effects/Pixelation.ts +2 -3
  102. src/engine-components-experimental/networking/PlayerSync.ts +1 -1
  103. src/engine-components/postprocessing/PostProcessingEffect.ts +1 -1
  104. src/engine-components/postprocessing/PostProcessingHandler.ts +47 -75
  105. src/engine/codegen/register_types.ts +290 -290
  106. src/engine-components/RendererInstancing.ts +45 -198
  107. src/engine-components/RigidBody.ts +0 -2
  108. src/engine-components/SceneSwitcher.ts +13 -41
  109. src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.ts +5 -6
  110. src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.ts +2 -3
  111. src/engine-components/postprocessing/Effects/Sharpening.ts +59 -72
  112. src/engine-components/timeline/SignalAsset.ts +1 -1
  113. src/engine-components/Skybox.ts +5 -21
  114. src/engine-components/SpatialTrigger.ts +3 -3
  115. src/engine-components/ui/Text.ts +0 -1
  116. src/engine-components/export/usdz/ThreeUSDZExporter.ts +1 -1
  117. src/engine-components/postprocessing/Effects/TiltShiftEffect.ts +6 -6
  118. src/engine-components/postprocessing/Effects/Tonemapping.ts +8 -9
  119. src/engine-components/TransformGizmo.ts +5 -6
  120. plugins/types/userconfig.d.ts +6 -29
  121. src/engine-components/VideoPlayer.ts +1 -1
  122. src/engine-components/postprocessing/Effects/Vignette.ts +2 -3
  123. src/engine-components/postprocessing/Volume.ts +12 -27
  124. src/engine-components/webxr/WebARCameraBackground.ts +135 -70
  125. src/engine-components/webxr/WebXR.ts +2 -2
  126. src/engine-components/webxr/controllers/XRControllerModel.ts +40 -54
  127. plugins/common/license.cjs +116 -0
  128. src/engine/engine_web_api.ts +120 -0
  129. src/engine/engine.ts +14 -0
  130. src/engine-components/FlyControls.ts +36 -0
plugins/next/alias.cjs CHANGED
@@ -37,4 +37,6 @@
37
37
  }
38
38
  }
39
39
 
40
+ console.log(config.resolve.alias);
41
+
40
42
  }
plugins/common/config.cjs CHANGED
@@ -7,7 +7,7 @@
7
7
  if (needleConfig.codegenDirectory) {
8
8
  const metaPath = workingDirectory + "/" + needleConfig.codegenDirectory + "/meta.json";
9
9
 
10
- /**@type {import("../types").needleMeta} */
10
+ /**@type {import("../types").needleConfig} */
11
11
  const meta = require(metaPath);
12
12
  return meta;
13
13
  }
plugins/next/license.cjs CHANGED
@@ -1,19 +1,5 @@
1
- const { getMeta } = require("../common/config.cjs");
1
+ const { replaceLicense } = require("../common/license.cjs");
2
2
 
3
- const mod = import("../common/license.js");
4
-
5
- module.exports = async function (source, _map) {
6
-
7
- /** @type {string | undefined} */
8
- let team = undefined;
9
-
10
- const meta = await getMeta();
11
- if (meta) {
12
- team = meta.license?.team;
13
- }
14
-
15
- // console.log("RESOLVE LICENSE...");
16
- return (await mod).replaceLicense(source, {
17
- team: team,
18
- });
3
+ module.exports = function (source, _map) {
4
+ return replaceLicense(source);
19
5
  };
plugins/vite/alias.js CHANGED
@@ -7,9 +7,6 @@
7
7
  * the first argument is the already resoled absolute path (it is only invoked if the path was found in node_modules)
8
8
  * the 2,3,4 args are the same as in vite.alias (packageName, index, path);
9
9
  */
10
- /**
11
- * @type {Record<string, null | ((res: string, packageName: string, index: number, path: string) => string | null | void)>}
12
- */
13
10
  const packages_to_resolve = {
14
11
  // Handle all previous imports where users did import using @needle-engine/src
15
12
  '@needle-tools/engine/src': (res, packageName, index, path) => {
@@ -18,11 +15,6 @@
18
15
  return res + "/../lib";
19
16
  }
20
17
  },
21
- /*
22
- Removed the previously present @needle-tools/engine entry
23
- because this is automatically done by vite according to whatever we define in our package.json exports
24
- This did previously prevent us from declaring proper exports in package.json
25
- */
26
18
  '@needle-tools/engine': (res, packageName, index, path) => {
27
19
  // Check if the import is something like @needle-tools/engine/engine/engine_utils
28
20
  // in which case we want to resolve into the lib directory
@@ -30,9 +22,7 @@
30
22
  return res + "/lib";
31
23
  }
32
24
  },
33
-
34
- /*
35
- Removed. Three.js is manually resolved below to ensure all dependencies resolve to the same three.js version.
25
+ /* Removed. Three.js is manually resolved below to ensure all dependencies resolve to the same three.js version.
36
26
  'three': null,
37
27
  */
38
28
  'peerjs': null,
@@ -63,12 +53,12 @@
63
53
  outputDebugFile.write(`[needle-alias] Logging to: ${outputFilePath} (${timestamp})\n`);
64
54
  log("[needle-alias] Logging to: ", outputFilePath);
65
55
  }
56
+
66
57
 
67
-
68
58
  const aliasPlugin = {
69
59
  name: "needle-alias",
70
60
  config(config) {
71
- if (debug) console.log('[needle-alias] ProjectDirectory: ' + projectDir);
61
+ if (debug) console.log('[needle-alias] ProjectDirectory: ' + projectDir);
72
62
  if (!config.resolve) config.resolve = {};
73
63
  if (!config.resolve.alias) config.resolve.alias = {};
74
64
  const aliasDict = config.resolve.alias;
@@ -133,38 +123,30 @@
133
123
  aliasDict['three/addons'] = (res, packageName, index, path) => {
134
124
  return "three/examples/jsm";
135
125
  };
126
+ aliasDict['three'] = (res, packageName, index, _path) => {
127
+ return path.resolve(projectDir, 'node_modules', 'three');
128
+ };
136
129
  aliasDict['three/nodes'] = (res, packageName, index, path) => {
137
130
  return "three/examples/jsm/nodes/Nodes.js";
138
131
  };
139
- aliasDict['three'] = (res, packageName, index, _path) => {
140
- return path.resolve(projectDir, 'node_modules', 'three');
141
- };
142
132
  }
143
133
 
144
134
  function addPathResolver(name, aliasDict, cb) {
145
135
  // If a package at the node_modules path exist we resolve the request there
146
136
  // introduced in 89a50718c38940abb99ee16c5e029065e41d7d65
147
- const fullpath = path.resolve(projectDir, 'node_modules', name);
137
+ const res = path.resolve(projectDir, 'node_modules', name);
148
138
  if (typeof cb !== "function") cb = null;
149
139
  const isDevEnvironment = process.env.NODE_ENV === "development";
150
-
151
- if (existsSync(fullpath)) {
140
+ if (existsSync(res)) {
152
141
  aliasDict[name] = (packageName, index, path) => {
153
142
  if (cb !== null && !isDevEnvironment) {
154
- const overrideResult = cb(fullpath, packageName, index, path);
143
+ const overrideResult = cb(res, packageName, index, path);
155
144
  if (overrideResult !== undefined)
156
145
  if (existsSync(overrideResult)) {
157
- console.warn(`[needle-alias] \"${path}\" was requested and resolved to \"${overrideResult}\"`);
158
146
  return overrideResult;
159
147
  }
160
148
  }
161
-
162
- if (path != packageName) {
163
- // TODO: we might want to check if the package.json exports contains the path to see if it's valid
164
- console.warn(`[needle-alias] \"${path}\" was requested and resolved to \"${fullpath}\"`);
165
- }
166
-
167
- return fullpath;
149
+ return res;
168
150
  }
169
151
  }
170
152
  }
plugins/vite/asap.js CHANGED
@@ -1,16 +1,12 @@
1
- import { existsSync, readdirSync, readFileSync, writeFileSync } from 'fs';
2
- import path from 'path';
3
- import { preloadScriptPaths } from './dependencies.js';
1
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
4
2
 
5
3
  const code = `import('@needle-tools/engine/src/asap/needle-asap.ts');`
6
4
 
7
5
 
8
-
9
6
  /**
10
7
  * Injects needle asap script into the index.html for when the main needle engine bundle is still being downloaded
11
- * @param {"build" | "serve"} command
12
8
  * @param {import('../types').userSettings} userSettings
13
- * @returns {Promise<import('vite').Plugin[] | null>}
9
+ * @returns {Promise<import('vite').Plugin | null>}
14
10
  */
15
11
  export const needleAsap = async (command, config, userSettings) => {
16
12
 
@@ -18,94 +14,30 @@
18
14
 
19
15
  fixMainTs();
20
16
 
21
- if (command != "build") {
22
- return null;
23
- }
24
-
25
- let logoSvg = "";
26
- try {
27
- const assets = await import("../../src/engine/assets/static.js");
28
- logoSvg = assets.NEEDLE_LOGO_SVG_URL;
29
- }
30
- catch (err) {
31
- console.warn("Could not load needle logo svg", err.message);
32
- }
33
-
34
- /** @type {import("vite").ResolvedConfig} */
35
- let viteConfig = null;
36
-
37
- return [{
17
+ return {
38
18
  name: 'needle:asap',
39
- configResolved(config) {
40
- viteConfig = config;
41
- },
42
19
  transformIndexHtml: {
43
20
  order: 'pre',
44
21
  handler(html, _ctx) {
45
- /** @type {import('vite').HtmlTagDescriptor[]} */
46
- const tags = [];
47
-
48
- if (logoSvg?.length) {
49
- tags.push({
50
- tag: 'link',
51
- attrs: {
52
- rel: "preload",
53
- fetchpriority: "high",
54
- as: "image",
55
- href: logoSvg,
56
- type: "image/svg+xml",
57
- }
58
- })
59
- }
60
-
61
-
62
- try {
63
- generateGltfPreloadLinks(config, html, tags);
64
- }
65
- catch (err) {
66
- console.error("Error generating gltf preload links", err);
67
- }
68
-
69
- // preconnect to gstatic.com and fonts.googleapis.com to safe 100ms according to lighthouse
70
- tags.push({
71
- tag: 'link',
72
- attrs: {
73
- rel: "preconnect",
74
- href: "https://fonts.gstatic.com",
22
+ if (existsSync(process.cwd() + "/node_modules/@needle-tools/engine/src/asap/needle-asap.ts")) {
23
+ return {
24
+ html,
25
+ tags: [
26
+ {
27
+ tag: 'script',
28
+ children: code,
29
+ attrs: {
30
+ type: "module",
31
+ async: true,
32
+ }
33
+ },
34
+ ]
75
35
  }
76
- });
77
- tags.push({
78
- tag: 'link',
79
- attrs: {
80
- rel: "preconnect",
81
- href: "https://fonts.googleapis.com",
82
- }
83
- });
84
-
85
- return {
86
- html,
87
- tags
88
36
  }
89
37
  }
90
38
  },
91
- },
92
- {
93
- name: "needle:asap:post",
94
- transformIndexHtml: {
95
- order: 'post',
96
- handler(html, _ctx) {
39
+ }
97
40
 
98
- /** @type {import('vite').HtmlTagDescriptor[]} */
99
- const tags = [];
100
- // we need to wait for the files to exist
101
- generateScriptPreloadLinks(viteConfig, tags);
102
- return {
103
- html,
104
- tags
105
- }
106
- }
107
- }
108
- }]
109
41
  }
110
42
 
111
43
  function fixMainTs() {
@@ -120,115 +52,4 @@
120
52
  writeFileSync(mainTsFilePath, code);
121
53
  }
122
54
  }
123
- }
124
-
125
- /**
126
- * @param {import('vite').ResolvedConfig} _config
127
- * @param {import('vite').HtmlTagDescriptor[]} tags
128
- */
129
- function generateScriptPreloadLinks(_config, tags) {
130
- try {
131
- const chunks = preloadScriptPaths;
132
- // console.log("ASAP", chunks)
133
- if (chunks.length > 0) {
134
- for (const chunk of chunks) {
135
- tags.push({
136
- tag: 'link',
137
- attrs: {
138
- rel: "modulepreload",
139
- as: "script",
140
- href: chunk,
141
- }
142
- });
143
- }
144
- }
145
- }
146
- catch (err) {
147
- console.error("Error generating script preload links", err);
148
- }
149
- }
150
-
151
-
152
- // https://regex101.com/r/I9k2nx/1
153
- // @ts-ignore
154
- const codegenRegex = /\"(?<gltf>.+(.glb|.gltf)(\?.*)?)\"/gm;
155
-
156
- // https://regex101.com/r/SVhzzD/1
157
- // @ts-ignore
158
- const needleEngineRegex = /<needle-engine.*?src=["'](?<src>.+)["']>/gm;
159
-
160
- /**
161
- * @param {import('../types').needleConfig} config
162
- * @param {string} html
163
- * @param {import('vite').HtmlTagDescriptor[]} tags
164
- **/
165
- function generateGltfPreloadLinks(config, html, tags) {
166
-
167
- // TODO: try to get the <needle-engine src> element src attribute and preload that
168
- const needleEngineMatches = html.matchAll(needleEngineRegex);
169
- if (needleEngineMatches) {
170
- while (true) {
171
- const match = needleEngineMatches.next();
172
- if (match.done) break;
173
- /** @type {null | string} */
174
- const value = match.value?.groups?.src;
175
- if (value) {
176
- if (value.startsWith("[")) {
177
- // we have an array assigned
178
- const arr = JSON.parse(value);
179
- for (const item of arr) {
180
- insertPreloadLink(tags, item, "model/gltf+json");
181
- }
182
- }
183
- else {
184
- insertPreloadLink(tags, value, "model/gltf+json");
185
- }
186
- }
187
- }
188
- }
189
-
190
-
191
- // TODO: we should export the entrypoint files to our meta file perhaps to make it easier to generate preload links
192
-
193
- // We can not simply preload ALL the files in the assets folder because that would be too much and we don't know what the user ACTUALLY wants
194
- let codegen_path = "/src/generated/";
195
- if (config.codegenDirectory) {
196
- codegen_path = config.codegenDirectory;
197
- }
198
- codegen_path = path.join(process.cwd(), codegen_path, "gen.js");
199
- if (existsSync(codegen_path)) {
200
- const code = readFileSync(codegen_path, "utf8");
201
- if (code) {
202
- const matches = code.matchAll(codegenRegex);
203
- if (matches) {
204
- while (true) {
205
- const match = matches.next();
206
- if (match.done) break;
207
- const value = match.value?.groups?.gltf;
208
- if (value) {
209
- insertPreloadLink(tags, value, "model/gltf+json");
210
- }
211
- }
212
- }
213
- }
214
- }
215
- }
216
-
217
- /**
218
- * @param {import('vite').HtmlTagDescriptor[]} tags
219
- * @param {string} href
220
- * @param {string} type
221
- */
222
- function insertPreloadLink(tags, href, type) {
223
- if (!href) return;
224
- tags.push({
225
- tag: 'link',
226
- attrs: {
227
- rel: "preload",
228
- as: "fetch",
229
- href: href,
230
- type: type,
231
- crossorigin: true,
232
- }
233
- });
234
55
  }
plugins/vite/build-pipeline.js CHANGED
@@ -1,85 +1,21 @@
1
- import { ChildProcess, exec } from 'child_process';
2
- import { getOutputDirectory, loadConfig } from './config.js';
3
- import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'fs';
4
- import { copyFilesSync } from '../common/files.js';
5
- import { delay } from '../common/timers.js';
1
+ import { ChildProcess, exec, execSync, spawn } from 'child_process';
2
+ import { getOutputDirectory, loadConfig, tryLoadProjectConfig } from './config.js';
3
+ import { existsSync, readFileSync, readdirSync, writeFileSync } from 'fs';
6
4
 
7
- /**
8
- * @param {import('../types').userSettings} config
9
- * @returns {boolean}
10
- */
11
- function validateCloudBuildConfiguration(config) {
12
- if (config.buildPipeline != undefined) {
13
- if (process.env.CI) {
14
- if ((process.env.NEEDLE_CLOUD_TOKEN == undefined || process.env.NEEDLE_CLOUD_TOKEN.length <= 0)) {
15
- const isGithubAction = process.env.CI && process.env.GITHUB_ACTION;
16
- let msg = `Missing Needle Cloud access token. Please set your Needle Cloud token via \`process.env.NEEDLE_CLOUD_TOKEN\`.`;
17
- if (isGithubAction) {
18
- msg += `
19
- Make sure to pass the token as a secret to the Github action.
20
- For this you may have to modify your .github workflow yaml file to include the following code:
21
- env:
22
- - NEEDLE_CLOUD_TOKEN: \${{ secrets.NEEDLE_CLOUD_TOKEN }}
23
- `;
24
- let error = `${msg}`;
25
- throw new Error(error);
26
- }
27
- }
28
- }
29
- }
30
-
31
- return true;
32
- }
33
-
34
5
  // see https://linear.app/needle/issue/NE-3798
35
6
 
7
+ export let buildPipelineTask;
36
8
 
37
- /** @type {Promise<any>|null} */
38
- let buildPipelineTask;
39
- /** @type {null | {tempDirectory:string, outputDirectory:string}} */
40
- let buildPipelineTaskResults = null;
41
-
42
- export function waitForBuildPipelineToFinish() {
43
- return buildPipelineTask;
44
- }
45
-
46
- /** This time is set when a build plugin is triggered to run
47
- * We increase the time by 10-20 seconds each time because we might have a multi step process
48
- * where the build pipeline is triggered in the SSR build (which we can not always detect)
49
- * and the final client build is triggered later (but the build pipeline is still running and waiting)
50
- */
51
- let maxOutputDirectoryCreatedWaitTime = 0;
52
9
  /**
53
- * @param {boolean} debugLog
54
- */
55
- function increaseMaxWaitTime(debugLog) {
56
- maxOutputDirectoryCreatedWaitTime = Date.now();
57
- let maxWaitTime = 10_000;
58
- if (process.env.CI) {
59
- maxWaitTime += 50_000;
60
- }
61
- maxOutputDirectoryCreatedWaitTime += maxWaitTime;
62
- if (debugLog) {
63
- log(`Increased max wait time by ${maxWaitTime / 1000}sec until ${new Date(maxOutputDirectoryCreatedWaitTime).toISOString()}`);
64
- }
65
- }
66
-
67
- /**
68
10
  * Runs the needle build pipeline as part of the vite build process
69
- * @param {string} command
70
- * @param {import('vite').UserConfig} config
71
11
  * @param {import('../types').userSettings} userSettings
72
- * @returns {Promise<import('vite').Plugin | null>}
12
+ * @returns {import('vite').Plugin}
73
13
  */
74
14
  export const needleBuildPipeline = async (command, config, userSettings) => {
75
15
 
76
16
  // we only want to run compression here if this is a distribution build
77
17
  // this is handled however in the `apply` hook
78
- if (userSettings.noBuildPipeline) return null;
79
- if (userSettings.buildPipeline?.enabled === false) {
80
- log("Skipping build pipeline because it is disabled in the user settings via `buildPipeline.enabled: false`");
81
- return null;
82
- }
18
+ if (userSettings.noBuildPipeline) return;
83
19
 
84
20
  const packageJsonPath = process.cwd() + "/package.json";
85
21
  await fixPackageJson(packageJsonPath);
@@ -90,102 +26,53 @@
90
26
  if (productionArgument >= 0) {
91
27
  shouldRun = true;
92
28
  }
29
+ else {
30
+ const meta = await loadConfig();
31
+ if (meta && meta.developmentBuild === false) {
32
+ shouldRun = true;
33
+ }
34
+ }
93
35
 
94
36
  if (!shouldRun) {
95
37
  log("Skipping build pipeline because this is a development build.\n- Invoke with `--production` to run the build pipeline.\n- For example \"vite build -- --production\".");
96
38
  await new Promise((resolve, _) => setTimeout(resolve, 1000));
97
- return null;
39
+ return;
98
40
  }
99
41
 
100
- if (process.env.CI) {
101
- log("Running in CI environment");
102
- }
103
-
104
- validateCloudBuildConfiguration(userSettings);
105
-
106
- const verboseOutput = userSettings?.buildPipeline?.verbose || false;
107
- let taskHasCompleted = false;
108
-
42
+ /** @type {Promise<any>|null} */
43
+ let task = null;
44
+ let taskFinished = false;
45
+ let taskSucceeded = false;
109
46
  return {
110
47
  name: 'needle:buildpipeline',
111
48
  enforce: "post",
112
- apply: (_conf, env) => {
113
- if (verboseOutput) {
114
- log("Apply:", env);
115
- }
116
- // Don't run for SSR builds (e.g. sveltekit).
117
- // Unfortunately this is always falls in vite 4.3 so we can not rely on it solely
118
- if (env.ssrBuild) return false;
119
- // Dont run if there's already a build pipeline task running
120
- if (env.command === "build") {
121
- increaseMaxWaitTime(verboseOutput);
122
- if (buildPipelineTask) {
123
- return false;
124
- }
125
- return true;
126
- }
127
- return false;
49
+ apply: 'build',
50
+ buildEnd() {
51
+ // start the compression process once vite is done copying the files
52
+ task = invokeBuildPipeline(userSettings).then((res) => {
53
+ taskFinished = true;
54
+ taskSucceeded = res;
55
+ });
56
+ buildPipelineTask = task;
128
57
  },
129
- buildEnd(error) {
130
- increaseMaxWaitTime(verboseOutput);
131
-
132
- if (verboseOutput) {
133
- log("Build end:", error ?? "No error");
134
- }
135
- if (error) {
136
- // if there was an error during the build we should not run the build pipeline
137
- }
138
- else {
139
- if (buildPipelineTask) {
140
- log("Build pipeline already running...");
141
- return;
142
- }
143
- let taskSucceeded = false;
144
- // start the compression process once vite is done copying the files
145
- buildPipelineTask = invokeBuildPipeline(userSettings)
146
- .then((res) => {
147
- taskSucceeded = res;
148
- })
149
- .finally(() => {
150
- taskHasCompleted = true;
151
- if (!taskSucceeded) {
152
- throw new Error("[needle-buildpipeline] - Build pipeline failed. Check the logs for more information.");
153
- }
154
- else {
155
- log("Finished successfully");
156
- }
157
- });
158
- }
159
- },
160
58
  closeBundle() {
161
- if (!buildPipelineTask) {
162
- return;
163
- }
164
- if (!taskHasCompleted) {
165
- log("Waiting for build pipeline to finish...");
166
- }
167
- // // this is the last hook that is called, so we can wait for the task to finish here
168
- return buildPipelineTask = buildPipelineTask?.then(() => {
169
- // Copy the results to their final output directory.
170
- if (buildPipelineTaskResults != null) {
171
- log("Copying files from temporary output directory to final output directory...");
172
- const ctx = { count: 0 }
173
- copyFilesSync(buildPipelineTaskResults.tempDirectory, buildPipelineTaskResults.outputDirectory, true, ctx);
174
- log(`Copied ${ctx.count} file(s)`);
175
- }
176
- else {
177
- log("No files to copy - build pipeline did not run or did not finish successfully");
178
- }
59
+ log("Waiting for postprocessing to finish...");
60
+ // this is the last hook that is called, so we can wait for the task to finish here
61
+ if (taskFinished) return;
62
+ // delay the final log slightly to give other plugins a chance to log their stuff
63
+ wait(100).then(() => {
64
+ if (!taskFinished) log("Waiting for postprocessing to finish...")
179
65
  });
66
+ return task.then(_ => {
67
+ log("finished", taskSucceeded ? "successfully" : "with errors");
68
+ });
180
69
  },
181
70
  }
182
71
  }
183
72
 
184
-
185
73
  /**
186
74
  * Previously we did always install the build pipeline and run an extra command to invoke the build pipeline.
187
75
  * This is now done automatically by the needle build pipeline plugin - so we update all legacy projects to use the new method.
188
- * @param {string} packageJsonPath
189
76
  */
190
77
  async function fixPackageJson(packageJsonPath) {
191
78
  if (!existsSync(packageJsonPath)) {
@@ -202,11 +89,9 @@
202
89
  writeFileSync(packageJsonPath, fixed);
203
90
  }
204
91
 
205
- /** @param {any} args */
206
92
  function log(...args) {
207
93
  console.log("[needle-buildpipeline]", ...args);
208
94
  }
209
- /** @param {any} args */
210
95
  function warn(...args) {
211
96
  console.warn("WARN: [needle-buildpipeline]", ...args);
212
97
  }
@@ -219,135 +104,63 @@
219
104
  const installPath = "node_modules/@needle-tools/gltf-build-pipeline";
220
105
  const fullInstallPath = process.cwd() + "/" + installPath;
221
106
  const existsLocally = existsSync(fullInstallPath);
222
- if (existsLocally) {
223
- log("Found local build pipeline installation at " + fullInstallPath);
107
+ if (!existsLocally) {
108
+ // await execSync("npx --yes @needle-tools/n")
109
+ // throw new Error(`ERR: Build pipeline not found at \"${fullInstallPath}\". \nTo disable this plugin you can pass \"noBuildPipeline: true\" to the needle config in vite.config.js`);
110
+ warn("@needle-tools/gltf-build-pipeline not found in package - using latest version")
224
111
  }
225
- await delay(500);
112
+ await wait(500);
226
113
  const outputDirectory = getOutputDirectory() + "/assets";
227
- const startWaitTime = Date.now();
228
- const maxEndTime = startWaitTime + 120_000;
229
- /** wait until the output directory exists
230
- * @param {number} iteration
231
- * @returns {Promise<boolean>}
232
- */
114
+ // wait until the output directory exists - this depends on speed
233
115
  function waitForOutputDirectory(iteration) {
234
- // we wait for the output directory
235
116
  if (!existsSync(outputDirectory)) {
236
- if (maxOutputDirectoryCreatedWaitTime != 0 && Date.now() > maxOutputDirectoryCreatedWaitTime) {
117
+ if (iteration > 10) {
237
118
  return Promise.resolve(false);
238
119
  }
239
- else if (Date.now() > maxEndTime) {
240
- log("Max wait time exceeded - aborting...");
241
- return Promise.resolve(false);
242
- }
243
- if (iteration <= 0) log(`Waiting for output directory to be created... (${outputDirectory})`);
244
- return delay(1000).then(() => waitForOutputDirectory(iteration + 1));
120
+ if (iteration <= 0) log("Waiting for output directory to be created...");
121
+ return wait(1000).then(() => waitForOutputDirectory(iteration + 1));
245
122
  }
246
123
  return Promise.resolve(true);
247
124
  }
248
125
  if (!await waitForOutputDirectory(0)) {
249
- warn(`Output directory not found/created at \"${outputDirectory}\" - aborting...`);
250
- return false;
126
+ warn("Directory not found at " + outputDirectory);
127
+ return;
251
128
  }
252
- const files = readdirSync(outputDirectory).filter(f => f.endsWith(".glb") || f.endsWith(".gltf") || f.endsWith(".vrm") || f.endsWith(".fbx"));
253
- log(`${files.length} file(s) to process in ${outputDirectory}`);
129
+ const files = readdirSync(outputDirectory).filter(f => f.endsWith(".glb") || f.endsWith(".gltf"));
130
+ log(files.length + " file(s) to process");
254
131
 
255
132
  /** @type {null | ChildProcess} */
256
- let proc = null;
133
+ let sub = null;
257
134
 
258
- let cloudAccessToken = opts.license?.accessToken;
259
- if (!cloudAccessToken) {
260
- cloudAccessToken = process.env.NEEDLE_CLOUD_TOKEN;
261
- }
262
- const runInCloud = typeof cloudAccessToken === "string" && cloudAccessToken.length > 0;
263
- // if a user has defined the build pipeline settings object but not passed in a token we should print out some information
264
- // or perhaps log an error / prevent the build from running completely
265
- if (opts.buildPipeline && !runInCloud && process.env.CI) {
266
- warn(`No cloud access token found. Please set it via process.env.NEEDLE_CLOUD_TOKEN`);
267
- return false;
268
- }
269
-
270
-
271
- // put the processed files first in a temporary directory. They will be moved to the output directory at the end of the buildstep
272
- // this is so that processes like sveltekit-static-adapter can run first and does not override already compressed files
273
- const tempOutputPath = process.cwd() + "/node_modules/.needle/build-pipeline/output";
274
- if (existsSync(tempOutputPath)) {
275
- log("Removing temporary output directory at " + tempOutputPath);
276
- rmSync(tempOutputPath, { recursive: true, force: true });
277
- }
278
- mkdirSync(tempOutputPath, { recursive: true });
279
-
280
- /** @param {number} code */
281
- function onExit(code) {
282
- if (code === 0)
283
- buildPipelineTaskResults = {
284
- tempDirectory: tempOutputPath,
285
- outputDirectory: outputDirectory
286
- }
287
- }
288
-
289
- // allow running the build pipeline in the cloud. It requires and access token to be set in the vite.config.js
290
- // this can be set via e.g. process.env.NEEDLE_CLOUD_TOKEN
291
- if (runInCloud) {
292
- if (!cloudAccessToken || !(typeof cloudAccessToken === "string") || cloudAccessToken.length <= 0) {
293
- throw new Error("No cloud access token configured. Please set it via process.env.NEEDLE_CLOUD_TOKEN or in the vite.config.js");
294
- }
295
- let cmd = `npx --yes needle-cloud@main optimize "${outputDirectory}" --token ${cloudAccessToken}`;
296
- let projectName = opts.buildPipeline?.projectName;
297
- // Default project name for compression
298
- // TODO: maybe this should be taken from the package.json name field or needle.config?
299
- if (!projectName) {
300
- projectName = "compression";
301
- }
302
- if (projectName) {
303
- cmd += ` --name "${projectName}"`;
304
- }
305
- if (opts.buildPipeline?.verbose === true) {
306
- cmd += " --verbose";
307
- }
308
- cmd += " --outdir \"" + tempOutputPath + "\"";
309
- console.log("\n")
310
- log("Running compression in cloud â›…");
311
- proc = exec(cmd);
312
- }
313
- else if (existsLocally) {
314
- const cmd = `needle-gltf transform "${outputDirectory}" \"${tempOutputPath}\"`;
135
+ if (existsLocally) {
136
+ const cmd = `needle-gltf transform "${outputDirectory}"`;
315
137
  log("Running command \"" + cmd + "\" at " + process.cwd() + "...");
316
- proc = exec(cmd, { cwd: installPath });
138
+ sub = exec(cmd, { cwd: installPath });
317
139
  }
318
140
  else {
319
- const version = opts.buildPipeline?.version || "latest";
320
- const cmd = `npx --yes @needle-tools/gltf-build-pipeline@${version} transform "${outputDirectory}" \"${tempOutputPath}\"`;
321
- log(`Running compression locally with version ${version}`);
322
- proc = exec(cmd);
141
+ const version = opts.buildPipelineVersion || "latest";
142
+ const cmd = `npx --yes @needle-tools/gltf-build-pipeline@${version} transform "${outputDirectory}"`;
143
+ log("Running command \"" + cmd);
144
+ sub = exec(cmd);
323
145
  }
324
- /** @param {any} data */
325
- function onLog(data) {
146
+ sub.stdout.on('data', data => {
326
147
  if (data.length <= 0) return;
327
148
  // ensure that it doesnt end with a newline
328
- while (data.endsWith("\n")) data = data.slice(0, -1);
329
- if (typeof data === "string") {
330
- if (data.startsWith("ERR:")) {
331
- console.error(data);
332
- return;
333
- }
334
- else if (data.startsWith("WARN:")) {
335
- console.warn(data);
336
- return;
337
- }
338
- // Ignore empty lines
339
- else if (data.trim().length <= 0) {
340
- return;
341
- }
342
- }
343
- log(data);
344
- }
345
- proc.stdout?.on('data', onLog);
346
- proc.stderr?.on('data', onLog);
149
+ if (data.endsWith("\n")) data = data.slice(0, -1);
150
+ console.log(data);
151
+ });
152
+ sub.stderr.on('data', console.error);
347
153
  return new Promise((resolve, reject) => {
348
- proc.on('exit', (code) => {
349
- onExit(code || 0);
154
+ sub.on('exit', (code) => {
350
155
  resolve(code === 0);
351
156
  });
352
157
  });
353
158
  }
159
+
160
+ function wait(ms) {
161
+ return new Promise((resolve, reject) => {
162
+ setTimeout(() => {
163
+ resolve();
164
+ }, ms);
165
+ });
166
+ }
plugins/common/buildinfo.js CHANGED
@@ -16,11 +16,11 @@
16
16
  totalsize: 0,
17
17
  files: []
18
18
  };
19
- console.log(`[needle-buildinfo] - Begin collecting files in \"${buildDirectory}\"`);
19
+ console.log("[needle-buildinfo] - Collect files in " + buildDirectory);
20
20
  recursivelyCollectFiles(buildDirectory, "", buildInfo);
21
21
  const buildInfoPath = `${buildDirectory}/needle.buildinfo.json`;
22
22
  const totalSizeInMB = buildInfo.totalsize / 1024 / 1024;
23
- console.log(`[needle-buildinfo] - Collected ${buildInfo.files.length} files (${totalSizeInMB.toFixed(2)} MB). Writing build info to \"${buildInfoPath}\"`);
23
+ console.log(`[needle-buildinfo] - Collected ${buildInfo.files.length} files (${totalSizeInMB.toFixed(2)} MB). Write info to \"${buildInfoPath}\"`);
24
24
  fs.writeFileSync(buildInfoPath, JSON.stringify(buildInfo));
25
25
  }
26
26
 
@@ -39,11 +39,10 @@
39
39
  }
40
40
  const newPath = path?.length <= 0 ? entry.name : `${path}/${entry.name}`;
41
41
  const newDirectory = `${directory}/${entry.name}`;
42
- console.log(`[needle-buildinfo] - Collect files in \"/${newPath}\"`);
42
+ console.log("[needle-buildinfo] - Collect files in " + newPath);
43
43
  recursivelyCollectFiles(newDirectory, newPath, info);
44
44
  } else {
45
45
  const relpath = `${path}/${entry.name}`;
46
- // console.log("[needle-buildinfo] - New File: " + relpath);
47
46
  const filehash = crypto.createHash('sha256');
48
47
  const fullpath = `${directory}/${entry.name}`;
49
48
  filehash.update(fs.readFileSync(fullpath));
plugins/vite/buildinfo.js CHANGED
@@ -1,38 +1,32 @@
1
1
  import { createBuildInfoFile } from '../common/buildinfo.js';
2
- import { waitForBuildPipelineToFinish } from './build-pipeline.js';
2
+ import { buildPipelineTask } from './build-pipeline.js';
3
3
  import { getOutputDirectory } from './config.js';
4
4
 
5
- let level = 0;
6
5
 
6
+
7
7
  /** Create a buildinfo file in the build directory
8
8
  * @param {import('../types').userSettings} userSettings
9
- * @returns {import('vite').Plugin | null}
9
+ * @returns {import('vite').Plugin}
10
10
  */
11
11
  export const needleBuildInfo = (command, config, userSettings) => {
12
12
 
13
- if (userSettings?.noBuildInfo) return null;
13
+ if (userSettings?.noBuildInfo) return;
14
14
 
15
15
  return {
16
16
  name: 'needle:buildinfo',
17
17
  apply: "build",
18
18
  enforce: "post",
19
- buildStart: () => {
20
- level++;
21
- },
22
19
  closeBundle: async () => {
23
- if (--level > 0) {
24
- console.log("[needle-buildinfo] - Skipped because of nested build");
25
- return;
26
- }
27
- const task = waitForBuildPipelineToFinish();
28
- if (task instanceof Promise) {
29
- console.log("[needle-buildinfo] - Waiting for build pipeline to finish");
30
- await task.catch(() => { }).finally(() => console.log("[needle-buildinfo] - Build pipeline finished!"));
31
- }
32
- // wait for gzip
33
- await delay(500);
34
- const buildDirectory = getOutputDirectory();
35
- createBuildInfoFile(buildDirectory);
20
+ return new Promise(async res => {
21
+ if (buildPipelineTask instanceof Promise) {
22
+ await buildPipelineTask.catch(() => { });
23
+ }
24
+ // wait for gzip
25
+ await delay(500);
26
+ const buildDirectory = getOutputDirectory();
27
+ createBuildInfoFile(buildDirectory);
28
+ res();
29
+ });
36
30
  }
37
31
  }
38
32
  }
plugins/common/config.js CHANGED
@@ -4,12 +4,12 @@
4
4
  const workingDirectory = process.cwd();
5
5
  const configPath = workingDirectory + "/needle.config.json";
6
6
  if(existsSync(configPath)) {
7
- const configStr = readFileSync(configPath, "utf8");
7
+ const configStr = readFileSync(configPath);
8
8
  const config = JSON.parse(configStr);
9
9
  if(config.codegenDirectory) {
10
10
  const dir = workingDirectory + "/" + config.codegenDirectory + "/meta.json";
11
11
  if(existsSync(dir)) {
12
- const metaStr = readFileSync(dir, "utf8");
12
+ const metaStr = readFileSync(dir);
13
13
  /**@type {import("../types").needleConfig} */
14
14
  const meta = JSON.parse(metaStr);
15
15
  return meta;
plugins/vite/config.js CHANGED
@@ -4,10 +4,9 @@
4
4
  let didLogCanNotFindConfig = false;
5
5
 
6
6
  /** the codegen meta file
7
- * @param {string | null} path
8
- * @returns {Promise<import("../types/needleConfig").needleMeta | null>}
7
+ * @returns {import("../types/needleConfig").needleMeta}
9
8
  */
10
- export async function loadConfig(path = null) {
9
+ export async function loadConfig(path) {
11
10
  try {
12
11
  // First try to get the path from the config
13
12
  if (!path) {
@@ -33,12 +32,12 @@
33
32
  console.error("Could not find config file at " + path);
34
33
  }
35
34
  }
36
- return null;
35
+ return {};
37
36
  }
38
37
  catch (err) {
39
- console.error("ERR: Error loading config file");
38
+ console.error("Error loading config file");
40
39
  console.error(err);
41
- return null;
40
+ return {};
42
41
  }
43
42
  }
44
43
 
@@ -52,7 +51,7 @@
52
51
  if (existsSync(path)) {
53
52
  const text = readFileSync(path);
54
53
  if (!text) return null;
55
- const json = JSON.parse(text.toString());
54
+ const json = JSON.parse(text);
56
55
  return json;
57
56
  }
58
57
  }
plugins/vite/copyfiles.js CHANGED
@@ -1,52 +1,41 @@
1
1
 
2
2
  import { resolve, join, isAbsolute } from 'path'
3
- import { existsSync, statSync, mkdirSync, readdirSync, copyFileSync, mkdir, rmSync } from 'fs';
3
+ import { existsSync, statSync, mkdirSync, readdirSync, copyFileSync, mkdir } from 'fs';
4
4
  import { builtAssetsDirectory, tryLoadProjectConfig } from './config.js';
5
- import { copyFilesSync } from '../common/files.js';
6
5
 
7
- const pluginName = "needle-copy-files";
8
6
 
9
-
10
7
  /** copy files on build from assets to dist
11
8
  * @param {import('../types').userSettings} userSettings
12
- * @returns {import('vite').Plugin | null}
13
9
  */
14
10
  export const needleCopyFiles = (command, config, userSettings) => {
15
11
 
16
12
  if (config?.noCopy === true || userSettings?.noCopy === true) {
17
- return null;
13
+ return;
18
14
  }
19
15
 
20
16
  return {
21
17
  name: 'needle-copy-files',
22
- // explicitly don't enforce post or pre because we want to run before the build-pipeline plugin
23
- enforce: "pre",
24
18
  buildStart() {
25
- return run("start", config);
19
+ return run(false, config);
26
20
  },
27
21
  closeBundle() {
28
- return run("end", config);
22
+ return run(true, config);
29
23
  },
30
24
  }
31
25
  }
32
26
 
33
- /**
34
- * @param {"start" | "end"} buildstep
35
- * @param {import('../types').userSettings} config
36
- */
37
- async function run(buildstep, config) {
38
- console.log(`[${pluginName}] - Copy files at ${buildstep}`);
27
+ async function run(isBuild, config) {
39
28
  const copyIncludesFromEngine = config?.copyIncludesFromEngine ?? true;
40
29
 
41
30
  const baseDir = process.cwd();
42
- const override = buildstep === "start";
31
+ const pluginName = "needle-copy-files";
43
32
 
44
33
  let assetsDirName = "assets";
45
34
  let outdirName = "dist";
46
35
 
47
36
  const needleConfig = tryLoadProjectConfig();
48
37
  if (needleConfig) {
49
- assetsDirName = needleConfig.assetsDirectory || assetsDirName;
38
+ assetsDirName = needleConfig.assetsDirectory;
50
39
  while (assetsDirName.startsWith('/')) assetsDirName = assetsDirName.substring(1);
51
40
 
52
41
  if (needleConfig.buildDirectory)
@@ -59,67 +48,60 @@
59
48
  if (existsSync(engineIncludeDir)) {
60
49
  console.log(`[${pluginName}] - Copy engine include to ${baseDir}/include`)
61
50
  const projectIncludeDir = resolve(baseDir, 'include');
62
- copyFilesSync(engineIncludeDir, projectIncludeDir);
51
+ copyRecursiveSync(engineIncludeDir, projectIncludeDir);
63
52
  }
64
53
  }
65
54
 
66
- const outDir = resolve(baseDir, outdirName);
67
- if (!existsSync(outDir)) {
68
- mkdirSync(outDir);
69
- }
55
+ if (isBuild) {
56
+ const outDir = resolve(baseDir, outdirName);
57
+ if (!existsSync(outDir)) {
58
+ mkdirSync(outDir);
59
+ }
70
60
 
71
- // copy a list of files or directories declared in build.copy = [] in the needle.config.json
72
- /*
73
- "build": {
74
- "copy": ["myFolder", "myFile.txt"]
75
- }
76
- */
77
- if (needleConfig?.build?.copy) {
78
- const arr = needleConfig.build.copy;
79
- for (let i = 0; i < arr.length; i++) {
80
- const entry = arr[i];
81
- if (Array.isArray(entry)) {
82
- console.log("WARN: build.copy can only contain string paths to copy to. Found array instead.");
83
- continue;
61
+ // copy a list of files or directories declared in build.copy = [] in the needle.config.json
62
+ /*
63
+ "build": {
64
+ "copy": ["myFolder", "myFile.txt"]
65
+ }
66
+ */
67
+ if (needleConfig?.build?.copy) {
68
+ const arr = needleConfig.build.copy;
69
+ for (let i = 0; i < arr.length; i++) {
70
+ const entry = arr[i];
71
+ if (Array.isArray(entry)) {
72
+ console.log("WARN: build.copy can only contain string paths to copy to. Found array instead.");
73
+ continue;
74
+ }
75
+ const src = resolve(baseDir, entry);
76
+ const dest = resolvePath(outDir, entry);
77
+ if (existsSync(src)) {
78
+ console.log(`[${pluginName}] - Copy ${entry} to ${outdirName}/${entry}`)
79
+ copyRecursiveSync(src, dest);
80
+ }
84
81
  }
85
- const src = resolve(baseDir, entry);
86
- const dest = resolvePath(outDir, entry);
87
- if (existsSync(src) && dest) {
88
- console.log(`[${pluginName}] - Copy ${entry} to ${outdirName}/${entry}`)
89
- copyFilesSync(src, dest, override);
90
- }
91
82
  }
92
- }
93
83
 
94
- // copy assets dir
95
- const assetsDir = resolve(baseDir, assetsDirName);
96
- if (existsSync(assetsDir)) {
97
- const targetDir = resolve(outDir, 'assets');
98
- // ensure that the target directory exists and is cleared if it already exists
99
- // otherwise we might run into issues where the build pipeline is running for already compressed files
100
- if (override && existsSync(targetDir)) {
101
- console.log(`[${pluginName}] - Clearing target directory \"${targetDir}\"`);
102
- rmSync(targetDir, { recursive: true, force: true });
84
+ // copy assets dir
85
+ const assetsDir = resolve(baseDir, assetsDirName);
86
+ if (existsSync(assetsDir)) {
87
+ console.log(`[${pluginName}] - Copy assets to ${outdirName}/${builtAssetsDirectory()}`)
88
+ const targetDir = resolve(outDir, 'assets');
89
+ copyRecursiveSync(assetsDir, targetDir);
103
90
  }
104
- console.log(`[${pluginName}] - Copy assets to ${outdirName}/${builtAssetsDirectory()}`)
105
- copyFilesSync(assetsDir, targetDir, override);
91
+ else console.log(`WARN: No assets directory found. Skipping copy of ${assetsDirName} resolved to ${assetsDir}`)
92
+ // copy include dir
93
+ const includeDir = resolve(baseDir, 'include');
94
+ if (existsSync(includeDir)) {
95
+ console.log(`[${pluginName}] - Copy include to ${outdirName}/include`)
96
+ const targetDir = resolve(outDir, 'include');
97
+ copyRecursiveSync(includeDir, targetDir);
98
+ }
106
99
  }
107
- else console.log(`WARN: No assets directory found. Skipping copy of ${assetsDirName} resolved to ${assetsDir}`)
108
-
109
- // copy include dir
110
- const includeDir = resolve(baseDir, 'include');
111
- if (existsSync(includeDir)) {
112
- console.log(`[${pluginName}] - Copy include to ${outdirName}/include`)
113
- const targetDir = resolve(outDir, 'include');
114
- copyFilesSync(includeDir, targetDir, override);
115
- }
116
100
  }
117
101
 
118
102
  /** resolves relative or absolute paths to a path inside the out directory
119
103
  * for example D:/myFile.txt would resolve to outDir/myFile.txt
120
104
  * wherereas "some/relative/path" would become outDir/some/relative/path
121
- * @param {string} outDir
122
- * @param {string} pathValue
123
105
  */
124
106
  function resolvePath(outDir, pathValue) {
125
107
  if (isAbsolute(pathValue)) {
@@ -128,12 +110,29 @@
128
110
  var stats = exists && statSync(pathValue);
129
111
  if (stats.isDirectory()) {
130
112
  const dirName = pathValue.replaceAll('\\', '/').split('/').pop();
131
- if (!dirName) return null;
132
113
  return resolve(outDir, dirName);
133
114
  }
134
115
  const fileName = pathValue.replaceAll('\\', '/').split('/').pop();
135
- if (!fileName) return null;
136
116
  return resolve(outDir, fileName);
137
117
  }
138
118
  return resolve(outDir, pathValue);
139
- }
119
+ }
120
+
121
+ function copyRecursiveSync(src, dest) {
122
+ if (dest === null) {
123
+ console.log(`[${pluginName}] - Copy ${src} to ${dest} - dest is null`)
124
+ return;
125
+ }
126
+ var exists = existsSync(src);
127
+ var stats = exists && statSync(src);
128
+ var isDirectory = exists && stats.isDirectory();
129
+ if (isDirectory) {
130
+ if (!existsSync(dest))
131
+ mkdirSync(dest, { recursive: true });
132
+ readdirSync(src).forEach(function (childItemName) {
133
+ copyRecursiveSync(join(src, childItemName), join(dest, childItemName));
134
+ });
135
+ } else {
136
+ copyFileSync(src, dest);
137
+ }
138
+ };
plugins/vite/defines.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { loadConfig } from "./config.js";
2
2
  import { tryGetNeedleEngineVersion } from "../common/version.js";
3
- import { getPublicIdentifier as getPublicIdentifier } from "../common/license.js";
4
3
 
5
4
  // NOTE: ALL DEFINES MUST BE SET HERE! NEVER ADD OR RELY ON DEFINES IN ANY OTHER PLUGIN
6
5
 
@@ -20,15 +19,10 @@
20
19
  let useRapier = true;
21
20
  if (needleEngineConfig?.useRapier === false || userSettings?.useRapier === false) useRapier = false;
22
21
 
23
- let usePostProcessing = true;
24
- if(userSettings.usePostprocessing === false) {
25
- usePostProcessing = false;
26
- }
27
-
28
22
  return {
29
23
  name: 'needle:defines',
30
24
  enforce: 'pre',
31
- async config(viteConfig) {
25
+ config(viteConfig) {
32
26
  // console.log("Update vite defines -------------------------------------------");
33
27
  if (!viteConfig.define) viteConfig.define = {};
34
28
  const version = tryGetNeedleEngineVersion();
@@ -39,8 +33,8 @@
39
33
  viteConfig.define.NEEDLE_ENGINE_GENERATOR = "\"" + needleEngineConfig.generator + "\"";
40
34
 
41
35
  if (useRapier && userSettings?.useRapier !== true) {
42
- const meta = await loadConfig();
43
- if (meta && meta.useRapier === false) {
36
+ const meta = loadConfig();
37
+ if (meta?.useRapier === false) {
44
38
  useRapier = false;
45
39
  }
46
40
  }
@@ -49,19 +43,8 @@
49
43
  viteConfig.define.NEEDLE_USE_RAPIER = useRapier;
50
44
  }
51
45
 
52
- // TODO: this doesn't make postprocessing optional yet
53
- if (viteConfig.define.NEEDLE_USE_POSTPROCESSING === undefined) {
54
- viteConfig.define.NEEDLE_USE_POSTPROCESSING = usePostProcessing;
55
- }
56
-
57
46
  // this gives a timestamp containing the timezone
58
47
  viteConfig.define.NEEDLE_PROJECT_BUILD_TIME = "\"" + new Date().toString() + "\"";
59
-
60
- const projectId = undefined; // TODO: this needs to be exported by the integration (if any)
61
- const publicIdentifier = await getPublicIdentifier(projectId).catch(console.warn);
62
- if (publicIdentifier) {
63
- viteConfig.define.NEEDLE_PUBLIC_KEY = "\"" + publicIdentifier + "\"";
64
- }
65
48
  }
66
49
  }
67
50
  }
plugins/vite/dependencies.js CHANGED
@@ -1,214 +1,34 @@
1
- import { tryGetNeedleEngineVersion, tryGetPackageVersion } from '../common/version.js';
2
1
 
3
- /**
4
- * @type {string[]}
5
- */
6
- export const preloadScriptPaths = [];
7
2
 
8
3
 
4
+
5
+
9
6
  /**
10
7
  * @param {import('../types').userSettings} userSettings
11
8
  */
12
9
  export const needleDependencies = (command, config, userSettings) => {
13
-
14
10
  /**
15
11
  * @type {import('vite').Plugin}
16
12
  */
17
13
  return {
18
14
  name: 'needle:dependencies',
19
15
  enforce: 'pre',
20
- /**
21
- * @param {import('vite').UserConfig} config
22
- */
23
- config: (config, env) => {
24
- handleOptimizeDeps(config);
25
- handleManualChunks(config);
26
- }
27
- }
28
- }
29
-
30
- /**
31
- * @param {import('vite').UserConfig} config
32
- */
33
- function handleOptimizeDeps(config) {
34
- if (config.optimizeDeps?.include?.includes("three-mesh-bvh")) {
35
- console.log("[needle-dependencies] three-mesh-bvh is included in the optimizeDeps.include array. This may cause issues with the worker import.");
36
- }
37
- else {
38
- if (!config.optimizeDeps) {
39
- config.optimizeDeps = {};
40
- }
41
- if (!config.optimizeDeps.exclude) {
42
- config.optimizeDeps.exclude = [];
43
- }
44
- console.log("[needle-dependencies] Adding three-mesh-bvh to the optimizeDeps.exclude array.");
45
- // This needs to be excluded from optimization because otherwise the worker import fails
46
- // three-mesh-bvh/src/workers/generateMeshBVH.worker.js?worker
47
- config.optimizeDeps.exclude.push("three-mesh-bvh");
48
- }
49
- }
50
-
51
- /**
52
- * @param {import('vite').UserConfig} config
53
- */
54
- function handleManualChunks(config) {
55
- if (!config.build) {
56
- config.build = {};
57
- }
58
- if (!config.build.rollupOptions) {
59
- config.build.rollupOptions = {};
60
- }
61
- if (!config.build.rollupOptions.output) {
62
- config.build.rollupOptions.output = {};
63
- }
64
-
65
- const rollupOutput = config.build.rollupOptions.output;
66
-
67
- if (Array.isArray(rollupOutput)) {
68
- // append the manualChunks function to the array
69
- console.log("[needle-dependencies] registering manualChunks");
70
- rollupOutput.push({
71
- manualChunks: needleManualChunks
72
- })
73
- }
74
- else {
75
- if (rollupOutput.manualChunks) {
76
- // if the user has already defined manualChunks, we don't want to overwrite it
77
- console.log("[needle-dependencies] manualChunks already defined");
78
- }
79
- else {
80
- console.log("[needle-dependencies] registering manualChunks");
81
- rollupOutput.manualChunks = needleManualChunks;
82
- }
83
-
84
- if (rollupOutput.chunkFileNames) {
85
- console.log("[needle-dependencies] chunkFileNames already defined");
86
- }
87
- else {
88
- rollupOutput.chunkFileNames = handleChunkFileNames;
89
- }
90
-
91
- if (rollupOutput.assetFileNames) {
92
- console.log("[needle-dependencies] assetFileNames already defined");
93
- }
94
- else {
95
- rollupOutput.assetFileNames = assetFileNames;
96
- }
97
- }
98
-
99
- // TODO: this was a test if it allows us to remove the sync import of postprocessing due to n8ao's import
100
- // config.build.rollupOptions.external = (source, importer, isResolved) => {
101
- // if (importer?.includes("node_modules/n8ao/") || importer?.includes("node_modules/postprocessing/")) {
102
- // console.log("EXTERNAL", importer);
103
- // return true;
104
- // }
105
- // }
106
-
107
- /** https://rollupjs.org/configuration-options/#output-assetfilenames
108
- * @param {import("vite").Rollup.PreRenderedAsset} chunkInfo */
109
- function assetFileNames(chunkInfo) {
110
- // "assets/..." is the default
111
-
112
- // this happens if e.g. a glTF or GLB file is link preloaded
113
- if (chunkInfo.name.toLowerCase().includes(".glb") || chunkInfo.name.toLowerCase().includes(".gltf")) {
114
- return `assets/[name][extname]`;
115
- }
116
- return `assets/[name].[hash][extname]`;
117
- }
118
-
119
- /** @param {import("vite").Rollup.PreRenderedChunk} chunk */
120
- function handleChunkFileNames(chunk) {
121
- if (chunk.name === 'needle-engine') {
122
- try {
123
- const version = tryGetNeedleEngineVersion();
124
- if (version) {
125
- const name = `assets/needle-engine@${version}.js`;
126
- preloadScriptPaths.push(`./${name}`);
127
- return name;
16
+ config: (config) => {
17
+ if (config.optimizeDeps?.include?.includes("three-mesh-bvh")) {
18
+ console.log("[needle-dependencies] three-mesh-bvh is included in the optimizeDeps.include array. This may cause issues with the worker import.");
19
+ }
20
+ else {
21
+ if (!config.optimizeDeps) {
22
+ config.optimizeDeps = {};
128
23
  }
24
+ if (!config.optimizeDeps.exclude) {
25
+ config.optimizeDeps.exclude = [];
26
+ }
27
+ console.log("[needle-dependencies] Adding three-mesh-bvh to the optimizeDeps.exclude array.");
28
+ // This needs to be excluded from optimization because otherwise the worker import fails
29
+ // three-mesh-bvh/src/workers/generateMeshBVH.worker.js?worker
30
+ config.optimizeDeps.exclude.push("three-mesh-bvh");
129
31
  }
130
- catch (e) {
131
- console.warn("[needle-dependencies] Error reading version", e);
132
- }
133
32
  }
134
- else if (chunk.name === 'three') {
135
- const version = tryGetPackageVersion("three");
136
- if (version) {
137
- const name = `assets/three@${version}.js`;
138
- preloadScriptPaths.push(`./${name}`);
139
- return name;
140
- }
141
- }
142
- return `assets/[name].[hash].js`;
143
33
  }
144
-
145
- /**
146
- * @param {string} id
147
- * @param {import('vite').Rollup.ManualChunkMeta | null} meta
148
- */
149
- function needleManualChunks(id, meta) {
150
-
151
- // console.log(id);
152
-
153
- if (id.includes("three/examples")) {
154
- return "three-examples";
155
- }
156
- if (id.includes('/three/')) {
157
- return "three";
158
- }
159
-
160
- if (id.includes("node_modules/n8ao/")) {
161
- detectSyncImports(id, meta);
162
- return "postprocessing.ao";
163
- }
164
-
165
- if (id.includes("node_modules/postprocessing/")) {
166
- // postprocessing bundle is preloaded https://github.com/vitejs/vite/pull/9938
167
- detectSyncImports(id, meta);
168
- return "postprocessing";
169
- }
170
-
171
- if (id.includes("node_modules/three-mesh-ui")) {
172
- return "three-mesh-ui";
173
- }
174
-
175
- if (id.includes("@dimforge/rapier3d")) {
176
- detectSyncImports(id, meta);
177
- return "rapier3d";
178
- }
179
-
180
- if (id.includes("node_modules/three.quarks")) {
181
- return "three-quarks";
182
- }
183
- // we want to bundle gltf-progressive separately because it also initiates Draco and KTX worker preloading
184
- if (id.includes("/gltf-progressive/")) {
185
- return "gltf-progressive";
186
- }
187
- if (id.includes("node_modules/needle-engine")
188
- // DEV
189
- // || id.includes("/package~/src/")
190
- ) {
191
- return "needle-engine";
192
- }
193
- }
194
34
  }
195
-
196
-
197
- /**
198
- * @param {string} id
199
- * @param {import('vite').Rollup.ManualChunkMeta | null} meta
200
- */
201
- function detectSyncImports(id, meta) {
202
- if (meta) {
203
- if (meta.getModuleInfo) {
204
- const info = meta.getModuleInfo(id);
205
- if (info && info.importers.length > 0) {
206
- const isNeedleDev = id.includes("/package~/src/");
207
- if (isNeedleDev) {
208
- console.warn(`WARN: SYNC IMPORTER DETECTED of ${id}`);
209
- console.warn(info.importers)
210
- }
211
- }
212
- }
213
- }
214
- }
plugins/vite/drop.js CHANGED
@@ -7,13 +7,8 @@
7
7
  const __dirname = path.dirname(__filename);
8
8
 
9
9
  /** experimental, allow dropping files from Unity into the running scene */
10
- /**
11
- * @param {import('../types/userconfig.js').userSettings} userSettings
12
- */
13
10
  export const needleDrop = (command, config, userSettings) => {
14
11
  if (command === "build") return;
15
-
16
- if(userSettings.useDrop !== true) return null;
17
12
 
18
13
  return {
19
14
  name: "needle:drop",
plugins/common/files.js DELETED
@@ -1,32 +0,0 @@
1
- import { copyFileSync, existsSync, mkdirSync, readdirSync, statSync } from "fs";
2
- import { join } from "path";
3
-
4
- /**
5
- * @param {string} src
6
- * @param {string} dest
7
- * @param {boolean} override
8
- * @param {{count:number} | undefined} ctx
9
- */
10
- export function copyFilesSync(src, dest, override = true, ctx = undefined) {
11
- if (dest === null) {
12
- console.log(`[needle-copy] - Copy ${src} to ${dest} - dest is null`)
13
- return;
14
- }
15
- let exists = existsSync(src);
16
- let stats = exists && statSync(src);
17
- let isDirectory = exists && typeof stats != "boolean" && stats.isDirectory();
18
- if (isDirectory) {
19
- if (!existsSync(dest))
20
- mkdirSync(dest, { recursive: true });
21
- readdirSync(src).forEach(function (childItemName) {
22
- // recurse
23
- copyFilesSync(join(src, childItemName), join(dest, childItemName), override, ctx);
24
- });
25
- }
26
- else if (override || !existsSync(dest)) {
27
- if (ctx) {
28
- ctx.count += 1;
29
- }
30
- copyFileSync(src, dest);
31
- }
32
- };
plugins/vite/index.js CHANGED
@@ -95,18 +95,17 @@
95
95
  ],
96
96
  }
97
97
  * ```
98
- * @param {"build" | "serve"} command
99
- * @param {{} | undefined} config
100
- * @param {import('../types/index.js').userSettings} userSettings
98
+ * @param {string} command
99
+ * @param {import('../types').userSettings} userSettings
101
100
  */
102
- export const needlePlugins = async (command, config = undefined, userSettings = {}) => {
101
+ export const needlePlugins = async (command, config, userSettings) => {
103
102
 
104
103
  if (!config) config = {}
105
104
 
106
105
  // ensure we have user settings initialized with defaults
107
- userSettings = { ...defaultUserSettings, ...userSettings };
108
-
106
+ userSettings = { ...defaultUserSettings, ...userSettings }
109
107
  const array = [
108
+ needleAsap(command, config, userSettings),
110
109
  needleDefines(command, config, userSettings),
111
110
  needleLicense(command, config, userSettings),
112
111
  needleViteAlias(command, config, userSettings),
@@ -130,10 +129,6 @@
130
129
  needleServer(command, config, userSettings),
131
130
  needleNPM(command, config, userSettings),
132
131
  ];
133
-
134
- const asap = await needleAsap(command, config, userSettings);
135
- if(asap) array.push(asap);
136
-
137
132
  array.push(await editorConnection(command, config, userSettings, array));
138
133
  return array;
139
134
  }
plugins/common/license.js DELETED
@@ -1,191 +0,0 @@
1
- import { spawn } from "child_process";
2
- import https from 'https';
3
- import http from 'http';
4
-
5
- const port = 8424;
6
- const licenseServerUrl = `http://localhost:${port}/api/license`;
7
- const projectIdentifierUrl = `http://localhost:${port}/api/public_key`;
8
-
9
- /**
10
- * Replace license string - used for webpack
11
- * @param {string} code
12
- * @param {{team:string|undefined}} opts
13
- */
14
- export async function replaceLicense(code, opts) {
15
- const index = code.indexOf("NEEDLE_ENGINE_LICENSE_TYPE");
16
- if (index >= 0) {
17
- const licenseType = await resolveLicense(opts);
18
- if (!licenseType) {
19
- return code;
20
- }
21
- const end = code.indexOf(";", index);
22
- if (end >= 0) {
23
- const line = code.substring(index, end);
24
- const replaced = "NEEDLE_ENGINE_LICENSE_TYPE = \"" + licenseType + "\"";
25
- code = code.replace(line, replaced);
26
- return code;
27
- }
28
- }
29
- return code;
30
- }
31
-
32
-
33
- /**
34
- * Resolve the license using the needle engine licensing server
35
- * @param {{accessToken?:string, team?:string} | null} args
36
- * @returns {Promise<string | null>}
37
- */
38
- export async function resolveLicense(args = null) {
39
- // Wait for the server to start
40
- await waitForLicenseServer();
41
-
42
- let accessToken = args?.accessToken;
43
- if (process.env.NEEDLE_CLOUD_TOKEN) {
44
- console.log("INFO: Using Needle Cloud access token from environment variable");
45
- accessToken = process.env.NEEDLE_CLOUD_TOKEN;
46
- }
47
-
48
- const url = new URL(licenseServerUrl);
49
- if (args?.team)
50
- url.searchParams.append("org", args.team);
51
- if (accessToken) {
52
- url.searchParams.append("token", accessToken);
53
- }
54
-
55
- console.log(`INFO: Fetching license...`);
56
- const licenseResponse = await fetch(url.toString(), {
57
- method: "GET",
58
- }).catch(console.error);
59
- if (!licenseResponse) {
60
- console.warn("WARN: Failed to fetch license");
61
- return null;
62
- }
63
-
64
- try {
65
- /** @type {{needle_engine_license:string}} */
66
- const licenseJson = JSON.parse(licenseResponse);
67
- console.log("\n");
68
- if (licenseJson.needle_engine_license) {
69
- console.log(`INFO: Successfully received \"${licenseJson.needle_engine_license?.toUpperCase()}\" license`)
70
- return licenseJson.needle_engine_license;
71
- }
72
- if ("error" in licenseJson) {
73
- console.error(`ERROR in license check: \"${licenseJson.error}\"`);
74
- }
75
- else if (licenseJson.needle_engine_license == null) {
76
- return null;
77
- }
78
- else {
79
- console.warn("WARN: Received invalid license.", licenseJson);
80
- }
81
- return null;
82
- }
83
- catch (err) {
84
- console.error("ERROR: Failed to parse license response");
85
- return null;
86
- }
87
- }
88
-
89
-
90
-
91
- /**
92
- * @param {string | undefined} project_id
93
- */
94
- export async function getPublicIdentifier(project_id) {
95
- // Wait for the server to start
96
- await waitForLicenseServer();
97
-
98
- const res = await fetch(projectIdentifierUrl, {
99
- method: "GET",
100
- });
101
-
102
- if (!res) {
103
- console.warn("WARN: Failed to fetch project identifier");
104
- return null;
105
- }
106
-
107
- try {
108
- /** @type {{public_key:string}} */
109
- const json = JSON.parse(res);
110
- return json.public_key;
111
- }
112
- catch (err) {
113
- // TODO: report error to backend
114
- return null;
115
- }
116
- };
117
-
118
-
119
-
120
- // If we run the build command without an editor and the license server is just being started
121
- // we need to to wait for the root URL to return a response
122
- async function waitForLicenseServer() {
123
- // Make sure the licensing server is running
124
- runCommand("npx", ["--yes", "needle-cloud@main", "start-server"]);
125
-
126
- let attempts = 0;
127
- while (attempts < 10) {
128
- const response = await fetch(licenseServerUrl, {
129
- method: "GET",
130
- }).catch(() => { /** ignore errors */ });
131
- if (response) {
132
- return true;
133
- }
134
- if (attempts === 0) {
135
- console.log("INFO: Waiting for license server to start...");
136
- }
137
- attempts++;
138
- await new Promise(res => setTimeout(res, 1000));
139
- }
140
- return false;
141
- }
142
-
143
-
144
- /**
145
- * @param {string} processName
146
- * @param {string[]} args
147
- */
148
- async function runCommand(processName, args) {
149
- const process = spawn(processName, [...args], { shell: true, timeout: 30_000 });
150
- return new Promise((resolve, reject) => {
151
- process.on('close', (code) => {
152
- if (code === 0) {
153
- resolve(true);
154
- } else {
155
- console.warn(`WARN: ${processName} exited with code ${code}`);
156
- resolve(false);
157
- }
158
- });
159
- process.on('error', (err) => {
160
- resolve(err);
161
- });
162
- });
163
- }
164
-
165
-
166
- /**
167
- * @param {string} str
168
- */
169
- function obscure(str) {
170
- const start = str.substring(0, 3);
171
- return start + "******";
172
- }
173
-
174
-
175
- // NODE 16 doesn't support fetch yet
176
- function fetch(url, options) {
177
- const module = url.startsWith("https") ? https : http;
178
- return new Promise((resolve, reject) => {
179
- module.get(url, options, (res) => {
180
- let data = '';
181
- res.on('data', (chunk) => {
182
- data += chunk;
183
- });
184
- res.on('end', () => {
185
- resolve(data);
186
- });
187
- }).on("error", (err) => {
188
- reject(err);
189
- });
190
- });
191
- }
plugins/vite/license.js CHANGED
@@ -1,11 +1,11 @@
1
- import { resolveLicense } from '../common/license.js';
1
+ import { resolveLicense } from '../common/license.cjs';
2
2
  import { loadConfig } from './config.js';
3
3
 
4
4
  /**
5
5
  * This plugin is used to apply the license to the needle engine.
6
6
  * @param {string} command - The command that is being run
7
7
  * @param {object} config - The config object
8
- * @param {import('../types/userconfig.js').userSettings} userSettings
8
+ * @param {import('../types/userconfig.js').userSettings}
9
9
  */
10
10
  export const needleLicense = (command, config, userSettings) => {
11
11
  let license = undefined;
@@ -14,20 +14,17 @@
14
14
  name: "needle:license",
15
15
  enforce: 'pre',
16
16
  async configResolved() {
17
-
18
- let team = userSettings?.license?.team;
19
- if (!team) {
20
- const meta = await loadConfig(null);
21
- if (meta) {
22
- team = meta.license?.team;
17
+ if (userSettings.license) {
18
+ // we only accept a license object here
19
+ if (typeof userSettings.license === "object")
20
+ license = await resolveLicense(userSettings.license);
21
+ }
22
+ else {
23
+ const needleConfig = await loadConfig();
24
+ if (needleConfig) {
25
+ license = await resolveLicense(needleConfig.license);
23
26
  }
24
27
  }
25
-
26
- license = await resolveLicense({
27
- team: team,
28
- accessToken: userSettings?.license?.accessToken
29
- });
30
-
31
28
  },
32
29
  async transform(src, id) {
33
30
  const isNeedleEngineFile = id.includes("engine/engine_license") || id.includes("needle-tools_engine");
plugins/next/next.js CHANGED
@@ -42,8 +42,6 @@
42
42
  /** @param {import ('next').NextConfig config } */
43
43
  function nextWebPack(config, { buildId, dev, isServer, defaultLoaders, webpack }) {
44
44
 
45
- // TODO: get public identifier key from license server
46
-
47
45
  const meta = getMeta();
48
46
  let useRapier = true;
49
47
  if (userSettings.useRapier === false) useRapier = false;
plugins/vite/peer.js CHANGED
@@ -1,5 +1,7 @@
1
1
 
2
- const peerjsString = `/* needle: fix for peerjs */ window.global = window; var parcelRequire;`
2
+ const peerjsString = `/* needle: injected fix for peerjs */
3
+ window.global = window;
4
+ var parcelRequire;`
3
5
 
4
6
  /**
5
7
  * @param {import('../types').userSettings} userSettings
plugins/vite/reload.js CHANGED
@@ -71,7 +71,6 @@
71
71
  if (config?.allowHotReload === false) return html;
72
72
  if (userSettings?.allowHotReload === false) return html;
73
73
  const file = path.join(__dirname, 'reload-client.js');
74
- const content = readFileSync(file, 'utf8');
75
74
  return {
76
75
  html,
77
76
  tags: [
@@ -80,7 +79,7 @@
80
79
  attrs: {
81
80
  type: 'module',
82
81
  },
83
- children: content,
82
+ children: readFileSync(file, 'utf8'),
84
83
  injectTo: 'body',
85
84
  },
86
85
  ]
src/engine/assets/static.js DELETED
@@ -1,5 +0,0 @@
1
- // This file must be static so it can be used from vite plugins
2
-
3
- const logoSvgString = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 160 187.74"><defs><linearGradient id="a" x1="89.64" y1="184.81" x2="90.48" y2="21.85" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#62d399"/><stop offset=".51" stop-color="#acd842"/><stop offset=".9" stop-color="#d7db0a"/></linearGradient><linearGradient id="b" x1="69.68" y1="178.9" x2="68.08" y2="16.77" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#0ba398"/><stop offset=".5" stop-color="#4ca352"/><stop offset="1" stop-color="#76a30a"/></linearGradient><linearGradient id="c" x1="36.6" y1="152.17" x2="34.7" y2="84.19" gradientUnits="userSpaceOnUse"><stop offset=".19" stop-color="#36a382"/><stop offset=".54" stop-color="#49a459"/><stop offset="1" stop-color="#76a30b"/></linearGradient><linearGradient id="d" x1="15.82" y1="153.24" x2="18" y2="90.86" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#267880"/><stop offset=".51" stop-color="#457a5c"/><stop offset="1" stop-color="#717516"/></linearGradient><linearGradient id="e" x1="135.08" y1="135.43" x2="148.93" y2="63.47" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#b0d939"/><stop offset="1" stop-color="#eadb04"/></linearGradient><linearGradient id="f" x1="-4163.25" y1="2285.12" x2="-4160.81" y2="2215.34" gradientTransform="rotate(20 4088.49 13316.712)" gradientUnits="userSpaceOnUse"><stop offset=".17" stop-color="#74af52"/><stop offset=".48" stop-color="#99be32"/><stop offset="1" stop-color="#c0c40a"/></linearGradient><symbol id="g" viewBox="0 0 160 187.74"><path style="fill:url(#a)" d="M79.32 36.98v150.76L95 174.54l6.59-156.31-22.27 18.75z"/><path style="fill:url(#b)" d="M79.32 36.98 57.05 18.23l6.59 156.31 15.68 13.2V36.98z"/><path style="fill:url(#c)" d="m25.19 104.83 8.63 49.04 12.5-14.95-2.46-56.42-18.67 22.33z"/><path style="fill:url(#d)" d="M25.19 104.83 0 90.24l16.97 53.86 16.85 9.77-8.63-49.04z"/><path style="fill:#9c3" d="M43.86 82.5 18.69 67.98 0 90.24l25.18 14.59L43.86 82.5z"/><path style="fill:url(#e)" d="m134.82 78.69-9.97 56.5 15.58-9.04L160 64.1l-25.18 14.59z"/><path style="fill:url(#f)" d="m134.82 78.69-18.68-22.33-2.86 65 11.57 13.83 9.97-56.5z"/><path style="fill:#ffe113" d="m160 64.1-18.69-22.26-25.17 14.52 18.67 22.33L160 64.1z"/><path style="fill:#f3e600" d="M101.59 18.23 79.32 0 57.05 18.23l22.27 18.75 22.27-18.75z"/></symbol></defs><use width="160" height="187.74" xlink:href="#g"/></svg>`;
4
- const logoSvgBlob = btoa(logoSvgString);
5
- export const NEEDLE_LOGO_SVG_URL = "data:image/svg+xml;base64," + logoSvgBlob;
plugins/common/timers.js DELETED
@@ -1,8 +0,0 @@
1
-
2
-
3
- /**
4
- * @param {number} ms
5
- */
6
- export function delay(ms) {
7
- return new Promise(res => setTimeout(res, ms));
8
- }
plugins/common/version.js CHANGED
@@ -4,35 +4,18 @@
4
4
  export function tryGetNeedleEngineVersion() {
5
5
  const needleEnginePackageJsonPath = process.cwd() + "/node_modules/@needle-tools/engine/package.json";
6
6
  if (existsSync(needleEnginePackageJsonPath)) {
7
- const content = readFileSync(needleEnginePackageJsonPath).toString();
8
- const json = JSON.parse(content);
7
+ const json = JSON.parse(readFileSync(needleEnginePackageJsonPath));
9
8
  const version = json.version;
10
9
  return version;
11
10
  }
12
11
  // check if we're in the needle engine package directory (for a release)
13
12
  const packageJsonPath = process.cwd() + "/package.json";
14
13
  if (existsSync(packageJsonPath)) {
15
- const content = readFileSync(packageJsonPath).toString();
16
- const json = JSON.parse(content);
14
+ const json = JSON.parse(readFileSync(packageJsonPath));
17
15
  if (json.name === "@needle-tools/engine") {
18
16
  const version = json.version;
19
17
  return version;
20
18
  }
21
19
  }
22
20
  return null;
23
- }
24
-
25
- /**
26
- * @param {string} packageName
27
- */
28
- export function tryGetPackageVersion(packageName) {
29
- const packageJsonPath = process.cwd() + `/node_modules/${packageName}/package.json`;
30
- if (existsSync(packageJsonPath)) {
31
- const content = readFileSync(packageJsonPath, "utf8");
32
- if (content) {
33
- const json = JSON.parse(content);
34
- const version = json.version;
35
- return version;
36
- }
37
- }
38
21
  }
src/engine-components/Animation.ts CHANGED
@@ -517,7 +517,7 @@
517
517
  this.promise = new Promise((res) => {
518
518
  this._resolveCallback = res;
519
519
  });
520
- // this.mixer.addEventListener('loop', this.onLoop);
520
+ this.mixer.addEventListener('loop', this.onLoop);
521
521
  this.mixer.addEventListener('finished', this.onFinished as any);
522
522
  return this.promise;
523
523
  }
@@ -542,8 +542,8 @@
542
542
  this._resolveCallback?.call(this, this.action);
543
543
  }
544
544
 
545
- // private onLoop = (_evt: MixerEvent) => {
546
- // }
545
+ private onLoop = (_evt: MixerEvent) => {
546
+ }
547
547
 
548
548
  private onFinished = (evt: MixerEvent) => {
549
549
  if (evt.action === this.action) {
@@ -552,7 +552,7 @@
552
552
  }
553
553
 
554
554
  private dispose() {
555
- // this.mixer.removeEventListener('loop', this.onLoop);
555
+ this.mixer.removeEventListener('loop', this.onLoop);
556
556
  this.mixer.removeEventListener('finished', this.onFinished as any);
557
557
  }
558
558
  }
src/engine-components/postprocessing/Effects/Antialiasing.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { MODULES } from "../../../engine/engine_modules.js";
1
+ import { EdgeDetectionMode, SMAAEffect, SMAAPreset } from "postprocessing";
2
+
2
3
  import { serializable } from "../../../engine/engine_serialization.js";
3
4
  import { type EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect.js";
4
5
  import { VolumeParameter } from "../VolumeParameter.js";
@@ -26,14 +27,13 @@
26
27
  // edgeDetectionThreshold!: VolumeParameter;
27
28
 
28
29
  @serializable(VolumeParameter)
29
- readonly preset: VolumeParameter = new VolumeParameter(2);
30
- // 2 is HIGH: https://github.com/pmndrs/postprocessing/blob/main/src/enums/SMAAPreset.js#L14
30
+ readonly preset: VolumeParameter = new VolumeParameter(SMAAPreset.HIGH);
31
31
 
32
32
 
33
33
  onCreateEffect(): EffectProviderResult {
34
- const effect = new MODULES.POSTPROCESSING.MODULE.SMAAEffect({
35
- preset: MODULES.POSTPROCESSING.MODULE.SMAAPreset.HIGH,
36
- edgeDetectionMode: MODULES.POSTPROCESSING.MODULE.EdgeDetectionMode.DEPTH
34
+ const effect = new SMAAEffect({
35
+ preset: SMAAPreset.HIGH,
36
+ edgeDetectionMode: EdgeDetectionMode.DEPTH
37
37
  });
38
38
 
39
39
  this.preset.onValueChanged = (newValue) => {
src/engine-components/api.ts CHANGED
@@ -52,9 +52,8 @@
52
52
  import "./AnimationUtilsAutoplay.js"
53
53
 
54
54
  export { DragMode } from "./DragControls.js"
55
- export type { DropListenerNetworkEventArguments } from "./DropListener.js";
56
55
  export * from "./particlesystem/api.js"
57
56
 
58
57
  // for correct type resolution in JSDoc
59
58
  import type { PhysicsMaterial } from "../engine/engine_physics.types.js";
60
- import type { Animation } from "./Animation.js";
59
+ import type { Animation } from "./Animation.js";
src/engine/api.ts CHANGED
@@ -45,10 +45,8 @@
45
45
  export { hasCommercialLicense, hasIndieLicense, hasProLicense } from "./engine_license.js";
46
46
  export * from "./engine_lifecycle_api.js";
47
47
  export * from "./engine_math.js";
48
- export { MODULES as NEEDLE_ENGINE_MODULES } from "./engine_modules.js";
49
48
  export * from "./engine_networking.js";
50
49
  export { syncField } from "./engine_networking_auto.js";
51
- export * from "./engine_networking_blob.js";
52
50
  export * from "./engine_networking_files.js";
53
51
  export * from "./engine_networking_instantiate.js";
54
52
  export * from "./engine_networking_peer.js";
@@ -75,6 +73,7 @@
75
73
  export * from "./engine_utils.js";
76
74
  export * from "./engine_utils_format.js";
77
75
  export * from "./engine_utils_screenshot.js";
76
+ export * from "./engine_web_api.js";
78
77
  export * from "./export/index.js";
79
78
  export * from "./extensions/index.js";
80
79
  export * from "./js-extensions/index.js";
src/engine-components/AvatarLoader.ts CHANGED
@@ -6,6 +6,7 @@
6
6
  import * as loaders from "../engine/engine_loaders.js"
7
7
  import { Context } from "../engine/engine_setup.js";
8
8
  import * as utils from "../engine/engine_utils.js"
9
+ import { download_file } from "../engine/engine_web_api.js";
9
10
  import { GameObject } from "./Component.js";
10
11
 
11
12
  const debug = utils.getParam("debugavatar");
@@ -99,8 +100,8 @@
99
100
  if (blob) bin = await blob.arrayBuffer();
100
101
  }
101
102
  if (!bin) {
102
- // bin = await BlobStorage.download(avatarId, avatarId, 0, "no url here go away", true);
103
- return null;
103
+ bin = await download_file(avatarId, avatarId, 0, "no url here go away", true);
104
+ if (!bin) return null;
104
105
  }
105
106
 
106
107
  const gltf = await getLoader().parseSync(context, bin, null!, 0);
src/engine-components/postprocessing/Effects/BloomEffect.ts CHANGED
@@ -1,7 +1,6 @@
1
- import type { BloomEffect as _BloomEffect } from "postprocessing";
1
+ import { BlendFunction, BloomEffect as _BloomEffect, SelectiveBloomEffect } from "postprocessing";
2
2
  import { MathUtils } from "three";
3
3
 
4
- import { MODULES } from "../../../engine/engine_modules.js";
5
4
  import { serializable } from "../../../engine/engine_serialization.js";
6
5
  import { PostProcessingEffect } from "../PostProcessingEffect.js";
7
6
  import { VolumeParameter } from "../VolumeParameter.js";
@@ -74,8 +73,8 @@
74
73
 
75
74
  if (this.selectiveBloom) {
76
75
  // https://github.com/pmndrs/postprocessing/blob/64d2829f014cfec97a46bf3c109f3abc55af0715/demo/src/demos/BloomDemo.js#L265
77
- const selectiveBloom = bloom = new MODULES.POSTPROCESSING.MODULE.SelectiveBloomEffect(this.context.scene, this.context.mainCamera!, {
78
- blendFunction: MODULES.POSTPROCESSING.MODULE.BlendFunction.ADD,
76
+ const selectiveBloom = bloom = new SelectiveBloomEffect(this.context.scene, this.context.mainCamera!, {
77
+ blendFunction: BlendFunction.ADD,
79
78
  mipmapBlur: true,
80
79
  luminanceThreshold: this.threshold.value,
81
80
  luminanceSmoothing: this.scatter.value,
@@ -85,8 +84,8 @@
85
84
  selectiveBloom.inverted = true;
86
85
  }
87
86
  else {
88
- bloom = new MODULES.POSTPROCESSING.MODULE.BloomEffect({
89
- blendFunction: MODULES.POSTPROCESSING.MODULE.BlendFunction.ADD,
87
+ bloom = new _BloomEffect({
88
+ blendFunction: BlendFunction.ADD,
90
89
  mipmapBlur: true,
91
90
  luminanceThreshold: this.threshold.value,
92
91
  luminanceSmoothing: this.scatter.value,
src/engine-components/ui/Button.ts CHANGED
@@ -74,7 +74,7 @@
74
74
  }
75
75
 
76
76
  @serializable(EventList)
77
- onClick: EventList<void> = new EventList();
77
+ onClick: EventList = new EventList();
78
78
 
79
79
  private _isHovered: number = 0;
80
80
 
src/engine-components/postprocessing/Effects/ChromaticAberration.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import { ChromaticAberrationEffect } from "postprocessing";
1
2
  import { Vector2 } from "three";
2
3
 
3
- import { MODULES } from "../../../engine/engine_modules.js";
4
4
  import { serializable } from "../../../engine/engine_serialization.js";
5
5
  import { type EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect.js";
6
6
  import { VolumeParameter } from "../VolumeParameter.js";
@@ -21,7 +21,7 @@
21
21
 
22
22
 
23
23
  onCreateEffect(): EffectProviderResult {
24
- const chromatic = new MODULES.POSTPROCESSING.MODULE.ChromaticAberrationEffect();
24
+ const chromatic = new ChromaticAberrationEffect();
25
25
  chromatic.offset = new Vector2(0, 0)
26
26
  chromatic.radialModulation = true;
27
27
  chromatic.modulationOffset = .15;
src/engine-components/Collider.ts CHANGED
@@ -198,9 +198,8 @@
198
198
 
199
199
  if (!this.sharedMesh?.isMesh) {
200
200
  // HACK using the renderer mesh
201
- if (this.gameObject instanceof Mesh || this.gameObject instanceof Group) {
202
- // We're passing a group in here as well, the code below handles that correctly
203
- this.sharedMesh = this.gameObject as Mesh;
201
+ if (this.gameObject instanceof Mesh) {
202
+ this.sharedMesh = this.gameObject;
204
203
  }
205
204
  }
206
205
 
@@ -240,9 +239,6 @@
240
239
  }
241
240
  });
242
241
  }
243
- else {
244
- console.warn("A MeshCollider mesh is assigned, but it's neither a Mesh nor a Group. Please report a bug!", this, this.sharedMesh);
245
- }
246
242
  }
247
243
  }
248
244
  }
src/engine-components/postprocessing/Effects/ColorAdjustments.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import { BrightnessContrastEffect, HueSaturationEffect } from "postprocessing";
1
2
  import { NoToneMapping } from "three";
2
3
 
3
- import { MODULES } from "../../../engine/engine_modules.js";
4
4
  import { serializable } from "../../../engine/engine_serialization.js";
5
5
  import { type EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect.js";
6
6
  import { VolumeParameter } from "../VolumeParameter.js";
@@ -79,10 +79,10 @@
79
79
  }
80
80
  };
81
81
 
82
- const brightnesscontrast = new MODULES.POSTPROCESSING.MODULE.BrightnessContrastEffect();
82
+ const brightnesscontrast = new BrightnessContrastEffect();
83
83
  this.contrast!.onValueChanged = v => brightnesscontrast.contrast = v;
84
84
 
85
- const hueSaturationEffect = new MODULES.POSTPROCESSING.MODULE.HueSaturationEffect();
85
+ const hueSaturationEffect = new HueSaturationEffect();
86
86
 
87
87
  effects.push(brightnesscontrast);
88
88
  effects.push(hueSaturationEffect);
src/engine-components/Component.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  import { activeInHierarchyFieldName } from "../engine/engine_constants.js";
6
6
  import { destroy, findByGuid, foreachComponent, HideFlags, type IInstantiateOptions, instantiate, isActiveInHierarchy, isActiveSelf, isDestroyed, isUsingInstancing, markAsInstancedRendered, setActive } from "../engine/engine_gameobject.js";
7
7
  import * as main from "../engine/engine_mainloop_utils.js";
8
- import { syncDestroy, syncInstantiate, SyncInstantiateOptions } from "../engine/engine_networking_instantiate.js";
8
+ import { syncDestroy, syncInstantiate } from "../engine/engine_networking_instantiate.js";
9
9
  import { Context, FrameEvent } from "../engine/engine_setup.js";
10
10
  import * as threeutils from "../engine/engine_three_utils.js";
11
11
  import type { Collision, ComponentInit, Constructor, ConstructorConcrete, GuidsMap, ICollider, IComponent, IGameObject, SourceIdentifier } from "../engine/engine_types.js";
@@ -115,7 +115,7 @@
115
115
  * @param instance object to instantiate
116
116
  * @param opts options for the instantiation
117
117
  */
118
- public static instantiateSynced(instance: GameObject | Object3D | null, opts: SyncInstantiateOptions): GameObject | null {
118
+ public static instantiateSynced(instance: GameObject | Object3D | null, opts: IInstantiateOptions): GameObject | null {
119
119
  if (!instance) return null;
120
120
  return syncInstantiate(instance as any, opts) as GameObject | null;
121
121
  }
src/engine-components/codegen/components.ts CHANGED
@@ -1,217 +1,217 @@
1
1
  /* eslint-disable */
2
2
  // Export types
3
3
  export class __Ignore {}
4
+ export { ActionBuilder } from "../export/usdz/extensions/behavior/BehavioursBuilder.js";
5
+ export { ActionCollection } from "../export/usdz/extensions/behavior/Actions.js";
6
+ export { ActionModel } from "../export/usdz/extensions/behavior/BehavioursBuilder.js";
4
7
  export { AlignmentConstraint } from "../AlignmentConstraint.js";
5
8
  export { Animation } from "../Animation.js";
6
- export { Keyframe } from "../AnimationCurve.js";
7
9
  export { AnimationCurve } from "../AnimationCurve.js";
10
+ export { AnimationExtension } from "../export/usdz/extensions/Animation.js";
11
+ export { AnimationTrackHandler } from "../timeline/TimelineTracks.js";
8
12
  export { Animator } from "../Animator.js";
9
13
  export { AnimatorController } from "../AnimatorController.js";
14
+ export { Antialiasing } from "../postprocessing/Effects/Antialiasing.js";
15
+ export { AudioExtension } from "../export/usdz/extensions/behavior/AudioExtension.js";
10
16
  export { AudioListener } from "../AudioListener.js";
11
17
  export { AudioSource } from "../AudioSource.js";
12
- export { Avatar_POI } from "../avatar/Avatar_Brain_LookAt.js";
18
+ export { AudioTrackHandler } from "../timeline/TimelineTracks.js";
19
+ export { Avatar } from "../webxr/Avatar.js";
13
20
  export { Avatar_Brain_LookAt } from "../avatar/Avatar_Brain_LookAt.js";
14
21
  export { Avatar_MouthShapes } from "../avatar/Avatar_MouthShapes.js";
15
22
  export { Avatar_MustacheShake } from "../avatar/Avatar_MustacheShake.js";
23
+ export { Avatar_POI } from "../avatar/Avatar_Brain_LookAt.js";
16
24
  export { AvatarBlink_Simple } from "../avatar/AvatarBlink_Simple.js";
17
25
  export { AvatarEyeLook_Rotation } from "../avatar/AvatarEyeLook_Rotation.js";
26
+ export { AvatarLoader } from "../AvatarLoader.js";
27
+ export { AvatarMarker } from "../webxr/WebXRAvatar.js";
18
28
  export { AvatarModel } from "../AvatarLoader.js";
19
- export { AvatarLoader } from "../AvatarLoader.js";
20
29
  export { AxesHelper } from "../AxesHelper.js";
30
+ export { BaseUIComponent } from "../ui/BaseUIComponent.js";
21
31
  export { BasicIKConstraint } from "../BasicIKConstraint.js";
32
+ export { BehaviorExtension } from "../export/usdz/extensions/behavior/Behaviour.js";
33
+ export { BehaviorModel } from "../export/usdz/extensions/behavior/BehavioursBuilder.js";
34
+ export { BloomEffect } from "../postprocessing/Effects/BloomEffect.js";
35
+ export { BoxCollider } from "../Collider.js";
36
+ export { BoxGizmo } from "../Gizmos.js";
22
37
  export { BoxHelperComponent } from "../BoxHelperComponent.js";
38
+ export { Button } from "../ui/Button.js";
39
+ export { CallInfo } from "../EventList.js";
23
40
  export { Camera } from "../Camera.js";
41
+ export { CameraTargetReachedEvent } from "../OrbitControls.js";
42
+ export { Canvas } from "../ui/Canvas.js";
43
+ export { CanvasGroup } from "../ui/CanvasGroup.js";
44
+ export { CapsuleCollider } from "../Collider.js";
45
+ export { ChangeMaterialOnClick } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
46
+ export { ChangeTransformOnClick } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
24
47
  export { CharacterController } from "../CharacterController.js";
25
48
  export { CharacterControllerInput } from "../CharacterController.js";
49
+ export { ChromaticAberration } from "../postprocessing/Effects/ChromaticAberration.js";
26
50
  export { Collider } from "../Collider.js";
27
- export { SphereCollider } from "../Collider.js";
28
- export { BoxCollider } from "../Collider.js";
29
- export { MeshCollider } from "../Collider.js";
30
- export { CapsuleCollider } from "../Collider.js";
51
+ export { ColorAdjustments } from "../postprocessing/Effects/ColorAdjustments.js";
52
+ export { ColorBySpeedModule } from "../particlesystem/ParticleSystemModules.js";
53
+ export { ColorOverLifetimeModule } from "../particlesystem/ParticleSystemModules.js";
31
54
  export { ContactShadows } from "../ContactShadows.js";
32
- export { LogStats } from "../debug/LogStats.js";
55
+ export { ControlTrackHandler } from "../timeline/TimelineTracks.js";
56
+ export { CustomBranding } from "../export/usdz/USDZExporter.js";
57
+ export { Deletable } from "../DeleteBox.js";
33
58
  export { DeleteBox } from "../DeleteBox.js";
34
- export { Deletable } from "../DeleteBox.js";
59
+ export { DepthOfField } from "../postprocessing/Effects/DepthOfField.js";
35
60
  export { DeviceFlag } from "../DeviceFlag.js";
61
+ export { DocumentExtension } from "../export/usdz/extensions/DocumentExtension.js";
36
62
  export { DragControls } from "../DragControls.js";
37
- export { DropListenerAddedEvent } from "../DropListener.js";
38
63
  export { DropListener } from "../DropListener.js";
39
64
  export { Duplicatable } from "../Duplicatable.js";
40
- export { CallInfo } from "../EventList.js";
65
+ export { EffectWrapper } from "../postprocessing/Effects/EffectWrapper.js";
66
+ export { EmissionModule } from "../particlesystem/ParticleSystemModules.js";
67
+ export { EmphasizeOnClick } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
68
+ export { EventList } from "../EventList.js";
41
69
  export { EventListEvent } from "../EventList.js";
42
- export { EventList } from "../EventList.js";
70
+ export { EventSystem } from "../ui/EventSystem.js";
43
71
  export { EventTrigger } from "../EventTrigger.js";
72
+ export { FieldWithDefault } from "../Renderer.js";
73
+ export { FixedJoint } from "../Joints.js";
74
+ export { FlyControls } from "../FlyControls.js";
75
+ export { Fog } from "../Fog.js";
76
+ export { GltfExport } from "../export/gltf/GltfExport.js";
44
77
  export { GltfExportBox } from "../export/gltf/GltfExport.js";
45
- export { GltfExport } from "../export/gltf/GltfExport.js";
46
- export { RegisteredAnimationInfo } from "../export/usdz/extensions/Animation.js";
47
- export { TransformData } from "../export/usdz/extensions/Animation.js";
48
- export { AnimationExtension } from "../export/usdz/extensions/Animation.js";
49
- export { VariantAction } from "../export/usdz/extensions/behavior/Actions.js";
50
- export { ActionCollection } from "../export/usdz/extensions/behavior/Actions.js";
51
- export { AudioExtension } from "../export/usdz/extensions/behavior/AudioExtension.js";
52
- export { BehaviorExtension } from "../export/usdz/extensions/behavior/Behaviour.js";
53
- export { ChangeTransformOnClick } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
54
- export { ChangeMaterialOnClick } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
55
- export { SetActiveOnClick } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
56
- export { HideOnStart } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
57
- export { EmphasizeOnClick } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
58
- export { PlayAudioOnClick } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
59
- export { PlayAnimationOnClick } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
60
- export { PreliminaryAction } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
61
- export { PreliminaryTrigger } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
62
- export { VisibilityAction } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
63
- export { TapGestureTrigger } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
64
- export { BehaviorModel } from "../export/usdz/extensions/behavior/BehavioursBuilder.js";
65
- export { TriggerModel } from "../export/usdz/extensions/behavior/BehavioursBuilder.js";
66
- export { TriggerBuilder } from "../export/usdz/extensions/behavior/BehavioursBuilder.js";
67
- export { GroupActionModel } from "../export/usdz/extensions/behavior/BehavioursBuilder.js";
68
- export { ActionModel } from "../export/usdz/extensions/behavior/BehavioursBuilder.js";
69
- export { ActionBuilder } from "../export/usdz/extensions/behavior/BehavioursBuilder.js";
70
- export { PhysicsExtension } from "../export/usdz/extensions/behavior/PhysicsExtension.js";
71
- export { DocumentExtension } from "../export/usdz/extensions/DocumentExtension.js";
72
- export { USDZText } from "../export/usdz/extensions/USDZText.js";
73
- export { TextBuilder } from "../export/usdz/extensions/USDZText.js";
74
- export { TextExtension } from "../export/usdz/extensions/USDZText.js";
75
- export { USDZUIExtension } from "../export/usdz/extensions/USDZUI.js";
76
- export { CustomBranding } from "../export/usdz/USDZExporter.js";
77
- export { USDZExporter } from "../export/usdz/USDZExporter.js";
78
- export { Fog } from "../Fog.js";
79
- export { BoxGizmo } from "../Gizmos.js";
78
+ export { Gradient } from "../particlesystem/ParticleSystemModules.js";
79
+ export { Graphic } from "../ui/Graphic.js";
80
+ export { GraphicRaycaster } from "../ui/Raycaster.js";
80
81
  export { GridHelper } from "../GridHelper.js";
82
+ export { GridLayoutGroup } from "../ui/Layout.js";
81
83
  export { GroundProjectedEnv } from "../GroundProjection.js";
82
- export { UsageMarker } from "../Interactable.js";
84
+ export { GroupActionModel } from "../export/usdz/extensions/behavior/BehavioursBuilder.js";
85
+ export { HideOnStart } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
86
+ export { HingeJoint } from "../Joints.js";
87
+ export { HorizontalLayoutGroup } from "../ui/Layout.js";
88
+ export { Image } from "../ui/Image.js";
89
+ export { InheritVelocityModule } from "../particlesystem/ParticleSystemModules.js";
90
+ export { InputField } from "../ui/InputField.js";
91
+ export { InstanceHandle } from "../RendererInstancing.js";
92
+ export { InstancingHandler } from "../RendererInstancing.js";
83
93
  export { Interactable } from "../Interactable.js";
84
- export { FixedJoint } from "../Joints.js";
85
- export { HingeJoint } from "../Joints.js";
94
+ export { Keyframe } from "../AnimationCurve.js";
86
95
  export { Light } from "../Light.js";
96
+ export { LimitVelocityOverLifetimeModule } from "../particlesystem/ParticleSystemModules.js";
97
+ export { LODGroup } from "../LODGroup.js";
87
98
  export { LODModel } from "../LODGroup.js";
88
- export { LODGroup } from "../LODGroup.js";
99
+ export { LogStats } from "../debug/LogStats.js";
100
+ export { LookAt } from "../utils/LookAt.js";
89
101
  export { LookAtConstraint } from "../LookAtConstraint.js";
102
+ export { MainModule } from "../particlesystem/ParticleSystemModules.js";
103
+ export { MaskableGraphic } from "../ui/Graphic.js";
104
+ export { MeshCollider } from "../Collider.js";
105
+ export { MeshRenderer } from "../Renderer.js";
106
+ export { MinMaxCurve } from "../particlesystem/ParticleSystemModules.js";
107
+ export { MinMaxGradient } from "../particlesystem/ParticleSystemModules.js";
90
108
  export { NeedleMenu } from "../NeedleMenu.js";
91
109
  export { NestedGltf } from "../NestedGltf.js";
92
110
  export { Networking } from "../Networking.js";
111
+ export { NoiseModule } from "../particlesystem/ParticleSystemModules.js";
112
+ export { ObjectRaycaster } from "../ui/Raycaster.js";
93
113
  export { OffsetConstraint } from "../OffsetConstraint.js";
94
- export { CameraTargetReachedEvent } from "../OrbitControls.js";
114
+ export { OpenURL } from "../utils/OpenURL.js";
95
115
  export { OrbitControls } from "../OrbitControls.js";
96
- export { ParticleSystemRenderer } from "../particlesystem/ParticleSystem.js";
97
- export { ParticleSystem } from "../particlesystem/ParticleSystem.js";
98
- export { SubEmitterSystem } from "../particlesystem/ParticleSystem.js";
99
- export { Gradient } from "../particlesystem/ParticleSystemModules.js";
100
- export { MinMaxCurve } from "../particlesystem/ParticleSystemModules.js";
101
- export { MinMaxGradient } from "../particlesystem/ParticleSystemModules.js";
102
- export { MainModule } from "../particlesystem/ParticleSystemModules.js";
116
+ export { Outline } from "../ui/Outline.js";
117
+ export { Padding } from "../ui/Layout.js";
103
118
  export { ParticleBurst } from "../particlesystem/ParticleSystemModules.js";
104
- export { EmissionModule } from "../particlesystem/ParticleSystemModules.js";
105
- export { ColorOverLifetimeModule } from "../particlesystem/ParticleSystemModules.js";
106
- export { SizeOverLifetimeModule } from "../particlesystem/ParticleSystemModules.js";
107
- export { ShapeModule } from "../particlesystem/ParticleSystemModules.js";
108
- export { NoiseModule } from "../particlesystem/ParticleSystemModules.js";
109
- export { TrailModule } from "../particlesystem/ParticleSystemModules.js";
110
- export { VelocityOverLifetimeModule } from "../particlesystem/ParticleSystemModules.js";
111
- export { TextureSheetAnimationModule } from "../particlesystem/ParticleSystemModules.js";
112
- export { RotationOverLifetimeModule } from "../particlesystem/ParticleSystemModules.js";
113
- export { RotationBySpeedModule } from "../particlesystem/ParticleSystemModules.js";
114
- export { LimitVelocityOverLifetimeModule } from "../particlesystem/ParticleSystemModules.js";
115
- export { InheritVelocityModule } from "../particlesystem/ParticleSystemModules.js";
116
- export { SizeBySpeedModule } from "../particlesystem/ParticleSystemModules.js";
117
- export { ColorBySpeedModule } from "../particlesystem/ParticleSystemModules.js";
118
119
  export { ParticleSubEmitter } from "../particlesystem/ParticleSystemSubEmitter.js";
120
+ export { ParticleSystem } from "../particlesystem/ParticleSystem.js";
121
+ export { ParticleSystemRenderer } from "../particlesystem/ParticleSystem.js";
122
+ export { PhysicsExtension } from "../export/usdz/extensions/behavior/PhysicsExtension.js";
123
+ export { PixelationEffect } from "../postprocessing/Effects/Pixelation.js";
124
+ export { PlayableDirector } from "../timeline/PlayableDirector.js";
125
+ export { PlayAnimationOnClick } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
126
+ export { PlayAudioOnClick } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
119
127
  export { PlayerColor } from "../PlayerColor.js";
120
- export { Antialiasing } from "../postprocessing/Effects/Antialiasing.js";
121
- export { BloomEffect } from "../postprocessing/Effects/BloomEffect.js";
122
- export { ChromaticAberration } from "../postprocessing/Effects/ChromaticAberration.js";
123
- export { ColorAdjustments } from "../postprocessing/Effects/ColorAdjustments.js";
124
- export { DepthOfField } from "../postprocessing/Effects/DepthOfField.js";
125
- export { EffectWrapper } from "../postprocessing/Effects/EffectWrapper.js";
126
- export { PixelationEffect } from "../postprocessing/Effects/Pixelation.js";
127
- export { ScreenSpaceAmbientOcclusion } from "../postprocessing/Effects/ScreenspaceAmbientOcclusion.js";
128
- export { ScreenSpaceAmbientOcclusionN8 } from "../postprocessing/Effects/ScreenspaceAmbientOcclusionN8.js";
129
- export { SharpeningEffect } from "../postprocessing/Effects/Sharpening.js";
130
- export { TiltShiftEffect } from "../postprocessing/Effects/TiltShiftEffect.js";
131
- export { ToneMappingEffect } from "../postprocessing/Effects/Tonemapping.js";
132
- export { Vignette } from "../postprocessing/Effects/Vignette.js";
128
+ export { PointerEventData } from "../ui/PointerEvents.js";
133
129
  export { PostProcessingHandler } from "../postprocessing/PostProcessingHandler.js";
134
- export { Volume } from "../postprocessing/Volume.js";
135
- export { VolumeParameter } from "../postprocessing/VolumeParameter.js";
136
- export { VolumeProfile } from "../postprocessing/VolumeProfile.js";
130
+ export { PreliminaryAction } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
131
+ export { PreliminaryTrigger } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
132
+ export { RawImage } from "../ui/Image.js";
133
+ export { Rect } from "../ui/RectTransform.js";
134
+ export { RectTransform } from "../ui/RectTransform.js";
137
135
  export { ReflectionProbe } from "../ReflectionProbe.js";
138
- export { FieldWithDefault } from "../Renderer.js";
136
+ export { RegisteredAnimationInfo } from "../export/usdz/extensions/Animation.js";
137
+ export { RemoteSkybox } from "../Skybox.js";
139
138
  export { Renderer } from "../Renderer.js";
140
- export { MeshRenderer } from "../Renderer.js";
141
- export { SkinnedMeshRenderer } from "../Renderer.js";
142
- export { InstancingHandler } from "../RendererInstancing.js";
143
- export { InstanceHandle } from "../RendererInstancing.js";
144
139
  export { RendererLightmap } from "../RendererLightmap.js";
145
140
  export { Rigidbody } from "../RigidBody.js";
141
+ export { RotationBySpeedModule } from "../particlesystem/ParticleSystemModules.js";
142
+ export { RotationOverLifetimeModule } from "../particlesystem/ParticleSystemModules.js";
146
143
  export { SceneSwitcher } from "../SceneSwitcher.js";
147
144
  export { ScreenCapture } from "../ScreenCapture.js";
145
+ export { ScreenSpaceAmbientOcclusion } from "../postprocessing/Effects/ScreenspaceAmbientOcclusion.js";
146
+ export { ScreenSpaceAmbientOcclusionN8 } from "../postprocessing/Effects/ScreenspaceAmbientOcclusionN8.js";
147
+ export { SetActiveOnClick } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
148
148
  export { ShadowCatcher } from "../ShadowCatcher.js";
149
- export { RemoteSkybox } from "../Skybox.js";
149
+ export { ShapeModule } from "../particlesystem/ParticleSystemModules.js";
150
+ export { SharpeningEffect } from "../postprocessing/Effects/Sharpening.js";
151
+ export { SignalAsset } from "../timeline/SignalAsset.js";
152
+ export { SignalReceiver } from "../timeline/SignalAsset.js";
153
+ export { SignalReceiverEvent } from "../timeline/SignalAsset.js";
154
+ export { SignalTrackHandler } from "../timeline/TimelineTracks.js";
155
+ export { Size } from "../ui/RectTransform.js";
156
+ export { SizeBySpeedModule } from "../particlesystem/ParticleSystemModules.js";
157
+ export { SizeOverLifetimeModule } from "../particlesystem/ParticleSystemModules.js";
158
+ export { SkinnedMeshRenderer } from "../Renderer.js";
150
159
  export { SmoothFollow } from "../SmoothFollow.js";
160
+ export { SpatialGrabRaycaster } from "../ui/Raycaster.js";
161
+ export { SpatialHtml } from "../ui/SpatialHtml.js";
162
+ export { SpatialTrigger } from "../SpatialTrigger.js";
151
163
  export { SpatialTriggerReceiver } from "../SpatialTrigger.js";
152
- export { SpatialTrigger } from "../SpatialTrigger.js";
153
164
  export { SpectatorCamera } from "../SpectatorCamera.js";
165
+ export { SphereCollider } from "../Collider.js";
154
166
  export { Sprite } from "../SpriteRenderer.js";
155
- export { SpriteSheet } from "../SpriteRenderer.js";
156
167
  export { SpriteData } from "../SpriteRenderer.js";
157
168
  export { SpriteRenderer } from "../SpriteRenderer.js";
169
+ export { SpriteSheet } from "../SpriteRenderer.js";
170
+ export { SubEmitterSystem } from "../particlesystem/ParticleSystem.js";
158
171
  export { SyncedCamera } from "../SyncedCamera.js";
159
172
  export { SyncedRoom } from "../SyncedRoom.js";
160
173
  export { SyncedTransform } from "../SyncedTransform.js";
174
+ export { TapGestureTrigger } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
175
+ export { TeleportTarget } from "../webxr/TeleportTarget.js";
161
176
  export { TestRunner } from "../TestRunner.js";
162
177
  export { TestSimulateUserData } from "../TestRunner.js";
163
- export { PlayableDirector } from "../timeline/PlayableDirector.js";
164
- export { SignalAsset } from "../timeline/SignalAsset.js";
165
- export { SignalReceiverEvent } from "../timeline/SignalAsset.js";
166
- export { SignalReceiver } from "../timeline/SignalAsset.js";
167
- export { AnimationTrackHandler } from "../timeline/TimelineTracks.js";
168
- export { AudioTrackHandler } from "../timeline/TimelineTracks.js";
169
- export { SignalTrackHandler } from "../timeline/TimelineTracks.js";
170
- export { ControlTrackHandler } from "../timeline/TimelineTracks.js";
178
+ export { Text } from "../ui/Text.js";
179
+ export { TextBuilder } from "../export/usdz/extensions/USDZText.js";
180
+ export { TextExtension } from "../export/usdz/extensions/USDZText.js";
181
+ export { TextureSheetAnimationModule } from "../particlesystem/ParticleSystemModules.js";
182
+ export { TiltShiftEffect } from "../postprocessing/Effects/TiltShiftEffect.js";
183
+ export { ToneMappingEffect } from "../postprocessing/Effects/Tonemapping.js";
184
+ export { TrailModule } from "../particlesystem/ParticleSystemModules.js";
185
+ export { TransformData } from "../export/usdz/extensions/Animation.js";
171
186
  export { TransformGizmo } from "../TransformGizmo.js";
172
- export { BaseUIComponent } from "../ui/BaseUIComponent.js";
187
+ export { TriggerBuilder } from "../export/usdz/extensions/behavior/BehavioursBuilder.js";
188
+ export { TriggerModel } from "../export/usdz/extensions/behavior/BehavioursBuilder.js";
189
+ export { UIRaycastUtils } from "../ui/RaycastUtils.js";
173
190
  export { UIRootComponent } from "../ui/BaseUIComponent.js";
174
- export { Button } from "../ui/Button.js";
175
- export { Canvas } from "../ui/Canvas.js";
176
- export { CanvasGroup } from "../ui/CanvasGroup.js";
177
- export { EventSystem } from "../ui/EventSystem.js";
178
- export { Graphic } from "../ui/Graphic.js";
179
- export { MaskableGraphic } from "../ui/Graphic.js";
180
- export { Image } from "../ui/Image.js";
181
- export { RawImage } from "../ui/Image.js";
182
- export { InputField } from "../ui/InputField.js";
183
- export { Padding } from "../ui/Layout.js";
191
+ export { UsageMarker } from "../Interactable.js";
192
+ export { USDZExporter } from "../export/usdz/USDZExporter.js";
193
+ export { USDZText } from "../export/usdz/extensions/USDZText.js";
194
+ export { USDZUIExtension } from "../export/usdz/extensions/USDZUI.js";
195
+ export { VariantAction } from "../export/usdz/extensions/behavior/Actions.js";
196
+ export { VelocityOverLifetimeModule } from "../particlesystem/ParticleSystemModules.js";
184
197
  export { VerticalLayoutGroup } from "../ui/Layout.js";
185
- export { HorizontalLayoutGroup } from "../ui/Layout.js";
186
- export { GridLayoutGroup } from "../ui/Layout.js";
187
- export { Outline } from "../ui/Outline.js";
188
- export { PointerEventData } from "../ui/PointerEvents.js";
189
- export { ObjectRaycaster } from "../ui/Raycaster.js";
190
- export { GraphicRaycaster } from "../ui/Raycaster.js";
191
- export { SpatialGrabRaycaster } from "../ui/Raycaster.js";
192
- export { UIRaycastUtils } from "../ui/RaycastUtils.js";
193
- export { Size } from "../ui/RectTransform.js";
194
- export { Rect } from "../ui/RectTransform.js";
195
- export { RectTransform } from "../ui/RectTransform.js";
196
- export { SpatialHtml } from "../ui/SpatialHtml.js";
197
- export { Text } from "../ui/Text.js";
198
- export { LookAt } from "../utils/LookAt.js";
199
- export { OpenURL } from "../utils/OpenURL.js";
200
198
  export { VideoPlayer } from "../VideoPlayer.js";
199
+ export { Vignette } from "../postprocessing/Effects/Vignette.js";
200
+ export { VisibilityAction } from "../export/usdz/extensions/behavior/BehaviourComponents.js";
201
201
  export { Voip } from "../Voip.js";
202
- export { Avatar } from "../webxr/Avatar.js";
203
- export { XRControllerFollow } from "../webxr/controllers/XRControllerFollow.js";
204
- export { XRControllerModel } from "../webxr/controllers/XRControllerModel.js";
205
- export { XRControllerMovement } from "../webxr/controllers/XRControllerMovement.js";
206
- export { TeleportTarget } from "../webxr/TeleportTarget.js";
202
+ export { Volume } from "../postprocessing/Volume.js";
203
+ export { VolumeParameter } from "../postprocessing/VolumeParameter.js";
204
+ export { VolumeProfile } from "../postprocessing/VolumeProfile.js";
207
205
  export { WebARCameraBackground } from "../webxr/WebARCameraBackground.js";
208
206
  export { WebARSessionRoot } from "../webxr/WebARSessionRoot.js";
209
207
  export { WebXR } from "../webxr/WebXR.js";
210
- export { AvatarMarker } from "../webxr/WebXRAvatar.js";
211
- export { WebXRTrackedImage } from "../webxr/WebXRImageTracking.js";
208
+ export { WebXRImageTracking } from "../webxr/WebXRImageTracking.js";
212
209
  export { WebXRImageTrackingModel } from "../webxr/WebXRImageTracking.js";
213
- export { WebXRImageTracking } from "../webxr/WebXRImageTracking.js";
214
210
  export { WebXRPlaneTracking } from "../webxr/WebXRPlaneTracking.js";
211
+ export { WebXRTrackedImage } from "../webxr/WebXRImageTracking.js";
212
+ export { XRControllerFollow } from "../webxr/controllers/XRControllerFollow.js";
213
+ export { XRControllerModel } from "../webxr/controllers/XRControllerModel.js";
214
+ export { XRControllerMovement } from "../webxr/controllers/XRControllerMovement.js";
215
+ export { XRFlag } from "../webxr/XRFlag.js";
215
216
  export { XRRig } from "../webxr/WebXRRig.js";
216
217
  export { XRState } from "../webxr/XRFlag.js";
217
- export { XRFlag } from "../webxr/XRFlag.js";
src/engine/debug/debug_spatial_console.ts CHANGED
@@ -170,7 +170,6 @@
170
170
  if (!fontFamily) {
171
171
  fontFamily = ThreeMeshUI.FontLibrary.addFontFamily(this.familyName);
172
172
  const variant = fontFamily.addVariant("normal", "normal", "./include/needle/arial-msdf.json", "./include/needle/arial.png") as any as ThreeMeshUI.FontVariant;
173
- /** @ts-ignore */
174
173
  variant?.addEventListener('ready', () => {
175
174
  ThreeMeshUI.update();
176
175
  });
src/engine-components/postprocessing/Effects/DepthOfField.ts CHANGED
@@ -1,7 +1,6 @@
1
- import type { DepthOfFieldEffect } from "postprocessing";
1
+ import { DepthOfFieldEffect } from "postprocessing";
2
2
 
3
3
  import { Mathf } from "../../../engine/engine_math.js";
4
- import { MODULES } from "../../../engine/engine_modules.js";
5
4
  import { serializable } from "../../../engine/engine_serialization.js";
6
5
  import { getParam, isMobileDevice } from "../../../engine/engine_utils.js";
7
6
  import { PostProcessingEffect } from "../PostProcessingEffect.js";
@@ -79,7 +78,7 @@
79
78
  // inverted: true,
80
79
  // // blendFunction: BlendFunction.SET,
81
80
  // });
82
- const dof = new MODULES.POSTPROCESSING.MODULE.DepthOfFieldEffect(this.context.mainCamera!, {
81
+ const dof = new DepthOfFieldEffect(this.context.mainCamera!, {
83
82
  worldFocusRange: .2,