From b2fa4a73b2e32038b0f974b7b6556c4976e08e69 Mon Sep 17 00:00:00 2001 From: Exelo Date: Mon, 17 Mar 2025 14:57:08 +0100 Subject: [PATCH 1/5] feat(graphics-2d): add base library --- packages/graphics-2d/.gitignore | 267 ++++++++++++++++++ packages/graphics-2d/.idea/.gitignore | 8 + packages/graphics-2d/.idea/.name | 1 + .../.idea/[NanoForge] Engine Graphics 2D.iml | 12 + .../graphics-2d/.idea/codeStyles/Project.xml | 172 +++++++++++ .../.idea/codeStyles/codeStyleConfig.xml | 5 + packages/graphics-2d/.idea/editor.xml | 107 +++++++ .../graphics-2d/.idea/git_toolbox_blame.xml | 6 + .../graphics-2d/.idea/git_toolbox_prj.xml | 15 + .../inspectionProfiles/Project_Default.xml | 12 + .../graphics-2d/.idea/jsLinters/eslint.xml | 6 + packages/graphics-2d/.idea/misc.xml | 24 ++ packages/graphics-2d/.idea/modules.xml | 8 + packages/graphics-2d/.idea/prettier.xml | 7 + packages/graphics-2d/.idea/vcs.xml | 6 + packages/graphics-2d/.nvmrc | 1 + packages/graphics-2d/.prettierignore | 8 + packages/graphics-2d/.prettierrc | 11 + packages/graphics-2d/README.md | 1 + packages/graphics-2d/eslint.config.js | 63 +++++ packages/graphics-2d/jest.config.json | 12 + packages/graphics-2d/package.json | 68 +++++ .../graphics-2d/src/graphics-2d.library.ts | 17 ++ packages/graphics-2d/src/index.ts | 1 + .../test/graphics-2d.library.spec.ts | 21 ++ packages/graphics-2d/test/tsconfig.json | 3 + packages/graphics-2d/tsconfig.build.json | 17 ++ packages/graphics-2d/tsconfig.json | 13 + pnpm-lock.yaml | 61 ++++ 29 files changed, 953 insertions(+) create mode 100644 packages/graphics-2d/.gitignore create mode 100644 packages/graphics-2d/.idea/.gitignore create mode 100644 packages/graphics-2d/.idea/.name create mode 100644 packages/graphics-2d/.idea/[NanoForge] Engine Graphics 2D.iml create mode 100644 packages/graphics-2d/.idea/codeStyles/Project.xml create mode 100644 packages/graphics-2d/.idea/codeStyles/codeStyleConfig.xml create mode 100644 packages/graphics-2d/.idea/editor.xml create mode 100644 packages/graphics-2d/.idea/git_toolbox_blame.xml create mode 100644 packages/graphics-2d/.idea/git_toolbox_prj.xml create mode 100644 packages/graphics-2d/.idea/inspectionProfiles/Project_Default.xml create mode 100644 packages/graphics-2d/.idea/jsLinters/eslint.xml create mode 100644 packages/graphics-2d/.idea/misc.xml create mode 100644 packages/graphics-2d/.idea/modules.xml create mode 100644 packages/graphics-2d/.idea/prettier.xml create mode 100644 packages/graphics-2d/.idea/vcs.xml create mode 100644 packages/graphics-2d/.nvmrc create mode 100644 packages/graphics-2d/.prettierignore create mode 100644 packages/graphics-2d/.prettierrc create mode 100644 packages/graphics-2d/README.md create mode 100644 packages/graphics-2d/eslint.config.js create mode 100644 packages/graphics-2d/jest.config.json create mode 100644 packages/graphics-2d/package.json create mode 100644 packages/graphics-2d/src/graphics-2d.library.ts create mode 100644 packages/graphics-2d/src/index.ts create mode 100644 packages/graphics-2d/test/graphics-2d.library.spec.ts create mode 100644 packages/graphics-2d/test/tsconfig.json create mode 100644 packages/graphics-2d/tsconfig.build.json create mode 100644 packages/graphics-2d/tsconfig.json diff --git a/packages/graphics-2d/.gitignore b/packages/graphics-2d/.gitignore new file mode 100644 index 00000000..ddfd7829 --- /dev/null +++ b/packages/graphics-2d/.gitignore @@ -0,0 +1,267 @@ +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### C++ template +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Node template +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +### Private + +# NX +.nx/ + +# Compiled files +src/**/*.js +src/**/*.d.ts diff --git a/packages/graphics-2d/.idea/.gitignore b/packages/graphics-2d/.idea/.gitignore new file mode 100644 index 00000000..13566b81 --- /dev/null +++ b/packages/graphics-2d/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/packages/graphics-2d/.idea/.name b/packages/graphics-2d/.idea/.name new file mode 100644 index 00000000..81d68e20 --- /dev/null +++ b/packages/graphics-2d/.idea/.name @@ -0,0 +1 @@ +[NanoForge] Engine Graphics 2D \ No newline at end of file diff --git a/packages/graphics-2d/.idea/[NanoForge] Engine Graphics 2D.iml b/packages/graphics-2d/.idea/[NanoForge] Engine Graphics 2D.iml new file mode 100644 index 00000000..24643cc3 --- /dev/null +++ b/packages/graphics-2d/.idea/[NanoForge] Engine Graphics 2D.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/codeStyles/Project.xml b/packages/graphics-2d/.idea/codeStyles/Project.xml new file mode 100644 index 00000000..a57ead77 --- /dev/null +++ b/packages/graphics-2d/.idea/codeStyles/Project.xml @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/codeStyles/codeStyleConfig.xml b/packages/graphics-2d/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 00000000..79ee123c --- /dev/null +++ b/packages/graphics-2d/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/editor.xml b/packages/graphics-2d/.idea/editor.xml new file mode 100644 index 00000000..8c39ae07 --- /dev/null +++ b/packages/graphics-2d/.idea/editor.xml @@ -0,0 +1,107 @@ + + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/git_toolbox_blame.xml b/packages/graphics-2d/.idea/git_toolbox_blame.xml new file mode 100644 index 00000000..7dc12496 --- /dev/null +++ b/packages/graphics-2d/.idea/git_toolbox_blame.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/git_toolbox_prj.xml b/packages/graphics-2d/.idea/git_toolbox_prj.xml new file mode 100644 index 00000000..02b915b8 --- /dev/null +++ b/packages/graphics-2d/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/inspectionProfiles/Project_Default.xml b/packages/graphics-2d/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000..41ec19c1 --- /dev/null +++ b/packages/graphics-2d/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/jsLinters/eslint.xml b/packages/graphics-2d/.idea/jsLinters/eslint.xml new file mode 100644 index 00000000..541945bb --- /dev/null +++ b/packages/graphics-2d/.idea/jsLinters/eslint.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/misc.xml b/packages/graphics-2d/.idea/misc.xml new file mode 100644 index 00000000..7ecbce57 --- /dev/null +++ b/packages/graphics-2d/.idea/misc.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/modules.xml b/packages/graphics-2d/.idea/modules.xml new file mode 100644 index 00000000..59ac9e2f --- /dev/null +++ b/packages/graphics-2d/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/prettier.xml b/packages/graphics-2d/.idea/prettier.xml new file mode 100644 index 00000000..0c83ac4e --- /dev/null +++ b/packages/graphics-2d/.idea/prettier.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.idea/vcs.xml b/packages/graphics-2d/.idea/vcs.xml new file mode 100644 index 00000000..b2bdec2d --- /dev/null +++ b/packages/graphics-2d/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/packages/graphics-2d/.nvmrc b/packages/graphics-2d/.nvmrc new file mode 100644 index 00000000..c9758a53 --- /dev/null +++ b/packages/graphics-2d/.nvmrc @@ -0,0 +1 @@ +v23.6.0 diff --git a/packages/graphics-2d/.prettierignore b/packages/graphics-2d/.prettierignore new file mode 100644 index 00000000..e814a634 --- /dev/null +++ b/packages/graphics-2d/.prettierignore @@ -0,0 +1,8 @@ +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock +bun.lock + +*.js +*.d.ts diff --git a/packages/graphics-2d/.prettierrc b/packages/graphics-2d/.prettierrc new file mode 100644 index 00000000..d5f635c3 --- /dev/null +++ b/packages/graphics-2d/.prettierrc @@ -0,0 +1,11 @@ +{ + "plugins": ["@trivago/prettier-plugin-sort-imports"], + "importOrderSeparation": true, + "importOrderSortSpecifiers": true, + "importOrderParserPlugins": ["typescript", "decorators-legacy"], + "importOrder": ["^~/(.*)$", "^[./]"], + "useTabs": false, + "singleQuote": false, + "trailingComma": "all", + "printWidth": 100 +} diff --git a/packages/graphics-2d/README.md b/packages/graphics-2d/README.md new file mode 100644 index 00000000..5d16e806 --- /dev/null +++ b/packages/graphics-2d/README.md @@ -0,0 +1 @@ +# Engine Graphics 2D diff --git a/packages/graphics-2d/eslint.config.js b/packages/graphics-2d/eslint.config.js new file mode 100644 index 00000000..4a7529ef --- /dev/null +++ b/packages/graphics-2d/eslint.config.js @@ -0,0 +1,63 @@ +import pluginJs from "@eslint/js"; +import eslintConfigPrettier from "eslint-config-prettier"; +import globals from "globals"; +import tseslint from "typescript-eslint"; +import pluginJest from "eslint-plugin-jest"; + +export default [ + { + files: ["src/**/*.{ts}"], + }, + { languageOptions: { globals: globals.node } }, + + + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + ...tseslint.configs.strict, + eslintConfigPrettier, + { ignores: ["**/*.js"] }, + { + rules: { + "@typescript-eslint/consistent-type-imports": [ + "error", + { + disallowTypeAnnotations: true, + fixStyle: "inline-type-imports", + prefer: "type-imports", + }, + ], + "@typescript-eslint/no-extraneous-class": "off", + "@typescript-eslint/no-empty-object-type": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/member-ordering": [ + "error", + { + default: [ + "static-field", + "field", + "public-static-method", + "constructor", + "method", + "protected-method", + "private-method", + ], + }, + ], + }, + }, + { + files: ["**/*.spec.ts"], + plugins: { jest: pluginJest }, + languageOptions: { + globals: pluginJest.environments.globals.globals, + }, + rules: { + "jest/no-disabled-tests": "warn", + "jest/no-focused-tests": "error", + "jest/no-identical-title": "error", + "jest/prefer-to-have-length": "warn", + "jest/valid-expect": "error", + } + } +]; diff --git a/packages/graphics-2d/jest.config.json b/packages/graphics-2d/jest.config.json new file mode 100644 index 00000000..b75e6b6c --- /dev/null +++ b/packages/graphics-2d/jest.config.json @@ -0,0 +1,12 @@ +{ + "moduleFileExtensions": ["js", "json", "ts"], + "rootDir": "test", + "collectCoverageFrom": ["**/*.(t|j)s"], + "testEnvironment": "node", + "testRegex": ".*\\.spec\\.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "verbose": true, + "testTimeout": 5000 +} diff --git a/packages/graphics-2d/package.json b/packages/graphics-2d/package.json new file mode 100644 index 00000000..f4d5393f --- /dev/null +++ b/packages/graphics-2d/package.json @@ -0,0 +1,68 @@ +{ + "name": "@nanoforge/graphics-2d", + "version": "1.0.0", + "description": "NanoForge Engine - Graphics 2D", + "homepage": "https://github.com/NanoForge-dev/Engine#readme", + "license": "MIT", + "contributors": [ + "Bill", + "Exelo", + "Fexkoser", + "Tchips" + ], + "funding": { + "type": "individual", + "url": "" + }, + "type": "module", + "main": "src/index.ts", + "repository": { + "type": "git", + "url": "git+https://github.com/NanoForge-dev/Engine.git", + "directory": "packages/graphics-2d" + }, + "scripts": { + "build": "tsc -b .", + "clean": "pnpm clean:types && pnpm clean:scripts && rm -f tsconfig.build.tsbuildinfo", + "clean:types": "find src -name '*.d.ts' -delete", + "clean:scripts": "find src -name '*.js' -delete", + "lint": "eslint . && prettier --check .", + "fix": "eslint . --fix && prettier --write .", + "taze": "taze major -w", + "lint-staged": "lint-staged", + "test:unit": "jest --config ./jest.config.json" + }, + "dependencies": { + "@nanoforge/common": "workspace:^" + }, + "devDependencies": { + "@commitlint/cli": "^19.8.0", + "@commitlint/config-conventional": "^19.8.0", + "@eslint/js": "^9.22.0", + "@trivago/prettier-plugin-sort-imports": "^5.2.2", + "@types/jest": "^29.5.14", + "@types/node": "^22.13.10", + "eslint": "^9.22.0", + "eslint-config-prettier": "^10.1.1", + "eslint-plugin-format": "^1.0.1", + "eslint-plugin-jest": "^28.11.0", + "eslint-plugin-prettier": "^5.2.3", + "globals": "^16.0.0", + "jest": "^29.7.0", + "lint-staged": "^15.4.3", + "prettier": "^3.5.3", + "ts-jest": "^29.2.6", + "typescript": "^5.8.2", + "typescript-eslint": "^8.26.0" + }, + "engines": { + "node": "23.6.0", + "pnpm": "10.6.2" + }, + "lint-staged": { + "**/*.{js,ts}": [ + "eslint --fix", + "prettier --write" + ] + } +} diff --git a/packages/graphics-2d/src/graphics-2d.library.ts b/packages/graphics-2d/src/graphics-2d.library.ts new file mode 100644 index 00000000..c3f92861 --- /dev/null +++ b/packages/graphics-2d/src/graphics-2d.library.ts @@ -0,0 +1,17 @@ +import { BaseGraphicsLibrary, type ExecutionContext, type InitContext } from "@nanoforge/common"; + +export class Graphics2DLibrary extends BaseGraphicsLibrary { + get name(): string { + return "Graphics2DLibrary"; + } + + public async init(context: InitContext): Promise { + if (!context.canvas) { + throw new Error("Can't initialize the canvas context"); + } + } + + public async run(context: ExecutionContext): Promise { + console.log(context); + } +} diff --git a/packages/graphics-2d/src/index.ts b/packages/graphics-2d/src/index.ts new file mode 100644 index 00000000..3fbf8410 --- /dev/null +++ b/packages/graphics-2d/src/index.ts @@ -0,0 +1 @@ +export { Graphics2DLibrary } from "./graphics-2d.library"; diff --git a/packages/graphics-2d/test/graphics-2d.library.spec.ts b/packages/graphics-2d/test/graphics-2d.library.spec.ts new file mode 100644 index 00000000..f9175281 --- /dev/null +++ b/packages/graphics-2d/test/graphics-2d.library.spec.ts @@ -0,0 +1,21 @@ +import { ApplicationContext, InitContext, LibraryManager } from "@nanoforge/common"; + +import { Graphics2DLibrary } from "../src"; + +describe("Graphics 2D Library", () => { + const library = new Graphics2DLibrary(); + const appContext = new ApplicationContext(); + const libraryManager = new LibraryManager(); + const context = new InitContext(appContext, libraryManager, { + // @ts-ignore + canvas: null, + files: { + assets: new Map([["/test.png", "blob:http://localhost:3000/test.png"]]), + scripts: new Map([["/test.wasm", "blob:http://localhost:3000/test.wasm"]]), + }, + }); + + it("Should throw if canvas is undefined", async () => { + await expect(library.init(context)).rejects.toThrow(); + }); +}); diff --git a/packages/graphics-2d/test/tsconfig.json b/packages/graphics-2d/test/tsconfig.json new file mode 100644 index 00000000..50d59661 --- /dev/null +++ b/packages/graphics-2d/test/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../../../tsconfig.spec.json" +} diff --git a/packages/graphics-2d/tsconfig.build.json b/packages/graphics-2d/tsconfig.build.json new file mode 100644 index 00000000..2e31798e --- /dev/null +++ b/packages/graphics-2d/tsconfig.build.json @@ -0,0 +1,17 @@ +{ + "extends": "../tsconfig.build.json", + "compilerOptions": { + "outDir": ".", + "rootDir": ".", + "paths": { + "@nanoforge/common": ["../common"], + "@nanoforge/common/*": ["../common/*"] + } + }, + "exclude": ["node_modules", "dist", "test/**/*", "*.spec.ts"], + "references": [ + { + "path": "../common/tsconfig.build.json" + } + ] +} diff --git a/packages/graphics-2d/tsconfig.json b/packages/graphics-2d/tsconfig.json new file mode 100644 index 00000000..a74c8e2d --- /dev/null +++ b/packages/graphics-2d/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../tsconfig.build.json", + "compilerOptions": { + "types": ["jest", "node"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.build.json" + } + ] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fcdcfb87..59768455 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -261,6 +261,67 @@ importers: specifier: ^8.26.0 version: 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2) + packages/graphics-2d: + dependencies: + '@nanoforge/common': + specifier: workspace:^ + version: link:../common + devDependencies: + '@commitlint/cli': + specifier: ^19.8.0 + version: 19.8.0(@types/node@22.13.10)(typescript@5.8.2) + '@commitlint/config-conventional': + specifier: ^19.8.0 + version: 19.8.0 + '@eslint/js': + specifier: ^9.22.0 + version: 9.22.0 + '@trivago/prettier-plugin-sort-imports': + specifier: ^5.2.2 + version: 5.2.2(prettier@3.5.3) + '@types/jest': + specifier: ^29.5.14 + version: 29.5.14 + '@types/node': + specifier: ^22.13.10 + version: 22.13.10 + eslint: + specifier: ^9.22.0 + version: 9.22.0(jiti@2.4.2) + eslint-config-prettier: + specifier: ^10.1.1 + version: 10.1.1(eslint@9.22.0(jiti@2.4.2)) + eslint-plugin-format: + specifier: ^1.0.1 + version: 1.0.1(eslint@9.22.0(jiti@2.4.2)) + eslint-plugin-jest: + specifier: ^28.11.0 + version: 28.11.0(@typescript-eslint/eslint-plugin@8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(jest@29.7.0(@types/node@22.13.10))(typescript@5.8.2) + eslint-plugin-prettier: + specifier: ^5.2.3 + version: 5.2.3(eslint-config-prettier@10.1.1(eslint@9.22.0(jiti@2.4.2)))(eslint@9.22.0(jiti@2.4.2))(prettier@3.5.3) + globals: + specifier: ^16.0.0 + version: 16.0.0 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@22.13.10) + lint-staged: + specifier: ^15.4.3 + version: 15.4.3 + prettier: + specifier: ^3.5.3 + version: 3.5.3 + ts-jest: + specifier: ^29.2.6 + version: 29.2.6(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(jest@29.7.0(@types/node@22.13.10))(typescript@5.8.2) + typescript: + specifier: ^5.8.2 + version: 5.8.2 + typescript-eslint: + specifier: ^8.26.0 + version: 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2) + packages: '@ampproject/remapping@2.3.0': From 1ab1a4db94c36be882ae3aba9c66de684fb129c8 Mon Sep 17 00:00:00 2001 From: Exelo Date: Mon, 17 Mar 2025 15:14:30 +0100 Subject: [PATCH 2/5] feat(asset-manager): add wgsl handling --- .../src/asset-manager.library.ts | 19 +++++++++++--- .../test/asset-manager.library.spec.ts | 25 +++++++++++++------ .../asset-manager.library.abstract.ts | 4 ++- .../finals/asset-manager.library.type.ts | 4 ++- .../common/src/options/types/options.type.ts | 3 ++- 5 files changed, 41 insertions(+), 14 deletions(-) diff --git a/packages/asset-manager/src/asset-manager.library.ts b/packages/asset-manager/src/asset-manager.library.ts index 00326337..39b6f8a7 100644 --- a/packages/asset-manager/src/asset-manager.library.ts +++ b/packages/asset-manager/src/asset-manager.library.ts @@ -2,7 +2,8 @@ import { BaseAssetManagerLibrary, type InitContext } from "@nanoforge/common"; export class AssetManagerLibrary extends BaseAssetManagerLibrary { private _assets: Map; - private _scripts: Map; + private _wasm: Map; + private _wgsl: Map; get name(): string { return "AssetManagerLibrary"; @@ -10,7 +11,8 @@ export class AssetManagerLibrary extends BaseAssetManagerLibrary { public async init(context: InitContext): Promise { this._assets = context.files.assets; - this._scripts = context.files.scripts; + this._wasm = context.files.wasm; + this._wgsl = context.files.wgsl; } /** @@ -25,8 +27,17 @@ export class AssetManagerLibrary extends BaseAssetManagerLibrary { /** * @todo Error management */ - public async getScript(path: string): Promise { - const res = this._scripts.get(this._parsePath(path)); + public async getWasm(path: string): Promise { + const res = this._wasm.get(this._parsePath(path)); + if (!res) throw new Error("Asset not found."); + return res; + } + + /** + * @todo Error management + */ + public async getWgsl(path: string): Promise { + const res = this._wgsl.get(this._parsePath(path)); if (!res) throw new Error("Asset not found."); return res; } diff --git a/packages/asset-manager/test/asset-manager.library.spec.ts b/packages/asset-manager/test/asset-manager.library.spec.ts index 30fe7b10..9c246c78 100644 --- a/packages/asset-manager/test/asset-manager.library.spec.ts +++ b/packages/asset-manager/test/asset-manager.library.spec.ts @@ -11,28 +11,39 @@ describe("Asset Manager Library", () => { canvas: null, files: { assets: new Map([["/test.png", "blob:http://localhost:3000/test.png"]]), - scripts: new Map([["/test.wasm", "blob:http://localhost:3000/test.wasm"]]), + wasm: new Map([["/test.wasm", "blob:http://localhost:3000/test.wasm"]]), + wgsl: new Map([["/test.wgsl", "blob:http://localhost:3000/test.wgsl"]]), }, }); library.init(context); - it("Test get asset", async () => { + it("Should get asset", async () => { await expect(library.getAsset("test.png")).resolves.toEqual( "blob:http://localhost:3000/test.png", ); }); - it("Test get unknown asset", async () => { + it("Should throw on unknown asset", async () => { await expect(library.getAsset("test-unknown.png")).rejects.toThrow(); }); - it("Test get script", async () => { - await expect(library.getScript("test.wasm")).resolves.toEqual( + it("Should get wasm", async () => { + await expect(library.getWasm("test.wasm")).resolves.toEqual( "blob:http://localhost:3000/test.wasm", ); }); - it("Test get unknown script", async () => { - await expect(library.getScript("test-unknown.wasm")).rejects.toThrow(); + it("Should throw on unknown wasm", async () => { + await expect(library.getWasm("test-unknown.wasm")).rejects.toThrow(); + }); + + it("Should get wgsl", async () => { + await expect(library.getWgsl("test.wgsl")).resolves.toEqual( + "blob:http://localhost:3000/test.wgsl", + ); + }); + + it("Should throw on unknown wgsl", async () => { + await expect(library.getWgsl("test-unknown.wgsl")).rejects.toThrow(); }); }); diff --git a/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts b/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts index 58190ce9..804578d7 100644 --- a/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts +++ b/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts @@ -7,5 +7,7 @@ export abstract class BaseAssetManagerLibrary extends Library implements IAssetM public abstract getAsset(path: string): Promise; - public abstract getScript(path: string): Promise; + public abstract getWasm(path: string): Promise; + + public abstract getWgsl(path: string): Promise; } diff --git a/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts index 61f2f7dc..f29f1fd1 100644 --- a/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts +++ b/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts @@ -3,5 +3,7 @@ import { type IExposedLibrary } from "../bases/exposed.library.type"; export interface IAssetManagerLibrary extends IExposedLibrary { getAsset(path: string): Promise; - getScript(path: string): Promise; + getWasm(path: string): Promise; + + getWgsl(path: string): Promise; } diff --git a/packages/common/src/options/types/options.type.ts b/packages/common/src/options/types/options.type.ts index b3cd5918..b0a02e36 100644 --- a/packages/common/src/options/types/options.type.ts +++ b/packages/common/src/options/types/options.type.ts @@ -2,6 +2,7 @@ export interface IRunOptions { canvas: HTMLCanvasElement; files: { assets: Map; - scripts: Map; + wasm: Map; + wgsl: Map; }; } From 91709a8bda7175f934c0e969de5e5760b6f121f9 Mon Sep 17 00:00:00 2001 From: Exelo Date: Tue, 18 Mar 2025 12:02:05 +0100 Subject: [PATCH 3/5] feat(asset-manager): add file return --- .../src/asset-manager.library.ts | 14 ++++++++------ packages/asset-manager/src/file.ts | 19 +++++++++++++++++++ packages/asset-manager/src/index.ts | 1 + .../asset-manager.library.abstract.ts | 8 ++++---- .../finals/asset-manager.library.type.ts | 12 +++++++++--- .../src/library/libraries/interfaces/index.ts | 2 +- 6 files changed, 42 insertions(+), 14 deletions(-) create mode 100644 packages/asset-manager/src/file.ts diff --git a/packages/asset-manager/src/asset-manager.library.ts b/packages/asset-manager/src/asset-manager.library.ts index 39b6f8a7..81fa345d 100644 --- a/packages/asset-manager/src/asset-manager.library.ts +++ b/packages/asset-manager/src/asset-manager.library.ts @@ -1,5 +1,7 @@ import { BaseAssetManagerLibrary, type InitContext } from "@nanoforge/common"; +import { NfFile } from "./file"; + export class AssetManagerLibrary extends BaseAssetManagerLibrary { private _assets: Map; private _wasm: Map; @@ -18,28 +20,28 @@ export class AssetManagerLibrary extends BaseAssetManagerLibrary { /** * @todo Error management */ - public async getAsset(path: string): Promise { + public async getAsset(path: string): Promise { const res = this._assets.get(this._parsePath(path)); if (!res) throw new Error("Asset not found."); - return res; + return new NfFile(res); } /** * @todo Error management */ - public async getWasm(path: string): Promise { + public async getWasm(path: string): Promise { const res = this._wasm.get(this._parsePath(path)); if (!res) throw new Error("Asset not found."); - return res; + return new NfFile(res); } /** * @todo Error management */ - public async getWgsl(path: string): Promise { + public async getWgsl(path: string): Promise { const res = this._wgsl.get(this._parsePath(path)); if (!res) throw new Error("Asset not found."); - return res; + return new NfFile(res); } private _parsePath(path: string): string { diff --git a/packages/asset-manager/src/file.ts b/packages/asset-manager/src/file.ts new file mode 100644 index 00000000..849456f1 --- /dev/null +++ b/packages/asset-manager/src/file.ts @@ -0,0 +1,19 @@ +import { type IFile } from "@nanoforge/common"; + +export class NfFile implements IFile { + private readonly _path: string; + + constructor(path: string) { + this._path = path; + } + + get path(): string { + return this._path; + } + + public async getText(): Promise { + const res = await fetch(this._path); + if (!res.ok) throw new Error(`${res.status} ${res.statusText}`); + return await res.text(); + } +} diff --git a/packages/asset-manager/src/index.ts b/packages/asset-manager/src/index.ts index b1ecb3a3..d3725508 100644 --- a/packages/asset-manager/src/index.ts +++ b/packages/asset-manager/src/index.ts @@ -1 +1,2 @@ export { AssetManagerLibrary } from "./asset-manager.library"; +export { NfFile } from "./file"; diff --git a/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts b/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts index 804578d7..4270e47c 100644 --- a/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts +++ b/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts @@ -1,13 +1,13 @@ import { type InitContext } from "../../../context"; -import type { IAssetManagerLibrary } from "../interfaces"; +import { type IAssetManagerLibrary, type IFile } from "../interfaces"; import { Library } from "../library"; export abstract class BaseAssetManagerLibrary extends Library implements IAssetManagerLibrary { public abstract init(context: InitContext): Promise; - public abstract getAsset(path: string): Promise; + public abstract getAsset(path: string): Promise; - public abstract getWasm(path: string): Promise; + public abstract getWasm(path: string): Promise; - public abstract getWgsl(path: string): Promise; + public abstract getWgsl(path: string): Promise; } diff --git a/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts index f29f1fd1..28ad944f 100644 --- a/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts +++ b/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts @@ -1,9 +1,15 @@ import { type IExposedLibrary } from "../bases/exposed.library.type"; +export interface IFile { + get path(): string; + + getText(): Promise; +} + export interface IAssetManagerLibrary extends IExposedLibrary { - getAsset(path: string): Promise; + getAsset(path: string): Promise; - getWasm(path: string): Promise; + getWasm(path: string): Promise; - getWgsl(path: string): Promise; + getWgsl(path: string): Promise; } diff --git a/packages/common/src/library/libraries/interfaces/index.ts b/packages/common/src/library/libraries/interfaces/index.ts index 1f1aea24..19028c01 100644 --- a/packages/common/src/library/libraries/interfaces/index.ts +++ b/packages/common/src/library/libraries/interfaces/index.ts @@ -1,6 +1,6 @@ export { IExposedLibrary } from "./bases/exposed.library.type"; export { IRunnerLibrary } from "./bases/runner.library.type"; -export { IAssetManagerLibrary } from "./finals/asset-manager.library.type"; +export { IAssetManagerLibrary, IFile } from "./finals/asset-manager.library.type"; export { IComponentSystemLibrary } from "./finals/component-system.library.type"; export { IGraphicsLibrary } from "./finals/graphics.library.type"; export { INetworkLibrary } from "./finals/network.library.type"; From 59e91f45fbe8bbdbe6afbdd3e1e385e9cf60ffc8 Mon Sep 17 00:00:00 2001 From: Exelo Date: Tue, 18 Mar 2025 12:31:09 +0100 Subject: [PATCH 4/5] feat(common): add templates to each get library functions --- .../asset-manager.library.abstract.ts | 8 +------- .../finals/asset-manager.library.type.ts | 14 +------------ .../manager/managers/base-library.manager.ts | 4 ++-- .../manager/managers/library.manager.ts | 20 +++++++++++-------- 4 files changed, 16 insertions(+), 30 deletions(-) diff --git a/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts b/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts index 4270e47c..6f6d027b 100644 --- a/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts +++ b/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts @@ -1,13 +1,7 @@ import { type InitContext } from "../../../context"; -import { type IAssetManagerLibrary, type IFile } from "../interfaces"; +import { type IAssetManagerLibrary } from "../interfaces"; import { Library } from "../library"; export abstract class BaseAssetManagerLibrary extends Library implements IAssetManagerLibrary { public abstract init(context: InitContext): Promise; - - public abstract getAsset(path: string): Promise; - - public abstract getWasm(path: string): Promise; - - public abstract getWgsl(path: string): Promise; } diff --git a/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts index 28ad944f..7348904f 100644 --- a/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts +++ b/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts @@ -1,15 +1,3 @@ import { type IExposedLibrary } from "../bases/exposed.library.type"; -export interface IFile { - get path(): string; - - getText(): Promise; -} - -export interface IAssetManagerLibrary extends IExposedLibrary { - getAsset(path: string): Promise; - - getWasm(path: string): Promise; - - getWgsl(path: string): Promise; -} +export interface IAssetManagerLibrary extends IExposedLibrary {} diff --git a/packages/common/src/library/manager/managers/base-library.manager.ts b/packages/common/src/library/manager/managers/base-library.manager.ts index cb52eecc..418e6078 100644 --- a/packages/common/src/library/manager/managers/base-library.manager.ts +++ b/packages/common/src/library/manager/managers/base-library.manager.ts @@ -1,5 +1,5 @@ import { type LibraryContext } from "../../../context"; -import { type ILibrary } from "../../libraries/library.type"; +import { type ILibrary } from "../../libraries"; import { LibraryHandle } from "../handle/library.handle"; export class BaseLibraryManager { @@ -11,7 +11,7 @@ export class BaseLibraryManager { /** * @todo Add error management */ - public get(sym: symbol): LibraryHandle { + public get(sym: symbol): LibraryHandle { const index = this._librariesIndex[sym]; if (!index) throw new Error(`Library not found: ${Symbol.keyFor(sym)}`); return this._get(index, sym); diff --git a/packages/common/src/library/manager/managers/library.manager.ts b/packages/common/src/library/manager/managers/library.manager.ts index 52a85d99..94969dd7 100644 --- a/packages/common/src/library/manager/managers/library.manager.ts +++ b/packages/common/src/library/manager/managers/library.manager.ts @@ -34,19 +34,23 @@ export class LibraryManager extends BaseLibraryManager { } } - public getComponentSystem(): LibraryHandle { - return this._get(DefaultLibrariesEnum.COMPONENT_SYSTEM); + public getComponentSystem< + T extends IComponentSystemLibrary = IComponentSystemLibrary, + >(): LibraryHandle { + return this._get(DefaultLibrariesEnum.COMPONENT_SYSTEM); } - public getGraphics(): LibraryHandle { - return this._get(DefaultLibrariesEnum.GRAPHICS); + public getGraphics(): LibraryHandle { + return this._get(DefaultLibrariesEnum.GRAPHICS); } - public getNetwork(): LibraryHandle { - return this._get(DefaultLibrariesEnum.NETWORK); + public getNetwork(): LibraryHandle { + return this._get(DefaultLibrariesEnum.NETWORK); } - public getAssetManager(): LibraryHandle { - return this._get(DefaultLibrariesEnum.ASSET_MANAGER); + public getAssetManager< + T extends IAssetManagerLibrary = IAssetManagerLibrary, + >(): LibraryHandle { + return this._get(DefaultLibrariesEnum.ASSET_MANAGER); } } From 0dc754adc4ad33e371b58a67ef15cc522a326b8c Mon Sep 17 00:00:00 2001 From: Exelo Date: Tue, 18 Mar 2025 16:15:16 +0100 Subject: [PATCH 5/5] chore: add current state of graphics library --- packages/graphics-2d/package.json | 2 + .../src/components/shape/common/shape.ts | 10 ++++ .../components/shape/shapes/circle.shape.ts | 29 ++++++++++ packages/graphics-2d/src/components/window.ts | 3 + packages/graphics-2d/src/core.ts | 56 +++++++++++++++++++ .../graphics-2d/src/graphics-2d.library.ts | 4 ++ packages/graphics-2d/src/index.ts | 3 + packages/graphics-2d/src/render.ts | 29 ++++++++++ .../graphics-2d/src/shader/shader.manager.ts | 46 +++++++++++++++ .../graphics-2d/src/shader/shaders.const.ts | 11 ++++ .../graphics-2d/src/shader/shaders.enum.ts | 4 ++ .../graphics-2d/src/shader/shaders/index.ts | 0 .../src/types/common/color.type.ts | 6 ++ .../graphics-2d/src/types/common/index.ts | 4 ++ .../graphics-2d/src/types/common/size.type.ts | 4 ++ .../src/types/common/vertex-2d.type.ts | 4 ++ .../src/types/common/vertex-4d.type.ts | 6 ++ packages/graphics-2d/src/types/index.ts | 2 + .../src/types/options/base/color.type.ts | 5 ++ .../src/types/options/base/position.type.ts | 5 ++ .../src/types/options/base/size.type.ts | 5 ++ .../options/final/circle-options.type.ts | 6 ++ .../src/types/options/final/index.ts | 3 + .../options/final/rectangle-options.type.ts | 5 ++ .../final/rounded-rectangle-options.type.ts | 5 ++ .../graphics-2d/src/types/options/index.ts | 1 + packages/graphics-2d/src/utils/string.ts | 7 +++ packages/graphics-2d/tsconfig.build.json | 8 ++- pnpm-lock.yaml | 11 ++++ 29 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 packages/graphics-2d/src/components/shape/common/shape.ts create mode 100644 packages/graphics-2d/src/components/shape/shapes/circle.shape.ts create mode 100644 packages/graphics-2d/src/components/window.ts create mode 100644 packages/graphics-2d/src/core.ts create mode 100644 packages/graphics-2d/src/render.ts create mode 100644 packages/graphics-2d/src/shader/shader.manager.ts create mode 100644 packages/graphics-2d/src/shader/shaders.const.ts create mode 100644 packages/graphics-2d/src/shader/shaders.enum.ts create mode 100644 packages/graphics-2d/src/shader/shaders/index.ts create mode 100644 packages/graphics-2d/src/types/common/color.type.ts create mode 100644 packages/graphics-2d/src/types/common/index.ts create mode 100644 packages/graphics-2d/src/types/common/size.type.ts create mode 100644 packages/graphics-2d/src/types/common/vertex-2d.type.ts create mode 100644 packages/graphics-2d/src/types/common/vertex-4d.type.ts create mode 100644 packages/graphics-2d/src/types/index.ts create mode 100644 packages/graphics-2d/src/types/options/base/color.type.ts create mode 100644 packages/graphics-2d/src/types/options/base/position.type.ts create mode 100644 packages/graphics-2d/src/types/options/base/size.type.ts create mode 100644 packages/graphics-2d/src/types/options/final/circle-options.type.ts create mode 100644 packages/graphics-2d/src/types/options/final/index.ts create mode 100644 packages/graphics-2d/src/types/options/final/rectangle-options.type.ts create mode 100644 packages/graphics-2d/src/types/options/final/rounded-rectangle-options.type.ts create mode 100644 packages/graphics-2d/src/types/options/index.ts create mode 100644 packages/graphics-2d/src/utils/string.ts diff --git a/packages/graphics-2d/package.json b/packages/graphics-2d/package.json index f4d5393f..d637e565 100644 --- a/packages/graphics-2d/package.json +++ b/packages/graphics-2d/package.json @@ -33,6 +33,7 @@ "test:unit": "jest --config ./jest.config.json" }, "dependencies": { + "@nanoforge/asset-manager": "workspace:^", "@nanoforge/common": "workspace:^" }, "devDependencies": { @@ -42,6 +43,7 @@ "@trivago/prettier-plugin-sort-imports": "^5.2.2", "@types/jest": "^29.5.14", "@types/node": "^22.13.10", + "@webgpu/types": "^0.1.56", "eslint": "^9.22.0", "eslint-config-prettier": "^10.1.1", "eslint-plugin-format": "^1.0.1", diff --git a/packages/graphics-2d/src/components/shape/common/shape.ts b/packages/graphics-2d/src/components/shape/common/shape.ts new file mode 100644 index 00000000..1e3ba8c1 --- /dev/null +++ b/packages/graphics-2d/src/components/shape/common/shape.ts @@ -0,0 +1,10 @@ +import { type GraphicsCore } from "../../../core"; +import { type ShaderManager } from "../../../shader/shader.manager"; + +export class NfShape { + private readonly _shaderManager: ShaderManager; + + constructor(core: GraphicsCore) { + this._shaderManager = core.shaderManager; + } +} diff --git a/packages/graphics-2d/src/components/shape/shapes/circle.shape.ts b/packages/graphics-2d/src/components/shape/shapes/circle.shape.ts new file mode 100644 index 00000000..b0b7fa59 --- /dev/null +++ b/packages/graphics-2d/src/components/shape/shapes/circle.shape.ts @@ -0,0 +1,29 @@ +import { type GraphicsCore } from "../../../core"; +import { type ICircleOptions, type IColor, type IVertex2D } from "../../../types"; +import { NfShape } from "../common/shape"; + +export class NfCircle extends NfShape { + private _pos: IVertex2D; + private _radius: number; + private _color: IColor; + + constructor(core: GraphicsCore, options?: Partial) { + super(core); + + this._pos = options?.pos ?? { x: 0, y: 0 }; + this._radius = options?.radius ?? 1; + this._color = options?.color ?? { r: 0, g: 0, b: 0, a: 1 }; + } + + public setPosition(pos: IVertex2D): void { + this._pos = pos; + } + + public setRadius(radius: number): void { + this._radius = radius; + } + + public setColor(color: IColor): void { + this._color = color; + } +} diff --git a/packages/graphics-2d/src/components/window.ts b/packages/graphics-2d/src/components/window.ts new file mode 100644 index 00000000..acefd29b --- /dev/null +++ b/packages/graphics-2d/src/components/window.ts @@ -0,0 +1,3 @@ +export class Window { + public render() {} +} diff --git a/packages/graphics-2d/src/core.ts b/packages/graphics-2d/src/core.ts new file mode 100644 index 00000000..2a19e936 --- /dev/null +++ b/packages/graphics-2d/src/core.ts @@ -0,0 +1,56 @@ +import { type InitContext } from "@nanoforge/common"; + +import { GraphicsRender } from "./render"; +import { ShaderManager } from "./shader/shader.manager"; + +export class GraphicsCore { + private readonly _initContext: InitContext; + + private readonly _shaderManager: ShaderManager; + private _render: GraphicsRender; + + private _adapter: GPUAdapter; + private _device: GPUDevice; + + constructor(context: InitContext) { + this._initContext = context; + + this._shaderManager = new ShaderManager(this); + } + + get initContext(): InitContext { + return this._initContext; + } + + get adapter(): GPUAdapter { + return this._adapter; + } + + get device(): GPUDevice { + return this._device; + } + + get shaderManager(): ShaderManager { + return this._shaderManager; + } + + public async init(): Promise { + if (!navigator.gpu) { + throw new Error("WebGPU not supported on this browser."); + } + + const adapter = await navigator.gpu.requestAdapter(); + if (!adapter) { + throw new Error("No appropriate GPUAdapter found."); + } + this._adapter = adapter; + + const device = await this._adapter.requestDevice(); + if (!device) { + throw new Error("No appropriate GPUDevice found."); + } + this._device = device; + + this._render = new GraphicsRender(this, this._initContext); + } +} diff --git a/packages/graphics-2d/src/graphics-2d.library.ts b/packages/graphics-2d/src/graphics-2d.library.ts index c3f92861..207639ce 100644 --- a/packages/graphics-2d/src/graphics-2d.library.ts +++ b/packages/graphics-2d/src/graphics-2d.library.ts @@ -1,5 +1,7 @@ import { BaseGraphicsLibrary, type ExecutionContext, type InitContext } from "@nanoforge/common"; +import { type ICircleOptions } from "./types"; + export class Graphics2DLibrary extends BaseGraphicsLibrary { get name(): string { return "Graphics2DLibrary"; @@ -11,6 +13,8 @@ export class Graphics2DLibrary extends BaseGraphicsLibrary { } } + public createCircle(options: ICircleOptions): void {} + public async run(context: ExecutionContext): Promise { console.log(context); } diff --git a/packages/graphics-2d/src/index.ts b/packages/graphics-2d/src/index.ts index 3fbf8410..13807318 100644 --- a/packages/graphics-2d/src/index.ts +++ b/packages/graphics-2d/src/index.ts @@ -1 +1,4 @@ +import "./shader/shaders"; + +export * from "./types"; export { Graphics2DLibrary } from "./graphics-2d.library"; diff --git a/packages/graphics-2d/src/render.ts b/packages/graphics-2d/src/render.ts new file mode 100644 index 00000000..01625050 --- /dev/null +++ b/packages/graphics-2d/src/render.ts @@ -0,0 +1,29 @@ +import { type InitContext } from "@nanoforge/common"; + +import { type GraphicsCore } from "./core"; + +export class GraphicsRender { + private readonly _core: GraphicsCore; + private readonly _canvas: HTMLCanvasElement; + private readonly _canvasContext: GPUCanvasContext; + private readonly _canvasFormat: GPUTextureFormat; + + constructor(core: GraphicsCore, initContext: InitContext) { + this._core = core; + + this._canvas = initContext.canvas; + + const context = initContext.canvas.getContext("webgpu"); + if (!context) { + throw new Error("Could not get canvas context."); + } + this._canvasContext = context; + + this._canvasFormat = navigator.gpu.getPreferredCanvasFormat(); + + this._canvasContext.configure({ + device: this._core.device, + format: this._canvasFormat, + }); + } +} diff --git a/packages/graphics-2d/src/shader/shader.manager.ts b/packages/graphics-2d/src/shader/shader.manager.ts new file mode 100644 index 00000000..d21c84ca --- /dev/null +++ b/packages/graphics-2d/src/shader/shader.manager.ts @@ -0,0 +1,46 @@ +import { type AssetManagerLibrary } from "@nanoforge/asset-manager"; + +import { type GraphicsCore } from "../core"; +import { SHADER_NAMES, SHADER_PATHS } from "./shaders.const"; +import { type ShadersEnum } from "./shaders.enum"; + +export class ShaderManager { + private _core: GraphicsCore; + private _assetManager: AssetManagerLibrary; + private _shaders: Map; + + constructor(core: GraphicsCore) { + this._core = core; + this._assetManager = + this._core.initContext.libraries.getAssetManager().library; + this._shaders = new Map(); + } + + /** + * @todo Error handling + */ + public async get(shader: ShadersEnum, reftech = true): Promise { + const res = this._shaders.get(shader); + if (!res) { + if (!reftech) throw new Error("Could not find shader"); + await this._loadShader(shader); + return this.get(shader, false); + } + return res; + } + + /** + * @todo Error handling + */ + private async _loadShader(shader: ShadersEnum): Promise { + const path = SHADER_PATHS[shader]; + if (!path) { + throw new Error("Could not find shader"); + } + const shaderFile = await this._assetManager.getWgsl(path); + this._core.device.createShaderModule({ + label: SHADER_NAMES[shader], + code: await shaderFile.getText(), + }); + } +} diff --git a/packages/graphics-2d/src/shader/shaders.const.ts b/packages/graphics-2d/src/shader/shaders.const.ts new file mode 100644 index 00000000..a6b7aea0 --- /dev/null +++ b/packages/graphics-2d/src/shader/shaders.const.ts @@ -0,0 +1,11 @@ +import { ShadersEnum } from "./shaders.enum"; + +export const SHADER_PATHS: Record = { + [ShadersEnum.RECTANGLE]: "rectangle.wgsl", + [ShadersEnum.CIRCLE]: "circle.wgsl", +}; + +export const SHADER_NAMES: Record = { + [ShadersEnum.RECTANGLE]: "Rectangle shader", + [ShadersEnum.CIRCLE]: "Rectangle shader", +}; diff --git a/packages/graphics-2d/src/shader/shaders.enum.ts b/packages/graphics-2d/src/shader/shaders.enum.ts new file mode 100644 index 00000000..d65b22f8 --- /dev/null +++ b/packages/graphics-2d/src/shader/shaders.enum.ts @@ -0,0 +1,4 @@ +export enum ShadersEnum { + RECTANGLE = 0, + CIRCLE = 1, +} diff --git a/packages/graphics-2d/src/shader/shaders/index.ts b/packages/graphics-2d/src/shader/shaders/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/graphics-2d/src/types/common/color.type.ts b/packages/graphics-2d/src/types/common/color.type.ts new file mode 100644 index 00000000..a5bc4c55 --- /dev/null +++ b/packages/graphics-2d/src/types/common/color.type.ts @@ -0,0 +1,6 @@ +export interface IColor { + r: number; + g: number; + b: number; + a: number; +} diff --git a/packages/graphics-2d/src/types/common/index.ts b/packages/graphics-2d/src/types/common/index.ts new file mode 100644 index 00000000..84737ae5 --- /dev/null +++ b/packages/graphics-2d/src/types/common/index.ts @@ -0,0 +1,4 @@ +export { IColor } from "./color.type"; +export { ISize } from "./size.type"; +export { IVertex2D } from "./vertex-2d.type"; +export { IVertex4D } from "./vertex-4d.type"; diff --git a/packages/graphics-2d/src/types/common/size.type.ts b/packages/graphics-2d/src/types/common/size.type.ts new file mode 100644 index 00000000..8264d49c --- /dev/null +++ b/packages/graphics-2d/src/types/common/size.type.ts @@ -0,0 +1,4 @@ +export interface ISize { + height: number; + width: number; +} diff --git a/packages/graphics-2d/src/types/common/vertex-2d.type.ts b/packages/graphics-2d/src/types/common/vertex-2d.type.ts new file mode 100644 index 00000000..4f4cc744 --- /dev/null +++ b/packages/graphics-2d/src/types/common/vertex-2d.type.ts @@ -0,0 +1,4 @@ +export interface IVertex2D { + x: number; + y: number; +} diff --git a/packages/graphics-2d/src/types/common/vertex-4d.type.ts b/packages/graphics-2d/src/types/common/vertex-4d.type.ts new file mode 100644 index 00000000..c24bf2d3 --- /dev/null +++ b/packages/graphics-2d/src/types/common/vertex-4d.type.ts @@ -0,0 +1,6 @@ +export interface IVertex4D { + x: number; + y: number; + z: number; + w: number; +} diff --git a/packages/graphics-2d/src/types/index.ts b/packages/graphics-2d/src/types/index.ts new file mode 100644 index 00000000..3f4c0d3a --- /dev/null +++ b/packages/graphics-2d/src/types/index.ts @@ -0,0 +1,2 @@ +export * from "./common"; +export * from "./options"; diff --git a/packages/graphics-2d/src/types/options/base/color.type.ts b/packages/graphics-2d/src/types/options/base/color.type.ts new file mode 100644 index 00000000..33a37737 --- /dev/null +++ b/packages/graphics-2d/src/types/options/base/color.type.ts @@ -0,0 +1,5 @@ +import { type IColor } from "../../common"; + +export interface IColorOption { + color: IColor; +} diff --git a/packages/graphics-2d/src/types/options/base/position.type.ts b/packages/graphics-2d/src/types/options/base/position.type.ts new file mode 100644 index 00000000..b46070f2 --- /dev/null +++ b/packages/graphics-2d/src/types/options/base/position.type.ts @@ -0,0 +1,5 @@ +import { type IVertex2D } from "../../common"; + +export interface IPositionOption { + pos: IVertex2D; +} diff --git a/packages/graphics-2d/src/types/options/base/size.type.ts b/packages/graphics-2d/src/types/options/base/size.type.ts new file mode 100644 index 00000000..a455eb8d --- /dev/null +++ b/packages/graphics-2d/src/types/options/base/size.type.ts @@ -0,0 +1,5 @@ +import { type ISize } from "../../common"; + +export interface ISizeOption { + size: ISize; +} diff --git a/packages/graphics-2d/src/types/options/final/circle-options.type.ts b/packages/graphics-2d/src/types/options/final/circle-options.type.ts new file mode 100644 index 00000000..c0af50ce --- /dev/null +++ b/packages/graphics-2d/src/types/options/final/circle-options.type.ts @@ -0,0 +1,6 @@ +import { type IColorOption } from "../base/color.type"; +import { type IPositionOption } from "../base/position.type"; + +export interface ICircleOptions extends IColorOption, IPositionOption { + radius: number; +} diff --git a/packages/graphics-2d/src/types/options/final/index.ts b/packages/graphics-2d/src/types/options/final/index.ts new file mode 100644 index 00000000..d9c15e8e --- /dev/null +++ b/packages/graphics-2d/src/types/options/final/index.ts @@ -0,0 +1,3 @@ +export { ICircleOptions } from "./circle-options.type"; +export { IRectangleOptions } from "./rectangle-options.type"; +export { IRoundedRectangleOptions } from "./rounded-rectangle-options.type"; diff --git a/packages/graphics-2d/src/types/options/final/rectangle-options.type.ts b/packages/graphics-2d/src/types/options/final/rectangle-options.type.ts new file mode 100644 index 00000000..28efe0b9 --- /dev/null +++ b/packages/graphics-2d/src/types/options/final/rectangle-options.type.ts @@ -0,0 +1,5 @@ +import { type IColorOption } from "../base/color.type"; +import { type IPositionOption } from "../base/position.type"; +import { type ISizeOption } from "../base/size.type"; + +export interface IRectangleOptions extends IColorOption, IPositionOption, ISizeOption {} diff --git a/packages/graphics-2d/src/types/options/final/rounded-rectangle-options.type.ts b/packages/graphics-2d/src/types/options/final/rounded-rectangle-options.type.ts new file mode 100644 index 00000000..8ab99817 --- /dev/null +++ b/packages/graphics-2d/src/types/options/final/rounded-rectangle-options.type.ts @@ -0,0 +1,5 @@ +import { type IRectangleOptions } from "./rectangle-options.type"; + +export interface IRoundedRectangleOptions extends IRectangleOptions { + round: number; +} diff --git a/packages/graphics-2d/src/types/options/index.ts b/packages/graphics-2d/src/types/options/index.ts new file mode 100644 index 00000000..c320d6b2 --- /dev/null +++ b/packages/graphics-2d/src/types/options/index.ts @@ -0,0 +1 @@ +export * from "./final"; diff --git a/packages/graphics-2d/src/utils/string.ts b/packages/graphics-2d/src/utils/string.ts new file mode 100644 index 00000000..9d539ad2 --- /dev/null +++ b/packages/graphics-2d/src/utils/string.ts @@ -0,0 +1,7 @@ +export const formatUpperToLisible = (value: string) => { + return capitalize(value.toLowerCase().replace("_", " ")); +}; + +export const capitalize = (value: string) => { + return value.charAt(0).toUpperCase() + value.slice(1); +}; diff --git a/packages/graphics-2d/tsconfig.build.json b/packages/graphics-2d/tsconfig.build.json index 2e31798e..cb32cea0 100644 --- a/packages/graphics-2d/tsconfig.build.json +++ b/packages/graphics-2d/tsconfig.build.json @@ -1,17 +1,23 @@ { "extends": "../tsconfig.build.json", "compilerOptions": { + "types": ["node", "@webgpu/types"], "outDir": ".", "rootDir": ".", "paths": { "@nanoforge/common": ["../common"], - "@nanoforge/common/*": ["../common/*"] + "@nanoforge/common/*": ["../common/*"], + "@nanoforge/asset-manager": ["../asset-manager"], + "@nanoforge/asset-manager/*": ["../asset-manager/*"] } }, "exclude": ["node_modules", "dist", "test/**/*", "*.spec.ts"], "references": [ { "path": "../common/tsconfig.build.json" + }, + { + "path": "../asset-manager/tsconfig.build.json" } ] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 59768455..d277974e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -263,6 +263,9 @@ importers: packages/graphics-2d: dependencies: + '@nanoforge/asset-manager': + specifier: workspace:^ + version: link:../asset-manager '@nanoforge/common': specifier: workspace:^ version: link:../common @@ -285,6 +288,9 @@ importers: '@types/node': specifier: ^22.13.10 version: 22.13.10 + '@webgpu/types': + specifier: ^0.1.56 + version: 0.1.56 eslint: specifier: ^9.22.0 version: 9.22.0(jiti@2.4.2) @@ -1123,6 +1129,9 @@ packages: resolution: {integrity: sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@webgpu/types@0.1.56': + resolution: {integrity: sha512-JkT4ngqwk4gKAFoWtXCcC1+TGhSStVtauS9z27slOGSFYr+QqjS0CoawiAxP7Gq9xkT4Pw9uouvWPT44HwbUiw==} + '@yarnpkg/lockfile@1.1.0': resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} @@ -5025,6 +5034,8 @@ snapshots: '@typescript-eslint/types': 8.26.1 eslint-visitor-keys: 4.2.0 + '@webgpu/types@0.1.56': {} + '@yarnpkg/lockfile@1.1.0': {} '@yarnpkg/parsers@3.0.2':