diff --git a/config-overrides.js b/config-overrides.js index 7aadc1274..16aad1093 100644 --- a/config-overrides.js +++ b/config-overrides.js @@ -34,3 +34,32 @@ module.exports = function override(webpackConfig) { return webpackConfig; }; + +// three is ESM-only since r186 (`three.cjs` is a deprecated shim re-exporting `three.module.js`), +// so Jest has to convert it to CommonJS and should resolve `three` straight to its ES module build +module.exports.jest = function overrideJest(jestConfig) { + jestConfig.transformIgnorePatterns = [ + '[/\\\\]node_modules[/\\\\](?!three[/\\\\]).+\\.(js|jsx|mjs|cjs|ts|tsx)$', + '^.+\\.module\\.(css|sass|scss)$' + ]; + + // only the module syntax needs converting, Node runs the rest of three natively + jestConfig.transform = { + '[/\\\\]node_modules[/\\\\]three[/\\\\].+\\.js$': [ + require.resolve('babel-jest'), + { + babelrc: false, + configFile: false, + plugins: [require.resolve('@babel/plugin-transform-modules-commonjs')] + } + ], + ...jestConfig.transform + }; + + jestConfig.moduleNameMapper = { + ...jestConfig.moduleNameMapper, + '^three$': '/node_modules/three/build/three.module.js' + }; + + return jestConfig; +}; diff --git a/package-lock.json b/package-lock.json index 9e6c61bf8..6a3349aba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,7 +49,7 @@ "set-interval-async": "^3.0.3", "signals": "^1.0.0", "split-grid": "^1.0.11", - "three": "^0.181.1", + "three": "^0.186.1", "throttle-debounce": "^5.0.2", "typescript": "^5.2.2", "use-interval": "^1.4.0", @@ -62,7 +62,7 @@ "@types/react": "^19.2.7", "@types/react-async-script": "^1.2.5", "@types/selenium-webdriver": "^4.35.4", - "@types/three": "^0.177.0", + "@types/three": "^0.186.0", "cross-env": "^10.1.0", "dependency-cruiser": "^17.3.1", "eslint-plugin-simple-import-sort": "^12.1.1", @@ -5500,19 +5500,18 @@ "license": "MIT" }, "node_modules/@types/three": { - "version": "0.177.0", - "resolved": "https://registry.npmjs.org/@types/three/-/three-0.177.0.tgz", - "integrity": "sha512-/ZAkn4OLUijKQySNci47lFO+4JLE1TihEjsGWPUT+4jWqxtwOPPEwJV1C3k5MEx0mcBPCdkFjzRzDOnHEI1R+A==", + "version": "0.186.0", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.186.0.tgz", + "integrity": "sha512-mxYSBpDC+D0pLfSP6sW4WZTcT+nrtmZcimMqnVmy36Hte3XpeYSrvgg4TRdaM1GemGog1AWzI5qL2VoIfMXbJQ==", "dev": true, "license": "MIT", "dependencies": { "@dimforge/rapier3d-compat": "~0.12.0", "@tweenjs/tween.js": "~23.1.3", "@types/stats.js": "*", - "@types/webxr": "*", - "@webgpu/types": "*", - "fflate": "~0.8.2", - "meshoptimizer": "~0.18.1" + "@types/webxr": ">=0.5.17", + "fflate": "~0.8.3", + "meshoptimizer": "~1.1.1" } }, "node_modules/@types/throttle-debounce": { @@ -5973,13 +5972,6 @@ "@xtuc/long": "4.2.2" } }, - "node_modules/@webgpu/types": { - "version": "0.1.60", - "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.60.tgz", - "integrity": "sha512-8B/tdfRFKdrnejqmvq95ogp8tf52oZ51p3f4QD5m5Paey/qlX4Rhhy5Y8tgFMi7Ms70HzcMMw3EQjH/jdhTwlA==", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -10412,9 +10404,9 @@ } }, "node_modules/fflate": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", - "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", + "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", "dev": true, "license": "MIT" }, @@ -16411,9 +16403,9 @@ } }, "node_modules/meshoptimizer": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.18.1.tgz", - "integrity": "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-1.1.1.tgz", + "integrity": "sha512-oRFNWJRDA/WTrVj7NWvqa5HqE1t9MYDj2VaWirQCzCCrAd2GHrqR/sQezCxiWATPNlKTcRaPRHPJwIRoPBAp5g==", "dev": true, "license": "MIT" }, @@ -22243,9 +22235,9 @@ } }, "node_modules/three": { - "version": "0.181.1", - "resolved": "https://registry.npmjs.org/three/-/three-0.181.1.tgz", - "integrity": "sha512-bz9xZUQMw3pJbjKy7roiwXWgAp+oVUa+4k5o0oBAQ+IFJuru1xzvtk63h6k72XZanXS/SgoEhV6927Vgazyq2w==", + "version": "0.186.1", + "resolved": "https://registry.npmjs.org/three/-/three-0.186.1.tgz", + "integrity": "sha512-blFeqb49wRCSGUGj7gtpfnSGHy2lwDk94RhUmS1c/hTby70kvChbWpkJ4Pm1390LqzzvTmzgXKHPEafJwCb8jA==", "license": "MIT" }, "node_modules/throat": { diff --git a/package.json b/package.json index edd214ceb..65875c167 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "set-interval-async": "^3.0.3", "signals": "^1.0.0", "split-grid": "^1.0.11", - "three": "^0.181.1", + "three": "^0.186.1", "throttle-debounce": "^5.0.2", "typescript": "^5.2.2", "use-interval": "^1.4.0", @@ -210,7 +210,7 @@ "@types/react": "^19.2.7", "@types/react-async-script": "^1.2.5", "@types/selenium-webdriver": "^4.35.4", - "@types/three": "^0.177.0", + "@types/three": "^0.186.0", "cross-env": "^10.1.0", "dependency-cruiser": "^17.3.1", "eslint-plugin-simple-import-sort": "^12.1.1", diff --git a/src/ThreeEditor/Simulation/Materials/SimulationMaterial.ts b/src/ThreeEditor/Simulation/Materials/SimulationMaterial.ts index 58beb608f..de4a4d4d8 100644 --- a/src/ThreeEditor/Simulation/Materials/SimulationMaterial.ts +++ b/src/ThreeEditor/Simulation/Materials/SimulationMaterial.ts @@ -147,7 +147,8 @@ export default class SimulationMaterial }: SimulationMaterialJSON ): SimulationMaterial { const material = new SimulationMaterial(editor, name, sanitizedName, icru, density); - material.uuid = uuid; + // @types/three marks Material.uuid as readonly, but three keeps it writable and we restore it on load + (material as { uuid: string }).uuid = uuid; material.customStoppingPower = customStoppingPower ?? false; material.renderProps = renderProps; material.applyRenderProps(); diff --git a/src/ThreeEditor/js/viewport/ViewportManager.js b/src/ThreeEditor/js/viewport/ViewportManager.js index da60d2322..8694e5a82 100644 --- a/src/ThreeEditor/js/viewport/ViewportManager.js +++ b/src/ThreeEditor/js/viewport/ViewportManager.js @@ -587,11 +587,12 @@ function ViewManager(editor) { // animations - const clock = new THREE.Clock(); // only used for animations + const timer = new THREE.Timer(); // only used for animations - function animate() { + function animate(timestamp) { const { mixer } = editor; - const delta = clock.getDelta(); + timer.update(timestamp); + const delta = timer.getDelta(); let needsUpdate = false;