Skip to content

Conversation

Copy link

Copilot AI commented Oct 30, 2025

Introduces a data-oriented ECS (Entity-Component-System) core with plugin system for AR.js-core. Provides source capture plugins (webcam, video, image), device profiling, and a capture system. Existing Source and Profile classes remain unchanged for backward compatibility.

Core Architecture

  • ECS (src/core/ecs.js) - Entities, components, queries, resources
  • EventBus (src/core/event-bus.js) - Pub/sub for decoupled messaging
  • PluginManager (src/core/plugin-manager.js) - Register/enable/disable plugins
  • Engine (src/core/engine.js) - Game loop and system orchestration
  • Components (src/core/components.js) - Shared data structures: ProcessingConfig, CaptureState, FrameSourceRef, DeviceProfile

Systems & Plugins

  • CaptureSystem (src/systems/capture-system.js) - Initializes capture plugin, manages state, emits lifecycle events
  • Source Plugins (plugins/source/) - Webcam (getUserMedia), video file, image capture
  • Profile Plugin (plugins/profile/default-profile.js) - Auto-detects mobile/desktop, applies performance settings

Usage

import { Engine } from "./src/core/engine.js";
import { CaptureSystem } from "./src/systems/capture-system.js";
import { WebcamPlugin } from "./plugins/source/webcam.js";

const engine = new Engine();
engine.plugins.register("source:webcam", new WebcamPlugin());
engine.plugins.enable("source:webcam");

const captureSystem = new CaptureSystem({ sourceType: "webcam" });
await captureSystem.init(engine);
engine.start();

Examples

Two working examples in examples/basic-ecs/:

  • index.html - Webcam capture demo
  • image-example.html - Image source demo

ECS Image Example Running

Exports

New ECS exports added to src/index.js alongside existing API. Session/SessionDebugUI temporarily disabled due to pre-existing three.js dependency issue.

Documentation

  • docs/ecs-architecture.md - Complete architecture guide
  • README.md - Updated with ECS quick start
Original prompt

Goal
Introduce a modular, data-oriented core to AR.js-core using an ECS (Entity-Component-System) architecture and a plugin system. Provide initial source capture plugins (webcam, video, image), a default profile policy plugin, a capture system, and a minimal example app. Keep current classes (arjs-source.js, arjs-profile.js) intact but add legacy adapters that map the old API to the new internals to preserve backward compatibility. Add basic build wiring (ESM + dev server) and documentation.

Scope of this PR

  1. Core (new files)
  • src/core/ecs.js: Minimal ECS with entities, components, queries.
  • src/core/event-bus.js: Lightweight pub/sub event bus.
  • src/core/plugin-manager.js: Register/enable/disable plugins.
  • src/core/engine.js: Wires ECS, events, plugin manager, game loop, and systems.
  • src/core/components.js: Declare shared component/resource keys (ProcessingConfig, CaptureState, FrameSourceRef, DeviceProfile).
  1. Systems (new)
  • src/systems/capture-system.js: Initializes the chosen capture plugin, writes FrameSourceRef + CaptureState resources, emits lifecycle events.
  1. Plugins (new)
  • plugins/source/webcam.js: getUserMedia-based capture, emits source lifecycle events, provides HTMLVideoElement/MediaStream.
  • plugins/source/video.js: Local/remote
  • plugins/source/image.js: Static source.
  • plugins/profile/default.js: Computes device class and writes ProcessingConfig and DeviceProfile resources; emits profile:updated.
  1. Legacy adapters (new)
  • adapters/legacy/arjs-source-adapter.js: Exposes the old Source class API; internally spins up an engine, registers capture plugins, and mirrors the old DOM behavior (appends element with styles and id="arjs-video").
  • adapters/legacy/arjs-profile-adapter.js: Exposes the old Profile class API; maps performance presets and defaults while deferring backend-specific URLs to tracker plugins (to be implemented in future PRs).
  1. Minimal example (new)
  • examples/minimal/index.html: Simple HTML page with a container and a notice for user gesture if needed.
  • examples/minimal/main.js: Creates engine, registers plugins, starts capture (webcam by default), and appends the video element to the page for visual confirmation. Demonstrates using the legacy Source adapter as well as the new API.
  1. Build/Dev wiring
  • package.json updates/additions:
    • Module type: ESM.
    • Scripts: "dev" (Vite), "build" (tsup/rollup/esbuild or Vite build to dist), "serve" (preview), "lint".
    • Add devDependencies: vite, esbuild (or rollup), eslint (basic), and optionally vite-plugin-basic-ssl for HTTPS dev on webcam.
  • vite.config.js: Simple ESM build and a dev server with HTTPS option to allow getUserMedia in local dev.
  • .editorconfig and .eslintrc.cjs: basic code style.
  1. Docs
  • README.md: High-level architecture overview (ECS + plugins), how to run the minimal example, and how to continue using legacy Source/Profile via adapters.
  • docs/plugins.md: Plugin contract (id, init, lifecycle hooks) and examples for capture/profile plugins; document events and ECS components.

