@needle-tools/engine 4.10.5-next.a5d5bf4 → 4.11.0-next.358bed1
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 +10 -0
- package/components.needle.json +1 -1
- package/dist/{gltf-progressive-B63NpN_i.js → gltf-progressive-CXVECA3a.js} +1 -1
- package/dist/{needle-engine.bundle-DPHrCUDs.umd.cjs → needle-engine.bundle-BX6JeEif.umd.cjs} +139 -139
- package/dist/{needle-engine.bundle-D56E0HeK.min.js → needle-engine.bundle-CDMrKOoV.min.js} +137 -137
- package/dist/{needle-engine.bundle-B2qX4saI.js → needle-engine.bundle-Dy5wgRLd.js} +6591 -6436
- package/dist/needle-engine.d.ts +14 -0
- package/dist/needle-engine.js +321 -320
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/lib/engine/codegen/register_types.js +2 -0
- package/lib/engine/codegen/register_types.js.map +1 -1
- package/lib/engine/engine_gizmos.js +2 -2
- package/lib/engine/engine_gizmos.js.map +1 -1
- package/lib/engine/engine_physics.js +44 -14
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/js-extensions/Object3D.d.ts +14 -0
- package/lib/engine/js-extensions/Object3D.js +13 -0
- package/lib/engine/js-extensions/Object3D.js.map +1 -1
- package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +2 -1
- package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
- package/lib/engine-components/Renderer.js +33 -32
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/RendererLightmap.d.ts +7 -5
- package/lib/engine-components/RendererLightmap.js +29 -30
- package/lib/engine-components/RendererLightmap.js.map +1 -1
- package/lib/engine-components/SeeThrough.d.ts +70 -0
- package/lib/engine-components/SeeThrough.js +223 -0
- package/lib/engine-components/SeeThrough.js.map +1 -0
- 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/ui/Graphic.js +13 -1
- package/lib/engine-components/ui/Graphic.js.map +1 -1
- package/lib/engine-components/ui/RaycastUtils.js +5 -3
- package/lib/engine-components/ui/RaycastUtils.js.map +1 -1
- package/lib/engine-components/utils/LookAt.js +4 -2
- package/lib/engine-components/utils/LookAt.js.map +1 -1
- package/lib/engine-components/web/Clickthrough.d.ts +2 -1
- package/lib/engine-components/web/Clickthrough.js +2 -1
- package/lib/engine-components/web/Clickthrough.js.map +1 -1
- package/lib/engine-components/web/CursorFollow.d.ts +7 -1
- package/lib/engine-components/web/CursorFollow.js +35 -2
- package/lib/engine-components/web/CursorFollow.js.map +1 -1
- package/package.json +1 -1
- package/plugins/common/needle-engine.js +41 -0
- package/plugins/common/worker.js +130 -0
- package/plugins/vite/asap.js +5 -23
- package/plugins/vite/dependencies.js +21 -11
- package/plugins/vite/index.js +4 -0
- package/plugins/vite/needle-app.js +148 -0
- package/src/engine/codegen/register_types.ts +2 -0
- package/src/engine/engine_gizmos.ts +3 -3
- package/src/engine/engine_physics.ts +51 -14
- package/src/engine/js-extensions/Object3D.ts +32 -0
- package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +3 -1
- package/src/engine-components/Renderer.ts +38 -37
- package/src/engine-components/RendererLightmap.ts +31 -33
- package/src/engine-components/SeeThrough.ts +256 -0
- package/src/engine-components/codegen/components.ts +1 -0
- package/src/engine-components/ui/Graphic.ts +13 -1
- package/src/engine-components/ui/RaycastUtils.ts +9 -8
- package/src/engine-components/utils/LookAt.ts +4 -1
- package/src/engine-components/web/Clickthrough.ts +2 -1
- package/src/engine-components/web/CursorFollow.ts +48 -7
|
@@ -4,9 +4,13 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
+
import { Ray } from "three";
|
|
8
|
+
import { Gizmos } from "../../engine/engine_gizmos.js";
|
|
7
9
|
import { serializable } from "../../engine/engine_serialization_decorator.js";
|
|
8
10
|
import { getTempVector } from "../../engine/engine_three_utils.js";
|
|
11
|
+
import { getParam } from "../../engine/engine_utils.js";
|
|
9
12
|
import { Behaviour } from "../Component.js";
|
|
13
|
+
const debug = getParam("debugcursor");
|
|
10
14
|
/**
|
|
11
15
|
* The CursorFollow component makes the object follow the cursor (or touch) position on screen.
|
|
12
16
|
*
|
|
@@ -32,6 +36,10 @@ export class CursorFollow extends Behaviour {
|
|
|
32
36
|
* @default true
|
|
33
37
|
*/
|
|
34
38
|
keepDistance = true;
|
|
39
|
+
/**
|
|
40
|
+
* If true, the object will attempt to snap to the surface of other objects in the scene using a raycast.
|
|
41
|
+
*/
|
|
42
|
+
snapToSurface = false;
|
|
35
43
|
_distance = -1;
|
|
36
44
|
updateDistance(force = false) {
|
|
37
45
|
if (!force && (this.keepDistance && this._distance !== -1)) {
|
|
@@ -43,10 +51,12 @@ export class CursorFollow extends Behaviour {
|
|
|
43
51
|
awake() {
|
|
44
52
|
this._distance = -1;
|
|
45
53
|
}
|
|
54
|
+
/** @internal */
|
|
46
55
|
onEnable() {
|
|
47
56
|
this._distance = -1;
|
|
48
57
|
window.addEventListener('pointermove', this._onPointerMove);
|
|
49
58
|
}
|
|
59
|
+
/** @internal */
|
|
50
60
|
onDisable() {
|
|
51
61
|
window.removeEventListener('pointermove', this._onPointerMove);
|
|
52
62
|
}
|
|
@@ -65,7 +75,7 @@ export class CursorFollow extends Behaviour {
|
|
|
65
75
|
this._ndc_y = -(y - domy) / domh * 2 + 1;
|
|
66
76
|
};
|
|
67
77
|
/** @internal */
|
|
68
|
-
|
|
78
|
+
lateUpdate() {
|
|
69
79
|
// continuously update distance in case camera or object moves
|
|
70
80
|
this.updateDistance();
|
|
71
81
|
const x = this.useFullPage ? this._ndc_x : this.context.input.mousePositionRC.x;
|
|
@@ -77,15 +87,34 @@ export class CursorFollow extends Behaviour {
|
|
|
77
87
|
const rayDirection = getTempVector(x, y, 1).unproject(camera);
|
|
78
88
|
rayDirection.sub(cameraPosition).normalize();
|
|
79
89
|
// position object at initial distance along the ray
|
|
80
|
-
const newPosition = rayDirection.multiplyScalar(this._distance).add(cameraPosition);
|
|
90
|
+
const newPosition = getTempVector(rayDirection).multiplyScalar(this._distance).add(cameraPosition);
|
|
91
|
+
let _position = newPosition;
|
|
81
92
|
if (this.damping > 0) {
|
|
82
93
|
const pos = this.gameObject.worldPosition;
|
|
83
94
|
pos.lerp(newPosition, this.context.time.deltaTime / this.damping);
|
|
84
95
|
this.gameObject.worldPosition = pos;
|
|
96
|
+
_position = pos;
|
|
85
97
|
}
|
|
86
98
|
else {
|
|
87
99
|
this.gameObject.worldPosition = newPosition;
|
|
88
100
|
}
|
|
101
|
+
if (this.snapToSurface) {
|
|
102
|
+
ray.origin = _position;
|
|
103
|
+
ray.direction = rayDirection.multiplyScalar(-1);
|
|
104
|
+
const hits = this.context.physics.raycastFromRay(ray);
|
|
105
|
+
if (hits?.length) {
|
|
106
|
+
const hit = hits[0];
|
|
107
|
+
if (this.damping > 0) {
|
|
108
|
+
this.gameObject.worldPosition = _position.lerp(hit.point, this.context.time.deltaTime / this.damping);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
this.gameObject.worldPosition = hit.point;
|
|
112
|
+
}
|
|
113
|
+
if (debug) {
|
|
114
|
+
Gizmos.DrawLine(hit.point, hit.normal.add(hit.point), 0x00FF00);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
89
118
|
}
|
|
90
119
|
}
|
|
91
120
|
__decorate([
|
|
@@ -97,4 +126,8 @@ __decorate([
|
|
|
97
126
|
__decorate([
|
|
98
127
|
serializable()
|
|
99
128
|
], CursorFollow.prototype, "keepDistance", void 0);
|
|
129
|
+
__decorate([
|
|
130
|
+
serializable()
|
|
131
|
+
], CursorFollow.prototype, "snapToSurface", void 0);
|
|
132
|
+
const ray = new Ray();
|
|
100
133
|
//# sourceMappingURL=CursorFollow.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CursorFollow.js","sourceRoot":"","sources":["../../../src/engine-components/web/CursorFollow.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gDAAgD,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"CursorFollow.js","sourceRoot":"","sources":["../../../src/engine-components/web/CursorFollow.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@needle-tools/engine",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.11.0-next.358bed1",
|
|
4
4
|
"description": "Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.",
|
|
5
5
|
"main": "dist/needle-engine.min.js",
|
|
6
6
|
"exports": {
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
// https://regex101.com/r/SVhzzD/1
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
const needleEngineRegex = /<needle-engine.*?src=["'](?<src>[\w\d]+?)["']>/gm;
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {string} html
|
|
10
|
+
* @returns {string[]} urls
|
|
11
|
+
*/
|
|
12
|
+
export function tryParseNeedleEngineSrcAttributeFromHtml(html) {
|
|
13
|
+
const needleEngineMatches = html.matchAll(needleEngineRegex);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @type {string[]}
|
|
17
|
+
*/
|
|
18
|
+
const results = [];
|
|
19
|
+
|
|
20
|
+
if (needleEngineMatches) {
|
|
21
|
+
while (true) {
|
|
22
|
+
const match = needleEngineMatches.next();
|
|
23
|
+
if (match.done) break;
|
|
24
|
+
/** @type {undefined | null | string} */
|
|
25
|
+
const value = match.value?.groups?.src;
|
|
26
|
+
if (value) {
|
|
27
|
+
if (value.startsWith("[")) {
|
|
28
|
+
// we have an array assigned
|
|
29
|
+
const arr = JSON.parse(value);
|
|
30
|
+
for (const item of arr) {
|
|
31
|
+
results.push(item);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
results.push(value);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return results;
|
|
41
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @type {() => import("vite").Plugin}
|
|
7
|
+
*/
|
|
8
|
+
export function viteFixWorkerImport() {
|
|
9
|
+
return {
|
|
10
|
+
name: 'vite-rewriteWorkerImport',
|
|
11
|
+
config: function (config, env) {
|
|
12
|
+
if (!config.build) {
|
|
13
|
+
config.build = {};
|
|
14
|
+
}
|
|
15
|
+
if (!config.build.rollupOptions) {
|
|
16
|
+
config.build.rollupOptions = {};
|
|
17
|
+
}
|
|
18
|
+
if (!config.build.rollupOptions.plugins) {
|
|
19
|
+
config.build.rollupOptions.plugins = [];
|
|
20
|
+
}
|
|
21
|
+
if (!Array.isArray(config.build.rollupOptions.plugins)) {
|
|
22
|
+
const value = config.build.rollupOptions.plugins;
|
|
23
|
+
config.build.rollupOptions.plugins = [];
|
|
24
|
+
config.build.rollupOptions.plugins.push(value);
|
|
25
|
+
}
|
|
26
|
+
config.build.rollupOptions.plugins.push(rollupFixWorkerImport({ logFail: false }));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
// https://regex101.com/r/hr01H4/1
|
|
34
|
+
const regex = /new\s+Worker\s*\(\s*new\s+URL\s*\(\s*(?:\/\*.*?\*\/\s*)?\"(?<url>[^"]+)\"\s*,\s*(?<base>import\.meta\.url|self\.location)[^)]*\)/gm;
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @type {(opts?: {logFail:boolean}) => import("vite").Plugin}
|
|
40
|
+
*/
|
|
41
|
+
export function rollupFixWorkerImport(opts = { logFail: true }) {
|
|
42
|
+
return {
|
|
43
|
+
name: 'rewriteWorkerImport',
|
|
44
|
+
renderChunk: {
|
|
45
|
+
order: 'post',
|
|
46
|
+
async handler(code, chunk, outputOptions) {
|
|
47
|
+
let regexMatchedWorkerCode = false;
|
|
48
|
+
const newWorkerStartIndex = code.indexOf("new Worker");
|
|
49
|
+
if (newWorkerStartIndex >= 0) {
|
|
50
|
+
const res = code.replace(regex, (match, url, _base) => {
|
|
51
|
+
regexMatchedWorkerCode = true;
|
|
52
|
+
// console.log("WORKER?", url)
|
|
53
|
+
if (url?.startsWith("/")) {
|
|
54
|
+
console.log(`[rollup] Rewrite worker import in ${chunk.fileName}`);
|
|
55
|
+
// Make url file-relative
|
|
56
|
+
const newUrl = url.replace(/^\//, "");
|
|
57
|
+
// For CORS issues we need to use importScripts: https://linear.app/needle/issue/NE-6572#comment-ea5dc65e
|
|
58
|
+
const output = `/* new-worker */ new Worker(URL.createObjectURL(new Blob(["import '" + \`\${new URL('./${newUrl}', import.meta.url).toString()}\` + "';"], { type: 'text/javascript' }))`;
|
|
59
|
+
console.log("[rollup] Did rewrite worker output to:", output);
|
|
60
|
+
return output;
|
|
61
|
+
// return `new Worker(new URL("./${newUrl}", import.meta.url)`;
|
|
62
|
+
}
|
|
63
|
+
return match;
|
|
64
|
+
});
|
|
65
|
+
if (!regexMatchedWorkerCode) {
|
|
66
|
+
|
|
67
|
+
const fixedCode = fixWorkerSelfLocation(chunk.fileName, code);
|
|
68
|
+
if (fixedCode !== code) {
|
|
69
|
+
return fixedCode;
|
|
70
|
+
}
|
|
71
|
+
if (opts?.logFail !== false) {
|
|
72
|
+
const str = `[...]${code.substring(newWorkerStartIndex, newWorkerStartIndex + 200)}[...]`
|
|
73
|
+
console.warn(`\n[rollup] Worker import in ${chunk.fileName} was not rewritten: ${str}`);
|
|
74
|
+
}
|
|
75
|
+
else console.log(`[rollup] Worker import in ${chunk.fileName}: ${str}`);
|
|
76
|
+
}
|
|
77
|
+
return res;
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Fix worker self.location to import.meta.url
|
|
87
|
+
* @param {string} filename
|
|
88
|
+
* @param {string} code
|
|
89
|
+
*/
|
|
90
|
+
function fixWorkerSelfLocation(filename, code) {
|
|
91
|
+
let lastIndex = 0;
|
|
92
|
+
while (true) {
|
|
93
|
+
const startIndex = code.indexOf("new Worker", lastIndex);
|
|
94
|
+
if (startIndex < 0) break;
|
|
95
|
+
let index = startIndex + 1;
|
|
96
|
+
let endIndex = -1;
|
|
97
|
+
let openingBraceCount = 0;
|
|
98
|
+
let foundAnyOpening = false;
|
|
99
|
+
while (true) {
|
|
100
|
+
const char = code[index];
|
|
101
|
+
if (char === "(") {
|
|
102
|
+
openingBraceCount++;
|
|
103
|
+
foundAnyOpening = true;
|
|
104
|
+
}
|
|
105
|
+
if (char === ")") openingBraceCount--;
|
|
106
|
+
if (openingBraceCount === 0 && foundAnyOpening) {
|
|
107
|
+
endIndex = index;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
// console.log(openingBraceCount, char, index, code.length);
|
|
111
|
+
index++;
|
|
112
|
+
if (index >= code.length) break;
|
|
113
|
+
}
|
|
114
|
+
if (endIndex > startIndex) {
|
|
115
|
+
const workerCode = code.substring(startIndex, endIndex + 1);
|
|
116
|
+
if (workerCode.indexOf("self.location") >= 0) {
|
|
117
|
+
const fixedCode = workerCode.replace("self.location", "import.meta.url");
|
|
118
|
+
code = code.substring(0, startIndex) + fixedCode + code.substring(endIndex + 1);
|
|
119
|
+
lastIndex = startIndex + fixedCode.length;
|
|
120
|
+
console.log(`[rollup] Rewrite worker 'self.location' to 'import.meta.url' in ${filename}`);
|
|
121
|
+
} else {
|
|
122
|
+
lastIndex = endIndex;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
lastIndex = startIndex + "new Worker".length;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return code;
|
|
130
|
+
}
|
package/plugins/vite/asap.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync, writeFileSync } from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { tryParseNeedleEngineSrcAttributeFromHtml } from '../common/needle-engine.js';
|
|
3
4
|
import { preloadScriptPaths } from './dependencies.js';
|
|
4
5
|
import { makeFilesLocalIsEnabled } from './local-files.js';
|
|
5
6
|
|
|
@@ -159,10 +160,6 @@ function generateScriptPreloadLinks(_config, tags) {
|
|
|
159
160
|
// @ts-ignore
|
|
160
161
|
const codegenRegex = /\"(?<gltf>.+(.glb|.gltf)(\?.*)?)\"/gm;
|
|
161
162
|
|
|
162
|
-
// https://regex101.com/r/SVhzzD/1
|
|
163
|
-
// @ts-ignore
|
|
164
|
-
const needleEngineRegex = /<needle-engine.*?src=["'](?<src>[\w\d]+?)["']>/gm;
|
|
165
|
-
|
|
166
163
|
/**
|
|
167
164
|
* @param {import('../types').needleConfig} config
|
|
168
165
|
* @param {string} html
|
|
@@ -171,25 +168,10 @@ const needleEngineRegex = /<needle-engine.*?src=["'](?<src>[\w\d]+?)["']>/gm;
|
|
|
171
168
|
function generateGltfPreloadLinks(config, html, tags) {
|
|
172
169
|
|
|
173
170
|
// TODO: try to get the <needle-engine src> element src attribute and preload that
|
|
174
|
-
const needleEngineMatches = html
|
|
175
|
-
if (needleEngineMatches) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (match.done) break;
|
|
179
|
-
/** @type {undefined | null | string} */
|
|
180
|
-
const value = match.value?.groups?.src;
|
|
181
|
-
if (value) {
|
|
182
|
-
if (value.startsWith("[")) {
|
|
183
|
-
// we have an array assigned
|
|
184
|
-
const arr = JSON.parse(value);
|
|
185
|
-
for (const item of arr) {
|
|
186
|
-
insertPreloadLink(tags, item, "model/gltf+json");
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
else {
|
|
190
|
-
insertPreloadLink(tags, value, "model/gltf+json");
|
|
191
|
-
}
|
|
192
|
-
}
|
|
171
|
+
const needleEngineMatches = tryParseNeedleEngineSrcAttributeFromHtml(html);
|
|
172
|
+
if (needleEngineMatches?.length) {
|
|
173
|
+
for (const item of needleEngineMatches) {
|
|
174
|
+
insertPreloadLink(tags, item, "model/gltf+json");
|
|
193
175
|
}
|
|
194
176
|
}
|
|
195
177
|
|
|
@@ -8,23 +8,26 @@ export const preloadScriptPaths = [];
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @param {import('../types').userSettings} userSettings
|
|
11
|
+
* @returns {import('vite').Plugin[]}
|
|
11
12
|
*/
|
|
12
13
|
export const needleDependencies = (command, config, userSettings) => {
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* @type {import('vite').Plugin}
|
|
16
17
|
*/
|
|
17
|
-
return
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
return [
|
|
19
|
+
{
|
|
20
|
+
name: 'needle:dependencies',
|
|
21
|
+
enforce: 'pre',
|
|
22
|
+
/**
|
|
23
|
+
* @param {import('vite').UserConfig} config
|
|
24
|
+
*/
|
|
25
|
+
config: (config, env) => {
|
|
26
|
+
handleOptimizeDeps(config);
|
|
27
|
+
handleManualChunks(config);
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
]
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
const excludeDependencies = [
|
|
@@ -167,6 +170,13 @@ function handleManualChunks(config) {
|
|
|
167
170
|
return name;
|
|
168
171
|
}
|
|
169
172
|
}
|
|
173
|
+
// else if(chunk.name === 'index') {
|
|
174
|
+
// console.log(chunk);
|
|
175
|
+
// debugger
|
|
176
|
+
// // this is the main chunk
|
|
177
|
+
// // we don't want to add a hash here to be able to easily import the main script
|
|
178
|
+
// return `index.js`;
|
|
179
|
+
// }
|
|
170
180
|
return `assets/[name].[hash].js`;
|
|
171
181
|
}
|
|
172
182
|
|
package/plugins/vite/index.js
CHANGED
|
@@ -68,6 +68,8 @@ import { needleNPM } from "./npm.js";
|
|
|
68
68
|
import { needleTransformCode } from "./transform.js";
|
|
69
69
|
import { needleMaterialXLoader } from "./materialx.js";
|
|
70
70
|
import { needleLogger } from "./logger.js";
|
|
71
|
+
import { needleApp } from "./needle-app.js";
|
|
72
|
+
import { viteFixWorkerImport } from "../common/worker.js";
|
|
71
73
|
export { needleServer } from "./server.js";
|
|
72
74
|
|
|
73
75
|
|
|
@@ -137,6 +139,8 @@ export const needlePlugins = async (command, config = undefined, userSettings =
|
|
|
137
139
|
needleServer(command, config, userSettings),
|
|
138
140
|
needleNPM(command, config, userSettings),
|
|
139
141
|
needleMaterialXLoader(command, config, userSettings),
|
|
142
|
+
needleApp(command, config, userSettings),
|
|
143
|
+
viteFixWorkerImport()
|
|
140
144
|
];
|
|
141
145
|
|
|
142
146
|
const asap = await needleAsap(command, config, userSettings);
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { writeFile } from 'fs';
|
|
2
|
+
import { tryParseNeedleEngineSrcAttributeFromHtml } from '../common/needle-engine.js';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {'serve' | 'build'} command
|
|
8
|
+
* @param {{} | undefined | null} config
|
|
9
|
+
* @param {import('../types').userSettings} userSettings
|
|
10
|
+
* @returns {import('vite').Plugin[] | null}
|
|
11
|
+
*/
|
|
12
|
+
export const needleApp = (command, config, userSettings) => {
|
|
13
|
+
|
|
14
|
+
if (command !== "build") {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** @type {Array<import("rollup").OutputChunk>} */
|
|
19
|
+
const entryFiles = new Array();
|
|
20
|
+
|
|
21
|
+
let outputDir = "dist";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @type {import('vite').Plugin}
|
|
25
|
+
*/
|
|
26
|
+
return [
|
|
27
|
+
{
|
|
28
|
+
name: 'needle:app',
|
|
29
|
+
enforce: "post",
|
|
30
|
+
configResolved(config) {
|
|
31
|
+
outputDir = config.build.outDir || "dist";
|
|
32
|
+
},
|
|
33
|
+
transformIndexHtml: {
|
|
34
|
+
handler: async function (html, context) {
|
|
35
|
+
const name = context.filename;
|
|
36
|
+
if (name.includes("index.html")) {
|
|
37
|
+
if (context.chunk?.isEntry) {
|
|
38
|
+
try {
|
|
39
|
+
entryFiles.push(context.chunk);
|
|
40
|
+
const path = context.chunk.fileName;
|
|
41
|
+
// console.log("[needle-dependencies] entry chunk imports", {
|
|
42
|
+
// name: context.chunk.fileName,
|
|
43
|
+
// imports: context.chunk.imports,
|
|
44
|
+
// dynamicImports: context.chunk.dynamicImports,
|
|
45
|
+
// refs: context.chunk.referencedFiles,
|
|
46
|
+
// });
|
|
47
|
+
|
|
48
|
+
const referencedGlbs = tryParseNeedleEngineSrcAttributeFromHtml(html);
|
|
49
|
+
const webComponent = generateNeedleEmbedWebComponent(path, referencedGlbs);
|
|
50
|
+
await writeFile(`${outputDir}/needle-app.js`, webComponent, (err) => {
|
|
51
|
+
if (err) {
|
|
52
|
+
console.error("[needle-app] could not create needle-app.js", err);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
console.log("[needle-app] created needle-app.js");
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
console.warn("WARN: could not create needle-app.js\n", e);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @param {string} filepath
|
|
74
|
+
* @param {string[]} needleEngineSrcPaths
|
|
75
|
+
* @returns {string}
|
|
76
|
+
*/
|
|
77
|
+
function generateNeedleEmbedWebComponent(filepath, needleEngineSrcPaths) {
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
// filepath is e.g. `assets/index-XXXXXXXX.js`
|
|
81
|
+
// we want to make sure the path is correct relative to where the component will be used
|
|
82
|
+
// this script will be emitted in the output directory root (e.g. needle-embed.js)
|
|
83
|
+
|
|
84
|
+
const src = needleEngineSrcPaths?.length ? `${needleEngineSrcPaths[0]}` : "";
|
|
85
|
+
|
|
86
|
+
const componentName = 'needle-app';
|
|
87
|
+
const className = 'NeedleApp';
|
|
88
|
+
|
|
89
|
+
return `
|
|
90
|
+
class ${className} extends HTMLElement {
|
|
91
|
+
constructor() {
|
|
92
|
+
super();
|
|
93
|
+
this.attachShadow({ mode: 'open' });
|
|
94
|
+
const template = document.createElement('template');
|
|
95
|
+
template.innerHTML = \`
|
|
96
|
+
<style>
|
|
97
|
+
:host {
|
|
98
|
+
position: relative;
|
|
99
|
+
display: block;
|
|
100
|
+
width: 100%;
|
|
101
|
+
height: 100%;
|
|
102
|
+
margin: 0;
|
|
103
|
+
padding: 0;
|
|
104
|
+
}
|
|
105
|
+
needle-engine {
|
|
106
|
+
position: absolute;
|
|
107
|
+
top: 0;
|
|
108
|
+
left: 0;
|
|
109
|
+
width: 100%;
|
|
110
|
+
height: 100%;
|
|
111
|
+
}
|
|
112
|
+
</style>
|
|
113
|
+
\`;
|
|
114
|
+
this.shadowRoot.appendChild(template.content.cloneNode(true));
|
|
115
|
+
|
|
116
|
+
const script = document.createElement('script');
|
|
117
|
+
script.type = 'module';
|
|
118
|
+
const url = new URL('.', import.meta.url);
|
|
119
|
+
let basePath = this.getAttribute('base-path') || \`\${url.protocol}//\${url.host}\${url.pathname}\`;
|
|
120
|
+
while(basePath.endsWith('/')) {
|
|
121
|
+
basePath = basePath.slice(0, -1);
|
|
122
|
+
}
|
|
123
|
+
script.src = this.getAttribute('script-src') || \`\${basePath}/${filepath}\`;
|
|
124
|
+
this.shadowRoot.appendChild(script);
|
|
125
|
+
|
|
126
|
+
const needleEngine = document.createElement('needle-engine');
|
|
127
|
+
needleEngine.src = this.getAttribute('src') || ${src?.length ? `\${basePath}/${needleEngineSrcPaths}` : undefined};
|
|
128
|
+
this.shadowRoot.appendChild(needleEngine);
|
|
129
|
+
|
|
130
|
+
console.debug(basePath, script.src, needleEngine.getAttribute("src"));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
onConnectedCallback() {
|
|
134
|
+
console.debug('NeedleEmbed connected to the DOM');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
disconnectedCallback() {
|
|
138
|
+
console.debug('NeedleEmbed disconnected from the DOM');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
if (!customElements.get('${componentName}')) {
|
|
144
|
+
console.debug("Defining ${componentName}");
|
|
145
|
+
customElements.define('${componentName}', ${className});
|
|
146
|
+
}
|
|
147
|
+
`
|
|
148
|
+
}
|
|
@@ -90,6 +90,7 @@ import { SkinnedMeshRenderer } from "../../engine-components/Renderer.js";
|
|
|
90
90
|
import { Rigidbody } from "../../engine-components/RigidBody.js";
|
|
91
91
|
import { SceneSwitcher } from "../../engine-components/SceneSwitcher.js";
|
|
92
92
|
import { ScreenCapture } from "../../engine-components/ScreenCapture.js";
|
|
93
|
+
import { SeeThrough } from "../../engine-components/SeeThrough.js";
|
|
93
94
|
import { ShadowCatcher } from "../../engine-components/ShadowCatcher.js";
|
|
94
95
|
import { RemoteSkybox } from "../../engine-components/Skybox.js";
|
|
95
96
|
import { SmoothFollow } from "../../engine-components/SmoothFollow.js";
|
|
@@ -249,6 +250,7 @@ TypeStore.add("SkinnedMeshRenderer", SkinnedMeshRenderer);
|
|
|
249
250
|
TypeStore.add("Rigidbody", Rigidbody);
|
|
250
251
|
TypeStore.add("SceneSwitcher", SceneSwitcher);
|
|
251
252
|
TypeStore.add("ScreenCapture", ScreenCapture);
|
|
253
|
+
TypeStore.add("SeeThrough", SeeThrough);
|
|
252
254
|
TypeStore.add("ShadowCatcher", ShadowCatcher);
|
|
253
255
|
TypeStore.add("RemoteSkybox", RemoteSkybox);
|
|
254
256
|
TypeStore.add("SmoothFollow", SmoothFollow);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AxesHelper, Box3, BoxGeometry, BufferAttribute, BufferGeometry, Color, type ColorRepresentation, CylinderGeometry, EdgesGeometry, Line, LineBasicMaterial, LineSegments, Material,Matrix4, Mesh, MeshBasicMaterial, Object3D, Quaternion, SphereGeometry, Vector3 } from 'three';
|
|
1
|
+
import { AxesHelper, Box3, BoxGeometry, BufferAttribute, BufferGeometry, Color, type ColorRepresentation, CylinderGeometry, EdgesGeometry, Line, LineBasicMaterial, LineSegments, Material, Matrix4, Mesh, MeshBasicMaterial, Object3D, Quaternion, SphereGeometry, Vector3 } from 'three';
|
|
2
2
|
import ThreeMeshUI, { Inline, Text } from "three-mesh-ui"
|
|
3
3
|
import { type Options } from 'three-mesh-ui/build/types/core/elements/MeshUIBaseElement.js';
|
|
4
4
|
|
|
@@ -289,11 +289,11 @@ export class Gizmos {
|
|
|
289
289
|
const mesh = Internal.getMesh(options.duration ?? 0);
|
|
290
290
|
if ("mesh" in options) {
|
|
291
291
|
mesh.geometry = options.mesh.geometry;
|
|
292
|
-
mesh.
|
|
292
|
+
mesh.matrixWorld.copy(options.mesh.matrixWorld);
|
|
293
293
|
}
|
|
294
294
|
else {
|
|
295
295
|
mesh.geometry = options.geometry;
|
|
296
|
-
mesh.
|
|
296
|
+
mesh.matrixWorld.copy(options.matrix);
|
|
297
297
|
}
|
|
298
298
|
mesh.matrixAutoUpdate = false;
|
|
299
299
|
mesh.matrixWorldAutoUpdate = false;
|