@needle-tools/engine 4.4.0-ci.1 → 4.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +67 -0
- package/dist/assets/generateMeshBVH.worker-b7788939.js +25 -0
- package/dist/needle-engine.bundle.js +7043 -6766
- package/dist/needle-engine.bundle.light.js +7205 -6928
- package/dist/needle-engine.bundle.light.min.js +169 -139
- package/dist/needle-engine.bundle.light.umd.cjs +173 -143
- package/dist/needle-engine.bundle.min.js +169 -139
- package/dist/needle-engine.bundle.umd.cjs +172 -142
- package/dist/needle-engine.js +468 -467
- package/dist/needle-engine.light.js +468 -467
- package/dist/needle-engine.light.min.js +1 -1
- package/dist/needle-engine.light.umd.cjs +1 -1
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/vendor.js +5108 -5122
- package/dist/vendor.light.js +5108 -5122
- package/dist/vendor.light.min.js +84 -84
- package/dist/vendor.light.umd.cjs +78 -78
- package/dist/vendor.min.js +84 -84
- package/dist/vendor.umd.cjs +78 -78
- package/lib/engine/codegen/register_types.js +2 -0
- package/lib/engine/codegen/register_types.js.map +1 -1
- package/lib/engine/engine_addressables.js.map +1 -1
- package/lib/engine/engine_components.js +3 -1
- package/lib/engine/engine_components.js.map +1 -1
- package/lib/engine/engine_context.d.ts +141 -14
- package/lib/engine/engine_context.js +164 -26
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_element.js +12 -10
- package/lib/engine/engine_element.js.map +1 -1
- package/lib/engine/engine_gameobject.js +5 -0
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_license.d.ts +2 -0
- package/lib/engine/engine_license.js +103 -62
- package/lib/engine/engine_license.js.map +1 -1
- package/lib/engine/engine_networking_blob.js +40 -24
- package/lib/engine/engine_networking_blob.js.map +1 -1
- package/lib/engine/engine_physics_rapier.js +10 -9
- package/lib/engine/engine_physics_rapier.js.map +1 -1
- package/lib/engine/engine_serialization_core.js +6 -2
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_utils_screenshot.js +1 -1
- package/lib/engine/engine_utils_screenshot.js.map +1 -1
- package/lib/engine/js-extensions/RGBAColor.d.ts +1 -0
- package/lib/engine/js-extensions/RGBAColor.js +56 -7
- package/lib/engine/js-extensions/RGBAColor.js.map +1 -1
- package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +4 -3
- package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +6 -6
- package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +4 -0
- package/lib/engine/webcomponents/needle menu/needle-menu.js +13 -2
- package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
- package/lib/engine/xr/NeedleXRController.js +2 -3
- package/lib/engine/xr/NeedleXRController.js.map +1 -1
- package/lib/engine/xr/NeedleXRSession.js +12 -12
- package/lib/engine/xr/NeedleXRSession.js.map +1 -1
- package/lib/engine-components/AudioSource.js +7 -0
- package/lib/engine-components/AudioSource.js.map +1 -1
- package/lib/engine-components/Camera.js +18 -12
- package/lib/engine-components/Camera.js.map +1 -1
- package/lib/engine-components/CameraUtils.js +8 -14
- package/lib/engine-components/CameraUtils.js.map +1 -1
- package/lib/engine-components/GroundProjection.js +1 -1
- package/lib/engine-components/GroundProjection.js.map +1 -1
- package/lib/engine-components/NeedleMenu.js +1 -1
- package/lib/engine-components/NeedleMenu.js.map +1 -1
- package/lib/engine-components/OrbitControls.js +3 -1
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/ReflectionProbe.d.ts +1 -0
- package/lib/engine-components/ReflectionProbe.js +16 -9
- package/lib/engine-components/ReflectionProbe.js.map +1 -1
- package/lib/engine-components/SceneSwitcher.js +28 -7
- package/lib/engine-components/SceneSwitcher.js.map +1 -1
- package/lib/engine-components/SyncedTransform.d.ts +6 -0
- package/lib/engine-components/SyncedTransform.js +10 -5
- package/lib/engine-components/SyncedTransform.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +1 -0
- package/lib/engine-components/codegen/components.js +1 -0
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/export/usdz/extensions/USDZUI.js +2 -1
- package/lib/engine-components/export/usdz/extensions/USDZUI.js.map +1 -1
- package/lib/engine-components/ui/BaseUIComponent.d.ts +0 -1
- package/lib/engine-components/ui/BaseUIComponent.js +1 -1
- package/lib/engine-components/ui/BaseUIComponent.js.map +1 -1
- package/lib/engine-components/ui/EventSystem.js +1 -1
- package/lib/engine-components/ui/EventSystem.js.map +1 -1
- package/lib/engine-components/ui/Graphic.js +1 -0
- package/lib/engine-components/ui/Graphic.js.map +1 -1
- package/lib/engine-components/ui/RaycastUtils.js +1 -1
- package/lib/engine-components/ui/RaycastUtils.js.map +1 -1
- package/lib/engine-components/ui/RectTransform.d.ts +2 -2
- package/lib/engine-components/ui/RectTransform.js +9 -6
- package/lib/engine-components/ui/RectTransform.js.map +1 -1
- package/lib/engine-components/ui/Symbols.d.ts +1 -0
- package/lib/engine-components/ui/Symbols.js +2 -0
- package/lib/engine-components/ui/Symbols.js.map +1 -0
- package/lib/engine-components/ui/Utils.js +1 -1
- package/lib/engine-components/ui/Utils.js.map +1 -1
- package/lib/engine-components/utils/EnvironmentScene.d.ts +1 -1
- package/lib/engine-components/utils/EnvironmentScene.js +1 -1
- package/lib/engine-components/utils/EnvironmentScene.js.map +1 -1
- package/package.json +3 -3
- package/plugins/common/license.js +115 -27
- package/plugins/types/userconfig.d.ts +8 -0
- package/plugins/vite/build-pipeline.js +1 -1
- package/plugins/vite/defines.js +3 -1
- package/plugins/vite/dependencies.js +23 -4
- package/plugins/vite/facebook-instant-games.js +7 -4
- package/plugins/vite/index.js +1 -1
- package/plugins/vite/license.js +2 -1
- package/src/engine/codegen/register_types.ts +2 -0
- package/src/engine/engine_addressables.ts +3 -2
- package/src/engine/engine_components.ts +2 -1
- package/src/engine/engine_context.ts +169 -33
- package/src/engine/engine_element.ts +10 -9
- package/src/engine/engine_gameobject.ts +7 -0
- package/src/engine/engine_license.ts +116 -67
- package/src/engine/engine_networking_blob.ts +47 -26
- package/src/engine/engine_physics_rapier.ts +10 -12
- package/src/engine/engine_serialization_core.ts +6 -1
- package/src/engine/engine_utils_screenshot.ts +1 -1
- package/src/engine/js-extensions/RGBAColor.ts +59 -8
- package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +6 -6
- package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +6 -6
- package/src/engine/webcomponents/needle menu/needle-menu.ts +13 -2
- package/src/engine/xr/NeedleXRController.ts +2 -3
- package/src/engine/xr/NeedleXRSession.ts +12 -12
- package/src/engine-components/AudioSource.ts +8 -3
- package/src/engine-components/Camera.ts +34 -22
- package/src/engine-components/CameraUtils.ts +8 -16
- package/src/engine-components/GroundProjection.ts +1 -1
- package/src/engine-components/NeedleMenu.ts +1 -1
- package/src/engine-components/OrbitControls.ts +2 -1
- package/src/engine-components/ReflectionProbe.ts +15 -8
- package/src/engine-components/SceneSwitcher.ts +28 -11
- package/src/engine-components/SyncedTransform.ts +11 -6
- package/src/engine-components/codegen/components.ts +1 -0
- package/src/engine-components/export/usdz/extensions/USDZUI.ts +2 -2
- package/src/engine-components/ui/BaseUIComponent.ts +1 -1
- package/src/engine-components/ui/EventSystem.ts +1 -1
- package/src/engine-components/ui/Graphic.ts +1 -1
- package/src/engine-components/ui/RaycastUtils.ts +1 -1
- package/src/engine-components/ui/RectTransform.ts +10 -7
- package/src/engine-components/ui/Symbols.ts +2 -0
- package/src/engine-components/ui/Utils.ts +2 -1
- package/src/engine-components/utils/EnvironmentScene.ts +1 -1
|
@@ -11,7 +11,7 @@ const _licenseCheckResultChangedCallbacks: ((result: boolean) => void)[] = [];
|
|
|
11
11
|
// This is modified by a bundler (e.g. vite)
|
|
12
12
|
// Do not edit manually
|
|
13
13
|
let NEEDLE_ENGINE_LICENSE_TYPE: string = "basic";
|
|
14
|
-
if (debug)
|
|
14
|
+
if (debug)
|
|
15
15
|
console.log("License Type: " + NEEDLE_ENGINE_LICENSE_TYPE)
|
|
16
16
|
|
|
17
17
|
/** @internal */
|
|
@@ -33,15 +33,24 @@ export function hasIndieLicense() {
|
|
|
33
33
|
return false;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/** @internal */
|
|
37
|
+
export function hasEduLicense() {
|
|
38
|
+
switch (NEEDLE_ENGINE_LICENSE_TYPE) {
|
|
39
|
+
case "edu":
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
36
45
|
/** @internal */
|
|
37
46
|
export function hasCommercialLicense() {
|
|
38
|
-
return hasProLicense() || hasIndieLicense();
|
|
47
|
+
return hasProLicense() || hasIndieLicense() || hasEduLicense();
|
|
39
48
|
}
|
|
40
49
|
|
|
41
50
|
|
|
42
51
|
/** @internal */
|
|
43
52
|
export function onLicenseCheckResultChanged(cb: (result: boolean) => void) {
|
|
44
|
-
if (hasProLicense() || hasIndieLicense())
|
|
53
|
+
if (hasProLicense() || hasIndieLicense() || hasEduLicense())
|
|
45
54
|
return cb(true);
|
|
46
55
|
_licenseCheckResultChangedCallbacks.push(cb);
|
|
47
56
|
}
|
|
@@ -85,14 +94,17 @@ async function checkLicense() {
|
|
|
85
94
|
invokeLicenseCheckResultChanged(true);
|
|
86
95
|
}
|
|
87
96
|
else if (res?.status === 403) {
|
|
97
|
+
invokeLicenseCheckResultChanged(false);
|
|
88
98
|
applicationIsForbidden = true;
|
|
89
99
|
applicationForbiddenText = await res.text();
|
|
90
100
|
}
|
|
91
101
|
else {
|
|
102
|
+
invokeLicenseCheckResultChanged(false);
|
|
92
103
|
if (debug) console.log("License check failed with status " + res?.status);
|
|
93
104
|
}
|
|
94
105
|
}
|
|
95
106
|
catch (err) {
|
|
107
|
+
invokeLicenseCheckResultChanged(false);
|
|
96
108
|
if (debug) console.error("License check failed", err);
|
|
97
109
|
}
|
|
98
110
|
}
|
|
@@ -167,7 +179,9 @@ async function handleForbidden(ctx: IContext) {
|
|
|
167
179
|
|
|
168
180
|
async function showLicenseInfo(ctx: IContext) {
|
|
169
181
|
try {
|
|
170
|
-
if (
|
|
182
|
+
if (!hasProLicense() && !hasIndieLicense()) {
|
|
183
|
+
return onNonCommercialVersionDetected(ctx);
|
|
184
|
+
}
|
|
171
185
|
}
|
|
172
186
|
catch (err) {
|
|
173
187
|
if (debug) console.log("License check failed", err)
|
|
@@ -179,85 +193,120 @@ async function showLicenseInfo(ctx: IContext) {
|
|
|
179
193
|
|
|
180
194
|
|
|
181
195
|
async function onNonCommercialVersionDetected(ctx: IContext) {
|
|
196
|
+
|
|
182
197
|
// if the engine loads faster than the license check, we need to capture the ready event here
|
|
183
198
|
let isReady = false;
|
|
184
199
|
ctx.domElement.addEventListener("ready", () => isReady = true);
|
|
185
200
|
|
|
186
201
|
await runtimeLicenseCheckPromise?.catch(() => { });
|
|
187
|
-
|
|
188
|
-
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
if (hasProLicense() || hasIndieLicense()) return;
|
|
205
|
+
if (hasCommercialLicense() === false) logNonCommercialUse();
|
|
189
206
|
|
|
190
207
|
// check if the engine is already ready (meaning has finished loading)
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
208
|
+
if (isReady) {
|
|
209
|
+
insertNonCommercialUseHint(ctx);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
ctx.domElement.addEventListener("ready", () => {
|
|
213
|
+
insertNonCommercialUseHint(ctx);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
199
216
|
}
|
|
200
217
|
|
|
201
218
|
// const licenseElementIdentifier = "needle-license-element";
|
|
202
219
|
// const licenseDuration = 10000;
|
|
203
220
|
// const licenseDelay = 1200;
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
//
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
221
|
+
function insertNonCommercialUseHint(ctx: IContext) {
|
|
222
|
+
|
|
223
|
+
const style = `
|
|
224
|
+
position: relative;
|
|
225
|
+
display: block;
|
|
226
|
+
background-size: 20px;
|
|
227
|
+
background-position: 10px 5px;
|
|
228
|
+
background-repeat:no-repeat;
|
|
229
|
+
background-image:url('${base64Logo}');
|
|
230
|
+
background-max-size: 40px;
|
|
231
|
+
padding: 10px;
|
|
232
|
+
padding-left: 30px;
|
|
233
|
+
`;
|
|
234
|
+
if (NEEDLE_ENGINE_LICENSE_TYPE === "edu") {
|
|
235
|
+
console.log("%c " + "Supported by Needle for Education – https://needle.tools", style);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
// if the user has a basic license we already show the logo in the menu and log a license message
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const banner = document.createElement("div");
|
|
243
|
+
banner.className = "needle-non-commercial-use";
|
|
244
|
+
banner.innerHTML = "Made with Needle for Education";
|
|
245
|
+
ctx.domElement.shadowRoot?.appendChild(banner);
|
|
246
|
+
let bannerStyle = `
|
|
247
|
+
position: absolute;
|
|
248
|
+
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
249
|
+
font-size: 12px;
|
|
250
|
+
color: rgb(100, 100, 100);
|
|
251
|
+
/*mix-blend-mode: difference;*/
|
|
252
|
+
background-color: transparent;
|
|
253
|
+
z-index: 10000;
|
|
254
|
+
|
|
255
|
+
cursor: pointer;
|
|
256
|
+
user-select: none;
|
|
257
|
+
opacity: 0;
|
|
258
|
+
|
|
259
|
+
bottom: 6px;
|
|
260
|
+
right: 12px;
|
|
261
|
+
transform: translateY(0px);
|
|
262
|
+
transition: all .5s ease-in-out 1s;
|
|
263
|
+
`;
|
|
264
|
+
banner.style.cssText = bannerStyle;
|
|
265
|
+
banner.addEventListener("click", () => { window.open("https://needle.tools", "_blank") });
|
|
266
|
+
let expectedBannerStyle = banner.style.cssText;
|
|
267
|
+
setTimeout(() => {
|
|
268
|
+
bannerStyle = bannerStyle.replace("opacity: 0", "opacity: 1");
|
|
269
|
+
bannerStyle = bannerStyle.replace("transform: translateY(10px)", "transform: translateY(0)");
|
|
270
|
+
banner.style.cssText = bannerStyle;
|
|
271
|
+
expectedBannerStyle = banner.style.cssText;
|
|
272
|
+
}, 100);
|
|
273
|
+
|
|
274
|
+
// ensure the banner is always visible
|
|
275
|
+
const interval = setInterval(() => {
|
|
276
|
+
const parent = ctx.domElement.shadowRoot || ctx.domElement;
|
|
277
|
+
if (banner.parentNode !== parent) {
|
|
278
|
+
parent.appendChild(banner);
|
|
279
|
+
}
|
|
280
|
+
if (expectedBannerStyle != banner.style.cssText) {
|
|
281
|
+
banner.style.cssText = bannerStyle;
|
|
282
|
+
expectedBannerStyle = banner.style.cssText;
|
|
283
|
+
}
|
|
284
|
+
}, 1000);
|
|
285
|
+
|
|
286
|
+
if (hasEduLicense()) {
|
|
287
|
+
const removeDelay = 20_000;
|
|
288
|
+
setTimeout(() => {
|
|
289
|
+
clearInterval(interval);
|
|
290
|
+
banner?.remove();
|
|
291
|
+
// show the logo every x minutes
|
|
292
|
+
const intervalInMinutes = 5;
|
|
293
|
+
setTimeout(() => {
|
|
294
|
+
if (ctx.domElement.parentNode)
|
|
295
|
+
insertNonCommercialUseHint(ctx);
|
|
296
|
+
}, 1000 * 60 * intervalInMinutes)
|
|
297
|
+
}, removeDelay);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
const base64Logo = "data:image/webp;base64,UklGRrABAABXRUJQVlA4WAoAAAAQAAAAHwAAHwAAQUxQSKEAAAARN6CmbSM4WR7vdARON11EBDq3fLiNbVtVzpMCPlKAEzsx0Y/x+Ovuv4dn0EFE/ydAvz6YggXzgh5sVgXM/zOC/4sii7qgGvB5N7hmuQYwkvazWAu1JPW41FXSHq6pnaQWvqYH18Fc0j1hO/BFTtIeSBlJi5w6qIIO7IOrwhFsB2Yxukif0FTRLpXswHR8MxbslKe9VZsn/Ub5C7YFOpqSTABWUDgg6AAAAFAGAJ0BKiAAIAA+7VyoTqmkpCI3+qgBMB2JbACdMt69DwMIQBLhkTO6XwY00UEDK6cNIDnuNibPf0EgAP7Y1myuiQHLDsF/0h5unrGh6WAbv7aegg2ZMd3uRKfT/3SJztcaujYfTvMXspfCTmYcoO6a+vhC3ss4M8uM58t4siiu59I4aOl59e9Sr6xoxYlHf2v+NnBNpJYeJf8jABQAId/PXuBkLEFkiCucgSGEcfhvajql/j3reCGl0M5/9gQWy7ayNPs+wlvIxFnNfSlfuND4CZOCyxOHhRqOmHN4ULHo3tCSrUNvgAA=";
|
|
304
|
+
|
|
255
305
|
let lastLogTime = 0;
|
|
256
306
|
async function logNonCommercialUse(_logo?: string) {
|
|
257
307
|
const now = Date.now();
|
|
258
308
|
if (now - lastLogTime < 2000) return;
|
|
259
309
|
lastLogTime = now;
|
|
260
|
-
const logo = "data:image/webp;base64,UklGRrABAABXRUJQVlA4WAoAAAAQAAAAHwAAHwAAQUxQSKEAAAARN6CmbSM4WR7vdARON11EBDq3fLiNbVtVzpMCPlKAEzsx0Y/x+Ovuv4dn0EFE/ydAvz6YggXzgh5sVgXM/zOC/4sii7qgGvB5N7hmuQYwkvazWAu1JPW41FXSHq6pnaQWvqYH18Fc0j1hO/BFTtIeSBlJi5w6qIIO7IOrwhFsB2Yxukif0FTRLpXswHR8MxbslKe9VZsn/Ub5C7YFOpqSTABWUDgg6AAAAFAGAJ0BKiAAIAA+7VyoTqmkpCI3+qgBMB2JbACdMt69DwMIQBLhkTO6XwY00UEDK6cNIDnuNibPf0EgAP7Y1myuiQHLDsF/0h5unrGh6WAbv7aegg2ZMd3uRKfT/3SJztcaujYfTvMXspfCTmYcoO6a+vhC3ss4M8uM58t4siiu59I4aOl59e9Sr6xoxYlHf2v+NnBNpJYeJf8jABQAId/PXuBkLEFkiCucgSGEcfhvajql/j3reCGl0M5/9gQWy7ayNPs+wlvIxFnNfSlfuND4CZOCyxOHhRqOmHN4ULHo3tCSrUNvgAA=";
|
|
261
310
|
const style = `
|
|
262
311
|
position: relative;
|
|
263
312
|
display: block;
|
|
@@ -265,7 +314,7 @@ async function logNonCommercialUse(_logo?: string) {
|
|
|
265
314
|
background-size: 20px;
|
|
266
315
|
background-position: 10px 5px;
|
|
267
316
|
background-repeat:no-repeat;
|
|
268
|
-
background-image:url('${
|
|
317
|
+
background-image:url('${base64Logo}');
|
|
269
318
|
background-max-size: 40px;
|
|
270
319
|
margin-bottom: 5px;
|
|
271
320
|
margin-top: .3em;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// workaround for this is not a function when deployed
|
|
2
2
|
// see https://github.com/pvorb/node-md5/issues/52
|
|
3
3
|
import md5 from "md5";
|
|
4
|
+
import { FileLoader } from "three";
|
|
4
5
|
|
|
5
6
|
import { showBalloonWarning } from "./debug/index.js";
|
|
6
7
|
import { hasCommercialLicense } from "./engine_license.js";
|
|
@@ -219,35 +220,55 @@ export namespace BlobStorage {
|
|
|
219
220
|
}
|
|
220
221
|
|
|
221
222
|
export async function download(url: string, progressCallback?: (prog: ProgressEvent) => void): Promise<Uint8Array | null> {
|
|
222
|
-
const response = await fetch(url);
|
|
223
|
-
|
|
224
|
-
const reader = response.body?.getReader();
|
|
225
|
-
const contentLength = response.headers.get('Content-Length');
|
|
226
|
-
const total = contentLength ? parseInt(contentLength) : 0;
|
|
227
|
-
|
|
228
|
-
if (!reader) return null;
|
|
229
|
-
|
|
230
|
-
let received: number = 0;
|
|
231
|
-
const chunks: Uint8Array[] = [];
|
|
232
|
-
while (true) {
|
|
233
|
-
const { done, value } = await reader.read();
|
|
234
|
-
if (value) {
|
|
235
|
-
chunks.push(value);
|
|
236
|
-
received += value.length;
|
|
237
|
-
progressCallback?.call(null, new ProgressEvent('progress', { loaded: received, total: total }));
|
|
238
|
-
}
|
|
239
223
|
|
|
240
|
-
|
|
241
|
-
|
|
224
|
+
// Using a FileLoader here instead of manually fetching so we're able to use the three.js cache system
|
|
225
|
+
const loader = new FileLoader();
|
|
226
|
+
loader.setResponseType('arraybuffer');
|
|
227
|
+
// loader.setRequestHeader( this.requestHeader );
|
|
228
|
+
// loader.setWithCredentials( this.withCredentials );
|
|
229
|
+
const res = await loader.loadAsync(url, prog => {
|
|
230
|
+
if (progressCallback) {
|
|
231
|
+
progressCallback.call(null, prog);
|
|
242
232
|
}
|
|
233
|
+
});
|
|
234
|
+
if (!(res instanceof ArrayBuffer)) {
|
|
235
|
+
console.error("Download failed, no arraybuffer returned");
|
|
236
|
+
return null;
|
|
243
237
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
238
|
+
return new Uint8Array(res);
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
// Old solution: this didn't re-use the three.js loading cache. Using a FileLoader the GLTFLoader under the hood is smart enough to NOT start a new download request
|
|
242
|
+
|
|
243
|
+
// const response = await fetch(url);
|
|
244
|
+
|
|
245
|
+
// const reader = response.body?.getReader();
|
|
246
|
+
// const contentLength = response.headers.get('Content-Length');
|
|
247
|
+
// const total = contentLength ? parseInt(contentLength) : 0;
|
|
248
|
+
|
|
249
|
+
// if (!reader) return null;
|
|
250
|
+
|
|
251
|
+
// let received: number = 0;
|
|
252
|
+
// const chunks: Uint8Array[] = [];
|
|
253
|
+
// while (true) {
|
|
254
|
+
// const { done, value } = await reader.read();
|
|
255
|
+
// if (value) {
|
|
256
|
+
// chunks.push(value);
|
|
257
|
+
// received += value.length;
|
|
258
|
+
// progressCallback?.call(null, new ProgressEvent('progress', { loaded: received, total: total }));
|
|
259
|
+
// }
|
|
260
|
+
|
|
261
|
+
// if (done) {
|
|
262
|
+
// break;
|
|
263
|
+
// }
|
|
264
|
+
// }
|
|
265
|
+
// const final = new Uint8Array(received);
|
|
266
|
+
// let position = 0;
|
|
267
|
+
// for (const chunk of chunks) {
|
|
268
|
+
// final.set(chunk, position);
|
|
269
|
+
// position += chunk.length;
|
|
270
|
+
// }
|
|
271
|
+
// return final;
|
|
251
272
|
}
|
|
252
273
|
}
|
|
253
274
|
|
|
@@ -598,17 +598,15 @@ export class RapierPhysics implements IPhysicsEngine {
|
|
|
598
598
|
scale.multiplyScalar(0.5);
|
|
599
599
|
|
|
600
600
|
// prevent negative scale
|
|
601
|
-
if (scale.x < 0)
|
|
602
|
-
|
|
603
|
-
if (scale.
|
|
604
|
-
scale.y = Math.abs(scale.y);
|
|
605
|
-
if (scale.z < 0)
|
|
606
|
-
scale.z = Math.abs(scale.z);
|
|
601
|
+
if (scale.x < 0) scale.x = Math.abs(scale.x);
|
|
602
|
+
if (scale.y < 0) scale.y = Math.abs(scale.y);
|
|
603
|
+
if (scale.z < 0) scale.z = Math.abs(scale.z);
|
|
607
604
|
|
|
608
605
|
// prevent zero scale - seems normals are flipped otherwise
|
|
609
|
-
|
|
610
|
-
if (scale.
|
|
611
|
-
if (scale.
|
|
606
|
+
const minSize = 0.0000001;
|
|
607
|
+
if (scale.x < minSize) scale.x = minSize;
|
|
608
|
+
if (scale.y < minSize) scale.y = minSize;
|
|
609
|
+
if (scale.z < minSize) scale.z = minSize;
|
|
612
610
|
|
|
613
611
|
const desc = MODULES.RAPIER_PHYSICS.MODULE.ColliderDesc.cuboid(scale.x, scale.y, scale.z);
|
|
614
612
|
// const objectLayerMask = collider.gameObject.layers.mask;
|
|
@@ -994,9 +992,9 @@ export class RapierPhysics implements IPhysicsEngine {
|
|
|
994
992
|
const sc = col as IBoxCollider;
|
|
995
993
|
const obj = col.gameObject;
|
|
996
994
|
const scale = getWorldScale(obj, this._tempPosition);
|
|
997
|
-
const newX = sc.size.x * 0.5 * scale.x;
|
|
998
|
-
const newY = sc.size.y * 0.5 * scale.y;
|
|
999
|
-
const newZ = sc.size.z * 0.5 * scale.z;
|
|
995
|
+
const newX = Math.abs(sc.size.x * 0.5 * scale.x);
|
|
996
|
+
const newY = Math.abs(sc.size.y * 0.5 * scale.y);
|
|
997
|
+
const newZ = Math.abs(sc.size.z * 0.5 * scale.z);
|
|
1000
998
|
sizeHasChanged = cuboid.halfExtents.x !== newX || cuboid.halfExtents.y !== newY || cuboid.halfExtents.z !== newZ;
|
|
1001
999
|
cuboid.halfExtents.x = newX;
|
|
1002
1000
|
cuboid.halfExtents.y = newY;
|
|
@@ -517,11 +517,14 @@ function deserializeObjectWithType(data: any, typeOrConstructor: ConstructorConc
|
|
|
517
517
|
// then we dont need to do anything else
|
|
518
518
|
if (!typeIsFunction && currentValue) {
|
|
519
519
|
if (currentValue instanceof Material) return currentValue;
|
|
520
|
-
if (currentValue instanceof Texture) return currentValue;
|
|
521
520
|
if (currentValue instanceof Mesh) return currentValue;
|
|
522
521
|
if (currentValue instanceof BufferGeometry) return currentValue;
|
|
523
522
|
if (currentValue instanceof AnimationClip) return currentValue;
|
|
523
|
+
// We need to call the RenderTexture deserializer so we can not just return here:
|
|
524
|
+
// if (currentValue instanceof Texture) return currentValue;
|
|
525
|
+
// So this has now been moved down below the deserializer code
|
|
524
526
|
}
|
|
527
|
+
|
|
525
528
|
// Removed this line because it prevents assigning serialized values to existing instances for e.g. EventList
|
|
526
529
|
// https://linear.app/needle/issue/NE-5350
|
|
527
530
|
// if (!typeIsFunction && currentValue instanceof type) return currentValue;
|
|
@@ -594,6 +597,8 @@ function deserializeObjectWithType(data: any, typeOrConstructor: ConstructorConc
|
|
|
594
597
|
|
|
595
598
|
// console.log(type.prototype.get("$serializedTypes"));
|
|
596
599
|
|
|
600
|
+
// We check textures AFTER running deserializers because some textures might need to be converted to a RenderTexture
|
|
601
|
+
if (currentValue instanceof Texture) return currentValue;
|
|
597
602
|
|
|
598
603
|
let instance: any = undefined;
|
|
599
604
|
if (data && (data.isMaterial || data.isTexture || data.isObject3D || data instanceof AnimationClip)) {
|
|
@@ -175,7 +175,7 @@ export function screenshot2(opts: ScreenshotOptionsDataUrl | ScreenshotOptionsTe
|
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
const renderer = context.renderer;
|
|
178
|
-
const isXRScreenshot = renderer.xr.enabled;
|
|
178
|
+
const isXRScreenshot = renderer.xr.enabled && renderer.xr.isPresenting;
|
|
179
179
|
|
|
180
180
|
|
|
181
181
|
// Perform XR screenshot in onBeforeRender (after the screenshot we want to render the original camera view)
|
|
@@ -20,14 +20,15 @@ export class RGBAColor extends Color {
|
|
|
20
20
|
*/
|
|
21
21
|
constructor(r: number, g: number, b: number, a: number);
|
|
22
22
|
constructor(r: number | ColorRepresentation, g?: number, b?: number, a?: number) {
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
// AMD compilation creates recursive super calls with local function wrappers
|
|
24
|
+
// Call super() first with the minimum arguments needed
|
|
25
|
+
super();
|
|
26
|
+
|
|
27
|
+
if (typeof r === "number" && typeof g === "number" && typeof b === "number") {
|
|
28
|
+
this.set(r, g, b);
|
|
29
|
+
this.alpha = typeof a === "number" ? a : 1;
|
|
30
|
+
} else if (r !== undefined) {
|
|
31
|
+
this.set(r as ColorRepresentation);
|
|
31
32
|
this.alpha = 1;
|
|
32
33
|
}
|
|
33
34
|
}
|
|
@@ -73,4 +74,54 @@ export class RGBAColor extends Color {
|
|
|
73
74
|
this.alpha = array[offset + 3];
|
|
74
75
|
return super.fromArray(array, offset);
|
|
75
76
|
}
|
|
77
|
+
|
|
78
|
+
static fromColorRepresentation(col: ColorRepresentation) {
|
|
79
|
+
|
|
80
|
+
if (typeof col === "string") {
|
|
81
|
+
if (col.trim() === "transparent") {
|
|
82
|
+
return new RGBAColor(0, 0, 0, 0);
|
|
83
|
+
}
|
|
84
|
+
// handle hex colors with alpha
|
|
85
|
+
if (col.startsWith("#") && col.length === 9) {
|
|
86
|
+
const hex = parseInt(col.slice(1, 9), 16);
|
|
87
|
+
const r = (hex >> 24) & 0xff;
|
|
88
|
+
const g = (hex >> 16) & 0xff;
|
|
89
|
+
const b = (hex >> 8) & 0xff;
|
|
90
|
+
const a = (hex >> 0) & 0xff;
|
|
91
|
+
return new RGBAColor(r / 255, g / 255, b / 255, a / 255);
|
|
92
|
+
}
|
|
93
|
+
// handle hex colors
|
|
94
|
+
else if (col.startsWith("#")) {
|
|
95
|
+
const hex = parseInt(col.slice(1), 16);
|
|
96
|
+
const r = (hex >> 16) & 0xff;
|
|
97
|
+
const g = (hex >> 8) & 0xff;
|
|
98
|
+
const b = (hex >> 0) & 0xff;
|
|
99
|
+
return new RGBAColor(r / 255, g / 255, b / 255, 1);
|
|
100
|
+
}
|
|
101
|
+
// handle rgba string
|
|
102
|
+
else if (col.startsWith("rgba")) {
|
|
103
|
+
const rgba = col.slice(5, -1).split(",").map(Number);
|
|
104
|
+
return new RGBAColor(rgba[0] / 255, rgba[1] / 255, rgba[2] / 255, rgba[3]);
|
|
105
|
+
}
|
|
106
|
+
// handle rgb string
|
|
107
|
+
else if (col.startsWith("rgb")) {
|
|
108
|
+
const rgb = col.slice(4, -1).split(",").map(Number);
|
|
109
|
+
return new RGBAColor(rgb[0] / 255, rgb[1] / 255, rgb[2] / 255, 1);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else if (Array.isArray(col)) {
|
|
113
|
+
// handle rgba colors
|
|
114
|
+
if (col.length === 4) {
|
|
115
|
+
return new RGBAColor(col[0], col[1], col[2], col[3]);
|
|
116
|
+
}
|
|
117
|
+
// handle rgb colors
|
|
118
|
+
else if (col.length === 3) {
|
|
119
|
+
return new RGBAColor(col[0], col[1], col[2], 1);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
console.error("Invalid color array length. Expected 3 or 4, got " + col.length);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return new RGBAColor(col);
|
|
126
|
+
}
|
|
76
127
|
}
|
|
@@ -3,13 +3,13 @@ import { MeshBVH } from 'three-mesh-bvh';
|
|
|
3
3
|
|
|
4
4
|
// Modified according to https://github.com/gkjohnson/three-mesh-bvh/issues/636#issuecomment-2209571751
|
|
5
5
|
import { WorkerBase } from "three-mesh-bvh/src/workers/utils/WorkerBase.js";
|
|
6
|
-
import generateMeshBVHWorker from "three-mesh-bvh/src/workers/generateMeshBVH.worker.js?worker&inline";
|
|
7
6
|
|
|
8
7
|
export class GenerateMeshBVHWorker extends WorkerBase {
|
|
9
8
|
|
|
10
9
|
constructor() {
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
super(new Worker(new URL("three-mesh-bvh/src/workers/generateMeshBVH.worker.js", import.meta.url), {
|
|
11
|
+
type: 'module'
|
|
12
|
+
}));
|
|
13
13
|
this.name = 'GenerateMeshBVHWorker';
|
|
14
14
|
|
|
15
15
|
}
|
|
@@ -27,10 +27,10 @@ export class GenerateMeshBVHWorker extends WorkerBase {
|
|
|
27
27
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
reject( new Error( `GenerateMeshBVHWorker: ${ e.message }` ) );
|
|
30
|
+
worker.onerror = e => {
|
|
33
31
|
|
|
32
|
+
reject(new Error(`[GenerateMeshBVHWorker] ${e.message || "Unknown error. Please check the server console. If you're using vite try adding 'three-mesh-bvh' to 'optimizeDeps.exclude' in your vite.config.js"}`));
|
|
33
|
+
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
worker.onmessage = e => {
|
|
@@ -155,7 +155,7 @@ export class NeedleSpatialMenu {
|
|
|
155
155
|
private readonly positionFilter = new OneEuroFilterXYZ(90, .5);
|
|
156
156
|
|
|
157
157
|
private updateMenu() {
|
|
158
|
-
performance.mark('NeedleSpatialMenu updateMenu start');
|
|
158
|
+
//performance.mark('NeedleSpatialMenu updateMenu start');
|
|
159
159
|
const menu = this.getMenu();
|
|
160
160
|
this.handleNeedleWatermark();
|
|
161
161
|
this._context.scene.add(menu as any);
|
|
@@ -200,14 +200,14 @@ export class NeedleSpatialMenu {
|
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
if (this.uiisDirty) {
|
|
203
|
-
performance.mark('SpatialMenu.update.uiisDirty.start');
|
|
203
|
+
//performance.mark('SpatialMenu.update.uiisDirty.start');
|
|
204
204
|
this.uiisDirty = false;
|
|
205
205
|
ThreeMeshUI.update();
|
|
206
|
-
performance.mark('SpatialMenu.update.uiisDirty.end');
|
|
207
|
-
performance.measure('SpatialMenu.update.uiisDirty', 'SpatialMenu.update.uiisDirty.start', 'SpatialMenu.update.uiisDirty.end');
|
|
206
|
+
//performance.mark('SpatialMenu.update.uiisDirty.end');
|
|
207
|
+
//performance.measure('SpatialMenu.update.uiisDirty', 'SpatialMenu.update.uiisDirty.start', 'SpatialMenu.update.uiisDirty.end');
|
|
208
208
|
}
|
|
209
|
-
performance.mark('NeedleSpatialMenu updateMenu end');
|
|
210
|
-
performance.measure('SpatialMenu.update', 'NeedleSpatialMenu updateMenu start', 'NeedleSpatialMenu updateMenu end');
|
|
209
|
+
//performance.mark('NeedleSpatialMenu updateMenu end');
|
|
210
|
+
//performance.measure('SpatialMenu.update', 'NeedleSpatialMenu updateMenu start', 'NeedleSpatialMenu updateMenu end');
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
private ensureRenderOnTop(obj: Object3D, level: number = 0) {
|
|
@@ -174,6 +174,10 @@ export class NeedleMenu {
|
|
|
174
174
|
this._spatialMenu?.showNeedleLogo(visible);
|
|
175
175
|
// setTimeout(()=>this.showNeedleLogo(!visible), 1000);
|
|
176
176
|
}
|
|
177
|
+
/** @returns true if the logo is visible */
|
|
178
|
+
get logoIsVisible() {
|
|
179
|
+
return this._menu.logoIsVisible;
|
|
180
|
+
}
|
|
177
181
|
/** When enabled=true the menu will be visible in VR/AR sessions */
|
|
178
182
|
showSpatialMenu(enabled: boolean) {
|
|
179
183
|
this._spatialMenu.setEnabled(enabled);
|
|
@@ -640,7 +644,7 @@ export class NeedleMenuElement extends HTMLElement {
|
|
|
640
644
|
|
|
641
645
|
</style>
|
|
642
646
|
|
|
643
|
-
<div id="root" class="logo-
|
|
647
|
+
<div id="root" class="logo-hidden floating-panel-style bottom">
|
|
644
648
|
<div class="wrapper">
|
|
645
649
|
<div class="foldout">
|
|
646
650
|
<div class="options" part="options">
|
|
@@ -699,6 +703,9 @@ export class NeedleMenuElement extends HTMLElement {
|
|
|
699
703
|
if (visible === undefined) visible = false;
|
|
700
704
|
this.___onSetLogoVisible(visible);
|
|
701
705
|
}
|
|
706
|
+
else {
|
|
707
|
+
this.___onSetLogoVisible(true);
|
|
708
|
+
}
|
|
702
709
|
}));
|
|
703
710
|
} catch (e) {
|
|
704
711
|
console.error("[Needle Menu] License check failed.", e);
|
|
@@ -822,13 +829,17 @@ export class NeedleMenuElement extends HTMLElement {
|
|
|
822
829
|
this._userRequestedLogoVisible = visible;
|
|
823
830
|
if (!visible) {
|
|
824
831
|
if (!hasCommercialLicense() || debugNonCommercial) {
|
|
825
|
-
console.warn("Needle
|
|
832
|
+
console.warn("[Needle Engine] You need a PRO license to hide the Needle Engine logo in production.");
|
|
826
833
|
const localNetwork = isLocalNetwork()
|
|
827
834
|
if (!localNetwork) return;
|
|
828
835
|
}
|
|
829
836
|
}
|
|
830
837
|
this.___onSetLogoVisible(visible);
|
|
831
838
|
}
|
|
839
|
+
/** @returns true if the logo is visible */
|
|
840
|
+
get logoIsVisible() {
|
|
841
|
+
return !this.root.classList.contains("logo-hidden");
|
|
842
|
+
}
|
|
832
843
|
|
|
833
844
|
private ___onSetLogoVisible(visible: boolean) {
|
|
834
845
|
this.logoContainer.style.display = "";
|
|
@@ -381,12 +381,11 @@ export class NeedleXRController implements IPointerHitEventReceiver {
|
|
|
381
381
|
}
|
|
382
382
|
|
|
383
383
|
onUpdate(frame: XRFrame) {
|
|
384
|
-
performance.mark('NeedleXRController onUpdate start');
|
|
385
384
|
this.onUpdateFrame(frame);
|
|
386
385
|
this.updateInputEvents();
|
|
387
386
|
this.onUpdateMove();
|
|
388
|
-
performance.mark('NeedleXRController onUpdate end');
|
|
389
|
-
performance.measure('NeedleXRController onUpdate', 'NeedleXRController onUpdate start', 'NeedleXRController onUpdate end');
|
|
387
|
+
//performance.mark('NeedleXRController onUpdate end');
|
|
388
|
+
//performance.measure('NeedleXRController onUpdate', 'NeedleXRController onUpdate start', 'NeedleXRController onUpdate end');
|
|
390
389
|
}
|
|
391
390
|
|
|
392
391
|
onRenderDebug() {
|