-
Notifications
You must be signed in to change notification settings - Fork 0
Add ECS architecture and plugin system with source capture plugins #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
kalwalt
merged 63 commits into
dev-arjs-next
from
copilot/add-ecs-architecture-and-plugins
Nov 4, 2025
Merged
Changes from 1 commit
Commits
Show all changes
63 commits
Select commit
Hold shift + click to select a range
c27a763
Initial plan
Copilot 265bc9b
Initial exploration - repository state analyzed
Copilot 839db39
Add ECS core infrastructure with plugins and systems
Copilot 3d71c45
Remove dist directory from git tracking
Copilot 5c7cb02
Add plugin documentation and index
Copilot 316eafa
Address code review feedback - clarify plugin import paths
Copilot d876c1a
Add comprehensive implementation summary
Copilot 34d4978
Update package.json with new content
kalwalt bf64747
Create vite.config.js file
kalwalt fe301d0
Updating README.md with new ECS architecture and plugin system details.
kalwalt 2d9e124
Update package.json
kalwalt 5525b35
formatting code with prettier
kalwalt 33c9e95
new image-example for testing
kalwalt 11fb9f4
docs: link Image Example in Running Examples
kalwalt 00eeaff
docs: enhance README formatting for clarity on Webpack, Vite, and Exa…
kalwalt 930de57
Fix webpack output filename to match package.json main field
Copilot 942abb4
Update webpack config: filename to arjs-core.js and library to ARJSCore
Copilot 3736ad4
feat: add ECS architecture with Vitest configuration and tests
kalwalt 41ac1f6
Merge remote-tracking branch 'origin/copilot/add-ecs-architecture-and…
kalwalt 61356e7
chore: remove jsdom dependency and update Vitest config to use node e…
kalwalt 4b5077f
test: add unit tests for PluginManager and smoke tests for plugins
kalwalt a6843e7
ci: add CI workflow for automated testing and builds
kalwalt 82af9d3
fix for formatting issue
kalwalt c8ef462
ci: update CI workflow to use webpack for stable builds and add Vite …
kalwalt 9b53573
chore: add Rollup as a dev dependency and include optional Rollup pac…
kalwalt 4e9b786
formatting code
kalwalt 3fb84be
chore: update .gitignore and package.json for coverage and dependency…
kalwalt 1cbfba2
Create examples/index.html with AR.js-core examples
kalwalt d9bf898
feat: add initial HTML structure and Vite configuration for AR.js-cor…
kalwalt 0b3fb67
feat: enhance HTML structure and update README for AR.js Core plugins
kalwalt 2d24215
Merge remote-tracking branch 'origin/copilot/add-ecs-architecture-and…
kalwalt b6517aa
feat: enhance index.html layout and update package.json for versionin…
kalwalt 72ef4bd
Initial plan
Copilot 1d92b2c
feat(profile): add QUALITY_TIERS and auto device profile; docs: migra…
kalwalt c7ed476
Implement capability-based device profiling with backward compatibility
Copilot 1be9af2
Merge branch 'copilot/add-ecs-architecture-and-plugins' into copilot/…
kalwalt 6ecf098
Optimize micro-benchmark and remove dead code per code review
Copilot 47c1656
feat(profile): implement capability-based device profiling with backw…
kalwalt 7e0ee68
feat(profile): enhance mobile device detection with additional patterns
Copilot 2a467d2
feat(profile): capability-based auto profile; keep legacy mappings
kalwalt e42bb56
Merge branch 'copilot/add-ecs-architecture-and-plugins' into copilot/…
kalwalt 2d7c53e
feat(profile): capability-based auto profile; keep legacy mappings
kalwalt 7f39264
docs(plugins): add migration note for capability-based device profiles
kalwalt 27285ca
refactor(default-policy): improve code readability with consistent fo…
kalwalt 468a221
chore(gitattributes): add line ending normalization for JavaScript an…
kalwalt 5b3143e
refactor: standardize quote style across JavaScript files and update …
kalwalt 74728e0
chore(ci): update Node.js version to 22.x for CI stability
kalwalt a4541d8
chore(ci): update Node.js version to 22.x for CI stability
kalwalt b092da9
Merge branch 'copilot/add-ecs-architecture-and-plugins' into copilot/…
kalwalt 420fec4
docs: add newline at end of README.md for consistency
kalwalt 6ba45e7
Merge pull request #5 from AR-js-org/copilot/replace-static-device-pr…
kalwalt 437900f
feat(engine): add static VERSION/REVISION from package.json; test: ad…
kalwalt 3279191
fix(engine): add newline at end of file for consistency
kalwalt 51cc5a2
feat(engine): add tests for VERSION and REVISION from package.json
kalwalt d5e767a
Add ESLint, Husky, lint-staged and CI workflow for format/lint enforc…
Copilot 5df0635
Update Husky pre-commit hook to use v10-compatible format
Copilot 2ba3aca
Add ESLint cache and improve lint-staged performance
Copilot abab221
Add explicit permissions to CI workflow for security
Copilot 6eff7fe
Update .nvmrc with Node.js version v22.21.1
kalwalt ab41c8a
Update CI workflow to run on all branches and use ubuntu-24.04
Copilot 4066cb7
chore(ci): update format-lint workflow to use .nvmrc for Node.js version
kalwalt c0d8888
feat(ci): enhance CI workflow with formatting and linting checks
kalwalt eea9464
AR.js Core ECS + ArtoolkitPlugin example (#7)
kalwalt File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,167 +1,172 @@ | ||
| <!doctype html> | ||
| <html lang="en"> | ||
| <head> | ||
| <head> | ||
| <meta charset="UTF-8" /> | ||
| <meta | ||
| name="viewport" | ||
| content="width=device-width, initial-scale=1.0, viewport-fit=cover" | ||
| name="viewport" | ||
| content="width=device-width, initial-scale=1.0, viewport-fit=cover" | ||
| /> | ||
| <title>AR.js-core ECS - Image Source Example</title> | ||
| <style> | ||
| html, body { | ||
| margin: 0; | ||
| padding: 0; | ||
| height: 100%; | ||
| background: #111; | ||
| color: #eee; | ||
| font-family: system-ui, sans-serif; | ||
| } | ||
| #app { | ||
| position: relative; | ||
| width: 100%; | ||
| height: 100%; | ||
| overflow: hidden; | ||
| } | ||
| #panel { | ||
| position: absolute; | ||
| top: 12px; | ||
| left: 12px; | ||
| right: 12px; | ||
| max-width: 720px; | ||
| padding: 10px 12px; | ||
| background: rgba(0,0,0,0.55); | ||
| border-radius: 6px; | ||
| z-index: 10; | ||
| } | ||
| #row { | ||
| display: flex; | ||
| gap: 8px; | ||
| margin-top: 8px; | ||
| } | ||
| #url { | ||
| flex: 1; | ||
| min-width: 240px; | ||
| color: #eee; | ||
| background: rgba(255,255,255,0.08); | ||
| border: 1px solid rgba(255,255,255,0.2); | ||
| padding: 6px 8px; | ||
| border-radius: 4px; | ||
| outline: none; | ||
| } | ||
| button { | ||
| color: #111; | ||
| background: #9ef01a; | ||
| border: none; | ||
| padding: 8px 12px; | ||
| border-radius: 4px; | ||
| cursor: pointer; | ||
| } | ||
| button:disabled { | ||
| opacity: 0.6; | ||
| cursor: not-allowed; | ||
| } | ||
| /* The image element created by the plugin gets id=arjs-video */ | ||
| #arjs-video { | ||
| position: absolute !important; | ||
| top: 0 !important; | ||
| left: 0 !important; | ||
| width: 100% !important; | ||
| height: 100% !important; | ||
| object-fit: contain; | ||
| z-index: -2 !important; | ||
| } | ||
| .status-ok { color: #9ef01a; } | ||
| .status-bad { color: #ff6b6b; } | ||
| html, | ||
| body { | ||
| margin: 0; | ||
| padding: 0; | ||
| height: 100%; | ||
| background: #111; | ||
| color: #eee; | ||
| font-family: system-ui, sans-serif; | ||
| } | ||
| #app { | ||
| position: relative; | ||
| width: 100%; | ||
| height: 100%; | ||
| overflow: hidden; | ||
| } | ||
| #panel { | ||
| position: absolute; | ||
| top: 12px; | ||
| left: 12px; | ||
| right: 12px; | ||
| max-width: 720px; | ||
| padding: 10px 12px; | ||
| background: rgba(0, 0, 0, 0.55); | ||
| border-radius: 6px; | ||
| z-index: 10; | ||
| } | ||
| #row { | ||
| display: flex; | ||
| gap: 8px; | ||
| margin-top: 8px; | ||
| } | ||
| #url { | ||
| flex: 1; | ||
| min-width: 240px; | ||
| color: #eee; | ||
| background: rgba(255, 255, 255, 0.08); | ||
| border: 1px solid rgba(255, 255, 255, 0.2); | ||
| padding: 6px 8px; | ||
| border-radius: 4px; | ||
| outline: none; | ||
| } | ||
| button { | ||
| color: #111; | ||
| background: #9ef01a; | ||
| border: none; | ||
| padding: 8px 12px; | ||
| border-radius: 4px; | ||
| cursor: pointer; | ||
| } | ||
| button:disabled { | ||
| opacity: 0.6; | ||
| cursor: not-allowed; | ||
| } | ||
| /* The image element created by the plugin gets id=arjs-video */ | ||
| #arjs-video { | ||
| position: absolute !important; | ||
| top: 0 !important; | ||
| left: 0 !important; | ||
| width: 100% !important; | ||
| height: 100% !important; | ||
| object-fit: contain; | ||
| z-index: -2 !important; | ||
| } | ||
| .status-ok { | ||
| color: #9ef01a; | ||
| } | ||
| .status-bad { | ||
| color: #ff6b6b; | ||
| } | ||
| </style> | ||
| </head> | ||
| <body> | ||
| <div id="app"> | ||
| <div id="panel"> | ||
| </head> | ||
| <body> | ||
| <div id="app"> | ||
| <div id="panel"> | ||
| <div><strong>AR.js-core ECS Image Example</strong></div> | ||
| <div id="status" class="status-ok">Ready</div> | ||
| <div id="row"> | ||
| <input | ||
| id="url" | ||
| type="text" | ||
| placeholder="Enter image URL..." | ||
| value="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/Example.jpg/640px-Example.jpg" | ||
| /> | ||
| <button id="load">Load</button> | ||
| <button id="clear">Clear</button> | ||
| <input | ||
| id="url" | ||
| type="text" | ||
| placeholder="Enter image URL..." | ||
| value="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/Example.jpg/640px-Example.jpg" | ||
| /> | ||
| <button id="load">Load</button> | ||
| <button id="clear">Clear</button> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> | ||
|
|
||
| <script type="module"> | ||
| import { Engine } from "../../src/core/engine.js"; | ||
| import { imagePlugin } from "../../plugins/source/image.js"; | ||
| <script type="module"> | ||
| import { Engine } from "../../src/core/engine.js"; | ||
| import { imagePlugin } from "../../plugins/source/image.js"; | ||
|
|
||
| const statusEl = document.getElementById("status"); | ||
| const urlEl = document.getElementById("url"); | ||
| const loadBtn = document.getElementById("load"); | ||
| const clearBtn = document.getElementById("clear"); | ||
| const statusEl = document.getElementById("status"); | ||
| const urlEl = document.getElementById("url"); | ||
| const loadBtn = document.getElementById("load"); | ||
| const clearBtn = document.getElementById("clear"); | ||
|
|
||
| // Initialize engine (provides eventBus and context) | ||
| const engine = new Engine(); | ||
| const context = engine.getContext(); | ||
| // Initialize engine (provides eventBus and context) | ||
| const engine = new Engine(); | ||
| const context = engine.getContext(); | ||
|
|
||
| // Initialize the image plugin | ||
| await imagePlugin.init(context); | ||
| // Initialize the image plugin | ||
| await imagePlugin.init(context); | ||
|
|
||
| function setStatus(msg, ok = true) { | ||
| function setStatus(msg, ok = true) { | ||
| statusEl.textContent = msg; | ||
| statusEl.className = ok ? "status-ok" : "status-bad"; | ||
| } | ||
| } | ||
|
|
||
| function removeExisting() { | ||
| function removeExisting() { | ||
| const el = document.getElementById("arjs-video"); | ||
| if (el && el.parentNode) el.parentNode.removeChild(el); | ||
| } | ||
| } | ||
|
|
||
| async function loadImage(url) { | ||
| async function loadImage(url) { | ||
| if (!url) return; | ||
| try { | ||
| setStatus("Loading image...", true); | ||
| // Remove any previous image first | ||
| removeExisting(); | ||
| setStatus("Loading image...", true); | ||
| // Remove any previous image first | ||
| removeExisting(); | ||
|
|
||
| // Ask plugin to capture; it will append to document.body on load | ||
| const frame = await imagePlugin.capture( | ||
| { | ||
| sourceUrl: url, | ||
| sourceWidth: 640, | ||
| sourceHeight: 480, | ||
| displayWidth: 640, | ||
| displayHeight: 480, | ||
| }, | ||
| context | ||
| ); | ||
| // Ask plugin to capture; it will append to document.body on load | ||
| const frame = await imagePlugin.capture( | ||
| { | ||
| sourceUrl: url, | ||
| sourceWidth: 640, | ||
| sourceHeight: 480, | ||
| displayWidth: 640, | ||
| displayHeight: 480, | ||
| }, | ||
| context, | ||
| ); | ||
|
|
||
| // If not yet appended by plugin, ensure it’s visible | ||
| if (frame?.element && !frame.element.isConnected) { | ||
| document.body.appendChild(frame.element); | ||
| } | ||
| // If not yet appended by plugin, ensure it’s visible | ||
| if (frame?.element && !frame.element.isConnected) { | ||
| document.body.appendChild(frame.element); | ||
| } | ||
|
|
||
| setStatus("Image loaded", true); | ||
| setStatus("Image loaded", true); | ||
| } catch (e) { | ||
| console.error(e); | ||
| setStatus("Failed to load image. Check the URL and CORS.", false); | ||
| console.error(e); | ||
| setStatus("Failed to load image. Check the URL and CORS.", false); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Wire up UI | ||
| loadBtn.addEventListener("click", () => { | ||
| // Wire up UI | ||
| loadBtn.addEventListener("click", () => { | ||
| const url = (urlEl.value || "").trim(); | ||
| loadImage(url); | ||
| }); | ||
| }); | ||
|
|
||
| clearBtn.addEventListener("click", () => { | ||
| clearBtn.addEventListener("click", () => { | ||
| removeExisting(); | ||
| setStatus("Cleared", true); | ||
| }); | ||
| }); | ||
|
|
||
| // Auto-load the initial URL | ||
| loadImage(urlEl.value); | ||
| </script> | ||
| </body> | ||
| </html> | ||
| // Auto-load the initial URL | ||
| loadImage(urlEl.value); | ||
| </script> | ||
| </body> | ||
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.