Skip to content

Commit fa9d0cb

Browse files
authored
scaffold ARToolKit plugin with initial setup and basic functionality (#1)
* scaffold ARToolKit plugin with initial setup and basic functionality * feat(worker): add detection worker stub and wire to plugin * fix(plugin): restore ArtoolkitPlugin class and integrate worker lifecycle * scaffold ARToolKit plugin with initial setup and basic functionality - missed plugin.js! * feat(worker): enhance cross-platform support for worker lifecycle and messaging * feat(plugin): enhance ImageBitmap handling and add browser smoke test * feat(plugin): enhance marker tracking configuration and sweep logic
1 parent 71751d4 commit fa9d0cb

File tree

13 files changed

+2994
-1
lines changed

13 files changed

+2994
-1
lines changed

.github/workflows/ci.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- '**'
7+
pull_request:
8+
branches:
9+
- '**'
10+
11+
jobs:
12+
test:
13+
runs-on: ubuntu-24.04
14+
steps:
15+
- uses: actions/checkout@v4
16+
- name: Setup Node.js
17+
uses: actions/setup-node@v4
18+
with:
19+
node-version-file: .nvmrc
20+
cache: npm
21+
- name: Install
22+
run: npm ci
23+
- name: Run tests
24+
run: npm test

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,6 @@ dist
137137
# Vite logs files
138138
vite.config.js.timestamp-*
139139
vite.config.ts.timestamp-*
140+
141+
# jetbrains IDEs files
142+
.idea/

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v22.21.1

README.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,24 @@
1-
# arjs-plugin-artoolkit
1+
# arjs-plugin-artoolkit
2+
```markdown
3+
# @ar-js-org/arjs-plugin-artoolkit
4+
5+
Minimal ARToolKit detection plugin scaffold for AR.js core.
6+
7+
## Usage
8+
9+
Register with the Engine plugin manager:
10+
11+
```js
12+
import { ArtoolkitPlugin } from '@ar-js-org/arjs-plugin-artoolkit';
13+
14+
engine.pluginManager.register('artoolkit', new ArtoolkitPlugin({ /* options */ }));
15+
await engine.pluginManager.enable('artoolkit');
16+
```
17+
18+
The plugin emits events on the engine event bus:
19+
- `ar:markerFound`
20+
- `ar:markerUpdated`
21+
- `ar:markerLost`
22+
23+
This repo contains a skeleton. Detection and worker/WASM integration will be implemented in follow-up work.
24+
```

dev/smoke-test-browser.html

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<!doctype html>
2+
<meta charset="utf-8" />
3+
<body>
4+
<h1>Browser smoke test (ImageBitmap transfer)</h1>
5+
6+
<p>This is a simple example to run in a browser (served via http(s)) to exercise ImageBitmap transfer:
7+
8+
1. Create an `index.html` and include a small script that:
9+
- obtains getUserMedia({ video: true })
10+
- creates a hidden canvas and draws video frames into it
11+
- uses `createImageBitmap(canvas)` to create an ImageBitmap
12+
- emits engine.update events with `{ id, imageBitmap, width, height }`
13+
- listens to `ar:markerFound`, `ar:markerUpdated`, `ar:markerLost` events
14+
15+
2. Ensure the plugin is initialized in a browser environment and registered with an engine object exposing `eventBus` with `on`/`emit`.
16+
</p>
17+
<video id="v" autoplay playsinline style="display:none"></video>
18+
<script type="module">
19+
import { ArtoolkitPlugin } from '../src/plugin.js';
20+
21+
const eventBus = {
22+
_h: new Map(),
23+
on(e,h){ if(!this._h.has(e)) this._h.set(e,[]); this._h.get(e).push(h); },
24+
off(e,h){ if(!this._h.has(e)) return; this._h.set(e, this._h.get(e).filter(x=>x!==h)); },
25+
emit(e,p){ (this._h.get(e)||[]).forEach(fn=>fn(p)); }
26+
};
27+
28+
const core = { eventBus };
29+
const plugin = new ArtoolkitPlugin({ worker: true });
30+
await plugin.init(core);
31+
await plugin.enable();
32+
33+
eventBus.on('ar:workerReady', ()=>console.log('worker ready'));
34+
eventBus.on('ar:markerFound', d => console.log('FOUND', d));
35+
eventBus.on('ar:markerUpdated', d => console.log('UPDATED', d));
36+
eventBus.on('ar:markerLost', d => console.log('LOST', d));
37+
38+
const video = document.getElementById('v');
39+
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
40+
video.srcObject = stream;
41+
42+
const canvas = document.createElement('canvas');
43+
const ctx = canvas.getContext('2d');
44+
45+
let id = 0;
46+
function tick() {
47+
if (video.videoWidth === 0) {
48+
requestAnimationFrame(tick);
49+
return;
50+
}
51+
canvas.width = video.videoWidth;
52+
canvas.height = video.videoHeight;
53+
ctx.drawImage(video, 0, 0);
54+
createImageBitmap(canvas).then((imageBitmap) => {
55+
eventBus.emit('engine:update', { id: ++id, imageBitmap, width: canvas.width, height: canvas.height });
56+
// imageBitmap will be transferred to worker; don't reuse it after emit
57+
});
58+
requestAnimationFrame(tick);
59+
}
60+
tick();
61+
</script>
62+
</body>
63+
```
64+
65+
Note: host via `npx http-server` or similar so getUserMedia works in a secure context if needed.
66+
```

dev/smoke-test.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { ArtoolkitPlugin } from '../src/plugin.js';
2+
3+
// minimal eventBus stub
4+
const eventBus = {
5+
_h: new Map(),
6+
on(e, h) { if (!this._h.has(e)) this._h.set(e, []); this._h.get(e).push(h); },
7+
off(e, h) { if (!this._h.has(e)) return; const a = this._h.get(e); this._h.set(e, a.filter(x=>x!==h)); },
8+
emit(e, p) { (this._h.get(e) || []).forEach(h => { try { h(p); } catch (err) { console.error(err); } }); }
9+
};
10+
11+
const core = { eventBus };
12+
13+
async function run() {
14+
const plugin = new ArtoolkitPlugin({ worker: true });
15+
await plugin.init(core);
16+
await plugin.enable();
17+
18+
// Listen to marker events:
19+
eventBus.on('ar:markerFound', d => console.log('FOUND', d));
20+
eventBus.on('ar:markerUpdated', d => console.log('UPDATED', d));
21+
eventBus.on('ar:markerLost', d => console.log('LOST', d));
22+
eventBus.on('ar:workerReady', () => console.log('Worker ready'));
23+
24+
// Emit engine:update frames periodically to trigger worker processing
25+
let id = 0;
26+
const iv = setInterval(() => {
27+
eventBus.emit('engine:update', { id: ++id, timestamp: Date.now() });
28+
if (id >= 10) {
29+
clearInterval(iv);
30+
// wait a bit and then stop plugin
31+
setTimeout(async () => {
32+
await plugin.disable();
33+
console.log('plugin disabled');
34+
}, 1000);
35+
}
36+
}, 100);
37+
}
38+
39+
run().catch(console.error);

0 commit comments

Comments
 (0)