Acceptance criteria

  • Build runs: npm i && npm run dev starts a dev server where examples/minimal works (webcam permission flow visible) and shows a playing video in the page (or a message if blocked until click).
  • npm run build generates ESM bundles under dist/ without bundling peer dependencies (three.js/ARToolkit are not introduced in this PR).
  • Legacy adapters work: importing adapters/legacy/arjs-source-adapter.js allows existing initialization patterns to display the source element.
  • No breaking changes to existing files (e.g., src/arjs-source.js and src/arjs-profile.js remain as-is). New code is additive.
  • Lint passes for newly added files.

Implementation notes / skeletons to include
Below are minimal skeletons to implement (adapt file paths if needed). These are intentionally compact and can be refined later.

  1. src/core/ecs.js
  • Entities are numeric IDs.
  • Components stored in Map<string, Map<entity, data>>.
  • API: createEntity(), removeEntity(), addComponent(entity, type, data), removeComponent(entity, type), getComponent(entity, type), query(types[]).
  1. src/core/event-bus.js
  • Simple on(event, handler) and emit(event, data) with unsubscribe support.
  1. src/core/plugin-manager.js
  • register(def), enable(id, options), disable(id), get(id), list().
  • def.init(core, options) returns instance; instance may expose onEnable/onDisable.
  1. src/core/engine.js
  • createEngine(opts): compose ecs, events, pluginManager; registerSystem(system), start/stop/tick loop; emit 'tick' and 'frame' events.
  1. src/core/components.js
  • Export string constants: ProcessingConfig, CaptureState, FrameSourceRef, DeviceProfile.
  1. src/systems/capture-system.js
  • createCaptureSystem({ capturePluginId, captureOptions }): on init, enable and start capture plugin, set ECS resources, emit source:* events.
  1. plugins/source/webcam.js
  • getUserMedia with configurable constraints; create...

This pull request was created as a result of the following prompt from Copilot chat.

Goal
Introduce a modular, data-oriented core to AR.js-core using an ECS (Entity-Component-System) architecture and a plugin system. Provide initial source capture plugins (webcam, video, image), a default profile policy plugin, a capture system, and a minimal example app. Keep current classes (arjs-source.js, arjs-profile.js) intact but add legacy adapters that map the old API to the new internals to preserve backward compatibility. Add basic build wiring (ESM + dev server) and documentation.

Scope of this PR

  1. Core (new files)
  • src/core/ecs.js: Minimal ECS with entities, components, queries.
  • src/core/event-bus.js: Lightweight pub/sub event bus.
  • src/core/plugin-manager.js: Register/enable/disable plugins.
  • src/core/engine.js: Wires ECS, events, plugin manager, game loop, and systems.
  • src/core/components.js: Declare shared component/resource keys (ProcessingConfig, CaptureState, FrameSourceRef, DeviceProfile).
  1. Systems (new)
  • src/systems/capture-system.js: Initializes the chosen capture plugin, writes FrameSourceRef + CaptureState resources, emits lifecycle events.
  1. Plugins (new)
  • plugins/source/webcam.js: getUserMedia-based capture, emits source lifecycle events, provides HTMLVideoElement/MediaStream.
  • plugins/source/video.js: Local/remote
  • plugins/source/image.js: Static source.
  • plugins/profile/default.js: Computes device class and writes ProcessingConfig and DeviceProfile resources; emits profile:updated.
  1. Legacy adapters (new)
  • adapters/legacy/arjs-source-adapter.js: Exposes the old Source class API; internally spins up an engine, registers capture plugins, and mirrors the old DOM behavior (appends element with styles and id="arjs-video").
  • adapters/legacy/arjs-profile-adapter.js: Exposes the old Profile class API; maps performance presets and defaults while deferring backend-specific URLs to tracker plugins (to be implemented in future PRs).
  1. Minimal example (new)
  • examples/minimal/index.html: Simple HTML page with a container and a notice for user gesture if needed.
  • examples/minimal/main.js: Creates engine, registers plugins, starts capture (webcam by default), and appends the video element to the page for visual confirmation. Demonstrates using the legacy Source adapter as well as the new API.
  1. Build/Dev wiring
  • package.json updates/additions:
    • Module type: ESM.
    • Scripts: "dev" (Vite), "build" (tsup/rollup/esbuild or Vite build to dist), "serve" (preview), "lint".
    • Add devDependencies: vite, esbuild (or rollup), eslint (basic), and optionally vite-plugin-basic-ssl for HTTPS dev on webcam.
  • vite.config.js: Simple ESM build and a dev server with HTTPS option to allow getUserMedia in local dev.
  • .editorconfig and .eslintrc.cjs: basic code style.
  1. Docs
  • README.md: High-level architecture overview (ECS + plugins), how to run the minimal example, and how to continue using legacy Source/Profile via adapters.
  • docs/plugins.md: Plugin contract (id, init, lifecycle hooks) and examples for capture/profile plugins; document events and ECS components.

