{"_id":"@ar-js-org/arjs-plugin-artoolkit","name":"@ar-js-org/arjs-plugin-artoolkit","dist-tags":{"latest":"0.1.3"},"versions":{"0.1.3":{"name":"@ar-js-org/arjs-plugin-artoolkit","version":"0.1.3","description":"ARToolKit detection plugin for AR.js core (ECS plugin)","type":"module","main":"dist/arjs-plugin-artoolkit.es.js","module":"dist/arjs-plugin-artoolkit.es.js","types":"types/index.d.ts","exports":{".":{"import":"./dist/arjs-plugin-artoolkit.es.js","require":"./dist/arjs-plugin-artoolkit.es.js"}},"scripts":{"build":"vite build","build:types":"tsc --emitDeclarationOnly","prepublishOnly":"npm run build && npm run build:types","coverage":"vitest run --coverage","format":"prettier --write .","format:check":"prettier --check .","test":"vitest","lint":"eslint . --ext .js","prepare":"husky","smoke:node":"node dev/smoke-node.js","smoke:browser":"npx http-server -p 8080"},"keywords":["arjs","artoolkit","artoolkit5","augmented-reality","esmodule","marker","marker-detection","plugin","tracking","wasm","webworker","worker"],"author":{"name":"Walter Perdan @kalwalt https://github.com/kalwalt"},"license":"MIT","devDependencies":{"@vitest/coverage-v8":"^4.0.14","eslint":"^9.39.1","husky":"^9.1.7","jsdom":"^27.2.0","prettier":"^3.6.2","typescript":"^5.9.3","vite":"^7.2.4","vitest":"^4.0.14"},"dependencies":{"@ar-js-org/artoolkit5-js":"^0.3.2"},"_id":"@ar-js-org/arjs-plugin-artoolkit@0.1.3","gitHead":"2700ff115e9258fcb7c223fe1383a54ed64b08a5","_nodeVersion":"22.21.1","_npmVersion":"10.9.4","dist":{"integrity":"sha512-ha0YvP+CpS4TbndgUjz985KoiKy5r4v2/diW1tUp6WeIp6BHwFR+etlp92CcfLOA5Kwz4PFyyorJg9yIDABBSA==","shasum":"1a4ce90206d2a870248cb2479e70e917441edd7d","tarball":"https://registry.npmjs.org/@ar-js-org/arjs-plugin-artoolkit/-/arjs-plugin-artoolkit-0.1.3.tgz","fileCount":15,"unpackedSize":939857,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIGDtbPypKlTv7dieK+AJPF9Sf8xf+nBCktUiGK4wVAmrAiA7hE4YhQBM9/Y4sf/Cs79RUU8lm7o/TCypjYTlXf8z+A=="}]},"_npmUser":{"name":"kalwalt","email":"info@kalwaltart.it"},"directories":{},"maintainers":[{"name":"kalwalt","email":"info@kalwaltart.it"},{"name":"nickw1","email":"nickw4426@gmail.com"},{"name":"nicolocarpignoli","email":"nicolocarpignoli@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/arjs-plugin-artoolkit_0.1.3_1765403314310_0.7880359943460515"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-10T21:48:34.237Z","0.1.3":"2025-12-10T21:48:34.483Z","modified":"2025-12-10T21:48:34.816Z"},"maintainers":[{"name":"kalwalt","email":"info@kalwaltart.it"},{"name":"nickw1","email":"nickw4426@gmail.com"},{"name":"nicolocarpignoli","email":"nicolocarpignoli@gmail.com"}],"description":"ARToolKit detection plugin for AR.js core (ECS plugin)","keywords":["arjs","artoolkit","artoolkit5","augmented-reality","esmodule","marker","marker-detection","plugin","tracking","wasm","webworker","worker"],"author":{"name":"Walter Perdan @kalwalt https://github.com/kalwalt"},"license":"MIT","readme":"# 🎯 arjs-plugin-artoolkit ⚡🕶️\n\n[![GitHub stars](https://img.shields.io/github/stars/ar-js-org/arjs-plugin-artoolkit?style=flat-square)](https://github.com/ar-js-org/arjs-plugin-artoolkit/stargazers)\n[![GitHub forks](https://img.shields.io/github/forks/ar-js-org/arjs-plugin-artoolkit?style=flat-square)](https://github.com/ar-js-org/arjs-plugin-artoolkit/network/members)\n[![CI](https://github.com/ar-js-org/arjs-plugin-artoolkit/actions/workflows/ci.yml/badge.svg)](https://github.com/ar-js-org/arjs-plugin-artoolkit/actions)\n[![Build](https://github.com/ar-js-org/arjs-plugin-artoolkit/actions/workflows/build.yml/badge.svg)](https://github.com/ar-js-org/arjs-plugin-artoolkit/actions)\n[![npm version](https://img.shields.io/npm/v/@ar-js-org/arjs-plugin-artoolkit?style=flat-square)](https://www.npmjs.com/package/@ar-js-org/arjs-plugin-artoolkit)\n[![Types](https://img.shields.io/badge/Types-included-blue?style=flat-square)](https://github.com/ar-js-org/arjs-plugin-artoolkit/blob/main/types/index.d.ts)\n[![Prettier](https://img.shields.io/badge/Prettier-enabled-2b7489?style=flat-square)](https://prettier.io/)\n[![License](https://img.shields.io/github/license/ar-js-org/arjs-plugin-artoolkit?style=flat-square)](https://github.com/ar-js-org/arjs-plugin-artoolkit/blob/main/LICENSE)\n[![Coverage](https://img.shields.io/codecov/c/gh/ar-js-org/arjs-plugin-artoolkit?style=flat-square)](https://codecov.io/gh/ar-js-org/arjs-plugin-artoolkit)\n\nLightweight WebWorker ARToolKit plugin for AR.js that detects square markers using WebAssembly and ImageBitmap zero-copy transfers, offering an event-driven API for realtime camera input, fast detection, and easy integration. 🔎🎯🚀⚡🧩\n\n## Table of Contents\n\n- [Features](#features-)\n- [Version](#version-)\n- [Installation](#installation-)\n- [Using the ESM build (recommended)](#using-the-esm-build-recommended-)\n- [Using source (development mode)](#using-source-development-mode-)\n- [Usage](#usage-)\n  - [Quick Start (copy-paste)](#quick-start-copy-paste-)\n  - [Register and enable](#register-and-enable-)\n  - [Events](#events-)\n  - [Sending frames](#sending-frames-)\n  - [Loading a pattern marker](#loading-a-pattern-marker-)\n- [Examples](#examples-)\n- [API Reference](#api-reference-)\n- [Troubleshooting](#troubleshooting-)\n\n<a id=\"features-\"></a>\n## Features ✨🧭\n\n- 🧠 Web Worker-based detection — marker detection runs off the main thread (Browser Module Worker)\n- 🖼️ ImageBitmap support — zero-copy frame transfer for efficient camera frames\n- 🧩 ARToolKit integration — square pattern markers (patt files)\n- ⚡ Event-driven API — markerFound / markerUpdated / markerLost + raw getMarker events\n- 🔍 Confidence filtering — only forwards PATTERN_MARKER events above minConfidence\n\n<a id=\"version-\"></a>\n## Version 🏷️\n\nThe plugin exposes its build-time version both as a constant and on each instance:\n\n```js\nimport {\n  ArtoolkitPlugin,\n  ARTOOLKIT_PLUGIN_VERSION,\n} from \"@ar-js-org/arjs-plugin-artoolkit\";\n\nconsole.log(\"Build version:\", ARTOOLKIT_PLUGIN_VERSION); // e.g. 0.1.0 or 'unknown'\nconst plugin = new ArtoolkitPlugin();\nconsole.log(\"Instance version:\", plugin.version);\n```\n\nIf the build-time define is missing (for example when using raw source or some test runners), the version falls back to `'unknown'`.\n\n<a id=\"installation-\"></a>\n## Installation 📦\n\n```bash\n# Attention: package may not be published yet\nnpm install @ar-js-org/arjs-plugin-artoolkit\n```\n\n<a id=\"using-the-esm-build-recommended-\"></a>\n## Using the ESM build (recommended) 🚀\n\nWhen you import the built ESM bundle from `dist/`, the worker and ARToolKit are already bundled and referenced correctly. You do NOT need to pass `artoolkitModuleUrl`.\n\nExample:\n\n```html\n<script type=\"module\">\n  import { ArtoolkitPlugin } from '/dist/arjs-plugin-artoolkit.es.js';\n\n  const engine = { eventBus: /* your event bus */ };\n\n  const plugin = new ArtoolkitPlugin({\n    worker: true,\n    cameraParametersUrl: '/path/to/camera_para.dat',\n    minConfidence: 0.6\n  });\n\n  await plugin.init(engine);\n  await plugin.enable();\n  console.log('Plugin version:', plugin.version);\n</script>\n```\n\nServing notes:\n\n- Serve from a web server so `/dist` assets resolve. The build is configured with `base: './'`, so the worker asset is referenced relative to the ESM file (e.g., `/dist/assets/worker-*.js`).\n- In your own apps, place `dist/` where you serve static assets and import the ESM with the appropriate path (absolute or relative).\n\n<a id=\"using-source-development-mode-\"></a>\n## Using source (development mode) 🛠️\n\nIf you develop against `src/` (not the built `dist/`), the worker will attempt to dynamically import ARToolKit. In that case, you must provide a valid `artoolkitModuleUrl` (for example a direct path to the UMD or ESM build) or ensure your dev server can resolve `@ar-js-org/artoolkit5-js` as an ES module. Browser module loading issues may occur if the module is not properly served or is not an ES module.\n\n```js\nconst plugin = new ArtoolkitPlugin({\n  worker: true,\n  artoolkitModuleUrl: '/node_modules/@ar-js-org/artoolkit5-js/dist/ARToolkit.js', // provide when using src/\n  cameraParametersUrl: '/path/to/camera_para.dat',\n  wasmBaseUrl: '/node_modules/@ar-js-org/artoolkit5-js/dist/', // optional; if your build requires it\n  minConfidence: 0.6,\n});\nconsole.log('Plugin version:', plugin.version);\n```\n\nCDN fallback (for source/dev):\n\n- Set `artoolkitModuleUrl` to a CDN ESM endpoint (e.g., jsDelivr/UNPKG) for `@ar-js-org/artoolkit5-js`.\n\nNotes:\n\n- The previous loader.js and manual WASM placement flow is no longer used.\n- In the `dist/` build, ARToolKit is bundled and `artoolkitModuleUrl` is NOT needed.\n\n<a id=\"usage-\"></a>\n## Usage 🧩\n\n<a id=\"quick-start-copy-paste-\"></a>\n### Quick Start (copy-paste) ⚡\n\n```js\nimport { ArtoolkitPlugin } from \"@ar-js-org/arjs-plugin-artoolkit\";\n\n// Minimal event bus stub\nconst eventBus = {\n  _h: new Map(),\n  on(e, h) {\n    if (!this._h.has(e)) this._h.set(e, []);\n    this._h.get(e).push(h);\n  },\n  emit(e, p) {\n    (this._h.get(e) || []).forEach((fn) => {\n      try {\n        fn(p);\n      } catch (err) {\n        console.error(err);\n      }\n    });\n  },\n};\nconst engine = { eventBus };\n\nconst plugin = new ArtoolkitPlugin({ worker: true, minConfidence: 0.6 });\nawait plugin.init(engine);\nawait plugin.enable();\nconsole.log(\"Version:\", plugin.version);\n\n// Load a marker (size is world units)\nawait plugin.loadMarker(\"/examples/simple-marker/data/patt.hiro\", 1);\n\neventBus.on(\"ar:markerFound\", (m) => console.log(\"FOUND\", m.id));\neventBus.on(\"ar:markerUpdated\", (m) => console.log(\"UPDATED\", m.id));\neventBus.on(\"ar:markerLost\", (m) => console.log(\"LOST\", m.id));\n```\n\n<a id=\"register-and-enable-\"></a>\n### Register and enable ✅\n\n```js\nimport { ArtoolkitPlugin } from \"@ar-js-org/arjs-plugin-artoolkit\";\n\nconst plugin = new ArtoolkitPlugin({\n  worker: true,\n  lostThreshold: 5, // frames before a marker is considered lost\n  frameDurationMs: 100, // expected ms per frame (affects lost timing)\n  // artoolkitModuleUrl: '/node_modules/@ar-js-org/artoolkit5-js/dist/ARToolkit.js', // Only for src/dev\n  cameraParametersUrl: \"/data/camera_para.dat\",\n  minConfidence: 0.6,\n});\n\nengine.pluginManager.register(\"artoolkit\", plugin);\nawait engine.pluginManager.enable(\"artoolkit\");\n```\n\n<a id=\"events-\"></a>\n### Events 🔔\n\nThe plugin emits the following events on your engine’s event bus:\n\n```js\n// Marker first detected\nengine.eventBus.on(\n  \"ar:markerFound\",\n  ({ id, poseMatrix, confidence, corners }) => {\n    // poseMatrix is Float32Array(16)\n  },\n);\n\n// Marker updated (tracking)\nengine.eventBus.on(\"ar:markerUpdated\", (data) => {\n  // same shape as markerFound\n});\n\n// Marker lost\nengine.eventBus.on(\"ar:markerLost\", ({ id }) => {});\n\n// Worker lifecycle\nengine.eventBus.on(\"ar:workerReady\", () => {});\nengine.eventBus.on(\"ar:workerError\", (error) => {});\n\n// Raw ARToolKit getMarker (filtered: PATTERN_MARKER only, above minConfidence)\nengine.eventBus.on(\"ar:getMarker\", (payload) => {\n  // payload = { type, matrix: number[16], marker: { idPatt, cfPatt, idMatrix?, cfMatrix?, vertex? } }\n});\n```\n\n<a id=\"sending-frames-\"></a>\n### Sending frames 🎞️\n\n```js\n// Create ImageBitmap from a <video> or <canvas>\nconst imageBitmap = await createImageBitmap(video);\n\n// Emit an engine update; the plugin transfers the ImageBitmap to the worker\nengine.eventBus.emit(\"engine:update\", {\n  id: frameId,\n  timestamp: Date.now(),\n  imageBitmap,\n  width: imageBitmap.width,\n  height: imageBitmap.height,\n});\n\n// The ImageBitmap is transferred and cannot be reused; the worker will close it.\n```\n\n<a id=\"loading-a-pattern-marker-\"></a>\n### Loading a pattern marker 📐\n\n```js\nconst { markerId, size } = await plugin.loadMarker(\n  \"/examples/simple-marker/data/patt.hiro\",\n  1,\n);\n```\n\n<a id=\"examples-\"></a>\n## Examples 🧪\n\nA complete webcam-based example is available under `examples/simple-marker/`.\n\nServe from the repository root so that `dist/` and example paths resolve:\n\n```bash\n# From repository root\nnpx http-server -p 8080\n# or\npython3 -m http.server 8080\n```\n\nOpen:\n\n- http://localhost:8080/examples/simple-marker/index.html\n\nThe example demonstrates:\n\n- Webcam capture with getUserMedia\n- ImageBitmap creation and frame submission\n- Event handling and console output\n- Raw `ar:getMarker` payloads for debugging\n\n<a id=\"api-reference-\"></a>\n## API Reference 📚\n\n<a id=\"arplugin-options-\"></a>\n### ArtoolkitPlugin options 🧭\n\n```text\n{\n  worker?: boolean;            // Enable worker (default: true)\n  lostThreshold?: number;      // Frames before 'lost' (default: 5)\n  frameDurationMs?: number;    // ms per frame used with lostThreshold (default: 200)\n  sweepIntervalMs?: number;    // Lost-sweep interval (default: 100)\n  artoolkitModuleUrl?: string; // Only needed when using source/dev; not needed for dist build\n  cameraParametersUrl?: string;// Camera params file URL (required unless you rely on a remote default)\n  wasmBaseUrl?: string;        // Base URL for ARToolKit assets (optional)\n  minConfidence?: number;      // Minimum confidence to forward getMarker (default: 0.6)\n}\n```\n\n<a id=\"methods-\"></a>\n### Methods 🛠️\n\n- `async init(core)` — initialize with engine core\n- `async enable()` — start worker and subscribe to frames\n- `async disable()` — stop worker and timers\n- `dispose()` — alias for disable\n- `getMarkerState(markerId)` — current tracked state\n- `async loadMarker(patternUrl: string, size = 1)` — load and track a pattern\n\n<a id=\"troubleshooting-\"></a>\n## Troubleshooting 🧰\n\n- Worker asset 404:\n  - Ensure you import the ESM from `/dist/arjs-plugin-artoolkit.es.js` and that `/dist/assets/worker-*.js` is served.\n  - The build uses `base: './'`, so worker URLs are relative to the ESM file location.\n- “Failed to resolve module specifier” in the Worker (source/dev only):\n  - Provide `artoolkitModuleUrl` or serve `/node_modules` from your dev server\n- Worker not starting:\n  - Serve via HTTP/HTTPS; ensure ES modules and Workers are supported\n- No detections:\n  - Confirm camera started, correct marker pattern, sufficient lighting\n  - Adjust `minConfidence` to reduce/raise filtering\n\n  - Check `plugin.version` (if 'unknown', ensure build-time define is configured)\n\n## Build & Publishing Notes\n\n- Sourcemap files (`.map`) generated in `dist/` and `types/` are excluded from the repository and the npm package to reduce package size and avoid shipping debug artifacts.\n  - See `.gitignore` and `.npmignore` for details.\n- When installing the package from npm (`npm install @ar-js-org/arjs-plugin-artoolkit`), all required built files are included and ready to use.\n  - If you install from source (e.g., cloning the repository), you must run the build manually: `npm run build`.\n\n### Releases and Built Artifacts\n\n- Built files (`dist/`) and TypeScript declarations (`types/`) are NOT committed to the repository. They are generated by the CI/build process and attached to GitHub Releases as downloadable assets.\n- To download the built files for a given release tag (example `v1.2.3`), use the Releases download URL:\n\n  `https://github.com/AR-js-org/arjs-plugin-artoolkit/releases/download/v1.2.3/dist/arjs-plugin-artoolkit.es.js`\n\n- If/when the package is published to npm, you can use jsDelivr to serve files from the npm package:\n\n  `https://cdn.jsdelivr.net/npm/@ar-js-org/arjs-plugin-artoolkit@1.2.3/dist/arjs-plugin-artoolkit.es.js`\n\n- Note: jsDelivr serves files from npm or from the repository tree at a tag/branch. Because `dist/` and `types/` are not committed to the repo, the npm package must contain the built files for jsDelivr to serve them.\n\nIf you want me to add publish instructions or a small note showing how to use the Release assets or jsDelivr URLs in your project, I can add examples.\n","readmeFilename":"README.md","_rev":"1-e265a88d0434ae1454c9c935214b426d"}