@wonderlandengine/ar-provider-zappar 1.0.0
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/README.md +95 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/src/face-tracking-mode-zappar.d.ts +40 -0
- package/dist/src/face-tracking-mode-zappar.js +261 -0
- package/dist/src/image-tracking-mode-zappar.d.ts +35 -0
- package/dist/src/image-tracking-mode-zappar.js +173 -0
- package/dist/src/slam-anchor-zappar.d.ts +16 -0
- package/dist/src/slam-anchor-zappar.js +39 -0
- package/dist/src/world-tracking-mode-zappar.d.ts +17 -0
- package/dist/src/world-tracking-mode-zappar.js +46 -0
- package/dist/src/zappar-module.d.ts +5 -0
- package/dist/src/zappar-module.js +43 -0
- package/dist/src/zappar-provider.d.ts +115 -0
- package/dist/src/zappar-provider.js +827 -0
- package/package.json +47 -0
- package/scripts/postinstall.mjs +184 -0
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wonderlandengine/ar-provider-zappar",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Wonderland Engine AR tracking provider based on Zappar",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"wonderlandengine": {},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"build:watch": "tsc --watch",
|
|
11
|
+
"postinstall": "node ./scripts/postinstall.mjs",
|
|
12
|
+
"prepublishOnly": "npm run build",
|
|
13
|
+
"prettier": "prettier --config ./.prettierrc.json --write ./src ./examples/**/js ./examples/common-components"
|
|
14
|
+
},
|
|
15
|
+
"prettier": "@wonderlandengine/prettier-config",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/WonderlandEngine/wonderland-ar-tracking.git"
|
|
19
|
+
},
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/WonderlandEngine/wonderland-ar-tracking/issues"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://github.com/WonderlandEngine/wonderland-ar-tracking#readme",
|
|
24
|
+
"keywords": [
|
|
25
|
+
"wonderland-engine",
|
|
26
|
+
"ar",
|
|
27
|
+
"zappar"
|
|
28
|
+
],
|
|
29
|
+
"files": [
|
|
30
|
+
"dist/**/*.js",
|
|
31
|
+
"dist/**/*.d.ts",
|
|
32
|
+
"scripts/**/*.mjs"
|
|
33
|
+
],
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"prettier": "^2.8.4",
|
|
36
|
+
"typescript": "^4.9.5"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"@wonderlandengine/api": "^1.0.0",
|
|
40
|
+
"@wonderlandengine/ar-tracking": "^1.0.0",
|
|
41
|
+
"@wonderlandengine/components": "^1.0.0"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@zappar/zappar": "^2.2.7",
|
|
45
|
+
"gl-matrix": "^3.4.3"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import {createRequire} from 'node:module';
|
|
4
|
+
import {fileURLToPath} from 'node:url';
|
|
5
|
+
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
|
|
10
|
+
const logPrefix = '[ar-provider-zappar:postinstall]';
|
|
11
|
+
|
|
12
|
+
function log(...args) {
|
|
13
|
+
// Keep output minimal but actionable.
|
|
14
|
+
console.log(logPrefix, ...args);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function warn(...args) {
|
|
18
|
+
console.warn(logPrefix, ...args);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function copyOrThrow(src, dest) {
|
|
22
|
+
fs.mkdirSync(path.dirname(dest), {recursive: true});
|
|
23
|
+
fs.copyFileSync(src, dest);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function safeLinkOrCopy(src, dest) {
|
|
27
|
+
fs.mkdirSync(path.dirname(dest), {recursive: true});
|
|
28
|
+
try {
|
|
29
|
+
if (fs.existsSync(dest)) fs.unlinkSync(dest);
|
|
30
|
+
fs.linkSync(src, dest);
|
|
31
|
+
} catch {
|
|
32
|
+
try {
|
|
33
|
+
if (fs.existsSync(dest)) fs.unlinkSync(dest);
|
|
34
|
+
} catch {
|
|
35
|
+
// ignore
|
|
36
|
+
}
|
|
37
|
+
fs.copyFileSync(src, dest);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function listFiles(dir) {
|
|
42
|
+
try {
|
|
43
|
+
return fs.readdirSync(dir, {withFileTypes: true});
|
|
44
|
+
} catch {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function findFirstFile(dir, predicate) {
|
|
50
|
+
for (const entry of listFiles(dir)) {
|
|
51
|
+
if (!entry.isFile()) continue;
|
|
52
|
+
if (predicate(entry.name)) return path.join(dir, entry.name);
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function findWasmFromWorker(workerPath, umdDir) {
|
|
58
|
+
try {
|
|
59
|
+
const src = fs.readFileSync(workerPath, 'utf8');
|
|
60
|
+
const match = src.match(/["']([^"']+\.wasm)["']/);
|
|
61
|
+
if (!match) return null;
|
|
62
|
+
|
|
63
|
+
const candidate = path.resolve(umdDir, match[1]);
|
|
64
|
+
const relative = path.relative(umdDir, candidate);
|
|
65
|
+
|
|
66
|
+
// Ensure we never resolve outside the umd directory.
|
|
67
|
+
if (relative.startsWith('..') || path.isAbsolute(relative)) return null;
|
|
68
|
+
|
|
69
|
+
return fs.existsSync(candidate) ? candidate : null;
|
|
70
|
+
} catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function resolveZapparRoot() {
|
|
76
|
+
const providerRoot = path.resolve(__dirname, '..');
|
|
77
|
+
const zapparPackageJson = require.resolve('@zappar/zappar/package.json', {
|
|
78
|
+
paths: [providerRoot],
|
|
79
|
+
});
|
|
80
|
+
return path.dirname(zapparPackageJson);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function resolveZapparCvRoot() {
|
|
84
|
+
const providerRoot = path.resolve(__dirname, '..');
|
|
85
|
+
const zapparCvPackageJson = require.resolve('@zappar/zappar-cv/package.json', {
|
|
86
|
+
paths: [providerRoot],
|
|
87
|
+
});
|
|
88
|
+
return path.dirname(zapparCvPackageJson);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function resolveProjectRoot() {
|
|
92
|
+
// INIT_CWD is set by npm/yarn/pnpm for lifecycle scripts and points at the
|
|
93
|
+
// consumer project that triggered the install.
|
|
94
|
+
const initCwd = process.env.INIT_CWD;
|
|
95
|
+
if (initCwd && initCwd.trim()) return path.resolve(initCwd);
|
|
96
|
+
|
|
97
|
+
// Fallback (best effort): current working directory.
|
|
98
|
+
return process.cwd();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function main() {
|
|
102
|
+
const zapparRoot = resolveZapparRoot();
|
|
103
|
+
const umdDir = path.join(zapparRoot, 'umd');
|
|
104
|
+
|
|
105
|
+
const zapparCvRoot = resolveZapparCvRoot();
|
|
106
|
+
const zapparCvLibDir = path.join(zapparCvRoot, 'lib');
|
|
107
|
+
|
|
108
|
+
const projectRoot = resolveProjectRoot();
|
|
109
|
+
const outDir = path.resolve(projectRoot, 'static', 'zappar-cv');
|
|
110
|
+
|
|
111
|
+
const workerSource =
|
|
112
|
+
findFirstFile(umdDir, (name) => name === 'zappar.worker.js') ??
|
|
113
|
+
findFirstFile(umdDir, (name) => name === 'zappar-cv.worker.js') ??
|
|
114
|
+
findFirstFile(zapparRoot, (name) => name === 'zappar.worker.js') ??
|
|
115
|
+
findFirstFile(zapparRoot, (name) => name === 'zappar-cv.worker.js') ??
|
|
116
|
+
null;
|
|
117
|
+
|
|
118
|
+
if (!workerSource) {
|
|
119
|
+
warn('Could not locate Zappar worker under', umdDir);
|
|
120
|
+
warn('Zappar root:', zapparRoot);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const wasmCandidates = listFiles(umdDir)
|
|
125
|
+
.filter((e) => e.isFile() && e.name.endsWith('.wasm'))
|
|
126
|
+
.map((e) => path.join(umdDir, e.name));
|
|
127
|
+
|
|
128
|
+
let wasmSource = wasmCandidates.length === 1 ? wasmCandidates[0] : null;
|
|
129
|
+
wasmSource = wasmSource ?? findWasmFromWorker(workerSource, umdDir);
|
|
130
|
+
wasmSource = wasmSource ?? (wasmCandidates.length > 0 ? wasmCandidates[0] : null);
|
|
131
|
+
|
|
132
|
+
if (!wasmSource) {
|
|
133
|
+
warn('Could not locate Zappar wasm under', umdDir);
|
|
134
|
+
warn('Worker found at:', workerSource);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
fs.mkdirSync(outDir, {recursive: true});
|
|
139
|
+
|
|
140
|
+
const workerDest = path.join(outDir, 'zappar-cv.worker.js');
|
|
141
|
+
copyOrThrow(workerSource, workerDest);
|
|
142
|
+
|
|
143
|
+
const wasmBasename = path.basename(wasmSource);
|
|
144
|
+
const wasmDest = path.join(outDir, wasmBasename);
|
|
145
|
+
copyOrThrow(wasmSource, wasmDest);
|
|
146
|
+
|
|
147
|
+
// Create a stable alias that the Wonderland provider code points at.
|
|
148
|
+
safeLinkOrCopy(wasmDest, path.join(outDir, 'zappar-cv.wasm'));
|
|
149
|
+
|
|
150
|
+
// Optional: copy any Zappar binary blobs shipped alongside the wasm.
|
|
151
|
+
// (Harmless if unused; avoids runtime 404s if Zappar expects them.)
|
|
152
|
+
for (const entry of listFiles(umdDir)) {
|
|
153
|
+
if (!entry.isFile()) continue;
|
|
154
|
+
if (!entry.name.endsWith('.zbin')) continue;
|
|
155
|
+
copyOrThrow(path.join(umdDir, entry.name), path.join(outDir, entry.name));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Required for face tracking defaults (FaceTracker.loadDefaultModel / FaceMesh.loadDefault*).
|
|
159
|
+
// These ship in @zappar/zappar-cv/lib but are fetched at runtime unless staged.
|
|
160
|
+
const requiredFaceModelFiles = [
|
|
161
|
+
'face_tracking_model.zbin',
|
|
162
|
+
'face_mesh_face_model.zbin',
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
for (const filename of requiredFaceModelFiles) {
|
|
166
|
+
const src = path.join(zapparCvLibDir, filename);
|
|
167
|
+
const dest = path.join(outDir, filename);
|
|
168
|
+
if (!fs.existsSync(src)) {
|
|
169
|
+
warn('Could not locate required Zappar face model:', filename);
|
|
170
|
+
warn('Looked under:', zapparCvLibDir);
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
copyOrThrow(src, dest);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
log('Copied Zappar CV assets into', outDir);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
try {
|
|
180
|
+
main();
|
|
181
|
+
} catch (e) {
|
|
182
|
+
// Postinstall should not hard-fail the whole install; consumers can still override.
|
|
183
|
+
warn('Failed to stage Zappar CV assets:', e);
|
|
184
|
+
}
|