Acceptance criteria

  • Build runs: npm i && npm run dev starts a dev server where examples/minimal works (webcam permission flow visible) and shows a playing video in the page (or a message if blocked until click).
  • npm run build generates ESM bundles under dist/ without bundling peer dependencies (three.js/ARToolkit are not introduced in this PR).
  • Legacy adapters work: importing adapters/legacy/arjs-source-adapter.js allows existing initialization patterns to display the source element.
  • No breaking changes to existing files (e.g., src/arjs-source.js and src/arjs-profile.js remain as-is). New code is additive.
  • Lint passes for newly added files.

Implementation notes / skeletons to include
Below are minimal skeletons to implement (adapt file paths if needed). These are intentionally compact and can be refined later.

  1. src/core/ecs.js
  • Entities are numeric IDs.
  • Components stored in Map<string, Map<entity, data>>.
  • API: createEntity(), removeEntity(), addComponent(entity, type, data), removeComponent(entity, type), getComponent(entity, type), query(types[]).
  1. src/core/event-bus.js
  • Simple on(event, handler) and emit(event, data) with unsubscribe support.
  1. src/core/plugin-manager.js
  • register(def), enable(id, options), disable(id), get(id), list().
  • def.init(core, options) returns instance; instance may expose onEnable/onDisable.
  1. src/core/engine.js
  • createEngine(opts): compose ecs, events, pluginManager; registerSystem(system), start/stop/tick loop; emit 'tick' and 'frame' events.
  1. src/core/components.js
  • Export string constants: ProcessingConfig, CaptureState, FrameSourceRef, DeviceProfile.
  1. src/systems/capture-system.js
  • createCaptureSystem({ capturePluginId, captureOptions }): on init, enable and start capture plugin, set ECS resources, emit source:* events.
  1. plugins/source/webcam.js
  • getUserMedia with configurable constraints; create HTMLVideoElement; handle autoplay/gesture; provide getFrameSource().
  1. plugins/source/video.js
  • HTMLVideoElement sourceUrl; loop/muted/autoplay/playsInline; provide getFrameSource().
  1. plugins/source/image.js
  • HTMLImageElement loading via sourceUrl; provide getFrameSource().
  1. plugins/profile/default.js
  • Guess device label (mobile vs desktop); map to ProcessingConfig presets; write DeviceProfile + ProcessingConfig to ECS; expose setLabel().
  1. adapters/legacy/arjs-source-adapter.js
  • Class Source with .init(onReady, onError), .domElement, .ready, .parameters consistent with current API; internally start engine + capture system and append the element with legacy styles.
  1. adapters/legacy/arjs-profile-adapter.js
  • Class Profile with .reset(), .performance(label), .defaultMarker(), mirroring the current behavior but note that backend URLs will be provided by future tracker plugins.
  1. examples/minimal/index.html and examples/minimal/main.js
  • Demonstrate both new API and legacy adapter to show the same result (video feed in the page).
  1. Build: vite.config.js
  • ESM library mode build for src/core/engine.js as entry; ensure examples can import from source during dev.
  1. README.md and docs/plugins.md
  • Describe new architecture, plugin contract, and how to run the example.

Non-goals for this PR

  • No tracker/renderer plugins (ARToolkit, three.js, A-Frame) yet — to be added in follow-up PRs.
  • No removal/refactor of existing arjs-source.js or arjs-profile.js; only additive changes and adapters.

Please create a feature branch (e.g., feat/modular-core-skeleton), implement the above files and wiring, add minimal tests if feasible, and open a pull request with a comprehensive description and instructions for reviewers.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@kalwalt kalwalt added the enhancement New feature or request label Oct 30, 2025
Copilot AI changed the title [WIP] Introduce modular data-oriented core using ECS architecture Add ECS architecture with plugin system for modular AR capture Oct 30, 2025
Copilot AI requested a review from kalwalt October 30, 2025 13:42
Copilot finished work on behalf of kalwalt October 30, 2025 13:42
@kalwalt kalwalt closed this Oct 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants